diff --git a/.gitignore b/.gitignore index ba7977ed0..a103ccdce 100644 --- a/.gitignore +++ b/.gitignore @@ -21,7 +21,8 @@ build lib -doc/html +doc/doc/* +doc/libpeerconnection.log editor/guacamole_editor guarc/guarc guacamole.sublime-workspace @@ -31,3 +32,4 @@ tags .nfs* .vim.custom tests/tests +plugins/guacamole-oculus/example-oculus/example-oculus diff --git a/CMakeLists.txt b/CMakeLists.txt index 3467d78ad..823cf7f19 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ PROJECT(GUACAMOLE CXX) # version number set(GUACAMOLE_MAJOR 0) -set(GUACAMOLE_MINOR 1) +set(GUACAMOLE_MINOR 5) set(GUACAMOLE_PATCH 0) set(GUACAMOLE_VERSION ${GUACAMOLE_MAJOR}.${GUACAMOLE_MINOR}.${GUACAMOLE_PATCH}) set(GUACAMOLE_DESCRIPTION "GUACAMOLE - an astonishing virtual reality engine") @@ -35,16 +35,17 @@ if (UNIX) pkg_check_modules(GL REQUIRED gl) pkg_check_modules(GLEW REQUIRED glew) elseif (WIN32) - include(find_assimp) + include(FindAssimp) endif (UNIX) +include(define_macros) include(find_compiler) -include(find_schism) -include(find_boost) -include(find_cuda) -#include(find_ev) -include(find_bullet) -include(find_json) +include(FindSchism) +include(FindBoost) + +set (BULLET_ROOT "/opt/bullet/default" CACHE PATH "Set to your bullet install path.") +find_package(Bullet REQUIRED) +find_package(Json REQUIRED) set(LIBS ${SCHISM_LIBRARIES} @@ -53,11 +54,7 @@ set(LIBS ${JSON_LIBRARIES} ${GL_LIBRARIES} ${GLEW_LIBRARIES} - ${EV_LIBRARIES} ${BULLET_LIBRARIES} - ${CUDA_LIBRARIES} - #profiler - #tcmalloc ) set(LIB_PATHS @@ -68,7 +65,6 @@ set(LIB_PATHS ${BOOST_LIBRARY_DIRS} ${BULLET_LIBRARY_DIRS} ${SCHISM_LIBRARY_DIRS} - ${CUDA_LIBRARY_DIRS} ) set(INCLUDE_PATHS @@ -80,9 +76,7 @@ set(INCLUDE_PATHS ${JSON_INCLUDE_DIRS} ${GL_INCLUDE_DIRS} ${GLEW_INCLUDE_DIRS} - ${EV_INCLUDE_DIRS} ${BULLET_INCLUDE_DIRS} - ${CUDA_INCLUDE_DIRS} ) if (NOT CMAKE_BUILD_TYPE) @@ -90,10 +84,10 @@ if (NOT CMAKE_BUILD_TYPE) endif() IF (UNIX) - set(CMAKE_CXX_FLAGS_RELEASE "-s -O4 --std=c++0x -fpermissive") - set(CMAKE_CXX_FLAGS_DEBUG "-g -Wall --std=c++0x -fpermissive") + set(CMAKE_CXX_FLAGS_RELEASE "-s -O4 --std=c++0x") + set(CMAKE_CXX_FLAGS_DEBUG "-g -Wall --std=c++0x") ELSEIF(MSVC) - set(CMAKE_CXX_FLAGS_RELEASE "-D _SECURE_SCL=0 -D _SCL_SECURE_NO_WARNINGS -D _CRT_SECURE_NO_DEPRECATE /MD /MP") + set(CMAKE_CXX_FLAGS_RELEASE "-D NDEBUG -D _SECURE_SCL=0 -D _SCL_SECURE_NO_WARNINGS -D _CRT_SECURE_NO_DEPRECATE /MD /MP") set(CMAKE_CXX_FLAGS_DEBUG "-D_DEBUG /MDd /Zi") ENDIF(UNIX) @@ -112,8 +106,6 @@ file(GLOB_RECURSE RESOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} resources/* ) -MESSAGE(${RESOURCES}) - if (NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/include/gua/generated/) file(MAKE_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/gua/generated) endif() @@ -122,31 +114,36 @@ if (NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/src/gua/generated/) file(MAKE_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/src/gua/generated) endif() -# ADD_CUSTOM_COMMAND(OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/src/gua/generated/R.inl - # COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/guarc/guarc - # ${CMAKE_CURRENT_SOURCE_DIR}/resources - # ${CMAKE_CURRENT_SOURCE_DIR}/include/gua/generated/R.inl - # ${CMAKE_CURRENT_SOURCE_DIR}/src/gua/generated/R.inl - # DEPENDS ${RESOURCES} guarc -# ) - -ADD_CUSTOM_TARGET(CompileResources ALL - DEPENDS ${RESOURCES} guarc -) -SET (_GUARC_EXECUTABLE "") IF (UNIX) - SET (_GUARC_EXECUTABLE "/guarc/guarc") -ELSEIF(WIN32) - SET (_GUARC_EXECUTABLE "/guarc/$(Configuration)/guarc.exe") + ADD_CUSTOM_COMMAND(OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/src/gua/generated/R.inl + COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/guarc/guarc + ${CMAKE_CURRENT_SOURCE_DIR}/resources + ${CMAKE_CURRENT_SOURCE_DIR}/include/gua/generated/R.inl + ${CMAKE_CURRENT_SOURCE_DIR}/src/gua/generated/R.inl + DEPENDS ${RESOURCES} guarc + ) + + ADD_CUSTOM_TARGET(CompileResources ALL + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/src/gua/generated/R.inl + ) + +ELSEIF(MSVC) + ADD_CUSTOM_TARGET(CompileResources ALL + DEPENDS ${RESOURCES} guarc + ) + + SET (_GUARC_EXECUTABLE "") + SET (_GUARC_EXECUTABLE "/guarc/$(Configuration)/guarc.exe") + + ADD_CUSTOM_COMMAND(TARGET CompileResources POST_BUILD + COMMAND ${CMAKE_CURRENT_SOURCE_DIR}${_GUARC_EXECUTABLE} + ${CMAKE_CURRENT_SOURCE_DIR}/resources + ${CMAKE_CURRENT_SOURCE_DIR}/include/gua/generated/R.inl + ${CMAKE_CURRENT_SOURCE_DIR}/src/gua/generated/R.inl + ) ENDIF(UNIX) -ADD_CUSTOM_COMMAND(TARGET CompileResources POST_BUILD - COMMAND ${CMAKE_CURRENT_SOURCE_DIR}${_GUARC_EXECUTABLE} - ${CMAKE_CURRENT_SOURCE_DIR}/resources - ${CMAKE_CURRENT_SOURCE_DIR}/include/gua/generated/R.inl - ${CMAKE_CURRENT_SOURCE_DIR}/src/gua/generated/R.inl -) ################################################################ # Create libraries @@ -156,53 +153,67 @@ file(MAKE_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/lib) set(LIBRARY_OUTPUT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/lib) add_subdirectory(src) +################################################################ +# Create plugins +################################################################ + +add_subdirectory(plugins) + +################################################################ +# Testing +################################################################ + +set (GUACAMOLE_TESTS "false" CACHE BOOL "Set to enable testing.") + +if (GUACAMOLE_TESTS) + add_subdirectory(tests) + enable_testing() + add_test( NAME testGUA COMMAND runTests ) +endif (GUACAMOLE_TESTS) + ################################################################ # Summary ################################################################ -message( "" ) -message( "Summary:" ) -message( " build type: ${CMAKE_BUILD_TYPE}" ) -message( "" ) -message( " schism:" ) -message( " library: ${SCHISM_LIBRARIES}" ) -message( " library path: ${SCHISM_LIBRARY_DIRS}" ) -message( " include: ${SCHISM_INCLUDE_DIRS}" ) -message( "" ) -message( " boost:" ) -message( " library: ${BOOST_LIBRARIES}" ) -message( " library path: ${BOOST_LIBRARY_DIRS}" ) -message( " include: ${BOOST_INCLUDE_DIRS}" ) -message( "" ) -message( " assimp:" ) -message( " library: ${ASSIMP_LIBRARIES}" ) -message( " library path: ${ASSIMP_LIBRARY_DIRS}" ) -message( " include: ${ASSIMP_INCLUDE_DIRS}" ) -message( "" ) -message( " json:" ) -message( " library: ${JSON_LIBRARIES}" ) -message( " library path: ${JSON_LIBRARY_DIRS}" ) -message( " include: ${JSON_INCLUDE_DIRS}" ) -message( "" ) -message( " cuda:" ) -message( " library: ${CUDA_LIBRARIES}" ) -message( " library path: ${CUDA_LIBRARY_DIRS}" ) -message( " include: ${CUDA_INCLUDE_DIRS}" ) -message( "" ) -message( " gl:" ) -message( " library: ${GL_LIBRARIES}" ) -message( " include: ${GL_INCLUDE_DIRS}" ) -message( "" ) -message( " glew:" ) -message( " library: ${GLEW_LIBRARIES}" ) -message( " include: ${GLEW_INCLUDE_DIRS}" ) -message( "" ) -message( " ev:" ) -message( " library: ${EV_LIBRARIES}" ) -message( " include: ${EV_INCLUDE_DIRS}" ) -message( "" ) -message( " bullet:" ) -message( " library: ${BULLET_LIBRARIES}" ) -message( " library path: ${BULLET_LIBRARY_DIRS}" ) -message( " include: ${BULLET_INCLUDE_DIRS}" ) -message( "" ) +message(STATUS "" ) +message(STATUS "Summary:" ) +message(STATUS " build type: ${CMAKE_BUILD_TYPE}" ) +message(STATUS "" ) +message(STATUS " schism:" ) +message(STATUS " library: ${SCHISM_LIBRARIES}" ) +message(STATUS " library path: ${SCHISM_LIBRARY_DIRS}" ) +message(STATUS " include: ${SCHISM_INCLUDE_DIRS}" ) +message(STATUS "" ) +message(STATUS " boost:" ) +message(STATUS " library: ${BOOST_LIBRARIES}" ) +message(STATUS " library path: ${BOOST_LIBRARY_DIRS}" ) +message(STATUS " include: ${BOOST_INCLUDE_DIRS}" ) +message(STATUS "" ) +message(STATUS " assimp:" ) +message(STATUS " library: ${ASSIMP_LIBRARIES}" ) +message(STATUS " library path: ${ASSIMP_LIBRARY_DIRS}" ) +message(STATUS " include: ${ASSIMP_INCLUDE_DIRS}" ) +message(STATUS "" ) +message(STATUS " json:" ) +message(STATUS " library: ${JSON_LIBRARIES}" ) +message(STATUS " library path: ${JSON_LIBRARY_DIRS}" ) +message(STATUS " include: ${JSON_INCLUDE_DIRS}" ) +message(STATUS "" ) +message(STATUS " cuda:" ) +message(STATUS " library: ${CUDA_LIBRARIES}" ) +message(STATUS " library path: ${CUDA_LIBRARY_DIRS}" ) +message(STATUS " include: ${CUDA_INCLUDE_DIRS}" ) +message(STATUS "" ) +message(STATUS " gl:" ) +message(STATUS " library: ${GL_LIBRARIES}" ) +message(STATUS " include: ${GL_INCLUDE_DIRS}" ) +message(STATUS "" ) +message(STATUS " glew:" ) +message(STATUS " library: ${GLEW_LIBRARIES}" ) +message(STATUS " include: ${GLEW_INCLUDE_DIRS}" ) +message(STATUS "" ) +message(STATUS " bullet:" ) +message(STATUS " library: ${BULLET_LIBRARIES}" ) +message(STATUS " library path: ${BULLET_LIBRARY_DIRS}" ) +message(STATUS " include: ${BULLET_INCLUDE_DIRS}" ) +message(STATUS "" ) diff --git a/cmake/modules/FindAssimp.cmake b/cmake/modules/FindAssimp.cmake new file mode 100644 index 000000000..b9284b58d --- /dev/null +++ b/cmake/modules/FindAssimp.cmake @@ -0,0 +1,128 @@ +############################################################################## +# search paths +############################################################################## +SET(ASSIMP_INCLUDE_SEARCH_DIRS + ${GLOBAL_EXT_DIR}/inc/assimp + /opt/assimp/current + /usr/include +) + +SET(ASSIMP_LIBRARY_SEARCH_DIRS + ${GLOBAL_EXT_DIR}/lib + /opt/assimp/current/assimp-build + /usr/lib +) + +############################################################################## +# feedback to provide user-defined paths to search for assimp +############################################################################## +MACRO (request_assimp_search_directories) + + IF ( NOT ASSIMP_INCLUDE_DIRS AND NOT ASSIMP_LIBRARY_DIRS ) + SET(ASSIMP_INCLUDE_SEARCH_DIR "Please provide assimp include path." CACHE PATH "path to assimp headers.") + SET(ASSIMP_LIBRARY_SEARCH_DIR "Please provide assimp library path." CACHE PATH "path to assimp libraries.") + MESSAGE(FATAL_ERROR "find_assimp.cmake: unable to find assimp.") + ENDIF ( NOT ASSIMP_INCLUDE_DIRS AND NOT ASSIMP_LIBRARY_DIRS ) + + IF ( NOT ASSIMP_INCLUDE_DIRS ) + SET(ASSIMP_INCLUDE_SEARCH_DIR "Please provide assimp include path." CACHE PATH "path to assimp headers.") + MESSAGE(FATAL_ERROR "find_assimp.cmake: unable to find assimp headers.") + ELSE ( NOT ASSIMP_INCLUDE_DIRS ) + UNSET(ASSIMP_INCLUDE_SEARCH_DIR CACHE) + ENDIF ( NOT ASSIMP_INCLUDE_DIRS ) + + IF ( NOT ASSIMP_LIBRARY_DIRS ) + SET(ASSIMP_LIBRARY_SEARCH_DIR "Please provide assimp library path." CACHE PATH "path to assimp libraries.") + MESSAGE(FATAL_ERROR "find_assimp.cmake: unable to find assimp libraries.") + ELSE ( NOT ASSIMP_LIBRARY_DIRS ) + UNSET(ASSIMP_LIBRARY_SEARCH_DIR CACHE) + ENDIF ( NOT ASSIMP_LIBRARY_DIRS ) + +ENDMACRO (request_assimp_search_directories) + +############################################################################## +# check for assimp +############################################################################## +message(STATUS "-- checking for ASSIMP") + +IF (NOT ASSIMP_INCLUDE_DIRS) + + SET(_ASSIMP_FOUND_INC_DIRS "") + + FOREACH(_SEARCH_DIR ${ASSIMP_INCLUDE_SEARCH_DIRS}) + FIND_PATH(_CUR_SEARCH + NAMES assimp/assimp.h + PATHS ${_SEARCH_DIR} + NO_DEFAULT_PATH) + IF (_CUR_SEARCH) + LIST(APPEND _ASSIMP_FOUND_INC_DIRS ${_CUR_SEARCH}) + ENDIF(_CUR_SEARCH) + SET(_CUR_SEARCH _CUR_SEARCH-NOTFOUND CACHE INTERNAL "internal use") + ENDFOREACH(_SEARCH_DIR ${ASSIMP_INCLUDE_SEARCH_DIRS}) + + IF (NOT _ASSIMP_FOUND_INC_DIRS) + request_assimp_search_directories() + ENDIF (NOT _ASSIMP_FOUND_INC_DIRS) + + FOREACH(_INC_DIR ${_ASSIMP_FOUND_INC_DIRS}) + LIST(APPEND _ASSIMP_INCLUDE_DIRS ${_INC_DIR}) + ENDFOREACH(_INC_DIR ${_BOOST_FOUND_INC_DIRS}) + + IF (_ASSIMP_FOUND_INC_DIRS) + SET(ASSIMP_INCLUDE_DIRS ${_ASSIMP_INCLUDE_DIRS} CACHE PATH "path to assimp headers.") + ENDIF (_ASSIMP_FOUND_INC_DIRS) + +ENDIF(NOT ASSIMP_INCLUDE_DIRS) + + +IF(UNIX) + SET(ASSIMP_LIB_FILENAME "libassimp.so") +ELSEIF(WIN32) + SET(ASSIMP_LIB_FILENAME "assimp.lib") +ENDIF(UNIX) + + +IF ( ASSIMP_INCLUDE_DIRS AND ( NOT ASSIMP_LIBRARY_DIRS OR NOT ASSIMP_LIBRARIES)) + + SET(_ASSIMP_FOUND_LIB_DIR "") + SET(_ASSIMP_POSTFIX "") + + FOREACH(_SEARCH_DIR ${ASSIMP_LIBRARY_SEARCH_DIRS}) + FIND_PATH(_CUR_SEARCH + NAMES ${ASSIMP_LIB_FILENAME} + PATHS ${_SEARCH_DIR} + PATH_SUFFIXES debug release + NO_DEFAULT_PATH) + IF (_CUR_SEARCH) + LIST(APPEND _ASSIMP_FOUND_LIB_DIR ${_SEARCH_DIR}) + ENDIF(_CUR_SEARCH) + SET(_CUR_SEARCH _CUR_SEARCH-NOTFOUND CACHE INTERNAL "internal use") + ENDFOREACH(_SEARCH_DIR ${ASSIMP_LIBRARY_SEARCH_DIRS}) + + IF (NOT _ASSIMP_FOUND_LIB_DIR) + request_assimp_search_directories() + ELSE (NOT _ASSIMP_FOUND_LIB_DIR) + SET(ASSIMP_LIBRARY_DIRS ${_ASSIMP_FOUND_LIB_DIR} CACHE STRING "The assimp library directory") + ENDIF (NOT _ASSIMP_FOUND_LIB_DIR) + + FOREACH(_LIB_DIR ${_ASSIMP_FOUND_LIB_DIR}) + LIST(APPEND _ASSIMP_LIBRARIES ${ASSIMP_LIB_FILENAME}) + ENDFOREACH(_LIB_DIR ${_ASSIMP_FOUND_INC_DIRS}) + + IF (_ASSIMP_FOUND_LIB_DIR) + SET(ASSIMP_LIBRARIES ${_ASSIMP_LIBRARIES} CACHE PATH "path to assimp library.") + ENDIF (_ASSIMP_FOUND_LIB_DIR) + +ENDIF ( ASSIMP_INCLUDE_DIRS AND ( NOT ASSIMP_LIBRARY_DIRS OR NOT ASSIMP_LIBRARIES)) + +############################################################################## +# verify +############################################################################## +IF ( NOT ASSIMP_INCLUDE_DIRS OR NOT ASSIMP_LIBRARY_DIRS ) + request_assimp_search_directories() +ELSE ( NOT ASSIMP_INCLUDE_DIRS OR NOT ASSIMP_LIBRARY_DIRS ) + UNSET(ASSIMP_INCLUDE_SEARCH_DIR CACHE) + UNSET(ASSIMP_LIBRARY_SEARCH_DIR CACHE) + MESSAGE(STATUS "-- found matching assimp version") +ENDIF ( NOT ASSIMP_INCLUDE_DIRS OR NOT ASSIMP_LIBRARY_DIRS ) + diff --git a/cmake/modules/FindBoost.cmake b/cmake/modules/FindBoost.cmake new file mode 100644 index 000000000..2b10e9404 --- /dev/null +++ b/cmake/modules/FindBoost.cmake @@ -0,0 +1,203 @@ +############################################################################## +# set search directories +############################################################################## +SET(BOOST_MIN_VERSION_MAJOR 1) +SET(BOOST_MIN_VERSION_MINOR 46) +SET(BOOST_MIN_VERSION_SUBMINOR 0) +SET(BOOST_MIN_VERSION "${BOOST_MIN_VERSION_MAJOR}.${BOOST_MIN_VERSION_MINOR}.${BOOST_MIN_VERSION_SUBMINOR}") +MATH(EXPR BOOST_MIN_VERSION_NUM "${BOOST_MIN_VERSION_MAJOR}*10000 + ${BOOST_MIN_VERSION_MINOR}*100 + ${BOOST_MIN_VERSION_SUBMINOR}") + +SET(BOOST_INCLUDE_SEARCH_DIRS + ${GLOBAL_EXT_DIR}/inc/boost + ${BOOST_INCLUDE_SEARCH_DIR} + /opt/boost/latest/include + ${CMAKE_SYSTEM_INCLUDE_PATH} + ${CMAKE_INCLUDE_PATH} + /usr/include +) + +SET(BOOST_LIBRARY_SEARCH_DIRS + ${GLOBAL_EXT_DIR}/lib + ${BOOST_LIBRARY_SEARCH_DIR} + /opt/boost/latest/lib + ${CMAKE_SYSTEM_LIBRARY_PATH} + ${CMAKE_LIBRARY_PATH} + /usr/lib64 +) + +############################################################################## +# feedback to provide user-defined paths to search for boost +############################################################################## +MACRO (request_boost_search_directories) + + IF ( NOT BOOST_INCLUDE_DIRS AND NOT BOOST_LIBRARY_DIRS ) + SET(BOOST_INCLUDE_SEARCH_DIR "Please provide boost include path." CACHE PATH "path to boost headers.") + SET(BOOST_LIBRARY_SEARCH_DIR "Please provide boost library path." CACHE PATH "path to boost libraries.") + MESSAGE(FATAL_ERROR "find_boost.cmake: unable to find boost.") + ENDIF ( NOT BOOST_INCLUDE_DIRS AND NOT BOOST_LIBRARY_DIRS ) + + IF ( NOT BOOST_INCLUDE_DIRS ) + SET(BOOST_INCLUDE_SEARCH_DIR "Please provide boost include path." CACHE PATH "path to boost headers.") + MESSAGE(FATAL_ERROR "find_boost.cmake: unable to find boost headers.") + ELSE ( NOT BOOST_INCLUDE_DIRS ) + UNSET(BOOST_INCLUDE_SEARCH_DIR CACHE) + ENDIF ( NOT BOOST_INCLUDE_DIRS ) + + IF ( NOT BOOST_LIBRARY_DIRS ) + SET(BOOST_LIBRARY_SEARCH_DIR "Please provide boost library path." CACHE PATH "path to boost libraries.") + MESSAGE(FATAL_ERROR "find_boost.cmake: unable to find boost libraries.") + ELSE ( NOT BOOST_LIBRARY_DIRS ) + UNSET(BOOST_LIBRARY_SEARCH_DIR CACHE) + ENDIF ( NOT BOOST_LIBRARY_DIRS ) + +ENDMACRO (request_boost_search_directories) + +############################################################################## +# start search +############################################################################## + +message(STATUS "-- checking for BOOST") + +IF ( NOT BOOST_INCLUDE_DIRS ) + + SET(_BOOST_FOUND_INC_DIRS "") + FOREACH(_SEARCH_DIR ${BOOST_INCLUDE_SEARCH_DIRS}) + FIND_PATH(_CUR_SEARCH + NAMES boost/config.hpp + PATHS ${_SEARCH_DIR} + NO_DEFAULT_PATH) + IF (_CUR_SEARCH) + LIST(APPEND _BOOST_FOUND_INC_DIRS ${_CUR_SEARCH}) + ENDIF(_CUR_SEARCH) + SET(_CUR_SEARCH _CUR_SEARCH-NOTFOUND CACHE INTERNAL "internal use") + ENDFOREACH(_SEARCH_DIR ${BOOST_INCLUDE_SEARCH_DIRS}) + + IF (NOT _BOOST_FOUND_INC_DIRS) + request_boost_search_directories() + ELSE (NOT _BOOST_FOUND_INC_DIRS) + SET(BOOST_INCLUDE_DIRS ${_BOOST_FOUND_INC_DIRS}) + ENDIF (NOT _BOOST_FOUND_INC_DIRS) + + SET(BOOST_VERSION 0) + SET(BOOST_LIB_VERSION "") + SET(BOOST_LIB_SUFFIX "") + + SET(_BOOST_CUR_VERSION ${BOOST_MIN_VERSION_NUM}) + + FOREACH(_INC_DIR ${_BOOST_FOUND_INC_DIRS}) + FILE(READ "${_INC_DIR}/boost/version.hpp" _BOOST_VERSION_CONTENTS) + + STRING(REGEX REPLACE ".*#define BOOST_VERSION ([0-9]+).*" "\\1" _BOOST_VERSION "${_BOOST_VERSION_CONTENTS}") + STRING(REGEX REPLACE ".*#define BOOST_LIB_VERSION \"([0-9_]+)\".*" "\\1" _BOOST_LIB_VERSION "${_BOOST_VERSION_CONTENTS}") + + IF(NOT "${_BOOST_VERSION}" STREQUAL "0") + MATH(EXPR _BOOST_MAJOR_VERSION "${_BOOST_VERSION} / 100000") + MATH(EXPR _BOOST_MINOR_VERSION "${_BOOST_VERSION} / 100 % 1000") + MATH(EXPR _BOOST_SUBMINOR_VERSION "${_BOOST_VERSION} % 100") + ELSE (NOT "${_BOOST_VERSION}" STREQUAL "0") + MESSAGE("WTF") + ENDIF(NOT "${_BOOST_VERSION}" STREQUAL "0") + + MATH(EXPR _BOOST_VERSION_NUM "${_BOOST_MAJOR_VERSION}*10000 + ${_BOOST_MINOR_VERSION}*100 + ${_BOOST_SUBMINOR_VERSION}") + + IF ( _BOOST_CUR_VERSION LESS _BOOST_VERSION_NUM + OR _BOOST_CUR_VERSION EQUAL _BOOST_VERSION_NUM) + SET(BOOST_VERSION ${_BOOST_VERSION}) + SET(BOOST_LIB_VERSION ${_BOOST_LIB_VERSION}) + SET(BOOST_LIB_SUFFIX ".${_BOOST_MAJOR_VERSION}.${_BOOST_MINOR_VERSION}.${_BOOST_SUBMINOR_VERSION}") + SET(BOOST_INCLUDE_DIRS ${_INC_DIR}) + SET(_BOOST_CUR_VERSION ${_BOOST_VERSION_NUM}) + ENDIF ( _BOOST_CUR_VERSION LESS _BOOST_VERSION_NUM + OR _BOOST_CUR_VERSION EQUAL _BOOST_VERSION_NUM) + + ENDFOREACH(_INC_DIR ${_BOOST_FOUND_INC_DIRS}) + + IF (BOOST_VERSION EQUAL 0) + MESSAGE(FATAL_ERROR "found boost versions ${_BOOST_VERSION} to old (min. version ${BOOST_MIN_VERSION} required)") + request_boost_search_directories() + ELSE (BOOST_VERSION EQUAL 0) + SET(BOOST_INCLUDE_DIRS ${BOOST_INCLUDE_DIRS} CACHE STRING "The boost include directory") + SET(BOOST_VERSION ${BOOST_VERSION} CACHE STRING "The boost version number") + SET(BOOST_LIB_SUFFIX ${BOOST_LIB_SUFFIX} CACHE STRING "The boost library suffix") + SET(BOOST_LIB_VERSION ${BOOST_LIB_VERSION} CACHE STRING "The boost library version string") + ENDIF (BOOST_VERSION EQUAL 0) + +ENDIF ( NOT BOOST_INCLUDE_DIRS ) + +IF ( BOOST_INCLUDE_DIRS AND NOT BOOST_LIBRARY_DIRS ) + + SET(_BOOST_FILESYSTEM_LIB "") + SET(_BOOST_FOUND_LIB_DIR "") + SET(_BOOST_POSTFIX "") + + if (UNIX) + LIST(APPEND _BOOST_FILESYSTEM_LIB "${CMAKE_SHARED_LIBRARY_PREFIX}boost_filesystem${COMPILER_SUFFIX}${BOOST_LIB_VERSION}${CMAKE_SHARED_LIBRARY_SUFFIX}${BOOST_LIB_SUFFIX}" + "${CMAKE_SHARED_LIBRARY_PREFIX}boost_filesystem${CMAKE_SHARED_LIBRARY_SUFFIX}${BOOST_LIB_SUFFIX}" + "${CMAKE_SHARED_LIBRARY_PREFIX}boost_filesystem${CMAKE_SHARED_LIBRARY_SUFFIX}${BOOST_LIB_SUFFIX}") + elseif (WIN32) + LIST(APPEND _BOOST_FILESYSTEM_LIB "${CMAKE_STATIC_LIBRARY_PREFIX}libboost_filesystem-${COMPILER_SUFFIX}-mt-${BOOST_LIB_VERSION}${CMAKE_STATIC_LIBRARY_SUFFIX}" + "${CMAKE_STATIC_LIBRARY_PREFIX}libboost_filesystem-mt${CMAKE_STATIC_LIBRARY_SUFFIX}") + endif (UNIX) + + FOREACH(_SEARCH_DIR ${BOOST_LIBRARY_SEARCH_DIRS}) + + FIND_PATH(_CUR_SEARCH + NAMES ${_BOOST_FILESYSTEM_LIB} + PATHS ${_SEARCH_DIR} + PATH_SUFFIXES debug release . + NO_DEFAULT_PATH) + IF (_CUR_SEARCH) + LIST(APPEND _BOOST_FOUND_LIB_DIR ${_SEARCH_DIR}) + if (UNIX) + FIND_FILE(_CUR_SEARCH_FILE NAMES ${_BOOST_FILESYSTEM_LIB} PATHS ${_CUR_SEARCH}) + if (_CUR_SEARCH_FILE) + #LIST(APPEND BOOST_LIBRARIES ${_CUR_SEARCH_FILE}) + STRING(REGEX REPLACE "${_CUR_SEARCH}/${CMAKE_SHARED_LIBRARY_PREFIX}boost_filesystem(.*).so(.*)" "\\2" _BOOST_UNIX_LIB_SUF ${_CUR_SEARCH_FILE}) + if (${_BOOST_UNIX_LIB_SUF} STREQUAL ${BOOST_LIB_SUFFIX}) + #list(APPEND BOOST_LIBRARIES _BOOST_FILESYSTEM_LIB) + STRING(REGEX REPLACE "${_CUR_SEARCH}/${CMAKE_SHARED_LIBRARY_PREFIX}boost_filesystem(.*).so(.*)" "\\1" _BOOST_POSTFIX ${_CUR_SEARCH_FILE}) + endif (${_BOOST_UNIX_LIB_SUF} STREQUAL ${BOOST_LIB_SUFFIX}) + endif (_CUR_SEARCH_FILE) + SET(_CUR_SEARCH_FILE _CUR_SEARCH_FILE-NOTFOUND CACHE INTERNAL "internal use") + endif (UNIX) + ENDIF(_CUR_SEARCH) + SET(_CUR_SEARCH _CUR_SEARCH-NOTFOUND CACHE INTERNAL "internal use") + + ENDFOREACH(_SEARCH_DIR ${BOOST_LIBRARY_SEARCH_DIRS}) + + IF (NOT _BOOST_FOUND_LIB_DIR) + request_boost_search_directories() + ELSE (NOT _BOOST_FOUND_LIB_DIR) + SET(BOOST_LIBRARY_DIRS ${_BOOST_FOUND_LIB_DIR} CACHE PATH "boost library path.") + IF (UNIX) + FILE(GLOB _BOOST_LIBRARIES ${_BOOST_FOUND_LIB_DIR}/*.so) + SET(BOOST_LIBRARIES ${_BOOST_LIBRARIES} CACHE PATH "boost libraries") + ELSEIF (MSVC) + # use boost auto link + ENDIF (UNIX) + ENDIF (NOT _BOOST_FOUND_LIB_DIR) + + if (UNIX) + set(BOOST_MT_REL "${_BOOST_POSTFIX}" CACHE STRING "boost dynamic library release postfix") + set(BOOST_MT_DBG "${_BOOST_POSTFIX}" CACHE STRING "boost dynamic library debug postfix") + set(BOOST_MT_S_REL "${_BOOST_POSTFIX}" CACHE STRING "boost static library release postfix") + set(BOOST_MT_S_DBG "${_BOOST_POSTFIX}" CACHE STRING "boost static library debug postfix") + elseif (WIN32) + set(BOOST_MT_REL "${COMPILER_SUFFIX}-mt-${BOOST_LIB_VERSION}" CACHE STRING "boost dynamic library release postfix") + set(BOOST_MT_DBG "${COMPILER_SUFFIX}-mt-gd-${BOOST_LIB_VERSION}" CACHE STRING "boost dynamic library debug postfix") + set(BOOST_MT_S_REL "${COMPILER_SUFFIX}-mt-s-${BOOST_LIB_VERSION}" CACHE STRING "boost static library release postfix") + set(BOOST_MT_S_DBG "${COMPILER_SUFFIX}-mt-sgd-${BOOST_LIB_VERSION}" CACHE STRING "boost static library debug postfix") + endif (UNIX) + +ENDIF ( BOOST_INCLUDE_DIRS AND NOT BOOST_LIBRARY_DIRS ) + +############################################################################## +# verify +############################################################################## +IF ( NOT BOOST_INCLUDE_DIRS OR NOT BOOST_LIBRARY_DIRS ) + request_boost_search_directories() +ELSE ( NOT BOOST_INCLUDE_DIRS OR NOT BOOST_LIBRARY_DIRS ) + UNSET(BOOST_INCLUDE_SEARCH_DIR CACHE) + UNSET(BOOST_LIBRARY_SEARCH_DIR CACHE) + MESSAGE(STATUS "-- found matching boost version") +ENDIF ( NOT BOOST_INCLUDE_DIRS OR NOT BOOST_LIBRARY_DIRS ) diff --git a/cmake/modules/FindBullet.cmake b/cmake/modules/FindBullet.cmake new file mode 100644 index 000000000..c152d46d0 --- /dev/null +++ b/cmake/modules/FindBullet.cmake @@ -0,0 +1,88 @@ +# - Try to find the Bullet physics engine +# +# This module defines the following variables +# +# BULLET_FOUND - Was bullet found +# BULLET_INCLUDE_DIRS - the Bullet include directories +# BULLET_LIBRARIES - Link to this, by default it includes +# all bullet components (Dynamics, +# Collision, LinearMath, & SoftBody) +# +# This module accepts the following variables +# +# BULLET_ROOT - Can be set to bullet install path or Windows build path +# + +#============================================================================= +# Copyright 2009 Kitware, Inc. +# Copyright 2009 Philip Lowman +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# (To distribute this file outside of CMake, substitute the full +# License text for the above reference.) + +macro(_FIND_BULLET_LIBRARY _var) + find_library(${_var} + NAMES + ${ARGN} + HINTS + ${BULLET_ROOT} + ${BULLET_ROOT}/lib/Release + ${BULLET_ROOT}/lib/Debug + ${BULLET_ROOT}/out/release8/libs + ${BULLET_ROOT}/out/debug8/libs + PATH_SUFFIXES lib + ) + mark_as_advanced(${_var}) +endmacro() + +macro(_BULLET_APPEND_LIBRARIES _list _release) + set(_debug ${_release}_DEBUG) + if(${_debug}) + set(${_list} ${${_list}} optimized ${${_release}} debug ${${_debug}}) + else() + set(${_list} ${${_list}} ${${_release}}) + endif() +endmacro() + +find_path(BULLET_INCLUDE_DIR NAMES btBulletCollisionCommon.h + HINTS + ${BULLET_ROOT}/include + ${BULLET_ROOT}/src + PATH_SUFFIXES bullet +) + +# Find the libraries + +_FIND_BULLET_LIBRARY(BULLET_DYNAMICS_LIBRARY BulletDynamics) +_FIND_BULLET_LIBRARY(BULLET_DYNAMICS_LIBRARY_DEBUG BulletDynamics_Debug BulletDynamics_d) +_FIND_BULLET_LIBRARY(BULLET_COLLISION_LIBRARY BulletCollision) +_FIND_BULLET_LIBRARY(BULLET_COLLISION_LIBRARY_DEBUG BulletCollision_Debug BulletCollision_d) +_FIND_BULLET_LIBRARY(BULLET_MATH_LIBRARY BulletMath LinearMath) +_FIND_BULLET_LIBRARY(BULLET_MATH_LIBRARY_DEBUG BulletMath_Debug BulletMath_d LinearMath_Debug LinearMath_d) +_FIND_BULLET_LIBRARY(BULLET_SOFTBODY_LIBRARY BulletSoftBody) +_FIND_BULLET_LIBRARY(BULLET_HACD_LIBRARY HACD) +_FIND_BULLET_LIBRARY(BULLET_SOFTBODY_LIBRARY_DEBUG BulletSoftBody_Debug BulletSoftBody_d) + + +# handle the QUIETLY and REQUIRED arguments and set BULLET_FOUND to TRUE if +# all listed variables are TRUE +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(Bullet DEFAULT_MSG + BULLET_DYNAMICS_LIBRARY BULLET_COLLISION_LIBRARY BULLET_MATH_LIBRARY + BULLET_SOFTBODY_LIBRARY BULLET_HACD_LIBRARY BULLET_INCLUDE_DIR) + +set(BULLET_INCLUDE_DIRS ${BULLET_INCLUDE_DIR}) +if(BULLET_FOUND) + _BULLET_APPEND_LIBRARIES(BULLET_LIBRARIES BULLET_DYNAMICS_LIBRARY) + _BULLET_APPEND_LIBRARIES(BULLET_LIBRARIES BULLET_COLLISION_LIBRARY) + _BULLET_APPEND_LIBRARIES(BULLET_LIBRARIES BULLET_MATH_LIBRARY) + _BULLET_APPEND_LIBRARIES(BULLET_LIBRARIES BULLET_SOFTBODY_LIBRARY) + _BULLET_APPEND_LIBRARIES(BULLET_LIBRARIES BULLET_HACD_LIBRARY) +endif() diff --git a/cmake/modules/FindJson.cmake b/cmake/modules/FindJson.cmake new file mode 100644 index 000000000..a6d97a8ac --- /dev/null +++ b/cmake/modules/FindJson.cmake @@ -0,0 +1,39 @@ +# - Try to find UnitTest++ +# Once done this will define +# JSON_FOUND - System has json +# JSON_INCLUDE_DIRS - The json include directories +# JSON_LIBRARIES - The libraries needed to use json +find_path(JSON_INCLUDE_DIR + NAMES json/features.h + PATHS /usr/include/jsoncpp/json + ${GLOBAL_EXT_DIR}/inc/json + ${GUACAMOLE_EXT_DIR}/inc/json + PATH_SUFFIXES jsoncpp json + ) + +find_library(JSON_LIBRARY + NAMES jsoncpp json + PATHS /usr/lib + ${GLOBAL_EXT_DIR}/lib + ${GUACAMOLE_EXT_DIR}/lib + PATH_SUFFIXES release + ) + +#find_library(JSON_LIBRARY_DEBUG +# NAMES jsoncpp json +# PATHS /usr/lib +# ${GLOBAL_EXT_DIR}/lib +# ${GUACAMOLE_EXT_DIR}/lib +# PATH_SUFFIXES debug +# ) + +set(JSON_LIBRARIES ${JSON_LIBRARY} ) +set(JSON_INCLUDE_DIRS ${JSON_INCLUDE_DIR} ) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(Json DEFAULT_MSG + JSON_LIBRARY JSON_INCLUDE_DIR) + +# Mark the named cached variables as advanced. An advanced variable will not be +# displayed in any of the cmake GUIs unless the show advanced option is on. +mark_as_advanced(JSON_INCLUDE_DIR JSON_LIBRARY ) diff --git a/cmake/modules/FindSchism.cmake b/cmake/modules/FindSchism.cmake new file mode 100644 index 000000000..5a7a5b5ae --- /dev/null +++ b/cmake/modules/FindSchism.cmake @@ -0,0 +1,144 @@ +############################################################################## +# search paths +############################################################################## +SET(SCHISM_INCLUDE_SEARCH_DIRS + ${GLOBAL_EXT_DIR}/inc/schism + ${SCHISM_INCLUDE_SEARCH_DIR} + /opt/schism/current +) + +SET(SCHISM_LIBRARY_SEARCH_DIRS + ${GLOBAL_EXT_DIR}/lib + ${SCHISM_LIBRARY_SEARCH_DIR} + ../ + /opt/schism/current/lib/linux_x86 +) + +############################################################################## +# feedback to provide user-defined paths to search for schism +############################################################################## +MACRO (request_schism_search_directories) + + IF ( NOT SCHISM_INCLUDE_DIRS AND NOT SCHISM_LIBRARY_DIRS ) + SET(SCHISM_INCLUDE_SEARCH_DIR "Please provide schism include path." CACHE PATH "path to schism headers.") + SET(SCHISM_LIBRARY_SEARCH_DIR "Please provide schism library path." CACHE PATH "path to schism libraries.") + MESSAGE(FATAL_ERROR "find_schism.cmake: unable to find schism.") + ENDIF ( NOT SCHISM_INCLUDE_DIRS AND NOT SCHISM_LIBRARY_DIRS ) + + IF ( NOT SCHISM_INCLUDE_DIRS ) + SET(SCHISM_INCLUDE_SEARCH_DIR "Please provide schism include path." CACHE PATH "path to schism headers.") + MESSAGE(FATAL_ERROR "find_schism.cmake: unable to find schism headers.") + ELSE ( NOT SCHISM_INCLUDE_DIRS ) + UNSET(SCHISM_INCLUDE_SEARCH_DIR CACHE) + ENDIF ( NOT SCHISM_INCLUDE_DIRS ) + + IF ( NOT SCHISM_LIBRARY_DIRS ) + SET(SCHISM_LIBRARY_SEARCH_DIR "Please provide schism library path." CACHE PATH "path to schism libraries.") + MESSAGE(FATAL_ERROR "find_schism.cmake: unable to find schism libraries.") + ELSE ( NOT SCHISM_LIBRARY_DIRS ) + UNSET(SCHISM_LIBRARY_SEARCH_DIR CACHE) + ENDIF ( NOT SCHISM_LIBRARY_DIRS ) + +ENDMACRO (request_schism_search_directories) + +############################################################################## +# check for schism +############################################################################## +message(STATUS "-- checking for schism") + +IF ( NOT SCHISM_INCLUDE_DIRS ) + + FOREACH(_SEARCH_DIR ${SCHISM_INCLUDE_SEARCH_DIRS}) + FIND_PATH(_CUR_SEARCH + NAMES scm_gl_core/src/scm/gl_core.h + PATHS ${_SEARCH_DIR} + NO_DEFAULT_PATH) + IF (_CUR_SEARCH) + LIST(APPEND _SCHISM_FOUND_INC_DIRS ${_CUR_SEARCH}) + ENDIF(_CUR_SEARCH) + SET(_CUR_SEARCH _CUR_SEARCH-NOTFOUND CACHE INTERNAL "internal use") + ENDFOREACH(_SEARCH_DIR ${SCHISM_INCLUDE_SEARCH_DIRS}) + + IF (NOT _SCHISM_FOUND_INC_DIRS) + request_schism_search_directories() + ENDIF (NOT _SCHISM_FOUND_INC_DIRS) + + FOREACH(_INC_DIR ${_SCHISM_FOUND_INC_DIRS}) + LIST(APPEND _SCHISM_INCLUDE_DIRS ${_INC_DIR}/scm_cl_core/src) + LIST(APPEND _SCHISM_INCLUDE_DIRS ${_INC_DIR}/scm_core/src) + LIST(APPEND _SCHISM_INCLUDE_DIRS ${_INC_DIR}/scm_gl_core/src) + LIST(APPEND _SCHISM_INCLUDE_DIRS ${_INC_DIR}/scm_gl_util/src) + LIST(APPEND _SCHISM_INCLUDE_DIRS ${_INC_DIR}/scm_input/src) + ENDFOREACH(_INC_DIR ${_BOOST_FOUND_INC_DIRS}) + + IF (_SCHISM_FOUND_INC_DIRS) + SET(SCHISM_INCLUDE_DIRS ${_SCHISM_INCLUDE_DIRS} CACHE PATH "path to schism headers.") + ENDIF (_SCHISM_FOUND_INC_DIRS) + +ENDIF ( NOT SCHISM_INCLUDE_DIRS ) + +IF ( SCHISM_INCLUDE_DIRS AND ( NOT SCHISM_LIBRARY_DIRS OR NOT SCHISM_LIBRARIES)) + + FOREACH(_SEARCH_DIR ${SCHISM_LIBRARY_SEARCH_DIRS}) + + IF (UNIX) + FIND_PATH(_CUR_SEARCH + NAMES libscm_gl_core.so + PATHS ${_SEARCH_DIR} + NO_DEFAULT_PATH) + ELSEIF(WIN32) + FIND_PATH(_CUR_SEARCH + NAMES scm_gl_core.lib + PATHS ${_SEARCH_DIR} + PATH_SUFFIXES debug release + NO_DEFAULT_PATH) + ENDIF(UNIX) + + IF (_CUR_SEARCH) + LIST(APPEND _SCHISM_FOUND_LIB_DIR ${_SEARCH_DIR}) + ENDIF(_CUR_SEARCH) + + SET(_CUR_SEARCH _CUR_SEARCH-NOTFOUND CACHE INTERNAL "internal use") + + ENDFOREACH(_SEARCH_DIR ${SCHISM_LIBRARY_SEARCH_DIRS}) + + IF (NOT _SCHISM_FOUND_LIB_DIR) + request_schism_search_directories() + ELSE (NOT _SCHISM_FOUND_LIB_DIR) + SET(SCHISM_LIBRARY_DIRS ${_SCHISM_FOUND_LIB_DIR} CACHE STRING "The schism library directory.") + ENDIF (NOT _SCHISM_FOUND_LIB_DIR) + + SET(_SCHISM_LIBRARIES "") + + FOREACH(_LIB_DIR ${_SCHISM_FOUND_LIB_DIR}) + IF (UNIX) + file(GLOB _SCHISM_LIBRARIES ${_LIB_DIR}/*.so) + ELSEIF(WIN32) + file(GLOB _SCHISM_LIBRARY_ABSOLUTE_PATHS ${_LIB_DIR}/release/scm*.lib) + FOREACH (_SCHISM_LIB_PATH ${_SCHISM_LIBRARY_ABSOLUTE_PATHS}) + SET(_SCHISM_LIB_FILENAME "") + GET_FILENAME_COMPONENT(_SCHISM_LIB_FILENAME ${_SCHISM_LIB_PATH} NAME) + LIST(APPEND _SCHISM_LIBRARIES ${_SCHISM_LIB_FILENAME}) + ENDFOREACH(_SCHISM_LIB_PATH) + ENDIF(UNIX) + ENDFOREACH(_LIB_DIR ${_SCHISM_FOUND_INC_DIRS}) + + IF (_SCHISM_FOUND_LIB_DIR) + SET(SCHISM_LIBRARIES ${_SCHISM_LIBRARIES} CACHE STRING "schism libraries.") + ENDIF (_SCHISM_FOUND_LIB_DIR) + +ENDIF ( SCHISM_INCLUDE_DIRS AND ( NOT SCHISM_LIBRARY_DIRS OR NOT SCHISM_LIBRARIES)) + +############################################################################## +# verify +############################################################################## +IF ( NOT SCHISM_INCLUDE_DIRS OR NOT SCHISM_LIBRARY_DIRS ) + request_schism_search_directories() +ELSE ( NOT SCHISM_INCLUDE_DIRS OR NOT SCHISM_LIBRARY_DIRS ) + UNSET(SCHISM_INCLUDE_SEARCH_DIR CACHE) + UNSET(SCHISM_LIBRARY_SEARCH_DIR CACHE) + MESSAGE(STATUS "-- found matching schism version") +ENDIF ( NOT SCHISM_INCLUDE_DIRS OR NOT SCHISM_LIBRARY_DIRS ) + + + diff --git a/cmake/modules/FindUnitTest++.cmake b/cmake/modules/FindUnitTest++.cmake new file mode 100644 index 000000000..9b08c4a96 --- /dev/null +++ b/cmake/modules/FindUnitTest++.cmake @@ -0,0 +1,31 @@ +# - Try to find UnitTest++ +# Once done this will define +# UNITTEST++_FOUND - System has UnitTest++ +# UNITTEST++_INCLUDE_DIRS - The UnitTest++ include directories +# UNITTEST++_LIBRARIES - The libraries needed to use UnitTest++ +find_path(UNITTEST++_INCLUDE_DIR UnitTest++.h + HINTS ${CMAKE_SOURCE_DIR}/externals/UnitTest++/include + PATHS /usr/include/unittest++ + PATH_SUFFIXES UnitTest++ unittest++ + ) + +find_library(UNITTEST++_LIBRARY + NAMES UnitTest++ UnitTest++.vsnet2005 UnitTest++.vsnet2008 + HINTS ${CMAKE_SOURCE_DIR}/externals/UnitTest++/lib + PATHS /usr/lib + ) + +#find_library(UNITTEST++_LIBRARY_DEBUG +# NAMES UnitTest++D UnitTest++.vsnet2005 UnitTest++.vsnet2008 +# HINTS ${CMAKE_SOURCE_DIR}/externals/UnitTest++/lib +# PATHS /usr/lib +# ) + +set(UNITTEST++_LIBRARIES ${UNITTEST++_LIBRARY} ) +set(UNITTEST++_INCLUDE_DIRS ${UNITTEST++_INCLUDE_DIR} ) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(UnitTest++ DEFAULT_MSG + UNITTEST++_LIBRARY UNITTEST++_INCLUDE_DIR) + +mark_as_advanced(UNITTEST++_INCLUDE_DIR UNITTEST++_LIBRARY ) diff --git a/cmake/modules/define_macros.cmake b/cmake/modules/define_macros.cmake new file mode 100644 index 000000000..4ea8ebaff --- /dev/null +++ b/cmake/modules/define_macros.cmake @@ -0,0 +1,37 @@ +############################################################################### + +MACRO(GET_SUBDIRECTORIES subdirectories current_directory) + + FILE(GLOB directory_content RELATIVE ${current_directory} *) + SET(dirlist "") + + FOREACH(child ${directory_content}) + + IF(IS_DIRECTORY ${current_directory}/${child}) + SET(dirlist ${dirlist} ${child}) + ENDIF() + + ENDFOREACH() + + SET(${subdirectories} ${dirlist}) + +ENDMACRO() + +############################################################################### + +# copy_runtime_dependencies [target_name] [path_to_runtime_libraries] [executable_path] +MACRO(COPY_RUNTIME_DEPENDENCIES _TARGET_NAME _RUNTIME_LIBRARY_PATH _TARGET_PATH) + + SET ( _COPY_COMMAND "copy" ) + SET ( _PUSH_DIRECTORY_COMMAND "pushd" ) + SET ( _POP_DIRECTORY_COMMAND "popd" ) + + IF (WIN32) + SET(_POST_PROCESS_COMMAND + ${_PUSH_DIRECTORY_COMMAND} ${_RUNTIME_LIBRARY_PATH} \n + ${_COPY_COMMAND} *.dll ${_TARGET_PATH} \n + ${_POP_DIRECTORY_COMMAND}) + ADD_CUSTOM_COMMAND ( TARGET ${_TARGET_NAME} POST_BUILD COMMAND ${_POST_PROCESS_COMMAND}) + ENDIF(WIN32) + +ENDMACRO(COPY_RUNTIME_DEPENDENCIES) diff --git a/cmake/modules/find_assimp.cmake b/cmake/modules/find_assimp.cmake deleted file mode 100644 index c61811c8b..000000000 --- a/cmake/modules/find_assimp.cmake +++ /dev/null @@ -1,80 +0,0 @@ -SET(ASSIMP_INCLUDE_SEARCH_DIRS - ${GLOBAL_EXT_DIR}/inc/assimp - /opt/assimp/current -) - -SET(ASSIMP_LIBRARY_SEARCH_DIRS - ${GLOBAL_EXT_DIR}/lib - /opt/assimp/current/assimp-build -) - -message("-- checking for ASSIMP") - -IF (NOT ASSIMP_INCLUDE_DIRS) - - SET(_ASSIMP_FOUND_INC_DIRS "") - - FOREACH(_SEARCH_DIR ${ASSIMP_INCLUDE_SEARCH_DIRS}) - FIND_PATH(_CUR_SEARCH - NAMES assimp/assimp.h - PATHS ${_SEARCH_DIR} - NO_DEFAULT_PATH) - IF (_CUR_SEARCH) - LIST(APPEND _ASSIMP_FOUND_INC_DIRS ${_CUR_SEARCH}) - ENDIF(_CUR_SEARCH) - SET(_CUR_SEARCH _CUR_SEARCH-NOTFOUND CACHE INTERNAL "internal use") - ENDFOREACH(_SEARCH_DIR ${ASSIMP_INCLUDE_SEARCH_DIRS}) - - IF (NOT _ASSIMP_FOUND_INC_DIRS) - MESSAGE(FATAL_ERROR "find_assimp.cmake: unable to find assimp headers") - ENDIF (NOT _ASSIMP_FOUND_INC_DIRS) - - FOREACH(_INC_DIR ${_ASSIMP_FOUND_INC_DIRS}) - LIST(APPEND ASSIMP_INCLUDE_DIRS ${_INC_DIR}) - ENDFOREACH(_INC_DIR ${_BOOST_FOUND_INC_DIRS}) - -ENDIF(NOT ASSIMP_INCLUDE_DIRS) - - -IF(UNIX) - SET(ASSIMP_LIB_FILENAME "libassimp.so") -ELSEIF(WIN32) - SET(ASSIMP_LIB_FILENAME "assimp.lib") -ENDIF(UNIX) - - -IF ( ASSIMP_INCLUDE_DIRS - AND NOT ASSIMP_LIBRARIES) - - SET(_ASSIMP_FOUND_LIB_DIR "") - SET(_ASSIMP_POSTFIX "") - - FOREACH(_SEARCH_DIR ${ASSIMP_LIBRARY_SEARCH_DIRS}) - FIND_PATH(_CUR_SEARCH - NAMES ${ASSIMP_LIB_FILENAME} - PATHS ${_SEARCH_DIR} - PATH_SUFFIXES debug release - NO_DEFAULT_PATH) - IF (_CUR_SEARCH) - LIST(APPEND _ASSIMP_FOUND_LIB_DIR ${_SEARCH_DIR}) - ENDIF(_CUR_SEARCH) - SET(_CUR_SEARCH _CUR_SEARCH-NOTFOUND CACHE INTERNAL "internal use") - ENDFOREACH(_SEARCH_DIR ${ASSIMP_LIBRARY_SEARCH_DIRS}) - - IF (NOT _ASSIMP_FOUND_LIB_DIR) - MESSAGE(FATAL_ERROR "find_assimp.cmake: unable to find assimp libraries") - ELSE (NOT _ASSIMP_FOUND_LIB_DIR) - SET(ASSIMP_LIBRARY_DIRS ${_ASSIMP_FOUND_LIB_DIR} CACHE STRING "The assimp library directory") - message("-- found matching version") - ENDIF (NOT _ASSIMP_FOUND_LIB_DIR) - - FOREACH(_LIB_DIR ${_ASSIMP_FOUND_LIB_DIR}) - LIST(APPEND ASSIMP_LIBRARIES ${ASSIMP_LIB_FILENAME}) - ENDFOREACH(_LIB_DIR ${_ASSIMP_FOUND_INC_DIRS}) - - -ENDIF( ASSIMP_INCLUDE_DIRS - AND NOT ASSIMP_LIBRARIES) - - - diff --git a/cmake/modules/find_boost.cmake b/cmake/modules/find_boost.cmake deleted file mode 100644 index 9b989eb7e..000000000 --- a/cmake/modules/find_boost.cmake +++ /dev/null @@ -1,166 +0,0 @@ -SET(GUA_BOOST_MIN_VERSION_MAJOR 1) -SET(GUA_BOOST_MIN_VERSION_MINOR 46) -SET(GUA_BOOST_MIN_VERSION_SUBMINOR 0) -SET(GUA_BOOST_MIN_VERSION "${GUA_BOOST_MIN_VERSION_MAJOR}.${GUA_BOOST_MIN_VERSION_MINOR}.${GUA_BOOST_MIN_VERSION_SUBMINOR}") -MATH(EXPR GUA_BOOST_MIN_VERSION_NUM "${GUA_BOOST_MIN_VERSION_MAJOR}*10000 + ${GUA_BOOST_MIN_VERSION_MINOR}*100 + ${GUA_BOOST_MIN_VERSION_SUBMINOR}") - -SET(GUA_BOOST_INCLUDE_SEARCH_DIRS - ${GLOBAL_EXT_DIR}/inc/boost - /opt/boost/latest/include - ${CMAKE_SYSTEM_INCLUDE_PATH} - ${CMAKE_INCLUDE_PATH} - /usr/include -) - -SET(GUA_BOOST_LIBRARY_SEARCH_DIRS - ${GLOBAL_EXT_DIR}/lib - /opt/boost/latest/lib - ${CMAKE_SYSTEM_LIBRARY_PATH} - ${CMAKE_LIBRARY_PATH} - /usr/lib64 -) - -message("-- checking for BOOST") - -IF (NOT BOOST_INCLUDE_DIRS) - - SET(_GUA_BOOST_FOUND_INC_DIRS "") - FOREACH(_SEARCH_DIR ${GUA_BOOST_INCLUDE_SEARCH_DIRS}) - FIND_PATH(_CUR_SEARCH - NAMES boost/config.hpp - PATHS ${_SEARCH_DIR} - NO_DEFAULT_PATH) - IF (_CUR_SEARCH) - LIST(APPEND _GUA_BOOST_FOUND_INC_DIRS ${_CUR_SEARCH}) - ENDIF(_CUR_SEARCH) - SET(_CUR_SEARCH _CUR_SEARCH-NOTFOUND CACHE INTERNAL "internal use") - ENDFOREACH(_SEARCH_DIR ${GUA_BOOST_INCLUDE_SEARCH_DIRS}) - - IF (NOT _GUA_BOOST_FOUND_INC_DIRS) - MESSAGE(FATAL_ERROR "guacamole_boost.cmake: unable to find boost library") - ELSE (NOT _GUA_BOOST_FOUND_INC_DIRS) - SET(BOOST_INCLUDE_DIRS ${_GUA_BOOST_FOUND_INC_DIRS}) - ENDIF (NOT _GUA_BOOST_FOUND_INC_DIRS) - - SET(GUA_BOOST_VERSION 0) - SET(GUA_BOOST_LIB_VERSION "") - SET(GUA_BOOST_LIB_SUFFIX "") - - SET(_GUA_BOOST_CUR_VERSION ${GUA_BOOST_MIN_VERSION_NUM}) - - FOREACH(_INC_DIR ${_GUA_BOOST_FOUND_INC_DIRS}) - FILE(READ "${_INC_DIR}/boost/version.hpp" _GUA_BOOST_VERSION_CONTENTS) - - STRING(REGEX REPLACE ".*#define BOOST_VERSION ([0-9]+).*" "\\1" _BOOST_VERSION "${_GUA_BOOST_VERSION_CONTENTS}") - STRING(REGEX REPLACE ".*#define BOOST_LIB_VERSION \"([0-9_]+)\".*" "\\1" _BOOST_LIB_VERSION "${_GUA_BOOST_VERSION_CONTENTS}") - - IF(NOT "${_BOOST_VERSION}" STREQUAL "0") - MATH(EXPR _BOOST_MAJOR_VERSION "${_BOOST_VERSION} / 100000") - MATH(EXPR _BOOST_MINOR_VERSION "${_BOOST_VERSION} / 100 % 1000") - MATH(EXPR _BOOST_SUBMINOR_VERSION "${_BOOST_VERSION} % 100") - ELSE (NOT "${_BOOST_VERSION}" STREQUAL "0") - MESSAGE("WTF") - ENDIF(NOT "${_BOOST_VERSION}" STREQUAL "0") - - MATH(EXPR _BOOST_VERSION_NUM "${_BOOST_MAJOR_VERSION}*10000 + ${_BOOST_MINOR_VERSION}*100 + ${_BOOST_SUBMINOR_VERSION}") - - IF ( _GUA_BOOST_CUR_VERSION LESS _BOOST_VERSION_NUM - OR _GUA_BOOST_CUR_VERSION EQUAL _BOOST_VERSION_NUM) - SET(GUA_BOOST_VERSION ${_BOOST_VERSION}) - SET(GUA_BOOST_LIB_VERSION ${_BOOST_LIB_VERSION}) - SET(GUA_BOOST_LIB_SUFFIX ".${_BOOST_MAJOR_VERSION}.${_BOOST_MINOR_VERSION}.${_BOOST_SUBMINOR_VERSION}") - SET(BOOST_INCLUDE_DIRS ${_INC_DIR}) - SET(_GUA_BOOST_CUR_VERSION ${_BOOST_VERSION_NUM}) - ENDIF ( _GUA_BOOST_CUR_VERSION LESS _BOOST_VERSION_NUM - OR _GUA_BOOST_CUR_VERSION EQUAL _BOOST_VERSION_NUM) - - ENDFOREACH(_INC_DIR ${_GUA_BOOST_FOUND_INC_DIRS}) - - IF (GUA_BOOST_VERSION EQUAL 0) - MESSAGE(FATAL_ERROR "found boost versions ${_BOOST_VERSION} to old (min. version ${GUA_BOOST_MIN_VERSION} required)") - ELSE (GUA_BOOST_VERSION EQUAL 0) - #SET(BOOST_INCLUDE_DIRS ${BOOST_INCLUDE_DIRS} CACHE STRING "The boost include directory") - SET(BOOST_INCLUDE_DIRS ${BOOST_INCLUDE_DIRS}) - SET(GUA_BOOST_VERSION ${GUA_BOOST_VERSION} CACHE STRING "The boost version number") - SET(GUA_BOOST_LIB_SUFFIX ${GUA_BOOST_LIB_SUFFIX} CACHE STRING "The boost library suffix") - SET(GUA_BOOST_LIB_VERSION ${GUA_BOOST_LIB_VERSION} CACHE STRING "The boost library version string") - ENDIF (GUA_BOOST_VERSION EQUAL 0) - -ENDIF(NOT BOOST_INCLUDE_DIRS) - -IF ( BOOST_INCLUDE_DIRS - AND NOT BOOST_LIBRARIES) - #AND NOT BOOST_LIBRARY_DIRS) - - SET(_GUA_BOOST_FILESYSTEM_LIB "") - SET(_GUA_BOOST_FOUND_LIB_DIR "") - SET(_GUA_BOOST_POSTFIX "") - - if (UNIX) - LIST(APPEND _GUA_BOOST_FILESYSTEM_LIB "${CMAKE_SHARED_LIBRARY_PREFIX}boost_filesystem${GUA_COMPILER_SUFFIX}${GUA_BOOST_LIB_VERSION}${CMAKE_SHARED_LIBRARY_SUFFIX}${GUA_BOOST_LIB_SUFFIX}" - "${CMAKE_SHARED_LIBRARY_PREFIX}boost_filesystem${CMAKE_SHARED_LIBRARY_SUFFIX}${GUA_BOOST_LIB_SUFFIX}" - "${CMAKE_SHARED_LIBRARY_PREFIX}boost_filesystem${CMAKE_SHARED_LIBRARY_SUFFIX}${GUA_BOOST_LIB_SUFFIX}") - elseif (WIN32) - LIST(APPEND _GUA_BOOST_FILESYSTEM_LIB "${CMAKE_STATIC_LIBRARY_PREFIX}libboost_filesystem-${GUA_COMPILER_SUFFIX}-mt-${GUA_BOOST_LIB_VERSION}${CMAKE_STATIC_LIBRARY_SUFFIX}" - "${CMAKE_STATIC_LIBRARY_PREFIX}libboost_filesystem-mt${CMAKE_STATIC_LIBRARY_SUFFIX}") - endif (UNIX) - - - FOREACH(_SEARCH_DIR ${GUA_BOOST_LIBRARY_SEARCH_DIRS}) - FIND_PATH(_CUR_SEARCH - NAMES ${_GUA_BOOST_FILESYSTEM_LIB} - PATHS ${_SEARCH_DIR} - PATH_SUFFIXES debug release . - NO_DEFAULT_PATH) - IF (_CUR_SEARCH) - LIST(APPEND _GUA_BOOST_FOUND_LIB_DIR ${_SEARCH_DIR}) - if (UNIX) - FIND_FILE(_CUR_SEARCH_FILE NAMES ${_GUA_BOOST_FILESYSTEM_LIB} PATHS ${_CUR_SEARCH}) - if (_CUR_SEARCH_FILE) - LIST(APPEND BOOST_LIBRARIES ${_CUR_SEARCH_FILE}) - STRING(REGEX REPLACE "${_CUR_SEARCH}/${CMAKE_SHARED_LIBRARY_PREFIX}boost_filesystem(.*).so(.*)" "\\2" _GUA_BOOST_UNIX_LIB_SUF ${_CUR_SEARCH_FILE}) - if (${_GUA_BOOST_UNIX_LIB_SUF} STREQUAL ${GUA_BOOST_LIB_SUFFIX}) - message("found matching version") - list(APPEND BOOST_LIBRARIES _GUA_BOOST_FILESYSTEM_LIB) - STRING(REGEX REPLACE "${_CUR_SEARCH}/${CMAKE_SHARED_LIBRARY_PREFIX}boost_filesystem(.*).so(.*)" "\\1" _GUA_BOOST_POSTFIX ${_CUR_SEARCH_FILE}) - endif (${_GUA_BOOST_UNIX_LIB_SUF} STREQUAL ${GUA_BOOST_LIB_SUFFIX}) - endif (_CUR_SEARCH_FILE) - SET(_CUR_SEARCH_FILE _CUR_SEARCH_FILE-NOTFOUND CACHE INTERNAL "internal use") - endif (UNIX) - ENDIF(_CUR_SEARCH) - SET(_CUR_SEARCH _CUR_SEARCH-NOTFOUND CACHE INTERNAL "internal use") - ENDFOREACH(_SEARCH_DIR ${GUA_BOOST_LIBRARY_SEARCH_DIRS}) - - IF (NOT _GUA_BOOST_FOUND_LIB_DIR) - MESSAGE(FATAL_ERROR "guacamole_boost.cmake: unable to find boost library") - ELSE (NOT _GUA_BOOST_FOUND_LIB_DIR) - SET(BOOST_LIBRARY_DIRS ${_GUA_BOOST_FOUND_LIB_DIR} CACHE STRING "The boost library directory") - message("-- found matching version") - FILE(GLOB BOOST_LIBRARIES ${_GUA_BOOST_FOUND_LIB_DIR}/*.so) - ENDIF (NOT _GUA_BOOST_FOUND_LIB_DIR) - - if (UNIX) -# SET(SCHISM_BOOST_LIB_POSTFIX_REL "${_GUA_BOOST_POSTFIX}" CACHE STRING "(deprecated) boost library release postfix") -# SET(SCHISM_BOOST_LIB_POSTFIX_DBG "${_GUA_BOOST_POSTFIX}" CACHE STRING "(deprecated) boost library debug postfix") -# IF (NOT _GUA_BOOST_POSTFIX) -# MESSAGE(FATAL_ERROR "guacamole_boost.cmake: unable to determine boost library suffix") -# ELSE (NOT _GUA_BOOST_POSTFIX) -# SET(SCHISM_BOOST_LIB_POSTFIX_REL "${_GUA_BOOST_POSTFIX}" CACHE STRING "boost library release postfix") -# SET(SCHISM_BOOST_LIB_POSTFIX_DBG "${_GUA_BOOST_POSTFIX}" CACHE STRING "boost library debug postfix") -# ENDIF (NOT _GUA_BOOST_POSTFIX) - set(GUA_BOOST_MT_REL "${_GUA_BOOST_POSTFIX}" CACHE STRING "boost dynamic library release postfix") - set(GUA_BOOST_MT_DBG "${_GUA_BOOST_POSTFIX}" CACHE STRING "boost dynamic library debug postfix") - set(GUA_BOOST_MT_S_REL "${_GUA_BOOST_POSTFIX}" CACHE STRING "boost static library release postfix") - set(GUA_BOOST_MT_S_DBG "${_GUA_BOOST_POSTFIX}" CACHE STRING "boost static library debug postfix") - elseif (WIN32) -# SET(SCHISM_BOOST_LIB_POSTFIX_REL "${GUA_COMPILER_SUFFIX}-mt-${GUA_BOOST_LIB_VERSION}" CACHE STRING "(deprecated) boost library release postfix") -# SET(SCHISM_BOOST_LIB_POSTFIX_DBG "${GUA_COMPILER_SUFFIX}-mt-gd-${GUA_BOOST_LIB_VERSION}" CACHE STRING "(deprecated) boost library debug postfix") - - set(GUA_BOOST_MT_REL "${GUA_COMPILER_SUFFIX}-mt-${GUA_BOOST_LIB_VERSION}" CACHE STRING "boost dynamic library release postfix") - set(GUA_BOOST_MT_DBG "${GUA_COMPILER_SUFFIX}-mt-gd-${GUA_BOOST_LIB_VERSION}" CACHE STRING "boost dynamic library debug postfix") - set(GUA_BOOST_MT_S_REL "${GUA_COMPILER_SUFFIX}-mt-s-${GUA_BOOST_LIB_VERSION}" CACHE STRING "boost static library release postfix") - set(GUA_BOOST_MT_S_DBG "${GUA_COMPILER_SUFFIX}-mt-sgd-${GUA_BOOST_LIB_VERSION}" CACHE STRING "boost static library debug postfix") - endif (UNIX) - -ENDIF(BOOST_INCLUDE_DIRS AND NOT BOOST_LIBRARIES) -# AND NOT BOOST_LIBRARY_DIRS) diff --git a/cmake/modules/find_bullet.cmake b/cmake/modules/find_bullet.cmake deleted file mode 100644 index 6ae7ee356..000000000 --- a/cmake/modules/find_bullet.cmake +++ /dev/null @@ -1,103 +0,0 @@ -SET(BULLET_INCLUDE_SEARCH_DIRS - ${GLOBAL_EXT_DIR}/inc/bullet - /opt/bullet/current -) - -SET(BULLET_LIBRARY_SEARCH_DIRS - ${GLOBAL_EXT_DIR}/lib - /opt/bullet/current/bullet-build -) - -message("-- checking for BULLET") - -IF (NOT BULLET_INCLUDE_DIRS) - - SET(_BULLET_FOUND_INC_DIRS "") - - FOREACH(_SEARCH_DIR ${BULLET_INCLUDE_SEARCH_DIRS}) - FIND_PATH(_CUR_SEARCH - NAMES src/btBulletDynamicsCommon.h - PATHS ${_SEARCH_DIR} - NO_DEFAULT_PATH) - IF (_CUR_SEARCH) - LIST(APPEND _BULLET_FOUND_INC_DIRS ${_CUR_SEARCH}) - ENDIF(_CUR_SEARCH) - SET(_CUR_SEARCH _CUR_SEARCH-NOTFOUND CACHE INTERNAL "internal use") - ENDFOREACH(_SEARCH_DIR ${BULLET_INCLUDE_SEARCH_DIRS}) - - IF (NOT _BULLET_FOUND_INC_DIRS) - MESSAGE(FATAL_ERROR "find_bullet.cmake: unable to find bullet headers") - ENDIF (NOT _BULLET_FOUND_INC_DIRS) - - FOREACH(_INC_DIR ${_BULLET_FOUND_INC_DIRS}) - LIST(APPEND BULLET_INCLUDE_DIRS ${_INC_DIR}/src) - LIST(APPEND BULLET_INCLUDE_DIRS ${_INC_DIR}/Extras/HACD) - ENDFOREACH(_INC_DIR ${_BOOST_FOUND_INC_DIRS}) - -ENDIF(NOT BULLET_INCLUDE_DIRS) - - -IF(UNIX) - SET(BULLET_DYNAMICS_LIB_SUFFIX "src/BulletDynamics/") - SET(BULLET_COLLISION_LIB_SUFFIX "src/BulletCollision/") - SET(BULLET_LINEAR_MATH_LIB_SUFFIX "src/LinearMath/") - SET(BULLET_HACD_LIB_SUFFIX "Extras/HACD/") - SET(BULLET_DYNAMICS_LIB "libBulletDynamics.so") - SET(BULLET_COLLISION_LIB "libBulletCollision.so") - SET(BULLET_LINEAR_MATH_LIB "libLinearMath.so") - SET(BULLET_HACD_LIB "libHACD.so") -ELSEIF(WIN32) - SET(BULLET_DYNAMICS_LIB_SUFFIX "") - SET(BULLET_COLLISION_LIB_SUFFIX "") - SET(BULLET_LINEAR_MATH_LIB_SUFFIX "") - SET(BULLET_HACD_LIB_SUFFIX "") - SET(BULLET_DYNAMICS_LIB "BulletDynamics.lib") - SET(BULLET_COLLISION_LIB "BulletCollision.lib") - SET(BULLET_LINEAR_MATH_LIB "LinearMath.lib") - SET(BULLET_HACD_LIB "HACD.lib") -ENDIF(UNIX) - - -IF ( BULLET_INCLUDE_DIRS - AND NOT BULLET_LIBRARIES) - - SET(_BULLET_FOUND_LIB_DIR "") - SET(_BULLET_POSTFIX "") - - FOREACH(_SEARCH_DIR ${BULLET_LIBRARY_SEARCH_DIRS}) - FIND_PATH(_CUR_SEARCH - NAMES ${BULLET_DYNAMICS_LIB} - PATHS ${_SEARCH_DIR} - PATH_SUFFIXES debug release ${BULLET_DYNAMICS_LIB_SUFFIX} - NO_DEFAULT_PATH) - message(${_SEARCH_DIR}) - IF (_CUR_SEARCH) - LIST(APPEND _BULLET_FOUND_LIB_DIR ${_SEARCH_DIR}) - ENDIF(_CUR_SEARCH) - SET(_CUR_SEARCH _CUR_SEARCH-NOTFOUND CACHE INTERNAL "internal use") - ENDFOREACH(_SEARCH_DIR ${BULLET_LIBRARY_SEARCH_DIRS}) - - IF (NOT _BULLET_FOUND_LIB_DIR) - MESSAGE(FATAL_ERROR "find_bullet.cmake: unable to find bullet libraries") - ELSE (NOT _BULLET_FOUND_LIB_DIR) - SET(BULLET_LIBRARY_DIRS ${_BULLET_FOUND_LIB_DIR} CACHE STRING "The bullet library directory") - message("-- found matching version") - ENDIF (NOT _BULLET_FOUND_LIB_DIR) - - FOREACH(_LIB_DIR ${_BULLET_FOUND_LIB_DIR}) - LIST(APPEND BULLET_LIBRARY_DIRS ${_LIB_DIR}/${BULLET_DYNAMICS_LIB_SUFFIX}) - LIST(APPEND BULLET_LIBRARY_DIRS ${_LIB_DIR}/${BULLET_COLLISION_LIB_SUFFIX}) - LIST(APPEND BULLET_LIBRARY_DIRS ${_LIB_DIR}/${BULLET_LINEAR_MATH_LIB_SUFFIX}) - LIST(APPEND BULLET_LIBRARY_DIRS ${_LIB_DIR}/${BULLET_HACD_LIB_SUFFIX}) - ENDFOREACH(_LIB_DIR ${_BULLET_FOUND_INC_DIRS}) - - LIST(APPEND BULLET_LIBRARIES ${BULLET_DYNAMICS_LIB}) - LIST(APPEND BULLET_LIBRARIES ${BULLET_COLLISION_LIB}) - LIST(APPEND BULLET_LIBRARIES ${BULLET_LINEAR_MATH_LIB}) - LIST(APPEND BULLET_LIBRARIES ${BULLET_HACD_LIB}) - -ENDIF( BULLET_INCLUDE_DIRS - AND NOT BULLET_LIBRARIES) - - - diff --git a/cmake/modules/find_compiler.cmake b/cmake/modules/find_compiler.cmake index 011ea8a71..1367cd53b 100644 --- a/cmake/modules/find_compiler.cmake +++ b/cmake/modules/find_compiler.cmake @@ -1,29 +1,38 @@ if (WIN32) if (MSVC71) - set (GUA_COMPILER_SUFFIX "vc71") + set (_COMPILER_SUFFIX "vc71") endif(MSVC71) if (MSVC80) - set (GUA_COMPILER_SUFFIX "vc80") + set (_COMPILER_SUFFIX "vc80") endif(MSVC80) if (MSVC90) - set (GUA_COMPILER_SUFFIX "vc90") + set (_COMPILER_SUFFIX "vc90") endif(MSVC90) if (MSVC10) - set (GUA_COMPILER_SUFFIX "vc100") + set (_COMPILER_SUFFIX "vc100") endif(MSVC10) if (MSVC11) - set (GUA_COMPILER_SUFFIX "vc110") + set (_COMPILER_SUFFIX "vc110") endif(MSVC11) if (MSVC12) - set (GUA_COMPILER_SUFFIX "vc120") + set (_COMPILER_SUFFIX "vc120") endif(MSVC12) endif (WIN32) +macro(GET_WIN32_WINNT version) + if (WIN32 AND CMAKE_SYSTEM_VERSION) + set(ver ${CMAKE_SYSTEM_VERSION}) + string(REPLACE "." "" ver ${ver}) + string(REGEX REPLACE "([0-9])" "0\\1" ver ${ver}) + set(${version} "0x${ver}") + endif() +endmacro(GET_WIN32_WINNT) + if (UNIX) if (CMAKE_COMPILER_IS_GNUCXX) #find out the version of gcc being used. @@ -31,17 +40,13 @@ if (UNIX) ARGS --version OUTPUT_VARIABLE _COMPILER_VERSION ) - message(${_COMPILER_VERSION}) string(REGEX REPLACE ".* ([0-9])\\.([0-9])\\.[0-9].*" "\\1\\2" _COMPILER_VERSION ${_COMPILER_VERSION}) - message(${_COMPILER_VERSION}) - set (GUA_COMPILER_SUFFIX "gcc${_COMPILER_VERSION}") - #set (GUA_COMPILER_SUFFIX "") - message(${GUA_COMPILER_SUFFIX}) + set (_COMPILER_SUFFIX "gcc${_COMPILER_VERSION}") endif (CMAKE_COMPILER_IS_GNUCXX) endif(UNIX) -if (GUA_COMPILER_SUFFIX STREQUAL "") - message(FATAL_ERROR "schism_compiler.cmake: unable to identify supported compiler") -else (GUA_COMPILER_SUFFIX STREQUAL "") - set(GUA_COMPILER_SUFFIX ${GUA_COMPILER_SUFFIX} CACHE STRING "The boost style compiler suffix") -endif (GUA_COMPILER_SUFFIX STREQUAL "") +if (_COMPILER_SUFFIX STREQUAL "") + message(FATAL_ERROR "find_compiler.cmake: unable to identify supported compiler") +else (_COMPILER_SUFFIX STREQUAL "") + set(COMPILER_SUFFIX ${_COMPILER_SUFFIX} CACHE STRING "The boost style compiler suffix") +endif (_COMPILER_SUFFIX STREQUAL "") diff --git a/cmake/modules/find_cuda.cmake b/cmake/modules/find_cuda.cmake deleted file mode 100644 index fc7b8fa0d..000000000 --- a/cmake/modules/find_cuda.cmake +++ /dev/null @@ -1,173 +0,0 @@ -#option(GUA_CUDA_BUILD_DEBUG "Build debug" OFF) -option(GUA_CUDA_BUILD_VERBOSE "Verbose Output" OFF) -option(GUA_CUDA_BUILD_COMPUTE20 "Enable Compute 2.0" ON) -option(GUA_CUDA_BUILD_COMPUTE30 "Enable Compute 3.0" OFF) -option(GUA_CUDA_BUILD_COMPUTE35 "Enable Compute 3.5" OFF) -option(GUA_CUDA_BUILD_USE_FAST_MATH "Use lower precision math calculations" ON) -option(GUA_CUDA_BUILD_KEEP_INTERMEDIATE_FILES "Keep the generated intermediate files" ON) - -IF (UNIX) - - ELSEIF(WIN32) - SET(CUDA_LIBRARY_DIRS ${GLOBAL_EXT_DIR}/lib/) - SET(CUDA_LIBRARIES cuda.lib cudart.lib OpenGL32.lib OpenCL.lib ) - SET(CUDA_INCLUDE_DIRS ${GLOBAL_EXT_DIR}/inc/cuda/) -ENDIF(UNIX) - -if (WIN32) - if (MSVC10) - set (GUA_CUDA_NVCC_OPTIONS --cl-version 2010 CACHE STRING "gua cuda internal" FORCE) - set(GUA_CUDA_SHARED_LIB_NAME "cudart64_50_32" CACHE STRING "gua cuda internal" FORCE) - endif(MSVC10) - - if (MSVC11) - set (GUA_CUDA_NVCC_OPTIONS --cl-version 2012 CACHE STRING "gua cuda internal" FORCE) - set(GUA_CUDA_SHARED_LIB_NAME "cudart64_55" CACHE STRING "gua cuda internal" FORCE) - endif(MSVC11) - - if (MSVC12) - set (GUA_CUDA_NVCC_OPTIONS --cl-version 2013 CACHE STRING "gua cuda internal" FORCE) - set(GUA_CUDA_SHARED_LIB_NAME "cudart64_55" CACHE STRING "gua cuda internal" FORCE) - endif(MSVC12) - - set(GUA_CUDA_NVCC_OPTIONS ${GUA_CUDA_NVCC_OPTIONS} --use-local-env --compile CACHE STRING "gua cuda internal" FORCE) - set(GUA_CUDA_NVCC_PATH ${GLOBAL_EXT_DIR}/bin/cuda/bin CACHE PATH "gua cuda internal") - if (${GUA_PLATFORM} MATCHES ${PLATFORM_WIN64}) - set(GUA_CUDA_NVCC_OPTIONS ${GUA_CUDA_NVCC_OPTIONS} --machine 64 -ccbin \"$(VCInstallDir)bin/x86_amd64/cl.exe\" CACHE STRING "gua cuda internal" FORCE) - else (${GUA_PLATFORM} MATCHES ${PLATFORM_WIN64}) - set(GUA_CUDA_NVCC_OPTIONS ${GUA_CUDA_NVCC_OPTIONS} --machine 32 -ccbin \"$(VCInstallDir)bin/x86_amd64/cl.exe\" CACHE STRING "gua cuda internal" FORCE) - endif (${GUA_PLATFORM} MATCHES ${PLATFORM_WIN64}) -elseif (UNIX) - set(GUA_CUDA_NVCC_PATH /opt/cuda/current/cuda/bin CACHE PATH "gua cuda internal") -endif (WIN32) - -set(GUA_CUDA_NVCC_COMMAND "${GUA_CUDA_NVCC_PATH}/nvcc" CACHE STRING "gua cuda internal") - -if (CMAKE_PATCH_VERSION GREATER "10") -# convert CXX compiler options into comma separated list -string(REPLACE " " "," GUA_CUDA_NVCC_CXX_FLAGS ${CMAKE_CXX_FLAGS}) -string(REPLACE " " "," GUA_CUDA_NVCC_CXX_FLAGS_RELEASE ${CMAKE_CXX_FLAGS_RELEASE}) -string(REPLACE " " "," GUA_CUDA_NVCC_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG}) - -string(REPLACE ",-std=c++0x" "," GUA_CUDA_NVCC_CXX_FLAGS ${GUA_CUDA_NVCC_CXX_FLAGS}) -string(REPLACE ",-std=c++0x" "," GUA_CUDA_NVCC_CXX_FLAGS_RELEASE ${GUA_CUDA_NVCC_CXX_FLAGS_RELEASE}) -string(REPLACE ",-std=c++0x" "," GUA_CUDA_NVCC_CXX_FLAGS_DEBUG ${GUA_CUDA_NVCC_CXX_FLAGS_DEBUG}) -endif (CMAKE_PATCH_VERSION GREATER "10") - -set(GUA_CUDA_NVCC_DEFINITIONS "") -set(GUA_CUDA_NVCC_INCLUDE_DIRECTORIES "") - -#if (GUA_CUDA_BUILD_DEBUG) -# set(GUA_CUDA_NVCC_OPTIONS ${GUA_CUDA_NVCC_OPTIONS} -Xcompiler ${GUA_CUDA_NVCC_CXX_FLAGS_DEBUG}${GUA_CUDA_NVCC_CXX_FLAGS} CACHE STRING "gua cuda internal" FORCE) -#else (GUA_CUDA_BUILD_DEBUG) -# set(GUA_CUDA_NVCC_OPTIONS ${GUA_CUDA_NVCC_OPTIONS} --optimize 3 -Xcompiler ${GUA_CUDA_NVCC_CXX_FLAGS_RELEASE}${GUA_CUDA_NVCC_CXX_FLAGS} CACHE STRING "gua cuda internal" FORCE) -#endif (GUA_CUDA_BUILD_DEBUG) - -set(GUA_CUDA_NVCC_OPTIONS ${GUA_CUDA_NVCC_OPTIONS} -Xcompiler CACHE STRING "gua cuda internal" FORCE) -set(GUA_CUDA_NVCC_OPTIONS ${GUA_CUDA_NVCC_OPTIONS} $<$:${GUA_CUDA_NVCC_CXX_FLAGS_DEBUG}${GUA_CUDA_NVCC_CXX_FLAGS}> CACHE STRING "gua cuda internal" FORCE) -set(GUA_CUDA_NVCC_OPTIONS ${GUA_CUDA_NVCC_OPTIONS} $<$:${GUA_CUDA_NVCC_CXX_FLAGS_RELEASE}${GUA_CUDA_NVCC_CXX_FLAGS}> CACHE STRING "gua cuda internal" FORCE) -set(GUA_CUDA_NVCC_OPTIONS ${GUA_CUDA_NVCC_OPTIONS} $<$:--optimize> $<$:3> CACHE STRING "gua cuda internal" FORCE) - -if (GUA_CUDA_BUILD_VERBOSE) - set(GUA_CUDA_NVCC_OPTIONS ${GUA_CUDA_NVCC_OPTIONS} --ptxas-options=-v CACHE STRING "gua cuda internal" FORCE) -endif (GUA_CUDA_BUILD_VERBOSE) - -if (GUA_CUDA_BUILD_COMPUTE20) - set(GUA_CUDA_NVCC_OPTIONS ${GUA_CUDA_NVCC_OPTIONS} -gencode arch=\"compute_20\",code=\"sm_20\" CACHE STRING "gua cuda internal" FORCE) -endif (GUA_CUDA_BUILD_COMPUTE20) - -if (GUA_CUDA_BUILD_COMPUTE30) - set(GUA_CUDA_NVCC_OPTIONS ${GUA_CUDA_NVCC_OPTIONS} -gencode arch=\"compute_30\",code=\"sm_30\" CACHE STRING "gua cuda internal" FORCE) -endif (GUA_CUDA_BUILD_COMPUTE30) - -if (GUA_CUDA_BUILD_COMPUTE35) - set(GUA_CUDA_NVCC_OPTIONS ${GUA_CUDA_NVCC_OPTIONS} -gencode arch=\"compute_35\",code=\"sm_35\" CACHE STRING "gua cuda internal" FORCE) -endif (GUA_CUDA_BUILD_COMPUTE35) - -if (GUA_CUDA_BUILD_KEEP_INTERMEDIATE_FILES) - if (WIN32) - set(GUA_CUDA_NVCC_OPTIONS "${GUA_CUDA_NVCC_OPTIONS} --keep-dir \"x64\\Release\"" CACHE STRING "gua cuda internal" FORCE) - endif (WIN32) -endif(GUA_CUDA_BUILD_KEEP_INTERMEDIATE_FILES) - -if (GUA_CUDA_BUILD_USE_FAST_MATH) - set(GUA_CUDA_NVCC_OPTIONS ${GUA_CUDA_NVCC_OPTIONS} --use_fast_math --fmad=true CACHE STRING "gua cuda internal" FORCE) -endif(GUA_CUDA_BUILD_USE_FAST_MATH) - -# add include directories to pass to the nvcc command -set(GUA_CUDA_NVCC_INCLUDE_DIRECTORIES "") -macro(scm_cuda_project_include_directories) - list(APPEND GUA_CUDA_NVCC_INCLUDE_DIRECTORIES ${ARGN}) -endmacro(scm_cuda_project_include_directories) - -# add definitions to pass to the nvcc command. -set(GUA_CUDA_NVCC_DEFINITIONS "") -macro(scm_cuda_definitions) - list(APPEND GUA_CUDA_NVCC_DEFINITIONS ${ARGN}) -endmacro(scm_cuda_definitions) - -# add the nvcc command to all .cu files -macro(scm_cuda_add_nvcc_prepass GUA_CUDA_OUTPUT_FILES) - set(input_file_list ${ARGV}) - set(output_file_list ) - - list(REMOVE_AT input_file_list 0) - - set(inc_dir_list_name "${PROJECT_NAME}_INCLUDE_DIRS") - set(GUA_CUDA_NVCC_INCLUDE_DIRECTORIES ${${inc_dir_list_name}} ${GUA_CUDA_NVCC_INCLUDE_DIRECTORIES}) - - foreach(cuda_idir ${GUA_CUDA_NVCC_INCLUDE_DIRECTORIES}) - set(GUA_CUDA_NVCC_INC_DIR_STRING ${GUA_CUDA_NVCC_INC_DIR_STRING} -I${cuda_idir}) - endforeach(cuda_idir ${GUA_CUDA_NVCC_INCLUDE_DIRECTORIES}) - - foreach(cuda_def ${GUA_CUDA_NVCC_DEFINITIONS}) - set(GUA_CUDA_NVCC_DEF_STRING ${GUA_CUDA_NVCC_DEF_STRING} -I${cuda_def}) - endforeach(cuda_def ${GUA_CUDA_NVCC_DEFINITIONS}) - - # remove the leading output variable - #LIST(REMOVE_AT input_file_list 0) - - foreach(input_file ${input_file_list}) - get_filename_component(input_file ${input_file} ABSOLUTE) - get_filename_component(input_file_name ${input_file} NAME) - get_filename_component(input_file_name_we ${input_file} NAME_WE) - get_filename_component(input_file_ext ${input_file} EXT) - get_filename_component(input_file_path ${input_file} PATH) - - if (input_file_ext STREQUAL ".cu") - - if (WIN32) - # CMake generates a directory where the intermediate files are stored - file(MAKE_DIRECTORY "${PROJECT_BINARY_DIR}/${PROJECT_NAME}.dir/$(ConfigurationName)") - set(CUDA_NVCC_OUTPUT_FILE ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.dir/$(ConfigurationName)/${input_file_name_we}.obj) - set(CUDA_NVCC_OUTPUT_CUBIN_FILE ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.dir/$(ConfigurationName)/${input_file_name_we}.cubin) - endif (WIN32) - if (UNIX) - # CMake generates a directory where the intermediate files are stored - file(MAKE_DIRECTORY "${PROJECT_BINARY_DIR}/CMakeFiles/${PROJECT_NAME}.dir${input_file_path}") - set(CUDA_NVCC_OUTPUT_FILE "${PROJECT_BINARY_DIR}/CMakeFiles/${PROJECT_NAME}.dir${input_file_path}/${input_file_name_we}.o") - set(CUDA_NVCC_OUTPUT_CUBIN_FILE "${PROJECT_BINARY_DIR}/CMakeFiles/${PROJECT_NAME}.dir${input_file_path}/${input_file_name_we}.cubin") - endif (UNIX) - - set(output_file_list ${output_file_list} ${CUDA_NVCC_OUTPUT_FILE}) - - # add the actual nvcc command to generate the .obj/.o file - add_custom_command(OUTPUT ${CUDA_NVCC_OUTPUT_FILE} - COMMAND ${GUA_CUDA_NVCC_COMMAND} - ARGS ${GUA_CUDA_NVCC_OPTIONS} - ${GUA_CUDA_NVCC_INC_DIR_STRING} - ${GUA_CUDA_NVCC_DEF_STRING} - -o \"${CUDA_NVCC_OUTPUT_FILE}\" - \"${input_file}\" - MAIN_DEPENDENCY ${input_file} - DEPENDS ${input_file} - COMMENT "NVCC compiling (${input_file_name}):") - - endif (input_file_ext STREQUAL ".cu") - endforeach(input_file) - - set_source_files_properties(${output_file_list} PROPERTIES GENERATED TRUE) - set(${GUA_CUDA_OUTPUT_FILES} ${output_file_list}) - -endmacro(scm_cuda_add_nvcc_prepass) - diff --git a/cmake/modules/find_ev.cmake b/cmake/modules/find_ev.cmake deleted file mode 100644 index efb48b56e..000000000 --- a/cmake/modules/find_ev.cmake +++ /dev/null @@ -1,68 +0,0 @@ -SET(EV_INCLUDE_SEARCH_DIRS - /usr/include -) - -SET(EV_LIBRARY_SEARCH_DIRS - /usr/lib -) - -message("-- checking for ev") - -IF (NOT EV_INCLUDE_DIRS) - - SET(_EV_FOUND_INC_DIRS "") - - FOREACH(_SEARCH_DIR ${EV_INCLUDE_SEARCH_DIRS}) - FIND_PATH(_CUR_SEARCH - NAMES ev.h - PATHS ${_SEARCH_DIR} - NO_DEFAULT_PATH) - IF (_CUR_SEARCH) - LIST(APPEND _EV_FOUND_INC_DIRS ${_CUR_SEARCH}) - ENDIF(_CUR_SEARCH) - SET(_CUR_SEARCH _CUR_SEARCH-NOTFOUND CACHE INTERNAL "internal use") - ENDFOREACH(_SEARCH_DIR ${EV_INCLUDE_SEARCH_DIRS}) - - IF (NOT _EV_FOUND_INC_DIRS) - MESSAGE(FATAL_ERROR "find_ev.cmake: unable to find ev headers") - ENDIF (NOT _EV_FOUND_INC_DIRS) - - FOREACH(_INC_DIR ${_EV_FOUND_INC_DIRS}) - LIST(APPEND EV_INCLUDE_DIRS ${_INC_DIR}) - ENDFOREACH(_INC_DIR ${_BOOST_FOUND_INC_DIRS}) - -ENDIF(NOT EV_INCLUDE_DIRS) - -IF ( EV_INCLUDE_DIRS - AND NOT EV_LIBRARIES) - - SET(_EV_FOUND_LIB_DIR "") - SET(_EV_POSTFIX "") - - FOREACH(_SEARCH_DIR ${EV_LIBRARY_SEARCH_DIRS}) - FIND_PATH(_CUR_SEARCH - NAMES libev.so - PATHS ${_SEARCH_DIR} - NO_DEFAULT_PATH) - IF (_CUR_SEARCH) - LIST(APPEND _EV_FOUND_LIB_DIR ${_SEARCH_DIR}) - ENDIF(_CUR_SEARCH) - SET(_CUR_SEARCH _CUR_SEARCH-NOTFOUND CACHE INTERNAL "internal use") - ENDFOREACH(_SEARCH_DIR ${EV_LIBRARY_SEARCH_DIRS}) - - IF (NOT _EV_FOUND_LIB_DIR) - MESSAGE(FATAL_ERROR "find_ev.cmake: unable to find ev library") - ELSE (NOT _EV_FOUND_LIB_DIR) - message("-- found matching version") - ENDIF (NOT _EV_FOUND_LIB_DIR) - - FOREACH(_LIB_DIR ${_EV_FOUND_LIB_DIR}) - LIST(APPEND EV_LIBRARIES ${_LIB_DIR}/libev.so) - ENDFOREACH(_LIB_DIR ${_EV_FOUND_INC_DIRS}) - - -ENDIF( EV_INCLUDE_DIRS - AND NOT EV_LIBRARIES) - - - diff --git a/cmake/modules/find_json.cmake b/cmake/modules/find_json.cmake deleted file mode 100644 index 3cc55cc3f..000000000 --- a/cmake/modules/find_json.cmake +++ /dev/null @@ -1,78 +0,0 @@ -SET(JSON_INCLUDE_SEARCH_DIRS - ${GLOBAL_EXT_DIR}/inc/json - /opt/json/current -) - -SET(JSON_LIBRARY_SEARCH_DIRS - ${GLOBAL_EXT_DIR}/lib - /opt/json/current/json-build -) - -message("-- checking for JSON") - -IF (NOT JSON_INCLUDE_DIRS) - - SET(_JSON_FOUND_INC_DIRS "") - - FOREACH(_SEARCH_DIR ${JSON_INCLUDE_SEARCH_DIRS}) - FIND_PATH(_CUR_SEARCH - NAMES jsoncpp/json/json.h - PATHS ${_SEARCH_DIR} - NO_DEFAULT_PATH) - IF (_CUR_SEARCH) - LIST(APPEND _JSON_FOUND_INC_DIRS ${_CUR_SEARCH}) - ENDIF(_CUR_SEARCH) - SET(_CUR_SEARCH _CUR_SEARCH-NOTFOUND CACHE INTERNAL "internal use") - ENDFOREACH(_SEARCH_DIR ${JSON_INCLUDE_SEARCH_DIRS}) - - IF (NOT _JSON_FOUND_INC_DIRS) - MESSAGE(FATAL_ERROR "find_json.cmake: unable to find json headers") - ENDIF (NOT _JSON_FOUND_INC_DIRS) - - FOREACH(_INC_DIR ${_JSON_FOUND_INC_DIRS}) - LIST(APPEND JSON_INCLUDE_DIRS ${_INC_DIR}) - ENDFOREACH(_INC_DIR ${_BOOST_FOUND_INC_DIRS}) - -ENDIF(NOT JSON_INCLUDE_DIRS) - -IF(UNIX) - SET(JSON_LIB_FILENAME "libjsoncpp.so") -ELSEIF(WIN32) - SET(JSON_LIB_FILENAME "json.lib") -ENDIF(UNIX) - -IF ( JSON_INCLUDE_DIRS - AND NOT JSON_LIBRARIES) - - SET(_JSON_FOUND_LIB_DIR "") - SET(_JSON_POSTFIX "") - - FOREACH(_SEARCH_DIR ${JSON_LIBRARY_SEARCH_DIRS}) - FIND_PATH(_CUR_SEARCH - NAMES ${JSON_LIB_FILENAME} - PATHS ${_SEARCH_DIR} - PATH_SUFFIXES debug release - NO_DEFAULT_PATH) - IF (_CUR_SEARCH) - LIST(APPEND _JSON_FOUND_LIB_DIR ${_SEARCH_DIR}) - ENDIF(_CUR_SEARCH) - SET(_CUR_SEARCH _CUR_SEARCH-NOTFOUND CACHE INTERNAL "internal use") - ENDFOREACH(_SEARCH_DIR ${JSON_LIBRARY_SEARCH_DIRS}) - - IF (NOT _JSON_FOUND_LIB_DIR) - MESSAGE(FATAL_ERROR "find_json.cmake: unable to find json libraries") - ELSE (NOT _JSON_FOUND_LIB_DIR) - SET(JSON_LIBRARY_DIRS ${_JSON_FOUND_LIB_DIR} CACHE STRING "The json library directory") - message("-- found matching version") - ENDIF (NOT _JSON_FOUND_LIB_DIR) - - FOREACH(_LIB_DIR ${_JSON_FOUND_LIB_DIR}) - LIST(APPEND JSON_LIBRARIES ${JSON_LIB_FILENAME}) - ENDFOREACH(_LIB_DIR ${_JSON_FOUND_INC_DIRS}) - - -ENDIF( JSON_INCLUDE_DIRS - AND NOT JSON_LIBRARIES) - - - diff --git a/cmake/modules/find_ovr.cmake b/cmake/modules/find_ovr.cmake new file mode 100644 index 000000000..40a724d12 --- /dev/null +++ b/cmake/modules/find_ovr.cmake @@ -0,0 +1,122 @@ +############################################################################## +# search paths +############################################################################## +SET(OVR_INCLUDE_SEARCH_DIRS + ${GLOBAL_EXT_DIR}/inc/ovr/include + ${OVR_INCLUDE_DIRS} + ${OVR_INCLUDE_SEARCH_DIR} + /opt/OculusSDK/LibOVR/Include +) + +SET(OVR_LIBRARY_SEARCH_DIRS + ${GLOBAL_EXT_DIR}/lib + ${OVR_LIBRARY_DIRS} + ${OVR_LIBRARY_SEARCH_DIR} + /opt/OculusSDK/LibOVR/Lib/Linux/Release/x86_64 +) + +############################################################################## +# feedback to provide user-defined paths to search for python +############################################################################## +MACRO (request_ovr_search_directories) + + IF ( NOT OVR_INCLUDE_DIRS AND NOT OVR_LIBRARY_DIRS ) + SET(OVR_INCLUDE_SEARCH_DIR "Please provide Oculus SDK include path." CACHE PATH "path to Oculus SDK headers.") + SET(OVR_LIBRARY_SEARCH_DIR "Please provide Oculus SDK library path." CACHE PATH "path to Oculus SDK libraries.") + MESSAGE(FATAL_ERROR "find_ovr.cmake: unable to find Oculus SDK.") + ENDIF ( NOT OVR_INCLUDE_DIRS AND NOT OVR_LIBRARY_DIRS ) + + IF ( NOT OVR_INCLUDE_DIRS ) + SET(OVR_INCLUDE_SEARCH_DIR "Please provide Oculus SDK include path." CACHE PATH "path to Oculus SDK headers.") + MESSAGE(FATAL_ERROR "find_ovr.cmake: unable to find Oculus SDK headers.") + ELSE ( NOT OVR_INCLUDE_DIRS ) + UNSET(OVR_INCLUDE_SEARCH_DIR CACHE) + ENDIF ( NOT OVR_INCLUDE_DIRS ) + + IF ( NOT OVR_LIBRARY_DIRS ) + SET(OVR_LIBRARY_SEARCH_DIR "Please provide Oculus SDK library path." CACHE PATH "path to Oculus SDK libraries.") + MESSAGE(FATAL_ERROR "find_ovr.cmake: unable to find Oculus SDK libraries.") + ELSE ( NOT OVR_LIBRARY_DIRS ) + UNSET(OVR_LIBRARY_SEARCH_DIR CACHE) + ENDIF ( NOT OVR_LIBRARY_DIRS ) + +ENDMACRO (request_ovr_search_directories) + +############################################################################## +# search +############################################################################## +message(STATUS "-- checking for OVR") + +IF (NOT OVR_INCLUDE_DIRS) + + SET(_OVR_FOUND_INC_DIRS "") + FOREACH(_SEARCH_DIR ${OVR_INCLUDE_SEARCH_DIRS}) + FIND_PATH(_CUR_SEARCH + NAMES OVR.h + PATHS ${_SEARCH_DIR} + NO_DEFAULT_PATH) + IF (_CUR_SEARCH) + LIST(APPEND _OVR_FOUND_INC_DIRS ${_CUR_SEARCH}) + ENDIF(_CUR_SEARCH) + SET(_CUR_SEARCH _CUR_SEARCH-NOTFOUND CACHE INTERNAL "internal use") + ENDFOREACH(_SEARCH_DIR ${OVR_INCLUDE_SEARCH_DIRS}) + + IF (NOT _OVR_FOUND_INC_DIRS) + request_ovr_search_directories() + ENDIF (NOT _OVR_FOUND_INC_DIRS) + + FOREACH(_INC_DIR ${_OVR_FOUND_INC_DIRS}) + SET(OVR_INCLUDE_DIRS ${OVR_INCLUDE_DIRS} ${_INC_DIR} CACHE PATH "Oculus SDK include directory.") + ENDFOREACH(_INC_DIR ${_OVR_FOUND_INC_DIRS}) + +ENDIF (NOT OVR_INCLUDE_DIRS) + +IF(UNIX) + SET(OVR_LIB_FILENAME "libovr.a") +ELSEIF(WIN32) + SET(OVR_LIB_FILENAME "libovr64.lib") +ENDIF(UNIX) + +IF ( NOT OVR_LIBRARY_DIRS ) + + SET(_OVR_FOUND_LIB_DIR "") + SET(_OVR_POSTFIX "") + + FOREACH(_SEARCH_DIR ${OVR_LIBRARY_SEARCH_DIRS}) + FIND_PATH(_CUR_SEARCH + NAMES ${OVR_LIB_FILENAME} + PATHS ${_SEARCH_DIR} + PATH_SUFFIXES debug release + NO_DEFAULT_PATH) + IF (_CUR_SEARCH) + LIST(APPEND _OVR_FOUND_LIB_DIR ${_SEARCH_DIR}) + ENDIF(_CUR_SEARCH) + SET(_CUR_SEARCH _CUR_SEARCH-NOTFOUND CACHE INTERNAL "internal use") + ENDFOREACH(_SEARCH_DIR ${OVR_LIBRARY_SEARCH_DIRS}) + + IF (NOT _OVR_FOUND_LIB_DIR) + request_ovr_search_directories() + ELSE (NOT _OVR_FOUND_LIB_DIR) + SET(OVR_LIBRARY_DIRS ${_OVR_FOUND_LIB_DIR} CACHE PATH "The Oculus SDK library directory") + ENDIF (NOT _OVR_FOUND_LIB_DIR) + + FOREACH(_LIB_DIR ${_OVR_FOUND_LIB_DIR}) + LIST(APPEND _OVR_LIBRARIES ${OVR_LIB_FILENAME}) + ENDFOREACH(_LIB_DIR ${_OVR_FOUND_INC_DIRS}) + + IF (_OVR_FOUND_LIB_DIR) + SET(OVR_LIBRARIES ${_OVR_LIBRARIES} CACHE FILEPATH "The Oculus SDK library filename.") + ENDIF (_OVR_FOUND_LIB_DIR) + +ENDIF ( NOT OVR_LIBRARY_DIRS ) + +############################################################################## +# verify +############################################################################## +IF ( NOT OVR_INCLUDE_DIRS OR NOT OVR_LIBRARY_DIRS ) + request_ovr_search_directories() +ELSE ( NOT OVR_INCLUDE_DIRS OR NOT OVR_LIBRARY_DIRS ) + UNSET(OVR_INCLUDE_SEARCH_DIR CACHE) + UNSET(OVR_LIBRARY_SEARCH_DIR CACHE) + MESSAGE(STATUS "-- found matching Oculus SDK version") +ENDIF ( NOT OVR_INCLUDE_DIRS OR NOT OVR_LIBRARY_DIRS ) diff --git a/cmake/modules/find_schism.cmake b/cmake/modules/find_schism.cmake deleted file mode 100644 index 0d5f8e58e..000000000 --- a/cmake/modules/find_schism.cmake +++ /dev/null @@ -1,96 +0,0 @@ -SET(SCHISM_INCLUDE_SEARCH_DIRS - ${GLOBAL_EXT_DIR}/inc/schism - #/opt/schism/schism_debug - /opt/schism/current - #/opt/schism/schism_debug -) - -SET(SCHISM_LIBRARY_SEARCH_DIRS - ${GLOBAL_EXT_DIR}/lib - #/opt/schism/schism_debug/lib/linux_x86 - /opt/schism/current/lib/linux_x86 - #/opt/schism/schism_debug/lib/linux_x86 -) - -message("-- checking for schism") - -IF (NOT SCHISM_INCLUDE_DIRS) - - SET(_SCHISM_FOUND_INC_DIRS "") - - FOREACH(_SEARCH_DIR ${SCHISM_INCLUDE_SEARCH_DIRS}) - FIND_PATH(_CUR_SEARCH - NAMES scm_gl_core/src/scm/gl_core.h - PATHS ${_SEARCH_DIR} - NO_DEFAULT_PATH) - IF (_CUR_SEARCH) - LIST(APPEND _SCHISM_FOUND_INC_DIRS ${_CUR_SEARCH}) - ENDIF(_CUR_SEARCH) - SET(_CUR_SEARCH _CUR_SEARCH-NOTFOUND CACHE INTERNAL "internal use") - ENDFOREACH(_SEARCH_DIR ${SCHISM_INCLUDE_SEARCH_DIRS}) - - IF (NOT _SCHISM_FOUND_INC_DIRS) - MESSAGE(FATAL_ERROR "find_schism.cmake: unable to find SCHISM headers") - ENDIF (NOT _SCHISM_FOUND_INC_DIRS) - - FOREACH(_INC_DIR ${_SCHISM_FOUND_INC_DIRS}) - LIST(APPEND SCHISM_INCLUDE_DIRS ${_INC_DIR}/scm_cl_core/src) - LIST(APPEND SCHISM_INCLUDE_DIRS ${_INC_DIR}/scm_core/src) - LIST(APPEND SCHISM_INCLUDE_DIRS ${_INC_DIR}/scm_gl_core/src) - LIST(APPEND SCHISM_INCLUDE_DIRS ${_INC_DIR}/scm_gl_util/src) - LIST(APPEND SCHISM_INCLUDE_DIRS ${_INC_DIR}/scm_input/src) - ENDFOREACH(_INC_DIR ${_BOOST_FOUND_INC_DIRS}) - -ENDIF(NOT SCHISM_INCLUDE_DIRS) - -IF ( SCHISM_INCLUDE_DIRS - AND NOT SCHISM_LIBRARIES) - - SET(_SCHISM_FOUND_LIB_DIR "") - SET(_SCHISM_POSTFIX "") - - FOREACH(_SEARCH_DIR ${SCHISM_LIBRARY_SEARCH_DIRS}) - IF (UNIX) - FIND_PATH(_CUR_SEARCH - NAMES libscm_gl_core.so - PATHS ${_SEARCH_DIR} - NO_DEFAULT_PATH) - ELSEIF(WIN32) - FIND_PATH(_CUR_SEARCH - NAMES scm_gl_core.lib - PATHS ${_SEARCH_DIR} - PATH_SUFFIXES debug release - NO_DEFAULT_PATH) - ENDIF(UNIX) - IF (_CUR_SEARCH) - LIST(APPEND _SCHISM_FOUND_LIB_DIR ${_SEARCH_DIR}) - ENDIF(_CUR_SEARCH) - SET(_CUR_SEARCH _CUR_SEARCH-NOTFOUND CACHE INTERNAL "internal use") - ENDFOREACH(_SEARCH_DIR ${SCHISM_LIBRARY_SEARCH_DIRS}) - - IF (NOT _SCHISM_FOUND_LIB_DIR) - MESSAGE(FATAL_ERROR "find_schism.cmake: unable to find SCHISM library") - ELSE (NOT _SCHISM_FOUND_LIB_DIR) - SET(SCHISM_LIBRARY_DIRS ${_SCHISM_FOUND_LIB_DIR} CACHE STRING "The schism library directory") - message("-- found matching version") - ENDIF (NOT _SCHISM_FOUND_LIB_DIR) - - FOREACH(_LIB_DIR ${_SCHISM_FOUND_LIB_DIR}) - IF (UNIX) - file(GLOB SCHISM_LIBRARIES ${_LIB_DIR}/*.so) - ELSEIF(WIN32) - file(GLOB _SCHISM_LIBRARY_ABSOLUTE_PATHS ${_LIB_DIR}/release/scm*.lib) - FOREACH (_SCHISM_LIB_PATH ${_SCHISM_LIBRARY_ABSOLUTE_PATHS}) - SET(_SCHISM_LIB_FILENAME, "") - GET_FILENAME_COMPONENT(_SCHISM_LIB_FILENAME ${_SCHISM_LIB_PATH} NAME) - LIST(APPEND SCHISM_LIBRARIES ${_SCHISM_LIB_FILENAME}) - ENDFOREACH(_SCHISM_LIB_PATH) - ENDIF(UNIX) - ENDFOREACH(_LIB_DIR ${_SCHISM_FOUND_INC_DIRS}) - - -ENDIF( SCHISM_INCLUDE_DIRS - AND NOT SCHISM_LIBRARIES) - - - diff --git a/doc/Doxyfile b/doc/Doxyfile new file mode 100644 index 000000000..b885839a1 --- /dev/null +++ b/doc/Doxyfile @@ -0,0 +1,1773 @@ +# Doxyfile 1.7.6.1 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# http://www.gnu.org/software/libiconv for the list of possible encodings. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or sequence of words) that should +# identify the project. Note that if you do not use Doxywizard you need +# to put quotes around the project name if it contains spaces. + +PROJECT_NAME = + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer +# a quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = + +# With the PROJECT_LOGO tag one can specify an logo or icon that is +# included in the documentation. The maximum height of the logo should not +# exceed 55 pixels and the maximum width should not exceed 200 pixels. +# Doxygen will copy the logo to the output directory. + +PROJECT_LOGO = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = doc + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = YES + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, +# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English +# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, +# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, +# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = YES + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful if your file system +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + +JAVADOC_AUTOBRIEF = YES + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 2 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding +# "class=itcl::class" will allow you to use the command class in the +# itcl::class meaning. + +TCL_SUBST = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for +# Java. For instance, namespaces will be presented as packages, qualified +# scopes will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources only. Doxygen will then generate output that is more tailored for +# Fortran. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for +# VHDL. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given extension. +# Doxygen has a built-in mapping, but you can override or extend it using this +# tag. The format is ext=language, where ext is a file extension, and language +# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, +# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make +# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C +# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions +# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also makes the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = YES + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. +# Doxygen will parse them like normal C++ but will assume all classes use public +# instead of private inheritance when no explicit protection keyword is present. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate getter +# and setter methods for a property. Setting this option to YES (the default) +# will make doxygen replace the get and set methods by a property in the +# documentation. This will only work if the methods are indeed getting or +# setting a simple type. If this is not the case, or you want to show the +# methods anyway, you should set this option to NO. + +IDL_PROPERTY_SUPPORT = NO + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = YES + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and +# unions are shown inside the group in which they are included (e.g. using +# @ingroup) instead of on a separate page (for HTML and Man pages) or +# section (for LaTeX and RTF). + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and +# unions with only public data fields will be shown inline in the documentation +# of the scope in which they are defined (i.e. file, namespace, or group +# documentation), provided this scope is documented. If set to NO (the default), +# structs, classes, and unions are shown on a separate page (for HTML and Man +# pages) or section (for LaTeX and RTF). + +INLINE_SIMPLE_STRUCTS = YES + +# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum +# is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically +# be useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. + +TYPEDEF_HIDES_STRUCT = NO + +# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to +# determine which symbols to keep in memory and which to flush to disk. +# When the cache is full, less often used symbols will be written to disk. +# For small to medium size projects (<1000 input files) the default value is +# probably good enough. For larger projects a too small cache size can cause +# doxygen to be busy swapping symbols to and from disk most of the time +# causing a significant performance penalty. +# If the system has enough physical memory increasing the cache will improve the +# performance by keeping more symbols in memory. Note that the value works on +# a logarithmic scale so increasing the size by one will roughly double the +# memory usage. The cache size is given by this formula: +# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols. + +SYMBOL_CACHE_SIZE = 0 + +# Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be +# set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given +# their name and scope. Since this can be an expensive process and often the +# same symbol appear multiple times in the code, doxygen keeps a cache of +# pre-resolved symbols. If the cache is too small doxygen will become slower. +# If the cache is too large, memory is wasted. The cache size is given by this +# formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols. + +LOOKUP_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = YES + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base +# name of the file that contains the anonymous namespace. By default +# anonymous namespaces are hidden. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = NO + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = YES + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen +# will list include files with double quotes in the documentation +# rather than with sharp brackets. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen +# will sort the (brief and detailed) documentation of class members so that +# constructors and destructors are listed first. If set to NO (the default) +# the constructors will appear in the respective orders defined by +# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. +# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO +# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. + +SORT_MEMBERS_CTORS_1ST = YES + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the +# hierarchy of group names into alphabetical order. If set to NO (the default) +# the group names will appear in their defined order. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to +# do proper type resolution of all parameters of a function it will reject a +# match between the prototype and the implementation of a member function even +# if there is only one candidate or it is obvious which candidate to choose +# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen +# will still accept a match between prototype and implementation in such cases. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = NO + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = NO + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = NO + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= NO + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or macro consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and macros in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = NO + +# If the sources in your project are distributed over multiple directories +# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy +# in the documentation. The default is NO. + +SHOW_DIRECTORIES = NO + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. +# This will remove the Files entry from the Quick Index and from the +# Folder Tree View (if specified). The default is YES. + +SHOW_FILES = NO + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the +# Namespaces page. This will remove the Namespaces entry from the Quick Index +# and from the Folder Tree View (if specified). The default is YES. + +SHOW_NAMESPACES = NO + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. The create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. +# You can optionally specify a file name after the option, if omitted +# DoxygenLayout.xml will be used as the name of the layout file. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files +# containing the references data. This must be a list of .bib files. The +# .bib extension is automatically appended if omitted. Using this command +# requires the bibtex tool to be installed. See also +# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style +# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this +# feature you need bibtex and perl available in the search path. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = NO + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = NO + +# The WARN_NO_PARAMDOC option can be enabled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = ../include + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is +# also the default input encoding. Doxygen uses libiconv (or the iconv built +# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for +# the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh +# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py +# *.f90 *.f *.for *.vhd *.vhdl + +FILE_PATTERNS = *.hpp \ + *.cpp + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = ../include/gua/renderer/nurbs_geometry + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = * + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty or if +# non of the patterns match the file name, INPUT_FILTER is applied. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) +# and it is also possible to disable source filtering for a specific pattern +# using *.ext= (so without naming a filter). This option only has effect when +# FILTER_SOURCE_FILES is enabled. + +FILTER_SOURCE_PATTERNS = + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. Otherwise they will link to the documentation. + +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = NO + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. Note that when using a custom header you are responsible +# for the proper inclusion of any scripts and style sheets that doxygen +# needs, which is dependent on the configuration options used. +# It is advised to generate a default header using "doxygen -w html +# header.html footer.html stylesheet.css YourConfigFile" and then modify +# that header. Note that the header is subject to change so you typically +# have to redo this when upgrading to a newer version of doxygen or when +# changing the value of configuration settings such as GENERATE_TREEVIEW! + +HTML_HEADER = header.html + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# style sheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that +# the files will be copied as-is; there are no commands or markers available. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. +# Doxygen will adjust the colors in the style sheet and background images +# according to this color. Hue is specified as an angle on a colorwheel, +# see http://en.wikipedia.org/wiki/Hue for more information. +# For instance the value 0 represents red, 60 is yellow, 120 is green, +# 180 is cyan, 240 is blue, 300 purple, and 360 is red again. +# The allowed range is 0 to 359. + +HTML_COLORSTYLE_HUE = 82 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of +# the colors in the HTML output. For a value of 0 the output will use +# grayscales only. A value of 255 will produce the most vivid colors. + +HTML_COLORSTYLE_SAT = 0 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to +# the luminance component of the colors in the HTML output. Values below +# 100 gradually make the output lighter, whereas values above 100 make +# the output darker. The value divided by 100 is the actual gamma applied, +# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, +# and 100 does not change the gamma. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting +# this to NO can help when comparing the output of multiple runs. + +HTML_TIMESTAMP = YES + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. For this to work a browser that supports +# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox +# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). + +HTML_DYNAMIC_SECTIONS = YES + +# If the GENERATE_DOCSET tag is set to YES, additional index files +# will be generated that can be used as input for Apple's Xcode 3 +# integrated development environment, introduced with OSX 10.5 (Leopard). +# To create a documentation set, doxygen will generate a Makefile in the +# HTML output directory. Running make will produce the docset in that +# directory and running "make install" will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find +# it at startup. +# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. + +GENERATE_DOCSET = NO + +# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the +# feed. A documentation feed provides an umbrella under which multiple +# documentation sets from a single provider (such as a company or product suite) +# can be grouped. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that +# should uniquely identify the documentation set bundle. This should be a +# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen +# will append .docset to the name. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING +# is used to encode HtmlHelp index (hhk), content (hhc) and project file +# content. + +CHM_INDEX_ENCODING = + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated +# that can be used as input for Qt's qhelpgenerator to generate a +# Qt Compressed Help (.qch) of the generated HTML documentation. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can +# be used to specify the file name of the resulting .qch file. +# The path specified is relative to the HTML output folder. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#namespace + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#virtual-folders + +QHP_VIRTUAL_FOLDER = doc + +# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to +# add. For more information please see +# http://doc.trolltech.com/qthelpproject.html#custom-filters + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see +# +# Qt Help Project / Custom Filters. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's +# filter section matches. +# +# Qt Help Project / Filter Attributes. + +QHP_SECT_FILTER_ATTRS = + +# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can +# be used to specify the location of Qt's qhelpgenerator. +# If non-empty doxygen will try to run qhelpgenerator on the generated +# .qhp file. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files +# will be generated, which together with the HTML files, form an Eclipse help +# plugin. To install this plugin and make it available under the help contents +# menu in Eclipse, the contents of the directory containing the HTML and XML +# files needs to be copied into the plugins directory of eclipse. The name of +# the directory within the plugins directory should be the same as +# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before +# the help appears. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have +# this name. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) +# at top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. Since the tabs have the same information as the +# navigation tree you can set this option to NO if you already set +# GENERATE_TREEVIEW to YES. + +DISABLE_INDEX = NO + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. +# If the tag value is set to YES, a side panel will be generated +# containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). +# Windows users are probably better off using the HTML help feature. +# Since the tree basically has the same information as the tab index you +# could consider to set DISABLE_INDEX to NO when enabling this option. + +GENERATE_TREEVIEW = NO + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values +# (range [0,1..20]) that doxygen will group on one line in the generated HTML +# documentation. Note that a value of 0 will completely suppress the enum +# values from appearing in the overview section. + +ENUM_VALUES_PER_LINE = 4 + +# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, +# and Class Hierarchy pages using a tree view instead of an ordered list. + +USE_INLINE_TREES = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open +# links to external symbols imported via tag files in a separate window. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of Latex formulas included +# as images in the HTML documentation. The default is 10. Note that +# when you change the font size after a successful doxygen run you need +# to manually remove any form_*.png images from the HTML output directory +# to force them to be regenerated. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are +# not supported properly for IE 6.0, but are supported on all modern browsers. +# Note that when changing this option you need to delete any form_*.png files +# in the HTML output before the changes have effect. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax +# (see http://www.mathjax.org) which uses client side Javascript for the +# rendering instead of using prerendered bitmaps. Use this if you do not +# have LaTeX installed or if you want to formulas look prettier in the HTML +# output. When enabled you also need to install MathJax separately and +# configure the path to it using the MATHJAX_RELPATH option. + +USE_MATHJAX = NO + +# When MathJax is enabled you need to specify the location relative to the +# HTML output directory using the MATHJAX_RELPATH option. The destination +# directory should contain the MathJax.js script. For instance, if the mathjax +# directory is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the +# mathjax.org site, so you can quickly see the result without installing +# MathJax, but it is strongly recommended to install a local copy of MathJax +# before deployment. + +MATHJAX_RELPATH = http://www.mathjax.org/mathjax + +# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension +# names that should be enabled during MathJax rendering. + +MATHJAX_EXTENSIONS = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box +# for the HTML output. The underlying search engine uses javascript +# and DHTML and should work on any modern browser. Note that when using +# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets +# (GENERATE_DOCSET) there is already a search function so this one should +# typically be disabled. For large projects the javascript based search engine +# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. + +SEARCHENGINE = YES + +# When the SERVER_BASED_SEARCH tag is enabled the search engine will be +# implemented using a PHP enabled web server instead of at the web client +# using Javascript. Doxygen will generate the search PHP script and index +# file to put on the web server. The advantage of the server +# based approach is that it scales better to large projects and allows +# full text search. The disadvantages are that it is more difficult to setup +# and does not have live searching capabilities. + +SERVER_BASED_SEARCH = NO + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. +# Note that when enabling USE_PDFLATEX this option is only used for +# generating bitmaps for formulas in the HTML output, but not in the +# Makefile that is written to the output directory. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = YES + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4 + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for +# the generated latex document. The footer should contain everything after +# the last chapter. If it is left blank doxygen will generate a +# standard footer. Notice: only use this tag if you know what you are doing! + +LATEX_FOOTER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = YES + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = YES + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +# If LATEX_SOURCE_CODE is set to YES then doxygen will include +# source code with syntax highlighting in the LaTeX output. +# Note that which sources are shown also depends on other settings +# such as SOURCE_BROWSER. + +LATEX_SOURCE_CODE = NO + +# The LATEX_BIB_STYLE tag can be used to specify the style to use for the +# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See +# http://en.wikipedia.org/wiki/BibTeX for more info. + +LATEX_BIB_STYLE = plain + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load style sheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. This is useful +# if you want to understand what is going on. On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = YES + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# pointed to by INCLUDE_PATH will be searched when a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = ../include + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition that +# overrules the definition found in the source code. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all references to function-like macros +# that are alone on a line, have an all uppercase name, and do not end with a +# semicolon, because these will confuse the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option also works with HAVE_DOT disabled, but it is recommended to +# install and use dot, since it yields more powerful graphs. + +CLASS_DIAGRAMS = YES + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see +# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the +# documentation. The MSCGEN_PATH tag allows you to specify the directory where +# the mscgen tool resides. If left empty the tool is assumed to be found in the +# default search path. + +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = NO + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = YES + +# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is +# allowed to run in parallel. When set to 0 (the default) doxygen will +# base this on the number of processors available in the system. You can set it +# explicitly to a value larger than 0 to get control over the balance +# between CPU load and processing speed. + +DOT_NUM_THREADS = 0 + +# By default doxygen will use the Helvetica font for all dot files that +# doxygen generates. When you want a differently looking font you can specify +# the font name using DOT_FONTNAME. You need to make sure dot is able to find +# the font, which can be done by putting it in a standard location or by setting +# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the +# directory containing the font. + +DOT_FONTNAME = Helvetica + +# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. +# The default size is 10pt. + +DOT_FONTSIZE = 10 + +# By default doxygen will tell dot to use the Helvetica font. +# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to +# set the path where dot can find it. + +DOT_FONTPATH = + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = NO + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = NO + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = NO + +# If the CALL_GRAPH and HAVE_DOT options are set to YES then +# doxygen will generate a call dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable call graphs +# for selected functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then +# doxygen will generate a caller dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable caller +# graphs for selected functions only using the \callergraph command. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will generate a graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = NO + +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = NO + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are svg, png, jpg, or gif. +# If left blank png will be used. If you choose svg you need to set +# HTML_FILE_EXTENSION to xhtml in order to make the SVG files +# visible in IE 9+ (other browsers do not have this requirement). + +DOT_IMAGE_FORMAT = png + +# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to +# enable generation of interactive SVG images that allow zooming and panning. +# Note that this requires a modern browser other than Internet Explorer. +# Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you +# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files +# visible. Older versions of IE do not have SVG support. + +INTERACTIVE_SVG = NO + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = /usr/bin + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The MSCFILE_DIRS tag can be used to specify one or more directories that +# contain msc files that are included in the documentation (see the +# \mscfile command). + +MSCFILE_DIRS = + +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the +# number of direct children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, because dot on Windows does not +# seem to support this out of the box. Warning: Depending on the platform used, +# enabling this option may lead to badly anti-aliased labels on the edges of +# a graph (i.e. they become hard to read). + +DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = NO + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES diff --git a/doc/body.png b/doc/body.png new file mode 100644 index 000000000..d98f86684 Binary files /dev/null and b/doc/body.png differ diff --git a/doc/bootstrap.min.css b/doc/bootstrap.min.css new file mode 100644 index 000000000..b74b4546a --- /dev/null +++ b/doc/bootstrap.min.css @@ -0,0 +1,9 @@ +/*! + * Bootstrap v2.0.4 + * + * Copyright 2012 Twitter, Inc + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Designed and built with all the love in the world @twitter by @mdo and @fat. + */article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}audio:not([controls]){display:none}html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}a:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}a:hover,a:active{outline:0}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{max-width:100%;vertical-align:middle;border:0;-ms-interpolation-mode:bicubic}#map_canvas img{max-width:none}button,input,select,textarea{margin:0;font-size:100%;vertical-align:middle}button,input{*overflow:visible;line-height:normal}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}button,input[type="button"],input[type="reset"],input[type="submit"]{cursor:pointer;-webkit-appearance:button}input[type="search"]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type="search"]::-webkit-search-decoration,input[type="search"]::-webkit-search-cancel-button{-webkit-appearance:none}textarea{overflow:auto;vertical-align:top}.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;content:""}.clearfix:after{clear:both}.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.input-block-level{display:block;width:100%;min-height:28px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box}body{margin:0;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px;line-height:18px;color:#333;background-color:#fff}a{color:#08c;text-decoration:none}a:hover{color:#005580;text-decoration:underline}.row{margin-left:-20px;*zoom:1}.row:before,.row:after{display:table;content:""}.row:after{clear:both}[class*="span"]{float:left;margin-left:20px}.container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:940px}.span12{width:940px}.span11{width:860px}.span10{width:780px}.span9{width:700px}.span8{width:620px}.span7{width:540px}.span6{width:460px}.span5{width:380px}.span4{width:300px}.span3{width:220px}.span2{width:140px}.span1{width:60px}.offset12{margin-left:980px}.offset11{margin-left:900px}.offset10{margin-left:820px}.offset9{margin-left:740px}.offset8{margin-left:660px}.offset7{margin-left:580px}.offset6{margin-left:500px}.offset5{margin-left:420px}.offset4{margin-left:340px}.offset3{margin-left:260px}.offset2{margin-left:180px}.offset1{margin-left:100px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:28px;margin-left:2.127659574%;*margin-left:2.0744680846382977%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .span12{width:99.99999998999999%;*width:99.94680850063828%}.row-fluid .span11{width:91.489361693%;*width:91.4361702036383%}.row-fluid .span10{width:82.97872339599999%;*width:82.92553190663828%}.row-fluid .span9{width:74.468085099%;*width:74.4148936096383%}.row-fluid .span8{width:65.95744680199999%;*width:65.90425531263828%}.row-fluid .span7{width:57.446808505%;*width:57.3936170156383%}.row-fluid .span6{width:48.93617020799999%;*width:48.88297871863829%}.row-fluid .span5{width:40.425531911%;*width:40.3723404216383%}.row-fluid .span4{width:31.914893614%;*width:31.8617021246383%}.row-fluid .span3{width:23.404255317%;*width:23.3510638276383%}.row-fluid .span2{width:14.89361702%;*width:14.8404255306383%}.row-fluid .span1{width:6.382978723%;*width:6.329787233638298%}.container{margin-right:auto;margin-left:auto;*zoom:1}.container:before,.container:after{display:table;content:""}.container:after{clear:both}.container-fluid{padding-right:20px;padding-left:20px;*zoom:1}.container-fluid:before,.container-fluid:after{display:table;content:""}.container-fluid:after{clear:both}p{margin:0 0 9px}p small{font-size:11px;color:#999}.lead{margin-bottom:18px;font-size:20px;font-weight:200;line-height:27px}h1,h2,h3,h4,h5,h6{margin:0;font-family:inherit;font-weight:bold;color:inherit;text-rendering:optimizelegibility}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small{font-weight:normal;color:#999}h1{font-size:30px;line-height:36px}h1 small{font-size:18px}h2{font-size:24px;line-height:36px}h2 small{font-size:18px}h3{font-size:18px;line-height:27px}h3 small{font-size:14px}h4,h5,h6{line-height:18px}h4{font-size:14px}h4 small{font-size:12px}h5{font-size:12px}h6{font-size:11px;color:#999;text-transform:uppercase}.page-header{padding-bottom:17px;margin:18px 0;border-bottom:1px solid #eee}.page-header h1{line-height:1}ul,ol{padding:0;margin:0 0 9px 25px}ul ul,ul ol,ol ol,ol ul{margin-bottom:0}ul{list-style:disc}ol{list-style:decimal}li{line-height:18px}ul.unstyled,ol.unstyled{margin-left:0;list-style:none}dl{margin-bottom:18px}dt,dd{line-height:18px}dt{font-weight:bold;line-height:17px}dd{margin-left:9px}.dl-horizontal dt{float:left;width:120px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:130px}hr{margin:18px 0;border:0;border-top:1px solid #eee;border-bottom:1px solid #fff}strong{font-weight:bold}em{font-style:italic}.muted{color:#999}abbr[title]{cursor:help;border-bottom:1px dotted #999}abbr.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:0 0 0 15px;margin:0 0 18px;border-left:5px solid #eee}blockquote p{margin-bottom:0;font-size:16px;font-weight:300;line-height:22.5px}blockquote small{display:block;line-height:18px;color:#999}blockquote small:before{content:'\2014 \00A0'}blockquote.pull-right{float:right;padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0}blockquote.pull-right p,blockquote.pull-right small{text-align:right}q:before,q:after,blockquote:before,blockquote:after{content:""}address{display:block;margin-bottom:18px;font-style:normal;line-height:18px}small{font-size:100%}cite{font-style:normal}code,pre{padding:0 3px 2px;font-family:Menlo,Monaco,Consolas,"Courier New",monospace;font-size:12px;color:#333;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}code{padding:2px 4px;color:#d14;background-color:#f7f7f9;border:1px solid #e1e1e8}pre{display:block;padding:8.5px;margin:0 0 9px;font-size:12.025px;line-height:18px;word-break:break-all;word-wrap:break-word;white-space:pre;white-space:pre-wrap;background-color:#f5f5f5;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.15);-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}pre.prettyprint{margin-bottom:18px}pre code{padding:0;color:inherit;background-color:transparent;border:0}.pre-scrollable{max-height:340px;overflow-y:scroll}form{margin:0 0 18px}fieldset{padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:27px;font-size:19.5px;line-height:36px;color:#333;border:0;border-bottom:1px solid #e5e5e5}legend small{font-size:13.5px;color:#999}label,input,button,select,textarea{font-size:13px;font-weight:normal;line-height:18px}input,button,select,textarea{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif}label{display:block;margin-bottom:5px}select,textarea,input[type="text"],input[type="password"],input[type="datetime"],input[type="datetime-local"],input[type="date"],input[type="month"],input[type="time"],input[type="week"],input[type="number"],input[type="email"],input[type="url"],input[type="search"],input[type="tel"],input[type="color"],.uneditable-input{display:inline-block;height:18px;padding:4px;margin-bottom:9px;font-size:13px;line-height:18px;color:#555}input,textarea{width:210px}textarea{height:auto}textarea,input[type="text"],input[type="password"],input[type="datetime"],input[type="datetime-local"],input[type="date"],input[type="month"],input[type="time"],input[type="week"],input[type="number"],input[type="email"],input[type="url"],input[type="search"],input[type="tel"],input[type="color"],.uneditable-input{background-color:#fff;border:1px solid #ccc;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-webkit-transition:border linear .2s,box-shadow linear .2s;-moz-transition:border linear .2s,box-shadow linear .2s;-ms-transition:border linear .2s,box-shadow linear .2s;-o-transition:border linear .2s,box-shadow linear .2s;transition:border linear .2s,box-shadow linear .2s}textarea:focus,input[type="text"]:focus,input[type="password"]:focus,input[type="datetime"]:focus,input[type="datetime-local"]:focus,input[type="date"]:focus,input[type="month"]:focus,input[type="time"]:focus,input[type="week"]:focus,input[type="number"]:focus,input[type="email"]:focus,input[type="url"]:focus,input[type="search"]:focus,input[type="tel"]:focus,input[type="color"]:focus,.uneditable-input:focus{border-color:rgba(82,168,236,0.8);outline:0;outline:thin dotted \9;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6)}input[type="radio"],input[type="checkbox"]{margin:3px 0;*margin-top:0;line-height:normal;cursor:pointer}input[type="submit"],input[type="reset"],input[type="button"],input[type="radio"],input[type="checkbox"]{width:auto}.uneditable-textarea{width:auto;height:auto}select,input[type="file"]{height:28px;*margin-top:4px;line-height:28px}select{width:220px;border:1px solid #bbb}select[multiple],select[size]{height:auto}select:focus,input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.radio,.checkbox{min-height:18px;padding-left:18px}.radio input[type="radio"],.checkbox input[type="checkbox"]{float:left;margin-left:-18px}.controls>.radio:first-child,.controls>.checkbox:first-child{padding-top:5px}.radio.inline,.checkbox.inline{display:inline-block;padding-top:5px;margin-bottom:0;vertical-align:middle}.radio.inline+.radio.inline,.checkbox.inline+.checkbox.inline{margin-left:10px}.input-mini{width:60px}.input-small{width:90px}.input-medium{width:150px}.input-large{width:210px}.input-xlarge{width:270px}.input-xxlarge{width:530px}input[class*="span"],select[class*="span"],textarea[class*="span"],.uneditable-input[class*="span"],.row-fluid input[class*="span"],.row-fluid select[class*="span"],.row-fluid textarea[class*="span"],.row-fluid .uneditable-input[class*="span"]{float:none;margin-left:0}.input-append input[class*="span"],.input-append .uneditable-input[class*="span"],.input-prepend input[class*="span"],.input-prepend .uneditable-input[class*="span"],.row-fluid .input-prepend [class*="span"],.row-fluid .input-append [class*="span"]{display:inline-block}input,textarea,.uneditable-input{margin-left:0}input.span12,textarea.span12,.uneditable-input.span12{width:930px}input.span11,textarea.span11,.uneditable-input.span11{width:850px}input.span10,textarea.span10,.uneditable-input.span10{width:770px}input.span9,textarea.span9,.uneditable-input.span9{width:690px}input.span8,textarea.span8,.uneditable-input.span8{width:610px}input.span7,textarea.span7,.uneditable-input.span7{width:530px}input.span6,textarea.span6,.uneditable-input.span6{width:450px}input.span5,textarea.span5,.uneditable-input.span5{width:370px}input.span4,textarea.span4,.uneditable-input.span4{width:290px}input.span3,textarea.span3,.uneditable-input.span3{width:210px}input.span2,textarea.span2,.uneditable-input.span2{width:130px}input.span1,textarea.span1,.uneditable-input.span1{width:50px}input[disabled],select[disabled],textarea[disabled],input[readonly],select[readonly],textarea[readonly]{cursor:not-allowed;background-color:#eee;border-color:#ddd}input[type="radio"][disabled],input[type="checkbox"][disabled],input[type="radio"][readonly],input[type="checkbox"][readonly]{background-color:transparent}.control-group.warning>label,.control-group.warning .help-block,.control-group.warning .help-inline{color:#c09853}.control-group.warning .checkbox,.control-group.warning .radio,.control-group.warning input,.control-group.warning select,.control-group.warning textarea{color:#c09853;border-color:#c09853}.control-group.warning .checkbox:focus,.control-group.warning .radio:focus,.control-group.warning input:focus,.control-group.warning select:focus,.control-group.warning textarea:focus{border-color:#a47e3c;-webkit-box-shadow:0 0 6px #dbc59e;-moz-box-shadow:0 0 6px #dbc59e;box-shadow:0 0 6px #dbc59e}.control-group.warning .input-prepend .add-on,.control-group.warning .input-append .add-on{color:#c09853;background-color:#fcf8e3;border-color:#c09853}.control-group.error>label,.control-group.error .help-block,.control-group.error .help-inline{color:#b94a48}.control-group.error .checkbox,.control-group.error .radio,.control-group.error input,.control-group.error select,.control-group.error textarea{color:#b94a48;border-color:#b94a48}.control-group.error .checkbox:focus,.control-group.error .radio:focus,.control-group.error input:focus,.control-group.error select:focus,.control-group.error textarea:focus{border-color:#953b39;-webkit-box-shadow:0 0 6px #d59392;-moz-box-shadow:0 0 6px #d59392;box-shadow:0 0 6px #d59392}.control-group.error .input-prepend .add-on,.control-group.error .input-append .add-on{color:#b94a48;background-color:#f2dede;border-color:#b94a48}.control-group.success>label,.control-group.success .help-block,.control-group.success .help-inline{color:#468847}.control-group.success .checkbox,.control-group.success .radio,.control-group.success input,.control-group.success select,.control-group.success textarea{color:#468847;border-color:#468847}.control-group.success .checkbox:focus,.control-group.success .radio:focus,.control-group.success input:focus,.control-group.success select:focus,.control-group.success textarea:focus{border-color:#356635;-webkit-box-shadow:0 0 6px #7aba7b;-moz-box-shadow:0 0 6px #7aba7b;box-shadow:0 0 6px #7aba7b}.control-group.success .input-prepend .add-on,.control-group.success .input-append .add-on{color:#468847;background-color:#dff0d8;border-color:#468847}input:focus:required:invalid,textarea:focus:required:invalid,select:focus:required:invalid{color:#b94a48;border-color:#ee5f5b}input:focus:required:invalid:focus,textarea:focus:required:invalid:focus,select:focus:required:invalid:focus{border-color:#e9322d;-webkit-box-shadow:0 0 6px #f8b9b7;-moz-box-shadow:0 0 6px #f8b9b7;box-shadow:0 0 6px #f8b9b7}.form-actions{padding:17px 20px 18px;margin-top:18px;margin-bottom:18px;background-color:#f5f5f5;border-top:1px solid #e5e5e5;*zoom:1}.form-actions:before,.form-actions:after{display:table;content:""}.form-actions:after{clear:both}.uneditable-input{overflow:hidden;white-space:nowrap;cursor:not-allowed;background-color:#fff;border-color:#eee;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.025);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.025);box-shadow:inset 0 1px 2px rgba(0,0,0,0.025)}:-moz-placeholder{color:#999}:-ms-input-placeholder{color:#999}::-webkit-input-placeholder{color:#999}.help-block,.help-inline{color:#555}.help-block{display:block;margin-bottom:9px}.help-inline{display:inline-block;*display:inline;padding-left:5px;vertical-align:middle;*zoom:1}.input-prepend,.input-append{margin-bottom:5px}.input-prepend input,.input-append input,.input-prepend select,.input-append select,.input-prepend .uneditable-input,.input-append .uneditable-input{position:relative;margin-bottom:0;*margin-left:0;vertical-align:middle;-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0}.input-prepend input:focus,.input-append input:focus,.input-prepend select:focus,.input-append select:focus,.input-prepend .uneditable-input:focus,.input-append .uneditable-input:focus{z-index:2}.input-prepend .uneditable-input,.input-append .uneditable-input{border-left-color:#ccc}.input-prepend .add-on,.input-append .add-on{display:inline-block;width:auto;height:18px;min-width:16px;padding:4px 5px;font-weight:normal;line-height:18px;text-align:center;text-shadow:0 1px 0 #fff;vertical-align:middle;background-color:#eee;border:1px solid #ccc}.input-prepend .add-on,.input-append .add-on,.input-prepend .btn,.input-append .btn{margin-left:-1px;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.input-prepend .active,.input-append .active{background-color:#a9dba9;border-color:#46a546}.input-prepend .add-on,.input-prepend .btn{margin-right:-1px}.input-prepend .add-on:first-child,.input-prepend .btn:first-child{-webkit-border-radius:3px 0 0 3px;-moz-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px}.input-append input,.input-append select,.input-append .uneditable-input{-webkit-border-radius:3px 0 0 3px;-moz-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px}.input-append .uneditable-input{border-right-color:#ccc;border-left-color:#eee}.input-append .add-on:last-child,.input-append .btn:last-child{-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0}.input-prepend.input-append input,.input-prepend.input-append select,.input-prepend.input-append .uneditable-input{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.input-prepend.input-append .add-on:first-child,.input-prepend.input-append .btn:first-child{margin-right:-1px;-webkit-border-radius:3px 0 0 3px;-moz-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px}.input-prepend.input-append .add-on:last-child,.input-prepend.input-append .btn:last-child{margin-left:-1px;-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0}.search-query{padding-right:14px;padding-right:4px \9;padding-left:14px;padding-left:4px \9;margin-bottom:0;-webkit-border-radius:14px;-moz-border-radius:14px;border-radius:14px}.form-search input,.form-inline input,.form-horizontal input,.form-search textarea,.form-inline textarea,.form-horizontal textarea,.form-search select,.form-inline select,.form-horizontal select,.form-search .help-inline,.form-inline .help-inline,.form-horizontal .help-inline,.form-search .uneditable-input,.form-inline .uneditable-input,.form-horizontal .uneditable-input,.form-search .input-prepend,.form-inline .input-prepend,.form-horizontal .input-prepend,.form-search .input-append,.form-inline .input-append,.form-horizontal .input-append{display:inline-block;*display:inline;margin-bottom:0;*zoom:1}.form-search .hide,.form-inline .hide,.form-horizontal .hide{display:none}.form-search label,.form-inline label{display:inline-block}.form-search .input-append,.form-inline .input-append,.form-search .input-prepend,.form-inline .input-prepend{margin-bottom:0}.form-search .radio,.form-search .checkbox,.form-inline .radio,.form-inline .checkbox{padding-left:0;margin-bottom:0;vertical-align:middle}.form-search .radio input[type="radio"],.form-search .checkbox input[type="checkbox"],.form-inline .radio input[type="radio"],.form-inline .checkbox input[type="checkbox"]{float:left;margin-right:3px;margin-left:0}.control-group{margin-bottom:9px}legend+.control-group{margin-top:18px;-webkit-margin-top-collapse:separate}.form-horizontal .control-group{margin-bottom:18px;*zoom:1}.form-horizontal .control-group:before,.form-horizontal .control-group:after{display:table;content:""}.form-horizontal .control-group:after{clear:both}.form-horizontal .control-label{float:left;width:140px;padding-top:5px;text-align:right}.form-horizontal .controls{*display:inline-block;*padding-left:20px;margin-left:160px;*margin-left:0}.form-horizontal .controls:first-child{*padding-left:160px}.form-horizontal .help-block{margin-top:9px;margin-bottom:0}.form-horizontal .form-actions{padding-left:160px}table{max-width:100%;background-color:transparent;border-collapse:collapse;border-spacing:0}.table{width:100%;margin-bottom:18px}.table th,.table td{padding:8px;line-height:18px;text-align:left;vertical-align:top;border-top:1px solid #ddd}.table th{font-weight:bold}.table thead th{vertical-align:bottom}.table caption+thead tr:first-child th,.table caption+thead tr:first-child td,.table colgroup+thead tr:first-child th,.table colgroup+thead tr:first-child td,.table thead:first-child tr:first-child th,.table thead:first-child tr:first-child td{border-top:0}.table tbody+tbody{border-top:2px solid #ddd}.table-condensed th,.table-condensed td{padding:4px 5px}.table-bordered{border:1px solid #ddd;border-collapse:separate;*border-collapse:collapsed;border-left:0;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.table-bordered th,.table-bordered td{border-left:1px solid #ddd}.table-bordered caption+thead tr:first-child th,.table-bordered caption+tbody tr:first-child th,.table-bordered caption+tbody tr:first-child td,.table-bordered colgroup+thead tr:first-child th,.table-bordered colgroup+tbody tr:first-child th,.table-bordered colgroup+tbody tr:first-child td,.table-bordered thead:first-child tr:first-child th,.table-bordered tbody:first-child tr:first-child th,.table-bordered tbody:first-child tr:first-child td{border-top:0}.table-bordered thead:first-child tr:first-child th:first-child,.table-bordered tbody:first-child tr:first-child td:first-child{-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-topleft:4px}.table-bordered thead:first-child tr:first-child th:last-child,.table-bordered tbody:first-child tr:first-child td:last-child{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-moz-border-radius-topright:4px}.table-bordered thead:last-child tr:last-child th:first-child,.table-bordered tbody:last-child tr:last-child td:first-child{-webkit-border-radius:0 0 0 4px;-moz-border-radius:0 0 0 4px;border-radius:0 0 0 4px;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-moz-border-radius-bottomleft:4px}.table-bordered thead:last-child tr:last-child th:last-child,.table-bordered tbody:last-child tr:last-child td:last-child{-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-moz-border-radius-bottomright:4px}.table-striped tbody tr:nth-child(odd) td,.table-striped tbody tr:nth-child(odd) th{background-color:#f9f9f9}.table tbody tr:hover td,.table tbody tr:hover th{background-color:#f5f5f5}table .span1{float:none;width:44px;margin-left:0}table .span2{float:none;width:124px;margin-left:0}table .span3{float:none;width:204px;margin-left:0}table .span4{float:none;width:284px;margin-left:0}table .span5{float:none;width:364px;margin-left:0}table .span6{float:none;width:444px;margin-left:0}table .span7{float:none;width:524px;margin-left:0}table .span8{float:none;width:604px;margin-left:0}table .span9{float:none;width:684px;margin-left:0}table .span10{float:none;width:764px;margin-left:0}table .span11{float:none;width:844px;margin-left:0}table .span12{float:none;width:924px;margin-left:0}table .span13{float:none;width:1004px;margin-left:0}table .span14{float:none;width:1084px;margin-left:0}table .span15{float:none;width:1164px;margin-left:0}table .span16{float:none;width:1244px;margin-left:0}table .span17{float:none;width:1324px;margin-left:0}table .span18{float:none;width:1404px;margin-left:0}table .span19{float:none;width:1484px;margin-left:0}table .span20{float:none;width:1564px;margin-left:0}table .span21{float:none;width:1644px;margin-left:0}table .span22{float:none;width:1724px;margin-left:0}table .span23{float:none;width:1804px;margin-left:0}table .span24{float:none;width:1884px;margin-left:0}[class^="icon-"],[class*=" icon-"]{display:inline-block;width:14px;height:14px;*margin-right:.3em;line-height:14px;vertical-align:text-top;background-image:url("../img/glyphicons-halflings.png");background-position:14px 14px;background-repeat:no-repeat}[class^="icon-"]:last-child,[class*=" icon-"]:last-child{*margin-left:0}.icon-white{background-image:url("../img/glyphicons-halflings-white.png")}.icon-glass{background-position:0 0}.icon-music{background-position:-24px 0}.icon-search{background-position:-48px 0}.icon-envelope{background-position:-72px 0}.icon-heart{background-position:-96px 0}.icon-star{background-position:-120px 0}.icon-star-empty{background-position:-144px 0}.icon-user{background-position:-168px 0}.icon-film{background-position:-192px 0}.icon-th-large{background-position:-216px 0}.icon-th{background-position:-240px 0}.icon-th-list{background-position:-264px 0}.icon-ok{background-position:-288px 0}.icon-remove{background-position:-312px 0}.icon-zoom-in{background-position:-336px 0}.icon-zoom-out{background-position:-360px 0}.icon-off{background-position:-384px 0}.icon-signal{background-position:-408px 0}.icon-cog{background-position:-432px 0}.icon-trash{background-position:-456px 0}.icon-home{background-position:0 -24px}.icon-file{background-position:-24px -24px}.icon-time{background-position:-48px -24px}.icon-road{background-position:-72px -24px}.icon-download-alt{background-position:-96px -24px}.icon-download{background-position:-120px -24px}.icon-upload{background-position:-144px -24px}.icon-inbox{background-position:-168px -24px}.icon-play-circle{background-position:-192px -24px}.icon-repeat{background-position:-216px -24px}.icon-refresh{background-position:-240px -24px}.icon-list-alt{background-position:-264px -24px}.icon-lock{background-position:-287px -24px}.icon-flag{background-position:-312px -24px}.icon-headphones{background-position:-336px -24px}.icon-volume-off{background-position:-360px -24px}.icon-volume-down{background-position:-384px -24px}.icon-volume-up{background-position:-408px -24px}.icon-qrcode{background-position:-432px -24px}.icon-barcode{background-position:-456px -24px}.icon-tag{background-position:0 -48px}.icon-tags{background-position:-25px -48px}.icon-book{background-position:-48px -48px}.icon-bookmark{background-position:-72px -48px}.icon-print{background-position:-96px -48px}.icon-camera{background-position:-120px -48px}.icon-font{background-position:-144px -48px}.icon-bold{background-position:-167px -48px}.icon-italic{background-position:-192px -48px}.icon-text-height{background-position:-216px -48px}.icon-text-width{background-position:-240px -48px}.icon-align-left{background-position:-264px -48px}.icon-align-center{background-position:-288px -48px}.icon-align-right{background-position:-312px -48px}.icon-align-justify{background-position:-336px -48px}.icon-list{background-position:-360px -48px}.icon-indent-left{background-position:-384px -48px}.icon-indent-right{background-position:-408px -48px}.icon-facetime-video{background-position:-432px -48px}.icon-picture{background-position:-456px -48px}.icon-pencil{background-position:0 -72px}.icon-map-marker{background-position:-24px -72px}.icon-adjust{background-position:-48px -72px}.icon-tint{background-position:-72px -72px}.icon-edit{background-position:-96px -72px}.icon-share{background-position:-120px -72px}.icon-check{background-position:-144px -72px}.icon-move{background-position:-168px -72px}.icon-step-backward{background-position:-192px -72px}.icon-fast-backward{background-position:-216px -72px}.icon-backward{background-position:-240px -72px}.icon-play{background-position:-264px -72px}.icon-pause{background-position:-288px -72px}.icon-stop{background-position:-312px -72px}.icon-forward{background-position:-336px -72px}.icon-fast-forward{background-position:-360px -72px}.icon-step-forward{background-position:-384px -72px}.icon-eject{background-position:-408px -72px}.icon-chevron-left{background-position:-432px -72px}.icon-chevron-right{background-position:-456px -72px}.icon-plus-sign{background-position:0 -96px}.icon-minus-sign{background-position:-24px -96px}.icon-remove-sign{background-position:-48px -96px}.icon-ok-sign{background-position:-72px -96px}.icon-question-sign{background-position:-96px -96px}.icon-info-sign{background-position:-120px -96px}.icon-screenshot{background-position:-144px -96px}.icon-remove-circle{background-position:-168px -96px}.icon-ok-circle{background-position:-192px -96px}.icon-ban-circle{background-position:-216px -96px}.icon-arrow-left{background-position:-240px -96px}.icon-arrow-right{background-position:-264px -96px}.icon-arrow-up{background-position:-289px -96px}.icon-arrow-down{background-position:-312px -96px}.icon-share-alt{background-position:-336px -96px}.icon-resize-full{background-position:-360px -96px}.icon-resize-small{background-position:-384px -96px}.icon-plus{background-position:-408px -96px}.icon-minus{background-position:-433px -96px}.icon-asterisk{background-position:-456px -96px}.icon-exclamation-sign{background-position:0 -120px}.icon-gift{background-position:-24px -120px}.icon-leaf{background-position:-48px -120px}.icon-fire{background-position:-72px -120px}.icon-eye-open{background-position:-96px -120px}.icon-eye-close{background-position:-120px -120px}.icon-warning-sign{background-position:-144px -120px}.icon-plane{background-position:-168px -120px}.icon-calendar{background-position:-192px -120px}.icon-random{background-position:-216px -120px}.icon-comment{background-position:-240px -120px}.icon-magnet{background-position:-264px -120px}.icon-chevron-up{background-position:-288px -120px}.icon-chevron-down{background-position:-313px -119px}.icon-retweet{background-position:-336px -120px}.icon-shopping-cart{background-position:-360px -120px}.icon-folder-close{background-position:-384px -120px}.icon-folder-open{background-position:-408px -120px}.icon-resize-vertical{background-position:-432px -119px}.icon-resize-horizontal{background-position:-456px -118px}.icon-hdd{background-position:0 -144px}.icon-bullhorn{background-position:-24px -144px}.icon-bell{background-position:-48px -144px}.icon-certificate{background-position:-72px -144px}.icon-thumbs-up{background-position:-96px -144px}.icon-thumbs-down{background-position:-120px -144px}.icon-hand-right{background-position:-144px -144px}.icon-hand-left{background-position:-168px -144px}.icon-hand-up{background-position:-192px -144px}.icon-hand-down{background-position:-216px -144px}.icon-circle-arrow-right{background-position:-240px -144px}.icon-circle-arrow-left{background-position:-264px -144px}.icon-circle-arrow-up{background-position:-288px -144px}.icon-circle-arrow-down{background-position:-312px -144px}.icon-globe{background-position:-336px -144px}.icon-wrench{background-position:-360px -144px}.icon-tasks{background-position:-384px -144px}.icon-filter{background-position:-408px -144px}.icon-briefcase{background-position:-432px -144px}.icon-fullscreen{background-position:-456px -144px}.dropup,.dropdown{position:relative}.dropdown-toggle{*margin-bottom:-3px}.dropdown-toggle:active,.open .dropdown-toggle{outline:0}.caret{display:inline-block;width:0;height:0;vertical-align:top;border-top:4px solid #000;border-right:4px solid transparent;border-left:4px solid transparent;content:"";opacity:.3;filter:alpha(opacity=30)}.dropdown .caret{margin-top:8px;margin-left:2px}.dropdown:hover .caret,.open .caret{opacity:1;filter:alpha(opacity=100)}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:4px 0;margin:1px 0 0;list-style:none;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);*border-right-width:2px;*border-bottom-width:2px;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);-moz-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2);-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{*width:100%;height:1px;margin:8px 1px;*margin:-5px 0 5px;overflow:hidden;background-color:#e5e5e5;border-bottom:1px solid #fff}.dropdown-menu a{display:block;padding:3px 15px;clear:both;font-weight:normal;line-height:18px;color:#333;white-space:nowrap}.dropdown-menu li>a:hover,.dropdown-menu .active>a,.dropdown-menu .active>a:hover{color:#fff;text-decoration:none;background-color:#08c}.open{*z-index:1000}.open>.dropdown-menu{display:block}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{border-top:0;border-bottom:4px solid #000;content:"\2191"}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:1px}.typeahead{margin-top:2px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #eee;border:1px solid rgba(0,0,0,0.05);-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);box-shadow:inset 0 1px 1px rgba(0,0,0,0.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,0.15)}.well-large{padding:24px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.well-small{padding:9px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.fade{opacity:0;-webkit-transition:opacity .15s linear;-moz-transition:opacity .15s linear;-ms-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{position:relative;height:0;overflow:hidden;-webkit-transition:height .35s ease;-moz-transition:height .35s ease;-ms-transition:height .35s ease;-o-transition:height .35s ease;transition:height .35s ease}.collapse.in{height:auto}.close{float:right;font-size:20px;font-weight:bold;line-height:18px;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:alpha(opacity=20)}.close:hover{color:#000;text-decoration:none;cursor:pointer;opacity:.4;filter:alpha(opacity=40)}button.close{padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none}.btn{display:inline-block;*display:inline;padding:4px 10px 4px;margin-bottom:0;*margin-left:.3em;font-size:13px;line-height:18px;*line-height:20px;color:#333;text-align:center;text-shadow:0 1px 1px rgba(255,255,255,0.75);vertical-align:middle;cursor:pointer;background-color:#f5f5f5;*background-color:#e6e6e6;background-image:-ms-linear-gradient(top,#fff,#e6e6e6);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fff),to(#e6e6e6));background-image:-webkit-linear-gradient(top,#fff,#e6e6e6);background-image:-o-linear-gradient(top,#fff,#e6e6e6);background-image:linear-gradient(top,#fff,#e6e6e6);background-image:-moz-linear-gradient(top,#fff,#e6e6e6);background-repeat:repeat-x;border:1px solid #ccc;*border:0;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);border-color:#e6e6e6 #e6e6e6 #bfbfbf;border-bottom-color:#b3b3b3;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ffffff',endColorstr='#e6e6e6',GradientType=0);filter:progid:dximagetransform.microsoft.gradient(enabled=false);*zoom:1;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05)}.btn:hover,.btn:active,.btn.active,.btn.disabled,.btn[disabled]{background-color:#e6e6e6;*background-color:#d9d9d9}.btn:active,.btn.active{background-color:#ccc \9}.btn:first-child{*margin-left:0}.btn:hover{color:#333;text-decoration:none;background-color:#e6e6e6;*background-color:#d9d9d9;background-position:0 -15px;-webkit-transition:background-position .1s linear;-moz-transition:background-position .1s linear;-ms-transition:background-position .1s linear;-o-transition:background-position .1s linear;transition:background-position .1s linear}.btn:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn.active,.btn:active{background-color:#e6e6e6;background-color:#d9d9d9 \9;background-image:none;outline:0;-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05)}.btn.disabled,.btn[disabled]{cursor:default;background-color:#e6e6e6;background-image:none;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.btn-large{padding:9px 14px;font-size:15px;line-height:normal;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}.btn-large [class^="icon-"]{margin-top:1px}.btn-small{padding:5px 9px;font-size:11px;line-height:16px}.btn-small [class^="icon-"]{margin-top:-1px}.btn-mini{padding:2px 6px;font-size:11px;line-height:14px}.btn-primary,.btn-primary:hover,.btn-warning,.btn-warning:hover,.btn-danger,.btn-danger:hover,.btn-success,.btn-success:hover,.btn-info,.btn-info:hover,.btn-inverse,.btn-inverse:hover{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.btn-primary.active,.btn-warning.active,.btn-danger.active,.btn-success.active,.btn-info.active,.btn-inverse.active{color:rgba(255,255,255,0.75)}.btn{border-color:#ccc;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25)}.btn-primary{background-color:#0074cc;*background-color:#05c;background-image:-ms-linear-gradient(top,#08c,#05c);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#05c));background-image:-webkit-linear-gradient(top,#08c,#05c);background-image:-o-linear-gradient(top,#08c,#05c);background-image:-moz-linear-gradient(top,#08c,#05c);background-image:linear-gradient(top,#08c,#05c);background-repeat:repeat-x;border-color:#05c #05c #003580;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#0088cc',endColorstr='#0055cc',GradientType=0);filter:progid:dximagetransform.microsoft.gradient(enabled=false)}.btn-primary:hover,.btn-primary:active,.btn-primary.active,.btn-primary.disabled,.btn-primary[disabled]{background-color:#05c;*background-color:#004ab3}.btn-primary:active,.btn-primary.active{background-color:#004099 \9}.btn-warning{background-color:#faa732;*background-color:#f89406;background-image:-ms-linear-gradient(top,#fbb450,#f89406);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fbb450),to(#f89406));background-image:-webkit-linear-gradient(top,#fbb450,#f89406);background-image:-o-linear-gradient(top,#fbb450,#f89406);background-image:-moz-linear-gradient(top,#fbb450,#f89406);background-image:linear-gradient(top,#fbb450,#f89406);background-repeat:repeat-x;border-color:#f89406 #f89406 #ad6704;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#fbb450',endColorstr='#f89406',GradientType=0);filter:progid:dximagetransform.microsoft.gradient(enabled=false)}.btn-warning:hover,.btn-warning:active,.btn-warning.active,.btn-warning.disabled,.btn-warning[disabled]{background-color:#f89406;*background-color:#df8505}.btn-warning:active,.btn-warning.active{background-color:#c67605 \9}.btn-danger{background-color:#da4f49;*background-color:#bd362f;background-image:-ms-linear-gradient(top,#ee5f5b,#bd362f);background-image:-webkit-gradient(linear,0 0,0 100%,from(#ee5f5b),to(#bd362f));background-image:-webkit-linear-gradient(top,#ee5f5b,#bd362f);background-image:-o-linear-gradient(top,#ee5f5b,#bd362f);background-image:-moz-linear-gradient(top,#ee5f5b,#bd362f);background-image:linear-gradient(top,#ee5f5b,#bd362f);background-repeat:repeat-x;border-color:#bd362f #bd362f #802420;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ee5f5b',endColorstr='#bd362f',GradientType=0);filter:progid:dximagetransform.microsoft.gradient(enabled=false)}.btn-danger:hover,.btn-danger:active,.btn-danger.active,.btn-danger.disabled,.btn-danger[disabled]{background-color:#bd362f;*background-color:#a9302a}.btn-danger:active,.btn-danger.active{background-color:#942a25 \9}.btn-success{background-color:#5bb75b;*background-color:#51a351;background-image:-ms-linear-gradient(top,#62c462,#51a351);background-image:-webkit-gradient(linear,0 0,0 100%,from(#62c462),to(#51a351));background-image:-webkit-linear-gradient(top,#62c462,#51a351);background-image:-o-linear-gradient(top,#62c462,#51a351);background-image:-moz-linear-gradient(top,#62c462,#51a351);background-image:linear-gradient(top,#62c462,#51a351);background-repeat:repeat-x;border-color:#51a351 #51a351 #387038;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#62c462',endColorstr='#51a351',GradientType=0);filter:progid:dximagetransform.microsoft.gradient(enabled=false)}.btn-success:hover,.btn-success:active,.btn-success.active,.btn-success.disabled,.btn-success[disabled]{background-color:#51a351;*background-color:#499249}.btn-success:active,.btn-success.active{background-color:#408140 \9}.btn-info{background-color:#49afcd;*background-color:#2f96b4;background-image:-ms-linear-gradient(top,#5bc0de,#2f96b4);background-image:-webkit-gradient(linear,0 0,0 100%,from(#5bc0de),to(#2f96b4));background-image:-webkit-linear-gradient(top,#5bc0de,#2f96b4);background-image:-o-linear-gradient(top,#5bc0de,#2f96b4);background-image:-moz-linear-gradient(top,#5bc0de,#2f96b4);background-image:linear-gradient(top,#5bc0de,#2f96b4);background-repeat:repeat-x;border-color:#2f96b4 #2f96b4 #1f6377;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#5bc0de',endColorstr='#2f96b4',GradientType=0);filter:progid:dximagetransform.microsoft.gradient(enabled=false)}.btn-info:hover,.btn-info:active,.btn-info.active,.btn-info.disabled,.btn-info[disabled]{background-color:#2f96b4;*background-color:#2a85a0}.btn-info:active,.btn-info.active{background-color:#24748c \9}.btn-inverse{background-color:#414141;*background-color:#222;background-image:-ms-linear-gradient(top,#555,#222);background-image:-webkit-gradient(linear,0 0,0 100%,from(#555),to(#222));background-image:-webkit-linear-gradient(top,#555,#222);background-image:-o-linear-gradient(top,#555,#222);background-image:-moz-linear-gradient(top,#555,#222);background-image:linear-gradient(top,#555,#222);background-repeat:repeat-x;border-color:#222 #222 #000;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#555555',endColorstr='#222222',GradientType=0);filter:progid:dximagetransform.microsoft.gradient(enabled=false)}.btn-inverse:hover,.btn-inverse:active,.btn-inverse.active,.btn-inverse.disabled,.btn-inverse[disabled]{background-color:#222;*background-color:#151515}.btn-inverse:active,.btn-inverse.active{background-color:#080808 \9}button.btn,input[type="submit"].btn{*padding-top:2px;*padding-bottom:2px}button.btn::-moz-focus-inner,input[type="submit"].btn::-moz-focus-inner{padding:0;border:0}button.btn.btn-large,input[type="submit"].btn.btn-large{*padding-top:7px;*padding-bottom:7px}button.btn.btn-small,input[type="submit"].btn.btn-small{*padding-top:3px;*padding-bottom:3px}button.btn.btn-mini,input[type="submit"].btn.btn-mini{*padding-top:1px;*padding-bottom:1px}.btn-group{position:relative;*margin-left:.3em;*zoom:1}.btn-group:before,.btn-group:after{display:table;content:""}.btn-group:after{clear:both}.btn-group:first-child{*margin-left:0}.btn-group+.btn-group{margin-left:5px}.btn-toolbar{margin-top:9px;margin-bottom:9px}.btn-toolbar .btn-group{display:inline-block;*display:inline;*zoom:1}.btn-group>.btn{position:relative;float:left;margin-left:-1px;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.btn-group>.btn:first-child{margin-left:0;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-bottomleft:4px;-moz-border-radius-topleft:4px}.btn-group>.btn:last-child,.btn-group>.dropdown-toggle{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-moz-border-radius-topright:4px;-moz-border-radius-bottomright:4px}.btn-group>.btn.large:first-child{margin-left:0;-webkit-border-bottom-left-radius:6px;border-bottom-left-radius:6px;-webkit-border-top-left-radius:6px;border-top-left-radius:6px;-moz-border-radius-bottomleft:6px;-moz-border-radius-topleft:6px}.btn-group>.btn.large:last-child,.btn-group>.large.dropdown-toggle{-webkit-border-top-right-radius:6px;border-top-right-radius:6px;-webkit-border-bottom-right-radius:6px;border-bottom-right-radius:6px;-moz-border-radius-topright:6px;-moz-border-radius-bottomright:6px}.btn-group>.btn:hover,.btn-group>.btn:focus,.btn-group>.btn:active,.btn-group>.btn.active{z-index:2}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.dropdown-toggle{*padding-top:4px;padding-right:8px;*padding-bottom:4px;padding-left:8px;-webkit-box-shadow:inset 1px 0 0 rgba(255,255,255,0.125),inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 1px 0 0 rgba(255,255,255,0.125),inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 1px 0 0 rgba(255,255,255,0.125),inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05)}.btn-group>.btn-mini.dropdown-toggle{padding-right:5px;padding-left:5px}.btn-group>.btn-small.dropdown-toggle{*padding-top:4px;*padding-bottom:4px}.btn-group>.btn-large.dropdown-toggle{padding-right:12px;padding-left:12px}.btn-group.open .dropdown-toggle{background-image:none;-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05)}.btn-group.open .btn.dropdown-toggle{background-color:#e6e6e6}.btn-group.open .btn-primary.dropdown-toggle{background-color:#05c}.btn-group.open .btn-warning.dropdown-toggle{background-color:#f89406}.btn-group.open .btn-danger.dropdown-toggle{background-color:#bd362f}.btn-group.open .btn-success.dropdown-toggle{background-color:#51a351}.btn-group.open .btn-info.dropdown-toggle{background-color:#2f96b4}.btn-group.open .btn-inverse.dropdown-toggle{background-color:#222}.btn .caret{margin-top:7px;margin-left:0}.btn:hover .caret,.open.btn-group .caret{opacity:1;filter:alpha(opacity=100)}.btn-mini .caret{margin-top:5px}.btn-small .caret{margin-top:6px}.btn-large .caret{margin-top:6px;border-top-width:5px;border-right-width:5px;border-left-width:5px}.dropup .btn-large .caret{border-top:0;border-bottom:5px solid #000}.btn-primary .caret,.btn-warning .caret,.btn-danger .caret,.btn-info .caret,.btn-success .caret,.btn-inverse .caret{border-top-color:#fff;border-bottom-color:#fff;opacity:.75;filter:alpha(opacity=75)}.alert{padding:8px 35px 8px 14px;margin-bottom:18px;color:#c09853;text-shadow:0 1px 0 rgba(255,255,255,0.5);background-color:#fcf8e3;border:1px solid #fbeed5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.alert-heading{color:inherit}.alert .close{position:relative;top:-2px;right:-21px;line-height:18px}.alert-success{color:#468847;background-color:#dff0d8;border-color:#d6e9c6}.alert-danger,.alert-error{color:#b94a48;background-color:#f2dede;border-color:#eed3d7}.alert-info{color:#3a87ad;background-color:#d9edf7;border-color:#bce8f1}.alert-block{padding-top:14px;padding-bottom:14px}.alert-block>p,.alert-block>ul{margin-bottom:0}.alert-block p+p{margin-top:5px}.nav{margin-bottom:18px;margin-left:0;list-style:none}.nav>li>a{display:block}.nav>li>a:hover{text-decoration:none;background-color:#eee}.nav>.pull-right{float:right}.nav .nav-header{display:block;padding:3px 15px;font-size:11px;font-weight:bold;line-height:18px;color:#999;text-shadow:0 1px 0 rgba(255,255,255,0.5);text-transform:uppercase}.nav li+.nav-header{margin-top:9px}.nav-list{padding-right:15px;padding-left:15px;margin-bottom:0}.nav-list>li>a,.nav-list .nav-header{margin-right:-15px;margin-left:-15px;text-shadow:0 1px 0 rgba(255,255,255,0.5)}.nav-list>li>a{padding:3px 15px}.nav-list>.active>a,.nav-list>.active>a:hover{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.2);background-color:#08c}.nav-list [class^="icon-"]{margin-right:2px}.nav-list .divider{*width:100%;height:1px;margin:8px 1px;*margin:-5px 0 5px;overflow:hidden;background-color:#e5e5e5;border-bottom:1px solid #fff}.nav-tabs,.nav-pills{*zoom:1}.nav-tabs:before,.nav-pills:before,.nav-tabs:after,.nav-pills:after{display:table;content:""}.nav-tabs:after,.nav-pills:after{clear:both}.nav-tabs>li,.nav-pills>li{float:left}.nav-tabs>li>a,.nav-pills>li>a{padding-right:12px;padding-left:12px;margin-right:2px;line-height:14px}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{margin-bottom:-1px}.nav-tabs>li>a{padding-top:8px;padding-bottom:8px;line-height:18px;border:1px solid transparent;-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>.active>a,.nav-tabs>.active>a:hover{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-pills>li>a{padding-top:8px;padding-bottom:8px;margin-top:2px;margin-bottom:2px;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}.nav-pills>.active>a,.nav-pills>.active>a:hover{color:#fff;background-color:#08c}.nav-stacked>li{float:none}.nav-stacked>li>a{margin-right:0}.nav-tabs.nav-stacked{border-bottom:0}.nav-tabs.nav-stacked>li>a{border:1px solid #ddd;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.nav-tabs.nav-stacked>li:first-child>a{-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0}.nav-tabs.nav-stacked>li:last-child>a{-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px}.nav-tabs.nav-stacked>li>a:hover{z-index:2;border-color:#ddd}.nav-pills.nav-stacked>li>a{margin-bottom:3px}.nav-pills.nav-stacked>li:last-child>a{margin-bottom:1px}.nav-tabs .dropdown-menu{-webkit-border-radius:0 0 5px 5px;-moz-border-radius:0 0 5px 5px;border-radius:0 0 5px 5px}.nav-pills .dropdown-menu{-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.nav-tabs .dropdown-toggle .caret,.nav-pills .dropdown-toggle .caret{margin-top:6px;border-top-color:#08c;border-bottom-color:#08c}.nav-tabs .dropdown-toggle:hover .caret,.nav-pills .dropdown-toggle:hover .caret{border-top-color:#005580;border-bottom-color:#005580}.nav-tabs .active .dropdown-toggle .caret,.nav-pills .active .dropdown-toggle .caret{border-top-color:#333;border-bottom-color:#333}.nav>.dropdown.active>a:hover{color:#000;cursor:pointer}.nav-tabs .open .dropdown-toggle,.nav-pills .open .dropdown-toggle,.nav>li.dropdown.open.active>a:hover{color:#fff;background-color:#999;border-color:#999}.nav li.dropdown.open .caret,.nav li.dropdown.open.active .caret,.nav li.dropdown.open a:hover .caret{border-top-color:#fff;border-bottom-color:#fff;opacity:1;filter:alpha(opacity=100)}.tabs-stacked .open>a:hover{border-color:#999}.tabbable{*zoom:1}.tabbable:before,.tabbable:after{display:table;content:""}.tabbable:after{clear:both}.tab-content{overflow:auto}.tabs-below>.nav-tabs,.tabs-right>.nav-tabs,.tabs-left>.nav-tabs{border-bottom:0}.tab-content>.tab-pane,.pill-content>.pill-pane{display:none}.tab-content>.active,.pill-content>.active{display:block}.tabs-below>.nav-tabs{border-top:1px solid #ddd}.tabs-below>.nav-tabs>li{margin-top:-1px;margin-bottom:0}.tabs-below>.nav-tabs>li>a{-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px}.tabs-below>.nav-tabs>li>a:hover{border-top-color:#ddd;border-bottom-color:transparent}.tabs-below>.nav-tabs>.active>a,.tabs-below>.nav-tabs>.active>a:hover{border-color:transparent #ddd #ddd #ddd}.tabs-left>.nav-tabs>li,.tabs-right>.nav-tabs>li{float:none}.tabs-left>.nav-tabs>li>a,.tabs-right>.nav-tabs>li>a{min-width:74px;margin-right:0;margin-bottom:3px}.tabs-left>.nav-tabs{float:left;margin-right:19px;border-right:1px solid #ddd}.tabs-left>.nav-tabs>li>a{margin-right:-1px;-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.tabs-left>.nav-tabs>li>a:hover{border-color:#eee #ddd #eee #eee}.tabs-left>.nav-tabs .active>a,.tabs-left>.nav-tabs .active>a:hover{border-color:#ddd transparent #ddd #ddd;*border-right-color:#fff}.tabs-right>.nav-tabs{float:right;margin-left:19px;border-left:1px solid #ddd}.tabs-right>.nav-tabs>li>a{margin-left:-1px;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.tabs-right>.nav-tabs>li>a:hover{border-color:#eee #eee #eee #ddd}.tabs-right>.nav-tabs .active>a,.tabs-right>.nav-tabs .active>a:hover{border-color:#ddd #ddd #ddd transparent;*border-left-color:#fff}.navbar{*position:relative;*z-index:2;margin-bottom:18px;overflow:visible}.navbar-inner{min-height:40px;padding-right:20px;padding-left:20px;background-color:#2c2c2c;background-image:-moz-linear-gradient(top,#333,#222);background-image:-ms-linear-gradient(top,#333,#222);background-image:-webkit-gradient(linear,0 0,0 100%,from(#333),to(#222));background-image:-webkit-linear-gradient(top,#333,#222);background-image:-o-linear-gradient(top,#333,#222);background-image:linear-gradient(top,#333,#222);background-repeat:repeat-x;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;filter:progid:dximagetransform.microsoft.gradient(startColorstr='#333333',endColorstr='#222222',GradientType=0);-webkit-box-shadow:0 1px 3px rgba(0,0,0,0.25),inset 0 -1px 0 rgba(0,0,0,0.1);-moz-box-shadow:0 1px 3px rgba(0,0,0,0.25),inset 0 -1px 0 rgba(0,0,0,0.1);box-shadow:0 1px 3px rgba(0,0,0,0.25),inset 0 -1px 0 rgba(0,0,0,0.1)}.navbar .container{width:auto}.nav-collapse.collapse{height:auto}.navbar{color:#999}.navbar .brand:hover{text-decoration:none}.navbar .brand{display:block;float:left;padding:8px 20px 12px;margin-left:-20px;font-size:20px;font-weight:200;line-height:1;color:#999}.navbar .navbar-text{margin-bottom:0;line-height:40px}.navbar .navbar-link{color:#999}.navbar .navbar-link:hover{color:#fff}.navbar .btn,.navbar .btn-group{margin-top:5px}.navbar .btn-group .btn{margin:0}.navbar-form{margin-bottom:0;*zoom:1}.navbar-form:before,.navbar-form:after{display:table;content:""}.navbar-form:after{clear:both}.navbar-form input,.navbar-form select,.navbar-form .radio,.navbar-form .checkbox{margin-top:5px}.navbar-form input,.navbar-form select{display:inline-block;margin-bottom:0}.navbar-form input[type="image"],.navbar-form input[type="checkbox"],.navbar-form input[type="radio"]{margin-top:3px}.navbar-form .input-append,.navbar-form .input-prepend{margin-top:6px;white-space:nowrap}.navbar-form .input-append input,.navbar-form .input-prepend input{margin-top:0}.navbar-search{position:relative;float:left;margin-top:6px;margin-bottom:0}.navbar-search .search-query{padding:4px 9px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px;font-weight:normal;line-height:1;color:#fff;background-color:#626262;border:1px solid #151515;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1),0 1px 0 rgba(255,255,255,0.15);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1),0 1px 0 rgba(255,255,255,0.15);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1),0 1px 0 rgba(255,255,255,0.15);-webkit-transition:none;-moz-transition:none;-ms-transition:none;-o-transition:none;transition:none}.navbar-search .search-query:-moz-placeholder{color:#ccc}.navbar-search .search-query:-ms-input-placeholder{color:#ccc}.navbar-search .search-query::-webkit-input-placeholder{color:#ccc}.navbar-search .search-query:focus,.navbar-search .search-query.focused{padding:5px 10px;color:#333;text-shadow:0 1px 0 #fff;background-color:#fff;border:0;outline:0;-webkit-box-shadow:0 0 3px rgba(0,0,0,0.15);-moz-box-shadow:0 0 3px rgba(0,0,0,0.15);box-shadow:0 0 3px rgba(0,0,0,0.15)}.navbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;z-index:1030;margin-bottom:0}.navbar-fixed-top .navbar-inner,.navbar-fixed-bottom .navbar-inner{padding-right:0;padding-left:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:940px}.navbar-fixed-top{top:0}.navbar-fixed-bottom{bottom:0}.navbar .nav{position:relative;left:0;display:block;float:left;margin:0 10px 0 0}.navbar .nav.pull-right{float:right}.navbar .nav>li{display:block;float:left}.navbar .nav>li>a{float:none;padding:9px 10px 11px;line-height:19px;color:#999;text-decoration:none;text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.navbar .btn{display:inline-block;padding:4px 10px 4px;margin:5px 5px 6px;line-height:18px}.navbar .btn-group{padding:5px 5px 6px;margin:0}.navbar .nav>li>a:hover{color:#fff;text-decoration:none;background-color:transparent}.navbar .nav .active>a,.navbar .nav .active>a:hover{color:#fff;text-decoration:none;background-color:#222}.navbar .divider-vertical{width:1px;height:40px;margin:0 9px;overflow:hidden;background-color:#222;border-right:1px solid #333}.navbar .nav.pull-right{margin-right:0;margin-left:10px}.navbar .btn-navbar{display:none;float:right;padding:7px 10px;margin-right:5px;margin-left:5px;background-color:#2c2c2c;*background-color:#222;background-image:-ms-linear-gradient(top,#333,#222);background-image:-webkit-gradient(linear,0 0,0 100%,from(#333),to(#222));background-image:-webkit-linear-gradient(top,#333,#222);background-image:-o-linear-gradient(top,#333,#222);background-image:linear-gradient(top,#333,#222);background-image:-moz-linear-gradient(top,#333,#222);background-repeat:repeat-x;border-color:#222 #222 #000;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#333333',endColorstr='#222222',GradientType=0);filter:progid:dximagetransform.microsoft.gradient(enabled=false);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.075);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.075);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.075)}.navbar .btn-navbar:hover,.navbar .btn-navbar:active,.navbar .btn-navbar.active,.navbar .btn-navbar.disabled,.navbar .btn-navbar[disabled]{background-color:#222;*background-color:#151515}.navbar .btn-navbar:active,.navbar .btn-navbar.active{background-color:#080808 \9}.navbar .btn-navbar .icon-bar{display:block;width:18px;height:2px;background-color:#f5f5f5;-webkit-border-radius:1px;-moz-border-radius:1px;border-radius:1px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,0.25);-moz-box-shadow:0 1px 0 rgba(0,0,0,0.25);box-shadow:0 1px 0 rgba(0,0,0,0.25)}.btn-navbar .icon-bar+.icon-bar{margin-top:3px}.navbar .dropdown-menu:before{position:absolute;top:-7px;left:9px;display:inline-block;border-right:7px solid transparent;border-bottom:7px solid #ccc;border-left:7px solid transparent;border-bottom-color:rgba(0,0,0,0.2);content:''}.navbar .dropdown-menu:after{position:absolute;top:-6px;left:10px;display:inline-block;border-right:6px solid transparent;border-bottom:6px solid #fff;border-left:6px solid transparent;content:''}.navbar-fixed-bottom .dropdown-menu:before{top:auto;bottom:-7px;border-top:7px solid #ccc;border-bottom:0;border-top-color:rgba(0,0,0,0.2)}.navbar-fixed-bottom .dropdown-menu:after{top:auto;bottom:-6px;border-top:6px solid #fff;border-bottom:0}.navbar .nav li.dropdown .dropdown-toggle .caret,.navbar .nav li.dropdown.open .caret{border-top-color:#fff;border-bottom-color:#fff}.navbar .nav li.dropdown.active .caret{opacity:1;filter:alpha(opacity=100)}.navbar .nav li.dropdown.open>.dropdown-toggle,.navbar .nav li.dropdown.active>.dropdown-toggle,.navbar .nav li.dropdown.open.active>.dropdown-toggle{background-color:transparent}.navbar .nav li.dropdown.active>.dropdown-toggle:hover{color:#fff}.navbar .pull-right .dropdown-menu,.navbar .dropdown-menu.pull-right{right:0;left:auto}.navbar .pull-right .dropdown-menu:before,.navbar .dropdown-menu.pull-right:before{right:12px;left:auto}.navbar .pull-right .dropdown-menu:after,.navbar .dropdown-menu.pull-right:after{right:13px;left:auto}.breadcrumb{padding:7px 14px;margin:0 0 18px;list-style:none;background-color:#fbfbfb;background-image:-moz-linear-gradient(top,#fff,#f5f5f5);background-image:-ms-linear-gradient(top,#fff,#f5f5f5);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fff),to(#f5f5f5));background-image:-webkit-linear-gradient(top,#fff,#f5f5f5);background-image:-o-linear-gradient(top,#fff,#f5f5f5);background-image:linear-gradient(top,#fff,#f5f5f5);background-repeat:repeat-x;border:1px solid #ddd;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ffffff',endColorstr='#f5f5f5',GradientType=0);-webkit-box-shadow:inset 0 1px 0 #fff;-moz-box-shadow:inset 0 1px 0 #fff;box-shadow:inset 0 1px 0 #fff}.breadcrumb li{display:inline-block;*display:inline;text-shadow:0 1px 0 #fff;*zoom:1}.breadcrumb .divider{padding:0 5px;color:#999}.breadcrumb .active a{color:#333}.pagination{height:36px;margin:18px 0}.pagination ul{display:inline-block;*display:inline;margin-bottom:0;margin-left:0;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;*zoom:1;-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:0 1px 2px rgba(0,0,0,0.05);box-shadow:0 1px 2px rgba(0,0,0,0.05)}.pagination li{display:inline}.pagination a{float:left;padding:0 14px;line-height:34px;text-decoration:none;border:1px solid #ddd;border-left-width:0}.pagination a:hover,.pagination .active a{background-color:#f5f5f5}.pagination .active a{color:#999;cursor:default}.pagination .disabled span,.pagination .disabled a,.pagination .disabled a:hover{color:#999;cursor:default;background-color:transparent}.pagination li:first-child a{border-left-width:1px;-webkit-border-radius:3px 0 0 3px;-moz-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px}.pagination li:last-child a{-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0}.pagination-centered{text-align:center}.pagination-right{text-align:right}.pager{margin-bottom:18px;margin-left:0;text-align:center;list-style:none;*zoom:1}.pager:before,.pager:after{display:table;content:""}.pager:after{clear:both}.pager li{display:inline}.pager a{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px}.pager a:hover{text-decoration:none;background-color:#f5f5f5}.pager .next a{float:right}.pager .previous a{float:left}.pager .disabled a,.pager .disabled a:hover{color:#999;cursor:default;background-color:#fff}.modal-open .dropdown-menu{z-index:2050}.modal-open .dropdown.open{*z-index:2050}.modal-open .popover{z-index:2060}.modal-open .tooltip{z-index:2070}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{opacity:0}.modal-backdrop,.modal-backdrop.fade.in{opacity:.8;filter:alpha(opacity=80)}.modal{position:fixed;top:50%;left:50%;z-index:1050;width:560px;margin:-250px 0 0 -280px;overflow:auto;background-color:#fff;border:1px solid #999;border:1px solid rgba(0,0,0,0.3);*border:1px solid #999;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 3px 7px rgba(0,0,0,0.3);-moz-box-shadow:0 3px 7px rgba(0,0,0,0.3);box-shadow:0 3px 7px rgba(0,0,0,0.3);-webkit-background-clip:padding-box;-moz-background-clip:padding-box;background-clip:padding-box}.modal.fade{top:-25%;-webkit-transition:opacity .3s linear,top .3s ease-out;-moz-transition:opacity .3s linear,top .3s ease-out;-ms-transition:opacity .3s linear,top .3s ease-out;-o-transition:opacity .3s linear,top .3s ease-out;transition:opacity .3s linear,top .3s ease-out}.modal.fade.in{top:50%}.modal-header{padding:9px 15px;border-bottom:1px solid #eee}.modal-header .close{margin-top:2px}.modal-body{max-height:400px;padding:15px;overflow-y:auto}.modal-form{margin-bottom:0}.modal-footer{padding:14px 15px 15px;margin-bottom:0;text-align:right;background-color:#f5f5f5;border-top:1px solid #ddd;-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px;*zoom:1;-webkit-box-shadow:inset 0 1px 0 #fff;-moz-box-shadow:inset 0 1px 0 #fff;box-shadow:inset 0 1px 0 #fff}.modal-footer:before,.modal-footer:after{display:table;content:""}.modal-footer:after{clear:both}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.tooltip{position:absolute;z-index:1020;display:block;padding:5px;font-size:11px;opacity:0;filter:alpha(opacity=0);visibility:visible}.tooltip.in{opacity:.8;filter:alpha(opacity=80)}.tooltip.top{margin-top:-2px}.tooltip.right{margin-left:2px}.tooltip.bottom{margin-top:2px}.tooltip.left{margin-left:-2px}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-top:5px solid #000;border-right:5px solid transparent;border-left:5px solid transparent}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-top:5px solid transparent;border-bottom:5px solid transparent;border-left:5px solid #000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-right:5px solid transparent;border-bottom:5px solid #000;border-left:5px solid transparent}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-top:5px solid transparent;border-right:5px solid #000;border-bottom:5px solid transparent}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;text-decoration:none;background-color:#000;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0}.popover{position:absolute;top:0;left:0;z-index:1010;display:none;padding:5px}.popover.top{margin-top:-5px}.popover.right{margin-left:5px}.popover.bottom{margin-top:5px}.popover.left{margin-left:-5px}.popover.top .arrow{bottom:0;left:50%;margin-left:-5px;border-top:5px solid #000;border-right:5px solid transparent;border-left:5px solid transparent}.popover.right .arrow{top:50%;left:0;margin-top:-5px;border-top:5px solid transparent;border-right:5px solid #000;border-bottom:5px solid transparent}.popover.bottom .arrow{top:0;left:50%;margin-left:-5px;border-right:5px solid transparent;border-bottom:5px solid #000;border-left:5px solid transparent}.popover.left .arrow{top:50%;right:0;margin-top:-5px;border-top:5px solid transparent;border-bottom:5px solid transparent;border-left:5px solid #000}.popover .arrow{position:absolute;width:0;height:0}.popover-inner{width:280px;padding:3px;overflow:hidden;background:#000;background:rgba(0,0,0,0.8);-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 3px 7px rgba(0,0,0,0.3);-moz-box-shadow:0 3px 7px rgba(0,0,0,0.3);box-shadow:0 3px 7px rgba(0,0,0,0.3)}.popover-title{padding:9px 15px;line-height:1;background-color:#f5f5f5;border-bottom:1px solid #eee;-webkit-border-radius:3px 3px 0 0;-moz-border-radius:3px 3px 0 0;border-radius:3px 3px 0 0}.popover-content{padding:14px;background-color:#fff;-webkit-border-radius:0 0 3px 3px;-moz-border-radius:0 0 3px 3px;border-radius:0 0 3px 3px;-webkit-background-clip:padding-box;-moz-background-clip:padding-box;background-clip:padding-box}.popover-content p,.popover-content ul,.popover-content ol{margin-bottom:0}.thumbnails{margin-left:-20px;list-style:none;*zoom:1}.thumbnails:before,.thumbnails:after{display:table;content:""}.thumbnails:after{clear:both}.row-fluid .thumbnails{margin-left:0}.thumbnails>li{float:left;margin-bottom:18px;margin-left:20px}.thumbnail{display:block;padding:4px;line-height:1;border:1px solid #ddd;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:0 1px 1px rgba(0,0,0,0.075);box-shadow:0 1px 1px rgba(0,0,0,0.075)}a.thumbnail:hover{border-color:#08c;-webkit-box-shadow:0 1px 4px rgba(0,105,214,0.25);-moz-box-shadow:0 1px 4px rgba(0,105,214,0.25);box-shadow:0 1px 4px rgba(0,105,214,0.25)}.thumbnail>img{display:block;max-width:100%;margin-right:auto;margin-left:auto}.thumbnail .caption{padding:9px}.label,.badge{font-size:10.998px;font-weight:bold;line-height:14px;color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);white-space:nowrap;vertical-align:baseline;background-color:#999}.label{padding:1px 4px 2px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.badge{padding:1px 9px 2px;-webkit-border-radius:9px;-moz-border-radius:9px;border-radius:9px}a.label:hover,a.badge:hover{color:#fff;text-decoration:none;cursor:pointer}.label-important,.badge-important{background-color:#b94a48}.label-important[href],.badge-important[href]{background-color:#953b39}.label-warning,.badge-warning{background-color:#f89406}.label-warning[href],.badge-warning[href]{background-color:#c67605}.label-success,.badge-success{background-color:#468847}.label-success[href],.badge-success[href]{background-color:#356635}.label-info,.badge-info{background-color:#3a87ad}.label-info[href],.badge-info[href]{background-color:#2d6987}.label-inverse,.badge-inverse{background-color:#333}.label-inverse[href],.badge-inverse[href]{background-color:#1a1a1a}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-moz-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-ms-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:0 0}to{background-position:40px 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:18px;margin-bottom:18px;overflow:hidden;background-color:#f7f7f7;background-image:-moz-linear-gradient(top,#f5f5f5,#f9f9f9);background-image:-ms-linear-gradient(top,#f5f5f5,#f9f9f9);background-image:-webkit-gradient(linear,0 0,0 100%,from(#f5f5f5),to(#f9f9f9));background-image:-webkit-linear-gradient(top,#f5f5f5,#f9f9f9);background-image:-o-linear-gradient(top,#f5f5f5,#f9f9f9);background-image:linear-gradient(top,#f5f5f5,#f9f9f9);background-repeat:repeat-x;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;filter:progid:dximagetransform.microsoft.gradient(startColorstr='#f5f5f5',endColorstr='#f9f9f9',GradientType=0);-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1)}.progress .bar{width:0;height:18px;font-size:12px;color:#fff;text-align:center;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#0e90d2;background-image:-moz-linear-gradient(top,#149bdf,#0480be);background-image:-webkit-gradient(linear,0 0,0 100%,from(#149bdf),to(#0480be));background-image:-webkit-linear-gradient(top,#149bdf,#0480be);background-image:-o-linear-gradient(top,#149bdf,#0480be);background-image:linear-gradient(top,#149bdf,#0480be);background-image:-ms-linear-gradient(top,#149bdf,#0480be);background-repeat:repeat-x;filter:progid:dximagetransform.microsoft.gradient(startColorstr='#149bdf',endColorstr='#0480be',GradientType=0);-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-moz-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box;-webkit-transition:width .6s ease;-moz-transition:width .6s ease;-ms-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress-striped .bar{background-color:#149bdf;background-image:-o-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-webkit-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-ms-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;-moz-background-size:40px 40px;-o-background-size:40px 40px;background-size:40px 40px}.progress.active .bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-moz-animation:progress-bar-stripes 2s linear infinite;-ms-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-danger .bar{background-color:#dd514c;background-image:-moz-linear-gradient(top,#ee5f5b,#c43c35);background-image:-ms-linear-gradient(top,#ee5f5b,#c43c35);background-image:-webkit-gradient(linear,0 0,0 100%,from(#ee5f5b),to(#c43c35));background-image:-webkit-linear-gradient(top,#ee5f5b,#c43c35);background-image:-o-linear-gradient(top,#ee5f5b,#c43c35);background-image:linear-gradient(top,#ee5f5b,#c43c35);background-repeat:repeat-x;filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ee5f5b',endColorstr='#c43c35',GradientType=0)}.progress-danger.progress-striped .bar{background-color:#ee5f5b;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-ms-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-success .bar{background-color:#5eb95e;background-image:-moz-linear-gradient(top,#62c462,#57a957);background-image:-ms-linear-gradient(top,#62c462,#57a957);background-image:-webkit-gradient(linear,0 0,0 100%,from(#62c462),to(#57a957));background-image:-webkit-linear-gradient(top,#62c462,#57a957);background-image:-o-linear-gradient(top,#62c462,#57a957);background-image:linear-gradient(top,#62c462,#57a957);background-repeat:repeat-x;filter:progid:dximagetransform.microsoft.gradient(startColorstr='#62c462',endColorstr='#57a957',GradientType=0)}.progress-success.progress-striped .bar{background-color:#62c462;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-ms-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-info .bar{background-color:#4bb1cf;background-image:-moz-linear-gradient(top,#5bc0de,#339bb9);background-image:-ms-linear-gradient(top,#5bc0de,#339bb9);background-image:-webkit-gradient(linear,0 0,0 100%,from(#5bc0de),to(#339bb9));background-image:-webkit-linear-gradient(top,#5bc0de,#339bb9);background-image:-o-linear-gradient(top,#5bc0de,#339bb9);background-image:linear-gradient(top,#5bc0de,#339bb9);background-repeat:repeat-x;filter:progid:dximagetransform.microsoft.gradient(startColorstr='#5bc0de',endColorstr='#339bb9',GradientType=0)}.progress-info.progress-striped .bar{background-color:#5bc0de;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-ms-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-warning .bar{background-color:#faa732;background-image:-moz-linear-gradient(top,#fbb450,#f89406);background-image:-ms-linear-gradient(top,#fbb450,#f89406);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fbb450),to(#f89406));background-image:-webkit-linear-gradient(top,#fbb450,#f89406);background-image:-o-linear-gradient(top,#fbb450,#f89406);background-image:linear-gradient(top,#fbb450,#f89406);background-repeat:repeat-x;filter:progid:dximagetransform.microsoft.gradient(startColorstr='#fbb450',endColorstr='#f89406',GradientType=0)}.progress-warning.progress-striped .bar{background-color:#fbb450;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-ms-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.accordion{margin-bottom:18px}.accordion-group{margin-bottom:2px;border:1px solid #e5e5e5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.accordion-heading{border-bottom:0}.accordion-heading .accordion-toggle{display:block;padding:8px 15px}.accordion-toggle{cursor:pointer}.accordion-inner{padding:9px 15px;border-top:1px solid #e5e5e5}.carousel{position:relative;margin-bottom:18px;line-height:1}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel .item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-moz-transition:.6s ease-in-out left;-ms-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel .item>img{display:block;line-height:1}.carousel .active,.carousel .next,.carousel .prev{display:block}.carousel .active{left:0}.carousel .next,.carousel .prev{position:absolute;top:0;width:100%}.carousel .next{left:100%}.carousel .prev{left:-100%}.carousel .next.left,.carousel .prev.right{left:0}.carousel .active.left{left:-100%}.carousel .active.right{left:100%}.carousel-control{position:absolute;top:40%;left:15px;width:40px;height:40px;margin-top:-20px;font-size:60px;font-weight:100;line-height:30px;color:#fff;text-align:center;background:#222;border:3px solid #fff;-webkit-border-radius:23px;-moz-border-radius:23px;border-radius:23px;opacity:.5;filter:alpha(opacity=50)}.carousel-control.right{right:15px;left:auto}.carousel-control:hover{color:#fff;text-decoration:none;opacity:.9;filter:alpha(opacity=90)}.carousel-caption{position:absolute;right:0;bottom:0;left:0;padding:10px 15px 5px;background:#333;background:rgba(0,0,0,0.75)}.carousel-caption h4,.carousel-caption p{color:#fff}.hero-unit{padding:60px;margin-bottom:30px;background-color:#eee;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.hero-unit h1{margin-bottom:0;font-size:60px;line-height:1;letter-spacing:-1px;color:inherit}.hero-unit p{font-size:18px;font-weight:200;line-height:27px;color:inherit}.pull-right{float:right}.pull-left{float:left}.hide{display:none}.show{display:block}.invisible{visibility:hidden} diff --git a/doc/darkstrap.css b/doc/darkstrap.css new file mode 100644 index 000000000..2f0e3ec4f --- /dev/null +++ b/doc/darkstrap.css @@ -0,0 +1,430 @@ +/* line 31, ../sass/darkstrap.scss */ +.well, .breadcrumb, input, +input[type="file"], +select, +textarea, .progress, code, pre { + -moz-box-shadow: rgba(255, 255, 255, 0.1) 0 1px 0, rgba(0, 0, 0, 0.8) 0 1px 7px 0px inset; + -webkit-box-shadow: rgba(255, 255, 255, 0.1) 0 1px 0, rgba(0, 0, 0, 0.8) 0 1px 7px 0px inset; + -o-box-shadow: rgba(255, 255, 255, 0.1) 0 1px 0, rgba(0, 0, 0, 0.8) 0 1px 7px 0px inset; + box-shadow: rgba(255, 255, 255, 0.1) 0 1px 0, rgba(0, 0, 0, 0.8) 0 1px 7px 0px inset; + background: #202020; + background-color: rgba(0, 0, 0, 0.3); +} + +/* line 33, ../sass/darkstrap.scss */ +body { + background: #2f2f2f; + color: #c6c6c6; +} + +/* line 39, ../sass/darkstrap.scss */ +.breadcrumb { + border: 0; +} +/* line 42, ../sass/darkstrap.scss */ +.breadcrumb li { + text-shadow: 0 1px 0 #000; +} + +/* line 48, ../sass/darkstrap.scss */ +.page-header { + -moz-box-shadow: rgba(255, 255, 255, 0.07) 0 1px 0; + -webkit-box-shadow: rgba(255, 255, 255, 0.07) 0 1px 0; + -o-box-shadow: rgba(255, 255, 255, 0.07) 0 1px 0; + box-shadow: rgba(255, 255, 255, 0.07) 0 1px 0; + border-bottom: 1px solid #121212; +} + +/* line 49, ../sass/darkstrap.scss */ +h1, h2, h3, h4, h5, h6 { + color: white; +} + +/* line 50, ../sass/darkstrap.scss */ +h6 { + color: #999; +} + +/* line 57, ../sass/darkstrap.scss */ +.nav-tabs .open .dropdown-toggle, +.nav-pills .open .dropdown-toggle, +.nav > .open.active > a:hover { + background-color: #222222; + border-color: #2f2f2f #2f2f2f transparent #2f2f2f; +} + +/* line 61, ../sass/darkstrap.scss */ +.nav > .dropdown.active > a:hover { + color: #fff; +} + +/* line 65, ../sass/darkstrap.scss */ +.nav-tabs .active .dropdown-toggle .caret, +.nav-pills .active .dropdown-toggle .caret { + border-top-color: #fff; +} + +/* line 68, ../sass/darkstrap.scss */ +.nav-tabs { + border-bottom: 1px solid #666; +} +/* line 71, ../sass/darkstrap.scss */ +.nav-tabs > .active > a, .nav-tabs > .active > a:hover { + background-color: #2f2f2f; + color: #fff; + border-color: #666 #666 transparent #666; +} +/* line 76, ../sass/darkstrap.scss */ +.nav-tabs > li > a:hover { + border-color: #2f2f2f #2f2f2f #666666 #2f2f2f; + background-color: #222222; + color: #00aaff; +} +/* line 83, ../sass/darkstrap.scss */ +.nav-tabs.nav-stacked > li > a, .nav-tabs.nav-stacked > li > a:hover { + border-color: #666; +} + +/* line 89, ../sass/darkstrap.scss */ +.nav-pills > li > a:hover { + background-color: #222222; + color: #00aaff; +} + +/* line 95, ../sass/darkstrap.scss */ +.nav-list > li > a, +.nav-list .nav-header { + text-shadow: 0 1px 0 #000; +} + +/* line 98, ../sass/darkstrap.scss */ +.nav-list > li > a:hover { + background-color: #161616; + color: #00aaff; +} + +/* line 103, ../sass/darkstrap.scss */ +.nav-list .active > a:hover { + background-color: #0088cc; + color: white; +} + +/* line 109, ../sass/darkstrap.scss */ +.tabs-below .nav-tabs { + border-top: 1px solid #666; +} + +/* line 110, ../sass/darkstrap.scss */ +.tabs-left .nav-tabs { + border-right: 1px solid #666; +} + +/* line 111, ../sass/darkstrap.scss */ +.tabs-right .nav-tabs { + border-left: 1px solid #666; +} + +/* line 113, ../sass/darkstrap.scss */ +.tabs-below .nav-tabs > li > a:hover { + border-top: 1px solid #666; +} + +/* line 116, ../sass/darkstrap.scss */ +.tabs-left .nav-tabs > li > a:hover { + border-color: transparent #666 transparent transparent; +} + +/* line 119, ../sass/darkstrap.scss */ +.tabs-right .nav-tabs > li > a:hover { + border-color: transparent transparent transparent #666; +} + +/* line 124, ../sass/darkstrap.scss */ +.tabs-below .nav-tabs .active > a, +.tabs-below .nav-tabs .active > a:hover { + border-color: transparent #666 #666 #666; +} + +/* line 128, ../sass/darkstrap.scss */ +.tabs-left .nav-tabs .active > a, +.tabs-left .nav-tabs .active > a:hover { + border-color: #666 transparent #666 #666; +} + +/* line 132, ../sass/darkstrap.scss */ +.tabs-right .nav-tabs .active > a, +.tabs-right .nav-tabs .active > a:hover { + border-color: #666 #666 #666 transparent; +} + +/* line 2, ../sass/mixins.scss */ +:-moz-placeholder { + color: #666666; +} + +/* line 5, ../sass/mixins.scss */ +::-webkit-input-placeholder { + color: #666666; +} + +/* line 140, ../sass/darkstrap.scss */ +.input-prepend .add-on, +.input-append .add-on { + background: #444; + color: #c6c6c6; + border-color: #111; + text-shadow: 0 1px 0 black; +} + +/* line 147, ../sass/darkstrap.scss */ +label { + color: #c6c6c6; +} + +/* line 154, ../sass/darkstrap.scss */ +input, +input[type="file"], +select, +textarea { + color: white; + border-color: #111111; +} + +/* line 160, ../sass/darkstrap.scss */ +.search-query { + -webkit-box-shadow: rgba(255, 255, 255, 0.1) 0 1px 0, rgba(0, 0, 0, 0) 0 1px 7px 0px inset; +} + +/* line 163, ../sass/darkstrap.scss */ +legend { + color: white; + -moz-box-shadow: rgba(255, 255, 255, 0.07) 0 1px 0; + -webkit-box-shadow: rgba(255, 255, 255, 0.07) 0 1px 0; + -o-box-shadow: rgba(255, 255, 255, 0.07) 0 1px 0; + box-shadow: rgba(255, 255, 255, 0.07) 0 1px 0; + border-bottom: 1px solid #121212; +} + +/* line 167, ../sass/darkstrap.scss */ +.form-actions { + border-top-color: #222; + background-color: #444; +} + +/* line 172, ../sass/darkstrap.scss */ +.help-inline { + color: #999; +} + +/* line 12, ../sass/mixins.scss */ +.control-group.warning > label, +.control-group.warning .help-block, +.control-group.warning .help-inline { + color: #faa732; +} +/* line 13, ../sass/mixins.scss */ +.control-group.warning input, .control-group.warning select, .control-group.warning textarea { + color: #faa732; + border-color: #faa732; +} +/* line 20, ../sass/mixins.scss */ +.control-group.warning input:focus, +.control-group.warning select:focus, +.control-group.warning textarea:focus { + border-color: #faa732; + -moz-box-shadow: 0 0 6px #faa732; + -webkit-box-shadow: 0 0 6px #faa732; + -o-box-shadow: 0 0 6px #faa732; + box-shadow: 0 0 6px #faa732; +} +/* line 12, ../sass/mixins.scss */ +.control-group.success > label, .control-group.success .help-block, .control-group.success .help-inline { + color: #5bb75b; +} +/* line 13, ../sass/mixins.scss */ +.control-group.success input, .control-group.success select, .control-group.success textarea { + color: #5bb75b; + border-color: #5bb75b; +} +/* line 20, ../sass/mixins.scss */ +.control-group.success input:focus, .control-group.success select:focus, .control-group.success textarea:focus { + border-color: #5bb75b; + -moz-box-shadow: 0 0 6px #5bb75b; + -webkit-box-shadow: 0 0 6px #5bb75b; + -o-box-shadow: 0 0 6px #5bb75b; + box-shadow: 0 0 6px #5bb75b; +} +/* line 12, ../sass/mixins.scss */ +.control-group.error > label, .control-group.error .help-block, .control-group.error .help-inline { + color: #fc5b5e; +} +/* line 13, ../sass/mixins.scss */ +.control-group.error input, .control-group.error select, .control-group.error textarea { + color: #fc5b5e; + border-color: #fc5b5e; +} +/* line 20, ../sass/mixins.scss */ +.control-group.error input:focus, .control-group.error select:focus, .control-group.error textarea:focus { + border-color: #fc5b5e; + -moz-box-shadow: 0 0 6px #fc5b5e; + -webkit-box-shadow: 0 0 6px #fc5b5e; + -o-box-shadow: 0 0 6px #fc5b5e; + box-shadow: 0 0 6px #fc5b5e; +} + +/* line 182, ../sass/darkstrap.scss */ +.table thead { + color: white; +} +/* line 185, ../sass/darkstrap.scss */ +.table td { + border-top-color: #666; +} + +/* line 191, ../sass/darkstrap.scss */ +.table-striped tbody tr:nth-child(2n+1) td, .table-striped tbody tr:nth-child(2n+1) th { + background-color: #444; +} + +/* line 197, ../sass/darkstrap.scss */ +.table-bordered { + border: 1px solid #666; +} +/* line 202, ../sass/darkstrap.scss */ +.table-bordered th + th, +.table-bordered td + td, +.table-bordered th + td, +.table-bordered td + th { + border-left: 1px solid #666; +} + +/* line 208, ../sass/darkstrap.scss */ +.pagination a:hover { + color: #00aaff; + background-color: #222222; +} + +/* line 212, ../sass/darkstrap.scss */ +.pagination .active a { + color: #fff; + background-color: #222222; +} + +/* line 216, ../sass/darkstrap.scss */ +.pagination a { + border-color: #666; +} + +/* line 219, ../sass/darkstrap.scss */ +.pager a { + background-color: #2f2f2f; + border-color: #666; +} +/* line 222, ../sass/darkstrap.scss */ +.pager a:hover { + background-color: #222222; + color: #00aaff; +} + +/* line 238, ../sass/darkstrap.scss */ +.alert { + color: #fff; + background-color: #faa732; + text-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); + border-color: #a86404; +} +/* line 234, ../sass/darkstrap.scss */ +.alert h4 { + color: #c17305; +} + +/* line 239, ../sass/darkstrap.scss */ +.alert-success { + color: #fff; + background-color: #5bb75b; + text-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); + border-color: #2d662d; +} +/* line 234, ../sass/darkstrap.scss */ +.alert-success h4 { + color: #347834; +} + +/* line 240, ../sass/darkstrap.scss */ +.alert-error { + color: #fff; + background-color: #fc5b5e; + text-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); + border-color: #d40408; +} +/* line 234, ../sass/darkstrap.scss */ +.alert-error h4 { + color: #ed0409; +} + +/* line 241, ../sass/darkstrap.scss */ +.alert-info { + color: #fff; + background-color: #3a87ad; + text-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); + border-color: #1a3c4e; +} +/* line 234, ../sass/darkstrap.scss */ +.alert-info h4 { + color: #204b61; +} + +/* line 245, ../sass/darkstrap.scss */ +.modal { + background-color: #444; +} + +/* line 248, ../sass/darkstrap.scss */ +.modal-header { + border-bottom: 1px solid #222; +} + +/* line 251, ../sass/darkstrap.scss */ +.modal-body p { + color: #c6c6c6; +} + +/* line 254, ../sass/darkstrap.scss */ +.modal-footer { + background-color: #373737; + border-top: 1px solid #222; + -moz-box-shadow: 0 1px 0 #333333 inset; + -webkit-box-shadow: 0 1px 0 #333333 inset; + -o-box-shadow: 0 1px 0 #333333 inset; + box-shadow: 0 1px 0 #333333 inset; +} + +/* line 266, ../sass/darkstrap.scss */ +blockquote { + border-left-color: #111; +} +/* line 268, ../sass/darkstrap.scss */ +blockquote.pull-right { + border-right-color: #111; +} + +/* line 271, ../sass/darkstrap.scss */ +hr { + -moz-box-shadow: rgba(255, 255, 255, 0.07) 0 1px 0; + -webkit-box-shadow: rgba(255, 255, 255, 0.07) 0 1px 0; + -o-box-shadow: rgba(255, 255, 255, 0.07) 0 1px 0; + box-shadow: rgba(255, 255, 255, 0.07) 0 1px 0; + border-bottom: 1px solid #121212; + border-top: none; +} + +/* line 277, ../sass/darkstrap.scss */ +code { + border: none; +} + +/* line 281, ../sass/darkstrap.scss */ +pre { + border: none; + color: #c6c6c6; +} \ No newline at end of file diff --git a/doc/header.html b/doc/header.html new file mode 100644 index 000000000..8f5e4d6c7 --- /dev/null +++ b/doc/header.html @@ -0,0 +1,129 @@ + + + + + +$projectname: $title +$title + + + + + + + + + +$treeview +$search +$mathjax + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + +
+
$projectname +  $projectnumber +
+
$projectbrief
+
+
$projectbrief
+
$searchbox
+
+ diff --git a/doc/style.css b/doc/style.css new file mode 100644 index 000000000..928f6a6d6 --- /dev/null +++ b/doc/style.css @@ -0,0 +1,1471 @@ +/* The standard CSS for doxygen */ + +body, table, div, p, dl { + font-family: Lucida Grande, Verdana, Geneva, Arial, sans-serif; + font-size: 13px; + line-height: 1.3; +} + +/* @group Heading Levels */ + +h1 { + font-size: 150%; +} + +.title { + font-size: 150%; + font-weight: bold; + margin: 10px 2px; +} + +h2 { + font-size: 120%; +} + +h3 { + font-size: 100%; +} + +dt { + font-weight: bold; +} + +div.multicol { + -moz-column-gap: 1em; + -webkit-column-gap: 1em; + -moz-column-count: 3; + -webkit-column-count: 3; +} + +p.startli, p.startdd, p.starttd { + margin-top: 2px; +} + +p.endli { + margin-bottom: 0px; +} + +p.enddd { + margin-bottom: 4px; +} + +p.endtd { + margin-bottom: 2px; +} + +/* @end */ + +caption { + font-weight: bold; +} + +span.legend { + font-size: 70%; + text-align: center; +} + +h3.version { + font-size: 90%; + text-align: center; +} + +div.qindex, div.navtab{ + background-color: #F1F1F1; + border: 1px solid #BDBDBD; + text-align: center; +} + +div.qindex, div.navpath { + width: 100%; + line-height: 140%; +} + +div.navtab { + margin-right: 15px; +} + +/* @group Link Styling */ + +a { + color: #646464; + font-weight: normal; + text-decoration: none; +} + +.contents a:visited { + color: #747474; +} + +a:hover { + text-decoration: underline; +} + +a.qindex { + font-weight: bold; +} + +a.qindexHL { + font-weight: bold; + background-color: #B8B8B8; + color: #ffffff; + border: 1px double #A8A8A8; +} + +.contents a.qindexHL:visited { + color: #ffffff; +} + +a.el { + font-weight: bold; +} + +a.elRef { +} + +a.code, a.code:visited { + color: #4665A2; +} + +a.codeRef, a.codeRef:visited { + color: #4665A2; +} + +/* @end */ + +dl.el { + margin-left: -1cm; +} + +.fragment { + font-family: monospace, fixed; + font-size: 105%; +} + +pre.fragment { + border: 1px solid #D5D5D5; + background-color: #FCFCFC; + padding: 4px 6px; + margin: 4px 8px 4px 2px; + overflow: auto; + word-wrap: break-word; + font-size: 9pt; + line-height: 125%; +} + +div.ah { + background-color: black; + font-weight: bold; + color: #ffffff; + margin-bottom: 3px; + margin-top: 3px; + padding: 0.2em; + border: solid thin #333; + border-radius: 0.5em; + -webkit-border-radius: .5em; + -moz-border-radius: .5em; + box-shadow: 2px 2px 3px #999; + -webkit-box-shadow: 2px 2px 3px #999; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px; + background-image: -webkit-gradient(linear, left top, left bottom, from(#eee), to(#000),color-stop(0.3, #444)); + background-image: -moz-linear-gradient(center top, #eee 0%, #444 40%, #000); +} + +div.groupHeader { + margin-left: 16px; + margin-top: 12px; + font-weight: bold; +} + +div.groupText { + margin-left: 16px; + font-style: italic; +} + +body { + background-color: white; + color: black; + margin: 0; +} + +div.contents { + margin-top: 10px; + margin-left: 8px; + margin-right: 8px; +} + +td.indexkey { + background-color: #F1F1F1; + font-weight: bold; + border: 1px solid #D5D5D5; + margin: 2px 0px 2px 0; + padding: 2px 10px; + white-space: nowrap; + vertical-align: top; +} + +td.indexvalue { + background-color: #F1F1F1; + border: 1px solid #D5D5D5; + padding: 2px 10px; + margin: 2px 0px; +} + +tr.memlist { + background-color: #F2F2F2; +} + +p.formulaDsp { + text-align: center; +} + +img.formulaDsp { + +} + +img.formulaInl { + vertical-align: middle; +} + +div.center { + text-align: center; + margin-top: 0px; + margin-bottom: 0px; + padding: 0px; +} + +div.center img { + border: 0px; +} + +address.footer { + text-align: right; + padding-right: 12px; +} + +img.footer { + border: 0px; + vertical-align: middle; +} + +/* @group Code Colorization */ + +span.keyword { + color: #008000 +} + +span.keywordtype { + color: #604020 +} + +span.keywordflow { + color: #e08000 +} + +span.comment { + color: #800000 +} + +span.preprocessor { + color: #806020 +} + +span.stringliteral { + color: #002080 +} + +span.charliteral { + color: #008080 +} + +span.vhdldigit { + color: #ff00ff +} + +span.vhdlchar { + color: #000000 +} + +span.vhdlkeyword { + color: #700070 +} + +span.vhdllogic { + color: #ff0000 +} + +/* @end */ + +/* +.search { + color: #003399; + font-weight: bold; +} + +form.search { + margin-bottom: 0px; + margin-top: 0px; +} + +input.search { + font-size: 75%; + color: #000080; + font-weight: normal; + background-color: #e8eef2; +} +*/ + +td.tiny { + font-size: 75%; +} + +.dirtab { + padding: 4px; + border-collapse: collapse; + border: 1px solid #BDBDBD; +} + +th.dirtab { + background: #F1F1F1; + font-weight: bold; +} + +hr { + height: 0px; + border: none; + border-top: 1px solid #7A7A7A; +} + +hr.footer { + height: 1px; +} + +/* @group Member Descriptions */ + +table.memberdecls { + border-spacing: 0px; + padding: 0px; +} + +.mdescLeft, .mdescRight, +.memItemLeft, .memItemRight, +.memTemplItemLeft, .memTemplItemRight, .memTemplParams { + background-color: #FAFAFA; + border: none; + margin: 4px; + padding: 1px 0 0 8px; +} + +.mdescLeft, .mdescRight { + padding: 0px 8px 4px 8px; + color: #555; +} + +.memItemLeft, .memItemRight, .memTemplParams { + border-top: 1px solid #D5D5D5; +} + +.memItemLeft, .memTemplItemLeft { + white-space: nowrap; +} + +.memItemRight { + width: 100%; +} + +.memTemplParams { + color: #747474; + white-space: nowrap; +} + +/* @end */ + +/* @group Member Details */ + +/* Styles for detailed member documentation */ + +.memtemplate { + font-size: 80%; + color: #747474; + font-weight: normal; + margin-left: 9px; +} + +.memnav { + background-color: #F1F1F1; + border: 1px solid #BDBDBD; + text-align: center; + margin: 2px; + margin-right: 15px; + padding: 2px; +} + +.mempage { + width: 100%; +} + +.memitem { + padding: 0; + margin-bottom: 10px; + margin-right: 5px; +} + +.memname { + white-space: nowrap; + font-weight: bold; + margin-left: 6px; +} + +.memproto, dl.reflist dt { + border-top: 1px solid #C0C0C0; + border-left: 1px solid #C0C0C0; + border-right: 1px solid #C0C0C0; + padding: 6px 0px 6px 0px; + color: #3D3D3D; + font-weight: bold; + text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); + /* opera specific markup */ + box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + border-top-right-radius: 8px; + border-top-left-radius: 8px; + /* firefox specific markup */ + -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; + -moz-border-radius-topright: 8px; + -moz-border-radius-topleft: 8px; + /* webkit specific markup */ + -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + -webkit-border-top-right-radius: 8px; + -webkit-border-top-left-radius: 8px; + background-image:url('nav_f.png'); + background-repeat:repeat-x; + background-color: #EAEAEA; + +} + +.memdoc, dl.reflist dd { + border-bottom: 1px solid #C0C0C0; + border-left: 1px solid #C0C0C0; + border-right: 1px solid #C0C0C0; + padding: 2px 5px; + background-color: #FCFCFC; + border-top-width: 0; + /* opera specific markup */ + border-bottom-left-radius: 8px; + border-bottom-right-radius: 8px; + box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + /* firefox specific markup */ + -moz-border-radius-bottomleft: 8px; + -moz-border-radius-bottomright: 8px; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; + background-image: -moz-linear-gradient(center top, #FFFFFF 0%, #FFFFFF 60%, #F9F9F9 95%, #F2F2F2); + /* webkit specific markup */ + -webkit-border-bottom-left-radius: 8px; + -webkit-border-bottom-right-radius: 8px; + -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + background-image: -webkit-gradient(linear,center top,center bottom,from(#FFFFFF), color-stop(0.6,#FFFFFF), color-stop(0.60,#FFFFFF), color-stop(0.95,#F9F9F9), to(#F2F2F2)); +} + +dl.reflist dt { + padding: 5px; +} + +dl.reflist dd { + margin: 0px 0px 10px 0px; + padding: 5px; +} + +.paramkey { + text-align: right; +} + +.paramtype { + white-space: nowrap; +} + +.paramname { + color: #602020; + white-space: nowrap; +} +.paramname em { + font-style: normal; +} + +.params, .retval, .exception, .tparams { + border-spacing: 6px 2px; +} + +.params .paramname, .retval .paramname { + font-weight: bold; + vertical-align: top; +} + +.params .paramtype { + font-style: italic; + vertical-align: top; +} + +.params .paramdir { + font-family: "courier new",courier,monospace; + vertical-align: top; +} + + + + +/* @end */ + +/* @group Directory (tree) */ + +/* for the tree view */ + +.ftvtree { + font-family: sans-serif; + margin: 0px; +} + +/* these are for tree view when used as main index */ + +.directory { + font-size: 9pt; + font-weight: bold; + margin: 5px; +} + +.directory h3 { + margin: 0px; + margin-top: 1em; + font-size: 11pt; +} + +/* +The following two styles can be used to replace the root node title +with an image of your choice. Simply uncomment the next two styles, +specify the name of your image and be sure to set 'height' to the +proper pixel height of your image. +*/ + +/* +.directory h3.swap { + height: 61px; + background-repeat: no-repeat; + background-image: url("yourimage.gif"); +} +.directory h3.swap span { + display: none; +} +*/ + +.directory > h3 { + margin-top: 0; +} + +.directory p { + margin: 0px; + white-space: nowrap; +} + +.directory div { + display: none; + margin: 0px; +} + +.directory img { + vertical-align: -30%; +} + +/* these are for tree view when not used as main index */ + +.directory-alt { + font-size: 100%; + font-weight: bold; +} + +.directory-alt h3 { + margin: 0px; + margin-top: 1em; + font-size: 11pt; +} + +.directory-alt > h3 { + margin-top: 0; +} + +.directory-alt p { + margin: 0px; + white-space: nowrap; +} + +.directory-alt div { + display: none; + margin: 0px; +} + +.directory-alt img { + vertical-align: -30%; +} + +/* @end */ + +div.dynheader { + margin-top: 8px; +} + +address { + font-style: normal; + color: #464646; +} + +table.doxtable { + border-collapse:collapse; +} + +table.doxtable td, table.doxtable th { + border: 1px solid #4A4A4A; + padding: 3px 7px 2px; +} + +table.doxtable th { + background-color: #5B5B5B; + color: #FFFFFF; + font-size: 110%; + padding-bottom: 4px; + padding-top: 5px; + text-align:left; +} + +table.fieldtable { + width: 100%; + margin-bottom: 10px; + border: 1px solid #C0C0C0; + border-spacing: 0px; + -moz-border-radius: 4px; + -webkit-border-radius: 4px; + border-radius: 4px; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px; + -webkit-box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15); + box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15); +} + +.fieldtable td, .fieldtable th { + padding: 3px 7px 2px; +} + +.fieldtable td.fieldtype, .fieldtable td.fieldname { + white-space: nowrap; + border-right: 1px solid #C0C0C0; + border-bottom: 1px solid #C0C0C0; + vertical-align: top; +} + +.fieldtable td.fielddoc { + border-bottom: 1px solid #C0C0C0; + width: 100%; +} + +.fieldtable tr:last-child td { + border-bottom: none; +} + +.fieldtable th { + background-image:url('nav_f.png'); + background-repeat:repeat-x; + background-color: #EAEAEA; + font-size: 90%; + color: #3D3D3D; + padding-bottom: 4px; + padding-top: 5px; + text-align:left; + -moz-border-radius-topleft: 4px; + -moz-border-radius-topright: 4px; + -webkit-border-top-left-radius: 4px; + -webkit-border-top-right-radius: 4px; + border-top-left-radius: 4px; + border-top-right-radius: 4px; + border-bottom: 1px solid #C0C0C0; +} + + +.tabsearch { + top: 0px; + left: 10px; + height: 36px; + background-image: url('tab_b.png'); + z-index: 101; + overflow: hidden; + font-size: 13px; +} + +.navpath ul +{ + font-size: 11px; + background-image:url('tab_b.png'); + background-repeat:repeat-x; + height:30px; + line-height:30px; + color:#ABABAB; + border:solid 1px #D3D3D3; + overflow:hidden; + margin:0px; + padding:0px; +} + +.navpath li +{ + list-style-type:none; + float:left; + padding-left:10px; + padding-right:15px; + background-image:url('bc_s.png'); + background-repeat:no-repeat; + background-position:right; + color:#595959; +} + +.navpath li.navelem a +{ + height:32px; + display:block; + text-decoration: none; + outline: none; +} + +.navpath li.navelem a:hover +{ + color:#929292; +} + +.navpath li.footer +{ + list-style-type:none; + float:right; + padding-left:10px; + padding-right:15px; + background-image:none; + background-repeat:no-repeat; + background-position:right; + color:#595959; + font-size: 8pt; +} + + +div.summary +{ + float: right; + font-size: 8pt; + padding-right: 5px; + width: 50%; + text-align: right; +} + +div.summary a +{ + white-space: nowrap; +} + +div.ingroups +{ + margin-left: 5px; + font-size: 8pt; + padding-left: 5px; + width: 50%; + text-align: left; +} + +div.ingroups a +{ + white-space: nowrap; +} + +div.header +{ + background-image:url('nav_h.png'); + background-repeat:repeat-x; + background-color: #FAFAFA; + margin: 0px; + border-bottom: 1px solid #D5D5D5; +} + +div.headertitle +{ + padding: 5px 5px 5px 7px; +} + +dl +{ + padding: 0 0 0 10px; +} + +dl.note, dl.warning, dl.attention, dl.pre, dl.post, dl.invariant, dl.deprecated, dl.todo, dl.test, dl.bug +{ + border-left:4px solid; + padding: 0 0 0 6px; +} + +dl.note +{ + border-color: #D0C000; +} + +dl.warning, dl.attention +{ + border-color: #FF0000; +} + +dl.pre, dl.post, dl.invariant +{ + border-color: #00D000; +} + +dl.deprecated +{ + border-color: #505050; +} + +dl.todo +{ + border-color: #00C0E0; +} + +dl.test +{ + border-color: #3030E0; +} + +dl.bug +{ + border-color: #C08050; +} + +#projectlogo +{ + text-align: center; + vertical-align: bottom; + border-collapse: separate; +} + +#projectlogo img +{ + border: 0px none; +} + +#projectname +{ + font: 300% Tahoma, Arial,sans-serif; + margin: 0px; + padding: 2px 0px; +} + +#projectbrief +{ + font: 120% Tahoma, Arial,sans-serif; + margin: 0px; + padding: 0px; +} + +#projectnumber +{ + font: 50% Tahoma, Arial,sans-serif; + margin: 0px; + padding: 0px; +} + +#titlearea +{ + padding: 0px; + margin: 0px; + width: 100%; + border-bottom: 1px solid #848484; +} + +.image +{ + text-align: center; +} + +.dotgraph +{ + text-align: center; +} + +.mscgraph +{ + text-align: center; +} + +.caption +{ + font-weight: bold; +} + +div.zoom +{ + border: 1px solid #AFAFAF; +} + +dl.citelist { + margin-bottom:50px; +} + +dl.citelist dt { + color:#545454; + float:left; + font-weight:bold; + margin-right:10px; + padding:5px; +} + +dl.citelist dd { + margin:2px 0; + padding:5px 0; +} + +@media print +{ + #top { display: none; } + #side-nav { display: none; } + #nav-path { display: none; } + body { overflow:visible; } + h1, h2, h3, h4, h5, h6 { page-break-after: avoid; } + .summary { display: none; } + .memitem { page-break-inside: avoid; } + #doc-content + { + margin-left:0 !important; + height:auto !important; + width:auto !important; + overflow:inherit; + display:inline; + } + pre.fragment + { + overflow: visible; + text-wrap: unrestricted; + white-space: -moz-pre-wrap; /* Moz */ + white-space: -pre-wrap; /* Opera 4-6 */ + white-space: -o-pre-wrap; /* Opera 7 */ + white-space: pre-wrap; /* CSS3 */ + word-wrap: break-word; /* IE 5.5+ */ + } +} + + +/* +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// + +custom css + +*/ + + +.mdescLeft, .mdescRight, .memItemLeft, .memItemRight, .memTemplItemLeft, .memTemplItemRight, .memTemplParams { + background: none !important; +} + +.mdescLeft, .mdescRight { + border-top: none !important; + color: #858585; +} + + +.table tbody tr:hover td, .table tbody tr:hover th { + background-color: rgba(255, 255, 255, 0.1); +} + +/* +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// + +guacamole css + +*/ + + +/* Partials */ +@import url(http://fonts.googleapis.com/css?family=Oxygen:100,300,400,700,900,100italic,300italic,400italic,700italic,900italic); +/* Theme Vars */ +/* Compass Vars */ +/* Override some defaults */ +/* line 12, ../_sass/_base.scss */ +html, body { + background-color: #2a2a2a; + background: url(body.png) repeat; +} + +/* line 17, ../_sass/_base.scss */ +body { + color: #bbb; + text-shadow: 1px 1px 1px #000; + height: 100%; + font-family: 'Oxygen', sans-serif; + font-size: 14px; +} + +/* line 25, ../_sass/_base.scss */ +h1, h2, h3, h4, h5, h6 { + margin: 0; + font-weight: normal; + color: #999; + text-rendering: optimizelegibility; +} + +/* line 32, ../_sass/_base.scss */ +a { + color: #a9c161; + -webkit-transition: all 0.3s; + -moz-transition: all 0.3s; + -o-transition: all 0.3s; + transition: all 0.3s; +} +/* line 34, ../_sass/_base.scss */ +a:hover { + color: #e5eccf; + text-decoration: none; +} + +/* line 41, ../_sass/_base.scss */ +h1 small, h2 small, h3 small, h4 small, h5 small, h6 small { + font-weight: normal; + color: #999999; +} + +/* line 46, ../_sass/_base.scss */ +h1, h2 { + margin: 0 0 15px; +} + +/* line 50, ../_sass/_base.scss */ +h1 { + font-size: 40px; +} + +/* line 54, ../_sass/_base.scss */ +h2 { + font-size: 30px; +} + +/* line 58, ../_sass/_base.scss */ +pre, code { + color: #ccc; +} + +/* line 62, ../_sass/_base.scss */ +pre > code { + /* Reset box-shadow for pygments */ + background: none; + box-shadow: none; + -moz-box-shadow: none; + -webkit-box-shadow: none; + -o-box-shadow: none; +} + +/* line 71, ../_sass/_base.scss */ +hr { + border: none; + background: rgba(0, 0, 0, 0.7); + height: 1px; +} + +/* Layout */ +/* line 78, ../_sass/_base.scss */ +.navbar { + margin-bottom: 0; +} +/* line 80, ../_sass/_base.scss */ +.navbar div.navbar-inner { + -webkit-border-radius: 0; + -moz-border-radius: 0; + -ms-border-radius: 0; + -o-border-radius: 0; + border-radius: 0; +} +/* line 82, ../_sass/_base.scss */ +.navbar div.navbar-inner a.brand { + padding: 10px 20px; +} +/* line 87, ../_sass/_base.scss */ +.navbar div.navbar-inner ul.nav:first-child li a { + padding: 12px 10px 8px; +} + +/* line 96, ../_sass/_base.scss */ +.container > footer { + margin-top: 20px; + clear: both; +} + +/* Content */ +/* line 103, ../_sass/_base.scss */ +.content { + /* when there's no page-header */ + /* Wide column content */ +} +/* line 104, ../_sass/_base.scss */ +.content img { + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.8); +} +/* line 108, ../_sass/_base.scss */ +.content.no-header { + padding-top: 40px; +} +/* line 115, ../_sass/_base.scss */ +.content div.row div.span8 > img { + display: block; + margin: 10px auto; +} +/* line 121, ../_sass/_base.scss */ +.content div.row div.span4 h4 { + margin-top: 10px; +} +/* line 123, ../_sass/_base.scss */ +.content div.row div.span4 h4:first { + margin-top: 0; +} +/* line 127, ../_sass/_base.scss */ +.content p { + padding-bottom: 15px; + line-height: 25px; + margin: 0; +} + +/* Page header tweaks */ +/* line 135, ../_sass/_base.scss */ +.page-header { + -webkit-box-shadow: rgba(255, 255, 255, 0.1) 0 1px 0, rgba(0, 0, 0, 0.8) 0 1px 7px 0px inset; + -moz-box-shadow: rgba(255, 255, 255, 0.1) 0 1px 0, rgba(0, 0, 0, 0.8) 0 1px 7px 0px inset; + box-shadow: rgba(255, 255, 255, 0.1) 0 1px 0, rgba(0, 0, 0, 0.8) 0 1px 7px 0px inset; + background: #202020; + background-color: rgba(0, 0, 0, 0.3); + border: none; + padding: 20px 20px 10px; + margin: 0px -20px 20px; + z-index: 0; + -moz-border-radius-bottomleft: 5px; + -webkit-border-bottom-left-radius: 5px; + border-bottom-left-radius: 5px; + -moz-border-radius-bottomright: 5px; + -webkit-border-bottom-right-radius: 5px; + border-bottom-right-radius: 5px; +} +/* line 148, ../_sass/_base.scss */ +.page-header h1 { + color: #eee; + margin-bottom: 0; +} + +/* line 154, ../_sass/_base.scss */ +.topbar .btn { + border: 0; +} + +/* Pagination */ +/* line 161, ../_sass/_base.scss */ +div.pagination li a { + -webkit-box-shadow: 0px 1px 1px black; + -moz-box-shadow: 0px 1px 1px black; + box-shadow: 0px 1px 1px black; +} + +/* Buttons */ +/* line 169, ../_sass/_base.scss */ +a.btn, a.btn.disabled { + color: rgba(255, 255, 255, 0.7); + text-shadow: 1px 1px 2px #000; + background: rgba(0, 0, 0, 0.2); + border: none; + -moz-box-shadow: rgba(255, 255, 255, 0.1) 0 1px 0, rgba(0, 0, 0, 0.8) 0 1px 7px 0px inset; + -webkit-box-shadow: rgba(0, 0, 0, 0.8) 0 1px 0, rgba(255, 255, 255, 0.5) 0 1px 1px 0px inset; + -o-box-shadow: rgba(255, 255, 255, 0.1) 0 1px 0, rgba(0, 0, 0, 0.8) 0 1px 7px 0px inset; +} +/* line 180, ../_sass/_base.scss */ +a.btn:hover, a.btn.disabled:hover { + background: rgba(255, 255, 255, 0.05); +} +/* line 183, ../_sass/_base.scss */ +a.btn.disabled, a.btn.disabled.disabled { + color: rgba(255, 255, 255, 0.3); +} + +/* Tags */ +/* line 189, ../_sass/_base.scss */ +.tag_box { + list-style: none; + margin: 0; + padding: 5px 0; + overflow: hidden; +} +/* line 195, ../_sass/_base.scss */ +.tag_box.inline li { + float: left; +} +/* line 199, ../_sass/_base.scss */ +.tag_box li { + line-height: 28px; +} +/* line 203, ../_sass/_base.scss */ +.tag_box a.active { + background: #57A957; + border: 1px solid #4C964D; + color: #FFF; +} +/* line 208, ../_sass/_base.scss */ +.tag_box a span { + vertical-align: super; + font-size: 0.8em; +} + +/* line 216, ../_sass/_base.scss */ +.tag_box.inline a, +.tag_box a { + padding: 3px 6px; + margin: 2px; + background: rgba(255, 255, 255, 0.2); + color: white; + border-radius: 3px; + text-decoration: none; + -moz-box-shadow: rgba(255, 255, 255, 0.1) 0 1px 0, rgba(0, 0, 0, 0.8) 0 1px 7px 0px inset; + -webkit-box-shadow: rgba(0, 0, 0, 0.8) 0 1px 0, rgba(255, 255, 255, 0.5) 0 1px 1px 0px inset; + -o-box-shadow: rgba(255, 255, 255, 0.1) 0 1px 0, rgba(0, 0, 0, 0.8) 0 1px 7px 0px inset; +} +/* line 228, ../_sass/_base.scss */ +.tag_box.inline a:hover, +.tag_box a:hover { + background: rgba(255, 255, 255, 0.3); +} + +/* Page-specific */ +/* line 235, ../_sass/_base.scss */ +div.content div#page-index { + padding-top: 30px !important; +} + +/* Zocial Overrides */ +/* line 241, ../_sass/_base.scss */ +.navbar a.zocial { + padding-left: 0 !important; + padding-right: 0 !important; +} + +/* line 247, ../_sass/_base.scss */ +.zocial.googleplus:focus, +.zocial.googleplus:hover { + color: #e01d30 !important; +} + +/* line 252, ../_sass/_base.scss */ +.zocial.twitter:focus, +.zocial.twitter:hover { + color: #46c0fb !important; +} + +/* line 257, ../_sass/_base.scss */ +.zocial.linkedin:focus, +.zocial.linkedin:hover { + color: #50a1cb !important; +} + +/* line 262, ../_sass/_base.scss */ +.zocial.rss:focus, +.zocial.rss:hover { + color: #fb9d3a !important; +} + +/* Responsive Overrides */ +@media (max-width: 767px) { + /* line 3, ../_sass/_responsive.scss */ + body { + padding-right: 0px; + padding-left: 0px; + } + + /* line 8, ../_sass/_responsive.scss */ + div.container { + padding: 0px 20px; + } + /* line 10, ../_sass/_responsive.scss */ + div.container div.page-header { + -webkit-border-radius: 0; + -moz-border-radius: 0; + -ms-border-radius: 0; + -o-border-radius: 0; + border-radius: 0; + } +} +/* Posts */ +/* line 3, ../_sass/_post.scss */ +article.post header { + margin-bottom: 10px; +} +/* line 5, ../_sass/_post.scss */ +article.post header h1, article.post header h2 { + margin: 0; +} +/* line 8, ../_sass/_post.scss */ +article.post header .category { + display: inline-block; + color: white; + border-left: 1px solid rgba(255, 255, 255, 0.2); + padding-left: 6px; + margin-left: 3px; +} + +/* line 25, ../_sass/_post.scss */ +div.posts article div.date { + font-size: 10px; + padding: 10px 0; +} +/* line 28, ../_sass/_post.scss */ +div.posts article div.date time { + -webkit-box-shadow: rgba(255, 255, 255, 0.1) 0 1px 0, rgba(0, 0, 0, 0.8) 0 1px 7px 0px inset; + -moz-box-shadow: rgba(255, 255, 255, 0.1) 0 1px 0, rgba(0, 0, 0, 0.8) 0 1px 7px 0px inset; + box-shadow: rgba(255, 255, 255, 0.1) 0 1px 0, rgba(0, 0, 0, 0.8) 0 1px 7px 0px inset; + background: #202020; + background-color: rgba(0, 0, 0, 0.3); + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + -ms-border-radius: 5px; + -o-border-radius: 5px; + border-radius: 5px; + padding: 5px 10px; +} + +/* line 4, ../_sass/_custom.scss */ +html, body { + height: 100%; +} + +/* line 8, ../_sass/_custom.scss */ +html > body { + min-height: 100%; + height: auto; + position: relative; +} + +/* line 14, ../_sass/_custom.scss */ +.content { + margin-bottom: 180px; +} + +/* line 18, ../_sass/_custom.scss */ +.text-right { + text-align: right; +} + +/* line 22, ../_sass/_custom.scss */ +.text-left { + text-align: left; +} + +/* line 26, ../_sass/_custom.scss */ +.text-center { + text-align: center; +} + +/* line 30, ../_sass/_custom.scss */ +.page-header { + -webkit-background-size: cover; + -moz-background-size: cover; + -o-background-size: cover; + background-size: cover; + position: relative; +} +/* line 35, ../_sass/_custom.scss */ +.page-header h1 { + font-size: 3.2em; + line-height: 1.2em; + bottom: 15px; + text-shadow: 1px 1px 15px #000; + padding-bottom: 10px; + font-weight: 300; +} +/* line 46, ../_sass/_custom.scss */ +.page-header.teaser h1 { + margin-top: 30px; + margin-bottom: 50px; +} +@media (max-width: 767px) { + /* line 53, ../_sass/_custom.scss */ + .page-header h1 { + font-size: 2.2em; + } +} +/* line 58, ../_sass/_custom.scss */ +.page-header small { + color: #fff; +} + +/* line 63, ../_sass/_custom.scss */ +.teaser-button { + margin-top: 20px; + margin-bottom: 20px; + font-weight: 900; + font-size: 1.2em; + line-height: 1em; +} +/* line 71, ../_sass/_custom.scss */ +.teaser-button i { + color: #fff; +} + +/* line 76, ../_sass/_custom.scss */ +.footer-wrapper { + position: absolute; + left: 0; + bottom: 0; + min-width: 100%; + line-height: 25px; +} +/* line 84, ../_sass/_custom.scss */ +.footer-wrapper .page-footer { + padding: 20px 20px 20px; + margin: 20px -20px 0px; + -moz-border-radius-topleft: 5px; + -webkit-border-top-left-radius: 5px; + border-top-left-radius: 5px; + -moz-border-radius-topright: 5px; + -webkit-border-top-right-radius: 5px; + border-top-right-radius: 5px; + -webkit-box-shadow: rgba(255, 255, 255, 0.1) 0 1px 0, rgba(0, 0, 0, 0.8) 0 1px 7px 0px inset; + -moz-box-shadow: rgba(255, 255, 255, 0.1) 0 1px 0, rgba(0, 0, 0, 0.8) 0 1px 7px 0px inset; + box-shadow: rgba(255, 255, 255, 0.1) 0 1px 0, rgba(0, 0, 0, 0.8) 0 1px 7px 0px inset; + background: #202020; + background-color: rgba(0, 0, 0, 0.3); + color: #888; +} +/* line 99, ../_sass/_custom.scss */ +.footer-wrapper .page-footer a { + color: #bbb; +} +/* line 102, ../_sass/_custom.scss */ +.footer-wrapper .page-footer a:hover { + color: #fff; +} +/* line 107, ../_sass/_custom.scss */ +.footer-wrapper .page-footer .text-right { + margin-top: 12px; +} +/* line 111, ../_sass/_custom.scss */ +.footer-wrapper .page-footer img { + position: relative; + top: -4px; + margin-left: 5px; + width: 100px; + height: 30px; + opacity: .8; + padding: 1px; + -webkit-transition: opacity 0.2s; + -moz-transition: opacity 0.2s; + -o-transition: opacity 0.2s; + transition: opacity 0.2s; +} +/* line 121, ../_sass/_custom.scss */ +.footer-wrapper .page-footer img:hover { + opacity: 1; +} diff --git a/guarc/main.cpp b/guarc/main.cpp index 0d1bef428..1c3bf6e65 100644 --- a/guarc/main.cpp +++ b/guarc/main.cpp @@ -41,6 +41,7 @@ void read_directory(fs::path const& directory, std::string const& root); void read_file(fs::path const& file, std::string const& root); void write_output(fs::path const& hpp_file, fs::path const& cpp_file); void make_variable_name(std::string& file); +bool is_temporary_file(std::string const& file); //////////////////////////////////////////////////////////////////////////////// @@ -113,7 +114,13 @@ void read_directory(fs::path const& directory, std::string const& root) { read_directory(dir_itr->path(), root); } else if (fs::is_regular_file(dir_itr->status())) { - read_file(dir_itr->path(), root); + + if (!is_temporary_file(dir_itr->path().filename().string())) { + read_file(dir_itr->path(), root); + } else { + std::cout << "Skipping temporary file "; + std::cout << dir_itr->path().filename() << std::endl; + } } else { std::cout << "Skipping non-regular file "; @@ -133,10 +140,10 @@ void read_file(fs::path const& file, std::string const& root) { std::string full_path(file.string()); std::string rel_path(full_path.substr(root.length() + 1, std::string::npos)); - // replace windows '\' with '/' for map key + // replace windows '\' with '/' for map key std::replace(rel_path.begin(), rel_path.end(), '\\', '/'); - std::cout << rel_path << std::endl; - + std::cout << "Embedding " << rel_path << " ..." << std::endl; + // open the file: std::ifstream s(file.string(), std::ios::in | std::ios::binary); @@ -189,12 +196,13 @@ void write_output(fs::path const& hpp_file, fs::path const& cpp_file) { cpp << "0x" << hex.str(); - if (i #include #include #include @@ -35,8 +36,10 @@ namespace physics { * * This Database stores collision shapes that can be shared among rigid bodies. * It can be accessed via string identifiers. + * + * \ingroup gua_databases */ -class CollisionShapeDatabase : public Database, +class GUA_DLL CollisionShapeDatabase : public Database, public Singleton { public: diff --git a/include/gua/databases/Database.hpp b/include/gua/databases/Database.hpp index b96106425..8be82b93b 100644 --- a/include/gua/databases/Database.hpp +++ b/include/gua/databases/Database.hpp @@ -40,6 +40,8 @@ namespace gua { * * It can store any type of Data. The data is mapped on strings, * which then can be used to access this data. + * + * \ingroup gua_databases */ template class Database { public: diff --git a/include/gua/scenegraph/GroupNode.hpp b/include/gua/databases/Doxygen.hpp similarity index 66% rename from include/gua/scenegraph/GroupNode.hpp rename to include/gua/databases/Doxygen.hpp index 11d64813f..7cbeb3618 100644 --- a/include/gua/scenegraph/GroupNode.hpp +++ b/include/gua/databases/Doxygen.hpp @@ -19,47 +19,12 @@ * * ******************************************************************************/ -#ifndef GUA_GROUP_NODE_HPP -#define GUA_GROUP_NODE_HPP - -#include +#ifndef GUA_DATABASES_DOXYGEN_HPP +#define GUA_DATABASES_DOXYGEN_HPP /** - * This class is used to represent an empty node in the SceneGraph. - * + * \defgroup gua_databases guacamole asset databases */ -namespace gua { - -class GroupNode : public Node { - public: - - GroupNode() {}; - - /** - * Constructor. - * - * This constructs a GroupNode with the given parameters. - * - * \param name The Node's name - * \param transform The transformation of the object the Node contains. - */ - GroupNode(std::string const& name, - math::mat4 const& transform = math::mat4::identity()); - - /** - * Accepts a visitor and calls concrete visit method - * - * This method implements the visitor pattern for Nodes - * - */ - /* virtual */ void accept(NodeVisitor&); - - private: - - std::shared_ptr copy() const; -}; - -} +#endif // GUA_DATABASES_DOXYGEN_HPP -#endif // GUA_GROUP_NODE_HPP diff --git a/include/gua/databases/GeometryDatabase.hpp b/include/gua/databases/GeometryDatabase.hpp index ea7efeabd..f7bdcf20b 100644 --- a/include/gua/databases/GeometryDatabase.hpp +++ b/include/gua/databases/GeometryDatabase.hpp @@ -34,21 +34,13 @@ namespace gua { * * This Database stores geometry data. It can be accessed via string * identifiers. + * + * \ingroup gua_databases */ -class GeometryDatabase : public Database, - public Singleton { +class GUA_DLL GeometryDatabase : public Database, + public Singleton { public: - /** - * Loads a geometry file to the database. - * - * This method loads a geometry to the data base. - * - * \param id An absolute or relative path to the - * geometry file. - */ - void load(std::string const& id); - friend class Singleton; private: diff --git a/include/gua/databases/MaterialDatabase.hpp b/include/gua/databases/MaterialDatabase.hpp index 727ab09ea..bdf0ac681 100644 --- a/include/gua/databases/MaterialDatabase.hpp +++ b/include/gua/databases/MaterialDatabase.hpp @@ -23,6 +23,7 @@ #define GUA_MATERIAL_DATABASE_HPP // guacamole headers +#include #include #include #include @@ -34,9 +35,11 @@ namespace gua { * * This Database stores material data. It can be accessed via string * identifiers. + * + * \ingroup gua_databases */ -class MaterialDatabase : public Database, - public Singleton { +class GUA_DLL MaterialDatabase : public Database, + public Singleton { public: /** @@ -44,10 +47,12 @@ class MaterialDatabase : public Database, * * This method loads gmd materials to the data base. * - * \param path_to_materials An absolute or relative path to the - * directory containing gmd files. + * \param directory An absolute or relative path to the + * directory containing gmd files. */ - static void load_materials_from(std::string const& path_to_materials); + static void load_materials_from(std::string const& directory); + + static void load_material(std::string const& filename); void reload_all(); diff --git a/include/gua/databases/Resources.hpp b/include/gua/databases/Resources.hpp index fc13c0306..15bdad8b4 100644 --- a/include/gua/databases/Resources.hpp +++ b/include/gua/databases/Resources.hpp @@ -23,8 +23,8 @@ #define GUA_RESOURCES_HPP // external headers - #include - #include +#include +#include namespace gua { diff --git a/include/gua/databases/ShadingModelDatabase.hpp b/include/gua/databases/ShadingModelDatabase.hpp index dfcd04148..91966db36 100644 --- a/include/gua/databases/ShadingModelDatabase.hpp +++ b/include/gua/databases/ShadingModelDatabase.hpp @@ -34,9 +34,11 @@ namespace gua { * * This Database stores shading model data. It can be accessed via string * identifiers. + * + * \ingroup gua_databases */ -class ShadingModelDatabase : public Database, - public Singleton { +class GUA_DLL ShadingModelDatabase : public Database, + public Singleton { public: /** @@ -44,11 +46,12 @@ class ShadingModelDatabase : public Database, * * This method loads gsd shading models to the data base. * - * \param path_to_shading_models An absolute or relative path to the - * directory containing gsd files. + * \param directory An absolute or relative path to the + * directory containing gsd files. */ - static void load_shading_models_from( - std::string const& path_to_shading_models); + static void load_shading_models_from(std::string const& directory); + + static void load_shading_model(std::string const& filename); void reload_all(); diff --git a/include/gua/databases/TextureDatabase.hpp b/include/gua/databases/TextureDatabase.hpp index 8248cbf69..7d886ccea 100644 --- a/include/gua/databases/TextureDatabase.hpp +++ b/include/gua/databases/TextureDatabase.hpp @@ -23,6 +23,7 @@ #define GUA_TEXTURE_DATABASE_HPP // guacamole headers +#include #include #include #include @@ -34,9 +35,11 @@ namespace gua { * * This Database stores texture data. It can be accessed via string * identifiers. + * + * \ingroup gua_databases */ -class TextureDatabase : public Database, - public Singleton { +class GUA_DLL TextureDatabase : public Database, + public Singleton { public: /** diff --git a/include/gua/events/MainLoop.hpp b/include/gua/events/MainLoop.hpp index 04914c42f..1d7df81d4 100644 --- a/include/gua/events/MainLoop.hpp +++ b/include/gua/events/MainLoop.hpp @@ -26,10 +26,12 @@ #include +#include + namespace gua { namespace events { - class MainLoop + class GUA_DLL MainLoop { public: diff --git a/include/gua/events/Scheduler.hpp b/include/gua/events/Scheduler.hpp index a3f6b235a..599cd032b 100644 --- a/include/gua/events/Scheduler.hpp +++ b/include/gua/events/Scheduler.hpp @@ -27,12 +27,13 @@ #include +#include #include namespace gua { namespace events { -class Scheduler { +class GUA_DLL Scheduler { public: Scheduler(); ~Scheduler(); diff --git a/include/gua/events/Ticker.hpp b/include/gua/events/Ticker.hpp index ad9ea5e29..a20a55ea7 100644 --- a/include/gua/events/Ticker.hpp +++ b/include/gua/events/Ticker.hpp @@ -24,6 +24,7 @@ #include +#include #include #include #include @@ -31,12 +32,15 @@ namespace gua { namespace events { - class Ticker { + class GUA_DLL Ticker { public: Ticker(MainLoop& mainloop, double tick_time); ~Ticker(); + void set_tick_time(double tick_time); + double get_tick_time() const; + Signal<> on_tick; private: diff --git a/include/gua/guacamole.hpp b/include/gua/guacamole.hpp index 76d42e06e..c8deb9d00 100644 --- a/include/gua/guacamole.hpp +++ b/include/gua/guacamole.hpp @@ -40,7 +40,8 @@ namespace gua { * using guacamole. */ -void init(int argc, char** argv); + void GUA_DLL init(int argc, char** argv); + } #endif // GUA_GUACAMOLE_HPP diff --git a/include/gua/math/math.hpp b/include/gua/math/math.hpp index b9ca4c913..f7891611c 100644 --- a/include/gua/math/math.hpp +++ b/include/gua/math/math.hpp @@ -24,13 +24,12 @@ #include #include +#include +#include -#if ASSIMP_VERSION == 3 -#include -#else -#include -#endif +struct aiMatrix4x4; +#include #include namespace gua { @@ -54,6 +53,8 @@ typedef scm::math::vec vec2i; typedef scm::math::vec vec4ui; typedef scm::math::vec vec3ui; typedef scm::math::vec vec2ui; + +typedef scm::math::quat quat; ///@} /** @@ -66,7 +67,12 @@ typedef scm::math::vec vec2ui; * * \return A frustum matrix. */ -math::mat4 const compute_frustum(math::vec4 const& eye_position, +math::mat4 const GUA_DLL compute_perspective_frustum(math::vec4 const& eye_position, + math::mat4 const& screen_transform, + float near_plane, + float far_plane); + +math::mat4 const GUA_DLL compute_orthographic_frustum(math::vec4 const& eye_position, math::mat4 const& screen_transform, float near_plane, float far_plane); @@ -78,7 +84,7 @@ math::mat4 const compute_frustum(math::vec4 const& eye_position, * * \return A schism matrix. */ -math::mat4 const mat_ai_to_scm(aiMatrix4x4 const& ai_mat); +math::mat4 const GUA_DLL mat_ai_to_scm(aiMatrix4x4 const& ai_mat); #if WIN32 template @@ -92,11 +98,30 @@ math::mat4 const mat_ai_to_scm(aiMatrix4x4 const& ai_mat); } #endif -inline math::vec3 get_translation(math::mat4 const& m) -{ +inline math::vec3 get_translation(math::mat4 const& m) { return math::vec3(m[12], m[13], m[14]); } +inline math::mat4 get_rotation(math::mat4 const& m) { + math::quat q = ::scm::math::quat::from_matrix(m); + return q.to_matrix(); +} + +std::tuple GUA_DLL barycentric(math::vec3 const& a, + math::vec3 const& b, + math::vec3 const& c, + math::vec3 const& p); + +template +ValueType interpolate(math::vec3 const& position, + std::pair const& a, + std::pair const& b, + std::pair const& c) { + float u, v, w; + std::tie(u,v,w) = barycentric(a.first,b.first,c.first,position); + return u * a.second + v * b.second + w * c.second; +} + } } diff --git a/include/gua/math/random.hpp b/include/gua/math/random.hpp index 9185ccbb6..f37d7d916 100644 --- a/include/gua/math/random.hpp +++ b/include/gua/math/random.hpp @@ -19,6 +19,8 @@ * * ******************************************************************************/ +#include + namespace gua { namespace math { namespace random { @@ -28,14 +30,14 @@ namespace random { * * \param seed The new seed. */ -void set_seed(unsigned int seed); +void GUA_DLL set_seed(unsigned int seed); /** * Gets the current seed. * * \return The current seed. */ -unsigned int get_seed(); +unsigned int GUA_DLL get_seed(); /** * Returns a random floating point value. @@ -45,7 +47,7 @@ unsigned int get_seed(); * * \return A random floating point value. */ -float get(float begin, float end); +float GUA_DLL get(float begin, float end); /** * Returns a random integer value. @@ -55,7 +57,7 @@ float get(float begin, float end); * * \return A random integer value. */ -int get(int begin, int end); +int GUA_DLL get(int begin, int end); } } } diff --git a/include/gua/physics/BoxShape.hpp b/include/gua/physics/BoxShape.hpp index f35952d04..4588c0010 100644 --- a/include/gua/physics/BoxShape.hpp +++ b/include/gua/physics/BoxShape.hpp @@ -23,6 +23,7 @@ #define GUA_BOX_SHAPE_HPP // guacamole headers +#include #include #include @@ -38,7 +39,7 @@ namespace physics { * length specified by half extents, in local shape coordinates. * The box shape can be used for both static and dynamic rigid bodies. */ -class BoxShape : public CollisionShape { +class GUA_DLL BoxShape : public CollisionShape { public: /** diff --git a/include/gua/physics/CollisionShape.hpp b/include/gua/physics/CollisionShape.hpp index 310338c54..6f5581aa7 100644 --- a/include/gua/physics/CollisionShape.hpp +++ b/include/gua/physics/CollisionShape.hpp @@ -22,6 +22,8 @@ #ifndef GUA_COLLISION_SHAPE_HPP #define GUA_COLLISION_SHAPE_HPP +#include + class btCollisionShape; class btCompoundShape; class btTransform; @@ -35,7 +37,7 @@ namespace physics { * This abstract class provides an interface for collision shapes that can be * shared among multiple rigid bodies. */ -class CollisionShape { +class GUA_DLL CollisionShape { friend class RigidBodyNode; public: diff --git a/include/gua/physics/CollisionShapeNode.hpp b/include/gua/physics/CollisionShapeNode.hpp index e10c3461a..ad2292d16 100644 --- a/include/gua/physics/CollisionShapeNode.hpp +++ b/include/gua/physics/CollisionShapeNode.hpp @@ -22,6 +22,7 @@ #ifndef GUA_COLLISION_SHAPE_NODE_HPP #define GUA_COLLISION_SHAPE_NODE_HPP +#include #include #include @@ -33,7 +34,7 @@ namespace gua { namespace physics { -class CollisionShapeNode : public Node { +class GUA_DLL CollisionShapeNode : public Node { public: struct Configuration { diff --git a/include/gua/physics/CollisionShapeNodeVisitor.hpp b/include/gua/physics/CollisionShapeNodeVisitor.hpp index 9e9d62ba9..64c51a3a2 100644 --- a/include/gua/physics/CollisionShapeNodeVisitor.hpp +++ b/include/gua/physics/CollisionShapeNodeVisitor.hpp @@ -23,14 +23,15 @@ #define GUA_COLLISION_SHAPE_NODE_VISITOR_HPP // guacamole headers +#include #include #include #include #include -#include +#include #include -#include +#include #include #include #include @@ -100,11 +101,11 @@ class CollisionShapeNodeVisitor : public NodeVisitor { * \param node Pointer to Node */ - /* virtual */ void visit(GroupNode* node) { generic_visit(node); } - - /* virtual */ void visit(ViewNode* node) { generic_visit(node); } + /* virtual */ void visit(TransformNode* node) { generic_visit(node); } /* virtual */ void visit(GeometryNode* node) { generic_visit(node); } + + /* virtual */ void visit(VolumeNode* node) { generic_visit(node); } /* virtual */ void visit(PointLightNode* node) { generic_visit(node); } diff --git a/include/gua/physics/Constraint.hpp b/include/gua/physics/Constraint.hpp index 6e3ae8031..9056ec7ff 100644 --- a/include/gua/physics/Constraint.hpp +++ b/include/gua/physics/Constraint.hpp @@ -49,7 +49,7 @@ class RigidBodyNode; * This abstract class is the base class for rigid body constraints. * */ -class Constraint { +class GUA_DLL Constraint { friend class Physics; public: diff --git a/include/gua/physics/ConvexHullShape.hpp b/include/gua/physics/ConvexHullShape.hpp index 5b8020c87..026947ab3 100644 --- a/include/gua/physics/ConvexHullShape.hpp +++ b/include/gua/physics/ConvexHullShape.hpp @@ -23,6 +23,7 @@ #define GUA_CONVEX_HULL_SHAPE_HPP // guacamole headers +#include #include #include #include @@ -38,7 +39,7 @@ namespace physics { * This class implements an implicit convex hull of an array of vertices. * The convex hull shape can be used for both static and dynamic rigid bodies. */ -class ConvexHullShape : public CollisionShape { +class GUA_DLL ConvexHullShape : public CollisionShape { public: /** diff --git a/include/gua/physics/CylinderShape.hpp b/include/gua/physics/CylinderShape.hpp index 32e96d741..b06f8132e 100644 --- a/include/gua/physics/CylinderShape.hpp +++ b/include/gua/physics/CylinderShape.hpp @@ -23,6 +23,7 @@ #define GUA_CYLINDER_SHAPE_HPP // guacamole headers +#include #include #include @@ -38,7 +39,7 @@ namespace physics { * aligned with Y axis of given half-extents vector. * The cylinder shape can be used for both static and dynamic rigid bodies. */ -class CylinderShape : public CollisionShape { +class GUA_DLL CylinderShape : public CollisionShape { public: /** diff --git a/include/gua/physics/FixedConstraint.hpp b/include/gua/physics/FixedConstraint.hpp index 8931bf4bf..3cfa8a433 100644 --- a/include/gua/physics/FixedConstraint.hpp +++ b/include/gua/physics/FixedConstraint.hpp @@ -22,6 +22,7 @@ #define FIXED_CONSTRAINT_HPP // guacamole headers +#include #include namespace gua { @@ -34,7 +35,7 @@ namespace physics { * The constraint restricts mutual rotations and translations between rigid * bodies or between a rigid body and static environment. */ -class FixedConstraint : public Constraint { +class GUA_DLL FixedConstraint : public Constraint { public: /** diff --git a/include/gua/physics/HingeConstraint.hpp b/include/gua/physics/HingeConstraint.hpp index 0be2dd49d..621734f28 100644 --- a/include/gua/physics/HingeConstraint.hpp +++ b/include/gua/physics/HingeConstraint.hpp @@ -23,6 +23,7 @@ #define HINGE_CONSTRAINT_HPP // guacamole headers +#include #include namespace gua { @@ -36,7 +37,7 @@ namespace physics { * a given axis. This constraint can be useful to represent doors or wheels * rotating around one axis. */ -class HingeConstraint : public Constraint { +class GUA_DLL HingeConstraint : public Constraint { public: /** diff --git a/include/gua/physics/Physics.hpp b/include/gua/physics/Physics.hpp index a7bae2a56..497308447 100644 --- a/include/gua/physics/Physics.hpp +++ b/include/gua/physics/Physics.hpp @@ -74,7 +74,7 @@ class Constraint; * rigid bodies and constraints as well as provides scene graph traversal * capability and methods to tune simulation parameters. */ -class Physics { +class GUA_DLL Physics { public: /** diff --git a/include/gua/physics/PlaneShape.hpp b/include/gua/physics/PlaneShape.hpp index 9f4806647..f811b68cb 100644 --- a/include/gua/physics/PlaneShape.hpp +++ b/include/gua/physics/PlaneShape.hpp @@ -23,6 +23,7 @@ #define GUA_PLANE_SHAPE_HPP // guacamole headers +#include #include #include @@ -36,7 +37,7 @@ namespace physics { * * The plane shape can only be used for static rigid bodies. */ -class PlaneShape : public CollisionShape { +class GUA_DLL PlaneShape : public CollisionShape { public: /** diff --git a/include/gua/physics/Point2PointConstraint.hpp b/include/gua/physics/Point2PointConstraint.hpp index 7196cf741..8366659f1 100644 --- a/include/gua/physics/Point2PointConstraint.hpp +++ b/include/gua/physics/Point2PointConstraint.hpp @@ -23,6 +23,7 @@ #define POINT_2_POINT_CONSTRAINT_HPP // guacamole headers +#include #include namespace gua { @@ -34,7 +35,7 @@ namespace physics { * * This constraint represents a ball socket joint. */ -class Point2PointConstraint : public Constraint { +class GUA_DLL Point2PointConstraint : public Constraint { public: /** diff --git a/include/gua/physics/RigidBodyNode.hpp b/include/gua/physics/RigidBodyNode.hpp index f7f9ee02a..8688c25a9 100644 --- a/include/gua/physics/RigidBodyNode.hpp +++ b/include/gua/physics/RigidBodyNode.hpp @@ -43,7 +43,7 @@ class CollisionShape; * * */ -class RigidBodyNode : public Node { +class GUA_DLL RigidBodyNode : public Node { friend class Physics; friend class CollisionShapeNodeVisitor; diff --git a/include/gua/physics/SliderConstraint.hpp b/include/gua/physics/SliderConstraint.hpp index ad1566f01..362c1e0e8 100644 --- a/include/gua/physics/SliderConstraint.hpp +++ b/include/gua/physics/SliderConstraint.hpp @@ -23,6 +23,7 @@ #define SLIDER_CONSTRAINT_HPP // guacamole headers +#include #include namespace gua { @@ -35,7 +36,7 @@ namespace physics { * The constraint allows the body to rotate around one axis and translate * along this axis. */ -class SliderConstraint : public Constraint { +class GUA_DLL SliderConstraint : public Constraint { public: /** diff --git a/include/gua/physics/SphereShape.hpp b/include/gua/physics/SphereShape.hpp index d4ddea0fa..5759304e6 100644 --- a/include/gua/physics/SphereShape.hpp +++ b/include/gua/physics/SphereShape.hpp @@ -23,6 +23,7 @@ #define GUA_SPHERE_SHAPE_HPP // guacamole headers +#include #include class btSphereShape; @@ -36,7 +37,7 @@ namespace physics { * This class is a sphere primitive around the origin with the given radius. * The sphere shape can be used for both static and dynamic rigid bodies. */ -class SphereShape : public CollisionShape { +class GUA_DLL SphereShape : public CollisionShape { public: /** diff --git a/include/gua/physics/TriangleMeshShape.hpp b/include/gua/physics/TriangleMeshShape.hpp index af8512488..da5dd0baa 100644 --- a/include/gua/physics/TriangleMeshShape.hpp +++ b/include/gua/physics/TriangleMeshShape.hpp @@ -23,6 +23,7 @@ #define GUA_TRIANGLE_SHAPE_HPP // guacamole headers +#include #include #include #include @@ -48,7 +49,7 @@ namespace physics { * For dynamic rigid bodies this class uses Hierarchical Approximate Convex * Decomposition (HACD). */ -class TriangleMeshShape : public CollisionShape { +class GUA_DLL TriangleMeshShape : public CollisionShape { public: /** diff --git a/include/gua/platform.hpp b/include/gua/platform.hpp index 101100e61..aef1ed873 100644 --- a/include/gua/platform.hpp +++ b/include/gua/platform.hpp @@ -37,34 +37,35 @@ // compiler #if defined(_MSC_VER) -#define GUA_COMPILER GUA_COMPILER_MSVC -#define GUA_COMPILER_VER _MSC_VER -#define gua_force_inline __force_inline -#define gua_align(border) __declspec(align(border)) + #define GUA_COMPILER GUA_COMPILER_MSVC + #define GUA_COMPILER_VER _MSC_VER + #define gua_force_inline __force_inline + #define gua_align(border) __declspec(align(border)) + #elif defined(__GNUC__) -#define GUA_COMPILER GUA_COMPILER_GNUC -#define GUA_COMPILER_VER \ - (((__GNUC__) * 100) + (__GNUC_MINOR__ * 10) + __GNUC_PATCHLEVEL__) -#define gua_force_inline __attribute__((always_inline)) -#define gua_align(border) __attribute__((aligned(border))) + #define GUA_COMPILER GUA_COMPILER_GNUC + #define GUA_COMPILER_VER \ + (((__GNUC__) * 100) + (__GNUC_MINOR__ * 10) + __GNUC_PATCHLEVEL__) + #define gua_force_inline __attribute__((always_inline)) + #define gua_align(border) __attribute__((aligned(border))) #else -#error "unknown compiler" + #error "unknown compiler" #endif // platform #if defined(__WIN32__) || defined(_WIN32) || defined(_WIN64) -#define GUA_PLATFORM GUA_PLATFORM_WINDOWS + #define GUA_PLATFORM GUA_PLATFORM_WINDOWS #elif defined(__APPLE_CC__) -#define GUA_PLATFORM GUA_PLATFORM_APPLE + #define GUA_PLATFORM GUA_PLATFORM_APPLE #else -#define GUA_PLATFORM GUA_PLATFORM_LINUX + #define GUA_PLATFORM GUA_PLATFORM_LINUX #endif // architecture #if defined(__x86_64__) || defined(_M_X64) -#define GUA_ARCHITECTURE_TYPE GUA_ARCHITECTURE_64 + #define GUA_ARCHITECTURE_TYPE GUA_ARCHITECTURE_64 #else -#define GUA_ARCHITECTURE_TYPE GUA_ARCHITECTURE_32 + #define GUA_ARCHITECTURE_TYPE GUA_ARCHITECTURE_32 #endif // compiler messages @@ -81,71 +82,42 @@ // windows related #ifndef GUA_STATIC_BUILD -#if GUA_PLATFORM == GUA_PLATFORM_WINDOWS - -#if GUA_COMPILER == GUA_COMPILER_MSVC - -#define __gua_export(lib) \ - export_(BOOST_PP_EXPAND(BOOST_PP_CAT(GUA_BUILD_LIBRARY_, lib))) -#ifndef export_ - #define export_(lib) \ - BOOST_PP_IF( \ - BOOST_PP_IS_NULLARY(lib), __declspec(dllexport), __declspec(dllimport)) -#endif -#define __gua_private(lib) -#else -#error "unsupported windows platform compiler" -#endif - -#ifndef NDEBUG -#define GUA_DEBUG 1 -#else -#define GUA_DEBUG 0 -#endif + #if GUA_PLATFORM == GUA_PLATFORM_WINDOWS + #if GUA_COMPILER == GUA_COMPILER_MSVC + #pragma warning(disable: 4251) // needs to have dll-interface to be used by clients of class + #pragma warning(disable: 4275) // non dll-interface class used as base for dll-interface class + + #if defined(GUA_LIBRARY) + #define GUA_DLL __declspec( dllexport ) + #else + #define GUA_DLL __declspec( dllimport ) + #endif + #endif + #endif +#else + #define GUA_DLL #endif // Linux, Apple #if GUA_PLATFORM == GUA_PLATFORM_LINUX || GUA_PLATFORM == GUA_PLATFORM_APPLE -#if GUA_COMPILER_VER >= 400 -// gcc 4.x attribute visibility -#define __gua_export(lib) __attribute__((visibility("default"))) -#define __gua_private(lib) __attribute__((visibility("hidden"))) -#else -#define __gua_export(lib) -#define __gua_private(lib) -#endif - -#ifndef NDEBUG -#define GUA_DEBUG 1 -#else -#define GUA_DEBUG 0 -#endif + #define GUA_DLL #endif -#else // GUA_STATIC_BUILD -#define __gua_export(lib) -#define __gua_private(lib) -#endif //GUA_STATIC_BUILD - #if GUA_PLATFORM == GUA_PLATFORM_WINDOWS - -#ifndef NDEBUG -#define GUA_DEBUG 1 -#else -#define GUA_DEBUG 0 -#endif - + #ifndef NDEBUG + #define GUA_DEBUG 1 + #else + #define GUA_DEBUG 0 + #endif #endif // Linux, Apple #if GUA_PLATFORM == GUA_PLATFORM_LINUX || GUA_PLATFORM == GUA_PLATFORM_APPLE - -#ifndef NDEBUG -#define GUA_DEBUG 1 -#else -#define GUA_DEBUG 0 -#endif - + #ifndef NDEBUG + #define GUA_DEBUG 1 + #else + #define GUA_DEBUG 0 + #endif #endif //#endif // namespace GUA_PLATFORM_HPP diff --git a/include/gua/renderer.hpp b/include/gua/renderer.hpp index 5f72f1e44..9aa8c13e1 100644 --- a/include/gua/renderer.hpp +++ b/include/gua/renderer.hpp @@ -24,6 +24,7 @@ // renderer headers #include +#include #include #include #include diff --git a/include/gua/renderer/BufferDescriptions.hpp b/include/gua/renderer/BufferDescriptions.hpp index af79364f8..07c0b54a5 100644 --- a/include/gua/renderer/BufferDescriptions.hpp +++ b/include/gua/renderer/BufferDescriptions.hpp @@ -22,6 +22,8 @@ #ifndef GUA_BUFFER_DESCRIPTIONS_HPP #define GUA_BUFFER_DESCRIPTIONS_HPP +#include + // external headers #include @@ -32,7 +34,7 @@ namespace gua { * * This struct is used to create new color buffers in render passes. */ -struct ColorBufferDescription { +struct GUA_DLL ColorBufferDescription { ColorBufferDescription(std::string const& name, unsigned location, scm::gl::data_format format = diff --git a/include/gua/renderer/BuiltInTextures.hpp b/include/gua/renderer/BuiltInTextures.hpp index d11df1bd7..8924c5b32 100644 --- a/include/gua/renderer/BuiltInTextures.hpp +++ b/include/gua/renderer/BuiltInTextures.hpp @@ -23,11 +23,12 @@ #define GUA_NOISE_TEXTURE_HPP // guacamole headers -#include +#include +#include namespace gua { -class NoiseTexture : public Texture { +class GUA_DLL NoiseTexture : public Texture2D { public: NoiseTexture(); @@ -36,7 +37,7 @@ class NoiseTexture : public Texture { static unsigned char pixel_data[64 * 64 * 3 + 1]; }; -class DefaultTexture : public Texture { +class GUA_DLL DefaultTexture : public Texture2D { public: DefaultTexture(); @@ -50,6 +51,15 @@ class DefaultTexture : public Texture { #endif }; +class GUA_DLL LoadingTexture : public Texture2D { + public: + + LoadingTexture(); + + private: + static unsigned char pixel_data[128 * 39 * 3 + 1]; +}; + } #endif // GUA_NOISE_TEXTURE_HPP diff --git a/include/gua/renderer/Camera.hpp b/include/gua/renderer/Camera.hpp index 309b14e17..bfea56921 100644 --- a/include/gua/renderer/Camera.hpp +++ b/include/gua/renderer/Camera.hpp @@ -22,6 +22,8 @@ #ifndef GUA_CAMERA_HPP #define GUA_CAMERA_HPP +#include + // external headers #include @@ -33,15 +35,29 @@ namespace gua { * It is defined by a screen, a view point a a render mask. */ -struct Camera { - Camera(std::string const& v = "unknown_view", std::string const& s = "unknown_screen", - std::string const& g = "scene_graph", std::string const& m = "") - : view(v), screen(s), scene_graph(g), render_mask(m) {} +struct GUA_DLL Camera { + + enum ProjectionMode { + PERSPECTIVE, + ORTHOGRAPHIC + }; + + Camera(std::string const& eye_l = "unknown_left_eye", + std::string const& eye_r = "unknown_right_eye", + std::string const& screen_l = "unknown_left_screen", + std::string const& screen_r = "unknown_right_screen", + std::string const& g = "scene_graph", std::string const& m = "", + ProjectionMode p = PERSPECTIVE) + : eye_l(eye_l), eye_r(eye_r), screen_l(screen_l), screen_r(screen_r), + scene_graph(g), render_mask(m), mode(p) {} - std::string view; - std::string screen; + std::string eye_l; + std::string eye_r; + std::string screen_l; + std::string screen_r; std::string scene_graph; std::string render_mask; + ProjectionMode mode; }; } diff --git a/include/gua/renderer/CompositePass.hpp b/include/gua/renderer/CompositePass.hpp new file mode 100644 index 000000000..9446ac1b2 --- /dev/null +++ b/include/gua/renderer/CompositePass.hpp @@ -0,0 +1,86 @@ +/****************************************************************************** + * guacamole - delicious VR * + * * + * Copyright: (c) 2011-2013 Bauhaus-Universität Weimar * + * Contact: felix.lauer@uni-weimar.de / simon.schneegans@uni-weimar.de * + * * + * This program is free software: you can redistribute it and/or modify it * + * under the terms of the GNU General Public License as published by the Free * + * Software Foundation, either version 3 of the License, or (at your option) * + * any later version. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * + * for more details. * + * * + * You should have received a copy of the GNU General Public License along * + * with this program. If not, see . * + * * + ******************************************************************************/ + +#ifndef GUA_COMPOSITE_PASS_HPP +#define GUA_COMPOSITE_PASS_HPP + +// guacamole headers +#include +#include +#include + +namespace gua { + +class GBuffer; + +/** + * + */ +class CompositePass : public Pass { + public: + + /** + * + */ + CompositePass(Pipeline* pipeline); + + /** + * + */ + virtual ~CompositePass(); + + virtual void create(RenderContext const& ctx, + std::vector > const& layers); + + /* virtual */ LayerMapping const* get_gbuffer_mapping() const; + + void print_shaders(std::string const& directory, + std::string const& name) const; + + bool pre_compile_shaders(RenderContext const& ctx); + + /* virtual */ void render_scene(Camera const& camera, RenderContext const& ctx); + +protected : + + /* virtual */ void rendering( SerializedScene const& scene, + RenderContext const& ctx, + CameraMode eye, + Camera const& camera, + FrameBufferObject* target); + + void init_ressources (RenderContext const& ctx); + + private: + + GBuffer* volume_raygeneration_buffer_; + + scm::gl::depth_stencil_state_ptr depth_stencil_state_; + scm::gl::quad_geometry_ptr fullscreen_quad_; + + ShaderProgram* composite_shader_; + ShaderProgram* ray_generation_shader_; +}; + +} + +#endif // GUA_COMPOSITE_PASS_HPP diff --git a/include/gua/renderer/DisplayData.hpp b/include/gua/renderer/DisplayData.hpp index 17b14f913..5c763d66e 100644 --- a/include/gua/renderer/DisplayData.hpp +++ b/include/gua/renderer/DisplayData.hpp @@ -22,6 +22,7 @@ #ifndef GUA_DISPLAY_DATA_HPP #define GUA_DISPLAY_DATA_HPP +#include #include namespace gua { @@ -30,7 +31,7 @@ namespace gua { * Temporary class that holds data for the PostFXPass. */ -class DisplayData { +class GUA_DLL DisplayData { public: void set_physics_fps(float fps); diff --git a/include/gua/renderer/FrameBufferObject.hpp b/include/gua/renderer/FrameBufferObject.hpp index 29e66c516..3587c02c4 100644 --- a/include/gua/renderer/FrameBufferObject.hpp +++ b/include/gua/renderer/FrameBufferObject.hpp @@ -24,15 +24,12 @@ // guacamole headers #include -#include +#include #include // external headers -#if GUA_COMPILER == GUA_COMPILER_MSVC&& SCM_COMPILER_VER <= 1700 -#include -#else #include -#endif + #include @@ -46,7 +43,7 @@ struct RenderContext; * This class allows to bind textures to a FBO. This FBO * can be used as drawing target for an rendering context. */ -class FrameBufferObject { +class GUA_DLL FrameBufferObject { public: /** @@ -72,7 +69,7 @@ class FrameBufferObject { */ void attach_color_buffer(RenderContext const& context, unsigned in_color_attachment, - std::shared_ptr const& buffer, + std::shared_ptr const& buffer, int mip_level = 0, int z_slice = 0); @@ -87,7 +84,7 @@ class FrameBufferObject { * \param z_slice The buffer's z_slice. */ void attach_depth_stencil_buffer(RenderContext const& context, - std::shared_ptr const& buffer, + std::shared_ptr const& buffer, int mip_level = 0, int z_slice = 0); @@ -147,7 +144,7 @@ class FrameBufferObject { ///@} private: - bool set_size(std::shared_ptr const& buffer); + bool set_size(std::shared_ptr const& buffer); unsigned width_, height_; mutable std::vector fbos_; diff --git a/include/gua/renderer/Frustum.hpp b/include/gua/renderer/Frustum.hpp index 3dffe4664..aaa425ead 100644 --- a/include/gua/renderer/Frustum.hpp +++ b/include/gua/renderer/Frustum.hpp @@ -35,25 +35,49 @@ class Frustum { public: - Frustum(math::mat4 const& camera_transform, - math::mat4 const& screen_transform, - float clip_near, - float clip_far); + Frustum(); - inline math::vec3 const& get_camera_position() const { - return camera_position_; + static Frustum perspective(math::mat4 const& camera_transform, + math::mat4 const& screen_transform, + float clip_near, + float clip_far); + + static Frustum orthographic(math::mat4 const& camera_transform, + math::mat4 const& screen_transform, + float clip_near, + float clip_far); + + std::vector get_corners() const; + + inline math::vec3 get_camera_position() const { + return math::vec3(camera_transform_.column(3)[0], + camera_transform_.column(3)[1], + camera_transform_.column(3)[2]); } + + inline math::mat4 const& get_camera_transform() const { return camera_transform_; } + inline math::mat4 const& get_screen_transform() const { return screen_transform_; } + inline math::mat4 const& get_projection() const { return projection_; } inline math::mat4 const& get_view() const { return view_; } + inline float get_clip_near() const { return clip_near_; } + inline float get_clip_far() const { return clip_far_; } bool is_inside(math::BoundingBox const& bbox) const; private: - math::vec3 camera_position_; + static void init_frustum_members(math::mat4 const& camera_transform, + math::mat4 const& screen_transform, + Frustum& frustum); + + math::mat4 camera_transform_; + math::mat4 screen_transform_; math::mat4 projection_; math::mat4 view_; std::vector planes_; + float clip_near_; + float clip_far_; }; diff --git a/include/gua/renderer/GBuffer.hpp b/include/gua/renderer/GBuffer.hpp index a3784ebc2..12ac806d4 100644 --- a/include/gua/renderer/GBuffer.hpp +++ b/include/gua/renderer/GBuffer.hpp @@ -58,10 +58,10 @@ class GBuffer : public FrameBufferObject { /** * */ - std::vector > const& get_color_buffers( + std::vector > const& get_color_buffers( BufferComponentType type) const; - inline std::shared_ptr const& get_depth_buffer() const { + inline std::shared_ptr const& get_depth_buffer() const { return depth_buffer_; } @@ -70,9 +70,9 @@ class GBuffer : public FrameBufferObject { layer_types_; unsigned width_, height_, mipmap_layers_; - std::map > > + std::map > > color_buffers_; - std::shared_ptr depth_buffer_; + std::shared_ptr depth_buffer_; }; } diff --git a/include/gua/renderer/GBufferPass.hpp b/include/gua/renderer/GBufferPass.hpp index dc1965d0f..2c2a7c334 100644 --- a/include/gua/renderer/GBufferPass.hpp +++ b/include/gua/renderer/GBufferPass.hpp @@ -52,7 +52,6 @@ class GBufferPass : public GeometryPass { void create( RenderContext const& ctx, - PipelineConfiguration const& config, std::vector > const& layers); diff --git a/include/gua/renderer/Geometry.hpp b/include/gua/renderer/Geometry.hpp index 2fc714d2c..754f01a89 100644 --- a/include/gua/renderer/Geometry.hpp +++ b/include/gua/renderer/Geometry.hpp @@ -23,6 +23,7 @@ #define GUA_GEOMETRY_HPP // guacamole_headers +#include #include #include #include @@ -39,7 +40,7 @@ struct Ray; /** * Base class for different geometries. */ -class Geometry { +class GUA_DLL Geometry { public: /** diff --git a/include/gua/renderer/GeometryLoader.hpp b/include/gua/renderer/GeometryLoader.hpp index d08654993..d2069436f 100644 --- a/include/gua/renderer/GeometryLoader.hpp +++ b/include/gua/renderer/GeometryLoader.hpp @@ -38,7 +38,7 @@ class Node; * This DataBase stores geometry data. It can be accessed via string * identifiers. */ -class GeometryLoader { +class GUA_DLL GeometryLoader { public: enum Flags { @@ -54,14 +54,21 @@ class GeometryLoader { virtual ~GeometryLoader(); + std::shared_ptr load_geometry(std::string const& file_name, unsigned flags = DEFAULTS); + std::shared_ptr create_geometry_from_file(std::string const& node_name, std::string const& file_name, std::string const& fallback_material, unsigned flags = DEFAULTS); + std::shared_ptr create_volume_from_file(std::string const& node_name, + std::string const& file_name, + unsigned flags = DEFAULTS); private: + void apply_fallback_material(std::shared_ptr const& root, std::string const& fallback_material) const; + static std::unordered_map> loaded_files_; std::string parent_material_name_; diff --git a/include/gua/renderer/GeometryPass.hpp b/include/gua/renderer/GeometryPass.hpp index e0c6af151..0072f30c5 100644 --- a/include/gua/renderer/GeometryPass.hpp +++ b/include/gua/renderer/GeometryPass.hpp @@ -58,7 +58,7 @@ class GeometryPass : public Pass { */ virtual ~GeometryPass() {} - void render_scene(Camera const& camera, RenderContext const& ctx); + virtual void render_scene(Camera const& camera, RenderContext const& ctx); protected: virtual void rendering(SerializedScene const& scene, diff --git a/include/gua/renderer/LightingPass.hpp b/include/gua/renderer/LightingPass.hpp index 395fc1dfb..b2e06b701 100644 --- a/include/gua/renderer/LightingPass.hpp +++ b/include/gua/renderer/LightingPass.hpp @@ -24,10 +24,9 @@ // guacamole headers #include +#include #include #include -#include -#include namespace gua { @@ -64,9 +63,8 @@ class LightingPass : public GeometryPass { bool pre_compile_shaders(RenderContext const& ctx); - public: // attributes - - GBuffer* shadow_map_; +public: + ShadowMap shadow_map_; private: void rendering(SerializedScene const& scene, @@ -75,26 +73,14 @@ class LightingPass : public GeometryPass { Camera const& camera, FrameBufferObject* target); - void render_shadow_map(RenderContext const& ctx, - Camera const& scene_camera, - math::mat4 const& transform, - unsigned map_size); - LightingUberShader* shader_; std::shared_ptr light_sphere_; std::shared_ptr light_cone_; - - Serializer* serializer_; - - ShadowMapMeshShader* shadow_map_mesh_shader_; - ShadowMapNURBSShader* shadow_map_nurbs_shader_; - - scm::gl::depth_stencil_state_ptr shadow_map_depth_stencil_state_; - scm::gl::rasterizer_state_ptr shadow_map_rasterizer_state_; - math::mat4 shadow_map_projection_view_matrix_; + scm::gl::quad_geometry_ptr fullscreen_quad_; scm::gl::depth_stencil_state_ptr depth_stencil_state_; - scm::gl::rasterizer_state_ptr rasterizer_state_; + scm::gl::rasterizer_state_ptr rasterizer_state_front_; + scm::gl::rasterizer_state_ptr rasterizer_state_back_; scm::gl::blend_state_ptr blend_state_; }; diff --git a/include/gua/renderer/LoaderBase.hpp b/include/gua/renderer/LoaderBase.hpp index 0ce42b70d..3cf8fbde5 100644 --- a/include/gua/renderer/LoaderBase.hpp +++ b/include/gua/renderer/LoaderBase.hpp @@ -63,7 +63,6 @@ class LoaderBase { * \param flags TODO: what does flags? */ virtual std::shared_ptr load(std::string const& file_name, - std::string const& fallback_material, unsigned flags) = 0; /** diff --git a/include/gua/renderer/Material.hpp b/include/gua/renderer/Material.hpp index 160c497cd..7a238100d 100644 --- a/include/gua/renderer/Material.hpp +++ b/include/gua/renderer/Material.hpp @@ -25,6 +25,7 @@ // guacamole headers #include #include +#include // external headers #include diff --git a/include/gua/renderer/MaterialDescription.hpp b/include/gua/renderer/MaterialDescription.hpp index efde2317f..51471ff4c 100644 --- a/include/gua/renderer/MaterialDescription.hpp +++ b/include/gua/renderer/MaterialDescription.hpp @@ -78,6 +78,7 @@ class MaterialDescription { inline void set_shading_model(std::string const& s) { shading_model_ = s; } inline std::string const& get_shading_model() const { return shading_model_; } + inline std::unordered_map& get_uniforms() { return uniforms_; } @@ -86,6 +87,8 @@ class MaterialDescription { return uniforms_; } + std::string const& get_filename() const {return file_name_;} + void save_to_file(std::string const& file_name) const; private: diff --git a/include/gua/renderer/MaterialLoader.hpp b/include/gua/renderer/MaterialLoader.hpp index 306861093..5b95ea1ed 100644 --- a/include/gua/renderer/MaterialLoader.hpp +++ b/include/gua/renderer/MaterialLoader.hpp @@ -23,6 +23,7 @@ #define GUA_MATERIAL_LOADER_HPP // guacamole headers +#include #include // external headers @@ -52,7 +53,7 @@ class GeometryNode; * This class can load mesh data from files and display them in multiple * contexts. A MaterialLoader object is made of several Mesh objects. */ -class MaterialLoader { +class GUA_DLL MaterialLoader { public: enum ShadingCapabilities { @@ -72,7 +73,7 @@ class MaterialLoader { }; std::string const load_material(aiMaterial const* material, - std::string const& name_prefix) const; + std::string const& file_name) const; private: std::string const load_shading_model(unsigned capabilities) const; diff --git a/include/gua/renderer/MeshLoader.hpp b/include/gua/renderer/MeshLoader.hpp index 906e5f741..d8d0ab49c 100644 --- a/include/gua/renderer/MeshLoader.hpp +++ b/include/gua/renderer/MeshLoader.hpp @@ -75,7 +75,6 @@ class MeshLoader : public LoaderBase { * \param material_name The material name that was set to the parent node */ std::shared_ptr load(std::string const& file_name, - std::string const& fallback_material, unsigned flags); /** @@ -98,8 +97,7 @@ class MeshLoader : public LoaderBase { aiScene const* ai_scene, aiNode* ai_root, std::string const& file_name, - std::string const& fallback_material, - unsigned flags); + unsigned flags, unsigned& mesh_count); unsigned node_counter_; diff --git a/include/gua/renderer/NURBS.hpp b/include/gua/renderer/NURBS.hpp index 8349e939e..7e5610f96 100644 --- a/include/gua/renderer/NURBS.hpp +++ b/include/gua/renderer/NURBS.hpp @@ -23,6 +23,7 @@ #define GUA_NURBS_HPP_INCLUDED // guacamole headers +#include #include #include #include @@ -46,7 +47,7 @@ namespace gua { -class NURBS : public Geometry { +class GUA_DLL NURBS : public Geometry { public: NURBS(std::shared_ptr const& object, @@ -71,16 +72,16 @@ class NURBS : public Geometry { NURBSData* _data; scm::gl::fill_mode _fill_mode; - //Texture Buffer for Parametric Data + //Texture2D Buffer for Parametric Data mutable std::vector _parametric_texture_buffer; - //Texture Buffer for Attributes + //Texture2D Buffer for Attributes mutable std::vector _attribute_texture_buffer; - //Texture Buffer for Domain + //Texture2D Buffer for Domain mutable std::vector _domain_texture_buffer; - //Texture Buffers for Trim Data + //Texture2D Buffers for Trim Data mutable std::vector _trim_partition_texture_buffer; mutable std::vector diff --git a/include/gua/renderer/NURBSLoader.hpp b/include/gua/renderer/NURBSLoader.hpp index fc4a531a2..c64a090aa 100644 --- a/include/gua/renderer/NURBSLoader.hpp +++ b/include/gua/renderer/NURBSLoader.hpp @@ -57,7 +57,6 @@ class NURBSLoader : public LoaderBase { * \param unsigned Special flag */ /* virtual */ std::shared_ptr load(std::string const& file_name, - std::string const& fallback_material, unsigned flags); /* virtual */ bool is_supported(std::string const& file_name) const; diff --git a/include/gua/renderer/Pass.hpp b/include/gua/renderer/Pass.hpp index 0cdc2d0d9..2c92a6989 100644 --- a/include/gua/renderer/Pass.hpp +++ b/include/gua/renderer/Pass.hpp @@ -26,7 +26,7 @@ #include #include #include -#include +#include #include #include @@ -38,7 +38,6 @@ namespace gua { class Pipeline; -struct PipelineConfiguration; struct SerializedScene; struct Camera; class LayerMapping; @@ -76,7 +75,6 @@ class Pass { virtual void create( RenderContext const& ctx, - PipelineConfiguration const& config, std::vector > const& layers); diff --git a/include/gua/renderer/Pipeline.hpp b/include/gua/renderer/Pipeline.hpp index bb64670c5..f93dd6e35 100644 --- a/include/gua/renderer/Pipeline.hpp +++ b/include/gua/renderer/Pipeline.hpp @@ -23,6 +23,7 @@ #define GUA_PIPELINE_HPP // guacamole headers +#include #include #include #include @@ -44,80 +45,6 @@ class FinalUberShader; class PostFXShader; class Serializer; -struct PipelineConfiguration { - - // camera for this pipeline - GUA_ADD_PROPERTY(Camera, camera, Camera()); - - // the final image of this pipeline will be stored in the texture database - // with this name. if enable_stereo is set to true, two images with postfixes - // _left and _right will be stored - GUA_ADD_PROPERTY(std::string, output_texture_name, "gua_pipeline"); - - // stereo configuration - GUA_ADD_PROPERTY(math::vec2ui, left_resolution, math::vec2ui(800, 600)); - GUA_ADD_PROPERTY(math::vec2ui, right_resolution, math::vec2ui(800, 600)); - GUA_ADD_PROPERTY(bool, enable_stereo, false); - - // various display options - GUA_ADD_PROPERTY(bool, enable_preview_display, false); - GUA_ADD_PROPERTY(bool, enable_fps_display, false); - GUA_ADD_PROPERTY(bool, enable_ray_display, false); - GUA_ADD_PROPERTY(bool, enable_bbox_display, false); - GUA_ADD_PROPERTY(bool, enable_wireframe, false); - - // FXAA - GUA_ADD_PROPERTY(bool, enable_fxaa, false); - - // clipping - GUA_ADD_PROPERTY(float, near_clip, 0.1f); - GUA_ADD_PROPERTY(float, far_clip, 1000.0f); - - // culling - GUA_ADD_PROPERTY(bool, enable_frustum_culling, true); - GUA_ADD_PROPERTY(bool, enable_backface_culling, true); - - // screen space ambient occlusion - GUA_ADD_PROPERTY(bool, enable_ssao, false); - GUA_ADD_PROPERTY(float, ssao_radius, 2.0f); - GUA_ADD_PROPERTY(float, ssao_intensity, 1.0f); - GUA_ADD_PROPERTY(float, ssao_falloff, 1.0f); - - // bloom - GUA_ADD_PROPERTY(bool, enable_bloom, false); - GUA_ADD_PROPERTY(float, bloom_radius, 10.0f); - GUA_ADD_PROPERTY(float, bloom_threshold, 0.8f); - GUA_ADD_PROPERTY(float, bloom_intensity, 0.4f); - - // fog - GUA_ADD_PROPERTY(bool, enable_fog, false); - GUA_ADD_PROPERTY(float, fog_start, 100.0f); - GUA_ADD_PROPERTY(float, fog_end, 1000.0f); - GUA_ADD_PROPERTY(std::string, fog_texture, ""); - GUA_ADD_PROPERTY(utils::Color3f, fog_color, utils::Color3f()); - - // background image / color - GUA_ADD_PROPERTY(std::string, background_texture, ""); - GUA_ADD_PROPERTY(utils::Color3f, background_color, utils::Color3f()); - - // ambient color - GUA_ADD_PROPERTY(utils::Color3f, ambient_color, utils::Color3f(0.1f, 0.1f, 0.1f)); - - // vignette - GUA_ADD_PROPERTY(bool, enable_vignette, false); - GUA_ADD_PROPERTY(utils::Color3f, vignette_color, utils::Color3f()); - GUA_ADD_PROPERTY(float, vignette_coverage, 0.3f); - GUA_ADD_PROPERTY(float, vignette_softness, 0.5f); - - // HDR - GUA_ADD_PROPERTY(bool, enable_hdr, false); - GUA_ADD_PROPERTY(float, hdr_key, 1.f); - - // NURBS tesselation - GUA_ADD_PROPERTY(int, max_tesselation, 4); - GUA_ADD_PROPERTY(float, tesselation_max_error, 8.0f); -}; - /** * A rendering pipeline describes how an image is generated. * @@ -125,7 +52,105 @@ struct PipelineConfiguration { * of (or the entire) SceneGraph to buffers. These buffers may be used as input * for other passes. One final buffer of a final pass is shown on the screen. */ -class Pipeline { +class GUA_DLL Pipeline { + public: + + enum BackgroundMode { + COLOR = 0, + SKYMAP_TEXTURE = 1, + QUAD_TEXTURE = 2, + }; + + struct Configuration { + + // camera for this pipeline + GUA_ADD_PROPERTY(Camera, camera, Camera()); + + // if set to false, this pipeline won't render anything + GUA_ADD_PROPERTY(bool, enabled, true); + + // global clipping plane nothing + GUA_ADD_PROPERTY(bool, enable_global_clipping_plane, false); + GUA_ADD_PROPERTY(math::vec4, global_clipping_plane, math::vec4(0, 1, 0, 0)); + + // the final image of this pipeline will be stored in the texture database + // with this name. if enable_stereo is set to true, two images with postfixes + // _left and _right will be stored + GUA_ADD_PROPERTY(std::string, output_texture_name, "gua_pipeline"); + + // stereo configuration + GUA_ADD_PROPERTY(math::vec2ui, left_resolution, math::vec2ui(800, 600)); + GUA_ADD_PROPERTY(math::vec2ui, right_resolution, math::vec2ui(800, 600)); + GUA_ADD_PROPERTY(bool, enable_stereo, false); + + // various display options + GUA_ADD_PROPERTY(bool, enable_preview_display, false); + GUA_ADD_PROPERTY(bool, enable_fps_display, false); + GUA_ADD_PROPERTY(bool, enable_ray_display, false); + GUA_ADD_PROPERTY(bool, enable_bbox_display, false); + GUA_ADD_PROPERTY(bool, enable_wireframe, false); + + // FXAA + GUA_ADD_PROPERTY(bool, enable_fxaa, false); + + // clipping + GUA_ADD_PROPERTY(float, near_clip, 0.1f); + GUA_ADD_PROPERTY(float, far_clip, 1000.0f); + + // culling + GUA_ADD_PROPERTY(bool, enable_frustum_culling, true); + GUA_ADD_PROPERTY(bool, enable_backface_culling, true); + + // screen space ambient occlusion + GUA_ADD_PROPERTY(bool, enable_ssao, false); + GUA_ADD_PROPERTY(float, ssao_radius, 2.0f); + GUA_ADD_PROPERTY(float, ssao_intensity, 1.0f); + GUA_ADD_PROPERTY(float, ssao_falloff, 1.0f); + + // bloom + GUA_ADD_PROPERTY(bool, enable_bloom, false); + GUA_ADD_PROPERTY(float, bloom_radius, 10.0f); + GUA_ADD_PROPERTY(float, bloom_threshold, 0.8f); + GUA_ADD_PROPERTY(float, bloom_intensity, 0.4f); + + // fog + GUA_ADD_PROPERTY(bool, enable_fog, false); + GUA_ADD_PROPERTY(float, fog_start, 100.0f); + GUA_ADD_PROPERTY(float, fog_end, 1000.0f); + GUA_ADD_PROPERTY(std::string, fog_texture, ""); + GUA_ADD_PROPERTY(utils::Color3f, fog_color, utils::Color3f()); + + // background image / color + GUA_ADD_PROPERTY(BackgroundMode, background_mode, BackgroundMode::COLOR); + GUA_ADD_PROPERTY(std::string, background_texture, ""); + GUA_ADD_PROPERTY(utils::Color3f, background_color, utils::Color3f()); + + // ambient color + GUA_ADD_PROPERTY(utils::Color3f, ambient_color, utils::Color3f(0.1f, 0.1f, 0.1f)); + + // vignette + GUA_ADD_PROPERTY(bool, enable_vignette, false); + GUA_ADD_PROPERTY(utils::Color3f, vignette_color, utils::Color3f()); + GUA_ADD_PROPERTY(float, vignette_coverage, 0.3f); + GUA_ADD_PROPERTY(float, vignette_softness, 0.5f); + + // HDR + GUA_ADD_PROPERTY(bool, enable_hdr, false); + GUA_ADD_PROPERTY(float, hdr_key, 1.f); + + // NURBS tesselation + GUA_ADD_PROPERTY(int, max_tesselation, 4); + GUA_ADD_PROPERTY(float, tesselation_max_error, 8.0f); + }; + + enum PipelineStage { + geometry = 0, + lighting = 1, + shading = 2, + compositing = 3, + postfx = 4 + }; + public: /** @@ -142,7 +167,7 @@ class Pipeline { */ virtual ~Pipeline(); - PipelineConfiguration config; + Configuration config; void print_shaders(std::string const& directory) const; @@ -158,13 +183,10 @@ class Pipeline { inline float get_application_fps() const { return application_fps_; } inline float get_rendering_fps() const { return rendering_fps_; } + SerializedScene const& get_current_scene(CameraMode mode) const; + inline SceneGraph const* get_current_graph() const { return current_graph_; } + friend class Renderer; - friend class GBufferPass; - friend class LightingPass; - friend class FinalPass; - friend class PostFXPass; - friend class GeometryPass; - friend class FullscreenPass; private: void process(std::vector> const& scene_graphs, @@ -174,14 +196,7 @@ class Pipeline { void create_passes(); void create_buffers(); - SerializedScene const& get_current_scene(CameraMode mode) const; - inline SceneGraph const* get_current_graph() const { return current_graph_; } - -#if GUA_COMPILER == GUA_COMPILER_MSVC&& GUA_COMPILER_VER <= 1600 - mutable boost::mutex upload_mutex_; -#else mutable std::mutex upload_mutex_; -#endif Window* window_; RenderContext* context_; @@ -199,6 +214,7 @@ class Pipeline { bool passes_need_reload_; bool buffers_need_reload_; + bool display_loading_screen_; unsigned last_shading_model_revision_; }; diff --git a/include/gua/renderer/PostFXPass.hpp b/include/gua/renderer/PostFXPass.hpp index e1c07bff7..a579247ec 100644 --- a/include/gua/renderer/PostFXPass.hpp +++ b/include/gua/renderer/PostFXPass.hpp @@ -30,7 +30,6 @@ namespace gua { class PostGBufferMeshUberShader; class GBuffer; -struct PipelineConfiguration; /** * @@ -52,7 +51,6 @@ class PostFXPass : public Pass { void create( RenderContext const& ctx, - PipelineConfiguration const& config, std::vector > const& layers); @@ -81,7 +79,7 @@ class PostFXPass : public Pass { CameraMode eye, RenderContext const& ctx); void render_ssao(RenderContext const& ctx); - void render_hdr(RenderContext const& ctx, std::shared_ptr const& texture); + void render_hdr(RenderContext const& ctx, std::shared_ptr const& texture); // postfx_shaders 0: SSAO, Fog, God Rays, // postfx_shaders 1: Glow, diff --git a/include/gua/renderer/RenderClient.hpp b/include/gua/renderer/RenderClient.hpp index 817cef1f9..006dbde3b 100644 --- a/include/gua/renderer/RenderClient.hpp +++ b/include/gua/renderer/RenderClient.hpp @@ -22,16 +22,14 @@ #ifndef GUA_RENDERCLIENT_HPP #define GUA_RENDERCLIENT_HPP -// guacamole headers -#include -#include -#include -#include - // external headers #include #include +// guacamole headers +#include +#include + namespace gua { /** diff --git a/include/gua/renderer/Renderer.hpp b/include/gua/renderer/Renderer.hpp index 0fda04029..d8e1ecb17 100644 --- a/include/gua/renderer/Renderer.hpp +++ b/include/gua/renderer/Renderer.hpp @@ -22,15 +22,17 @@ #ifndef GUA_RENDERER_HPP #define GUA_RENDERER_HPP -#include - // external headers #include #include #include + +#include #include #include +#define USE_RAW_POINTER_RENDER_CLIENTS 1 + namespace gua { class SceneGraph; @@ -41,7 +43,7 @@ class Pipeline; * * This class is used to provide a renderer frontend interface to the user. */ -class Renderer { +class GUA_DLL Renderer { public: typedef std::vector > render_vec_t; typedef render_vec_t const const_render_vec_t; @@ -56,6 +58,11 @@ class Renderer { */ Renderer(std::vector const& pipelines); + /** + * + */ + ~Renderer(); + /** * Request a redraw of all RenderClients. * @@ -67,8 +74,11 @@ class Renderer { private: typedef RenderClient > renderclient_t; +#if USE_RAW_POINTER_RENDER_CLIENTS + std::vector render_clients_; +#else std::vector > render_clients_; - +#endif FpsCounter application_fps_; }; diff --git a/include/gua/renderer/SerializedScene.hpp b/include/gua/renderer/SerializedScene.hpp index c94b7251e..40455aa82 100644 --- a/include/gua/renderer/SerializedScene.hpp +++ b/include/gua/renderer/SerializedScene.hpp @@ -23,15 +23,16 @@ #define GUA_SERIALIZED_SCENE_HPP // guacamole headers -#include #include +#include #include #include +#include #include #include #include -#include #include +#include // external headers #include @@ -52,32 +53,44 @@ struct SerializedScene { /** * All geometry nodes. */ - std::vector > meshnodes_; + std::vector meshnodes_; /** * All NURBS nodes. */ - std::vector > nurbsnodes_; + std::vector nurbsnodes_; + + /** + * All Volume nodes. + */ + std::vector volumenodes_; /** * All point light nodes. */ - std::vector > point_lights_; + std::vector point_lights_; /** * All spot light nodes. */ - std::vector > spot_lights_; + std::vector spot_lights_; + + /** + * All sun light nodes. + */ + std::vector sun_lights_; /** - * All cameras. + * The frustum. */ - SerializedNode view_; + Frustum frustum; + bool enable_global_clipping_plane; + math::vec4 global_clipping_plane; /** - * All screens. + * The center of interest. */ - SerializedNode screen_; + math::vec3 center_of_interest; /** * All used materials. @@ -92,12 +105,12 @@ struct SerializedScene { /** * All bounding boxes. */ - std::vector > rays_; + std::vector rays_; /** * All textured quads. */ - std::vector > textured_quads_; + std::vector textured_quads_; }; } diff --git a/include/gua/renderer/Serializer.hpp b/include/gua/renderer/Serializer.hpp index 927ef4ccd..215b2558d 100644 --- a/include/gua/renderer/Serializer.hpp +++ b/include/gua/renderer/Serializer.hpp @@ -61,29 +61,28 @@ class Serializer : public NodeVisitor { */ void check(SerializedScene* output, SceneGraph const* scene_graph, - Camera const& camera, - Frustum const& frustum, + std::string const& render_mask, bool draw_bounding_boxes, bool draw_rays, bool enable_frustum_culling); /** - * Visits a GroupNode + * Visits a TransformNode * - * This function provides the interface to visit a GroupNode + * This function provides the interface to visit a TransformNode * - * \param cam Pointer to GroupNode + * \param cam Pointer to TransformNode */ - /* virtual */ void visit(GroupNode* cam); + /* virtual */ void visit(Node* node); /** - * Visits a ViewNode + * Visits an LODNode * - * This function provides the interface to visit a ViewNode + * This function provides the interface to visit an LODNode * - * \param cam Pointer to ViewNode + * \param cam Pointer to LODNode */ - /* virtual */ void visit(ViewNode* cam); + /* virtual */ void visit(LODNode* lod); /** * Visits a GeometryNode @@ -94,6 +93,15 @@ class Serializer : public NodeVisitor { */ /* virtual */ void visit(GeometryNode* geometry); + /** + * Visits a VolumeNode + * + * This function provides the interface to visit a VolumeNode + * + * \param volume Pointer to VolumeNode + */ + /* virtual */ void visit(VolumeNode* volume); + /** * Visits a PointLightNode * @@ -103,15 +111,6 @@ class Serializer : public NodeVisitor { */ /* virtual */ void visit(PointLightNode* pointlight); - /** - * Visits a ScreenLightNode - * - * This function provides the interface to visit a ScreenLightNode - * - * \param screen Pointer to ScreenLightNode - */ - /* virtual */ void visit(ScreenNode* screen); - /** * Visits a SpotLightNode * @@ -121,6 +120,15 @@ class Serializer : public NodeVisitor { */ /* virtual */ void visit(SpotLightNode* spot); + /** + * Visits a SunLightNode + * + * This function provides the interface to visit a SunLightNode + * + * \param spot Pointer to SunLightNode + */ + /* virtual */ void visit(SunLightNode* sun); + /** * Visits a RayNode * @@ -164,8 +172,8 @@ class Serializer : public NodeVisitor { void visit_children(Node* node); Frustum current_frustum_; - Camera current_camera_; Mask current_render_mask_; + math::vec3 current_center_of_interest_; SerializedScene* data_; bool draw_bounding_boxes_; diff --git a/include/gua/renderer/ShaderProgram.hpp b/include/gua/renderer/ShaderProgram.hpp index e489c41a2..66cf8275a 100644 --- a/include/gua/renderer/ShaderProgram.hpp +++ b/include/gua/renderer/ShaderProgram.hpp @@ -28,11 +28,7 @@ #include // external headers -#if GUA_COMPILER == GUA_COMPILER_MSVC&& SCM_COMPILER_VER <= 1700 -#include -#else #include -#endif #include #include @@ -61,7 +57,7 @@ struct ShaderProgramStage { * It combines data from a FragmentShader and a VertexShader in order to * achieve different visual appearances of the same mesh. */ -class ShaderProgram { +class GUA_DLL ShaderProgram { public: friend class GBufferNURBSUberShader; diff --git a/include/gua/renderer/ShadowMap.hpp b/include/gua/renderer/ShadowMap.hpp new file mode 100644 index 000000000..5419b940a --- /dev/null +++ b/include/gua/renderer/ShadowMap.hpp @@ -0,0 +1,106 @@ +/****************************************************************************** + * guacamole - delicious VR * + * * + * Copyright: (c) 2011-2013 Bauhaus-Universität Weimar * + * Contact: felix.lauer@uni-weimar.de / simon.schneegans@uni-weimar.de * + * * + * This program is free software: you can redistribute it and/or modify it * + * under the terms of the GNU General Public License as published by the Free * + * Software Foundation, either version 3 of the License, or (at your option) * + * any later version. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * + * for more details. * + * * + * You should have received a copy of the GNU General Public License along * + * with this program. If not, see . * + * * + ******************************************************************************/ + +#ifndef GUA_SHADOW_MAP_HPP +#define GUA_SHADOW_MAP_HPP + +// guacamole headers +#include +#include + +namespace gua { + +class Serializer; +class GBuffer; +class Frustum; +class Camera; +class Pipeline; +class GBufferMeshUberShader; +class GBufferNURBSUberShader; + +/** + * + */ +class ShadowMap { + public: + + /** + * + */ + ShadowMap(Pipeline* pipeline); + + virtual ~ShadowMap(); + + void render(RenderContext const& ctx, + math::vec3 const& center_of_interest, + Camera const& scene_camera, + math::mat4 const& transform, + unsigned map_size); + + void render_cascaded(RenderContext const& ctx, + math::vec3 const& center_of_interest, + Frustum const& scene_frustum, + Camera const& scene_camera, + math::mat4 const& transform, + unsigned map_size, + float split_0, + float split_1, + float split_2, + float split_3, + float split_4, + float near_clipping_in_sun_direction); + + void print_shaders(std::string const& directory, + std::string const& name) const; + + bool pre_compile_shaders(RenderContext const& ctx); + + void apply_material_mapping(std::set const& materials) const; + + GBuffer* get_buffer() const {return buffer_;} + std::vector const& get_projection_view_matrices() const {return projection_view_matrices_;} + + private: + + void update_members(RenderContext const& ctx, unsigned map_size); + void render_geometry(RenderContext const & ctx, + math::vec3 const& center_of_interest, + Frustum const& shadow_frustum, + Camera const& scene_camera, + unsigned cascade); + + GBuffer* buffer_; + + Serializer* serializer_; + + Pipeline* pipeline_; + + GBufferMeshUberShader* mesh_shader_; + // GBufferNURBSUberShader* nurbs_shader_; + + scm::gl::depth_stencil_state_ptr depth_stencil_state_; + scm::gl::rasterizer_state_ptr rasterizer_state_; + std::vector projection_view_matrices_; +}; + +} + +#endif // GUA_SHADOW_MAP_HPP diff --git a/include/gua/renderer/StereoBuffer.hpp b/include/gua/renderer/StereoBuffer.hpp index 284f9124c..fe1929323 100644 --- a/include/gua/renderer/StereoBuffer.hpp +++ b/include/gua/renderer/StereoBuffer.hpp @@ -24,10 +24,10 @@ // guacamole headers #include +#include namespace gua { -struct PipelineConfiguration; /** * */ @@ -38,7 +38,7 @@ class StereoBuffer { */ StereoBuffer( RenderContext const& ctx, - PipelineConfiguration const& config, + Pipeline::Configuration const& config, std::vector > const& layers); diff --git a/include/gua/renderer/TextRenderer.hpp b/include/gua/renderer/TextRenderer.hpp index b39e30c06..364a86c41 100644 --- a/include/gua/renderer/TextRenderer.hpp +++ b/include/gua/renderer/TextRenderer.hpp @@ -23,6 +23,7 @@ #define GUA_TEXT_RENDERER_HPP // guacamole headers +#include #include // external headers @@ -39,7 +40,7 @@ class StereoBuffer; * * It can write some predefined strings and information on a given FBO. */ -class TextRenderer { +class GUA_DLL TextRenderer { public: /** diff --git a/include/gua/renderer/Texture.hpp b/include/gua/renderer/Texture.hpp index 395365ee1..67e8800fc 100644 --- a/include/gua/renderer/Texture.hpp +++ b/include/gua/renderer/Texture.hpp @@ -31,13 +31,8 @@ // external headers #include #include - -#if GUA_COMPILER == GUA_COMPILER_MSVC&& GUA_COMPILER_VER <= 1600 -#include -#else #include #include -#endif namespace gua { @@ -47,7 +42,7 @@ namespace gua { * This class allows to load texture data from a file and bind the * texture to an OpenGL context. */ -class Texture { +class GUA_DLL Texture { public: /** @@ -55,15 +50,11 @@ class Texture { * * This constructs a new texture with the given parameters. * - * \param width The width of the resulting texture. - * \param height The height of the resulting texture. * \param color_format The color format of the resulting * texture. * \param state_descripton The sampler state for the loaded texture. */ - Texture(unsigned width, - unsigned height, - scm::gl::data_format color_format, + Texture(scm::gl::data_format color_format, std::vector const& data, unsigned mipmap_layers = 1, scm::gl::sampler_state_desc const& state_descripton = @@ -76,15 +67,11 @@ class Texture { * * This constructs a new texture with the given parameters. * - * \param width The width of the resulting texture. - * \param height The height of the resulting texture. * \param color_format The color format of the resulting * texture. * \param state_descripton The sampler state for the loaded texture. */ - Texture(unsigned width, - unsigned height, - scm::gl::data_format color_format = scm::gl::FORMAT_RGB_32F, + Texture(scm::gl::data_format color_format = scm::gl::FORMAT_RGB_32F, unsigned mipmap_layers = 1, scm::gl::sampler_state_desc const& state_descripton = scm::gl::sampler_state_desc(scm::gl::FILTER_MIN_MAG_MIP_LINEAR, @@ -122,28 +109,20 @@ class Texture { * returned. * \return A pointer to the schism texture. */ - virtual scm::gl::texture_2d_ptr const& get_buffer( + virtual scm::gl::texture_image_ptr const& get_buffer( RenderContext const& context) const; void make_resident(RenderContext const& context) const; void make_non_resident(RenderContext const& context) const; void make_non_resident() const; - ///@{ - /** - * Gets the size. - * - * Returns the size of the Texture. - */ - unsigned width() const; - unsigned height() const; - ///@} + virtual void upload_to(RenderContext const& context) const = 0; protected: - mutable unsigned width_, height_, mipmap_layers_; + mutable unsigned mipmap_layers_; scm::gl::data_format color_format_; scm::gl::sampler_state_desc state_descripton_; - mutable std::vector textures_; + mutable std::vector textures_; mutable std::vector sampler_states_; mutable std::vector render_contexts_; @@ -152,8 +131,7 @@ class Texture { #else mutable std::mutex upload_mutex_; #endif - virtual void upload_to(RenderContext const& context) const; - + std::vector data_; std::string file_name_; @@ -162,4 +140,4 @@ class Texture { }; } -#endif // GUA_TEXTURE_HPP +#endif // GUA_TEXTURE2D_HPP diff --git a/include/gua/renderer/Texture2D.hpp b/include/gua/renderer/Texture2D.hpp new file mode 100644 index 000000000..e70e93977 --- /dev/null +++ b/include/gua/renderer/Texture2D.hpp @@ -0,0 +1,130 @@ +/****************************************************************************** + * guacamole - delicious VR * + * * + * Copyright: (c) 2011-2013 Bauhaus-Universität Weimar * + * Contact: felix.lauer@uni-weimar.de / simon.schneegans@uni-weimar.de * + * * + * This program is free software: you can redistribute it and/or modify it * + * under the terms of the GNU General Public License as published by the Free * + * Software Foundation, either version 3 of the License, or (at your option) * + * any later version. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * + * for more details. * + * * + * You should have received a copy of the GNU General Public License along * + * with this program. If not, see . * + * * + ******************************************************************************/ + +#ifndef GUA_TEXTURE2D_HPP +#define GUA_TEXTURE2D_HPP + +// guacamole headers +#include +#include +#include +#include +#include + +// external headers +#include +#include + +#include +#include + +namespace gua { + +/** + * A class representing a texture. + * + * This class allows to load texture data from a file and bind the + * texture to an OpenGL context. + */ + class GUA_DLL Texture2D : public Texture { + public: + + /** + * Constructor. + * + * This constructs a new texture with the given parameters. + * + * \param width The width of the resulting texture. + * \param height The height of the resulting texture. + * \param color_format The color format of the resulting + * texture. + * \param state_descripton The sampler state for the loaded texture. + */ + Texture2D(unsigned width, + unsigned height, + scm::gl::data_format color_format, + std::vector const& data, + unsigned mipmap_layers = 1, + scm::gl::sampler_state_desc const& state_descripton = + scm::gl::sampler_state_desc(scm::gl::FILTER_MIN_MAG_LINEAR, + scm::gl::WRAP_CLAMP_TO_EDGE, + scm::gl::WRAP_CLAMP_TO_EDGE)); + + /** + * Constructor. + * + * This constructs a new texture with the given parameters. + * + * \param width The width of the resulting texture. + * \param height The height of the resulting texture. + * \param color_format The color format of the resulting + * texture. + * \param state_descripton The sampler state for the loaded texture. + */ + Texture2D(unsigned width, + unsigned height, + scm::gl::data_format color_format = scm::gl::FORMAT_RGB_32F, + unsigned mipmap_layers = 1, + scm::gl::sampler_state_desc const& state_descripton = + scm::gl::sampler_state_desc(scm::gl::FILTER_MIN_MAG_MIP_LINEAR, + scm::gl::WRAP_CLAMP_TO_EDGE, + scm::gl::WRAP_CLAMP_TO_EDGE)); + + /** + * Constructor. + * + * This constructs a new texture from a given file. + * + * \param file The file which contains the texture data. + * \param state_descripton The sampler state for the loaded texture. + */ + Texture2D(std::string const& file, + bool generate_mipmaps = false, + scm::gl::sampler_state_desc const& state_descripton = + scm::gl::sampler_state_desc(scm::gl::FILTER_ANISOTROPIC, + scm::gl::WRAP_REPEAT, + scm::gl::WRAP_REPEAT)); + + virtual ~Texture2D() {} + + ///@{ + /** + * Gets the size. + * + * Returns the size of the Texture2D. + */ + unsigned width() const { return width_; } + unsigned height() const { return height_; } + + virtual void upload_to(RenderContext const& context) const; + + ///@} + + protected: + mutable unsigned width_; + mutable unsigned height_; + + private: + +}; + +} +#endif // GUA_TEXTURE2D_HPP diff --git a/include/gua/renderer/Texture3D.hpp b/include/gua/renderer/Texture3D.hpp new file mode 100644 index 000000000..39723b51f --- /dev/null +++ b/include/gua/renderer/Texture3D.hpp @@ -0,0 +1,138 @@ +/****************************************************************************** + * guacamole - delicious VR * + * * + * Copyright: (c) 2011-2013 Bauhaus-Universität Weimar * + * Contact: felix.lauer@uni-weimar.de / simon.schneegans@uni-weimar.de * + * * + * This program is free software: you can redistribute it and/or modify it * + * under the terms of the GNU General Public License as published by the Free * + * Software Foundation, either version 3 of the License, or (at your option) * + * any later version. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * + * for more details. * + * * + * You should have received a copy of the GNU General Public License along * + * with this program. If not, see . * + * * + ******************************************************************************/ + +#ifndef GUA_TEXTURE3D_HPP +#define GUA_TEXTURE3D_HPP + +// guacamole headers +#include +#include +#include +#include +#include + +// external headers +#include +#include + +#include +#include + + +namespace gua { + +/** + * A class representing a texture. + * + * This class allows to load texture data from a file and bind the + * texture to an OpenGL context. + */ +class GUA_DLL Texture3D : public Texture { + public: + + /** + * Constructor. + * + * This constructs a new texture with the given parameters. + * + * \param width The width of the resulting 3D texture. + * \param height The height of the resulting 3D texture. + * \param depth The depth of the resulting 3D texture. + * \param color_format The color format of the resulting 3D + * texture. + * \param state_descripton The sampler state for the loaded 3D texture. + */ + Texture3D(unsigned width, + unsigned height, + unsigned depth, + scm::gl::data_format color_format, + std::vector const& data, + unsigned mipmap_layers = 1, + scm::gl::sampler_state_desc const& state_descripton = + scm::gl::sampler_state_desc(scm::gl::FILTER_MIN_MAG_LINEAR, + scm::gl::WRAP_CLAMP_TO_EDGE, + scm::gl::WRAP_CLAMP_TO_EDGE)); + + /** + * Constructor. + * + * This constructs a new texture with the given parameters. + * + * \param width The width of the resulting texture. + * \param height The height of the resulting texture. + * \param depth The depth of the resulting 3D texture. + * \param color_format The color format of the resulting + * texture. + * \param state_descripton The sampler state for the loaded texture. + */ + Texture3D(unsigned width, + unsigned height, + unsigned depth, + scm::gl::data_format color_format = scm::gl::FORMAT_RGB_32F, + unsigned mipmap_layers = 1, + scm::gl::sampler_state_desc const& state_descripton = + scm::gl::sampler_state_desc(scm::gl::FILTER_MIN_MAG_MIP_LINEAR, + scm::gl::WRAP_CLAMP_TO_EDGE, + scm::gl::WRAP_CLAMP_TO_EDGE)); + + /** + * Constructor. + * + * This constructs a new texture from a given file. + * + * \param file The file which contains the texture data. + * \param state_descripton The sampler state for the loaded texture. + */ + Texture3D(std::string const& file, + bool generate_mipmaps = false, + scm::gl::sampler_state_desc const& state_descripton = + scm::gl::sampler_state_desc(scm::gl::FILTER_ANISOTROPIC, + scm::gl::WRAP_REPEAT, + scm::gl::WRAP_REPEAT)); + + virtual ~Texture3D() {} + + ///@{ + /** + * Gets the size. + * + * Returns the size of the Texture3D. + */ + inline unsigned width() const { return width_; } + inline unsigned height() const { return height_; } + inline unsigned depth() const { return depth_; } + + virtual void upload_to(RenderContext const& context) const; + ///@} + + protected: + mutable unsigned width_; + mutable unsigned height_; + mutable unsigned depth_; + + + + private: + +}; + +} +#endif // GUA_TEXTURE3D_HPP diff --git a/include/gua/renderer/Uniform.hpp b/include/gua/renderer/Uniform.hpp index 5bf1a4b26..341f7f5a6 100644 --- a/include/gua/renderer/Uniform.hpp +++ b/include/gua/renderer/Uniform.hpp @@ -24,6 +24,8 @@ // guacamole headers #include +#include +#include #include #include #include @@ -152,6 +154,93 @@ class UniformValue : public UniformValueBase { }; +template <> +class UniformValue > : public UniformValueBase { + public: + UniformValue(std::shared_ptr const& value) + : UniformValueBase(), value_(value) {} + + void apply(RenderContext const& context, + scm::gl::program_ptr program, + std::string const& name, + unsigned position = 0) const { + + program->uniform(name, position, value_->get_handle(context)); + } + + std::shared_ptr const& value() const { return value_; } + + void value(std::shared_ptr const& value) { value_ = value; } + + private: + std::shared_ptr value_; +}; + +template <> +class UniformValue : public UniformValueBase { + public: + UniformValue(Texture2D* value) + : UniformValueBase(), value_(value) {} + + void apply(RenderContext const& context, + scm::gl::program_ptr program, + std::string const& name, + unsigned position = 0) const { + + program->uniform(name, position, value_->get_handle(context)); + } + + Texture2D* value() const { return value_; } + + void value(Texture2D* value) { value_ = value; } + + private: + Texture2D* value_; +}; + +template <> +class UniformValue > : public UniformValueBase { + public: + UniformValue(std::shared_ptr const& value) + : UniformValueBase(), value_(value) {} + + void apply(RenderContext const& context, + scm::gl::program_ptr program, + std::string const& name, + unsigned position = 0) const { + + program->uniform(name, position, value_->get_handle(context)); + } + + std::shared_ptr const& value() const { return value_; } + + void value(std::shared_ptr const& value) { value_ = value; } + + private: + std::shared_ptr value_; +}; + +template <> +class UniformValue : public UniformValueBase { + public: + UniformValue(Texture3D* value) + : UniformValueBase(), value_(value) {} + + void apply(RenderContext const& context, + scm::gl::program_ptr program, + std::string const& name, + unsigned position = 0) const { + + program->uniform(name, position, value_->get_handle(context)); + } + + Texture3D* value() const { return value_; } + + void value(Texture3D* value) { value_ = value; } + + private: + Texture3D* value_; +}; template <> class UniformValue : public UniformValueBase { public: @@ -163,7 +252,9 @@ template <> class UniformValue : public UniformValueBase { unsigned position = 0) const { auto texture(TextureDatabase::instance()->lookup(value_)); - program->uniform(name, position, texture->get_handle(context)); + if (texture) { + program->uniform(name, position, texture->get_handle(context)); + } } std::string const& value() const { return value_; } diff --git a/include/gua/renderer/Volume.hpp b/include/gua/renderer/Volume.hpp new file mode 100644 index 000000000..74bec9e43 --- /dev/null +++ b/include/gua/renderer/Volume.hpp @@ -0,0 +1,177 @@ +/****************************************************************************** +* guacamole - delicious VR * +* * +* Copyright: (c) 2011-2013 Bauhaus-Universität Weimar * +* Contact: felix.lauer@uni-weimar.de / simon.schneegans@uni-weimar.de * +* * +* This program is free software: you can redistribute it and/or modify it * +* under the terms of the GNU General Public License as published by the Free * +* Software Foundation, either version 3 of the License, or (at your option) * +* any later version. * +* * +* This program is distributed in the hope that it will be useful, but * +* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * +* for more details. * +* * +* You should have received a copy of the GNU General Public License along * +* with this program. If not, see . * +* * +******************************************************************************/ + +#ifndef GUA_VOLUME_HPP +#define GUA_VOLUME_HPP + +// guacamole headers +#include +#include +#include +#include +#include + +// external headers +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include + +//struct aiMesh; + + +namespace gua { + + struct RenderContext; + + /** + * Stores geometry data. + * + * A volume can be loaded from an Assimp volume and the draw onto multiple + * contexts. + * Do not use this class directly, it is just used by the Geometry class to + * store the individual meshes of a file. + */ + class Volume : public Geometry { + public: + + /** + * Default constructor. + * + * Creates a new and empty Volume. + */ + Volume(); + + /** + * Constructor from an Assimp volume. + * + * Initializes the volume from a given file path + * + * \param volume The Assimp volume to load the data from. + */ + Volume(std::string const& file_name); + + /** + * Draws the Volume. + * + * Draws the Volume to the given context. There is no compositing happening + * + * \param context The RenderContext to draw onto. + */ + void draw(RenderContext const& context) const; + + /** + * Draws the Volume. + * + * Draws the Volume proxy to the given context. + * + * \param context The RenderContext to draw onto. + */ + void draw_proxy(RenderContext const& context) const; + + /** + * Sets the necessary uniform values for compositing shader + * + * Draws the Volume proxy to the given context. + * + * \param shaderProgram The RenderContext to draw onto. + */ + void set_uniforms(RenderContext const& ctx, ShaderProgram* cs) const; + + void ray_test(Ray const& ray, PickResult::Options options, + Node* owner, std::set& hits); + + + float step_size() const; + void step_size(const float size); + + void set_transfer_function(const scm::data::piecewise_function_1d& in_alpha, const scm::data::piecewise_function_1d& in_color); + + private: + void upload_to(RenderContext const& context) const; + + std::shared_ptr create_color_map(RenderContext const& context, + unsigned in_size, + const scm::data::piecewise_function_1d& in_alpha, + const scm::data::piecewise_function_1d& in_color) const; + + bool update_color_map(RenderContext const& context, + std::shared_ptr, + const scm::data::piecewise_function_1d& in_alpha, + const scm::data::piecewise_function_1d& in_color) const; + + mutable bool _update_transfer_function; + + ////Volume files + //mutable std::vector + // _volume_file_pathes; + // Volume File path + std::string _volume_file_path; + + //Volume boxes for each volume + mutable std::vector + _volume_boxes_ptr; + + //Texture3D for volume data for each volume + mutable std::vector> + _volume_texture_ptr; + + mutable std::vector> + _transfer_texture_ptr; + + mutable std::vector _sstate; + +#if GUA_COMPILER == GUA_COMPILER_MSVC && SCM_COMPILER_VER <= 1700 + mutable boost::mutex upload_mutex_; +#else + mutable std::mutex upload_mutex_; +#endif + + scm::data::piecewise_function_1d _alpha_transfer; + scm::data::piecewise_function_1d _color_transfer; + + ///Volume Info + math::vec3ui _volume_dimensions; + math::vec3 _volume_dimensions_normalized; + float _step_size; + + public: + + }; + +} + +#endif // GUA_VOLUME_HPP diff --git a/include/gua/renderer/VolumeLoader.hpp b/include/gua/renderer/VolumeLoader.hpp new file mode 100644 index 000000000..ca4048216 --- /dev/null +++ b/include/gua/renderer/VolumeLoader.hpp @@ -0,0 +1,103 @@ +/****************************************************************************** +* guacamole - delicious VR * +* * +* Copyright: (c) 2011-2013 Bauhaus-Universität Weimar * +* Contact: felix.lauer@uni-weimar.de / simon.schneegans@uni-weimar.de * +* * +* This program is free software: you can redistribute it and/or modify it * +* under the terms of the GNU General Public License as published by the Free * +* Software Foundation, either version 3 of the License, or (at your option) * +* any later version. * +* * +* This program is distributed in the hope that it will be useful, but * +* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * +* for more details. * +* * +* You should have received a copy of the GNU General Public License along * +* with this program. If not, see . * +* * +******************************************************************************/ + +#ifndef GUA_VOLUME_LOADER_HPP +#define GUA_VOLUME_LOADER_HPP + +// guacamole headers +#include +#include +#include + +// external headers +#include +#include +#include + +namespace gua { + + class Node; + class InnerNode; + class VolumeNode; + + /** + * Loads and draws meshes. + * + * This class can load mesh data from files and display them in multiple + * contexts. A VolumeLoader object is made of several Mesh objects. + */ + class GUA_DLL VolumeLoader : public LoaderBase { + public: + + enum Flags { + DEFAULTS = 0, + MAKE_PICKABLE = 1 << 0, + NORMALIZE_POSITION = 1 << 1, + NORMALIZE_SCALE = 1 << 2 + }; + + /** + * Default constructor. + * + * Constructs a new and empty VolumeLoader. + */ + VolumeLoader(); + + /** + * Constructor from a file. + * + * Creates a new VolumeLoader from a given file. + * + * \param file_name The file to load the meh's data from. + */ + + + std::shared_ptr create_volume_from_file(std::string const& node_name, + std::string const& file_name, + unsigned flags); + + std::shared_ptr load(std::string const& file_name, + unsigned flags); + + /** + * Constructor from memory buffer. + * + * Creates a new VolumeLoader from a existing memory buffer. + * + * \param buffer_name The buffer to load the meh's data from. + * \param buffer_size The buffer's size. + */ + //std::vector const load_from_buffer(char const* buffer_name, + // unsigned buffer_size); + + /* virtual */ bool is_supported(std::string const& file_name) const; + + private: + + static std::unordered_map> loaded_files_; + + boost::unordered_set _supported_file_extensions; + + }; + +} + +#endif // GUA_VOLUME_LOADER_HPP diff --git a/include/gua/renderer/WarpMatrix.hpp b/include/gua/renderer/WarpMatrix.hpp index a34339d73..7dcc3a03a 100644 --- a/include/gua/renderer/WarpMatrix.hpp +++ b/include/gua/renderer/WarpMatrix.hpp @@ -23,7 +23,8 @@ #define GUA_WARP_MATRIX_HPP // guacamole headers -#include +#include +#include namespace gua { @@ -34,7 +35,7 @@ namespace gua { * when the projecting beamers for the colors red, green and blue don't * overlap exactly. */ -class WarpMatrix : public Texture { +class GUA_DLL WarpMatrix : public Texture2D { public: /** diff --git a/include/gua/renderer/Window.hpp b/include/gua/renderer/Window.hpp index f55bb11e7..03820379f 100644 --- a/include/gua/renderer/Window.hpp +++ b/include/gua/renderer/Window.hpp @@ -23,6 +23,7 @@ #define GUA_WINDOW_HPP // guacamole headers +#include #include #include #include @@ -38,7 +39,7 @@ namespace gua { class Geometry; -class Texture; +class Texture2D; class StereoBuffer; /** @@ -46,14 +47,16 @@ class StereoBuffer; * * It's a window which can display OpenGL stuff. */ -class Window { +class GUA_DLL Window { public: enum TextureDisplayMode { FULL, RED, GREEN, - CYAN + CYAN, + CHECKER_EVEN, + CHECKER_ODD }; /** @@ -104,6 +107,8 @@ class Window { void open(); bool get_is_open() const; + virtual void create_shader(); + void close(); /** @@ -131,10 +136,10 @@ class Window { /** * */ - void display(std::shared_ptr const& center_texture); + virtual void display(std::shared_ptr const& center_texture); - void display(std::shared_ptr const& left_texture, - std::shared_ptr const& right_texture); + virtual void display(std::shared_ptr const& left_texture, + std::shared_ptr const& right_texture); /** * Get the RenderContext of this window. @@ -146,8 +151,16 @@ class Window { */ RenderContext* get_context(); +protected: + ShaderProgram fullscreen_shader_; + scm::gl::quad_geometry_ptr fullscreen_quad_; + + scm::gl::depth_stencil_state_ptr depth_stencil_state_; + scm::gl::blend_state_ptr blend_state_; + RenderContext ctx_; + private: - void display(std::shared_ptr const& texture, + void display(std::shared_ptr const& texture, math::vec2ui const& size, math::vec2ui const& position, TextureDisplayMode mode = FULL, @@ -157,15 +170,6 @@ class Window { static unsigned last_context_id_; - - RenderContext ctx_; - - ShaderProgram fullscreen_shader_; - scm::gl::quad_geometry_ptr fullscreen_quad_; - - scm::gl::depth_stencil_state_ptr depth_stencil_state_; - scm::gl::blend_state_ptr blend_state_; - std::shared_ptr warpRR_, warpGR_, warpBR_, warpRL_, warpGL_, warpBL_; }; diff --git a/include/gua/renderer/enums.hpp b/include/gua/renderer/enums.hpp index f37f2c464..b1064143a 100644 --- a/include/gua/renderer/enums.hpp +++ b/include/gua/renderer/enums.hpp @@ -51,7 +51,8 @@ enum class StereoMode { MONO = 0, SIDE_BY_SIDE, ANAGLYPH_RED_GREEN, - ANAGLYPH_RED_CYAN + ANAGLYPH_RED_CYAN, + CHECKERBOARD }; /** @@ -66,8 +67,10 @@ enum class UniformType { VEC4, MAT3, MAT4, - SAMPLER, - CUBEMAP, + SAMPLER1D, + SAMPLER2D, + SAMPLER3D, + SAMPLERCUBE, NONE }; diff --git a/include/gua/scenegraph.hpp b/include/gua/scenegraph.hpp index 6f9c173f0..937359718 100644 --- a/include/gua/scenegraph.hpp +++ b/include/gua/scenegraph.hpp @@ -27,11 +27,10 @@ // node headers #include -#include +#include #include #include #include #include -#include #endif // GUA_INCLUDE_SCENEGRAPH_HPP diff --git a/include/gua/scenegraph/Doxygen.hpp b/include/gua/scenegraph/Doxygen.hpp new file mode 100644 index 000000000..698e64656 --- /dev/null +++ b/include/gua/scenegraph/Doxygen.hpp @@ -0,0 +1,30 @@ +/****************************************************************************** + * guacamole - delicious VR * + * * + * Copyright: (c) 2011-2013 Bauhaus-Universität Weimar * + * Contact: felix.lauer@uni-weimar.de / simon.schneegans@uni-weimar.de * + * * + * This program is free software: you can redistribute it and/or modify it * + * under the terms of the GNU General Public License as published by the Free * + * Software Foundation, either version 3 of the License, or (at your option) * + * any later version. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * + * for more details. * + * * + * You should have received a copy of the GNU General Public License along * + * with this program. If not, see . * + * * + ******************************************************************************/ + +#ifndef GUA_SCENEGRAPH_DOXYGEN_HPP +#define GUA_SCENEGRAPH_DOXYGEN_HPP + +/** + * \defgroup gua_scenegraph guacamole scenegraph + */ + +#endif // GUA_SCENEGRAPH_DOXYGEN_HPP + diff --git a/include/gua/scenegraph/GeometryNode.hpp b/include/gua/scenegraph/GeometryNode.hpp index 1e1717c61..5cea0f6cd 100644 --- a/include/gua/scenegraph/GeometryNode.hpp +++ b/include/gua/scenegraph/GeometryNode.hpp @@ -29,54 +29,87 @@ // external headers #include +namespace gua { + /** * This class is used to represent geometry in the SceneGraph. * + * A GeometryNode only stores references to existing rendering assets stored in + * guacamole's databases. GeometryNodes typically aren't instantiated directly + * but by utilizing guacamole's GeometryLoader. + * + * \ingroup gua_scenegraph */ - -namespace gua { - -class GeometryNode : public Node { +class GUA_DLL GeometryNode : public Node { public: - struct Configuration { - GUA_ADD_PROPERTY(std::string, geometry, "gua_default_geometry"); - GUA_ADD_PROPERTY(std::string, material, "gua_default_material"); - }; + /** + * A string referring to an entry in guacamole's GeometryDatabase. + */ + std::string const& get_geometry() const { return geometry_; } + void set_geometry(std::string const& v) { geometry_ = v; geometry_changed_ = self_dirty_ = true; } - Configuration data; + /** + * A string referring to an entry in guacamole's MaterialDatabase. + */ + std::string const& get_material() const { return material_; } + void set_material(std::string const& v) { material_ = v; material_changed_ = self_dirty_ = true; } + /** + * Constructor. + * + * This constructs an empty GeometryNode. + * + */ GeometryNode() {}; /** * Constructor. * - * This constructs a GeometryNode with the given parameters and calls - * the constructor of base class Core with the type GEOMETRY. + * This constructs a GeometryNode with the given parameters. * - * \param geometry The name of the GeometryNode's geometry. - * \param material The name of the GeometryNodeCore's material. + * \param name The name of the new GeometryNode. + * \param configuration A configuration struct to define the GeometryNode's + * properties. + * \param transform A matrix to describe the GeometryNode's + * transformation. */ GeometryNode(std::string const& name, - Configuration const& configuration = Configuration(), + std::string const& geometry = "gua_default_geometry", + std::string const& material = "gua_default_material", math::mat4 const& transform = math::mat4::identity()); /** - * Accepts a visitor and calls concrete visit method + * Accepts a visitor and calls concrete visit method. * - * This method implements the visitor pattern for Nodes + * This method implements the visitor pattern for Nodes. * + * \param visitor A visitor to process the GeometryNode's data. */ - /* virtual */ void accept(NodeVisitor&); + /* virtual */ void accept(NodeVisitor& visitor); + /** + * Updates a GeometryNode's BoundingBox. + * + * The bounding box is updated according to the transformation matrices of + * all children. + */ /*virtual*/ void update_bounding_box() const; + /*virtual*/ void update_cache(); + /*virtual*/ void ray_test_impl(RayNode const& ray, PickResult::Options options, Mask const& mask, std::set& hits); private: std::shared_ptr copy() const; + + std::string geometry_; + std::string material_; + + bool geometry_changed_; + bool material_changed_; }; } diff --git a/include/gua/scenegraph/LODNode.hpp b/include/gua/scenegraph/LODNode.hpp new file mode 100644 index 000000000..ee77be54d --- /dev/null +++ b/include/gua/scenegraph/LODNode.hpp @@ -0,0 +1,100 @@ +/****************************************************************************** + * guacamole - delicious VR * + * * + * Copyright: (c) 2011-2013 Bauhaus-Universität Weimar * + * Contact: felix.lauer@uni-weimar.de / simon.schneegans@uni-weimar.de * + * * + * This program is free software: you can redistribute it and/or modify it * + * under the terms of the GNU General Public License as published by the Free * + * Software Foundation, either version 3 of the License, or (at your option) * + * any later version. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * + * for more details. * + * * + * You should have received a copy of the GNU General Public License along * + * with this program. If not, see . * + * * + ******************************************************************************/ + +#ifndef GUA_LOD_NODE_HPP +#define GUA_LOD_NODE_HPP + +#include +#include +#include + +namespace gua { + +/** + * This class is used to represent a level of detail node in the SceneGraph. + * + * While processing the LODNode, guacamole's renderer computes the distance + * between the LODNode's translation and the current camera's translation in + * world coordinates. The computed value is checked against a user-defined + * distances vector. That vector contains distance values which are being mapped + * to the LODNode's children sequentially. An entrance in the distances vector + * therefore describes upto which distance between the current camera and the + * LODNode the LODNode's child with the same index shall be visible. + * + * \ingroup gua_scenegraph + */ +class GUA_DLL LODNode : public TransformNode { + public: + + struct Configuration { + /** + * A vector storing distances. Indices are mapped to the indices of the + * LODNode's children vector. + */ + GUA_ADD_PROPERTY(std::vector, lod_distances, std::vector()); + }; + + /** + * The LODNode's configuration. + */ + Configuration data; + + /** + * Constructor. + * + * This constructs an empty LODNode. + * + */ + LODNode() {}; + + /** + * Constructor. + * + * This constructs a LODNode with the given parameters. + * + * \param name The name of the new LODNode. + * \param configuration A configuration struct to define the LODNode's + * properties. + * \param transform A matrix to describe the LODNode's + * transformation. + */ + LODNode(std::string const& name, + Configuration const& configuration = Configuration(), + math::mat4 const& transform = math::mat4::identity()); + + + /** + * Accepts a visitor and calls concrete visit method. + * + * This method implements the visitor pattern for Nodes. + * + * \param visitor A visitor to process the LODNode's data. + */ + /* virtual */ void accept(NodeVisitor& visitor); + + private: + + std::shared_ptr copy() const; +}; + +} + +#endif // GUA_LOD_NODE_HPP diff --git a/include/gua/scenegraph/Node.hpp b/include/gua/scenegraph/Node.hpp index 7f0383463..2690845c5 100644 --- a/include/gua/scenegraph/Node.hpp +++ b/include/gua/scenegraph/Node.hpp @@ -23,6 +23,7 @@ #define GUA_NODE_HPP // guacamole headers +#include #include #include #include @@ -37,26 +38,22 @@ namespace gua { -/** - * This class is used to build the internal structure of a SceneGraph. - * - * Nodes have a name and hold objects and there transforms. Furthermore they - * keep track of which Nodes are attached to them (children) an to which Node - * they are attached to (parent). Nodes can be assigned a group name which - * allows to group them concerning similar properties etc. - * - * NOTE: This class is ment to be used inside the SceneGraph class only! - * All interaction with the graph must be handled with Iterators and via - * the SceneGraph interface. - * - */ - class NodeVisitor; class RayNode; namespace physics { class CollisionShapeNodeVisitor; } -class Node { +/** + * This class is used as a base class to provide basic node behaviour. + * + * A Node stores a name and, a tansformation matrix and an axis-aligned + * BoundingBox. Each of guacamole's Nodes may have multiple child Nodes and one + * parent Node. Furthermore, Nodes can be assigned a group name which allows for + * user-defined grouping concerning similar properties etc. + * + * \ingroup gua_scenegraph + */ +class GUA_DLL Node { public: /** @@ -64,10 +61,8 @@ class Node { * * This constructs a Node with the given parameters. * - * \param name The Node's name - * \param transform The transformation of the object the Node contains. - * \param core The Core of the node, representing its containing - * object. + * \param name The Node's name + * \param transform The Node's transformation. */ Node(std::string const& name = "", math::mat4 const& transform = math::mat4::identity()); @@ -80,32 +75,29 @@ class Node { */ virtual ~Node(); - /** - * Accepts a visitor and calls concrete visit method - * - * This method implements the visitor pattern for Nodes - * - * \param visitor A concrete NodeVisitor - */ - virtual void accept(NodeVisitor& visitor) = 0; - - virtual void update_cache(); /** * Returns the Node's name. * - * \return string The Node's name. + * \return std::string The Node's name. */ inline std::string const& get_name() const { return name_; } + /** + * Sets the Node's name. + * + * \param name The Node's new name. + */ inline void set_name(std::string const& name) { name_ = name; } /** * Adds a child. * - * This adds a Node to the Node's children list. + * This adds a Node to the Node's children vector and returns a shared pointer + * to the new child. * - * \param child The Node to be added as a child. + * \param node_name The name of the new Node to be added as a child. + * \tparam T The type of the new Node to be added as a child. */ template std::shared_ptr add_child(std::string const& node_name) { @@ -114,6 +106,15 @@ class Node { return add_child(new_node); } + /** + * Adds a child. + * + * This adds a Node to the Node's children vector and returns a shared pointer + * to the new child. + * + * \param new_node The new Node to be added as a child. + * \tparam T The type of the new Node to be added as a child. + */ template std::shared_ptr add_child(std::shared_ptr const& new_node) { @@ -126,12 +127,25 @@ class Node { } /** - * Returns the Node's children list. + * Removes a child. + * + * This removes a Node from the Node's children vector. + * + * \param child The Node to be removed. + */ + void remove_child(std::shared_ptr const& child); + + /** + * Returns the Node's children vector. * - * \return list The Node's children list. + * \return std::vector> The Node's children vector. */ inline std::vector> const& get_children() const { return children_; } + /** + * Clears the Node's children vector. Additionally, the parent node pointer of + * each child is set to nullptr. + */ void clear_children(); /** @@ -158,17 +172,17 @@ class Node { /** * Checks whether the Node is in a certain group. * - * \param group The name of the group to be checked. + * \param group The name of the group to be checked. * - * \return is_in_group Returns true if the Node is in the given group, - * else false. + * \return bool Returns true if the Node is in the given group, + * else false. */ bool is_in_group(std::string const& group) const; /** - * Gets the groups the Node is in. + * Returns the groups the Node is in. * - * \return groups Returns all groups the Node is in. + * \return std::set Returns all groups the Node is in. */ inline std::set const& get_groups() const { return group_list_; @@ -176,50 +190,65 @@ class Node { /** - * Returns the transformation of the object the Node contains. - * - * Returns the transformation accumulated with its parents so the - * resulting matrix represents the transformation in world - * coordinates. + * Returns the Node's transformation. * - * \return transform The Object's transformation. + * \return math::mat4 The Object's transformation. */ inline virtual math::mat4 get_transform() const { return transform_; } /** - * Returns the transformation of the object the Node contains. + * Returns the Node's world transformation. * - * Returns the transformation accumulated with its parents so the - * resulting matrix represents the transformation in world - * coordinates. + * Returns the Node's transformation accumulated with its parent's + * transformation * - * \return transform The Object's transformation. + * \return math::mat4 The Node's world transformation. */ math::mat4 get_world_transform() const; + /** + * Returns the Node's world postion. + * + * Accumulates the Node's transformation with its parent's transformation + * and returns the translational part of the resulting matrix. + * + * \return math::vec3 The Node's world position. + */ math::vec3 get_world_position() const; /** - * Sets the transformation of the object the Node contains. + * Sets the Node's transformation. * - * \param transform The new transformation of the Node's object. + * \param transform The Node's new transformation. */ virtual void set_transform(math::mat4 const& transform); /** - * Applies a scaling on the Node's object's transformation. + * Applies a scaling on the Node's transformation. * * \param x The x value of the scaling. * \param y The y value of the scaling. * \param z The z value of the scaling. */ - virtual void scale(float s); virtual void scale(float x, float y, float z); + + /** + * Applies a scaling on the Node's transformation. + * + * \param s The scaling vector to be used. + */ virtual void scale(math::vec3 const& s); /** - * Applies a rotation on the Node's object's transformation. + * Applies a uniform scaling on the Node's transformation. + * + * \param s The scaling value for all axes. + */ + virtual void scale(float s); + + /** + * Applies a rotation on the Node's transformation. * * \param angle The angle of the rotation in degrees. * \param x The x factor of the rotation. @@ -227,16 +256,29 @@ class Node { * \param z The z factor of the rotation. */ virtual void rotate(float angle, float x, float y, float z); + + /** + * Applies a rotation on the Node's transformation. + * + * \param angle The angle of the rotation in degrees. + * \param axis A vector containing the rotation's axis values. + */ virtual void rotate(float angle, math::vec3 const& axis); /** - * Applies a translation on the Node's object's transformation. + * Applies a translation on the Node's transformation. * * \param x The x value of the translation. * \param y The y value of the translation. * \param z The z value of the translation. */ virtual void translate(float x, float y, float z); + + /** + * Applies a translation on the Node's transformation. + * + * \param offset The translation vector. + */ virtual void translate(math::vec3 const& offset); /** @@ -250,42 +292,115 @@ class Node { int get_depth() const; /** - * Returns if the Node has Children + * Returns if the Node has children * - * \return bool Has the Node any children + * \return bool The return value is true if the Node has any children, else + * false. */ inline bool has_children() const { return !children_.empty(); } /** * Returns the full path to the node. * - * This function recursively computes the full path of the Node. + * This function recursively computes the full path of the Node. A Node's path + * contains the names of all of its parents, concatenated by "/". * - * \return path The full path to the Node. + * \return std::string The full path to the Node. */ std::string get_path() const; /** - * Returns the Node's parent. + * Returns a raw pointer to the Node's parent. * - * \return Node The Node's parent. + * \return Node* The Node's parent. */ inline Node* get_parent() const { return parent_; } + + /** + * Returns a shared pointer to the Node's parent. + * + * \return std::shared_ptr The Node's parent. + */ std::shared_ptr get_parent_shared() const; + /** + * Returns the Node's BoundingBox. + * + * \return math::BoundingBox The Node's BoundingBox. + */ virtual inline math::BoundingBox const& get_bounding_box() const { return bounding_box_; } + /** + * Updates a Node's BoundingBox. + * + * The bounding box is updated according to the transformation matrices of + * all children. + */ + virtual void update_bounding_box() const; + + /** + * Intersects a Node with a given RayNode. + * + * The function checks wheter a given RayNode intersects the Node or not. If + * an intersection was found, a std::set is returned, containing + * information about individual hits. The user may specify PickResult::Options + * and a mask (referring to Nodes' group names) to configure the intersection + * process. + * + * \param ray The RayNode used to check for intersections. + * \param options PickResult::Options to configure the intersection process. + * \param mask A mask to restrict the intersection to certain Nodes. + */ virtual std::set const ray_test(RayNode const& ray, PickResult::Options options = PickResult::PICK_ALL, std::string const& mask = ""); - void* get_user_data(unsigned handle) const; + /** + * Accepts a visitor and calls concrete visit method + * + * This method must be implemented by derived classes. + * + * \param visitor A visitor to process the Node's data + */ + virtual void accept(NodeVisitor& visitor) = 0; + + /** + * Updates the Node's cache. + * + * For optimization purposes, a Node caches data each time the rendering is + * being processed. This function computes and stores the Node's current + * BoundingBox and world transformation. + */ + virtual void update_cache(); + + /** + * Adds user-defined data to a Node. + * + * A user may store any data within one of guacamole's Nodes. This function + * returns a handle which can be used to regain the information later. + * + * \param data A pointer to the data to be stored. + * + * \return unsigned A handle for later access. + */ unsigned add_user_data(void* data); + /** + * Returns user-defined data for a given handle. + * + * + * \param handle The handle belonging to the wanted data. + * + * \return void* The user-defined data. This defaults to nullptr if the given + * handle is invalid. + */ + void* get_user_data(unsigned handle) const; + friend class SceneGraph; friend class GeometryLoader; + friend class VolumeLoader; friend class MeshLoader; friend class Serializer; friend class DotGenerator; @@ -307,19 +422,9 @@ class Node { */ inline bool is_root() const { return parent_ == nullptr; } - virtual void update_bounding_box() const; private: - /** - * Removes a child. - * - * This removes a Node from the Node's children list. - * - * \param child The Node to be removed. - */ - void remove_child(std::shared_ptr const& child); - /** * Sets the Node's parent. * diff --git a/include/gua/scenegraph/NodeVisitor.hpp b/include/gua/scenegraph/NodeVisitor.hpp index c32003388..258f7d986 100644 --- a/include/gua/scenegraph/NodeVisitor.hpp +++ b/include/gua/scenegraph/NodeVisitor.hpp @@ -29,12 +29,14 @@ namespace gua { class Node; -class GroupNode; -class ViewNode; +class TransformNode; +class LODNode; class GeometryNode; +class VolumeNode; class PointLightNode; class ScreenNode; class SpotLightNode; +class SunLightNode; class RayNode; class TexturedQuadNode; @@ -46,8 +48,9 @@ class CollisionShapeNode; } /** - * This class is used to recursively visit nodes in a scenegraph + * This class is used to recursively visit nodes in a SceneGraph * + * \ingroup gua_scenegraph */ class NodeVisitor { public: @@ -67,101 +70,132 @@ class NodeVisitor { virtual ~NodeVisitor(); /** - * Visits a GroupNode + * Visits a Node. * - * This function provides the interface to visit a GroupNode + * This function provides the interface to visit a Node. + * Unless overwritten by derived classes, this defaults to visit(Node*). * - * \param cam Pointer to GroupNode + * \param cam Pointer to a Node. */ virtual void visit(Node* node) {}; /** - * Visits a GroupNode + * Visits a TransformNode. * - * This function provides the interface to visit a GroupNode + * This function provides the interface to visit a TransformNode. + * Unless overwritten by derived classes, this defaults to visit(Node*). * - * \param cam Pointer to GroupNode + * \param cam Pointer to a TransformNode. */ - virtual void visit(GroupNode* node) { visit(reinterpret_cast(node)); } + virtual void visit(TransformNode* node) { visit(reinterpret_cast(node)); } /** - * Visits a ViewNode + * Visits an LODNode. * - * This function provides the interface to visit a ViewNode + * This function provides the interface to visit an LODNode. + * Unless overwritten by derived classes, this defaults to visit(Node*). * - * \param cam Pointer to ViewNode + * \param cam Pointer to a LODNode. */ - virtual void visit(ViewNode* node) { visit(reinterpret_cast(node)); } + virtual void visit(LODNode* node) { visit(reinterpret_cast(node)); } /** - * Visits a GeometryNode + * Visits a GeometryNode. * - * This function provides the interface to visit a GeometryNode + * This function provides the interface to visit a GeometryNode. + * Unless overwritten by derived classes, this defaults to visit(Node*). * - * \param cam Pointer to GeometryNode + * \param cam Pointer to a GeometryNode. */ virtual void visit(GeometryNode* node) { visit(reinterpret_cast(node)); } /** - * Visits a PointLightNode + * Visits a GeometryNode. + * + * This function provides the interface to visit a GeometryNode. + * Unless overwritten by derived classes, this defaults to visit(Node*). + * + * \param cam Pointer to a GeometryNode. + */ + virtual void visit(VolumeNode* node) { visit(reinterpret_cast(node)); } + + /** + * Visits a PointLightNode. * - * This function provides the interface to visit a PointLightNode + * This function provides the interface to visit a PointLightNode. + * Unless overwritten by derived classes, this defaults to visit(Node*). * - * \param cam Pointer to PointLightNode + * \param cam Pointer to a PointLightNode. */ virtual void visit(PointLightNode* node) { visit(reinterpret_cast(node)); } /** - * Visits a SpotLightNode + * Visits a SpotLightNode. * - * This function provides the interface to visit a SpotLightNode + * This function provides the interface to visit a SpotLightNode. + * Unless overwritten by derived classes, this defaults to visit(Node*). * - * \param cam Pointer to SpotLightNode + * \param cam Pointer to a SpotLightNode. */ virtual void visit(SpotLightNode* node) { visit(reinterpret_cast(node)); } /** - * Visits a SpotLightNode + * Visits a SunLightNode. + * + * This function provides the interface to visit a SunLightNode. + * Unless overwritten by derived classes, this defaults to visit(Node*). + * + * \param cam Pointer to a SunLightNode. + */ + virtual void visit(SunLightNode* node) { visit(reinterpret_cast(node)); } + + /** + * Visits a SpotLightNode. * - * This function provides the interface to visit a ScreenNode + * This function provides the interface to visit a ScreenNode. + * Unless overwritten by derived classes, this defaults to visit(Node*). * - * \param cam Pointer to ScreenNode + * \param cam Pointer to a ScreenNode. */ virtual void visit(ScreenNode* node) { visit(reinterpret_cast(node)); } /** - * Visits a RayNode + * Visits a RayNode. * - * This function provides the interface to visit a ScreenNode + * This function provides the interface to visit a ScreenNode. + * Unless overwritten by derived classes, this defaults to visit(Node*). * - * \param cam Pointer to ScreenNode + * \param cam Pointer to a ScreenNode. */ virtual void visit(RayNode* node) { visit(reinterpret_cast(node)); } /** - * Visits a RigidBodyNode + * Visits a RigidBodyNode. * - * This function provides the interface to visit a RigidBodyNode + * This function provides the interface to visit a RigidBodyNode. + * Unless overwritten by derived classes, this defaults to visit(Node*). * - * \param cam Pointer to RigidBodyNode + * \param cam Pointer to a RigidBodyNode. */ virtual void visit(physics::RigidBodyNode* node) { visit(reinterpret_cast(node)); } /** - * Visits a CollisionShapeNode + * Visits a CollisionShapeNode. * - * This function provides the interface to visit a CollisionShapeNode + * This function provides the interface to visit a CollisionShapeNode. + * Unless overwritten by derived classes, this defaults to visit(Node*). * - * \param cam Pointer to CollisionShapeNode + * \param cam Pointer to a CollisionShapeNode. */ virtual void visit(physics::CollisionShapeNode* node) { visit(reinterpret_cast(node)); } /** - * Visits a TexturedQuadNode + * Visits a TexturedQuadNode. * - * This function provides the interface to visit a TexturedQuadNode + * This function provides the interface to visit a TexturedQuadNode. + * Unless overwritten by derived classes, this defaults to visit(Node*). * - * \param cam Pointer to TexturedQuadNode + * \param cam Pointer to a TexturedQuadNode. */ virtual void visit(TexturedQuadNode* node) { visit(reinterpret_cast(node)); } diff --git a/include/gua/scenegraph/PickResult.hpp b/include/gua/scenegraph/PickResult.hpp index b37baa6db..2ebfb49fb 100644 --- a/include/gua/scenegraph/PickResult.hpp +++ b/include/gua/scenegraph/PickResult.hpp @@ -23,6 +23,7 @@ #define GUA_PICK_RESULT_HPP // guacamole headers +#include #include @@ -30,19 +31,101 @@ namespace gua { class Node; -struct PickResult { +/** + * This class is used to encapsulate properties of intersections generated by + * SceneGraph::ray_test(). + * + * A PickResult contains several data defining an intersection, such as distance + * of hit position to a RayNode's origin, a pointer to the hit Node itself, + * the hit position and corresponding surface normal in object and world + * coordinates and texture coordinates. + * + * \ingroup gua_scenegraph + */ - enum Options { PICK_ALL = 0, +struct GUA_DLL PickResult { + + /** + * These options are used by SceneGraph::ray_test() to configure the + * intersection. + */ + enum Options { + /** + * A PickResult is returned for each hit Node along a RayNode's + * length. This is the default value for picking. + */ + PICK_ALL = 0, + + /** + * Only the first hit Node is used as a PickResult. + */ PICK_ONLY_FIRST_OBJECT = 1<<1, + + /** + * Only the first face of each hit Node is used as a + * PickResult. + */ PICK_ONLY_FIRST_FACE = 1<<2, + + /** + * If set, the positions of all intersection points in the hit + * Nodes' object coordinates are written to the respective + * PickResult. + */ GET_POSITIONS = 1<<3, + + /** + * If set, the world positions of all intersection points in + * are written to the respective PickResult. + */ GET_WORLD_POSITIONS = 1<<4, + + /** + * If set, the normals of the surfaces at all intersection + * points in the hit Nodes' object coordinates are written to + * the respective PickResult. + */ GET_NORMALS = 1<<5, + + /** + * If set, the normals of the surfaces at all intersection + * points in world coordinates are written to the respective + * PickResult. + */ GET_WORLD_NORMALS = 1<<6, + + /** + * If set, all obtained normals are interpolated according to + * the hit Node's vertex normals and written to the respective + * PickResult. + */ INTERPOLATE_NORMALS = 1<<7, + + /** + * If set, the hit Node's texture coordinates at the hit's + * position are interpolated and written to the respective + * PickResult. + */ GET_TEXTURE_COORDS = 1<<8 }; + /** + * Constructor. + * + * This constructs a PickResult with the given parameters. A PickResult is + * instantiated for each successful intersection of a RayNode with a + * GeometryNode. + * + * \param d The distance between the RayNode's origin and the + * intersection point. + * \param o The Node beeing hit. + * \param p The hit's position in the hit Node's object coordinates. + * \param wp The hit's position in world coordinates. + * \param n The surface normal at the hit's position the hit Node's object + * coordinates. + * \param wn The surface normal at the hit's position in world coordinates. + * \param t The hit Node's texture coordinates at the hit's position. + */ PickResult(float d, Node* o, math::vec3 const& p, math::vec3 const& wp, math::vec3 const& n, math::vec3 const& wn, @@ -52,16 +135,31 @@ struct PickResult { normal(n), world_normal(wn), texture_coords(t) {} + /** The distance between a RayNode's origin and the intersection point.*/ float distance; + /** The Node beeing hit.*/ Node* object; + /** The Node beeing hit.*/ mutable math::vec3 position; + /** The hit's position in the hit Node's object coordinates.*/ mutable math::vec3 world_position; + /** The surface normal at the hit's position the hit Node's object coordinates.*/ mutable math::vec3 normal; + /** The surface normal at the hit's position in world coordinates.*/ mutable math::vec3 world_normal; + /** The hit Node's texture coordinates at the hit's position.*/ mutable math::vec2 texture_coords; - bool operator<(PickResult const& lhs) const { - return distance < lhs.distance; + /** + * Compares two PickResults. + * + * As comparison criterion, the PickResults' distance to the respective + * RayNode's origin is used. + * + * \param rhs The PickResult to be compared with. + */ + bool operator<(PickResult const& rhs) const { + return distance < rhs.distance; } }; diff --git a/include/gua/scenegraph/PointLightNode.hpp b/include/gua/scenegraph/PointLightNode.hpp index d40203be7..468882e85 100644 --- a/include/gua/scenegraph/PointLightNode.hpp +++ b/include/gua/scenegraph/PointLightNode.hpp @@ -22,6 +22,7 @@ #ifndef GUA_POINT_LIGHT_NODE_HPP #define GUA_POINT_LIGHT_NODE_HPP +#include #include #include @@ -29,51 +30,101 @@ #include +namespace gua { + /** - * This class is used to represent light in the SceneGraph. + * This class is used to represent a point light in the SceneGraph. * + * \ingroup gua_scenegraph */ - -namespace gua { - -class PointLightNode : public Node { +class GUA_DLL PointLightNode : public Node { public: struct Configuration { - GUA_ADD_PROPERTY(utils::Color3f, color, utils::Color3f(1.f, 1.f, 1.f)); + /** + * The color of the light source. + * It's possible to use negative values and values > 1. + */ + GUA_ADD_PROPERTY(utils::Color3f, color, utils::Color3f(1.f, 1.f, 1.f)); + + /** + * The exponent of distance attenuation. + * E.g. a value of 2 means quadratic falloff, 1 means linear falloff + */ GUA_ADD_PROPERTY(float, falloff, 1.f); + + /** + * Triggers whether the light casts shadows. NOTE: Not implemented yet! + */ GUA_ADD_PROPERTY(bool, enable_shadows, false); + + /** + * Triggers volumetric screen-space effects for the light source. + */ GUA_ADD_PROPERTY(bool, enable_godrays, false); + + /** + * Triggers whether or not the light source has influence on objects' + * diffuse shading. + */ GUA_ADD_PROPERTY(bool, enable_diffuse_shading, true); + + /** + * Triggers whether or not the light source has influence on objects' + * specular shading. + */ GUA_ADD_PROPERTY(bool, enable_specular_shading, true); + + /** + * Sets the size in pixel of the texture used for shadow map generation. + * Choose wisely! + */ GUA_ADD_PROPERTY(unsigned, shadow_map_size, 512); }; + /** + * The PointLightNode's configuration. + */ Configuration data; /** * Constructor. * - * This constructs a PointLightNode with the given parameters and calls - * the constructor of base class Core with the type LIGHT. + * This constructs an empty PointLightNode. * - * \param color The light's color. */ - PointLightNode() {} + /** + * Constructor. + * + * This constructs a PointLightNode with the given parameters. + * + * \param name The name of the new PointLightNode. + * \param configuration A configuration struct to define the PointLightNode's + * properties. + * \param transform A matrix to describe the PointLightNode's + * transformation. + */ PointLightNode(std::string const& name, Configuration const& configuration = Configuration(), math::mat4 const& transform = math::mat4::identity()); /** - * Accepts a visitor and calls concrete visit method + * Accepts a visitor and calls concrete visit method. * - * This method implements the visitor pattern for Nodes + * This method implements the visitor pattern for Nodes. * + * \param visitor A visitor to process the PointLightNode's data. */ - /* virtual */ void accept(NodeVisitor&); + /* virtual */ void accept(NodeVisitor& visitor); + /** + * Updates a PointLightNode's BoundingBox. + * + * The bounding box is updated according to the transformation matrices of + * all children. + */ void update_bounding_box() const; private: diff --git a/include/gua/scenegraph/RayNode.hpp b/include/gua/scenegraph/RayNode.hpp index 3d88b09d3..cd18c8134 100644 --- a/include/gua/scenegraph/RayNode.hpp +++ b/include/gua/scenegraph/RayNode.hpp @@ -26,51 +26,83 @@ #include #include +namespace gua { + /** - * This class is used to represent a camera in the SceneGraph. + * This class is used to represent a ray in the SceneGraph. * + * A RayNode is used to intersect scene geometry and utilized by + * SceneGraph::ray_test(). + * + * \ingroup gua_scenegraph */ - -namespace gua { - -class RayNode : public Node { +class GUA_DLL RayNode : public Node { public: + /** + * Constructor. + * + * This constructs an empty RayNode. + * + */ RayNode() {} /** * Constructor. * - * This constructs a RayNode with the given parameters and calls - * the constructor of base class Core with the type CAMERA. + * This constructs a RayNode with the given parameters. * - * \param stereo_width The gap between the eyes. + * \param name The name of the new RayNode. + * \param transform A matrix to describe the RayNode's transformation. */ RayNode(std::string const& name, math::mat4 const& transform = math::mat4::identity()); - /** - * Accepts a visitor and calls concrete visit method + /** + * Accepts a visitor and calls concrete visit method. * - * This method implements the visitor pattern for Nodes + * This method implements the visitor pattern for Nodes. * + * \param visitor A visitor to process the RayNode's data. */ - /* virtual */ void accept(NodeVisitor&); + /* virtual */ void accept(NodeVisitor& visitor); + /** + * Updates a RayNode's BoundingBox. + * + * The bounding box is updated according to the transformation matrices of + * all children. + */ + void update_bounding_box() const; + + /** + * Used internally to check whether a RayNode hits a given BoundingBox. + * + * \param box The box to be checked against. + * + * \return std::pair A pair of parameters which describe the + * to potential intersecition points with a + * BoundingBox in ray space. + */ std::pair intersect( math::BoundingBox const& box) const; + /** + * Used internally to get a world-transformed mathematical representation of a + * ray. + * + * \return Ray A mathematical representation (origin, direction, length) of + * the RayNode. + */ Ray const get_world_ray() const; - void update_bounding_box() const; - + /** + * Used internally to check whether or not intersections occured. + */ static const float END; private: - /** - * - */ std::shared_ptr copy() const; }; diff --git a/include/gua/scenegraph/SceneGraph.hpp b/include/gua/scenegraph/SceneGraph.hpp index 083d5d0a0..b11130c89 100644 --- a/include/gua/scenegraph/SceneGraph.hpp +++ b/include/gua/scenegraph/SceneGraph.hpp @@ -22,6 +22,7 @@ #ifndef GUA_SCENE_GRAPH_HPP #define GUA_SCENE_GRAPH_HPP +#include #include #include #include @@ -41,15 +42,19 @@ class RayNode; * This class is used to build and structure a graph describing a scene with * all its contents. It provides an interface to set up and have access to * a graph consisting of several Nodes in order to build a scene abstraction. + * + * \ingroup gua_scenegraph */ -class SceneGraph { +class GUA_DLL SceneGraph { public: /** * Constructor. * - * This constructs an empty SceneGraph. + * This constructs a new SceneGraph. + * + * \param name The new SceneGraph's name. */ SceneGraph(std::string const& name = "scenegraph"); @@ -65,21 +70,17 @@ class SceneGraph { /** * Adds a new Node. * - * This function adds a new Node to the graph. If the given path to a - * parent Node is invalid (this means this Node doesn't exist), an - * Node on the SceneGraph's "end" is returned. Otherwise an - * Node on the added Node is given back. + * This function adds a new Node to the SceneGraph. If the given path to a + * parent Node is invalid (this means this Node doesn't exist), a new Node is + * returned but not added to any parent. + * + * \param path_to_parent The location of the Node the new Node will be + * attached to. + * \param node_name The name of the new Node. * - * \param path_to_parent The location of the Node the new Node will be - * attached to. - * \param node_name The name of the new Node. - * \param core The core the new Node shall refer to. - * \param transform The transformation of the object the new Node - * carries. + * \tparam tparam The type of the Node to be added. * - * \return Iterator An Iterator on the recently added Node. If the - * path to the parent was invalid, the returned - * Iterator points to the SceneGraph's "end". + * \return std::shared_ptr A shared pointer to the recently added Node. */ template std::shared_ptr add_node(std::string const& path_to_parent, std::string const& node_name) { @@ -96,6 +97,18 @@ class SceneGraph { return add_node(parent, new_node); } + /** + * Adds a new Node. + * + * This function adds a new Node to the SceneGraph. + * + * \param parent The Node the new Node will be attached to. + * \param node_name The name of the new Node. + * + * \tparam tparam The type of the Node to be added. + * + * \return std::shared_ptr A shared pointer to the recently added Node. + */ template std::shared_ptr add_node(std::shared_ptr const& parent, std::string const& node_name) { @@ -105,6 +118,21 @@ class SceneGraph { return new_node; } + /** + * Adds a new Node. + * + * This function adds a new Node to the SceneGraph. If the given path to a + * parent Node is invalid (this means this Node doesn't exist), a new Node is + * returned but not added to any parent. + * + * \param path_to_parent The location of the Node the new Node will be + * attached to. + * \param new_node The Node to be attached. + * + * \tparam tparam The type of the Node to be added. + * + * \return std::shared_ptr A shared pointer to the recently added Node. + */ template std::shared_ptr add_node(std::string const& path_to_parent, std::shared_ptr const& new_node) { @@ -118,6 +146,18 @@ class SceneGraph { return add_node(parent, new_node); } + /** + * Adds a new Node. + * + * This function adds a new Node to the SceneGraph. + * + * \param parent The Node the new Node will be attached to. + * \param new_node The Node to be attached. + * + * \tparam tparam The type of the Node to be added. + * + * \return std::shared_ptr A shared pointer to the recently added Node. + */ template std::shared_ptr add_node(std::shared_ptr const& parent, std::shared_ptr const& new_node) { parent->add_child(new_node); @@ -127,41 +167,108 @@ class SceneGraph { /** * Removes a Node. * - * This function removes a Node from the graph and returnes an Iterator - * on the next Node with respect to the Iterator's traversion style. + * This function removes a Node from the SceneGraph. * * \param path_to_node The location of the Node to be removed. - * - * \return Iterator An Iterator on the next Node. */ void remove_node(std::string const& path_to_node); + + /** + * Removes a Node. + * + * This function removes a Node from the SceneGraph. + * + * \param to_remove The Node to be removed. + */ void remove_node(std::shared_ptr const& to_remove); + /** + * Sets the SceneGraph's name. + * + * \param name The SceneGraph's new name. + */ void set_name(std::string const& name); + + /** + * Returns the SceneGraph's name. + * + * \return std::string The SceneGraph's name. + */ std::string const& get_name() const; + /** + * Sets the SceneGraph's root Node. + * + * \param root The SceneGraph's new root Node. + */ void set_root(std::shared_ptr const& root); + + /** + * Returns the SceneGraph's root Node. + * + * \return std::shared_ptr The SceneGraph's root Node. + */ std::shared_ptr const& get_root() const; /** * Allows to access nodes via the index operator. * * This operator allows to access nodes via the index operator. If a - * given path doesn't refer to an existing set of nodes, all missing - * nodes in the path are added to the SceneGraph. + * given path doesn't refer to an existing set of nodes, a nullptr is returned. * - * \param path_to_node The path to the Node you want to access. + * \param path_to_node The path to the wanted Node. * - * \return Iterator An Iterator on the given Node. + * \return std::shared_ptr The wanted Node. */ std::shared_ptr operator[](std::string const& path_to_node) const; + + /** + * Assignment operator. + * + * This operator deep copies a given SceneGraph, assignes the copy's values to + * the existing graph and returns a reference to it. + * + * \param rhs The SceneGraph to be copied. + * + * \return SceneGraph const& The SceneGraph containing the copied values. + */ SceneGraph const& operator=(SceneGraph const& rhs); + /** + * Prints the SceneGraph to a file in GraphViz' dot format. + * + * Serializes the graph and writes all its Nodes to a file. + * + * \param file Complete path to the output file. The file doesn't need to + * exist. The directory structure, however, does. + */ void to_dot_file(std::string const& file) const; + /** + * Updates the cache of all SceneGraph Nodes. + * + * Calls Node::update_cache() on the root Node. + */ void update_cache() const; + + /** + * Accepts a NodeVisitor to process all SceneGraph Nodes. + * + * Calls Node::accept() on the root Node. + * + * \param visitor The NodeVisitor to pe accepted. + */ void accept(NodeVisitor& visitor) const; + /** + * Intersects a SceneGraph with a given RayNode. + * + * Calls Node::ray_test() on the root Node. + * + * \param ray The RayNode used to check for intersections. + * \param options PickResult::Options to configure the intersection process. + * \param mask A mask to restrict the intersection to certain Nodes. + */ std::set const ray_test(RayNode const& ray, PickResult::Options options = PickResult::PICK_ALL, std::string const& mask = ""); diff --git a/include/gua/scenegraph/ScreenNode.hpp b/include/gua/scenegraph/ScreenNode.hpp index ca68aaa50..108c15bd2 100644 --- a/include/gua/scenegraph/ScreenNode.hpp +++ b/include/gua/scenegraph/ScreenNode.hpp @@ -19,53 +19,94 @@ * * ******************************************************************************/ -#ifndef GUA_SCREEN_CORE_HPP -#define GUA_SCREEN_CORE_HPP +#ifndef GUA_SCREEN_NODE_HPP +#define GUA_SCREEN_NODE_HPP +#include #include #include +namespace gua { + /** * This class is used to represent a screen in the SceneGraph. * + * A ScreenNode is used to specify arbitrary viewing frustra. For that purpose, + * additionally any of guacamole's Nodes may serve as eye representation. To + * combine ScreenNode and eye, a Camera has to be specified. + * + * \ingroup gua_scenegraph */ - -namespace gua { - -class ScreenNode : public Node { +class GUA_DLL ScreenNode : public Node { public: struct Configuration { + /** + * A vector containing width and height of the ScreenNode. + */ GUA_ADD_PROPERTY(math::vec2, size, math::vec2(1.f, 1.f)); }; + /** + * The ScreenNode's configuration. + */ Configuration data; + /** + * Constructor. + * + * This constructs an empty ScreenNode. + * + */ ScreenNode() {} + /** + * Constructor. + * + * This constructs a ScreenNode with the given parameters. + * + * \param name The name of the new ScreenNode. + * \param configuration A configuration struct to define the ScreenNode's + * properties. + * \param transform A matrix to describe the ScreenNode's + * transformation. By default, the ScreenNode is aligned + * with the xy-plane and facing in +z direction. + */ ScreenNode(std::string const& name, Configuration const& configuration = Configuration(), math::mat4 const& transform = math::mat4::identity()); + /** + * Returns the ScreenNode's transformation, considering the scaling specified + * in the Configuration. + * + * \return math::mat4 The ScreenNode's scaled transformation. + */ math::mat4 get_scaled_transform() const; - math::mat4 get_scaled_world_transform() const; /** - * Accepts a visitor and calls concrete visit method - * - * This method implements the visitor pattern for Nodes + * Returns the ScreenNode's world transformation, considering the scaling + * specified in the Configuration. * + * \return math::mat4 The ScreenNode's scaled world transformation. */ - /* virtual */ void accept(NodeVisitor&); + math::mat4 get_scaled_world_transform() const; - private: /** + * Accepts a visitor and calls concrete visit method. + * + * This method implements the visitor pattern for Nodes. * + * \param visitor A visitor to process the ScreenNode's data. */ + /* virtual */ void accept(NodeVisitor& visitor); + + private: + std::shared_ptr copy() const; }; } -#endif // GUA_SCREEN_CORE_HPP +#endif // GUA_SCREEN_NODE_HPP diff --git a/include/gua/scenegraph/SpotLightNode.hpp b/include/gua/scenegraph/SpotLightNode.hpp index 3b498acf2..9721c4a45 100644 --- a/include/gua/scenegraph/SpotLightNode.hpp +++ b/include/gua/scenegraph/SpotLightNode.hpp @@ -22,6 +22,7 @@ #ifndef GUA_SPOT_LIGHT_NODE_HPP #define GUA_SPOT_LIGHT_NODE_HPP +#include #include #include @@ -29,44 +30,113 @@ #include +namespace gua { + /** - * This class is used to represent light in the SceneGraph. + * This class is used to represent spot light in the SceneGraph. * + * \ingroup gua_scenegraph */ - -namespace gua { - -class SpotLightNode : public Node { +class GUA_DLL SpotLightNode : public Node { public: struct Configuration { + /** + * The color of the light source. + * It's possible to use negative values and values > 1. + */ GUA_ADD_PROPERTY(utils::Color3f, color, utils::Color3f(1.f, 1.f, 1.f)); + + /** + * The exponent of distance attenuation. + * E.g. a value of 2 means quadratic falloff, 1 means linear falloff + */ GUA_ADD_PROPERTY(float, falloff, 1.f); + + /** + * The exponent of radial attenuation. + * E.g. a value of 2 means quadratic falloff, 1 means linear falloff + */ GUA_ADD_PROPERTY(float, softness, 0.5f); + + /** + * Triggers whether the light casts shadows. + */ GUA_ADD_PROPERTY(bool, enable_shadows, false); + + /** + * Triggers volumetric screen-space effects for the light source. + */ GUA_ADD_PROPERTY(bool, enable_godrays, false); + + /** + * Triggers whether or not the light source has influence on objects' + * diffuse shading. + */ GUA_ADD_PROPERTY(bool, enable_diffuse_shading, true); + + /** + * Triggers whether or not the light source has influence on objects' + * specular shading. + */ GUA_ADD_PROPERTY(bool, enable_specular_shading, true); + + /** + * Sets the size in pixel of the texture used for shadow map generation. + * Choose wisely! + */ GUA_ADD_PROPERTY(unsigned, shadow_map_size, 512); + + /** + * Sets the offset between a shadow casting object and the shadow's edge. + * Increase this value to reduce artefacts (especially shadow acne). + */ GUA_ADD_PROPERTY(float, shadow_offset, 0.001f); }; + /** + * The SpotLightNode's configuration. + */ Configuration data; + /** + * Constructor. + * + * This constructs an empty SpotLightNode. + * + */ SpotLightNode() {} + /** + * Constructor. + * + * This constructs a SpotLightNode with the given parameters. + * + * \param name The name of the new SpotLightNode. + * \param configuration A configuration struct to define the SpotLightNode's + * properties. + * \param transform A matrix to describe the SpotLightNode's + * transformation. The default light direction is -y. + */ SpotLightNode(std::string const& name, Configuration const& configuration = Configuration(), math::mat4 const& transform = math::mat4::identity()); /** - * Accepts a visitor and calls concrete visit method + * Accepts a visitor and calls concrete visit method. * - * This method implements the visitor pattern for Nodes + * This method implements the visitor pattern for Nodes. * + * \param visitor A visitor to process the SpotLightNode's data. */ - /* virtual */ void accept(NodeVisitor&); + /* virtual */ void accept(NodeVisitor& visitor); + /** + * Updates a SpotLightNode's BoundingBox. + * + * The bounding box is updated according to the transformation matrices of + * all children. + */ void update_bounding_box() const; private: diff --git a/include/gua/scenegraph/SunLightNode.hpp b/include/gua/scenegraph/SunLightNode.hpp new file mode 100644 index 000000000..2d8f7a842 --- /dev/null +++ b/include/gua/scenegraph/SunLightNode.hpp @@ -0,0 +1,152 @@ +/****************************************************************************** + * guacamole - delicious VR * + * * + * Copyright: (c) 2011-2013 Bauhaus-Universität Weimar * + * Contact: felix.lauer@uni-weimar.de / simon.schneegans@uni-weimar.de * + * * + * This program is free software: you can redistribute it and/or modify it * + * under the terms of the GNU General Public License as published by the Free * + * Software Foundation, either version 3 of the License, or (at your option) * + * any later version. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * + * for more details. * + * * + * You should have received a copy of the GNU General Public License along * + * with this program. If not, see . * + * * + ******************************************************************************/ + +#ifndef GUA_SUN_LIGHT_NODE_HPP +#define GUA_SUN_LIGHT_NODE_HPP + +#include +#include + +#include +#include + +#include + +namespace gua { + +/** + * This class is used to represent directional and parallel light in the + * SceneGraph. + * + * \ingroup gua_scenegraph + */ +class GUA_DLL SunLightNode : public Node { + public: + + struct Configuration { + /** + * The color of the light source. + * It's possible to use negative values and values > 1. + */ + GUA_ADD_PROPERTY(utils::Color3f, color, utils::Color3f(1.f, 1.f, 1.f)); + + /** + * Triggers whether the light casts shadows. + */ + GUA_ADD_PROPERTY(bool, enable_shadows, false); + + /** + * Triggers volumetric screen-space effects for the light source. + */ + GUA_ADD_PROPERTY(bool, enable_godrays, false); + + /** + * Triggers whether or not the light source has influence on objects' + * diffuse shading. + */ + GUA_ADD_PROPERTY(bool, enable_diffuse_shading, true); + + /** + * Triggers whether or not the light source has influence on objects' + * specular shading. + */ + GUA_ADD_PROPERTY(bool, enable_specular_shading, true); + + /** + * Sets the size in pixel of the texture used for shadow map generation. + * Choose wisely! + */ + GUA_ADD_PROPERTY(unsigned, shadow_map_size, 1024); + + /** + * Sets the offset between a shadow casting object and the shadow's edge. + * Increase this value to reduce artefacts (especially shadow acne). + */ + GUA_ADD_PROPERTY(float, shadow_offset, 0.001f); + + /** + * Sets the split distance-to-camera values for rendering cascaded shadow + * maps in world coordinates. + */ + GUA_ADD_PROPERTY(std::vector, shadow_cascaded_splits, std::vector({0.1f, 2, 10, 50, 100.f})); + + /** + * Sets the value used for near clipping when renering cascaded shadow maps. + */ + GUA_ADD_PROPERTY(float, shadow_near_clipping_in_sun_direction, 100.f); + }; + + /** + * The SunLightNode's configuration. + */ + Configuration data; + + /** + * Constructor. + * + * This constructs an empty SunLightNode. + * + */ + SunLightNode() {} + + /** + * Constructor. + * + * This constructs a SunLightNode with the given parameters. + * + * \param name The name of the new SunLightNode. + * \param configuration A configuration struct to define the SunLightNode's + * properties. + * \param transform A matrix to describe the SunLightNode's + * transformation. The default light direction is -y. + * NOTE: Since a SunLightNode is a directional light + * source, only rotations are needed to describe its + * transformation. + */ + SunLightNode(std::string const& name, + Configuration const& configuration = Configuration(), + math::mat4 const& transform = math::mat4::identity()); + + /** + * Accepts a visitor and calls concrete visit method. + * + * This method implements the visitor pattern for Nodes. + * + * \param visitor A visitor to process the SunLightNode's data. + */ + /* virtual */ void accept(NodeVisitor& visitor); + + /** + * Updates a SunLightNode's BoundingBox. + * + * The bounding box is updated according to the transformation matrices of + * all children. + */ + void update_bounding_box() const; + + private: + + std::shared_ptr copy() const; +}; + +} + +#endif // GUA_SUN_LIGHT_NODE_HPP diff --git a/include/gua/scenegraph/TexturedQuadNode.hpp b/include/gua/scenegraph/TexturedQuadNode.hpp index cc58e1ece..4b82164b7 100644 --- a/include/gua/scenegraph/TexturedQuadNode.hpp +++ b/include/gua/scenegraph/TexturedQuadNode.hpp @@ -25,40 +25,100 @@ #include #include +namespace gua { + /** - * This class is used to represent a screen in the SceneGraph. + * This class is used to represent a textured quad in the SceneGraph. * + * A TexturedQuadNode is capable of displaying any texture and even Pipeline + * output. It may therefore be used to implement portals, mirrors etc. + * + * \ingroup gua_scenegraph */ - -namespace gua { - -class TexturedQuadNode : public Node { +class GUA_DLL TexturedQuadNode : public Node { public: struct Configuration { + /** + * A string referring to an entry in guacamole's TextureDatabase. + */ GUA_ADD_PROPERTY(std::string, texture, ""); + + /** + * A vector containing width and height of the TexturedQuadNode. + */ GUA_ADD_PROPERTY(math::vec2, size, math::vec2(1.f, 1.f)); + + /** + * Sets wheter the given texture is a stereo texture. Set this to true, if + * you want to display a texture rendered by a Pipeline with stereo enabled. + */ GUA_ADD_PROPERTY(bool, is_stereo_texture, false); + + /** + * Triggers whether the given texture's x coordinates are flipped. + */ + GUA_ADD_PROPERTY(bool, flip_x, false); + + /** + * Triggers whether the given texture's y coordinates are flipped. + */ + GUA_ADD_PROPERTY(bool, flip_y, false); }; + /** + * The TexturedQuadNode's configuration. + */ Configuration data; + /** + * Constructor. + * + * This constructs an empty TexturedQuadNode. + * + */ TexturedQuadNode() {} + /** + * Constructor. + * + * This constructs a TexturedQuadNode with the given parameters. + * + * \param name The name of the new TexturedQuadNode. + * \param configuration A configuration struct to define the + * TexturedQuadNode's properties. + * \param transform A matrix to describe the TexturedQuadNode's + * transformation. By default, the TexturedQuadNode is + * aligned with the xy-plane and facing in +z direction. + */ TexturedQuadNode(std::string const& name, Configuration const& configuration = Configuration(), math::mat4 const& transform = math::mat4::identity()); + /** + * Returns the TexturedQuadNode's transformation, considering the scaling + * specified in the Configuration. + * + * \return math::mat4 The TexturedQuadNode's scaled transformation. + */ math::mat4 get_scaled_transform() const; + + /** + * Returns the TexturedQuadNode's world transformation, considering the + * scaling specified in the Configuration. + * + * \return math::mat4 The TexturedQuadNode's scaled world transformation. + */ math::mat4 get_scaled_world_transform() const; /** - * Accepts a visitor and calls concrete visit method + * Accepts a visitor and calls concrete visit method. * - * This method implements the visitor pattern for Nodes + * This method implements the visitor pattern for Nodes. * + * \param visitor A visitor to process the TexturedQuadNode's data. */ - /* virtual */ void accept(NodeVisitor&); + /* virtual */ void accept(NodeVisitor& visitor); /*virtual*/ void update_bounding_box() const; diff --git a/include/gua/scenegraph/ViewNode.hpp b/include/gua/scenegraph/TransformNode.hpp similarity index 61% rename from include/gua/scenegraph/ViewNode.hpp rename to include/gua/scenegraph/TransformNode.hpp index 9a74a159c..64e57950e 100644 --- a/include/gua/scenegraph/ViewNode.hpp +++ b/include/gua/scenegraph/TransformNode.hpp @@ -19,58 +19,60 @@ * * ******************************************************************************/ -#ifndef GUA_VIEW_NODE_HPP -#define GUA_VIEW_NODE_HPP +#ifndef GUA_GROUP_NODE_HPP +#define GUA_GROUP_NODE_HPP +#include #include -#include + +namespace gua { /** - * This class is used to represent a camera in the SceneGraph. + * This class is used to represent an transformation node in the SceneGraph. * + * Because any of guacamole's Nodes stores children and transformation, the + * TransformationNode only exists for the convenience of explicitly limiting a + * Node's purpose to the transformation of several children. + * + * \ingroup gua_scenegraph */ - -namespace gua { - -class ViewNode : public Node { +class GUA_DLL TransformNode : public Node { public: - struct Configuration { - GUA_ADD_PROPERTY(float, stereo_width, 0.07f); - }; - - Configuration data; - - ViewNode() {} - /** * Constructor. * - * This constructs a ViewNode with the given parameters and calls - * the constructor of base class Core with the type CAMERA. + * This constructs an empty TransformNode. * - * \param stereo_width The gap between the eyes. */ - ViewNode(std::string const& name, - Configuration const& configuration = Configuration(), - math::mat4 const& transform = math::mat4::identity()); + TransformNode() {}; /** - * Accepts a visitor and calls concrete visit method + * Constructor. * - * This method implements the visitor pattern for Nodes + * This constructs a TransformNode with the given parameters. * + * \param name The name of the new TransformNode. + * \param transform A matrix to describe the TransformNode's + * transformation. */ - /* virtual */ void accept(NodeVisitor&); - - private: + TransformNode(std::string const& name, + math::mat4 const& transform = math::mat4::identity()); /** + * Accepts a visitor and calls concrete visit method. * + * This method implements the visitor pattern for Nodes. + * + * \param visitor A visitor to process the TransformNode's data. */ + /* virtual */ void accept(NodeVisitor& visitor); + + private: + std::shared_ptr copy() const; }; } -#endif // GUA_VIEW_NODE_HPP +#endif // GUA_GROUP_NODE_HPP diff --git a/include/gua/scenegraph/VolumeNode.hpp b/include/gua/scenegraph/VolumeNode.hpp new file mode 100644 index 000000000..be77f84bc --- /dev/null +++ b/include/gua/scenegraph/VolumeNode.hpp @@ -0,0 +1,106 @@ +/****************************************************************************** + * guacamole - delicious VR * + * * + * Copyright: (c) 2011-2013 Bauhaus-Universität Weimar * + * Contact: felix.lauer@uni-weimar.de / simon.schneegans@uni-weimar.de * + * * + * This program is free software: you can redistribute it and/or modify it * + * under the terms of the GNU General Public License as published by the Free * + * Software Foundation, either version 3 of the License, or (at your option) * + * any later version. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * + * for more details. * + * * + * You should have received a copy of the GNU General Public License along * + * with this program. If not, see . * + * * + ******************************************************************************/ + +#ifndef GUA_VOLUME_NODE_HPP +#define GUA_VOLUME_NODE_HPP + +// guacamole headers +#include +#include + +// external headers +#include + +namespace gua { + +/** + * This class is used to represent a volume in the SceneGraph. + * + * \ingroup gua_scenegraph + */ +class GUA_DLL VolumeNode : public Node { + public: + + struct Configuration { + /** + * A string referring to an entry in guacamole's GeometryDatabase. + */ + GUA_ADD_PROPERTY(std::string, volume, "gua_volume_default"); + }; + + /** + * The VolumeNode's configuration. + */ + Configuration data; + + /** + * Constructor. + * + * This constructs an empty VolumeNode. + * + */ + VolumeNode() {}; + + /** + * Constructor. + * + * This constructs a VolumeNode with the given parameters. + * + * \param name The name of the new VolumeNode. + * \param configuration A configuration struct to define the VolumeNode's + * properties. + * \param transform A matrix to describe the VolumeNode's + * transformation. + */ + VolumeNode(std::string const& name, + Configuration const& configuration = Configuration(), + math::mat4 const& transform = math::mat4::identity()); + + /** + * Accepts a visitor and calls concrete visit method. + * + * This method implements the visitor pattern for Nodes. + * + * \param visitor A visitor to process the VolumeNode's data. + */ + /*virtual*/ void accept(NodeVisitor& visitor); + + /** + * Updates a VolumeNode's BoundingBox. + * + * The bounding box is updated according to the transformation matrices of + * all children. + */ + /*virtual*/ void update_bounding_box() const; + + /*virtual*/ void ray_test_impl(RayNode const& ray, + PickResult::Options options, + Mask const& mask, + std::set& hits); + + private: + + std::shared_ptr copy() const; +}; + +} + +#endif // GUA_VOLUME_NODE_HPP diff --git a/include/gua/utils/AnimatedValue.hpp b/include/gua/utils/AnimatedValue.hpp index f5a10815f..044ce15ef 100644 --- a/include/gua/utils/AnimatedValue.hpp +++ b/include/gua/utils/AnimatedValue.hpp @@ -22,13 +22,15 @@ #ifndef GUA_ANIMATEDVALUE_HPP #define GUA_ANIMATEDVALUE_HPP +#include + namespace gua { namespace utils { /** * A class for smooth value interpolation. */ -class AnimatedValue { +class GUA_DLL AnimatedValue { public: enum Direction { In, diff --git a/include/gua/utils/Color3f.hpp b/include/gua/utils/Color3f.hpp index be75b0358..b51f48fb4 100644 --- a/include/gua/utils/Color3f.hpp +++ b/include/gua/utils/Color3f.hpp @@ -22,6 +22,7 @@ #ifndef COLOR_3F_HPP #define COLOR_3F_HPP +#include #include namespace gua { @@ -34,7 +35,7 @@ namespace utils { * interface as well. */ -struct Color3f { +struct GUA_DLL Color3f { public: /** @@ -104,6 +105,8 @@ struct Color3f { */ static const Color3f random(); + friend bool operator==(Color3f const& lhs, Color3f const& rhs); + private: void set_hsv(float hue, float saturation, float value); diff --git a/include/gua/utils/Directory.hpp b/include/gua/utils/Directory.hpp index b15cc3a7f..d92c8db1c 100644 --- a/include/gua/utils/Directory.hpp +++ b/include/gua/utils/Directory.hpp @@ -22,6 +22,8 @@ #ifndef GUA_DIRECTORY_HPP #define GUA_DIRECTORY_HPP +#include + #include /** @@ -30,7 +32,7 @@ namespace gua { -class Directory { +class GUA_DLL Directory { public: diff --git a/include/gua/utils/DotGenerator.hpp b/include/gua/utils/DotGenerator.hpp index c91ea0328..e53e34581 100644 --- a/include/gua/utils/DotGenerator.hpp +++ b/include/gua/utils/DotGenerator.hpp @@ -27,6 +27,7 @@ #include // guacamole header +#include #include namespace gua { @@ -34,7 +35,6 @@ namespace gua { class SceneGraph; class Node; -class ViewNode; class GeometryNode; class PointLightNode; class ScreenNode; @@ -43,7 +43,7 @@ class SpotLightNode; /** * This class may be used to parse a path. */ -class DotGenerator : public NodeVisitor { +class GUA_DLL DotGenerator : public NodeVisitor { public: DotGenerator(); @@ -65,9 +65,9 @@ class DotGenerator : public NodeVisitor { * Visiters for each Node type */ /*virtual*/ void visit(Node* node); - /*virtual*/ void visit(GroupNode* cam); - /*virtual*/ void visit(ViewNode* cam); + /*virtual*/ void visit(TransformNode* cam); /*virtual*/ void visit(GeometryNode* geometry); + /*virtual*/ void visit(VolumeNode* volume); /*virtual*/ void visit(PointLightNode* pointlight); /*virtual*/ void visit(ScreenNode* screen); /*virtual*/ void visit(SpotLightNode* spotlight); diff --git a/include/gua/utils/FpsCounter.hpp b/include/gua/utils/FpsCounter.hpp index 841a48b1d..94609dde4 100644 --- a/include/gua/utils/FpsCounter.hpp +++ b/include/gua/utils/FpsCounter.hpp @@ -22,11 +22,12 @@ #ifndef GUA_FPS_COUNTER_HPP #define GUA_FPS_COUNTER_HPP +#include #include namespace gua { -struct FpsCounter +struct GUA_DLL FpsCounter { FpsCounter(unsigned t) : fps(0.0f), frame_count(0), timer(), delay(t) {} void step() { diff --git a/include/gua/utils/KDTreeUtils.hpp b/include/gua/utils/KDTreeUtils.hpp index 008af0b34..81fa1a531 100644 --- a/include/gua/utils/KDTreeUtils.hpp +++ b/include/gua/utils/KDTreeUtils.hpp @@ -41,8 +41,6 @@ struct Ray { Ray(); Ray(math::vec3 const& origin, math::vec3 const& direction, float t_max); - std::pair intersect( - math::BoundingBox const& box) const; Ray const intersection(math::BoundingBox const& box) const; math::vec3 origin_; @@ -52,6 +50,9 @@ struct Ray { static const float END; }; +std::pair intersect(Ray const& ray, + math::BoundingBox const& box); + /** * This helper class represents a triangle. * diff --git a/include/gua/utils/Mask.hpp b/include/gua/utils/Mask.hpp index 020926822..8e4f8e20b 100644 --- a/include/gua/utils/Mask.hpp +++ b/include/gua/utils/Mask.hpp @@ -27,6 +27,8 @@ #include #include +#include + namespace gua { /** @@ -43,7 +45,7 @@ namespace gua { * ) --- closing parenthesis * Whitespaces are ignored and all other characters are treated as group names. */ -class Mask { +class GUA_DLL Mask { public: /** diff --git a/include/gua/utils/Profiler.hpp b/include/gua/utils/Profiler.hpp index 6598d621f..63681a6df 100644 --- a/include/gua/utils/Profiler.hpp +++ b/include/gua/utils/Profiler.hpp @@ -23,6 +23,7 @@ #define GUA_PROFILER_HPP // guacamole headers +#include #include // external headers @@ -37,7 +38,7 @@ namespace gua { * * */ -class Profiler { +class GUA_DLL Profiler { public: class Timer { diff --git a/include/gua/utils/Timer.hpp b/include/gua/utils/Timer.hpp index 0edd52c4f..f092f5d55 100644 --- a/include/gua/utils/Timer.hpp +++ b/include/gua/utils/Timer.hpp @@ -24,13 +24,15 @@ #include +#include + /** * */ namespace gua { -class Timer { +class GUA_DLL Timer { public: void start(); diff --git a/include/gua/utils/configuration_macro.hpp b/include/gua/utils/configuration_macro.hpp index 8858563b1..8766b27a7 100644 --- a/include/gua/utils/configuration_macro.hpp +++ b/include/gua/utils/configuration_macro.hpp @@ -22,18 +22,23 @@ #ifndef GUA_ADD_PROPERTY_HPP #define GUA_ADD_PROPERTY_HPP -#define GUA_ADD_PROPERTY(TYPE, NAME, VALUE) \ - struct NAME##_struct { \ - public: \ - NAME##_struct() : val_(VALUE) {} \ - NAME##_struct(TYPE const& val) : val_(val) {} \ - \ - TYPE& operator()() { return val_; } \ - TYPE const& operator()() const { return val_; } \ - private: \ - TYPE val_; \ - } NAME; \ - void set_##NAME(TYPE const & val) { NAME() = val; } \ +#define GUA_ADD_PROPERTY(TYPE, NAME, VALUE) \ + /** \cond */ \ + struct NAME##_struct { \ + public: \ + NAME##_struct() : val_(VALUE) {} \ + NAME##_struct(TYPE const& val) : val_(val) {} \ + \ + TYPE& operator()() { return val_; } \ + TYPE const& operator()() const { return val_; } \ + private: \ + TYPE val_; \ + } NAME; \ + /** \endcond */ \ + Configuration& set_##NAME(TYPE const & val) { NAME() = val; return *this; } \ + /** + The default value is VALUE. + */ \ TYPE const& get_##NAME() const { return NAME(); } #endif // GUA_ADD_PROPERTY_HPP diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt new file mode 100644 index 000000000..e6d6872f7 --- /dev/null +++ b/plugins/CMakeLists.txt @@ -0,0 +1,14 @@ +GET_SUBDIRECTORIES(_LIST_OF_PLUGINS ${CMAKE_CURRENT_SOURCE_DIR}) + +FOREACH (_PLUGIN ${_LIST_OF_PLUGINS}) + SET(PLUGIN_${_PLUGIN} false CACHE BOOL "Build module ${_PLUGIN}") + MESSAGE(STATUS "Found plugin ${_PLUGIN}") +ENDFOREACH (_PLUGIN) + +FOREACH (_PLUGIN ${_LIST_OF_PLUGINS}) + IF (NOT PLUGIN_${_PLUGIN}) + SET(PLUGIN_${_PLUGIN} false CACHE BOOL "Build module ${_PLUGIN}") + ELSEIF (${PLUGIN_${_PLUGIN}}) + add_subdirectory(${_PLUGIN}) + ENDIF (NOT PLUGIN_${_PLUGIN}) +ENDFOREACH (_PLUGIN) diff --git a/plugins/guacamole-oculus/.gitignore b/plugins/guacamole-oculus/.gitignore new file mode 100644 index 000000000..e69affda6 --- /dev/null +++ b/plugins/guacamole-oculus/.gitignore @@ -0,0 +1,9 @@ +*.out +build +*.gv +*.o +*.so +guacamole_editor +tags +*.sublime-workspace +.nfs* diff --git a/plugins/guacamole-oculus/CMakeLists.txt b/plugins/guacamole-oculus/CMakeLists.txt new file mode 100644 index 000000000..016b4603e --- /dev/null +++ b/plugins/guacamole-oculus/CMakeLists.txt @@ -0,0 +1,42 @@ +# dependencies +include(find_ovr) + +# determine source and header files +file(GLOB_RECURSE GUACAMOLE_OCULUS_SRC RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} + src/*.cpp + include/*.h + include/*.hpp +) + +SET(GUACAMOLE_OCULUS_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include) + +LINK_DIRECTORIES(${LIB_PATHS} ${OVR_LIBRARY_DIRS}) + +INCLUDE_DIRECTORIES( ${INCLUDE_PATHS} + ${GUACAMOLE_SOURCE_DIR} + ${OVR_INCLUDE_DIRS} + ${GUACAMOLE_OCULUS_SOURCE_DIR} +) + +ADD_LIBRARY( guacamole-oculus SHARED + ${GUACAMOLE_OCULUS_SRC} +) + +ADD_DEPENDENCIES(guacamole-oculus guacamole) + +IF (MSVC) + set_target_properties(guacamole-oculus PROPERTIES COMPILE_FLAGS "-D GUA_OCULUS_LIBRARY") +ENDIF (MSVC) + +IF (UNIX) + LIST(APPEND LIBS udev Xinerama guacamole ${OVR_LIBRARIES}) +ELSEIF (MSVC) + LIST(APPEND LIBS winmm.lib guacamole ${OVR_LIBRARIES}) +ENDIF(UNIX) + + +TARGET_LINK_LIBRARIES( guacamole-oculus debug ${LIBS} optimized ${LIBS}) + +# compile examples + +ADD_SUBDIRECTORY(example-oculus) diff --git a/plugins/guacamole-oculus/example-oculus/CMakeLists.txt b/plugins/guacamole-oculus/example-oculus/CMakeLists.txt new file mode 100644 index 000000000..2d854eacf --- /dev/null +++ b/plugins/guacamole-oculus/example-oculus/CMakeLists.txt @@ -0,0 +1,38 @@ +# determine source and header files +file(GLOB_RECURSE EXAMPLE_SRC RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.c *.cpp *.cc) + +GET_FILENAME_COMPONENT(_EXE_NAME ${CMAKE_CURRENT_SOURCE_DIR} NAME) + +SET(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_SOURCE_DIR}) + +LIST(APPEND LIB_PATHS ${CMAKE_SOURCE_DIR}/lib) + +LINK_DIRECTORIES(${LIB_PATHS}) + +INCLUDE_DIRECTORIES( ${INCLUDE_PATHS} + ${GUACAMOLE_SOURCE_DIR} + ${OVR_INCLUDE_DIRS} + ${GUACAMOLE_OCULUS_SOURCE_DIR} +) + +ADD_EXECUTABLE( ${_EXE_NAME} + ${EXAMPLE_SRC} +) + +ADD_DEPENDENCIES(${_EXE_NAME} guacamole-oculus) + +LIST(APPEND LIBS guacamole-oculus guacamole ${OVR_LIBRARIES}) + +TARGET_LINK_LIBRARIES( ${_EXE_NAME} debug ${LIBS} optimized ${LIBS}) + +# copy runtime libraries as a post-build process +IF (MSVC) + + COPY_RUNTIME_DEPENDENCIES ( ${_EXE_NAME} \"${GLOBAL_EXT_DIR}/bin/$(Configuration)/\" \"${EXECUTABLE_OUTPUT_PATH}/$(Configuration)/\") + COPY_RUNTIME_DEPENDENCIES ( ${_EXE_NAME} \"${LIBRARY_OUTPUT_PATH}/$(Configuration)/\" \"${EXECUTABLE_OUTPUT_PATH}/$(Configuration)/\") + + FOREACH (_LIB_DIR ${GUACAMOLE_LIBRARY_DIRS}) + COPY_RUNTIME_DEPENDENCIES ( ${_EXE_NAME} \"${_LIB_DIR}/$(Configuration)/\" \"${EXECUTABLE_OUTPUT_PATH}/$(Configuration)/\") + ENDFOREACH (_LIB_DIR ${GUACAMOLE_LIBRARY_DIRS}) + +ENDIF (MSVC) \ No newline at end of file diff --git a/plugins/guacamole-oculus/example-oculus/data/materials/ComplexTexture.gsd b/plugins/guacamole-oculus/example-oculus/data/materials/ComplexTexture.gsd new file mode 100644 index 000000000..853e91dc1 --- /dev/null +++ b/plugins/guacamole-oculus/example-oculus/data/materials/ComplexTexture.gsd @@ -0,0 +1,55 @@ + +{ + "final_shading_stage" : + { + "body" : "vec3 diffuse = texture2D(diffuse_map, texcoords).rgb;\n\ngua_color = diffuse * emit + (1.0 - emit) * \n my_diffuse_color * diffuse + my_specular_intensity;\n", + "functions" : "", + "outputs" : null, + "uniforms" : + { + "diffuse_map" : "sampler2D", + "emit" : "float" + } + }, + "gbuffer_fragment_stage" : + { + "body" : "vec3 ts_normal = normalize(texture2D(normal_map, my_texcoords).rgb * 2.0 - 1.0);\n\ngua_normal = normalize( my_tangent * ts_normal.x + my_bitangent * \n ts_normal.y + my_normal * ts_normal.z);\n \ntexcoords = my_texcoords;", + "functions" : "", + "outputs" : + { + "texcoords" : "vec2" + }, + "uniforms" : + { + "normal_map" : "sampler2D" + } + }, + "gbuffer_vertex_stage" : + { + "body" : "my_tangent = gua_world_tangent;\nmy_texcoords = gua_texcoords;\nmy_bitangent = gua_world_bitangent;\nmy_normal = gua_world_normal;\n\ngua_position = gua_world_position;", + "functions" : "", + "outputs" : + { + "my_bitangent" : "vec3", + "my_normal" : "vec3", + "my_tangent" : "vec3", + "my_texcoords" : "vec2" + }, + "uniforms" : null + }, + "lbuffer_stage" : + { + "body" : "my_diffuse_color = my_dot(gua_normal, gua_light_direction) * \n gua_light_intensity * gua_light_color;\n \nfloat spec = texture2D(specular_map, texcoords).x;\n\nmy_specular_intensity = spec * pow(max(0, dot(\n reflect(gua_light_direction, gua_normal), \n normalize(gua_position - gua_camera_position)\n )), shinyness) * gua_light_intensity;", + "functions" : "float my_dot(vec3 a, vec3 b) {\n return dot(a, b);\n}", + "outputs" : + { + "my_diffuse_color" : "vec3", + "my_specular_intensity" : "float" + }, + "uniforms" : + { + "shinyness" : "float", + "specular_map" : "sampler2D" + } + } +} diff --git a/plugins/guacamole-oculus/example-oculus/data/materials/Shadeless.gsd b/plugins/guacamole-oculus/example-oculus/data/materials/Shadeless.gsd new file mode 100644 index 000000000..ac17b1eda --- /dev/null +++ b/plugins/guacamole-oculus/example-oculus/data/materials/Shadeless.gsd @@ -0,0 +1,41 @@ + +{ + "final_shading_stage" : + { + "body" : "gua_color = diffuse_color;\n", + "functions" : "", + "outputs" : null, + "uniforms" : + { + "diffuse_color" : "vec3" + } + }, + "gbuffer_fragment_stage" : + { + "body" : "gua_normal = varying_normal;\n", + "functions" : "", + "outputs" : null, + "uniforms" : null + }, + "gbuffer_vertex_stage" : + { + "body" : "gua_position = gua_world_position;\nvarying_normal = gua_world_normal;\n", + "functions" : "", + "outputs" : + { + "varying_normal" : "vec3" + }, + "uniforms" : null + }, + "lbuffer_stage" : + { + "body" : "", + "functions" : "", + "outputs" : + { + "diffuse" : "vec3", + "specular" : "float" + }, + "uniforms" : null + } +} diff --git a/plugins/guacamole-oculus/example-oculus/data/materials/Stones.gmd b/plugins/guacamole-oculus/example-oculus/data/materials/Stones.gmd new file mode 100644 index 000000000..66a05f4cf --- /dev/null +++ b/plugins/guacamole-oculus/example-oculus/data/materials/Stones.gmd @@ -0,0 +1,12 @@ + +{ + "shading_model" : "ComplexTexture.gsd", + "uniforms" : + { + "diffuse_map" : "data/textures/stones_diffuse.jpg", + "emit" : "0.1", + "normal_map" : "data/textures/stones_normal.jpg", + "shinyness" : "50", + "specular_map" : "data/textures/stones_specular.jpg" + } +} diff --git a/plugins/guacamole-oculus/example-oculus/data/materials/White.gmd b/plugins/guacamole-oculus/example-oculus/data/materials/White.gmd new file mode 100644 index 000000000..16b84b973 --- /dev/null +++ b/plugins/guacamole-oculus/example-oculus/data/materials/White.gmd @@ -0,0 +1,8 @@ + +{ + "shading_model" : "Shadeless.gsd", + "uniforms" : + { + "diffuse_color" : "(1.000 1.000 1.000)" + } +} diff --git a/plugins/guacamole-oculus/example-oculus/data/objects/light_sphere.obj b/plugins/guacamole-oculus/example-oculus/data/objects/light_sphere.obj new file mode 100644 index 000000000..4c00d38a2 --- /dev/null +++ b/plugins/guacamole-oculus/example-oculus/data/objects/light_sphere.obj @@ -0,0 +1,647 @@ +# Blender v2.62 (sub 4) OBJ File: '' +# www.blender.org +v 0.000000 -0.500000 0.000000 +v 0.361804 -0.223610 0.262863 +v -0.138194 -0.223610 0.425325 +v -0.447213 -0.223608 0.000000 +v -0.138194 -0.223610 -0.425325 +v 0.361804 -0.223610 -0.262863 +v 0.138194 0.223610 0.425325 +v -0.361804 0.223610 0.262863 +v -0.361804 0.223610 -0.262863 +v 0.138194 0.223610 -0.425325 +v 0.447213 0.223608 0.000000 +v 0.000000 0.500000 0.000000 +v 0.101590 -0.483975 0.073809 +v 0.212661 -0.425327 0.154506 +v 0.304773 -0.328759 0.221428 +v 0.265970 -0.251151 0.340856 +v 0.131434 -0.262869 0.404506 +v -0.014820 -0.251151 0.432092 +v -0.116411 -0.328760 0.358282 +v -0.081228 -0.425327 0.249998 +v -0.038803 -0.483975 0.119426 +v 0.101590 -0.483975 -0.073809 +v 0.212661 -0.425327 -0.154506 +v 0.304773 -0.328759 -0.221428 +v 0.406365 -0.251150 -0.147619 +v 0.425324 -0.262868 0.000000 +v 0.406365 -0.251150 0.147619 +v -0.241986 -0.251151 0.358282 +v -0.344095 -0.262868 0.249998 +v -0.415525 -0.251149 0.119427 +v -0.376721 -0.328757 0.000000 +v -0.262865 -0.425326 0.000000 +v -0.125573 -0.483974 0.000000 +v -0.415525 -0.251149 -0.119427 +v -0.344095 -0.262868 -0.249998 +v -0.241986 -0.251151 -0.358282 +v -0.116411 -0.328760 -0.358282 +v -0.081228 -0.425327 -0.249998 +v -0.038803 -0.483975 -0.119426 +v -0.014820 -0.251151 -0.432092 +v 0.131434 -0.262869 -0.404506 +v 0.265970 -0.251151 -0.340856 +v 0.430349 -0.125575 -0.221429 +v 0.475529 0.000000 -0.154506 +v 0.478313 0.125575 -0.073809 +v 0.478313 0.125575 0.073809 +v 0.475529 -0.000000 0.154506 +v 0.430349 -0.125575 0.221429 +v 0.343579 -0.125576 0.340858 +v 0.293893 0.000000 0.404508 +v 0.218003 0.125576 0.432094 +v 0.077608 0.125576 0.477711 +v 0.000000 -0.000000 0.500000 +v -0.077608 -0.125576 0.477711 +v -0.218003 -0.125576 0.432094 +v -0.293893 0.000000 0.404508 +v -0.343579 0.125576 0.340858 +v -0.430349 0.125575 0.221429 +v -0.475529 -0.000000 0.154506 +v -0.478313 -0.125575 0.073809 +v -0.478313 -0.125575 -0.073809 +v -0.475529 0.000000 -0.154506 +v -0.430349 0.125575 -0.221429 +v -0.343579 0.125576 -0.340858 +v -0.293893 -0.000000 -0.404508 +v -0.218003 -0.125576 -0.432094 +v -0.077608 -0.125576 -0.477711 +v 0.000000 0.000000 -0.500000 +v 0.077608 0.125576 -0.477711 +v 0.218003 0.125576 -0.432094 +v 0.293893 -0.000000 -0.404508 +v 0.343579 -0.125576 -0.340858 +v 0.415525 0.251149 0.119427 +v 0.344095 0.262868 0.249998 +v 0.241986 0.251151 0.358282 +v 0.014820 0.251151 0.432092 +v -0.131434 0.262869 0.404506 +v -0.265970 0.251151 0.340856 +v -0.406365 0.251150 0.147619 +v -0.425324 0.262868 0.000000 +v -0.406365 0.251150 -0.147619 +v -0.265970 0.251151 -0.340856 +v -0.131434 0.262869 -0.404506 +v 0.014820 0.251151 -0.432092 +v 0.241986 0.251151 -0.358282 +v 0.344095 0.262868 -0.249998 +v 0.415525 0.251149 -0.119427 +v 0.376721 0.328757 0.000000 +v 0.262865 0.425326 0.000000 +v 0.125573 0.483974 0.000000 +v 0.038803 0.483975 0.119426 +v 0.081228 0.425327 0.249998 +v 0.116411 0.328760 0.358282 +v -0.101590 0.483975 0.073809 +v -0.212661 0.425327 0.154506 +v -0.304773 0.328759 0.221428 +v -0.101590 0.483975 -0.073809 +v -0.212661 0.425327 -0.154506 +v -0.304773 0.328759 -0.221428 +v 0.038803 0.483975 -0.119426 +v 0.081228 0.425327 -0.249998 +v 0.116411 0.328760 -0.358282 +v 0.026395 -0.361806 0.344093 +v 0.069099 -0.447215 0.212660 +v 0.180902 -0.361805 0.293890 +v 0.335409 -0.361805 -0.081228 +v 0.335409 -0.361805 0.081229 +v 0.223605 -0.447214 0.000000 +v -0.319097 -0.361805 0.131432 +v -0.180901 -0.447214 0.131432 +v -0.223605 -0.361805 0.262864 +v -0.223605 -0.361806 -0.262864 +v -0.180901 -0.447214 -0.131431 +v -0.319097 -0.361805 -0.131431 +v 0.180902 -0.361806 -0.293890 +v 0.069098 -0.447215 -0.212661 +v 0.026395 -0.361805 -0.344093 +v 0.500000 0.000000 0.000000 +v 0.473607 -0.138198 0.081229 +v 0.473607 -0.138198 -0.081229 +v 0.154509 0.000000 0.475528 +v 0.069100 -0.138199 0.475527 +v 0.223608 -0.138199 0.425324 +v -0.404509 0.000000 0.293892 +v -0.430902 -0.138198 0.212662 +v -0.335410 -0.138199 0.344095 +v -0.404509 -0.000000 -0.293892 +v -0.335409 -0.138199 -0.344095 +v -0.430902 -0.138198 -0.212662 +v 0.154509 -0.000000 -0.475528 +v 0.223608 -0.138199 -0.425324 +v 0.069100 -0.138199 -0.475527 +v 0.335410 0.138198 0.344095 +v 0.404509 -0.000001 0.293891 +v 0.430902 0.138197 0.212662 +v -0.223608 0.138198 0.425324 +v -0.154509 -0.000000 0.475528 +v -0.069100 0.138198 0.475528 +v -0.473607 0.138198 -0.081229 +v -0.500000 0.000000 0.000000 +v -0.473606 0.138198 0.081229 +v -0.069099 0.138199 -0.475528 +v -0.154508 -0.000000 -0.475528 +v -0.223608 0.138199 -0.425324 +v 0.430902 0.138198 -0.212661 +v 0.404510 0.000000 -0.293891 +v 0.335410 0.138199 -0.344095 +v 0.180900 0.447215 0.131431 +v 0.223605 0.361806 0.262864 +v 0.319097 0.361805 0.131432 +v -0.069099 0.447215 0.212660 +v -0.180902 0.361806 0.293889 +v -0.026395 0.361806 0.344092 +v -0.223605 0.447215 0.000000 +v -0.335408 0.361805 -0.081229 +v -0.335408 0.361805 0.081229 +v -0.069099 0.447215 -0.212660 +v -0.026395 0.361806 -0.344092 +v -0.180902 0.361806 -0.293889 +v 0.180900 0.447215 -0.131431 +v 0.319097 0.361805 -0.131432 +v 0.223605 0.361806 -0.262864 +vn 0.000000 1.000000 0.000000 +vn 0.080569 0.965392 -0.247963 +vn -0.210944 0.965392 -0.153264 +vn -0.723594 0.447218 -0.525712 +vn -0.815180 0.503800 -0.285714 +vn -0.604205 0.664968 -0.438978 +vn 0.260750 0.965392 0.000000 +vn 0.080569 0.965392 0.247963 +vn -0.210944 0.965392 0.153264 +vn -0.864986 0.243049 -0.438978 +vn 0.276376 0.447218 -0.850642 +vn 0.150212 0.243049 -0.958281 +vn 0.019837 0.503800 -0.863552 +vn 0.894406 0.447188 0.000000 +vn 0.957823 0.243049 -0.153264 +vn 0.827448 0.503800 -0.247963 +vn 0.276376 0.447218 0.850642 +vn 0.441725 0.243049 0.863582 +vn 0.491531 0.503800 0.710288 +vn -0.723594 0.447218 0.525712 +vn -0.684805 0.243049 0.686972 +vn -0.523637 0.503800 0.686972 +vn -0.684805 0.243049 -0.686972 +vn 0.441725 0.243049 -0.863582 +vn 0.957823 0.243049 0.153264 +vn 0.150212 0.243049 0.958281 +vn -0.864986 0.243049 0.438978 +vn -0.276376 -0.447218 -0.850642 +vn -0.230781 -0.664968 -0.710288 +vn -0.491531 -0.503800 -0.710288 +vn 0.723594 -0.447218 -0.525712 +vn 0.604205 -0.664968 -0.438978 +vn 0.523637 -0.503800 -0.686972 +vn 0.723594 -0.447218 0.525712 +vn 0.604205 -0.664968 0.438978 +vn 0.815180 -0.503800 0.285714 +vn -0.276376 -0.447218 0.850642 +vn -0.230781 -0.664968 0.710288 +vn -0.019837 -0.503800 0.863552 +vn -0.894406 -0.447188 0.000000 +vn -0.746849 -0.664968 0.000000 +vn -0.827448 -0.503800 0.247963 +vn 0.230781 0.664968 -0.710288 +vn 0.162450 0.850642 -0.499985 +vn -0.059206 0.727531 -0.683493 +vn -0.140629 0.890408 -0.432844 +vn -0.262856 0.525712 -0.808985 +vn -0.353832 0.727531 -0.587756 +vn -0.523637 0.503800 -0.686972 +vn -0.425306 0.850642 -0.309000 +vn -0.815180 0.503800 0.285714 +vn -0.604205 0.664968 0.438978 +vn -0.850642 0.525712 0.000000 +vn -0.668325 0.727531 0.154881 +vn -0.668325 0.727531 -0.154881 +vn -0.425306 0.850642 0.309000 +vn -0.455123 0.890408 0.000000 +vn 0.746849 0.664968 0.000000 +vn 0.525712 0.850642 0.000000 +vn 0.631733 0.727531 -0.267495 +vn 0.368206 0.890408 -0.267495 +vn 0.688162 0.525712 -0.499985 +vn 0.449629 0.727531 -0.518143 +vn 0.491531 0.503800 -0.710288 +vn 0.230781 0.664968 0.710288 +vn 0.162450 0.850642 0.499985 +vn 0.449629 0.727531 0.518143 +vn 0.368206 0.890408 0.267495 +vn 0.688162 0.525712 0.499985 +vn 0.631733 0.727531 0.267495 +vn 0.827448 0.503800 0.247963 +vn -0.353832 0.727531 0.587756 +vn -0.140629 0.890408 0.432844 +vn -0.262856 0.525712 0.808985 +vn -0.059206 0.727531 0.683493 +vn 0.019837 0.503800 0.863552 +vn -0.957823 -0.243049 -0.153264 +vn -0.957823 -0.243049 0.153264 +vn -0.951048 0.000000 -0.309000 +vn -0.999939 0.008850 0.000000 +vn -0.949614 0.272408 -0.154881 +vn -0.951048 0.000000 0.309000 +vn -0.949614 0.272408 0.154881 +vn -0.150212 -0.243049 -0.958281 +vn -0.441725 -0.243049 -0.863582 +vn 0.000000 0.000000 -1.000000 +vn -0.309000 0.008850 -0.951018 +vn -0.146123 0.272408 -0.950987 +vn -0.587756 0.000000 -0.809015 +vn -0.440748 0.272408 -0.855251 +vn 0.864986 -0.243049 -0.438978 +vn 0.684805 -0.243049 -0.686972 +vn 0.951048 0.000000 -0.309000 +vn 0.808985 0.008850 -0.587756 +vn 0.859310 0.272408 -0.432844 +vn 0.587756 0.000000 -0.809015 +vn 0.677206 0.272408 -0.683493 +vn 0.684805 -0.243049 0.686972 +vn 0.864986 -0.243049 0.438978 +vn 0.587756 0.000000 0.809015 +vn 0.808985 0.008850 0.587756 +vn 0.677206 0.272408 0.683493 +vn 0.951048 0.000000 0.309000 +vn 0.859310 0.272408 0.432844 +vn -0.441725 -0.243049 0.863582 +vn -0.150212 -0.243049 0.958281 +vn -0.587756 0.000000 0.809015 +vn -0.309000 0.008850 0.951018 +vn -0.440748 0.272408 0.855251 +vn 0.000000 0.000000 1.000000 +vn -0.146123 0.272408 0.950987 +vn -0.677206 -0.272408 -0.683493 +vn -0.808985 -0.008850 -0.587756 +vn -0.688162 -0.525712 -0.499985 +vn -0.859310 -0.272408 -0.432844 +vn -0.827448 -0.503800 -0.247963 +vn 0.440748 -0.272408 -0.855251 +vn 0.309000 -0.008850 -0.951018 +vn 0.262856 -0.525712 -0.808985 +vn 0.146123 -0.272408 -0.950987 +vn -0.019837 -0.503800 -0.863552 +vn 0.949614 -0.272408 0.154881 +vn 0.999939 -0.008850 0.000000 +vn 0.850642 -0.525712 0.000000 +vn 0.949614 -0.272408 -0.154881 +vn 0.815180 -0.503800 -0.285714 +vn 0.146123 -0.272408 0.951018 +vn 0.309000 -0.008850 0.951018 +vn 0.262856 -0.525712 0.808985 +vn 0.440748 -0.272408 0.855251 +vn 0.523637 -0.503800 0.686972 +vn -0.859310 -0.272408 0.432844 +vn -0.808985 -0.008850 0.587756 +vn -0.688162 -0.525712 0.499985 +vn -0.677206 -0.272408 0.683493 +vn -0.491531 -0.503800 0.710288 +vn -0.080569 -0.965392 -0.247963 +vn 0.000000 -1.000000 0.000000 +vn -0.260750 -0.965392 0.000000 +vn -0.162450 -0.850642 -0.499985 +vn -0.368206 -0.890408 -0.267495 +vn -0.449629 -0.727531 -0.518143 +vn -0.525712 -0.850642 0.000000 +vn -0.631733 -0.727531 -0.267495 +vn 0.210944 -0.965392 -0.153264 +vn 0.425306 -0.850642 -0.309000 +vn 0.140629 -0.890408 -0.432844 +vn 0.353832 -0.727531 -0.587725 +vn 0.059206 -0.727531 -0.683493 +vn 0.210944 -0.965392 0.153264 +vn 0.425306 -0.850642 0.309000 +vn 0.455123 -0.890408 0.000000 +vn 0.668325 -0.727531 0.154881 +vn 0.668325 -0.727531 -0.154881 +vn -0.080569 -0.965392 0.247963 +vn -0.162450 -0.850642 0.499985 +vn 0.140629 -0.890408 0.432844 +vn 0.059206 -0.727531 0.683493 +vn 0.353832 -0.727531 0.587725 +vn -0.368206 -0.890408 0.267495 +vn -0.631733 -0.727531 0.267495 +vn -0.449629 -0.727531 0.518143 +s 1 +f 1//1 21//2 13//3 +f 2//4 27//5 15//6 +f 1//1 33//7 21//2 +f 1//1 39//8 33//7 +f 1//1 22//9 39//8 +f 2//4 48//10 27//5 +f 3//11 54//12 18//13 +f 4//14 60//15 30//16 +f 5//17 66//18 36//19 +f 6//20 72//21 42//22 +f 2//4 49//23 48//10 +f 3//11 55//24 54//12 +f 4//14 61//25 60//15 +f 5//17 67//26 66//18 +f 6//20 43//27 72//21 +f 7//28 93//29 75//30 +f 8//31 96//32 78//33 +f 9//34 99//35 81//36 +f 10//37 102//38 84//39 +f 11//40 88//41 87//42 +f 19//43 3//11 18//13 +f 20//44 19//43 103//45 +f 21//2 20//44 104//46 +f 19//43 18//13 103//45 +f 103//45 18//13 17//47 +f 20//44 103//45 104//46 +f 104//46 103//45 105//48 +f 103//45 17//47 105//48 +f 105//48 17//47 16//49 +f 21//2 104//46 13//3 +f 13//3 104//46 14//50 +f 104//46 105//48 14//50 +f 14//50 105//48 15//6 +f 105//48 16//49 15//6 +f 15//6 16//49 2//4 +f 25//51 6//20 24//52 +f 26//53 25//51 106//54 +f 27//5 26//53 107//55 +f 25//51 24//52 106//54 +f 106//54 24//52 23//56 +f 26//53 106//54 107//55 +f 107//55 106//54 108//57 +f 106//54 23//56 108//57 +f 108//57 23//56 22//9 +f 27//5 107//55 15//6 +f 15//6 107//55 14//50 +f 107//55 108//57 14//50 +f 14//50 108//57 13//3 +f 108//57 22//9 13//3 +f 22//9 1//1 13//3 +f 31//58 4//14 30//16 +f 32//59 31//58 109//60 +f 33//7 32//59 110//61 +f 31//58 30//16 109//60 +f 109//60 30//16 29//62 +f 32//59 109//60 110//61 +f 110//61 109//60 111//63 +f 109//60 29//62 111//63 +f 111//63 29//62 28//64 +f 33//7 110//61 21//2 +f 21//2 110//61 20//44 +f 110//61 111//63 20//44 +f 20//44 111//63 19//43 +f 111//63 28//64 19//43 +f 19//43 28//64 3//11 +f 37//65 5//17 36//19 +f 38//66 37//65 112//67 +f 39//8 38//66 113//68 +f 37//65 36//19 112//67 +f 112//67 36//19 35//69 +f 38//66 112//67 113//68 +f 113//68 112//67 114//70 +f 112//67 35//69 114//70 +f 114//70 35//69 34//71 +f 39//8 113//68 33//7 +f 33//7 113//68 32//59 +f 113//68 114//70 32//59 +f 32//59 114//70 31//58 +f 114//70 34//71 31//58 +f 31//58 34//71 4//14 +f 24//52 6//20 42//22 +f 23//56 24//52 115//72 +f 22//9 23//56 116//73 +f 24//52 42//22 115//72 +f 115//72 42//22 41//74 +f 23//56 115//72 116//73 +f 116//73 115//72 117//75 +f 115//72 41//74 117//75 +f 117//75 41//74 40//76 +f 22//9 116//73 39//8 +f 39//8 116//73 38//66 +f 116//73 117//75 38//66 +f 38//66 117//75 37//65 +f 117//75 40//76 37//65 +f 37//65 40//76 5//17 +f 46//77 11//40 45//78 +f 47//79 46//77 118//80 +f 48//10 47//79 119//81 +f 46//77 45//78 118//80 +f 118//80 45//78 44//82 +f 47//79 118//80 119//81 +f 119//81 118//80 120//83 +f 118//80 44//82 120//83 +f 120//83 44//82 43//27 +f 48//10 119//81 27//5 +f 27//5 119//81 26//53 +f 119//81 120//83 26//53 +f 26//53 120//83 25//51 +f 120//83 43//27 25//51 +f 25//51 43//27 6//20 +f 52//84 7//28 51//85 +f 53//86 52//84 121//87 +f 54//12 53//86 122//88 +f 52//84 51//85 121//87 +f 121//87 51//85 50//89 +f 53//86 121//87 122//88 +f 122//88 121//87 123//90 +f 121//87 50//89 123//90 +f 123//90 50//89 49//23 +f 54//12 122//88 18//13 +f 18//13 122//88 17//47 +f 122//88 123//90 17//47 +f 17//47 123//90 16//49 +f 123//90 49//23 16//49 +f 16//49 49//23 2//4 +f 58//91 8//31 57//92 +f 59//93 58//91 124//94 +f 60//15 59//93 125//95 +f 58//91 57//92 124//94 +f 124//94 57//92 56//96 +f 59//93 124//94 125//95 +f 125//95 124//94 126//97 +f 124//94 56//96 126//97 +f 126//97 56//96 55//24 +f 60//15 125//95 30//16 +f 30//16 125//95 29//62 +f 125//95 126//97 29//62 +f 29//62 126//97 28//64 +f 126//97 55//24 28//64 +f 28//64 55//24 3//11 +f 64//98 9//34 63//99 +f 65//100 64//98 127//101 +f 66//18 65//100 128//102 +f 64//98 63//99 127//101 +f 127//101 63//99 62//103 +f 65//100 127//101 128//102 +f 128//102 127//101 129//104 +f 127//101 62//103 129//104 +f 129//104 62//103 61//25 +f 66//18 128//102 36//19 +f 36//19 128//102 35//69 +f 128//102 129//104 35//69 +f 35//69 129//104 34//71 +f 129//104 61//25 34//71 +f 34//71 61//25 4//14 +f 70//105 10//37 69//106 +f 71//107 70//105 130//108 +f 72//21 71//107 131//109 +f 70//105 69//106 130//108 +f 130//108 69//106 68//110 +f 71//107 130//108 131//109 +f 131//109 130//108 132//111 +f 130//108 68//110 132//111 +f 132//111 68//110 67//26 +f 72//21 131//109 42//22 +f 42//22 131//109 41//74 +f 131//109 132//111 41//74 +f 41//74 132//111 40//76 +f 132//111 67//26 40//76 +f 40//76 67//26 5//17 +f 51//85 7//28 75//30 +f 50//89 51//85 133//112 +f 49//23 50//89 134//113 +f 51//85 75//30 133//112 +f 133//112 75//30 74//114 +f 50//89 133//112 134//113 +f 134//113 133//112 135//115 +f 133//112 74//114 135//115 +f 135//115 74//114 73//116 +f 49//23 134//113 48//10 +f 48//10 134//113 47//79 +f 134//113 135//115 47//79 +f 47//79 135//115 46//77 +f 135//115 73//116 46//77 +f 46//77 73//116 11//40 +f 57//92 8//31 78//33 +f 56//96 57//92 136//117 +f 55//24 56//96 137//118 +f 57//92 78//33 136//117 +f 136//117 78//33 77//119 +f 56//96 136//117 137//118 +f 137//118 136//117 138//120 +f 136//117 77//119 138//120 +f 138//120 77//119 76//121 +f 55//24 137//118 54//12 +f 54//12 137//118 53//86 +f 137//118 138//120 53//86 +f 53//86 138//120 52//84 +f 138//120 76//121 52//84 +f 52//84 76//121 7//28 +f 63//99 9//34 81//36 +f 62//103 63//99 139//122 +f 61//25 62//103 140//123 +f 63//99 81//36 139//122 +f 139//122 81//36 80//124 +f 62//103 139//122 140//123 +f 140//123 139//122 141//125 +f 139//122 80//124 141//125 +f 141//125 80//124 79//126 +f 61//25 140//123 60//15 +f 60//15 140//123 59//93 +f 140//123 141//125 59//93 +f 59//93 141//125 58//91 +f 141//125 79//126 58//91 +f 58//91 79//126 8//31 +f 69//106 10//37 84//39 +f 68//110 69//106 142//127 +f 67//26 68//110 143//128 +f 69//106 84//39 142//127 +f 142//127 84//39 83//129 +f 68//110 142//127 143//128 +f 143//128 142//127 144//130 +f 142//127 83//129 144//130 +f 144//130 83//129 82//131 +f 67//26 143//128 66//18 +f 66//18 143//128 65//100 +f 143//128 144//130 65//100 +f 65//100 144//130 64//98 +f 144//130 82//131 64//98 +f 64//98 82//131 9//34 +f 45//78 11//40 87//42 +f 44//82 45//78 145//132 +f 43//27 44//82 146//133 +f 45//78 87//42 145//132 +f 145//132 87//42 86//134 +f 44//82 145//132 146//133 +f 146//133 145//132 147//135 +f 145//132 86//134 147//135 +f 147//135 86//134 85//136 +f 43//27 146//133 72//21 +f 72//21 146//133 71//107 +f 146//133 147//135 71//107 +f 71//107 147//135 70//105 +f 147//135 85//136 70//105 +f 70//105 85//136 10//37 +f 91//137 12//138 90//139 +f 92//140 91//137 148//141 +f 93//29 92//140 149//142 +f 91//137 90//139 148//141 +f 148//141 90//139 89//143 +f 92//140 148//141 149//142 +f 149//142 148//141 150//144 +f 148//141 89//143 150//144 +f 150//144 89//143 88//41 +f 93//29 149//142 75//30 +f 75//30 149//142 74//114 +f 149//142 150//144 74//114 +f 74//114 150//144 73//116 +f 150//144 88//41 73//116 +f 73//116 88//41 11//40 +f 94//145 12//138 91//137 +f 95//146 94//145 151//147 +f 96//32 95//146 152//148 +f 94//145 91//137 151//147 +f 151//147 91//137 92//140 +f 95//146 151//147 152//148 +f 152//148 151//147 153//149 +f 151//147 92//140 153//149 +f 153//149 92//140 93//29 +f 96//32 152//148 78//33 +f 78//33 152//148 77//119 +f 152//148 153//149 77//119 +f 77//119 153//149 76//121 +f 153//149 93//29 76//121 +f 76//121 93//29 7//28 +f 97//150 12//138 94//145 +f 98//151 97//150 154//152 +f 99//35 98//151 155//153 +f 97//150 94//145 154//152 +f 154//152 94//145 95//146 +f 98//151 154//152 155//153 +f 155//153 154//152 156//154 +f 154//152 95//146 156//154 +f 156//154 95//146 96//32 +f 99//35 155//153 81//36 +f 81//36 155//153 80//124 +f 155//153 156//154 80//124 +f 80//124 156//154 79//126 +f 156//154 96//32 79//126 +f 79//126 96//32 8//31 +f 100//155 12//138 97//150 +f 101//156 100//155 157//157 +f 102//38 101//156 158//158 +f 100//155 97//150 157//157 +f 157//157 97//150 98//151 +f 101//156 157//157 158//158 +f 158//158 157//157 159//159 +f 157//157 98//151 159//159 +f 159//159 98//151 99//35 +f 102//38 158//158 84//39 +f 84//39 158//158 83//129 +f 158//158 159//159 83//129 +f 83//129 159//159 82//131 +f 159//159 99//35 82//131 +f 82//131 99//35 9//34 +f 90//139 12//138 100//155 +f 89//143 90//139 160//160 +f 88//41 89//143 161//161 +f 90//139 100//155 160//160 +f 160//160 100//155 101//156 +f 89//143 160//160 161//161 +f 161//161 160//160 162//162 +f 160//160 101//156 162//162 +f 162//162 101//156 102//38 +f 88//41 161//161 87//42 +f 87//42 161//161 86//134 +f 161//161 162//162 86//134 +f 86//134 162//162 85//136 +f 162//162 102//38 85//136 +f 85//136 102//38 10//37 diff --git a/plugins/guacamole-oculus/example-oculus/data/objects/monkey.obj b/plugins/guacamole-oculus/example-oculus/data/objects/monkey.obj new file mode 100644 index 000000000..9f4cdfbac --- /dev/null +++ b/plugins/guacamole-oculus/example-oculus/data/objects/monkey.obj @@ -0,0 +1,10833 @@ +# Blender v2.58 (sub 0) OBJ File: '' +# www.blender.org +o Monkey +v 0.492188 0.185547 0.720703 +v -0.492188 0.185547 0.720703 +v 0.558594 0.158203 0.625000 +v -0.558594 0.158203 0.625000 +v 0.437500 0.039063 0.650391 +v -0.437500 0.039063 0.650391 +v 0.410156 0.105469 0.738281 +v -0.410156 0.105469 0.738281 +v 0.294922 0.105469 0.759766 +v -0.294922 0.105469 0.759766 +v 0.265625 0.039063 0.681641 +v -0.265625 0.039063 0.681641 +v 0.144531 0.158203 0.697266 +v -0.144531 0.158203 0.697266 +v 0.214844 0.185547 0.769531 +v -0.214844 0.185547 0.769531 +v 0.214844 0.300781 0.769531 +v -0.214844 0.300781 0.769531 +v 0.144531 0.328125 0.697266 +v -0.144531 0.328125 0.697266 +v 0.265625 0.449219 0.681641 +v -0.265625 0.449219 0.681641 +v 0.294922 0.382813 0.759766 +v -0.294922 0.382813 0.759766 +v 0.410156 0.382813 0.738281 +v -0.410156 0.382813 0.738281 +v 0.437500 0.449219 0.650391 +v -0.437500 0.449219 0.650391 +v 0.558594 0.328125 0.625000 +v -0.558594 0.328125 0.625000 +v 0.492188 0.300781 0.720703 +v -0.492188 0.300781 0.720703 +v 0.457031 0.287109 0.769531 +v -0.457031 0.287109 0.769531 +v 0.396484 0.349609 0.783203 +v -0.396484 0.349609 0.783203 +v 0.310547 0.349609 0.800781 +v -0.310547 0.349609 0.800781 +v 0.251953 0.287109 0.808594 +v -0.251953 0.287109 0.808594 +v 0.251953 0.201172 0.808594 +v -0.251953 0.201172 0.808594 +v 0.310547 0.142578 0.800781 +v -0.310547 0.142578 0.800781 +v 0.396484 0.142578 0.783203 +v -0.396484 0.142578 0.783203 +v 0.457031 0.201172 0.769531 +v -0.457031 0.201172 0.769531 +v 0.424479 0.213542 0.794271 +v -0.424479 0.213542 0.794271 +v 0.382812 0.171875 0.804688 +v -0.382812 0.171875 0.804688 +v 0.322917 0.171875 0.817708 +v -0.322917 0.171875 0.817708 +v 0.281250 0.213542 0.822917 +v -0.281250 0.213542 0.822917 +v 0.281250 0.273438 0.822917 +v -0.281250 0.273438 0.822917 +v 0.322917 0.317708 0.817708 +v -0.322917 0.317708 0.817708 +v 0.382812 0.317708 0.804688 +v -0.382812 0.317708 0.804688 +v 0.424479 0.273438 0.794271 +v -0.424479 0.273438 0.794271 +v 0.085938 -0.957031 0.601563 +v -0.085938 -0.957031 0.601563 +v 0.226562 -0.939453 0.585938 +v -0.226562 -0.939453 0.585938 +v 0.298828 -0.892578 0.587891 +v -0.298828 -0.892578 0.587891 +v 0.308594 -0.777344 0.613281 +v -0.308594 -0.777344 0.613281 +v 0.281250 -0.570312 0.634766 +v -0.281250 -0.570312 0.634766 +v 0.291016 -0.119141 0.644531 +v -0.291016 -0.119141 0.644531 +v 0.521484 -0.042969 0.591797 +v -0.521484 -0.042969 0.591797 +v 0.701172 0.091797 0.552734 +v -0.701172 0.091797 0.552734 +v 0.789062 0.289063 0.574219 +v -0.789062 0.289063 0.574219 +v 0.750000 0.425781 0.650391 +v -0.750000 0.425781 0.650391 +v 0.582031 0.511719 0.708984 +v -0.582031 0.511719 0.708984 +v 0.390625 0.636719 0.763672 +v -0.390625 0.636719 0.763672 +v 0.248047 0.683594 0.794922 +v -0.248047 0.683594 0.794922 +v 0.130859 0.564453 0.800781 +v -0.130859 0.564453 0.800781 +v 0.041016 0.425781 0.789062 +v -0.041016 0.425781 0.789062 +v 0.179688 0.482422 0.806641 +v -0.179688 0.482422 0.806641 +v 0.273438 0.550781 0.796875 +v -0.273438 0.550781 0.796875 +v 0.376953 0.525391 0.773437 +v -0.376953 0.525391 0.773437 +v 0.539062 0.443359 0.726562 +v -0.539062 0.443359 0.726562 +v 0.667969 0.365234 0.673828 +v -0.667969 0.365234 0.673828 +v 0.683594 0.265625 0.638672 +v -0.683594 0.265625 0.638672 +v 0.615234 0.126953 0.636719 +v -0.615234 0.126953 0.636719 +v 0.470703 0.021484 0.667969 +v -0.470703 0.021484 0.667969 +v 0.275391 -0.009766 0.732422 +v -0.275391 -0.009766 0.732422 +v 0.123047 0.044922 0.757812 +v -0.123047 0.044922 0.757812 +v 0.097656 0.375000 0.800781 +v -0.097656 0.375000 0.800781 +v 0.064453 0.269531 0.777344 +v -0.064453 0.269531 0.777344 +v 0.074219 0.152344 0.750000 +v -0.074219 0.152344 0.750000 +v 0.056641 -0.912109 0.664063 +v -0.056641 -0.912109 0.664063 +v 0.144531 -0.890625 0.667969 +v -0.144531 -0.890625 0.667969 +v 0.181641 -0.822266 0.685547 +v -0.181641 -0.822266 0.685547 +v 0.164062 -0.570312 0.720703 +v -0.164062 -0.570312 0.720703 +v 0.185547 -0.732422 0.705078 +v -0.185547 -0.732422 0.705078 +v 0.041016 -0.376953 0.746094 +v -0.041016 -0.376953 0.746094 +v 0.048828 -0.564453 0.742188 +v -0.048828 -0.564453 0.742188 +v 0.056641 -0.712891 0.734375 +v -0.056641 -0.712891 0.734375 +v 0.109375 -0.253906 0.767578 +v -0.109375 -0.253906 0.767578 +v 0.117188 -0.183594 0.767578 +v -0.117188 -0.183594 0.767578 +v 0.062500 -0.136719 0.761719 +v -0.062500 -0.136719 0.761719 +v 0.009766 -0.162109 0.767578 +v -0.009766 -0.162109 0.767578 +v 0.044922 -0.302734 0.761719 +v -0.044922 -0.302734 0.761719 +v 0.042969 -0.283203 0.792969 +v -0.042969 -0.283203 0.792969 +v 0.021484 -0.166016 0.804688 +v -0.021484 -0.166016 0.804688 +v 0.072266 -0.140625 0.796875 +v -0.072266 -0.140625 0.796875 +v 0.111328 -0.185547 0.804688 +v -0.111328 -0.185547 0.804688 +v 0.103516 -0.244141 0.802734 +v -0.103516 -0.244141 0.802734 +v 0.062500 -0.183594 0.820312 +v -0.062500 -0.183594 0.820312 +v 0.046875 -0.242187 0.816406 +v -0.046875 -0.242187 0.816406 +v 0.056641 -0.085937 0.755859 +v -0.056641 -0.085937 0.755859 +v 0.128906 -0.179687 0.753906 +v -0.128906 -0.179687 0.753906 +v 0.138672 -0.267578 0.728516 +v -0.138672 -0.267578 0.728516 +v 0.138672 -0.373047 0.728516 +v -0.138672 -0.373047 0.728516 +v 0.240234 -0.376953 0.636719 +v -0.240234 -0.376953 0.636719 +v 0.208984 -0.279297 0.632812 +v -0.208984 -0.279297 0.632812 +v 0.181641 -0.195312 0.660156 +v -0.181641 -0.195312 0.660156 +v 0.050781 -0.750000 0.728516 +v -0.050781 -0.750000 0.728516 +v 0.103516 -0.779297 0.720703 +v -0.103516 -0.779297 0.720703 +v 0.080078 -0.851562 0.701172 +v -0.080078 -0.851562 0.701172 +v 0.027344 -0.878906 0.689453 +v -0.027344 -0.878906 0.689453 +v 0.023438 -0.863281 0.660156 +v -0.023438 -0.863281 0.660156 +v 0.070312 -0.837891 0.667969 +v -0.070312 -0.837891 0.667969 +v 0.093750 -0.781250 0.685547 +v -0.093750 -0.781250 0.685547 +v 0.046875 -0.761719 0.691406 +v -0.046875 -0.761719 0.691406 +v 0.035156 -0.810547 0.646484 +v -0.035156 -0.810547 0.646484 +v 0.078125 -0.804687 0.645833 +v -0.078125 -0.804687 0.645833 +v 0.164062 0.181641 0.765625 +v -0.164062 0.181641 0.765625 +v 0.152344 0.257813 0.771484 +v -0.152344 0.257813 0.771484 +v 0.169922 0.347656 0.775391 +v -0.169922 0.347656 0.775391 +v 0.195312 0.125000 0.761719 +v -0.195312 0.125000 0.761719 +v 0.294922 0.070313 0.742188 +v -0.294922 0.070313 0.742188 +v 0.429688 0.060547 0.708984 +v -0.429688 0.060547 0.708984 +v 0.542969 0.136719 0.679688 +v -0.542969 0.136719 0.679688 +v 0.607422 0.242188 0.666016 +v -0.607422 0.242188 0.666016 +v 0.597656 0.328125 0.673828 +v -0.597656 0.328125 0.673828 +v 0.503906 0.390625 0.712891 +v -0.503906 0.390625 0.712891 +v 0.378906 0.435547 0.748047 +v -0.378906 0.435547 0.748047 +v 0.296875 0.449219 0.757812 +v -0.296875 0.449219 0.757812 +v 0.224609 0.419922 0.771484 +v -0.224609 0.419922 0.771484 +v 0.250000 0.388672 0.769531 +v -0.250000 0.388672 0.769531 +v 0.306641 0.414063 0.761719 +v -0.306641 0.414063 0.761719 +v 0.376953 0.406250 0.757812 +v -0.376953 0.406250 0.757812 +v 0.482422 0.369141 0.724609 +v -0.482422 0.369141 0.724609 +v 0.558594 0.314453 0.683594 +v -0.558594 0.314453 0.683594 +v 0.566406 0.244141 0.677734 +v -0.566406 0.244141 0.677734 +v 0.515625 0.156250 0.693359 +v -0.515625 0.156250 0.693359 +v 0.421875 0.091797 0.722656 +v -0.421875 0.091797 0.722656 +v 0.304688 0.095703 0.751953 +v -0.304688 0.095703 0.751953 +v 0.214844 0.140625 0.765625 +v -0.214844 0.140625 0.765625 +v 0.205078 0.332031 0.769531 +v -0.205078 0.332031 0.769531 +v 0.185547 0.259766 0.767578 +v -0.185547 0.259766 0.767578 +v 0.189453 0.193359 0.763672 +v -0.189453 0.193359 0.763672 +v 0.042969 0.447266 0.675781 +v -0.042969 0.447266 0.675781 +v 0.130859 0.583984 0.683594 +v -0.130859 0.583984 0.683594 +v 0.251953 0.707031 0.675781 +v -0.251953 0.707031 0.675781 +v 0.408203 0.650391 0.642578 +v -0.408203 0.650391 0.642578 +v 0.591797 0.523438 0.589844 +v -0.591797 0.523438 0.589844 +v 0.761719 0.443359 0.542969 +v -0.761719 0.443359 0.542969 +v 0.814453 0.287109 0.468750 +v -0.814453 0.287109 0.468750 +v 0.708984 0.068359 0.443359 +v -0.708984 0.068359 0.443359 +v 0.527344 -0.068359 0.488281 +v -0.527344 -0.068359 0.488281 +v 0.076172 -0.501953 0.304688 +v -0.076172 -0.501953 0.304688 +v 0.066406 -0.667969 0.347656 +v -0.066406 -0.667969 0.347656 +v 0.076172 -0.871094 0.402344 +v -0.076172 -0.871094 0.402344 +v 0.085938 -0.968750 0.507813 +v -0.085938 -0.968750 0.507813 +v 0.250000 -0.943359 0.478516 +v -0.250000 -0.943359 0.478516 +v 0.328125 -0.865234 0.458984 +v -0.328125 -0.865234 0.458984 +v 0.314453 -0.699219 0.468750 +v -0.314453 -0.699219 0.468750 +v 0.201172 -0.626953 0.375000 +v -0.201172 -0.626953 0.375000 +v 0.230469 -0.832031 0.396484 +v -0.230469 -0.832031 0.396484 +v 0.197266 -0.451172 0.353516 +v -0.197266 -0.451172 0.353516 +v 0.287109 -0.496094 0.484375 +v -0.287109 -0.496094 0.484375 +v 0.230469 -0.267578 0.501953 +v -0.230469 -0.267578 0.501953 +v 0.255859 -0.345703 0.490234 +v -0.255859 -0.345703 0.490234 +v 0.212891 -0.208984 0.521484 +v -0.212891 -0.208984 0.521484 +v 0.320312 -0.148437 0.515625 +v -0.320312 -0.148437 0.515625 +v 0.169922 -0.054688 -0.675781 +v -0.169922 -0.054688 -0.675781 +v 0.160156 -0.259766 -0.457031 +v -0.160156 -0.259766 -0.457031 +v 0.126953 -0.386719 -0.066406 +v -0.126953 -0.386719 -0.066406 +v 0.097656 -0.437500 0.222656 +v -0.097656 -0.437500 0.222656 +v 0.210938 -0.359375 0.314453 +v -0.210938 -0.359375 0.314453 +v 0.740234 0.087891 0.228516 +v -0.740234 0.087891 0.228516 +v 0.199219 0.281250 -0.761719 +v -0.199219 0.281250 -0.761719 +v 0.226562 0.916016 0.093750 +v -0.226562 0.916016 0.093750 +v 0.226562 0.919922 -0.269531 +v -0.226562 0.919922 -0.269531 +v 0.228516 0.691406 -0.621094 +v -0.228516 0.691406 -0.621094 +v 0.708984 0.429688 0.392578 +v -0.708984 0.429688 0.392578 +v 0.699219 0.531250 0.199219 +v -0.699219 0.531250 0.199219 +v 0.718750 0.658203 -0.033203 +v -0.718750 0.658203 -0.033203 +v 0.718750 0.646484 -0.279297 +v -0.718750 0.646484 -0.279297 +v 0.707031 0.453125 -0.457031 +v -0.707031 0.453125 -0.457031 +v 0.542969 0.578125 -0.529297 +v -0.542969 0.578125 -0.529297 +v 0.546875 0.806641 -0.273438 +v -0.546875 0.806641 -0.273438 +v 0.546875 0.808594 0.005859 +v -0.546875 0.808594 0.005859 +v 0.546875 0.632812 0.250000 +v -0.546875 0.632812 0.250000 +v 0.564453 0.496094 0.439453 +v -0.564453 0.496094 0.439453 +v 0.228516 0.710938 0.380859 +v -0.228516 0.710938 0.380859 +v 0.281250 0.591797 0.593750 +v -0.281250 0.591797 0.593750 +v 0.263672 0.527344 0.541016 +v -0.263672 0.527344 0.541016 +v 0.036458 0.479167 0.593750 +v -0.036458 0.479167 0.593750 +v 0.787109 0.302734 0.306641 +v -0.787109 0.302734 0.306641 +v 0.808594 0.380859 0.117187 +v -0.808594 0.380859 0.117187 +v 0.818359 0.457031 -0.060547 +v -0.818359 0.457031 -0.060547 +v 0.796875 0.437500 -0.279297 +v -0.796875 0.437500 -0.279297 +v 0.335938 -0.267578 -0.041016 +v -0.335938 -0.267578 -0.041016 +v 0.541016 -0.134766 -0.039062 +v -0.541016 -0.134766 -0.039062 +v 0.544922 -0.078125 0.275391 +v -0.544922 -0.078125 0.275391 +v 0.318359 -0.193359 0.378906 +v -0.318359 -0.193359 0.378906 +v 0.278646 -0.281250 0.247396 +v -0.278646 -0.281250 0.247396 +v 0.283854 -0.164062 0.479167 +v -0.283854 -0.164062 0.479167 +v 0.628906 0.152344 -0.500000 +v -0.628906 0.152344 -0.500000 +v 0.474609 0.210937 -0.625000 +v -0.474609 0.210937 -0.625000 +v 0.537109 -0.076172 -0.337891 +v -0.537109 -0.076172 -0.337891 +v 0.388672 -0.158203 -0.390625 +v -0.388672 -0.158203 -0.390625 +v 0.388021 -0.023438 -0.583333 +v -0.388021 -0.023438 -0.583333 +v 0.962891 0.414062 -0.263672 +v -0.962891 0.414062 -0.263672 +v 1.115234 0.458984 -0.353516 +v -1.115234 0.458984 -0.353516 +v 1.259766 0.388672 -0.410156 +v -1.259766 0.388672 -0.410156 +v 1.277344 0.185547 -0.416016 +v -1.277344 0.185547 -0.416016 +v 1.140625 -0.001953 -0.367188 +v -1.140625 -0.001953 -0.367188 +v 0.917969 -0.087891 -0.222656 +v -0.917969 -0.087891 -0.222656 +v 0.945312 -0.033203 -0.253906 +v -0.945312 -0.033203 -0.253906 +v 1.117188 0.033203 -0.380859 +v -1.117188 0.033203 -0.380859 +v 1.224609 0.177734 -0.425781 +v -1.224609 0.177734 -0.425781 +v 1.214844 0.333984 -0.419922 +v -1.214844 0.333984 -0.419922 +v 1.099609 0.388672 -0.369141 +v -1.099609 0.388672 -0.369141 +v 0.976562 0.355469 -0.289063 +v -0.976562 0.355469 -0.289063 +v 0.693359 -0.048828 -0.083984 +v -0.693359 -0.048828 -0.083984 +v 0.728516 -0.089844 -0.148438 +v -0.728516 -0.089844 -0.148438 +v 0.792969 0.126953 0.001953 +v -0.792969 0.126953 0.001953 +v 0.869141 0.345703 -0.216797 +v -0.869141 0.345703 -0.216797 +v 0.810547 -0.033203 -0.197266 +v -0.810547 -0.033203 -0.197266 +v 0.773438 0.003906 -0.226562 +v -0.773438 0.003906 -0.226562 +v 0.785156 0.058594 -0.251953 +v -0.785156 0.058594 -0.251953 +v 0.777344 0.126953 -0.236328 +v -0.777344 0.126953 -0.236328 +v 0.841797 0.226562 -0.240234 +v -0.841797 0.226562 -0.240234 +v 0.900391 0.298828 -0.246094 +v -0.900391 0.298828 -0.246094 +v 0.830078 0.285156 -0.167969 +v -0.830078 0.285156 -0.167969 +v 0.775391 0.140625 -0.128906 +v -0.775391 0.140625 -0.128906 +v 0.721354 0.005208 -0.143229 +v -0.721354 0.005208 -0.143229 +v 0.919922 0.267578 -0.304688 +v -0.919922 0.267578 -0.304688 +v 0.865234 0.205078 -0.294922 +v -0.865234 0.205078 -0.294922 +v 0.800781 0.132812 -0.296875 +v -0.800781 0.132812 -0.296875 +v 0.792969 0.087891 -0.296875 +v -0.792969 0.087891 -0.296875 +v 0.835938 0.048828 -0.296875 +v -0.835938 0.048828 -0.296875 +v 0.830078 -0.000000 -0.296875 +v -0.830078 -0.000000 -0.296875 +v 0.847656 -0.017578 -0.267578 +v -0.847656 -0.017578 -0.267578 +v 0.990234 0.316406 -0.351563 +v -0.990234 0.316406 -0.351563 +v 1.105469 0.343750 -0.423828 +v -1.105469 0.343750 -0.423828 +v 1.212891 0.298828 -0.464844 +v -1.212891 0.298828 -0.464844 +v 1.222656 0.167969 -0.466797 +v -1.222656 0.167969 -0.466797 +v 1.121094 0.044922 -0.429688 +v -1.121094 0.044922 -0.429688 +v 0.962891 -0.009766 -0.316406 +v -0.962891 -0.009766 -0.316406 +v 0.876953 0.066406 -0.326172 +v -0.876953 0.066406 -0.326172 +v 0.947266 0.117187 -0.345703 +v -0.947266 0.117187 -0.345703 +v 1.007812 0.179687 -0.369141 +v -1.007812 0.179687 -0.369141 +v 1.066406 0.226562 -0.384766 +v -1.066406 0.226562 -0.384766 +v 1.023438 0.281250 -0.380859 +v -1.023438 0.281250 -0.380859 +v 0.955078 0.232422 -0.347656 +v -0.955078 0.232422 -0.347656 +v 0.896484 0.171875 -0.330078 +v -0.896484 0.171875 -0.330078 +v 0.832031 0.113281 -0.322266 +v -0.832031 0.113281 -0.322266 +v 0.871094 0.011719 -0.310547 +v -0.871094 0.011719 -0.310547 +v 0.966797 0.042969 -0.347656 +v -0.966797 0.042969 -0.347656 +v 1.078125 0.099609 -0.414062 +v -1.078125 0.099609 -0.414062 +v 1.158203 0.181641 -0.437500 +v -1.158203 0.181641 -0.437500 +v 1.160156 0.267578 -0.439453 +v -1.160156 0.267578 -0.439453 +v 1.104167 0.315104 -0.429688 +v -1.104167 0.315104 -0.429688 +v 0.910156 -0.113281 -0.318359 +v -0.910156 -0.113281 -0.318359 +v 1.167969 -0.019531 -0.445312 +v -1.167969 -0.019531 -0.445312 +v 1.328125 0.181641 -0.470703 +v -1.328125 0.181641 -0.470703 +v 1.300781 0.398437 -0.472656 +v -1.300781 0.398437 -0.472656 +v 1.132812 0.472656 -0.441406 +v -1.132812 0.472656 -0.441406 +v 0.949219 0.425781 -0.353516 +v -0.949219 0.425781 -0.353516 +v 0.927734 0.152344 -0.421875 +v -0.927734 0.152344 -0.421875 +v 1.156250 0.218750 -0.513672 +v -1.156250 0.218750 -0.513672 +v 1.309896 0.273437 -0.526042 +v -1.309896 0.273437 -0.526042 +v 0.835938 0.345703 -0.314453 +v -0.835938 0.345703 -0.314453 +v 0.765625 0.128906 -0.394531 +v -0.765625 0.128906 -0.394531 +v 0.699219 -0.099609 -0.261719 +v -0.699219 -0.099609 -0.261719 +v 0.463867 0.198242 0.753418 +v 0.459961 0.137207 0.728027 +v 0.528320 0.169922 0.676270 +v 0.503906 0.242676 0.717773 +v -0.459961 0.137207 0.728027 +v -0.463867 0.198242 0.753418 +v -0.503906 0.242676 0.717773 +v -0.528320 0.169922 0.676270 +v 0.510742 0.086426 0.635254 +v 0.585938 0.148438 0.570312 +v 0.576172 0.242676 0.621094 +v -0.510742 0.086426 0.635254 +v -0.576172 0.242676 0.621094 +v -0.585938 0.148438 0.570312 +v 0.424805 0.067383 0.698730 +v 0.351562 0.021484 0.666992 +v 0.449219 0.015625 0.597656 +v -0.351562 0.021484 0.666992 +v -0.424805 0.067383 0.698730 +v -0.449219 0.015625 0.597656 +v 0.398926 0.136231 0.767090 +v 0.352051 0.093750 0.749512 +v -0.352051 0.093750 0.749512 +v -0.398926 0.136231 0.767090 +v 0.307617 0.136231 0.784668 +v 0.246582 0.137207 0.767090 +v 0.278809 0.067383 0.725586 +v -0.246582 0.137207 0.767090 +v -0.307617 0.136231 0.784668 +v -0.278809 0.067383 0.725586 +v 0.192383 0.086426 0.692383 +v 0.253906 0.015625 0.632812 +v -0.192383 0.086426 0.692383 +v -0.253906 0.015625 0.632812 +v 0.175781 0.169922 0.737793 +v 0.126953 0.242676 0.698242 +v 0.117188 0.148438 0.652344 +v -0.126953 0.242676 0.698242 +v -0.175781 0.169922 0.737793 +v -0.117188 0.148438 0.652344 +v 0.245605 0.198242 0.792969 +v 0.203125 0.242676 0.769531 +v -0.203125 0.242676 0.769531 +v -0.245605 0.198242 0.792969 +v 0.245605 0.289551 0.792969 +v 0.246582 0.350586 0.767090 +v 0.175781 0.315430 0.737793 +v -0.246582 0.350586 0.767090 +v -0.245605 0.289551 0.792969 +v -0.175781 0.315430 0.737793 +v 0.192383 0.401367 0.692383 +v 0.117188 0.339844 0.652344 +v -0.192383 0.401367 0.692383 +v -0.117188 0.339844 0.652344 +v 0.278809 0.418945 0.725586 +v 0.351562 0.466797 0.666992 +v 0.253906 0.476563 0.632812 +v -0.351562 0.466797 0.666992 +v -0.278809 0.418945 0.725586 +v -0.253906 0.476563 0.632812 +v 0.307617 0.354981 0.784668 +v 0.352051 0.394531 0.749512 +v -0.352051 0.394531 0.749512 +v -0.307617 0.354981 0.784668 +v 0.398926 0.354981 0.767090 +v 0.459961 0.350586 0.728027 +v 0.424805 0.418945 0.698730 +v -0.459961 0.350586 0.728027 +v -0.398926 0.354981 0.767090 +v -0.424805 0.418945 0.698730 +v 0.510742 0.401367 0.635254 +v 0.449219 0.476563 0.597656 +v -0.510742 0.401367 0.635254 +v -0.449219 0.476563 0.597656 +v 0.528320 0.315430 0.676270 +v 0.585938 0.339844 0.570312 +v -0.528320 0.315430 0.676270 +v -0.585938 0.339844 0.570312 +v 0.463867 0.289551 0.753418 +v -0.463867 0.289551 0.753418 +v 0.434082 0.325195 0.774902 +v 0.450846 0.284668 0.779622 +v 0.464844 0.243164 0.767578 +v -0.434082 0.325195 0.774902 +v -0.464844 0.243164 0.767578 +v -0.450846 0.284668 0.779622 +v 0.352539 0.358398 0.792480 +v 0.394043 0.344564 0.793457 +v -0.352539 0.358398 0.792480 +v -0.394043 0.344564 0.793457 +v 0.275391 0.325195 0.806641 +v 0.312663 0.344564 0.810872 +v -0.275391 0.325195 0.806641 +v -0.312663 0.344564 0.810872 +v 0.243164 0.243164 0.808594 +v 0.256348 0.284668 0.818034 +v -0.243164 0.243164 0.808594 +v -0.256348 0.284668 0.818034 +v 0.275391 0.166016 0.806641 +v 0.256348 0.203288 0.818034 +v -0.275391 0.166016 0.806641 +v -0.256348 0.203288 0.818034 +v 0.352539 0.133789 0.792480 +v 0.312663 0.146973 0.810872 +v -0.352539 0.133789 0.792480 +v -0.312663 0.146973 0.810872 +v 0.434082 0.166016 0.774902 +v 0.394043 0.146973 0.793457 +v -0.434082 0.166016 0.774902 +v -0.394043 0.146973 0.793457 +v 0.450846 0.203288 0.779622 +v -0.450846 0.203288 0.779622 +v 0.401042 0.195964 0.802083 +v 0.419271 0.242839 0.797526 +v -0.401042 0.195964 0.802083 +v -0.419271 0.242839 0.797526 +v 0.352214 0.175781 0.813802 +v -0.352214 0.175781 0.813802 +v 0.305339 0.195964 0.822266 +v -0.305339 0.195964 0.822266 +v 0.285156 0.242839 0.823568 +v -0.285156 0.242839 0.823568 +v 0.305339 0.292318 0.822266 +v -0.305339 0.292318 0.822266 +v 0.352214 0.313151 0.813802 +v -0.352214 0.313151 0.813802 +v 0.401042 0.292318 0.802083 +v -0.401042 0.292318 0.802083 +v 0.164062 -0.948730 0.593750 +v 0.076660 -0.936035 0.634766 +v 0.000000 -0.960937 0.605469 +v 0.087891 -0.969727 0.560547 +v -0.076660 -0.936035 0.634766 +v -0.164062 -0.948730 0.593750 +v -0.087891 -0.969727 0.560547 +v 0.271973 -0.922852 0.582520 +v 0.192383 -0.918457 0.629883 +v 0.246094 -0.949219 0.535645 +v -0.192383 -0.918457 0.629883 +v -0.271973 -0.922852 0.582520 +v -0.246094 -0.949219 0.535645 +v 0.310059 -0.845215 0.599121 +v 0.245117 -0.862305 0.642578 +v 0.330566 -0.898437 0.525391 +v -0.245117 -0.862305 0.642578 +v -0.310059 -0.845215 0.599121 +v -0.330566 -0.898437 0.525391 +v 0.297852 -0.686523 0.626465 +v 0.252441 -0.758301 0.667481 +v 0.335449 -0.765625 0.545898 +v -0.252441 -0.758301 0.667481 +v -0.297852 -0.686523 0.626465 +v -0.335449 -0.765625 0.545898 +v 0.261230 -0.457519 0.638184 +v 0.226562 -0.572266 0.688477 +v 0.308105 -0.549805 0.564941 +v -0.226562 -0.572266 0.688477 +v -0.261230 -0.457519 0.638184 +v -0.308105 -0.549805 0.564941 +v 0.312988 -0.148926 0.563477 +v 0.412109 -0.087402 0.609863 +v 0.272461 -0.069336 0.715332 +v 0.200195 -0.150879 0.669922 +v -0.412109 -0.087402 0.609863 +v -0.312988 -0.148926 0.563477 +v -0.200195 -0.150879 0.669922 +v -0.272461 -0.069336 0.715332 +v 0.529785 -0.072754 0.537598 +v 0.618164 0.016113 0.577148 +v 0.501953 -0.003418 0.639160 +v -0.618164 0.016113 0.577148 +v -0.529785 -0.072754 0.537598 +v -0.501953 -0.003418 0.639160 +v 0.717773 0.067383 0.495117 +v 0.761230 0.183106 0.543457 +v 0.665039 0.119141 0.604004 +v -0.761230 0.183106 0.543457 +v -0.717773 0.067383 0.495117 +v -0.665039 0.119141 0.604004 +v 0.822754 0.288574 0.520508 +v 0.785156 0.379883 0.618652 +v 0.735352 0.283203 0.617676 +v -0.785156 0.379883 0.618652 +v -0.822754 0.288574 0.520508 +v -0.735352 0.283203 0.617676 +v 0.770508 0.445801 0.603027 +v 0.682617 0.458984 0.677734 +v 0.711914 0.395020 0.676758 +v -0.682617 0.458984 0.677734 +v -0.770508 0.445801 0.603027 +v -0.711914 0.395020 0.676758 +v 0.594238 0.530273 0.652832 +v 0.475586 0.574219 0.739258 +v 0.561523 0.479004 0.739746 +v -0.475586 0.574219 0.739258 +v -0.594238 0.530273 0.652832 +v -0.561523 0.479004 0.739746 +v 0.402832 0.661621 0.707031 +v 0.317871 0.679688 0.782227 +v 0.379395 0.587402 0.792480 +v -0.317871 0.679688 0.782227 +v -0.402832 0.661621 0.707031 +v -0.379395 0.587402 0.792480 +v 0.244141 0.716797 0.740723 +v 0.184570 0.645996 0.801269 +v 0.259277 0.623047 0.819824 +v -0.184570 0.645996 0.801269 +v -0.244141 0.716797 0.740723 +v -0.259277 0.623047 0.819824 +v 0.120117 0.589844 0.748047 +v 0.083984 0.478027 0.795898 +v 0.153809 0.523438 0.825684 +v -0.083984 0.478027 0.795898 +v -0.120117 0.589844 0.748047 +v -0.153809 0.523438 0.825684 +v 0.036621 0.448731 0.739258 +v 0.000000 0.408203 0.785156 +v 0.060059 0.395508 0.813477 +v -0.036621 0.448731 0.739258 +v -0.060059 0.395508 0.813477 +v 0.204590 0.446289 0.777344 +v 0.226562 0.529785 0.803223 +v 0.135742 0.425293 0.806152 +v -0.226562 0.529785 0.803223 +v -0.204590 0.446289 0.777344 +v -0.135742 0.425293 0.806152 +v 0.287109 0.486328 0.763672 +v 0.322754 0.548340 0.787109 +v -0.322754 0.548340 0.787109 +v -0.287109 0.486328 0.763672 +v 0.445801 0.488281 0.753906 +v 0.378418 0.468750 0.745605 +v -0.445801 0.488281 0.753906 +v -0.378418 0.468750 0.745605 +v 0.624023 0.399414 0.697754 +v 0.518555 0.411621 0.705566 +v -0.624023 0.399414 0.697754 +v -0.518555 0.411621 0.705566 +v 0.683594 0.325684 0.654297 +v 0.626953 0.341309 0.665039 +v -0.683594 0.325684 0.654297 +v -0.626953 0.341309 0.665039 +v 0.662598 0.195801 0.631348 +v 0.639160 0.248047 0.650391 +v -0.662598 0.195801 0.631348 +v -0.639160 0.248047 0.650391 +v 0.548828 0.066406 0.650391 +v 0.568848 0.128418 0.659180 +v -0.548828 0.066406 0.650391 +v -0.568848 0.128418 0.659180 +v 0.379883 -0.004883 0.693848 +v 0.441895 0.040039 0.687988 +v -0.379883 -0.004883 0.693848 +v -0.441895 0.040039 0.687988 +v 0.181641 0.006836 0.761230 +v 0.287109 0.042481 0.729980 +v -0.181641 0.006836 0.761230 +v -0.287109 0.042481 0.729980 +v 0.171387 0.101074 0.752930 +v 0.090332 0.096191 0.746094 +v 0.076172 -0.023926 0.763184 +v -0.090332 0.096191 0.746094 +v -0.171387 0.101074 0.752930 +v -0.076172 -0.023926 0.763184 +v 0.071777 0.325195 0.791016 +v 0.139160 0.360352 0.778809 +v -0.139160 0.360352 0.778809 +v -0.071777 0.325195 0.791016 +v 0.000000 0.275391 0.785156 +v 0.067871 0.210938 0.762695 +v 0.118652 0.260742 0.768066 +v -0.118652 0.260742 0.768066 +v -0.067871 0.210938 0.762695 +v 0.133789 0.171387 0.755859 +v 0.000000 0.140625 0.748047 +v -0.133789 0.171387 0.755859 +v 0.036621 -0.891113 0.684082 +v 0.000000 -0.915039 0.664063 +v 0.106934 -0.903809 0.665039 +v -0.036621 -0.891113 0.684082 +v -0.106934 -0.903809 0.665039 +v 0.101074 -0.865234 0.693848 +v 0.169434 -0.865723 0.674316 +v -0.101074 -0.865234 0.693848 +v -0.169434 -0.865723 0.674316 +v 0.127930 -0.789062 0.712891 +v 0.185547 -0.773437 0.697266 +v -0.127930 -0.789062 0.712891 +v -0.185547 -0.773437 0.697266 +v 0.147949 -0.458496 0.727539 +v 0.102051 -0.566894 0.736816 +v 0.179199 -0.673340 0.711914 +v -0.102051 -0.566894 0.736816 +v -0.147949 -0.458496 0.727539 +v -0.179199 -0.673340 0.711914 +v 0.117188 -0.712891 0.727051 +v -0.117188 -0.712891 0.727051 +v 0.042969 -0.324219 0.748047 +v 0.000000 -0.381836 0.746094 +v 0.041992 -0.458008 0.747070 +v 0.085938 -0.371094 0.741699 +v -0.042969 -0.324219 0.748047 +v -0.085938 -0.371094 0.741699 +v -0.041992 -0.458008 0.747070 +v 0.000000 -0.563477 0.742188 +v 0.055664 -0.661133 0.736328 +v -0.055664 -0.661133 0.736328 +v 0.054199 -0.736816 0.732910 +v 0.000000 -0.717773 0.734375 +v -0.054199 -0.736816 0.732910 +v 0.121094 -0.222656 0.770508 +v 0.109863 -0.249512 0.787109 +v 0.083496 -0.279785 0.763184 +v 0.114746 -0.259277 0.747070 +v -0.109863 -0.249512 0.787109 +v -0.121094 -0.222656 0.770508 +v -0.114746 -0.259277 0.747070 +v -0.083496 -0.279785 0.763184 +v 0.097656 -0.150391 0.763184 +v 0.117676 -0.182129 0.787598 +v 0.118164 -0.184570 0.753418 +v -0.117676 -0.182129 0.787598 +v -0.097656 -0.150391 0.763184 +v -0.118164 -0.184570 0.753418 +v 0.027832 -0.141113 0.763184 +v 0.070801 -0.133789 0.780273 +v 0.055176 -0.127930 0.750488 +v -0.070801 -0.133789 0.780273 +v -0.027832 -0.141113 0.763184 +v -0.055176 -0.127930 0.750488 +v 0.000000 -0.176758 0.770508 +v 0.017578 -0.160156 0.787598 +v 0.000000 -0.165039 0.756836 +v -0.017578 -0.160156 0.787598 +v 0.045410 -0.294922 0.779297 +v 0.000000 -0.313477 0.761719 +v -0.045410 -0.294922 0.779297 +v 0.079590 -0.262695 0.795410 +v 0.041992 -0.266113 0.804688 +v 0.000000 -0.293945 0.792969 +v -0.079590 -0.262695 0.795410 +v -0.041992 -0.266113 0.804688 +v 0.000000 -0.180664 0.808594 +v 0.032715 -0.175293 0.816406 +v 0.044922 -0.145019 0.798828 +v -0.032715 -0.175293 0.816406 +v -0.044922 -0.145019 0.798828 +v 0.068848 -0.157227 0.810547 +v 0.096680 -0.153809 0.798828 +v -0.068848 -0.157227 0.810547 +v -0.096680 -0.153809 0.798828 +v 0.094238 -0.187988 0.816406 +v 0.114258 -0.220703 0.808105 +v -0.094238 -0.187988 0.816406 +v -0.114258 -0.220703 0.808105 +v 0.084473 -0.240723 0.812988 +v -0.084473 -0.240723 0.812988 +v 0.054688 -0.213867 0.823242 +v -0.054688 -0.213867 0.823242 +v 0.000000 -0.244141 0.816406 +v 0.103027 -0.128906 0.766113 +v 0.000000 -0.066406 0.745117 +v -0.103027 -0.128906 0.766113 +v 0.139160 -0.229004 0.735840 +v 0.149902 -0.179687 0.734375 +v -0.139160 -0.229004 0.735840 +v -0.149902 -0.179687 0.734375 +v 0.135742 -0.310547 0.727539 +v 0.172852 -0.275391 0.695801 +v -0.135742 -0.310547 0.727539 +v -0.172852 -0.275391 0.695801 +v 0.192383 -0.376953 0.696777 +v -0.192383 -0.376953 0.696777 +v 0.266602 -0.368164 0.562988 +v 0.221680 -0.320312 0.633789 +v -0.221680 -0.320312 0.633789 +v -0.266602 -0.368164 0.562988 +v 0.232910 -0.277344 0.561035 +v 0.197266 -0.241699 0.639648 +v -0.197266 -0.241699 0.639648 +v -0.232910 -0.277344 0.561035 +v 0.208008 -0.210449 0.574707 +v -0.208008 -0.210449 0.574707 +v 0.000000 -0.759766 0.727539 +v 0.047852 -0.756836 0.716309 +v 0.089355 -0.747559 0.727539 +v -0.089355 -0.747559 0.727539 +v -0.047852 -0.756836 0.716309 +v 0.096191 -0.780762 0.710938 +v 0.098633 -0.821777 0.710938 +v -0.098633 -0.821777 0.710938 +v -0.096191 -0.780762 0.710938 +v 0.072754 -0.844238 0.691895 +v 0.054199 -0.870117 0.693359 +v -0.054199 -0.870117 0.693359 +v -0.072754 -0.844238 0.691895 +v 0.024414 -0.871094 0.681152 +v 0.000000 -0.880859 0.688477 +v -0.024414 -0.871094 0.681152 +v 0.046875 -0.854980 0.662109 +v 0.026367 -0.846191 0.643066 +v 0.000000 -0.865234 0.660156 +v -0.046875 -0.854980 0.662109 +v -0.026367 -0.846191 0.643066 +v 0.087891 -0.812988 0.676270 +v 0.072266 -0.826660 0.646810 +v -0.087891 -0.812988 0.676270 +v -0.072266 -0.826660 0.646810 +v 0.082031 -0.758789 0.691895 +v 0.089844 -0.787109 0.659017 +v -0.082031 -0.758789 0.691895 +v -0.089844 -0.787109 0.659017 +v 0.000000 -0.769531 0.689453 +v 0.043945 -0.775879 0.664551 +v -0.043945 -0.775879 0.664551 +v 0.000000 -0.815430 0.645508 +v 0.063477 -0.804199 0.647298 +v -0.063477 -0.804199 0.647298 +v 0.177734 0.150879 0.762695 +v 0.178223 0.187500 0.770996 +v 0.155273 0.217285 0.769043 +v -0.177734 0.150879 0.762695 +v -0.155273 0.217285 0.769043 +v -0.178223 0.187500 0.770996 +v 0.172363 0.258301 0.775391 +v 0.156738 0.301758 0.773438 +v -0.156738 0.301758 0.773438 +v -0.172363 0.258301 0.775391 +v 0.191406 0.337891 0.776855 +v 0.192383 0.389160 0.775391 +v -0.192383 0.389160 0.775391 +v -0.191406 0.337891 0.776855 +v 0.229980 0.099609 0.756836 +v 0.206055 0.132813 0.770508 +v -0.229980 0.099609 0.756836 +v -0.206055 0.132813 0.770508 +v 0.368652 0.052246 0.724121 +v 0.300293 0.084473 0.754395 +v -0.368652 0.052246 0.724121 +v -0.300293 0.084473 0.754395 +v 0.485352 0.090332 0.694824 +v 0.425781 0.079102 0.723145 +v -0.485352 0.090332 0.694824 +v -0.425781 0.079102 0.723145 +v 0.588379 0.190430 0.668457 +v 0.528320 0.147461 0.692871 +v -0.588379 0.190430 0.668457 +v -0.528320 0.147461 0.692871 +v 0.607910 0.289063 0.668945 +v 0.584473 0.242676 0.677734 +v -0.607910 0.289063 0.668945 +v -0.584473 0.242676 0.677734 +v 0.566406 0.361328 0.686523 +v 0.576172 0.320801 0.685059 +v -0.566406 0.361328 0.686523 +v -0.576172 0.320801 0.685059 +v 0.433594 0.415527 0.738281 +v 0.492676 0.377441 0.726562 +v -0.433594 0.415527 0.738281 +v -0.492676 0.377441 0.726562 +v 0.334961 0.447754 0.751465 +v 0.378418 0.417481 0.759277 +v -0.334961 0.447754 0.751465 +v -0.378418 0.417481 0.759277 +v 0.261230 0.439941 0.765137 +v 0.303223 0.428711 0.762695 +v -0.261230 0.439941 0.765137 +v -0.303223 0.428711 0.762695 +v 0.239746 0.401367 0.773926 +v -0.239746 0.401367 0.773926 +v 0.225098 0.363770 0.769531 +v 0.257812 0.378906 0.761719 +v 0.277832 0.405762 0.767578 +v -0.225098 0.363770 0.769531 +v -0.277832 0.405762 0.767578 +v -0.257812 0.378906 0.761719 +v 0.308594 0.402344 0.757812 +v 0.338867 0.414063 0.756836 +v -0.338867 0.414063 0.756836 +v -0.308594 0.402344 0.757812 +v 0.375000 0.398438 0.750000 +v 0.423828 0.391113 0.751465 +v -0.423828 0.391113 0.751465 +v -0.375000 0.398438 0.750000 +v 0.472656 0.363281 0.714844 +v 0.533691 0.342773 0.695801 +v -0.533691 0.342773 0.695801 +v -0.472656 0.363281 0.714844 +v 0.542969 0.308594 0.675781 +v 0.566406 0.282227 0.680176 +v -0.566406 0.282227 0.680176 +v -0.542969 0.308594 0.675781 +v 0.550781 0.246094 0.671875 +v 0.551758 0.201660 0.680664 +v -0.551758 0.201660 0.680664 +v -0.550781 0.246094 0.671875 +v 0.503906 0.164063 0.687500 +v 0.468750 0.116699 0.709473 +v -0.468750 0.116699 0.709473 +v -0.503906 0.164063 0.687500 +v 0.417969 0.101563 0.714844 +v 0.369141 0.083984 0.735840 +v -0.369141 0.083984 0.735840 +v -0.417969 0.101563 0.714844 +v 0.308594 0.105469 0.742188 +v 0.247070 0.117676 0.764160 +v -0.247070 0.117676 0.764160 +v -0.308594 0.105469 0.742188 +v 0.222656 0.148438 0.753906 +v 0.198730 0.165527 0.763184 +v -0.198730 0.165527 0.763184 +v -0.222656 0.148438 0.753906 +v 0.191406 0.296387 0.769043 +v 0.214844 0.328125 0.757812 +v -0.191406 0.296387 0.769043 +v -0.214844 0.328125 0.757812 +v 0.185547 0.224609 0.765625 +v 0.195312 0.261719 0.753906 +v -0.185547 0.224609 0.765625 +v -0.195312 0.261719 0.753906 +v 0.199219 0.199219 0.750000 +v -0.199219 0.199219 0.750000 +v 0.086426 0.496094 0.679687 +v 0.047201 0.448405 0.620117 +v 0.000000 0.432617 0.673828 +v -0.086426 0.496094 0.679687 +v -0.047201 0.448405 0.620117 +v 0.183594 0.668457 0.683594 +v 0.179199 0.575195 0.625977 +v -0.183594 0.668457 0.683594 +v -0.179199 0.575195 0.625977 +v 0.329102 0.700684 0.661621 +v 0.266113 0.662598 0.620117 +v -0.329102 0.700684 0.661621 +v -0.266113 0.662598 0.620117 +v 0.494141 0.582520 0.618652 +v 0.377441 0.621094 0.596191 +v -0.494141 0.582520 0.618652 +v -0.377441 0.621094 0.596191 +v 0.686035 0.476074 0.562500 +v 0.580078 0.506836 0.519043 +v -0.686035 0.476074 0.562500 +v -0.580078 0.506836 0.519043 +v 0.808105 0.391602 0.516602 +v 0.736816 0.433105 0.472168 +v -0.808105 0.391602 0.516602 +v -0.736816 0.433105 0.472168 +v 0.781250 0.166992 0.433105 +v 0.792969 0.290039 0.402832 +v -0.781250 0.166992 0.433105 +v -0.792969 0.290039 0.402832 +v 0.617676 -0.009766 0.471191 +v 0.706055 0.080078 0.365234 +v -0.617676 -0.009766 0.471191 +v -0.706055 0.080078 0.365234 +v 0.430664 -0.112793 0.500977 +v 0.527832 -0.060059 0.411621 +v -0.430664 -0.112793 0.500977 +v -0.527832 -0.060059 0.411621 +v 0.000000 -0.514648 0.302734 +v 0.088379 -0.459473 0.266602 +v 0.144531 -0.476562 0.318848 +v 0.066895 -0.569824 0.333008 +v -0.088379 -0.459473 0.266602 +v -0.066895 -0.569824 0.333008 +v -0.144531 -0.476562 0.318848 +v 0.000000 -0.677734 0.339844 +v 0.133301 -0.647949 0.362305 +v 0.070801 -0.775391 0.365234 +v -0.070801 -0.775391 0.365234 +v -0.133301 -0.647949 0.362305 +v 0.000000 -0.880859 0.402344 +v 0.152832 -0.851562 0.400879 +v 0.081543 -0.940430 0.452148 +v -0.081543 -0.940430 0.452148 +v -0.152832 -0.851562 0.400879 +v 0.000000 -0.974609 0.513672 +v 0.169922 -0.956543 0.494629 +v -0.169922 -0.956543 0.494629 +v 0.243164 -0.908691 0.427734 +v 0.308594 -0.916992 0.464844 +v -0.308594 -0.916992 0.464844 +v -0.243164 -0.908691 0.427734 +v 0.293945 -0.830566 0.409180 +v 0.324707 -0.791504 0.460449 +v -0.324707 -0.791504 0.460449 +v -0.293945 -0.830566 0.409180 +v 0.263672 -0.634277 0.404297 +v 0.300781 -0.597656 0.478516 +v -0.300781 -0.597656 0.478516 +v -0.263672 -0.634277 0.404297 +v 0.215332 -0.731934 0.380371 +v 0.193359 -0.529297 0.369629 +v -0.215332 -0.731934 0.380371 +v -0.193359 -0.529297 0.369629 +v 0.242188 -0.449707 0.408691 +v 0.205566 -0.394043 0.333008 +v -0.242188 -0.449707 0.408691 +v -0.205566 -0.394043 0.333008 +v 0.272461 -0.407715 0.487793 +v -0.272461 -0.407715 0.487793 +v 0.240723 -0.301758 0.494141 +v 0.244629 -0.242187 0.444824 +v 0.222168 -0.238281 0.511719 +v -0.244629 -0.242187 0.444824 +v -0.240723 -0.301758 0.494141 +v -0.222168 -0.238281 0.511719 +v 0.229980 -0.334473 0.410156 +v -0.229980 -0.334473 0.410156 +v 0.227702 -0.192871 0.492350 +v 0.234863 -0.179199 0.524902 +v -0.234863 -0.179199 0.524902 +v -0.227702 -0.192871 0.492350 +v 0.311198 -0.144531 0.490885 +v -0.311198 -0.144531 0.490885 +v 0.176270 0.087891 -0.732422 +v 0.309408 -0.042969 -0.615560 +v 0.168457 -0.164551 -0.585938 +v 0.000000 -0.058594 -0.712891 +v -0.309408 -0.042969 -0.615560 +v -0.176270 0.087891 -0.732422 +v -0.168457 -0.164551 -0.585938 +v 0.297363 -0.219727 -0.413086 +v 0.145996 -0.335449 -0.285156 +v 0.000000 -0.274414 -0.484375 +v -0.297363 -0.219727 -0.413086 +v -0.145996 -0.335449 -0.285156 +v 0.242676 -0.339355 -0.052246 +v 0.108887 -0.418945 0.126953 +v 0.000000 -0.404297 -0.074219 +v -0.242676 -0.339355 -0.052246 +v -0.108887 -0.418945 0.126953 +v 0.174805 -0.400391 0.239746 +v 0.000000 -0.455078 0.228516 +v -0.174805 -0.400391 0.239746 +v 0.229818 -0.328125 0.288900 +v -0.229818 -0.328125 0.288900 +v 0.655273 -0.009277 0.247070 +v 0.779785 0.100586 0.088867 +v 0.788086 0.197266 0.241211 +v -0.655273 -0.009277 0.247070 +v -0.788086 0.197266 0.241211 +v -0.779785 0.100586 0.088867 +v 0.222168 0.493164 -0.734375 +v 0.367676 0.246094 -0.688477 +v 0.000000 0.298828 -0.800781 +v -0.367676 0.246094 -0.688477 +v -0.222168 0.493164 -0.734375 +v 0.227051 0.844238 0.249512 +v 0.419922 0.876465 0.065918 +v 0.226562 0.937500 -0.081055 +v 0.000000 0.928711 0.099609 +v -0.419922 0.876465 0.065918 +v -0.227051 0.844238 0.249512 +v -0.226562 0.937500 -0.081055 +v 0.419922 0.880859 -0.249023 +v 0.227051 0.844238 -0.455078 +v 0.000000 0.930664 -0.291016 +v -0.419922 0.880859 -0.249023 +v -0.227051 0.844238 -0.455078 +v 0.421387 0.643555 -0.559082 +v 0.000000 0.710937 -0.660156 +v -0.421387 0.643555 -0.559082 +v 0.754883 0.386230 0.374023 +v 0.691895 0.455078 0.302246 +v 0.646484 0.458008 0.401367 +v -0.754883 0.386230 0.374023 +v -0.646484 0.458008 0.401367 +v -0.691895 0.455078 0.302246 +v 0.757812 0.470215 0.194336 +v 0.713867 0.613770 0.086426 +v 0.629883 0.580078 0.196289 +v -0.757812 0.470215 0.194336 +v -0.629883 0.580078 0.196289 +v -0.713867 0.613770 0.086426 +v 0.782715 0.573730 -0.021484 +v 0.718750 0.667969 -0.156250 +v 0.636719 0.729980 -0.041992 +v -0.782715 0.573730 -0.021484 +v -0.636719 0.729980 -0.041992 +v -0.718750 0.667969 -0.156250 +v 0.777344 0.560059 -0.258789 +v 0.715820 0.579590 -0.385254 +v 0.636719 0.720703 -0.298340 +v -0.777344 0.560059 -0.258789 +v -0.636719 0.720703 -0.298340 +v -0.715820 0.579590 -0.385254 +v 0.681641 0.299805 -0.495117 +v 0.626953 0.509766 -0.504395 +v 0.768555 0.423828 -0.383301 +v -0.626953 0.509766 -0.504395 +v -0.681641 0.299805 -0.495117 +v -0.768555 0.423828 -0.383301 +v 0.545898 0.732910 -0.407715 +v 0.523926 0.388672 -0.610840 +v -0.545898 0.732910 -0.407715 +v -0.523926 0.388672 -0.610840 +v 0.546875 0.823730 -0.133301 +v -0.546875 0.823730 -0.133301 +v 0.546875 0.749023 0.136230 +v -0.546875 0.749023 0.136230 +v 0.422363 0.679688 0.323730 +v 0.551270 0.526367 0.350098 +v -0.551270 0.526367 0.350098 +v -0.422363 0.679688 0.323730 +v 0.443359 0.525391 0.491211 +v -0.443359 0.525391 0.491211 +v 0.238281 0.583008 0.480469 +v 0.000000 0.722656 0.405273 +v -0.238281 0.583008 0.480469 +v 0.284668 0.533691 0.574707 +v -0.284668 0.533691 0.574707 +v 0.102376 0.509440 0.578613 +v -0.102376 0.509440 0.578613 +v 0.000000 0.483724 0.589844 +v 0.793457 0.331055 0.203613 +v -0.793457 0.331055 0.203613 +v 0.828125 0.265625 0.031738 +v 0.820801 0.430176 0.033691 +v -0.820801 0.430176 0.033691 +v -0.828125 0.265625 0.031738 +v 0.832031 0.347656 -0.119629 +v 0.808105 0.459961 -0.165039 +v -0.808105 0.459961 -0.165039 +v -0.832031 0.347656 -0.119629 +v 0.806641 0.344238 -0.308594 +v -0.806641 0.344238 -0.308594 +v 0.362793 -0.233398 -0.227051 +v 0.428223 -0.192383 -0.035645 +v 0.307943 -0.277832 0.129720 +v -0.362793 -0.233398 -0.227051 +v -0.307943 -0.277832 0.129720 +v -0.428223 -0.192383 -0.035645 +v 0.556641 -0.107910 0.113770 +v 0.525391 -0.132813 -0.187988 +v 0.640625 -0.088867 -0.054199 +v -0.556641 -0.107910 0.113770 +v -0.640625 -0.088867 -0.054199 +v -0.525391 -0.132813 -0.187988 +v 0.426758 -0.134277 0.317871 +v -0.426758 -0.134277 0.317871 +v 0.312663 -0.169434 0.448893 +v 0.305501 -0.231934 0.301107 +v -0.312663 -0.169434 0.448893 +v -0.305501 -0.231934 0.301107 +v 0.702148 0.134766 -0.440430 +v 0.572754 0.022949 -0.453613 +v 0.551270 0.178711 -0.564453 +v -0.572754 0.022949 -0.453613 +v -0.702148 0.134766 -0.440430 +v -0.551270 0.178711 -0.564453 +v 0.420736 0.066406 -0.604818 +v -0.420736 0.066406 -0.604818 +v 0.459961 -0.101563 -0.371582 +v 0.617676 -0.077148 -0.298340 +v -0.459961 -0.101563 -0.371582 +v -0.617676 -0.077148 -0.298340 +v 0.401204 -0.076660 -0.514974 +v -0.401204 -0.076660 -0.514974 +v 0.956543 0.430664 -0.291016 +v 0.911133 0.381348 -0.233398 +v 0.969238 0.385742 -0.265137 +v 1.029297 0.440918 -0.304688 +v -0.911133 0.381348 -0.233398 +v -0.956543 0.430664 -0.291016 +v -1.029297 0.440918 -0.304688 +v -0.969238 0.385742 -0.265137 +v 1.104492 0.424805 -0.350586 +v 1.199219 0.448242 -0.394043 +v 1.126465 0.479004 -0.382324 +v -1.104492 0.424805 -0.350586 +v -1.126465 0.479004 -0.382324 +v -1.199219 0.448242 -0.394043 +v 1.231934 0.362305 -0.406738 +v 1.288574 0.295898 -0.413574 +v 1.286621 0.403809 -0.431641 +v -1.231934 0.362305 -0.406738 +v -1.286621 0.403809 -0.431641 +v -1.288574 0.295898 -0.413574 +v 1.244629 0.182617 -0.413574 +v 1.227539 0.079102 -0.404785 +v 1.309570 0.185547 -0.434570 +v -1.244629 0.182617 -0.413574 +v -1.309570 0.185547 -0.434570 +v -1.227539 0.079102 -0.404785 +v 1.125000 0.017578 -0.364746 +v 1.032227 -0.057617 -0.305664 +v 1.157227 -0.017090 -0.392578 +v -1.125000 0.017578 -0.364746 +v -1.157227 -0.017090 -0.392578 +v -1.032227 -0.057617 -0.305664 +v 0.930664 -0.057617 -0.228516 +v 0.812012 -0.097168 -0.157227 +v 0.910156 -0.110840 -0.248535 +v -0.930664 -0.057617 -0.228516 +v -0.910156 -0.110840 -0.248535 +v -0.812012 -0.097168 -0.157227 +v 1.033203 -0.009766 -0.326660 +v 0.957520 -0.016602 -0.287109 +v 0.866699 -0.040039 -0.198730 +v -0.957520 -0.016602 -0.287109 +v -1.033203 -0.009766 -0.326660 +v -0.866699 -0.040039 -0.198730 +v 1.185059 0.095703 -0.414551 +v 1.116211 0.042969 -0.405762 +v -1.116211 0.042969 -0.405762 +v -1.185059 0.095703 -0.414551 +v 1.234863 0.262695 -0.424316 +v 1.217285 0.172363 -0.445801 +v -1.217285 0.172363 -0.445801 +v -1.234863 0.262695 -0.424316 +v 1.168457 0.379883 -0.404297 +v 1.208496 0.310547 -0.441895 +v -1.208496 0.310547 -0.441895 +v -1.168457 0.379883 -0.404297 +v 1.028809 0.375488 -0.326660 +v 1.100098 0.358887 -0.397461 +v -1.100098 0.358887 -0.397461 +v -1.028809 0.375488 -0.326660 +v 0.936035 0.329590 -0.260742 +v 0.983887 0.330078 -0.322266 +v -0.936035 0.329590 -0.260742 +v -0.983887 0.330078 -0.322266 +v 0.683594 -0.071777 -0.142090 +v 0.715007 -0.016764 -0.117350 +v 0.736816 0.007812 -0.020508 +v -0.683594 -0.071777 -0.142090 +v -0.736816 0.007812 -0.020508 +v -0.715007 -0.016764 -0.117350 +v 0.698730 -0.113770 -0.174805 +v 0.771484 -0.054199 -0.162598 +v -0.698730 -0.113770 -0.174805 +v -0.771484 -0.054199 -0.162598 +v 0.788574 0.146973 -0.061035 +v -0.788574 0.146973 -0.061035 +v 0.840820 0.312012 -0.199707 +v 0.883789 0.323242 -0.223145 +v 0.854004 0.356445 -0.242188 +v -0.883789 0.323242 -0.223145 +v -0.840820 0.312012 -0.199707 +v -0.854004 0.356445 -0.242188 +v 0.838379 -0.022461 -0.237305 +v 0.778809 -0.017090 -0.217285 +v -0.838379 -0.022461 -0.237305 +v -0.778809 -0.017090 -0.217285 +v 0.780273 0.029297 -0.234863 +v 0.733073 0.006185 -0.182292 +v 0.814941 0.000977 -0.267578 +v -0.733073 0.006185 -0.182292 +v -0.780273 0.029297 -0.234863 +v -0.814941 0.000977 -0.267578 +v 0.759766 0.079590 -0.237305 +v 0.821289 0.052246 -0.273926 +v 0.789062 0.081543 -0.273926 +v -0.759766 0.079590 -0.237305 +v -0.789062 0.081543 -0.273926 +v -0.821289 0.052246 -0.273926 +v 0.812988 0.182129 -0.240234 +v 0.767090 0.127441 -0.190918 +v 0.792969 0.131348 -0.270020 +v -0.767090 0.127441 -0.190918 +v -0.812988 0.182129 -0.240234 +v -0.792969 0.131348 -0.270020 +v 0.828125 0.250977 -0.207520 +v 0.858398 0.211426 -0.268555 +v 0.869141 0.264160 -0.240723 +v -0.828125 0.250977 -0.207520 +v -0.869141 0.264160 -0.240723 +v -0.858398 0.211426 -0.268555 +v 0.914062 0.278320 -0.276367 +v -0.914062 0.278320 -0.276367 +v 0.815430 0.237305 -0.138672 +v -0.815430 0.237305 -0.138672 +v 0.735514 0.046224 -0.132487 +v -0.735514 0.046224 -0.132487 +v 0.891602 0.237305 -0.296387 +v 0.929688 0.255859 -0.329102 +v 0.952148 0.294434 -0.322266 +v -0.891602 0.237305 -0.296387 +v -0.952148 0.294434 -0.322266 +v -0.929688 0.255859 -0.329102 +v 0.836426 0.170410 -0.296387 +v 0.874023 0.195801 -0.316406 +v -0.836426 0.170410 -0.296387 +v -0.874023 0.195801 -0.316406 +v 0.779297 0.102051 -0.296875 +v 0.810547 0.127930 -0.314941 +v -0.779297 0.102051 -0.296875 +v -0.810547 0.127930 -0.314941 +v 0.819336 0.075195 -0.296875 +v 0.804688 0.093262 -0.314941 +v -0.819336 0.075195 -0.296875 +v -0.804688 0.093262 -0.314941 +v 0.840332 0.020020 -0.296875 +v 0.848145 0.052246 -0.315918 +v -0.840332 0.020020 -0.296875 +v -0.848145 0.052246 -0.315918 +v 0.825684 -0.012207 -0.289551 +v 0.841309 0.002930 -0.312012 +v -0.825684 -0.012207 -0.289551 +v -0.841309 0.002930 -0.312012 +v 0.894043 -0.016602 -0.265137 +v 0.853516 -0.009277 -0.291016 +v -0.894043 -0.016602 -0.265137 +v -0.853516 -0.009277 -0.291016 +v 1.001465 0.303711 -0.372559 +v 1.039551 0.333008 -0.387207 +v -1.039551 0.333008 -0.387207 +v -1.001465 0.303711 -0.372559 +v 1.109050 0.332682 -0.437988 +v 1.169434 0.336426 -0.452637 +v -1.169434 0.336426 -0.452637 +v -1.109050 0.332682 -0.437988 +v 1.204590 0.288086 -0.470215 +v 1.231934 0.239746 -0.467285 +v -1.231934 0.239746 -0.467285 +v -1.204590 0.288086 -0.470215 +v 1.212402 0.169434 -0.470215 +v 1.185547 0.098144 -0.456543 +v -1.185547 0.098144 -0.456543 +v -1.212402 0.169434 -0.470215 +v 1.114258 0.057617 -0.437500 +v 1.042480 0.008789 -0.383789 +v -1.042480 0.008789 -0.383789 +v -1.114258 0.057617 -0.437500 +v 0.964844 0.004395 -0.337891 +v -0.964844 0.004395 -0.337891 +v 0.884277 0.039062 -0.323242 +v 0.913086 0.088867 -0.333984 +v 0.856934 0.091797 -0.324219 +v -0.884277 0.039062 -0.323242 +v -0.856934 0.091797 -0.324219 +v -0.913086 0.088867 -0.333984 +v 0.962891 0.086914 -0.349121 +v 0.979004 0.148437 -0.358398 +v 0.923828 0.142578 -0.338867 +v -0.962891 0.086914 -0.349121 +v -0.923828 0.142578 -0.338867 +v -0.979004 0.148437 -0.358398 +v 1.035156 0.147949 -0.383301 +v 1.036133 0.207031 -0.377930 +v 0.984863 0.204590 -0.360840 +v -1.035156 0.147949 -0.383301 +v -0.984863 0.204590 -0.360840 +v -1.036133 0.207031 -0.377930 +v 1.097168 0.201660 -0.398926 +v 1.105469 0.244629 -0.401367 +v 1.047852 0.253906 -0.382813 +v -1.097168 0.201660 -0.398926 +v -1.047852 0.253906 -0.382813 +v -1.105469 0.244629 -0.401367 +v 0.986816 0.259277 -0.361816 +v 1.063151 0.299479 -0.403809 +v -0.986816 0.259277 -0.361816 +v -1.063151 0.299479 -0.403809 +v 0.925781 0.202637 -0.337402 +v -0.925781 0.202637 -0.337402 +v 0.865723 0.141602 -0.325195 +v -0.865723 0.141602 -0.325195 +v 0.914551 0.025391 -0.314941 +v -0.914551 0.025391 -0.314941 +v 1.022949 0.066895 -0.387695 +v -1.022949 0.066895 -0.387695 +v 1.125488 0.138672 -0.429688 +v -1.125488 0.138672 -0.429688 +v 1.171387 0.225586 -0.439941 +v -1.171387 0.225586 -0.439941 +v 1.134440 0.299967 -0.436035 +v -1.134440 0.299967 -0.436035 +v 0.792969 -0.119629 -0.258301 +v 0.916504 -0.042969 -0.390137 +v 1.039062 -0.080078 -0.395996 +v -0.792969 -0.119629 -0.258301 +v -1.039062 -0.080078 -0.395996 +v -0.916504 -0.042969 -0.390137 +v 1.168945 0.041992 -0.495605 +v 1.272461 0.067871 -0.469238 +v -1.272461 0.067871 -0.469238 +v -1.168945 0.041992 -0.495605 +v 1.329427 0.201660 -0.506999 +v 1.336914 0.299316 -0.466309 +v -1.336914 0.299316 -0.466309 +v -1.329427 0.201660 -0.506999 +v 1.306966 0.359375 -0.511393 +v 1.229492 0.461914 -0.470703 +v -1.229492 0.461914 -0.470703 +v -1.306966 0.359375 -0.511393 +v 1.140625 0.399414 -0.496582 +v 1.032227 0.453125 -0.397949 +v -1.032227 0.453125 -0.397949 +v -1.140625 0.399414 -0.496582 +v 0.939941 0.349609 -0.410645 +v 0.883789 0.390137 -0.321289 +v -0.883789 0.390137 -0.321289 +v -0.939941 0.349609 -0.410645 +v 1.036621 0.180664 -0.478027 +v 0.835449 0.134766 -0.381836 +v -1.036621 0.180664 -0.478027 +v -0.835449 0.134766 -0.381836 +v 1.257161 0.253906 -0.529460 +v -1.257161 0.253906 -0.529460 +v 0.808594 0.280762 -0.382324 +v -0.808594 0.280762 -0.382324 +v 0.723633 -0.025879 -0.353516 +v -0.723633 -0.025879 -0.353516 +v 0.438843 0.160767 0.759033 +v -0.438843 0.160767 0.759033 +v 0.487305 0.108154 0.685547 +v -0.487305 0.108154 0.685547 +v 0.532227 0.068359 0.581055 +v -0.532227 0.068359 0.581055 +v 0.351562 -0.003906 0.616211 +v -0.351562 -0.003906 0.616211 +v 0.351685 0.052246 0.713013 +v -0.351685 0.052246 0.713013 +v 0.352417 0.127197 0.776123 +v -0.352417 0.127197 0.776123 +v 0.270142 0.160767 0.790894 +v -0.270142 0.160767 0.790894 +v 0.216675 0.108154 0.734497 +v -0.216675 0.108154 0.734497 +v 0.170898 0.068359 0.645508 +v -0.170898 0.068359 0.645508 +v 0.097656 0.243164 0.654297 +v -0.097656 0.243164 0.654297 +v 0.160645 0.242432 0.738037 +v -0.160645 0.242432 0.738037 +v 0.236572 0.243042 0.792969 +v -0.236572 0.243042 0.792969 +v 0.270142 0.329590 0.790894 +v -0.270142 0.329590 0.790894 +v 0.216675 0.377930 0.734497 +v -0.216675 0.377930 0.734497 +v 0.170898 0.422852 0.645508 +v -0.170898 0.422852 0.645508 +v 0.351562 0.496094 0.616211 +v -0.351562 0.496094 0.616211 +v 0.351685 0.434082 0.713013 +v -0.351685 0.434082 0.713013 +v 0.352417 0.364014 0.776123 +v -0.352417 0.364014 0.776123 +v 0.438843 0.329590 0.759033 +v -0.438843 0.329590 0.759033 +v 0.487305 0.377930 0.685547 +v -0.487305 0.377930 0.685547 +v 0.532227 0.422852 0.581055 +v -0.532227 0.422852 0.581055 +v 0.605469 0.243164 0.566406 +v -0.605469 0.243164 0.566406 +v 0.543457 0.242432 0.672607 +v -0.543457 0.242432 0.672607 +v 0.472656 0.243042 0.751221 +v -0.472656 0.243042 0.751221 +v 0.455404 0.243083 0.778971 +v -0.455404 0.243083 0.778971 +v 0.427531 0.318929 0.785848 +v -0.427531 0.318929 0.785848 +v 0.352458 0.350505 0.803426 +v -0.352458 0.350505 0.803426 +v 0.280924 0.318929 0.816406 +v -0.280924 0.318929 0.816406 +v 0.250244 0.243083 0.818197 +v -0.250244 0.243083 0.818197 +v 0.280924 0.171550 0.816406 +v -0.280924 0.171550 0.816406 +v 0.351969 0.242798 0.822428 +v -0.351969 0.242798 0.822428 +v 0.352458 0.140869 0.803426 +v -0.352458 0.140869 0.803426 +v 0.427531 0.171550 0.785848 +v -0.427531 0.171550 0.785848 +v 0.000000 0.432861 0.736816 +v 0.000000 0.352431 0.809679 +v 0.000000 -0.661133 0.736328 +v 0.000000 -0.306152 0.779297 +v 0.000000 -0.175293 0.791260 +v 0.000000 -0.765137 0.714600 +v 0.000000 0.439046 0.617676 +v 0.000000 0.566551 0.546875 +v 0.000000 0.855713 -0.490723 +v 0.000000 0.518066 -0.772461 +v 0.000000 0.093262 -0.771973 +v 0.000000 -0.352295 -0.304687 +v 0.226929 -0.177246 0.577515 +v -0.226929 -0.177246 0.577515 +v 0.288696 -0.443359 0.565674 +v -0.288696 -0.443359 0.565674 +v 0.323975 -0.664795 0.558960 +v -0.323975 -0.664795 0.558960 +v 0.338867 -0.845703 0.532471 +v -0.338867 -0.845703 0.532471 +v 0.302368 -0.930664 0.526001 +v -0.302368 -0.930664 0.526001 +v 0.171387 -0.960205 0.548950 +v -0.171387 -0.960205 0.548950 +v 0.000000 -0.974121 0.565918 +v 0.427002 -0.116943 0.545776 +v -0.427002 -0.116943 0.545776 +v 0.625366 -0.012573 0.525269 +v -0.625366 -0.012573 0.525269 +v 0.789429 0.167603 0.481934 +v -0.789429 0.167603 0.481934 +v 0.816772 0.393555 0.573364 +v -0.816772 0.393555 0.573364 +v 0.693237 0.479858 0.624512 +v -0.693237 0.479858 0.624512 +v 0.491455 0.592407 0.682251 +v -0.491455 0.592407 0.682251 +v 0.322388 0.711792 0.726685 +v -0.322388 0.711792 0.726685 +v 0.174561 0.676270 0.748169 +v -0.174561 0.676270 0.748169 +v 0.075806 0.499878 0.743896 +v -0.075806 0.499878 0.743896 +v 0.166992 0.407227 0.780640 +v -0.166992 0.407227 0.780640 +v 0.122559 0.310059 0.773926 +v -0.122559 0.310059 0.773926 +v 0.212769 0.071533 0.748657 +v -0.212769 0.071533 0.748657 +v 0.371216 0.027466 0.706543 +v -0.371216 0.027466 0.706543 +v 0.505615 0.075317 0.672729 +v -0.505615 0.075317 0.672729 +v 0.617920 0.189331 0.650635 +v -0.617920 0.189331 0.650635 +v 0.639771 0.300171 0.656006 +v -0.639771 0.300171 0.656006 +v 0.590088 0.376709 0.680542 +v -0.590088 0.376709 0.680542 +v 0.439087 0.443237 0.730469 +v -0.439087 0.443237 0.730469 +v 0.246460 0.473877 0.770996 +v -0.246460 0.473877 0.770996 +v 0.000000 -0.746338 0.732666 +v 0.112500 -0.737188 0.726406 +v -0.112500 -0.737188 0.726406 +v 0.121704 -0.835449 0.702271 +v -0.121704 -0.835449 0.702271 +v 0.071045 -0.882446 0.687744 +v -0.071045 -0.882446 0.687744 +v 0.000000 -0.893310 0.682861 +v 0.000000 -0.163086 0.768555 +v 0.000000 -0.134440 0.747396 +v 0.096069 -0.148437 0.753906 +v -0.096069 -0.148437 0.753906 +v 0.123657 -0.225220 0.750610 +v -0.123657 -0.225220 0.750610 +v 0.089531 -0.299844 0.743984 +v -0.089531 -0.299844 0.743984 +v 0.393799 -0.043579 0.667725 +v -0.393799 -0.043579 0.667725 +v 0.593506 0.050903 0.620850 +v -0.593506 0.050903 0.620850 +v 0.713379 0.197754 0.599365 +v -0.713379 0.197754 0.599365 +v 0.733887 0.355591 0.647339 +v -0.733887 0.355591 0.647339 +v 0.658203 0.427490 0.707153 +v -0.658203 0.427490 0.707153 +v 0.456909 0.536621 0.769775 +v -0.456909 0.536621 0.769775 +v 0.317383 0.619995 0.808838 +v -0.317383 0.619995 0.808838 +v 0.204834 0.592285 0.825439 +v -0.204834 0.592285 0.825439 +v 0.105713 0.447510 0.821411 +v -0.105713 0.447510 0.821411 +v 0.142415 -0.096300 0.776693 +v -0.142415 -0.096300 0.776693 +v 0.208252 -0.459473 0.695435 +v -0.208252 -0.459473 0.695435 +v 0.242798 -0.682739 0.678345 +v -0.242798 -0.682739 0.678345 +v 0.253784 -0.813354 0.655640 +v -0.253784 -0.813354 0.655640 +v 0.225098 -0.899292 0.632568 +v -0.225098 -0.899292 0.632568 +v 0.143921 -0.927978 0.631592 +v -0.143921 -0.927978 0.631592 +v 0.000000 -0.939697 0.636719 +v 0.000000 0.041558 0.738824 +v 0.000000 0.209473 0.765137 +v 0.329956 0.484375 0.755249 +v -0.329956 0.484375 0.755249 +v 0.149536 0.133545 0.752197 +v -0.149536 0.133545 0.752197 +v 0.123657 0.213989 0.761841 +v -0.123657 0.213989 0.761841 +v 0.114380 -0.664185 0.730225 +v -0.114380 -0.664185 0.730225 +v 0.089478 -0.457153 0.742188 +v -0.089478 -0.457153 0.742188 +v 0.000000 -0.458984 0.747070 +v 0.000000 -0.333008 0.748047 +v 0.084229 -0.272339 0.781250 +v -0.084229 -0.272339 0.781250 +v 0.121338 -0.221191 0.791138 +v -0.121338 -0.221191 0.791138 +v 0.100342 -0.147827 0.782104 +v -0.100342 -0.147827 0.782104 +v 0.039673 -0.138428 0.782104 +v -0.039673 -0.138428 0.782104 +v 0.000000 -0.202365 0.823351 +v 0.047743 -0.157769 0.809028 +v -0.047743 -0.157769 0.809028 +v 0.088108 -0.165148 0.809028 +v -0.088108 -0.165148 0.809028 +v 0.093994 -0.218994 0.819458 +v -0.093994 -0.218994 0.819458 +v 0.070095 -0.256510 0.804471 +v -0.070095 -0.256510 0.804471 +v 0.000000 -0.274170 0.804688 +v 0.246460 -0.315674 0.560303 +v -0.246460 -0.315674 0.560303 +v 0.164673 -0.234375 0.705688 +v -0.164673 -0.234375 0.705688 +v 0.180176 -0.317871 0.695801 +v -0.180176 -0.317871 0.695801 +v 0.221558 -0.244995 0.565674 +v -0.221558 -0.244995 0.565674 +v 0.000000 -0.873047 0.680908 +v 0.048706 -0.862427 0.684082 +v -0.048706 -0.862427 0.684082 +v 0.090576 -0.816894 0.701782 +v -0.090576 -0.816894 0.701782 +v 0.083862 -0.754517 0.716675 +v -0.083862 -0.754517 0.716675 +v 0.000000 -0.782959 0.662842 +v 0.077393 -0.771606 0.664876 +v -0.077393 -0.771606 0.664876 +v 0.084201 -0.809245 0.658782 +v -0.084201 -0.809245 0.658782 +v 0.051025 -0.838623 0.644247 +v -0.051025 -0.838623 0.644247 +v 0.000000 -0.848877 0.642822 +v 0.172607 0.220825 0.773804 +v -0.172607 0.220825 0.773804 +v 0.189331 0.158203 0.769165 +v -0.189331 0.158203 0.769165 +v 0.337891 0.427857 0.757935 +v -0.337891 0.427857 0.757935 +v 0.271484 0.419922 0.769409 +v -0.271484 0.419922 0.769409 +v 0.428711 0.399902 0.753296 +v -0.428711 0.399902 0.753296 +v 0.548950 0.350830 0.697632 +v -0.548950 0.350830 0.697632 +v 0.584595 0.285400 0.681030 +v -0.584595 0.285400 0.681030 +v 0.568237 0.195679 0.680054 +v -0.568237 0.195679 0.680054 +v 0.476807 0.105957 0.709473 +v -0.476807 0.105957 0.709473 +v 0.369019 0.070679 0.737061 +v -0.369019 0.070679 0.737061 +v 0.239380 0.109009 0.767944 +v -0.239380 0.109009 0.767944 +v 0.178345 0.297974 0.776245 +v -0.178345 0.297974 0.776245 +v 0.211792 0.373779 0.776367 +v -0.211792 0.373779 0.776367 +v 0.235352 0.356445 0.758789 +v -0.235352 0.356445 0.758789 +v 0.200195 0.295898 0.756836 +v -0.200195 0.295898 0.756836 +v 0.253906 0.125977 0.752930 +v -0.253906 0.125977 0.752930 +v 0.369141 0.094727 0.727539 +v -0.369141 0.094727 0.727539 +v 0.460938 0.125000 0.702148 +v -0.460938 0.125000 0.702148 +v 0.537109 0.208008 0.675781 +v -0.537109 0.208008 0.675781 +v 0.550781 0.279297 0.672852 +v -0.550781 0.279297 0.672852 +v 0.519531 0.335938 0.687500 +v -0.519531 0.335938 0.687500 +v 0.418945 0.385742 0.741211 +v -0.418945 0.385742 0.741211 +v 0.282227 0.394531 0.762695 +v -0.282227 0.394531 0.762695 +v 0.338867 0.403320 0.751953 +v -0.338867 0.403320 0.751953 +v 0.207031 0.172852 0.750977 +v -0.207031 0.172852 0.750977 +v 0.196289 0.228516 0.750977 +v -0.196289 0.228516 0.750977 +v 0.125521 0.489245 0.612891 +v -0.125521 0.489245 0.612891 +v 0.205729 0.638021 0.640625 +v -0.205729 0.638021 0.640625 +v 0.327691 0.665365 0.622179 +v -0.327691 0.665365 0.622179 +v 0.458125 0.553438 0.557578 +v -0.458125 0.553438 0.557578 +v 0.668091 0.463501 0.489014 +v -0.668091 0.463501 0.489014 +v 0.780396 0.385376 0.449707 +v -0.780396 0.385376 0.449707 +v 0.769775 0.177979 0.363892 +v -0.769775 0.177979 0.363892 +v 0.619507 -0.000366 0.387573 +v -0.619507 -0.000366 0.387573 +v 0.416667 -0.110781 0.449245 +v -0.416667 -0.110781 0.449245 +v 0.000000 0.856201 0.263916 +v 0.000000 0.950195 -0.085938 +v 0.000000 -0.175049 -0.618652 +v 0.000000 -0.436523 0.129395 +v 0.000000 -0.948242 0.456543 +v 0.000000 -0.786133 0.360352 +v 0.000000 -0.579346 0.325684 +v 0.000000 -0.475830 0.270508 +v 0.814697 0.226074 0.114136 +v -0.814697 0.226074 0.114136 +v 0.836328 0.300938 -0.049844 +v -0.836328 0.300938 -0.049844 +v 0.762813 0.282891 -0.418750 +v -0.762813 0.282891 -0.418750 +v 0.408691 0.442139 -0.665405 +v -0.408691 0.442139 -0.665405 +v 0.700312 -0.032500 0.072812 +v -0.700312 -0.032500 0.072812 +v 0.616094 -0.109531 -0.167969 +v -0.616094 -0.109531 -0.167969 +v 0.649780 0.005127 -0.400513 +v -0.649780 0.005127 -0.400513 +v 0.325521 0.077148 -0.660970 +v -0.325521 0.077148 -0.660970 +v 0.236694 -0.381103 0.408814 +v -0.236694 -0.381103 0.408814 +v 0.161865 -0.426758 0.279297 +v -0.161865 -0.426758 0.279297 +v 0.279541 -0.735840 0.403076 +v -0.279541 -0.735840 0.403076 +v 0.250000 -0.535644 0.407837 +v -0.250000 -0.535644 0.407837 +v 0.286024 -0.887153 0.430339 +v -0.286024 -0.887153 0.430339 +v 0.142334 -0.753784 0.373901 +v -0.142334 -0.753784 0.373901 +v 0.131958 -0.550171 0.349487 +v -0.131958 -0.550171 0.349487 +v 0.162720 -0.924683 0.441650 +v -0.162720 -0.924683 0.441650 +v 0.235833 -0.284766 0.404818 +v -0.235833 -0.284766 0.404818 +v 0.239176 -0.215210 0.474040 +v -0.239176 -0.215210 0.474040 +v 0.253111 -0.171658 0.501809 +v -0.253111 -0.171658 0.501809 +v 0.212630 -0.369297 0.155833 +v -0.212630 -0.369297 0.155833 +v 0.273193 -0.293091 -0.251099 +v -0.273193 -0.293091 -0.251099 +v 0.310872 -0.132080 -0.535482 +v -0.310872 -0.132080 -0.535482 +v 0.420288 0.804932 -0.407593 +v -0.420288 0.804932 -0.407593 +v 0.419922 0.896362 -0.089233 +v -0.419922 0.896362 -0.089233 +v 0.420532 0.808472 0.206787 +v -0.420532 0.808472 0.206787 +v 0.428833 0.561523 0.418091 +v -0.428833 0.561523 0.418091 +v 0.743408 0.409424 0.289062 +v -0.743408 0.409424 0.289062 +v 0.630615 0.487549 0.302734 +v -0.630615 0.487549 0.302734 +v 0.635010 0.679565 0.081543 +v -0.635010 0.679565 0.081543 +v 0.777710 0.535889 0.090576 +v -0.777710 0.535889 0.090576 +v 0.780151 0.582275 -0.138916 +v -0.780151 0.582275 -0.138916 +v 0.636719 0.740601 -0.170044 +v -0.636719 0.740601 -0.170044 +v 0.634277 0.650391 -0.414063 +v -0.634277 0.650391 -0.414063 +v 0.758247 0.524089 -0.343750 +v -0.758247 0.524089 -0.343750 +v 0.603149 0.339111 -0.558228 +v -0.603149 0.339111 -0.558228 +v 0.482005 0.019531 -0.522786 +v -0.482005 0.019531 -0.522786 +v 0.824766 0.347656 -0.205313 +v -0.824766 0.347656 -0.205313 +v 0.405755 -0.181641 0.158802 +v -0.405755 -0.181641 0.158802 +v 0.438843 -0.174072 -0.207764 +v -0.438843 -0.174072 -0.207764 +v 0.897949 0.395508 -0.258789 +v -0.897949 0.395508 -0.258789 +v 0.793335 -0.121094 -0.181519 +v -0.793335 -0.121094 -0.181519 +v 1.035889 -0.077881 -0.333130 +v -1.035889 -0.077881 -0.333130 +v 1.254883 0.070923 -0.426514 +v -1.254883 0.070923 -0.426514 +v 1.320435 0.304077 -0.431397 +v -1.320435 0.304077 -0.431397 +v 1.218506 0.467773 -0.420288 +v -1.218506 0.467773 -0.420288 +v 1.031982 0.459351 -0.333862 +v -1.031982 0.459351 -0.333862 +v 1.027222 0.409180 -0.304321 +v -1.027222 0.409180 -0.304321 +v 1.179810 0.415039 -0.389526 +v -1.179810 0.415039 -0.389526 +v 1.255371 0.280273 -0.411621 +v -1.255371 0.280273 -0.411621 +v 1.200806 0.088623 -0.401611 +v -1.200806 0.088623 -0.401611 +v 1.030518 -0.031006 -0.306030 +v -1.030518 -0.031006 -0.306030 +v 0.839600 -0.064575 -0.168579 +v -0.839600 -0.064575 -0.168579 +v 0.923706 0.356445 -0.236816 +v -0.923706 0.356445 -0.236816 +v 0.946167 0.306885 -0.293213 +v -0.946167 0.306885 -0.293213 +v 0.886963 -0.023926 -0.235107 +v -0.886963 -0.023926 -0.235107 +v 1.037964 0.004150 -0.356323 +v -1.037964 0.004150 -0.356323 +v 1.180054 0.099243 -0.435547 +v -1.180054 0.099243 -0.435547 +v 1.227051 0.247681 -0.445068 +v -1.227051 0.247681 -0.445068 +v 1.165039 0.350952 -0.428589 +v -1.165039 0.350952 -0.428589 +v 1.033203 0.347534 -0.358643 +v -1.033203 0.347534 -0.358643 +v 0.851318 0.287598 -0.216064 +v -0.851318 0.287598 -0.216064 +v 0.828857 0.173584 -0.270386 +v -0.828857 0.173584 -0.270386 +v 0.772461 0.096680 -0.270264 +v -0.772461 0.096680 -0.270264 +v 0.811632 0.071181 -0.281467 +v -0.811632 0.071181 -0.281467 +v 0.823608 0.022583 -0.269653 +v -0.823608 0.022583 -0.269653 +v 0.813721 -0.013672 -0.259521 +v -0.813721 -0.013672 -0.259521 +v 0.739176 0.032064 -0.078288 +v -0.739176 0.032064 -0.078288 +v 0.727526 -0.027448 -0.168229 +v -0.727526 -0.027448 -0.168229 +v 0.738307 0.048411 -0.191979 +v -0.738307 0.048411 -0.191979 +v 0.803589 0.201538 -0.198730 +v -0.803589 0.201538 -0.198730 +v 0.885498 0.245972 -0.269043 +v -0.885498 0.245972 -0.269043 +v 0.900635 0.226685 -0.320068 +v -0.900635 0.226685 -0.320068 +v 0.837023 -0.007596 -0.299479 +v -0.837023 -0.007596 -0.299479 +v 0.853027 0.024536 -0.315186 +v -0.853027 0.024536 -0.315186 +v 0.830688 0.077881 -0.315430 +v -0.830688 0.077881 -0.315430 +v 0.794705 0.106554 -0.310113 +v -0.794705 0.106554 -0.310113 +v 0.845459 0.162964 -0.315552 +v -0.845459 0.162964 -0.315552 +v 1.049113 0.320719 -0.404785 +v -1.049113 0.320719 -0.404785 +v 1.164836 0.323649 -0.460449 +v -1.164836 0.323649 -0.460449 +v 1.222412 0.234009 -0.471924 +v -1.222412 0.234009 -0.471924 +v 1.175903 0.106567 -0.460327 +v -1.175903 0.106567 -0.460327 +v 1.039795 0.023315 -0.397949 +v -1.039795 0.023315 -0.397949 +v 0.899414 -0.004639 -0.291016 +v -0.899414 -0.004639 -0.291016 +v 0.962769 0.281982 -0.345825 +v -0.962769 0.281982 -0.345825 +v 0.890503 0.114258 -0.329834 +v -0.890503 0.114258 -0.329834 +v 0.924194 0.060791 -0.331177 +v -0.924194 0.060791 -0.331177 +v 1.000000 0.116333 -0.369141 +v -1.000000 0.116333 -0.369141 +v 0.955688 0.173706 -0.349731 +v -0.955688 0.173706 -0.349731 +v 1.014526 0.232300 -0.371948 +v -1.014526 0.232300 -0.371948 +v 1.067749 0.177734 -0.392822 +v -1.067749 0.177734 -0.392822 +v 1.123481 0.223524 -0.411024 +v -1.123481 0.223524 -0.411024 +v 1.087077 0.274699 -0.401489 +v -1.087077 0.274699 -0.401489 +v 1.032837 0.375732 -0.458740 +v -1.032837 0.375732 -0.458740 +v 1.239828 0.400635 -0.516642 +v -1.239828 0.400635 -0.516642 +v 1.328270 0.287543 -0.496600 +v -1.328270 0.287543 -0.496600 +v 1.274984 0.114136 -0.510905 +v -1.274984 0.114136 -0.510905 +v 1.039917 -0.011475 -0.456787 +v -1.039917 -0.011475 -0.456787 +v 0.807983 -0.048950 -0.340698 +v -0.807983 -0.048950 -0.340698 +v 0.864380 0.318726 -0.376953 +v -0.864380 0.318726 -0.376953 +vt 0.481096 0.886074 +vt 0.482512 0.871343 +vt 0.492098 0.872954 +vt 0.490947 0.884499 +vt 0.491589 0.894442 +vt 0.481943 0.898903 +vt 0.468931 0.904205 +vt 0.467876 0.887817 +vt 0.469678 0.869121 +vt 0.039865 0.789567 +vt 0.041625 0.780388 +vt 0.054224 0.794512 +vt 0.049723 0.800654 +vt 0.045817 0.805288 +vt 0.038183 0.796684 +vt 0.028138 0.791794 +vt 0.027075 0.783199 +vt 0.025414 0.772242 +vt 0.453331 0.888300 +vt 0.455522 0.866536 +vt 0.454431 0.907321 +vt 0.439187 0.909345 +vt 0.438123 0.888153 +vt 0.440706 0.863769 +vt 0.041466 0.772283 +vt 0.040348 0.764715 +vt 0.056528 0.783129 +vt 0.056046 0.788730 +vt 0.022611 0.762815 +vt 0.019237 0.754154 +vt 0.458805 0.920523 +vt 0.472714 0.915572 +vt 0.749184 0.938074 +vt 0.748278 0.934282 +vt 0.759252 0.918124 +vt 0.762017 0.919061 +vt 0.465365 0.926301 +vt 0.451444 0.930481 +vt 0.444047 0.924041 +vt 0.063804 0.810211 +vt 0.065049 0.807405 +vt 0.065118 0.833437 +vt 0.063980 0.833149 +vt 0.061159 0.832400 +vt 0.060952 0.812869 +vt 0.484928 0.907759 +vt 0.493982 0.901303 +vt 0.744531 0.928959 +vt 0.741167 0.924705 +vt 0.748008 0.914379 +vt 0.753171 0.916091 +vt 0.054886 0.815232 +vt 0.054967 0.830731 +vt 0.049720 0.829302 +vt 0.049731 0.816915 +vt 0.756342 0.901570 +vt 0.750577 0.903021 +vt 0.748805 0.892144 +vt 0.753972 0.887511 +vt 0.760122 0.881485 +vt 0.763209 0.899571 +vt 0.049579 0.844583 +vt 0.054194 0.850046 +vt 0.041620 0.863407 +vt 0.039829 0.854986 +vt 0.038086 0.848267 +vt 0.045578 0.840185 +vt 0.766729 0.897198 +vt 0.763269 0.875942 +vt 0.764914 0.870640 +vt 0.768574 0.894639 +vt 0.763124 0.919450 +vt 0.964742 0.269659 +vt 0.951782 0.275614 +vt 0.952007 0.261999 +vt 0.964824 0.257430 +vt 0.976538 0.251908 +vt 0.976518 0.262435 +vt 0.055814 0.853969 +vt 0.055937 0.857122 +vt 0.751588 0.858748 +vt 0.749963 0.866729 +vt 0.734897 0.857300 +vt 0.734094 0.847799 +vt 0.732482 0.839216 +vt 0.752037 0.851423 +vt 0.964411 0.238893 +vt 0.951889 0.241320 +vt 0.951838 0.216860 +vt 0.964164 0.217079 +vt 0.975596 0.217228 +vt 0.975962 0.235954 +vt 0.745987 0.876023 +vt 0.742625 0.883261 +vt 0.733275 0.877508 +vt 0.734081 0.868638 +vt 0.985568 0.231991 +vt 0.985239 0.217237 +vt 0.992484 0.217197 +vt 0.992737 0.228767 +vt 0.026822 0.860140 +vt 0.028024 0.852250 +vt 0.024995 0.870082 +vt 0.719950 0.866886 +vt 0.721994 0.876021 +vt 0.710661 0.878758 +vt 0.705761 0.870592 +vt 0.699169 0.860094 +vt 0.717087 0.855192 +vt 0.576905 0.857737 +vt 0.588803 0.851307 +vt 0.593086 0.864077 +vt 0.580353 0.867693 +vt 0.570785 0.870708 +vt 0.567903 0.862933 +vt 0.563366 0.858817 +vt 0.571275 0.852489 +vt 0.581714 0.844594 +vt 0.836115 0.475434 +vt 0.838688 0.453512 +vt 0.829257 0.452073 +vt 0.826911 0.470779 +vt 0.826265 0.486994 +vt 0.835616 0.494473 +vt 0.846311 0.501639 +vt 0.846555 0.480014 +vt 0.849257 0.455181 +vt 0.601676 0.847373 +vt 0.615035 0.844686 +vt 0.621303 0.861691 +vt 0.606920 0.862400 +vt 0.593217 0.839496 +vt 0.964741 0.195019 +vt 0.952261 0.191899 +vt 0.838079 0.507319 +vt 0.828287 0.497991 +vt 0.662030 0.916118 +vt 0.649717 0.909228 +vt 0.659213 0.892314 +vt 0.673156 0.896153 +vt 0.687752 0.900137 +vt 0.675171 0.922841 +vt 0.849254 0.516083 +vt 0.608285 0.882997 +vt 0.622902 0.885054 +vt 0.620138 0.910863 +vt 0.605906 0.905728 +vt 0.592291 0.900850 +vt 0.594249 0.881552 +vt 0.639060 0.902006 +vt 0.630378 0.912575 +vt 0.624285 0.904606 +vt 0.631184 0.896458 +vt 0.637168 0.886101 +vt 0.646574 0.888766 +vt 0.638716 0.922856 +vt 0.581378 0.881332 +vt 0.579910 0.896484 +vt 0.570683 0.893256 +vt 0.571743 0.881341 +vt 0.651614 0.874590 +vt 0.641253 0.874767 +vt 0.642753 0.864493 +vt 0.653466 0.861765 +vt 0.667869 0.858377 +vt 0.665543 0.874471 +vt 0.677925 0.498737 +vt 0.689335 0.506109 +vt 0.689458 0.495315 +vt 0.677981 0.490263 +vt 0.669579 0.486309 +vt 0.669554 0.492981 +vt 0.575881 0.910980 +vt 0.567507 0.904876 +vt 0.587208 0.919088 +vt 0.680581 0.875178 +vt 0.683263 0.856306 +vt 0.699152 0.854893 +vt 0.696173 0.876297 +vt 0.702733 0.511573 +vt 0.717126 0.516083 +vt 0.717096 0.501984 +vt 0.702809 0.498993 +vt 0.599917 0.927158 +vt 0.613317 0.935209 +vt 0.680163 0.842652 +vt 0.665352 0.846712 +vt 0.461024 0.845105 +vt 0.474464 0.850828 +vt 0.446789 0.839496 +vt 0.695411 0.839496 +vt 0.700973 0.480098 +vt 0.714803 0.480610 +vt 0.710837 0.455956 +vt 0.697576 0.458288 +vt 0.685199 0.460521 +vt 0.688021 0.479168 +vt 0.651414 0.852579 +vt 0.640983 0.857312 +vt 0.486314 0.856780 +vt 0.495081 0.861287 +vt 0.013120 0.782779 +vt 0.007853 0.771817 +vt 0.016991 0.791306 +vt 0.676828 0.477398 +vt 0.668601 0.475975 +vt 0.499276 0.862675 +vt 0.496506 0.873707 +vt 0.636693 0.857970 +vt 0.638428 0.864587 +vt 0.634842 0.865361 +vt 0.633769 0.858828 +vt 0.501933 0.863788 +vt 0.499717 0.874300 +vt 0.664548 0.476086 +vt 0.662006 0.475916 +vt 0.662523 0.484818 +vt 0.665453 0.485920 +vt 0.666786 0.464098 +vt 0.662812 0.464867 +vt 0.660119 0.465346 +vt 0.636917 0.874237 +vt 0.632924 0.884910 +vt 0.629586 0.884020 +vt 0.633906 0.874069 +vt 0.563655 0.902816 +vt 0.561094 0.901223 +vt 0.563284 0.890597 +vt 0.566525 0.891789 +vt 0.665273 0.492365 +vt 0.662491 0.491556 +vt 0.627212 0.894590 +vt 0.067509 0.725084 +vt 0.071466 0.726806 +vt 0.069637 0.720075 +vt 0.065802 0.718615 +vt 0.063547 0.716803 +vt 0.065074 0.723573 +vt 0.624547 0.893296 +vt 0.567420 0.880585 +vt 0.564496 0.880111 +vt 0.563155 0.870915 +vt 0.566449 0.870584 +vt 0.065634 0.708733 +vt 0.069457 0.709685 +vt 0.070270 0.697702 +vt 0.066397 0.697410 +vt 0.064083 0.697195 +vt 0.063357 0.707910 +vt 0.997139 0.205853 +vt 0.999711 0.206503 +vt 0.999443 0.217239 +vt 0.996724 0.217198 +vt 0.992914 0.205191 +vt 0.563721 0.863167 +vt 0.561034 0.863404 +vt 0.067484 0.686620 +vt 0.071422 0.686190 +vt 0.742845 0.885075 +vt 0.748606 0.893511 +vt 0.747773 0.894733 +vt 0.742851 0.886280 +vt 0.734397 0.881643 +vt 0.734108 0.879604 +vt 0.996973 0.228043 +vt 0.999553 0.227516 +vt 1.000000 0.235714 +vt 0.997287 0.237123 +vt 0.993056 0.238446 +vt 0.750361 0.903747 +vt 0.063028 0.610557 +vt 0.058507 0.610915 +vt 0.058509 0.622843 +vt 0.062932 0.621762 +vt 0.748000 0.914410 +vt 0.747405 0.914179 +vt 0.750107 0.904237 +vt 0.045800 0.839461 +vt 0.045860 0.838912 +vt 0.049106 0.829135 +vt 0.049730 0.829272 +vt 0.997066 0.243173 +vt 0.992827 0.244780 +vt 0.999732 0.242058 +vt 0.498412 0.900428 +vt 0.501974 0.903367 +vt 0.497566 0.904311 +vt 0.495994 0.893850 +vt 0.499240 0.892977 +vt 0.501280 0.899786 +vt 0.741411 0.924123 +vt 0.741562 0.923508 +vt 0.049612 0.817535 +vt 0.049397 0.818131 +vt 0.045108 0.808121 +vt 0.045783 0.806548 +vt 0.062884 0.599126 +vt 0.058508 0.598012 +vt 0.058499 0.610092 +vt 0.495385 0.884521 +vt 0.498248 0.884476 +vt 0.038578 0.798606 +vt 0.038639 0.800269 +vt 0.029632 0.796769 +vt 0.029145 0.794131 +vt 0.660500 0.454268 +vt 0.664299 0.452794 +vt 0.723993 0.925671 +vt 0.718115 0.922183 +vt 0.726149 0.906586 +vt 0.730681 0.921604 +vt 0.732452 0.929475 +vt 0.722720 0.932439 +vt 0.713279 0.930374 +vt 0.035957 0.806612 +vt 0.029131 0.806267 +vt 0.039279 0.813699 +vt 0.027198 0.823705 +vt 0.737919 0.919156 +vt 0.740484 0.911683 +vt 0.043956 0.819742 +vt 0.041960 0.827387 +vt 0.744228 0.904980 +vt 0.740703 0.898933 +vt 0.041371 0.835042 +vt 0.038658 0.845540 +vt 0.035091 0.838131 +vt 0.738851 0.891691 +vt 0.731957 0.890340 +vt 0.029542 0.843140 +vt 0.029883 0.849860 +vt 0.020274 0.849047 +vt 0.023052 0.840452 +vt 0.725318 0.886942 +vt 0.718933 0.891293 +vt 0.714474 0.883047 +vt 0.724464 0.879828 +vt 0.015641 0.839612 +vt 0.010995 0.845067 +vt 0.004452 0.836859 +vt 0.012728 0.832455 +vt 0.711278 0.893417 +vt 0.709446 0.900791 +vt 0.700040 0.897557 +vt 0.705463 0.888570 +vt 0.007524 0.826452 +vt 0.000000 0.827274 +vt 0.000451 0.816788 +vt 0.010077 0.819296 +vt 0.704969 0.907593 +vt 0.708910 0.913964 +vt 0.627520 0.875332 +vt 0.626348 0.870133 +vt 0.622902 0.882261 +vt 0.010109 0.811152 +vt 0.003538 0.806493 +vt 0.010902 0.799441 +vt 0.016916 0.808024 +vt 0.710460 0.920922 +vt 0.704332 0.925987 +vt 0.699153 0.917789 +vt 0.022055 0.803084 +vt 0.019752 0.795475 +vt 0.992866 0.383426 +vt 0.981805 0.383672 +vt 0.979426 0.405182 +vt 0.991312 0.403568 +vt 0.112970 0.007488 +vt 0.132821 0.002970 +vt 0.128413 0.006026 +vt 0.111367 0.010033 +vt 0.092459 0.015988 +vt 0.091733 0.014053 +vt 0.993949 0.361255 +vt 0.983204 0.361005 +vt 0.071419 0.023077 +vt 0.074301 0.023939 +vt 0.058825 0.032133 +vt 0.053495 0.032731 +vt 0.993901 0.339058 +vt 0.993288 0.318866 +vt 0.981490 0.316699 +vt 0.982863 0.338296 +vt 0.678945 0.437389 +vt 0.668474 0.428378 +vt 0.669342 0.421808 +vt 0.680671 0.432693 +vt 0.148976 0.000088 +vt 0.161467 0.000000 +vt 0.150417 0.005006 +vt 0.140987 0.003919 +vt 0.989944 0.419678 +vt 0.976830 0.424417 +vt 0.039431 0.041186 +vt 0.047968 0.038818 +vt 0.041580 0.045839 +vt 0.029965 0.049336 +vt 0.992673 0.302709 +vt 0.993707 0.291005 +vt 0.979586 0.282825 +vt 0.979794 0.297364 +vt 0.686993 0.428080 +vt 0.675068 0.415649 +vt 0.686622 0.408289 +vt 0.698060 0.422330 +vt 0.714840 0.430086 +vt 0.703100 0.435653 +vt 0.694523 0.440226 +vt 0.025837 0.058073 +vt 0.039512 0.055041 +vt 0.041090 0.065620 +vt 0.026724 0.068694 +vt 0.021981 0.077227 +vt 0.019792 0.065292 +vt 0.023878 0.055454 +vt 0.714023 0.414220 +vt 0.704972 0.398117 +vt 0.727630 0.384752 +vt 0.734669 0.402476 +vt 0.745026 0.413812 +vt 0.727849 0.423582 +vt 0.032306 0.082496 +vt 0.045644 0.076769 +vt 0.053962 0.091852 +vt 0.042095 0.100690 +vt 0.887880 0.777665 +vt 0.887591 0.801327 +vt 0.904979 0.804846 +vt 0.904907 0.778624 +vt 0.905747 0.757689 +vt 0.889333 0.759830 +vt 0.759784 0.385827 +vt 0.752111 0.367817 +vt 0.774115 0.351321 +vt 0.783509 0.368858 +vt 0.793521 0.382130 +vt 0.769270 0.398444 +vt 0.055601 0.124487 +vt 0.066835 0.114230 +vt 0.080513 0.137227 +vt 0.069812 0.147649 +vt 0.889469 0.831328 +vt 0.892558 0.860292 +vt 0.910958 0.861718 +vt 0.907395 0.834463 +vt 0.851947 0.314539 +vt 0.851757 0.327390 +vt 0.831038 0.312464 +vt 0.832467 0.302566 +vt 0.833390 0.290527 +vt 0.849940 0.298952 +vt 0.868449 0.303928 +vt 0.873735 0.321132 +vt 0.881184 0.341525 +vt 0.090857 0.225638 +vt 0.097129 0.228716 +vt 0.071577 0.249803 +vt 0.065428 0.246873 +vt 0.061518 0.247399 +vt 0.085791 0.228286 +vt 0.370922 0.611255 +vt 0.347956 0.609997 +vt 0.352910 0.631669 +vt 0.378467 0.633670 +vt 0.109282 0.207988 +vt 0.124218 0.205325 +vt 0.853420 0.284963 +vt 0.838559 0.278740 +vt 0.846452 0.263753 +vt 0.860695 0.269659 +vt 0.875270 0.273461 +vt 0.869419 0.288575 +vt 0.295480 0.173792 +vt 0.292477 0.180146 +vt 0.261983 0.178368 +vt 0.264687 0.172116 +vt 0.043337 0.268389 +vt 0.049778 0.271200 +vt 0.032835 0.293339 +vt 0.025431 0.291729 +vt 0.023037 0.290644 +vt 0.040664 0.267368 +vt 0.870072 0.250126 +vt 0.855550 0.242111 +vt 0.871931 0.221180 +vt 0.885557 0.231754 +vt 0.898576 0.241924 +vt 0.884629 0.256976 +vt 0.012557 0.318434 +vt 0.021853 0.316649 +vt 0.016936 0.339078 +vt 0.006033 0.345191 +vt 0.000000 0.349839 +vt 0.008446 0.319679 +vt 0.911154 0.219934 +vt 0.901671 0.208327 +vt 0.931401 0.202057 +vt 0.936637 0.214214 +vt 0.937543 0.225359 +vt 0.918190 0.231111 +vt 0.007172 0.368688 +vt 0.018190 0.358571 +vt 0.023626 0.371983 +vt 0.014248 0.384675 +vt 0.009291 0.394704 +vt 0.000809 0.376493 +vt 0.414625 0.533938 +vt 0.415837 0.524795 +vt 0.427421 0.516083 +vt 0.427586 0.528035 +vt 0.427770 0.548000 +vt 0.413253 0.551420 +vt 0.403024 0.558206 +vt 0.405342 0.544215 +vt 0.951782 0.214145 +vt 0.950704 0.225487 +vt 0.025530 0.388905 +vt 0.031255 0.376169 +vt 0.045940 0.375827 +vt 0.043685 0.387764 +vt 0.805497 0.532629 +vt 0.796288 0.528110 +vt 0.792623 0.542154 +vt 0.801837 0.544945 +vt 0.816055 0.549878 +vt 0.818184 0.538527 +vt 0.413768 0.577396 +vt 0.428650 0.573549 +vt 0.430752 0.600019 +vt 0.415764 0.604818 +vt 0.404473 0.610171 +vt 0.403038 0.583196 +vt 0.071377 0.387636 +vt 0.072539 0.375659 +vt 0.101657 0.376371 +vt 0.101340 0.389255 +vt 0.782035 0.523910 +vt 0.765328 0.520395 +vt 0.762459 0.535210 +vt 0.779054 0.538594 +vt 0.418834 0.626637 +vt 0.434600 0.622748 +vt 0.437199 0.643422 +vt 0.420715 0.645356 +vt 0.407406 0.646101 +vt 0.406417 0.630117 +vt 0.126308 0.393352 +vt 0.123898 0.378671 +vt 0.141075 0.378874 +vt 0.146881 0.394708 +vt 0.748752 0.517932 +vt 0.737337 0.516083 +vt 0.730886 0.531208 +vt 0.744161 0.532946 +vt 0.419140 0.663477 +vt 0.435553 0.663724 +vt 0.657824 0.993693 +vt 0.672162 1.001452 +vt 0.668198 0.991199 +vt 0.654312 0.984171 +vt 0.283593 0.343106 +vt 0.264869 0.339860 +vt 0.264430 0.323794 +vt 0.280370 0.326261 +vt 0.405975 0.661187 +vt 0.425089 0.791435 +vt 0.412194 0.794938 +vt 0.406521 0.781129 +vt 0.418310 0.775343 +vt 0.433950 0.772028 +vt 0.441409 0.789667 +vt 0.444931 0.809729 +vt 0.428339 0.809333 +vt 0.163659 0.388102 +vt 0.155007 0.373294 +vt 0.652107 0.963208 +vt 0.665811 0.968984 +vt 0.664616 0.945784 +vt 0.651100 0.940913 +vt 0.245042 0.326495 +vt 0.226606 0.311812 +vt 0.228426 0.300692 +vt 0.246295 0.312965 +vt 0.407856 0.761945 +vt 0.397478 0.768360 +vt 0.388635 0.756339 +vt 0.397889 0.750292 +vt 0.412277 0.747509 +vt 0.422810 0.758473 +vt 0.651184 0.927396 +vt 0.664231 0.932578 +vt 0.663861 0.928495 +vt 0.651073 0.922856 +vt 0.212056 0.304615 +vt 0.200794 0.304747 +vt 0.195271 0.290025 +vt 0.213285 0.293892 +vt 0.392572 0.739432 +vt 0.383565 0.744773 +vt 0.378467 0.729486 +vt 0.390830 0.728911 +vt 0.404824 0.728260 +vt 0.406639 0.737642 +vt 0.249748 0.303145 +vt 0.234335 0.294368 +vt 0.241237 0.289791 +vt 0.253723 0.295436 +vt 0.266382 0.298398 +vt 0.265180 0.309822 +vt 0.162867 0.335741 +vt 0.171927 0.340866 +vt 0.165391 0.360951 +vt 0.155635 0.350920 +vt 0.147216 0.343106 +vt 0.154802 0.332549 +vt 0.160494 0.320083 +vt 0.168703 0.318991 +vt 0.177313 0.319868 +vt 0.278494 0.310851 +vt 0.277505 0.298165 +vt 0.287985 0.294603 +vt 0.290542 0.306714 +vt 0.294533 0.321300 +vt 0.146284 0.360453 +vt 0.134487 0.365262 +vt 0.128448 0.354457 +vt 0.138684 0.350247 +vt 0.302179 0.297890 +vt 0.298714 0.287577 +vt 0.311749 0.277724 +vt 0.316365 0.285093 +vt 0.322578 0.293487 +vt 0.307339 0.309849 +vt 0.119918 0.366270 +vt 0.100816 0.365961 +vt 0.099445 0.357374 +vt 0.115745 0.356222 +vt 0.336061 0.269037 +vt 0.329146 0.265681 +vt 0.344353 0.253630 +vt 0.353882 0.254085 +vt 0.364188 0.256429 +vt 0.344042 0.273798 +vt 0.075419 0.366823 +vt 0.052160 0.367283 +vt 0.059039 0.360672 +vt 0.078420 0.359747 +vt 0.362443 0.244601 +vt 0.350814 0.243752 +vt 0.350759 0.234184 +vt 0.363557 0.236083 +vt 0.378467 0.238856 +vt 0.375473 0.247027 +vt 0.039474 0.365770 +vt 0.033032 0.360087 +vt 0.041423 0.350238 +vt 0.047675 0.357481 +vt 0.359036 0.224032 +vt 0.346418 0.223061 +vt 0.336336 0.211802 +vt 0.348336 0.210945 +vt 0.361862 0.209671 +vt 0.373740 0.225178 +vt 0.028511 0.348036 +vt 0.027963 0.331141 +vt 0.037565 0.323893 +vt 0.037377 0.339005 +vt 0.330912 0.199320 +vt 0.319059 0.201824 +vt 0.298846 0.194429 +vt 0.309301 0.190532 +vt 0.319801 0.185677 +vt 0.343406 0.196011 +vt 0.033440 0.310924 +vt 0.043937 0.290090 +vt 0.054376 0.286147 +vt 0.044015 0.305013 +vt 0.286039 0.185957 +vt 0.279956 0.190919 +vt 0.261182 0.192832 +vt 0.260987 0.185942 +vt 0.058449 0.271343 +vt 0.077310 0.254853 +vt 0.081695 0.260170 +vt 0.066295 0.271078 +vt 0.234005 0.190835 +vt 0.241316 0.201706 +vt 0.225153 0.213273 +vt 0.211760 0.200454 +vt 0.193077 0.179491 +vt 0.228867 0.179292 +vt 0.100851 0.240791 +vt 0.123934 0.233404 +vt 0.122278 0.251869 +vt 0.102495 0.253788 +vt 0.200914 0.214616 +vt 0.217489 0.223262 +vt 0.214962 0.232590 +vt 0.197715 0.230138 +vt 0.171528 0.226740 +vt 0.183608 0.202947 +vt 0.141419 0.236937 +vt 0.146778 0.216764 +vt 0.154038 0.246524 +vt 0.142660 0.259716 +vt 0.134622 0.254352 +vt 0.221080 0.287033 +vt 0.230627 0.281972 +vt 0.210966 0.279098 +vt 0.222550 0.272644 +vt 0.173862 0.304748 +vt 0.176261 0.292118 +vt 0.184246 0.304787 +vt 0.163342 0.307216 +vt 0.163291 0.294876 +vt 0.204977 0.268519 +vt 0.217656 0.262472 +vt 0.189623 0.274972 +vt 0.184758 0.262005 +vt 0.201373 0.256398 +vt 0.215145 0.252100 +vt 0.173814 0.280211 +vt 0.168556 0.268710 +vt 0.160286 0.283996 +vt 0.155355 0.274531 +vt 0.198410 0.243835 +vt 0.179548 0.248116 +vt 0.214214 0.242171 +vt 0.162524 0.257298 +vt 0.149526 0.266440 +vt 0.107545 0.014562 +vt 0.120369 0.011773 +vt 0.112719 0.017764 +vt 0.103792 0.019274 +vt 0.094795 0.022213 +vt 0.093605 0.019043 +vt 0.080159 0.024837 +vt 0.086085 0.025917 +vt 0.078368 0.030651 +vt 0.068665 0.031171 +vt 0.130467 0.011054 +vt 0.138367 0.013804 +vt 0.128426 0.022391 +vt 0.121219 0.018347 +vt 0.060585 0.037272 +vt 0.072348 0.036681 +vt 0.069580 0.044468 +vt 0.056444 0.044539 +vt 0.144592 0.021423 +vt 0.149246 0.030956 +vt 0.133646 0.043072 +vt 0.133472 0.031265 +vt 0.158028 0.010577 +vt 0.163798 0.019583 +vt 0.056767 0.054373 +vt 0.071616 0.054472 +vt 0.079251 0.063479 +vt 0.059532 0.064614 +vt 0.160341 0.076323 +vt 0.176380 0.073132 +vt 0.181205 0.099450 +vt 0.165619 0.102234 +vt 0.151099 0.106514 +vt 0.145090 0.081256 +vt 0.140111 0.058923 +vt 0.155633 0.052647 +vt 0.171357 0.047808 +vt 0.081015 0.106084 +vt 0.068988 0.085154 +vt 0.084807 0.079671 +vt 0.095747 0.099768 +vt 0.107835 0.122745 +vt 0.094084 0.129072 +vt 0.152430 0.039444 +vt 0.136801 0.048036 +vt 0.167702 0.030976 +vt 0.062716 0.073103 +vt 0.080140 0.069293 +vt 0.145996 0.128536 +vt 0.157498 0.126173 +vt 0.164282 0.141614 +vt 0.150837 0.140005 +vt 0.139710 0.141931 +vt 0.135669 0.131161 +vt 0.129147 0.113777 +vt 0.139381 0.110187 +vt 0.126164 0.135976 +vt 0.119077 0.117805 +vt 0.130061 0.147799 +vt 0.120993 0.157855 +vt 0.115946 0.141762 +vt 0.132246 0.086145 +vt 0.125966 0.064380 +vt 0.120524 0.090792 +vt 0.112509 0.069429 +vt 0.108637 0.095002 +vt 0.099052 0.074478 +vt 0.121915 0.052865 +vt 0.107811 0.056907 +vt 0.105467 0.050658 +vt 0.119362 0.047855 +vt 0.094529 0.063139 +vt 0.093156 0.057686 +vt 0.848774 0.366161 +vt 0.844286 0.362787 +vt 0.851499 0.357724 +vt 0.855258 0.361348 +vt 0.858848 0.365213 +vt 0.852772 0.369326 +vt 0.847843 0.372601 +vt 0.843471 0.370228 +vt 0.836219 0.369471 +vt 0.064202 0.632029 +vt 0.063080 0.639497 +vt 0.067781 0.637657 +vt 0.068982 0.630228 +vt 0.071466 0.626224 +vt 0.066680 0.627960 +vt 0.061722 0.628988 +vt 0.058615 0.632509 +vt 0.119258 0.167819 +vt 0.118204 0.168957 +vt 0.123487 0.160067 +vt 0.865637 0.461077 +vt 0.868750 0.460967 +vt 0.872775 0.466861 +vt 0.870446 0.466345 +vt 0.866486 0.465470 +vt 0.861268 0.460752 +vt 0.862746 0.354564 +vt 0.866232 0.358300 +vt 0.860261 0.351872 +vt 0.066608 0.671507 +vt 0.066368 0.661389 +vt 0.061040 0.661454 +vt 0.061432 0.671581 +vt 0.062683 0.680527 +vt 0.067639 0.680156 +vt 0.070026 0.680802 +vt 0.070241 0.671469 +vt 0.071466 0.661027 +vt 0.872029 0.475504 +vt 0.875567 0.477559 +vt 0.874829 0.491787 +vt 0.870754 0.484407 +vt 0.866916 0.481171 +vt 0.868263 0.473187 +vt 0.068539 0.683746 +vt 0.063554 0.684209 +vt 0.870559 0.507747 +vt 0.866598 0.509712 +vt 0.865983 0.501638 +vt 0.870099 0.498765 +vt 0.874269 0.506023 +vt 0.071443 0.686190 +vt 0.866987 0.488905 +vt 0.868959 0.491519 +vt 0.866531 0.491408 +vt 0.864424 0.491312 +vt 0.739156 0.456290 +vt 0.739209 0.452389 +vt 0.733951 0.451374 +vt 0.734206 0.455488 +vt 0.734566 0.461392 +vt 0.739211 0.461917 +vt 0.666981 0.445965 +vt 0.660119 0.448062 +vt 0.660128 0.440226 +vt 0.667680 0.443519 +vt 0.866757 0.493943 +vt 0.862350 0.495761 +vt 0.859882 0.491105 +vt 0.152652 0.143407 +vt 0.140889 0.145073 +vt 0.163858 0.144921 +vt 0.839524 0.374778 +vt 0.843898 0.377002 +vt 0.842706 0.380149 +vt 0.838419 0.377832 +vt 0.063964 0.649738 +vt 0.068609 0.647984 +vt 0.130932 0.151556 +vt 0.066819 0.661027 +vt 0.071461 0.659407 +vt 0.797282 0.498317 +vt 0.800362 0.487352 +vt 0.801962 0.487426 +vt 0.798736 0.499015 +vt 0.793062 0.508788 +vt 0.792177 0.507548 +vt 0.791685 0.505071 +vt 0.794337 0.497929 +vt 0.796763 0.487186 +vt 0.798303 0.476151 +vt 0.795335 0.476266 +vt 0.793351 0.468911 +vt 0.794069 0.466490 +vt 0.795064 0.465336 +vt 0.799816 0.475589 +vt 0.730426 0.452911 +vt 0.730000 0.448882 +vt 0.858209 0.485476 +vt 0.855286 0.490895 +vt 0.849289 0.490622 +vt 0.854547 0.482406 +vt 0.858535 0.478703 +vt 0.862372 0.479607 +vt 0.730954 0.458664 +vt 0.857704 0.496559 +vt 0.861315 0.502782 +vt 0.857411 0.503333 +vt 0.853778 0.499283 +vt 0.863673 0.472599 +vt 0.858503 0.473247 +vt 0.858112 0.468251 +vt 0.861912 0.466208 +vt 0.861973 0.509880 +vt 0.859637 0.516083 +vt 0.856039 0.513704 +vt 0.856883 0.508764 +vt 0.059362 0.682194 +vt 0.058553 0.678736 +vt 0.856890 0.462193 +vt 0.853727 0.466466 +vt 0.849257 0.466325 +vt 0.851870 0.461207 +vt 0.868427 0.362442 +vt 0.861827 0.368721 +vt 0.776888 0.457494 +vt 0.785662 0.457141 +vt 0.786108 0.462400 +vt 0.778400 0.461981 +vt 0.772151 0.463278 +vt 0.768557 0.460897 +vt 0.057225 0.670449 +vt 0.056821 0.661331 +vt 0.856502 0.371756 +vt 0.788161 0.513547 +vt 0.782946 0.516083 +vt 0.783874 0.510888 +vt 0.788560 0.508643 +vt 0.852158 0.373999 +vt 0.790622 0.460146 +vt 0.790568 0.465066 +vt 0.784225 0.455245 +vt 0.790474 0.458499 +vt 0.775863 0.502379 +vt 0.773854 0.494587 +vt 0.781389 0.486478 +vt 0.783480 0.500710 +vt 0.776160 0.510596 +vt 0.852999 0.474636 +vt 0.768538 0.503682 +vt 0.768772 0.498237 +vt 0.777349 0.470137 +vt 0.770175 0.468165 +vt 0.784780 0.472498 +vt 0.774632 0.477710 +vt 0.851529 0.506879 +vt 0.789687 0.498977 +vt 0.790711 0.486908 +vt 0.790801 0.474795 +vt 0.173919 0.191478 +vt 0.162233 0.201966 +vt 0.156434 0.186508 +vt 0.170215 0.182683 +vt 0.178261 0.174067 +vt 0.181171 0.176710 +vt 0.146533 0.201753 +vt 0.131357 0.195400 +vt 0.131810 0.191494 +vt 0.143537 0.192692 +vt 0.183571 0.164083 +vt 0.180580 0.164007 +vt 0.178584 0.154649 +vt 0.182515 0.153731 +vt 0.861069 0.350865 +vt 0.848010 0.354940 +vt 0.841505 0.349055 +vt 0.857451 0.346360 +vt 0.189310 0.163945 +vt 0.121243 0.187466 +vt 0.116830 0.191138 +vt 0.109633 0.182812 +vt 0.115229 0.178974 +vt 0.118794 0.177080 +vt 0.123446 0.185441 +vt 0.839084 0.359732 +vt 0.179401 0.145790 +vt 0.173685 0.148142 +vt 0.175112 0.136510 +vt 0.830346 0.366571 +vt 0.822748 0.360131 +vt 0.831473 0.353477 +vt 0.112352 0.170945 +vt 0.104542 0.175253 +vt 0.099198 0.166393 +vt 0.109479 0.161134 +vt 0.170530 0.122144 +vt 0.184263 0.119268 +vt 0.914473 0.516083 +vt 0.907560 0.502295 +vt 0.914571 0.498319 +vt 0.919834 0.510321 +vt 0.103480 0.147300 +vt 0.091244 0.154167 +vt 0.799989 0.356155 +vt 0.789344 0.339276 +vt 0.906055 0.483928 +vt 0.911497 0.465608 +vt 0.919884 0.463204 +vt 0.914457 0.480830 +vt 0.898384 0.507546 +vt 0.895584 0.488692 +vt 0.895900 0.880841 +vt 0.881548 0.882602 +vt 0.883908 0.897682 +vt 0.898813 0.895218 +vt 0.917219 0.894166 +vt 0.914466 0.880849 +vt 0.878967 0.861452 +vt 0.819760 0.340504 +vt 0.811360 0.346958 +vt 0.799956 0.330845 +vt 0.808109 0.325190 +vt 0.815631 0.321217 +vt 0.828699 0.336130 +vt 0.900615 0.905667 +vt 0.885395 0.908551 +vt 0.884329 0.919352 +vt 0.900294 0.915487 +vt 0.918585 0.912385 +vt 0.918518 0.903978 +vt 0.841686 0.333173 +vt 0.824349 0.317828 +vt 0.896838 0.927979 +vt 0.879026 0.934230 +vt 0.110362 0.197227 +vt 0.103738 0.212861 +vt 0.105615 0.203955 +vt 0.917644 0.921488 +vt 0.117576 0.045606 +vt 0.127140 0.042743 +vt 0.104511 0.048111 +vt 0.104499 0.048078 +vt 0.116707 0.045444 +vt 0.125596 0.042665 +vt 0.093023 0.054818 +vt 0.093570 0.054124 +vt 0.083936 0.058953 +vt 0.085047 0.057877 +vt 0.128126 0.034962 +vt 0.123704 0.026765 +vt 0.126563 0.036181 +vt 0.122477 0.029418 +vt 0.906340 0.461405 +vt 0.906162 0.458615 +vt 0.912849 0.460101 +vt 0.914427 0.463205 +vt 0.078075 0.053740 +vt 0.076014 0.044657 +vt 0.895593 0.457945 +vt 0.897040 0.455401 +vt 0.117044 0.022653 +vt 0.109492 0.021548 +vt 0.116205 0.025799 +vt 0.939028 0.450052 +vt 0.941472 0.451665 +vt 0.942413 0.446822 +vt 0.939920 0.445120 +vt 0.879266 0.968901 +vt 0.882321 0.967093 +vt 0.883275 0.971722 +vt 0.880540 0.973729 +vt 0.078326 0.037180 +vt 0.083287 0.031379 +vt 0.878967 0.962209 +vt 0.882053 0.960874 +vt 0.102393 0.022366 +vt 0.095652 0.024497 +vt 0.879358 0.941156 +vt 0.879727 0.934230 +vt 0.882737 0.935730 +vt 0.882178 0.941990 +vt 0.881824 0.948286 +vt 0.879151 0.948214 +vt 0.878974 0.955272 +vt 0.881835 0.954593 +vt 0.089172 0.027327 +vt 0.887901 0.942398 +vt 0.887499 0.948441 +vt 0.947978 0.445934 +vt 0.942393 0.444571 +vt 0.948219 0.448064 +vt 0.888631 0.936363 +vt 0.894718 0.935457 +vt 0.893892 0.941804 +vt 0.893435 0.948602 +vt 0.887572 0.954497 +vt 0.893522 0.955415 +vt 0.894002 0.961797 +vt 0.887974 0.960562 +vt 0.947730 0.452567 +vt 0.940152 0.458933 +vt 0.946736 0.459162 +vt 0.951244 0.459596 +vt 0.953522 0.454794 +vt 0.953371 0.451702 +vt 0.888556 0.966631 +vt 0.894726 0.967304 +vt 0.894038 0.970368 +vt 0.889576 0.971200 +vt 0.945460 0.467568 +vt 0.939037 0.468463 +vt 0.629880 0.969789 +vt 0.635999 0.968976 +vt 0.639030 0.964980 +vt 0.632740 0.965995 +vt 0.624967 0.966620 +vt 0.622910 0.970416 +vt 0.951979 0.465264 +vt 0.906509 0.452045 +vt 0.905498 0.445030 +vt 0.909417 0.446343 +vt 0.912209 0.453639 +vt 0.898522 0.448872 +vt 0.899817 0.444347 +vt 0.630247 0.957258 +vt 0.636571 0.956007 +vt 0.632533 0.944268 +vt 0.626256 0.945767 +vt 0.506511 0.955486 +vt 0.508193 0.943383 +vt 0.508837 0.943383 +vt 0.507307 0.954730 +vt 0.506315 0.963366 +vt 0.505856 0.964564 +vt 0.506512 0.931279 +vt 0.507307 0.932036 +vt 0.624625 0.933713 +vt 0.630831 0.931971 +vt 0.628972 0.922856 +vt 0.622902 0.924791 +vt 0.505858 0.922202 +vt 0.506316 0.923399 +vt 0.513862 0.952461 +vt 0.514938 0.943383 +vt 0.522687 0.943383 +vt 0.522067 0.950191 +vt 0.520369 0.956558 +vt 0.512421 0.959773 +vt 0.513863 0.934305 +vt 0.512422 0.926993 +vt 0.520370 0.930208 +vt 0.522068 0.936575 +vt 0.512396 0.963556 +vt 0.509461 0.966581 +vt 0.517752 0.962043 +vt 0.954567 0.460384 +vt 0.901245 0.440905 +vt 0.895584 0.440526 +vt 0.512397 0.923210 +vt 0.517753 0.924724 +vt 0.509462 0.920184 +vt 0.222064 0.240841 +vt 0.222821 0.249320 +vt 0.222881 0.232969 +vt 0.226081 0.232974 +vt 0.225798 0.240384 +vt 0.227148 0.248110 +vt 0.142738 0.270602 +vt 0.139625 0.272714 +vt 0.134538 0.267319 +vt 0.136945 0.265210 +vt 0.147745 0.277486 +vt 0.143690 0.279421 +vt 0.225439 0.258450 +vt 0.230131 0.267727 +vt 0.230187 0.256391 +vt 0.234941 0.264665 +vt 0.151779 0.286086 +vt 0.146848 0.287657 +vt 0.154346 0.296160 +vt 0.148709 0.297017 +vt 0.237112 0.276645 +vt 0.246033 0.283913 +vt 0.241435 0.272374 +vt 0.249399 0.278616 +vt 0.154954 0.307469 +vt 0.148888 0.307096 +vt 0.153014 0.318811 +vt 0.146995 0.317035 +vt 0.224987 0.225661 +vt 0.231398 0.217266 +vt 0.234084 0.217516 +vt 0.227943 0.225643 +vt 0.130551 0.261091 +vt 0.128313 0.263022 +vt 0.118342 0.260940 +vt 0.120200 0.258985 +vt 0.245131 0.206133 +vt 0.262050 0.197030 +vt 0.263249 0.199958 +vt 0.247206 0.207716 +vt 0.102533 0.259632 +vt 0.102012 0.262189 +vt 0.084825 0.266898 +vt 0.083802 0.263903 +vt 0.278017 0.194724 +vt 0.294460 0.197634 +vt 0.293211 0.200587 +vt 0.278153 0.197957 +vt 0.070259 0.272669 +vt 0.072283 0.275194 +vt 0.062670 0.287080 +vt 0.059787 0.285677 +vt 0.724391 0.447821 +vt 0.724582 0.461230 +vt 0.717126 0.461917 +vt 0.717867 0.447033 +vt 0.312805 0.204177 +vt 0.328682 0.213116 +vt 0.323860 0.215070 +vt 0.309719 0.206721 +vt 0.729128 0.447039 +vt 0.730000 0.459378 +vt 0.050274 0.302672 +vt 0.054271 0.302559 +vt 0.049111 0.318149 +vt 0.044194 0.319848 +vt 0.337722 0.223213 +vt 0.341683 0.233413 +vt 0.335328 0.233613 +vt 0.331817 0.224344 +vt 0.044027 0.333399 +vt 0.049218 0.330367 +vt 0.052670 0.339659 +vt 0.047752 0.343688 +vt 0.342324 0.242658 +vt 0.337131 0.251788 +vt 0.331651 0.250013 +vt 0.336133 0.241949 +vt 0.053351 0.351073 +vt 0.057547 0.346467 +vt 0.066228 0.349593 +vt 0.063267 0.354534 +vt 0.323590 0.261640 +vt 0.307825 0.271303 +vt 0.070182 0.528500 +vt 0.068729 0.546805 +vt 0.063510 0.548440 +vt 0.065681 0.531727 +vt 0.067987 0.516996 +vt 0.071466 0.512230 +vt 0.668463 0.448377 +vt 0.673189 0.448566 +vt 0.673188 0.440540 +vt 0.667680 0.440226 +vt 0.079946 0.353048 +vt 0.098178 0.349957 +vt 0.081089 0.347837 +vt 0.295956 0.279868 +vt 0.286243 0.286281 +vt 0.069945 0.560875 +vt 0.071457 0.572143 +vt 0.067516 0.571665 +vt 0.065208 0.561338 +vt 0.112751 0.348602 +vt 0.110968 0.343491 +vt 0.121684 0.342263 +vt 0.124286 0.347043 +vt 0.063372 0.551295 +vt 0.063510 0.565417 +vt 0.058159 0.564289 +vt 0.058613 0.551288 +vt 0.276943 0.289490 +vt 0.267297 0.289980 +vt 0.267947 0.284176 +vt 0.276587 0.283875 +vt 0.285058 0.280970 +vt 0.133401 0.343343 +vt 0.129976 0.338879 +vt 0.136682 0.333423 +vt 0.140989 0.337368 +vt 0.256544 0.288239 +vt 0.258560 0.282486 +vt 0.147943 0.328984 +vt 0.142641 0.325976 +vt 0.260121 0.279107 +vt 0.268353 0.280591 +vt 0.252006 0.275783 +vt 0.254233 0.274183 +vt 0.261453 0.276916 +vt 0.268636 0.278116 +vt 0.139243 0.324457 +vt 0.136798 0.323683 +vt 0.140438 0.316876 +vt 0.143169 0.316616 +vt 0.134018 0.330990 +vt 0.132177 0.329312 +vt 0.276214 0.280369 +vt 0.284171 0.277888 +vt 0.275834 0.277918 +vt 0.283433 0.275921 +vt 0.127951 0.335994 +vt 0.126625 0.333897 +vt 0.120325 0.339358 +vt 0.119588 0.337392 +vt 0.292688 0.272594 +vt 0.302963 0.265523 +vt 0.304820 0.266885 +vt 0.293937 0.274846 +vt 0.291824 0.271726 +vt 0.301679 0.265689 +vt 0.110428 0.340973 +vt 0.110508 0.339751 +vt 0.097534 0.344653 +vt 0.098038 0.342405 +vt 0.099114 0.341686 +vt 0.316192 0.257712 +vt 0.327346 0.249756 +vt 0.319302 0.258466 +vt 0.313669 0.258167 +vt 0.323630 0.250259 +vt 0.082936 0.345223 +vt 0.085135 0.343907 +vt 0.069301 0.346568 +vt 0.072431 0.344502 +vt 0.331399 0.242253 +vt 0.330693 0.234629 +vt 0.327394 0.243063 +vt 0.326918 0.236051 +vt 0.061313 0.343582 +vt 0.064863 0.341558 +vt 0.056830 0.337375 +vt 0.060609 0.335963 +vt 0.327572 0.226311 +vt 0.320358 0.217851 +vt 0.324158 0.228696 +vt 0.317517 0.221044 +vt 0.053709 0.329057 +vt 0.057850 0.328608 +vt 0.053578 0.317940 +vt 0.057819 0.318476 +vt 0.307373 0.209799 +vt 0.292167 0.203726 +vt 0.305396 0.213143 +vt 0.013693 0.870082 +vt 0.016342 0.872796 +vt 0.009710 0.884822 +vt 0.006799 0.883158 +vt 0.064446 0.452817 +vt 0.067800 0.451047 +vt 0.071424 0.462214 +vt 0.068112 0.464839 +vt 0.058063 0.303333 +vt 0.065522 0.288757 +vt 0.061899 0.438256 +vt 0.065180 0.437566 +vt 0.278293 0.201202 +vt 0.264439 0.203041 +vt 0.002336 0.895925 +vt 0.005407 0.896551 +vt 0.003301 0.909528 +vt 0.000128 0.909930 +vt 0.061571 0.424736 +vt 0.064687 0.425082 +vt 0.074312 0.277730 +vt 0.085956 0.270003 +vt 0.063770 0.410729 +vt 0.066666 0.412086 +vt 0.249296 0.210056 +vt 0.236801 0.219104 +vt 0.000000 0.926723 +vt 0.003259 0.925292 +vt 0.005088 0.939294 +vt 0.001771 0.941494 +vt 0.068803 0.394708 +vt 0.071466 0.397070 +vt 0.101977 0.265327 +vt 0.117340 0.263922 +vt 0.058835 0.686190 +vt 0.056821 0.691838 +vt 0.059541 0.694017 +vt 0.061234 0.688743 +vt 0.005260 0.949440 +vt 0.009344 0.953115 +vt 0.007414 0.955807 +vt 0.003499 0.951951 +vt 0.230890 0.227039 +vt 0.008597 0.946983 +vt 0.012717 0.950527 +vt 0.057039 0.697767 +vt 0.059866 0.699821 +vt 0.127011 0.266012 +vt 0.133084 0.270354 +vt 0.057920 0.704209 +vt 0.060864 0.706138 +vt 0.244496 0.270483 +vt 0.238210 0.263776 +vt 0.060573 0.402886 +vt 0.061147 0.412080 +vt 0.057701 0.412276 +vt 0.057233 0.403962 +vt 0.056564 0.396662 +vt 0.059655 0.394708 +vt 0.145339 0.307685 +vt 0.143047 0.308755 +vt 0.143911 0.300289 +vt 0.145663 0.298497 +vt 0.233763 0.256230 +vt 0.230872 0.248525 +vt 0.061183 0.421537 +vt 0.060866 0.430623 +vt 0.056701 0.429698 +vt 0.057314 0.421111 +vt 0.144049 0.289888 +vt 0.142316 0.292449 +vt 0.139387 0.285359 +vt 0.141158 0.282183 +vt 0.229254 0.241342 +vt 0.012899 0.955079 +vt 0.010901 0.958255 +vt 0.016377 0.952096 +vt 0.060383 0.438704 +vt 0.056493 0.437269 +vt 0.057895 0.711396 +vt 0.061191 0.712952 +vt 0.137651 0.275708 +vt 0.057370 0.719459 +vt 0.060903 0.720513 +vt 0.680651 0.931251 +vt 0.680041 0.927497 +vt 0.681278 0.943843 +vt 0.699152 0.941040 +vt 0.695058 0.930713 +vt 0.694565 0.928321 +vt 0.420973 0.738616 +vt 0.433823 0.739113 +vt 0.441374 0.759007 +vt 0.426547 0.749590 +vt 0.419120 0.727596 +vt 0.432673 0.726965 +vt 0.682507 0.966504 +vt 0.684862 0.988216 +vt 0.695910 0.979706 +vt 0.698186 0.963326 +vt 0.407858 0.849184 +vt 0.415952 0.862408 +vt 0.399402 0.867861 +vt 0.387685 0.861117 +vt 0.436885 0.760595 +vt 0.447794 0.773719 +vt 0.429105 0.839496 +vt 0.438111 0.850402 +vt 0.688866 0.997962 +vt 0.449041 0.661077 +vt 0.450564 0.641065 +vt 0.204365 0.916029 +vt 0.203991 0.895856 +vt 0.216765 0.893927 +vt 0.220451 0.909419 +vt 0.226149 0.924235 +vt 0.215103 0.932031 +vt 0.378467 0.878040 +vt 0.395094 0.883140 +vt 0.392852 0.898906 +vt 0.379955 0.898162 +vt 0.455084 0.791050 +vt 0.458458 0.810835 +vt 0.447828 0.620745 +vt 0.443981 0.598710 +vt 0.213898 0.873320 +vt 0.228000 0.848235 +vt 0.243636 0.854870 +vt 0.227531 0.878936 +vt 0.391897 0.919689 +vt 0.404954 0.912839 +vt 0.423209 0.935319 +vt 0.408252 0.943367 +vt 0.749095 0.548931 +vt 0.767028 0.551076 +vt 0.735804 0.547325 +vt 0.442174 0.573551 +vt 0.441500 0.549223 +vt 0.456899 0.553145 +vt 0.456397 0.575919 +vt 0.240215 0.820416 +vt 0.253163 0.821160 +vt 0.782836 0.554509 +vt 0.789395 0.572295 +vt 0.801233 0.576746 +vt 0.795603 0.558016 +vt 0.776535 0.566478 +vt 0.441054 0.529680 +vt 0.440197 0.517730 +vt 0.059391 0.748977 +vt 0.059697 0.729792 +vt 0.071441 0.726806 +vt 0.071466 0.744451 +vt 0.456207 0.535413 +vt 0.804415 0.560384 +vt 0.809382 0.578647 +vt 0.822218 0.581943 +vt 0.818402 0.564489 +vt 0.893292 0.198498 +vt 0.922132 0.191321 +vt 0.864190 0.211793 +vt 0.855600 0.196568 +vt 0.883843 0.185525 +vt 0.910831 0.179816 +vt 0.846692 0.573208 +vt 0.848116 0.590579 +vt 0.878136 0.597390 +vt 0.878697 0.579125 +vt 0.341372 0.479322 +vt 0.323411 0.491599 +vt 0.334557 0.487251 +vt 0.353283 0.474792 +vt 0.844632 0.559867 +vt 0.847674 0.231901 +vt 0.838548 0.252753 +vt 0.827021 0.234525 +vt 0.837606 0.214532 +vt 0.320214 0.511247 +vt 0.303059 0.515397 +vt 0.305121 0.537768 +vt 0.324024 0.534526 +vt 0.336112 0.530121 +vt 0.331872 0.506637 +vt 0.308712 0.497514 +vt 0.831612 0.268279 +vt 0.826974 0.280826 +vt 0.819433 0.270607 +vt 0.821009 0.251654 +vt 0.327081 0.557697 +vt 0.309780 0.560976 +vt 0.319448 0.588328 +vt 0.330743 0.582419 +vt 0.341087 0.581345 +vt 0.338161 0.554872 +vt 0.089872 0.877857 +vt 0.101189 0.881919 +vt 0.101745 0.899454 +vt 0.090128 0.897768 +vt 0.273448 0.727090 +vt 0.268000 0.708117 +vt 0.264039 0.708897 +vt 0.269059 0.731167 +vt 0.278773 0.748593 +vt 0.282566 0.743284 +vt 0.084977 0.859311 +vt 0.097167 0.864360 +vt 0.265845 0.688495 +vt 0.268141 0.670053 +vt 0.262617 0.666579 +vt 0.260237 0.686387 +vt 0.267358 0.708243 +vt 0.266634 0.690781 +vt 0.269104 0.673172 +vt 0.121292 0.884963 +vt 0.143287 0.887007 +vt 0.143668 0.905535 +vt 0.121981 0.902389 +vt 0.117483 0.866957 +vt 0.140036 0.867872 +vt 0.116369 0.918901 +vt 0.107600 0.935083 +vt 0.087384 0.931800 +vt 0.096230 0.916107 +vt 0.138038 0.923191 +vt 0.129483 0.940614 +vt 0.953309 0.379981 +vt 0.958624 0.381492 +vt 0.959426 0.360450 +vt 0.952838 0.360296 +vt 0.160279 0.888071 +vt 0.159638 0.907852 +vt 0.158937 0.867874 +vt 0.954356 0.399805 +vt 0.957116 0.402423 +vt 0.154632 0.927000 +vt 0.147606 0.945982 +vt 0.954226 0.340655 +vt 0.954403 0.342046 +vt 0.951782 0.360272 +vt 0.959606 0.339393 +vt 0.959076 0.318415 +vt 0.956196 0.320901 +vt 0.969257 0.382875 +vt 0.966750 0.404508 +vt 0.970622 0.360711 +vt 0.970292 0.338508 +vt 0.968797 0.316781 +vt 0.660423 0.415937 +vt 0.662165 0.407233 +vt 0.963657 0.425119 +vt 0.954815 0.423147 +vt 0.957233 0.434273 +vt 0.962535 0.440226 +vt 0.966668 0.296049 +vt 0.957744 0.297607 +vt 0.966251 0.280906 +vt 0.960678 0.286605 +vt 0.671188 0.397125 +vt 0.686346 0.385596 +vt 0.663184 0.396198 +vt 0.671005 0.382602 +vt 0.161293 0.822480 +vt 0.158447 0.830985 +vt 0.137497 0.831704 +vt 0.144505 0.820937 +vt 0.969892 0.275946 +vt 0.961037 0.284568 +vt 0.982678 0.275614 +vt 0.924127 0.750352 +vt 0.906069 0.743931 +vt 0.926143 0.769286 +vt 0.943484 0.781638 +vt 0.938647 0.757589 +vt 0.706494 0.372629 +vt 0.728825 0.358554 +vt 0.122471 0.820416 +vt 0.114058 0.832445 +vt 0.091068 0.832677 +vt 0.098055 0.820441 +vt 0.927137 0.793171 +vt 0.946694 0.807666 +vt 0.928119 0.819472 +vt 0.949175 0.833020 +vt 0.113734 0.848705 +vt 0.137056 0.848393 +vt 0.092283 0.847631 +vt 0.098819 0.951517 +vt 0.077948 0.946451 +vt 0.121092 0.958443 +vt 0.116773 0.974569 +vt 0.094510 0.967199 +vt 0.072534 0.960444 +vt 0.157994 0.847481 +vt 0.168179 0.834464 +vt 0.171727 0.846161 +vt 0.954693 0.419865 +vt 0.957469 0.300879 +vt 0.140907 0.965267 +vt 0.136654 0.981211 +vt 0.740758 0.313008 +vt 0.748783 0.299443 +vt 0.762781 0.311537 +vt 0.748821 0.322444 +vt 0.076963 0.844390 +vt 0.071466 0.831872 +vt 0.731342 0.311754 +vt 0.734634 0.295316 +vt 0.276045 0.654618 +vt 0.272733 0.656298 +vt 0.278310 0.640293 +vt 0.286933 0.640651 +vt 0.293647 0.640774 +vt 0.276141 0.652414 +vt 0.750531 0.343701 +vt 0.769215 0.330522 +vt 0.074123 0.820536 +vt 0.930100 0.845650 +vt 0.951821 0.855052 +vt 0.932309 0.868370 +vt 0.954061 0.872624 +vt 0.800682 0.311915 +vt 0.792309 0.315585 +vt 0.781557 0.295190 +vt 0.796321 0.296016 +vt 0.806554 0.297633 +vt 0.808337 0.309367 +vt 0.933968 0.904623 +vt 0.932566 0.912416 +vt 0.942565 0.917191 +vt 0.949067 0.909375 +vt 0.958130 0.897186 +vt 0.934676 0.895644 +vt 0.782481 0.321469 +vt 0.772542 0.304462 +vt 0.933979 0.884297 +vt 0.955324 0.884600 +vt 0.816016 0.306847 +vt 0.822042 0.302068 +vt 0.814251 0.298005 +vt 0.819436 0.295714 +vt 0.931185 0.920207 +vt 0.938828 0.923461 +vt 0.337451 0.638409 +vt 0.350090 0.637204 +vt 0.339942 0.632136 +vt 0.334298 0.628445 +vt 0.331357 0.635712 +vt 0.824739 0.292742 +vt 0.821782 0.287450 +vt 0.490615 0.932841 +vt 0.484957 0.930718 +vt 0.479303 0.958206 +vt 0.491665 0.961315 +vt 0.501974 0.959945 +vt 0.501965 0.930481 +vt 0.336368 0.610352 +vt 0.331362 0.613737 +vt 0.660119 0.309235 +vt 0.660104 0.353457 +vt 0.633416 0.350086 +vt 0.635412 0.304462 +vt 0.633775 0.265411 +vt 0.654528 0.272226 +vt 0.089049 0.788087 +vt 0.111286 0.820416 +vt 0.121888 0.818713 +vt 0.099865 0.785571 +vt 0.082773 0.744605 +vt 0.071466 0.746833 +vt 0.072089 0.701991 +vt 0.083051 0.700217 +vt 0.090859 0.661199 +vt 0.080403 0.663645 +vt 0.080131 0.659458 +vt 0.071759 0.700386 +vt 0.071744 0.746778 +vt 0.120907 0.779242 +vt 0.105106 0.740206 +vt 0.141844 0.811226 +vt 0.171926 0.798940 +vt 0.153599 0.769075 +vt 0.140140 0.733304 +vt 0.104921 0.698094 +vt 0.139027 0.695101 +vt 0.144658 0.660518 +vt 0.112164 0.660558 +vt 0.199368 0.755047 +vt 0.189550 0.723571 +vt 0.688218 0.221010 +vt 0.663100 0.168592 +vt 0.674081 0.164798 +vt 0.697294 0.212780 +vt 0.725258 0.259946 +vt 0.713085 0.265262 +vt 0.240986 0.742094 +vt 0.234484 0.714719 +vt 0.186696 0.690723 +vt 0.230118 0.686924 +vt 0.236381 0.658388 +vt 0.188682 0.659877 +vt 0.261227 0.735152 +vt 0.256090 0.710463 +vt 0.724923 0.287653 +vt 0.733311 0.282795 +vt 0.727747 0.300231 +vt 0.251480 0.685671 +vt 0.255122 0.664650 +vt 0.752668 0.289985 +vt 0.754427 0.279289 +vt 0.274743 0.651276 +vt 0.270704 0.647103 +vt 0.979382 0.875169 +vt 0.973663 0.866852 +vt 0.298656 0.641554 +vt 0.301752 0.639404 +vt 0.816504 0.185036 +vt 0.839428 0.168477 +vt 0.801911 0.206932 +vt 0.768301 0.174659 +vt 0.795791 0.154009 +vt 0.824274 0.137729 +vt 0.269890 0.512936 +vt 0.236219 0.509160 +vt 0.223967 0.532489 +vt 0.269419 0.535388 +vt 0.280712 0.498211 +vt 0.252154 0.496833 +vt 0.596468 0.293570 +vt 0.590934 0.344720 +vt 0.538294 0.338071 +vt 0.546333 0.281264 +vt 0.555237 0.233844 +vt 0.600701 0.250262 +vt 0.081785 0.692371 +vt 0.087339 0.646944 +vt 0.583575 0.395639 +vt 0.576906 0.438640 +vt 0.528787 0.443236 +vt 0.531955 0.395092 +vt 0.624004 0.394773 +vt 0.607145 0.660290 +vt 0.610074 0.718717 +vt 0.563883 0.720865 +vt 0.562981 0.662217 +vt 0.566026 0.612063 +vt 0.606344 0.610346 +vt 0.644051 0.608593 +vt 0.649515 0.658320 +vt 0.654887 0.716634 +vt 0.699153 0.701395 +vt 0.699265 0.746724 +vt 0.709564 0.743489 +vt 0.709676 0.703229 +vt 0.612579 0.777164 +vt 0.616416 0.826967 +vt 0.576112 0.828999 +vt 0.568427 0.779344 +vt 0.654949 0.775194 +vt 0.690242 0.656426 +vt 0.699153 0.714576 +vt 0.678507 0.606991 +vt 0.393130 0.260769 +vt 0.405593 0.212019 +vt 0.442308 0.216561 +vt 0.433145 0.265696 +vt 0.427654 0.324095 +vt 0.386060 0.318841 +vt 0.709825 0.794286 +vt 0.735175 0.839216 +vt 0.743216 0.821828 +vt 0.718670 0.783792 +vt 0.695676 0.773301 +vt 0.378467 0.376847 +vt 0.418451 0.382025 +vt 0.488053 0.272251 +vt 0.481133 0.330850 +vt 0.497315 0.223224 +vt 0.473264 0.389330 +vt 0.470044 0.439120 +vt 0.415108 0.431895 +vt 0.474227 0.541769 +vt 0.476423 0.557823 +vt 0.454986 0.524205 +vt 0.472609 0.529980 +vt 0.494891 0.531910 +vt 0.498065 0.545078 +vt 0.502640 0.560706 +vt 0.812887 0.599436 +vt 0.809330 0.623674 +vt 0.821315 0.624504 +vt 0.824497 0.601824 +vt 0.805512 0.599397 +vt 0.801155 0.625863 +vt 0.530677 0.541669 +vt 0.538115 0.559246 +vt 0.523659 0.526849 +vt 0.555009 0.520249 +vt 0.566194 0.536231 +vt 0.576255 0.556147 +vt 0.793107 0.652287 +vt 0.775552 0.683446 +vt 0.795205 0.678556 +vt 0.808748 0.650355 +vt 0.780872 0.656043 +vt 0.759058 0.688445 +vt 0.598749 0.533455 +vt 0.610464 0.554115 +vt 0.585039 0.517559 +vt 0.612817 0.516930 +vt 0.627922 0.532099 +vt 0.640880 0.552701 +vt 0.768000 0.715326 +vt 0.769452 0.747061 +vt 0.790689 0.738603 +vt 0.789098 0.708287 +vt 0.750107 0.721580 +vt 0.751501 0.754621 +vt 0.653293 0.530919 +vt 0.667637 0.551457 +vt 0.637411 0.516512 +vt 0.471536 0.142575 +vt 0.490250 0.129689 +vt 0.508242 0.136932 +vt 0.499588 0.146881 +vt 0.484663 0.166218 +vt 0.454617 0.161788 +vt 0.778910 0.777789 +vt 0.799460 0.802749 +vt 0.812235 0.789485 +vt 0.800240 0.768554 +vt 0.760721 0.786740 +vt 0.782459 0.814074 +vt 0.536553 0.153838 +vt 0.535952 0.137750 +vt 0.571747 0.143766 +vt 0.574814 0.165279 +vt 0.571304 0.185264 +vt 0.527152 0.173492 +vt 0.834188 0.817183 +vt 0.821407 0.832759 +vt 0.490795 0.516083 +vt 0.486577 0.494709 +vt 0.532270 0.494286 +vt 0.530700 0.514516 +vt 0.874757 0.822490 +vt 0.876425 0.800766 +vt 0.839164 0.796139 +vt 0.512211 0.193462 +vt 0.564170 0.204982 +vt 0.462525 0.186424 +vt 0.477071 0.471651 +vt 0.443614 0.491189 +vt 0.427196 0.466113 +vt 0.530262 0.473414 +vt 0.429362 0.181980 +vt 0.673507 0.574407 +vt 0.643714 0.575792 +vt 0.738138 0.785009 +vt 0.729257 0.749775 +vt 0.761344 0.816940 +vt 0.610223 0.577350 +vt 0.573325 0.579065 +vt 0.728664 0.713753 +vt 0.739736 0.678541 +vt 0.722567 0.665053 +vt 0.533311 0.580926 +vt 0.523739 0.613555 +vt 0.487824 0.613553 +vt 0.497542 0.581453 +vt 0.765852 0.645744 +vt 0.789894 0.616661 +vt 0.779022 0.602963 +vt 0.751798 0.631002 +vt 0.266070 0.822936 +vt 0.258721 0.856029 +vt 0.473379 0.579168 +vt 0.466624 0.610784 +vt 0.794745 0.592595 +vt 0.785891 0.582827 +vt 0.516872 0.663982 +vt 0.515486 0.723115 +vt 0.464289 0.725495 +vt 0.478536 0.663240 +vt 0.522353 0.781864 +vt 0.533869 0.831436 +vt 0.498109 0.834771 +vt 0.484251 0.786160 +vt 0.238743 0.902155 +vt 0.253848 0.898540 +vt 0.266303 0.938052 +vt 0.243131 0.928139 +vt 0.413979 0.888686 +vt 0.429352 0.890894 +vt 0.457689 0.657646 +vt 0.448894 0.699748 +vt 0.438364 0.694255 +vt 0.450547 0.652551 +vt 0.260370 0.902874 +vt 0.464013 0.793664 +vt 0.477258 0.839496 +vt 0.435447 0.885976 +vt 0.438123 0.932775 +vt 0.457375 0.799400 +vt 0.451350 0.752560 +vt 0.442559 0.717082 +vt 0.444439 0.726418 +vt 0.432691 0.714764 +vt 0.443433 0.735889 +vt 0.871150 0.164485 +vt 0.899497 0.165351 +vt 0.860222 0.139200 +vt 0.477389 0.521428 +vt 0.504190 0.518541 +vt 0.847970 0.615673 +vt 0.844008 0.642763 +vt 0.873723 0.661788 +vt 0.877089 0.628960 +vt 0.856068 0.113490 +vt 0.818740 0.114529 +vt 0.812606 0.092330 +vt 0.852353 0.088528 +vt 0.883749 0.084029 +vt 0.887593 0.115897 +vt 0.890846 0.145015 +vt 0.833986 0.666124 +vt 0.824003 0.688783 +vt 0.859756 0.705627 +vt 0.866203 0.683826 +vt 0.842742 0.065487 +vt 0.810950 0.071003 +vt 0.797415 0.054150 +vt 0.826859 0.044502 +vt 0.856320 0.030748 +vt 0.873324 0.055444 +vt 0.820158 0.713763 +vt 0.822791 0.740752 +vt 0.852813 0.747071 +vt 0.850041 0.725041 +vt 0.804325 0.025705 +vt 0.780633 0.034662 +vt 0.751694 0.023926 +vt 0.785603 0.008031 +vt 0.812357 0.000000 +vt 0.832739 0.010547 +vt 0.832246 0.769436 +vt 0.857055 0.773709 +vt 0.711345 0.200677 +vt 0.737251 0.237162 +vt 0.687836 0.157310 +vt 0.701074 0.149330 +vt 0.725170 0.186884 +vt 0.758965 0.224535 +vt 0.193380 0.634407 +vt 0.197066 0.609394 +vt 0.157718 0.614351 +vt 0.151427 0.635604 +vt 0.234022 0.633769 +vt 0.244978 0.605869 +vt 0.733567 0.173581 +vt 0.738041 0.160225 +vt 0.763053 0.199221 +vt 0.710506 0.144060 +vt 0.716260 0.141625 +vt 0.196017 0.579917 +vt 0.161911 0.590748 +vt 0.233735 0.568375 +vt 0.191770 0.554539 +vt 0.164274 0.566412 +vt 0.795178 0.226940 +vt 0.793451 0.247944 +vt 0.275160 0.563299 +vt 0.285813 0.592297 +vt 0.793871 0.272831 +vt 0.810018 0.283069 +vt 0.773964 0.263949 +vt 0.300074 0.618016 +vt 0.278791 0.625592 +vt 0.314712 0.634536 +vt 0.065920 0.600575 +vt 0.067626 0.625538 +vt 0.066039 0.602368 +vt 0.319074 0.615772 +vt 0.756076 0.262012 +vt 0.262875 0.635795 +vt 0.816620 0.289075 +vt 0.063576 0.609576 +vt 0.063028 0.626211 +vt 0.328142 0.621567 +vt 0.064214 0.601702 +vt 0.068014 0.572143 +vt 0.606754 0.183038 +vt 0.605665 0.163839 +vt 0.628061 0.180297 +vt 0.628169 0.200358 +vt 0.634589 0.224787 +vt 0.606338 0.203192 +vt 0.109922 0.573747 +vt 0.101084 0.595920 +vt 0.099476 0.614465 +vt 0.111555 0.588203 +vt 0.118550 0.566554 +vt 0.118652 0.552752 +vt 0.134572 0.533651 +vt 0.122221 0.557446 +vt 0.114950 0.579535 +vt 0.604156 0.222868 +vt 0.632290 0.240443 +vt 0.093664 0.617556 +vt 0.087598 0.632929 +vt 0.111147 0.601133 +vt 0.573440 0.466032 +vt 0.017855 0.399361 +vt 0.028351 0.419633 +vt 0.056493 0.417720 +vt 0.048232 0.394708 +vt 0.697655 0.104702 +vt 0.688970 0.104358 +vt 0.688643 0.054017 +vt 0.698260 0.064582 +vt 0.000040 0.409530 +vt 0.012132 0.428801 +vt 0.131321 0.593690 +vt 0.124865 0.615265 +vt 0.136522 0.571462 +vt 0.676199 0.111813 +vt 0.662370 0.119964 +vt 0.660119 0.081018 +vt 0.672430 0.073494 +vt 0.118645 0.635251 +vt 0.096359 0.636343 +vt 0.648694 0.251029 +vt 0.672520 0.051660 +vt 0.686401 0.031896 +vt 0.665284 0.050704 +vt 0.085894 0.641874 +vt 0.032841 0.971857 +vt 0.039736 0.951721 +vt 0.048007 0.948398 +vt 0.041201 0.970951 +vt 0.034646 0.988866 +vt 0.026465 0.987866 +vt 0.779600 0.920118 +vt 0.780334 0.902977 +vt 0.786794 0.902249 +vt 0.785918 0.917498 +vt 0.787233 0.935126 +vt 0.781404 0.940087 +vt 0.880181 0.586699 +vt 0.886161 0.590018 +vt 0.885303 0.605268 +vt 0.878967 0.603813 +vt 0.175538 0.861875 +vt 0.174385 0.844682 +vt 0.182478 0.846242 +vt 0.183216 0.865304 +vt 0.182770 0.888858 +vt 0.175918 0.883155 +vt 0.884237 0.567063 +vt 0.889466 0.572652 +vt 0.045796 0.926561 +vt 0.053512 0.921100 +vt 0.787287 0.963316 +vt 0.792458 0.956060 +vt 0.802848 0.972561 +vt 0.799069 0.981571 +vt 0.046856 0.903499 +vt 0.053336 0.896246 +vt 0.892714 0.544651 +vt 0.906489 0.527849 +vt 0.909223 0.537229 +vt 0.897029 0.552446 +vt 0.173962 0.908961 +vt 0.179628 0.916527 +vt 0.753991 0.448296 +vt 0.746875 0.453554 +vt 0.747237 0.461917 +vt 0.753980 0.457409 +vt 0.038752 0.889657 +vt 0.043101 0.881024 +vt 0.818573 0.986619 +vt 0.819659 0.976892 +vt 0.838682 0.970392 +vt 0.840604 0.979625 +vt 0.026486 0.885712 +vt 0.028844 0.876349 +vt 0.926440 0.525044 +vt 0.947536 0.534489 +vt 0.944580 0.543445 +vt 0.926416 0.534831 +vt 0.904594 0.519291 +vt 0.926983 0.516083 +vt 0.950439 0.525957 +vt 0.859966 0.961756 +vt 0.863459 0.969518 +vt 0.842521 0.988431 +vt 0.855710 0.954399 +vt 0.868047 0.931253 +vt 0.873730 0.935639 +vt 0.877805 0.941407 +vt 0.964748 0.554437 +vt 0.975464 0.581945 +vt 0.969320 0.585660 +vt 0.959686 0.561264 +vt 0.969098 0.547121 +vt 0.980166 0.576677 +vt 0.019381 0.692825 +vt 0.011364 0.691570 +vt 0.015496 0.666042 +vt 0.021993 0.668394 +vt 0.878967 0.903904 +vt 0.872999 0.903290 +vt 0.530189 0.866580 +vt 0.533873 0.869035 +vt 0.530456 0.899945 +vt 0.527403 0.901333 +vt 0.026253 0.716301 +vt 0.017393 0.716066 +vt 0.977070 0.614070 +vt 0.972140 0.647694 +vt 0.967146 0.643656 +vt 0.971071 0.614003 +vt 0.980846 0.611726 +vt 0.974394 0.648497 +vt 0.041651 0.738079 +vt 0.033029 0.738905 +vt 0.030431 0.710846 +vt 0.044868 0.730687 +vt 0.509877 0.917124 +vt 0.501974 0.920184 +vt 0.510078 0.896886 +vt 0.519173 0.890011 +vt 0.056564 0.752631 +vt 0.048431 0.754154 +vt 0.963247 0.679701 +vt 0.950885 0.705560 +vt 0.949212 0.694282 +vt 0.959753 0.671980 +vt 0.964068 0.683217 +vt 0.950080 0.711395 +vt 0.531831 0.925033 +vt 0.526413 0.932881 +vt 0.536264 0.895495 +vt 0.542776 0.889974 +vt 0.538284 0.917280 +vt 0.537148 0.939477 +vt 0.531235 0.949345 +vt 0.526591 0.960502 +vt 0.954759 0.056654 +vt 0.955709 0.032352 +vt 0.960983 0.042576 +vt 0.960707 0.064800 +vt 0.963456 0.092337 +vt 0.957308 0.086413 +vt 0.059021 0.533406 +vt 0.057518 0.551288 +vt 0.061467 0.544800 +vt 0.063510 0.525765 +vt 0.061766 0.512230 +vt 0.057495 0.520813 +vt 0.539667 0.867791 +vt 0.537949 0.843401 +vt 0.543334 0.844829 +vt 0.880872 0.455510 +vt 0.885488 0.473971 +vt 0.890247 0.476475 +vt 0.886171 0.459879 +vt 0.545617 0.864368 +vt 0.958945 0.114278 +vt 0.964665 0.118071 +vt 0.966134 0.139414 +vt 0.961147 0.137426 +vt 0.955682 0.138510 +vt 0.953242 0.112669 +vt 0.951794 0.081604 +vt 0.852635 0.950244 +vt 0.837942 0.964360 +vt 0.882489 0.495266 +vt 0.875567 0.516083 +vt 0.881688 0.513993 +vt 0.887672 0.495489 +vt 0.863264 0.929727 +vt 0.965389 0.153039 +vt 0.969663 0.153778 +vt 0.071147 0.509497 +vt 0.065786 0.510992 +vt 0.065950 0.491537 +vt 0.071466 0.487548 +vt 0.956160 0.565044 +vt 0.943161 0.549354 +vt 0.960600 0.155965 +vt 0.821475 0.970072 +vt 0.806737 0.966054 +vt 0.809901 0.962626 +vt 0.823312 0.966683 +vt 0.838025 0.961792 +vt 0.071466 0.469137 +vt 0.065737 0.475305 +vt 0.927447 0.541812 +vt 0.928888 0.545388 +vt 0.915104 0.547899 +vt 0.912349 0.544134 +vt 0.772996 0.006830 +vt 0.783123 0.004541 +vt 0.789197 0.018547 +vt 0.778804 0.019498 +vt 0.767957 0.017519 +vt 0.762458 0.005991 +vt 0.797232 0.950976 +vt 0.800846 0.948470 +vt 0.901197 0.558038 +vt 0.904503 0.560938 +vt 0.897486 0.577995 +vt 0.894074 0.576374 +vt 0.782018 0.031755 +vt 0.792112 0.031841 +vt 0.791816 0.043553 +vt 0.782292 0.042768 +vt 0.772288 0.039675 +vt 0.771422 0.029033 +vt 0.891065 0.591993 +vt 0.894457 0.592562 +vt 0.893953 0.605388 +vt 0.890488 0.605739 +vt 0.740096 0.146273 +vt 0.760629 0.148484 +vt 0.726411 0.138696 +vt 0.730120 0.125035 +vt 0.740704 0.133808 +vt 0.756214 0.132985 +vt 0.185867 0.541824 +vt 0.179926 0.537297 +vt 0.166322 0.536682 +vt 0.170527 0.547416 +vt 0.203938 0.526827 +vt 0.192481 0.528463 +vt 0.518865 0.868435 +vt 0.515474 0.856737 +vt 0.522493 0.839496 +vt 0.522258 0.860835 +vt 0.522687 0.885284 +vt 0.508659 0.879252 +vt 0.502025 0.867714 +vt 0.935548 0.720739 +vt 0.935844 0.705870 +vt 0.932645 0.728539 +vt 0.917862 0.743931 +vt 0.924934 0.726710 +vt 0.923028 0.709456 +vt 0.786886 0.132048 +vt 0.780944 0.116394 +vt 0.217559 0.509367 +vt 0.204817 0.513033 +vt 0.235777 0.496526 +vt 0.219457 0.497582 +vt 0.739211 0.451083 +vt 0.746875 0.448475 +vt 0.746080 0.460557 +vt 0.739232 0.461917 +vt 0.782064 0.888233 +vt 0.785550 0.876581 +vt 0.790592 0.876233 +vt 0.788144 0.888451 +vt 0.720930 0.462834 +vt 0.722446 0.473270 +vt 0.726984 0.478923 +vt 0.725746 0.467648 +vt 0.879016 0.618658 +vt 0.885081 0.619130 +vt 0.886129 0.631547 +vt 0.881159 0.630630 +vt 0.174025 0.831140 +vt 0.171727 0.820552 +vt 0.178707 0.820416 +vt 0.182069 0.832048 +vt 0.539346 0.961374 +vt 0.535832 0.975467 +vt 0.544374 0.949754 +vt 0.552946 0.951903 +vt 0.549219 0.964866 +vt 0.545700 0.982684 +vt 0.964567 0.020863 +vt 0.974642 0.018005 +vt 0.977539 0.031178 +vt 0.968847 0.032779 +vt 0.951782 0.020923 +vt 0.961956 0.006576 +vt 0.972261 0.000000 +vt 0.726020 0.107001 +vt 0.717892 0.098088 +vt 0.721706 0.093927 +vt 0.729643 0.101042 +vt 0.741339 0.107723 +vt 0.734511 0.116633 +vt 0.553914 0.963566 +vt 0.551129 0.977600 +vt 0.555847 0.949718 +vt 0.950808 0.495529 +vt 0.956135 0.492834 +vt 0.958390 0.481188 +vt 0.949838 0.485004 +vt 0.921466 0.691825 +vt 0.917107 0.702000 +vt 0.909933 0.693491 +vt 0.917626 0.685848 +vt 0.923957 0.676456 +vt 0.926371 0.681753 +vt 0.951915 0.505186 +vt 0.955620 0.503002 +vt 0.472743 0.950225 +vt 0.474369 0.942532 +vt 0.478749 0.942997 +vt 0.478673 0.953127 +vt 0.479233 0.968282 +vt 0.471466 0.957682 +vt 0.463255 0.947278 +vt 0.465336 0.943148 +vt 0.469020 0.940176 +vt 0.912135 0.679025 +vt 0.918043 0.671779 +vt 0.446397 0.945137 +vt 0.452640 0.939077 +vt 0.445308 0.930481 +vt 0.440335 0.943362 +vt 0.438130 0.952426 +vt 0.442062 0.952021 +vt 0.445022 0.952772 +vt 0.449216 0.949470 +vt 0.749138 0.085046 +vt 0.744266 0.077167 +vt 0.751865 0.069213 +vt 0.758782 0.074302 +vt 0.769550 0.079706 +vt 0.756742 0.094313 +vt 0.739860 0.093025 +vt 0.737730 0.083325 +vt 0.162230 0.524378 +vt 0.158451 0.529749 +vt 0.167281 0.533656 +vt 0.173480 0.524860 +vt 0.176743 0.514612 +vt 0.164687 0.514513 +vt 0.899875 0.670390 +vt 0.896184 0.654398 +vt 0.898337 0.650806 +vt 0.899466 0.664502 +vt 0.153927 0.521902 +vt 0.151653 0.527747 +vt 0.767049 0.066274 +vt 0.773897 0.059296 +vt 0.782979 0.060940 +vt 0.777519 0.069243 +vt 0.759081 0.062594 +vt 0.765320 0.056116 +vt 0.893452 0.641706 +vt 0.897020 0.639170 +vt 0.894065 0.655742 +vt 0.889082 0.642465 +vt 0.891627 0.630374 +vt 0.895688 0.628382 +vt 0.779281 0.051705 +vt 0.788258 0.052815 +vt 0.769988 0.048590 +vt 0.890657 0.618459 +vt 0.894514 0.617224 +vt 0.790681 0.071537 +vt 0.786079 0.085539 +vt 0.790758 0.060559 +vt 0.886229 0.639126 +vt 0.190479 0.504935 +vt 0.178069 0.507894 +vt 0.193637 0.508168 +vt 0.867611 0.735411 +vt 0.878967 0.726690 +vt 0.861723 0.744159 +vt 0.769120 0.104289 +vt 0.750481 0.120008 +vt 0.188900 0.519638 +vt 0.181225 0.531645 +vt 0.740839 0.124915 +vt 0.949735 0.475192 +vt 0.939040 0.472518 +vt 0.939028 0.487781 +vt 0.955168 0.468463 +vt 0.175569 0.536485 +vt 0.763157 0.044514 +vt 0.764993 0.035726 +vt 0.759057 0.051893 +vt 0.752918 0.048628 +vt 0.756663 0.041260 +vt 0.758468 0.032736 +vt 0.895424 0.616004 +vt 0.897468 0.614461 +vt 0.898119 0.625306 +vt 0.896345 0.626841 +vt 0.152159 0.488839 +vt 0.152698 0.496186 +vt 0.160251 0.496305 +vt 0.160124 0.488812 +vt 0.895132 0.604375 +vt 0.897515 0.602846 +vt 0.753424 0.058168 +vt 0.746889 0.064326 +vt 0.742112 0.061448 +vt 0.747913 0.055131 +vt 0.897468 0.637178 +vt 0.899120 0.635614 +vt 0.899921 0.646425 +vt 0.898384 0.648181 +vt 0.151347 0.503392 +vt 0.149200 0.511396 +vt 0.155997 0.512049 +vt 0.158490 0.503783 +vt 0.740081 0.071352 +vt 0.734394 0.076956 +vt 0.732820 0.073139 +vt 0.735978 0.068257 +vt 0.898681 0.661020 +vt 0.899974 0.658780 +vt 0.901282 0.665578 +vt 0.900301 0.670097 +vt 0.147350 0.521141 +vt 0.145548 0.527150 +vt 0.475401 0.936538 +vt 0.479303 0.936078 +vt 0.468464 0.935746 +vt 0.467203 0.930481 +vt 0.474122 0.931038 +vt 0.476726 0.931400 +vt 0.441940 0.958071 +vt 0.441705 0.962683 +vt 0.445444 0.961283 +vt 0.444975 0.956715 +vt 0.438473 0.959265 +vt 0.438123 0.962545 +vt 0.463357 0.937359 +vt 0.722345 0.083901 +vt 0.727049 0.088348 +vt 0.716442 0.088430 +vt 0.714123 0.083680 +vt 0.719700 0.079197 +vt 0.461954 0.931832 +vt 0.451478 0.954669 +vt 0.451791 0.959389 +vt 0.458643 0.957310 +vt 0.458654 0.952711 +vt 0.456341 0.946434 +vt 0.712653 0.091967 +vt 0.716261 0.102097 +vt 0.711471 0.095528 +vt 0.559330 0.942930 +vt 0.557257 0.945565 +vt 0.558098 0.941586 +vt 0.561017 0.938455 +vt 0.710557 0.088149 +vt 0.952428 0.512397 +vt 0.951805 0.516083 +vt 0.954407 0.512851 +vt 0.955513 0.510490 +vt 0.927128 0.677122 +vt 0.925419 0.671920 +vt 0.925561 0.667578 +vt 0.927517 0.673525 +vt 0.549453 0.943753 +vt 0.542732 0.933830 +vt 0.548228 0.928757 +vt 0.554032 0.939106 +vt 0.973534 0.039090 +vt 0.977810 0.044019 +vt 0.971360 0.053978 +vt 0.966197 0.048567 +vt 0.981438 0.037778 +vt 0.982024 0.041802 +vt 0.763834 0.025222 +vt 0.760314 0.013992 +vt 0.757655 0.022763 +vt 0.754803 0.012198 +vt 0.895897 0.591662 +vt 0.898611 0.590226 +vt 0.899128 0.577283 +vt 0.901720 0.576321 +vt 0.802535 0.948948 +vt 0.811504 0.962855 +vt 0.755066 0.003029 +vt 0.750489 0.001893 +vt 0.804116 0.948931 +vt 0.812655 0.960532 +vt 0.906236 0.560654 +vt 0.907804 0.560850 +vt 0.916723 0.547853 +vt 0.917603 0.550291 +vt 0.058526 0.590305 +vt 0.056686 0.598012 +vt 0.060689 0.593255 +vt 0.063028 0.585315 +vt 0.061620 0.572143 +vt 0.056700 0.577461 +vt 0.824459 0.967247 +vt 0.824840 0.964304 +vt 0.837861 0.960425 +vt 0.838575 0.962954 +vt 0.930092 0.544957 +vt 0.930137 0.547925 +vt 0.060101 0.478445 +vt 0.061390 0.468709 +vt 0.067292 0.464839 +vt 0.060500 0.493696 +vt 0.943630 0.550823 +vt 0.942635 0.553254 +vt 0.893269 0.496110 +vt 0.895584 0.477908 +vt 0.887856 0.513839 +vt 0.851028 0.950802 +vt 0.848909 0.949074 +vt 0.856206 0.931991 +vt 0.859602 0.932582 +vt 0.954626 0.564308 +vt 0.952325 0.565784 +vt 0.060648 0.512230 +vt 0.061183 0.456068 +vt 0.058074 0.458386 +vt 0.058098 0.440375 +vt 0.060835 0.438704 +vt 0.961080 0.583382 +vt 0.957639 0.583585 +vt 0.891970 0.462289 +vt 0.882053 0.449265 +vt 0.875608 0.445917 +vt 0.549769 0.860285 +vt 0.551626 0.839496 +vt 0.554546 0.840606 +vt 0.553524 0.860019 +vt 0.552540 0.883310 +vt 0.547939 0.885370 +vt 0.968550 0.122410 +vt 0.972280 0.122914 +vt 0.972068 0.142352 +vt 0.969083 0.143275 +vt 0.968316 0.097260 +vt 0.972777 0.099607 +vt 0.543910 0.912126 +vt 0.549253 0.908191 +vt 0.965995 0.070301 +vt 0.971077 0.074568 +vt 0.828593 0.856453 +vt 0.820784 0.855787 +vt 0.820130 0.847851 +vt 0.827707 0.847866 +vt 0.833854 0.844903 +vt 0.835213 0.853924 +vt 0.836522 0.865763 +vt 0.829190 0.867603 +vt 0.821159 0.866277 +vt 0.921643 0.655506 +vt 0.923500 0.644496 +vt 0.930576 0.647155 +vt 0.927934 0.658769 +vt 0.919790 0.663938 +vt 0.912260 0.663094 +vt 0.913809 0.655283 +vt 0.915370 0.644903 +vt 0.828054 0.879402 +vt 0.820101 0.877745 +vt 0.836017 0.878546 +vt 0.834473 0.891586 +vt 0.825904 0.891166 +vt 0.818136 0.889412 +vt 0.923709 0.632644 +vt 0.922906 0.620712 +vt 0.931467 0.621266 +vt 0.931524 0.634397 +vt 0.915619 0.633389 +vt 0.914989 0.621575 +vt 0.823457 0.902209 +vt 0.815787 0.900500 +vt 0.832662 0.904196 +vt 0.831172 0.915748 +vt 0.821840 0.912484 +vt 0.814125 0.911239 +vt 0.921726 0.609463 +vt 0.921284 0.599071 +vt 0.930926 0.596885 +vt 0.931097 0.608532 +vt 0.913912 0.610292 +vt 0.913477 0.599434 +vt 0.822181 0.921943 +vt 0.814220 0.921858 +vt 0.830592 0.925612 +vt 0.829466 0.934881 +vt 0.823390 0.933581 +vt 0.814767 0.934036 +vt 0.922694 0.589712 +vt 0.925215 0.578286 +vt 0.931399 0.577683 +vt 0.931467 0.587020 +vt 0.914775 0.588894 +vt 0.916698 0.576856 +vt 0.931158 0.511327 +vt 0.933460 0.498866 +vt 0.937557 0.500927 +vt 0.934365 0.516083 +vt 0.805361 0.920555 +vt 0.798311 0.918702 +vt 0.798652 0.906040 +vt 0.805468 0.908730 +vt 0.925838 0.506881 +vt 0.927599 0.494818 +vt 0.905825 0.589184 +vt 0.904592 0.600945 +vt 0.907982 0.577191 +vt 0.806885 0.897506 +vt 0.799922 0.894494 +vt 0.801798 0.883793 +vt 0.808937 0.886598 +vt 0.904728 0.612257 +vt 0.905530 0.623328 +vt 0.810949 0.875719 +vt 0.803960 0.873664 +vt 0.805981 0.863013 +vt 0.812453 0.864744 +vt 0.906297 0.634365 +vt 0.906547 0.645440 +vt 0.812980 0.853550 +vt 0.813220 0.844602 +vt 0.807435 0.850745 +vt 0.809505 0.844139 +vt 0.905802 0.656621 +vt 0.905027 0.665538 +vt 0.557564 0.931544 +vt 0.553876 0.920616 +vt 0.559345 0.914259 +vt 0.561034 0.925359 +vt 0.839453 0.846572 +vt 0.836471 0.839216 +vt 0.980855 0.051790 +vt 0.983925 0.058182 +vt 0.981534 0.069153 +vt 0.976479 0.062461 +vt 0.984739 0.045112 +vt 0.931313 0.666554 +vt 0.554854 0.904094 +vt 0.557367 0.885422 +vt 0.845201 0.873032 +vt 0.846075 0.890397 +vt 0.560210 0.901934 +vt 0.940023 0.640917 +vt 0.936241 0.655816 +vt 0.942860 0.623762 +vt 0.952740 0.627003 +vt 0.947138 0.648215 +vt 0.940542 0.665147 +vt 0.846170 0.908025 +vt 0.857976 0.910915 +vt 0.844679 0.924315 +vt 0.856259 0.888297 +vt 0.944951 0.606258 +vt 0.945316 0.589905 +vt 0.957009 0.604725 +vt 0.840799 0.937667 +vt 0.834157 0.946789 +vt 0.942974 0.576199 +vt 0.937409 0.566383 +vt 0.926489 0.474439 +vt 0.930122 0.459992 +vt 0.936446 0.468348 +vt 0.932207 0.479068 +vt 0.922223 0.492122 +vt 0.919884 0.488084 +vt 0.920724 0.473977 +vt 0.922547 0.458508 +vt 0.928103 0.561696 +vt 0.918144 0.561507 +vt 0.935933 0.485951 +vt 0.939028 0.483077 +vt 0.910618 0.565184 +vt 0.024145 0.495486 +vt 0.010473 0.529549 +vt 0.025704 0.527915 +vt 0.041111 0.494580 +vt 0.054588 0.463653 +vt 0.036321 0.464534 +vt 0.023503 0.469101 +vt 0.013718 0.497685 +vt 0.002440 0.530199 +vt 0.113835 0.498959 +vt 0.103187 0.499386 +vt 0.119685 0.524695 +vt 0.133232 0.525978 +vt 0.151157 0.522351 +vt 0.130505 0.495675 +vt 0.107390 0.467139 +vt 0.092223 0.469292 +vt 0.084277 0.470632 +vt 0.000000 0.683584 +vt 0.005855 0.659587 +vt 0.004244 0.706622 +vt 0.006188 0.563110 +vt 0.000000 0.563693 +vt 0.004656 0.590864 +vt 0.010206 0.589915 +vt 0.079835 0.437808 +vt 0.073693 0.438760 +vt 0.093017 0.438038 +vt 0.088378 0.413252 +vt 0.077155 0.410836 +vt 0.071541 0.411278 +vt 0.021866 0.634834 +vt 0.041072 0.611276 +vt 0.049371 0.616136 +vt 0.030338 0.640107 +vt 0.004662 0.643568 +vt 0.017651 0.625045 +vt 0.033348 0.609149 +vt 0.084664 0.394708 +vt 0.077923 0.395693 +vt 0.970487 0.541871 +vt 0.980766 0.571039 +vt 0.810866 0.441888 +vt 0.801991 0.443191 +vt 0.801962 0.473814 +vt 0.810559 0.472300 +vt 0.818430 0.468997 +vt 0.820346 0.446745 +vt 0.050292 0.874935 +vt 0.062757 0.890315 +vt 0.034600 0.870082 +vt 0.056515 0.590864 +vt 0.042333 0.592652 +vt 0.569960 0.003528 +vt 0.583723 0.003656 +vt 0.572957 0.019770 +vt 0.553188 0.019963 +vt 0.813792 0.497800 +vt 0.823293 0.487394 +vt 0.803583 0.499526 +vt 0.802628 0.516083 +vt 0.815317 0.514149 +vt 0.285236 0.966108 +vt 0.271399 0.947135 +vt 0.290867 0.950580 +vt 0.298832 0.968247 +vt 0.768323 0.516083 +vt 0.757724 0.506625 +vt 0.741741 0.502226 +vt 0.753413 0.512129 +vt 0.065118 0.915739 +vt 0.544014 0.043966 +vt 0.567530 0.044903 +vt 0.564649 0.072592 +vt 0.539739 0.069605 +vt 0.266303 0.921949 +vt 0.289651 0.924897 +vt 0.189027 0.925192 +vt 0.178975 0.948663 +vt 0.171830 0.940127 +vt 0.194022 0.896904 +vt 0.266307 0.895957 +vt 0.291368 0.897111 +vt 0.747954 0.495323 +vt 0.742227 0.483275 +vt 0.732624 0.490803 +vt 0.537662 0.090946 +vt 0.561523 0.096374 +vt 0.768538 0.482144 +vt 0.761821 0.471033 +vt 0.267772 0.874565 +vt 0.292201 0.873139 +vt 0.195436 0.871641 +vt 0.195670 0.851104 +vt 0.272456 0.857843 +vt 0.295732 0.853753 +vt 0.606722 0.105261 +vt 0.610873 0.077446 +vt 0.651393 0.081707 +vt 0.646179 0.113168 +vt 0.637869 0.140362 +vt 0.602702 0.128771 +vt 0.561814 0.116077 +vt 0.338247 0.871815 +vt 0.338153 0.847964 +vt 0.374747 0.842322 +vt 0.378467 0.870513 +vt 0.378430 0.902403 +vt 0.337762 0.899934 +vt 0.610637 0.046282 +vt 0.607986 0.019683 +vt 0.637576 0.018783 +vt 0.648409 0.047749 +vt 0.332398 0.930634 +vt 0.369896 0.935406 +vt 0.354441 0.962193 +vt 0.325403 0.956433 +vt 0.604892 0.005568 +vt 0.598670 0.000000 +vt 0.619242 0.002297 +vt 0.320027 0.969847 +vt 0.333643 0.975435 +vt 0.826265 0.465093 +vt 0.547087 0.121619 +vt 0.569182 0.131527 +vt 0.545740 0.129074 +vt 0.743755 0.471574 +vt 0.741912 0.470464 +vt 0.765532 0.461957 +vt 0.197124 0.836994 +vt 0.200262 0.829946 +vt 0.282119 0.845862 +vt 0.282017 0.838287 +vt 0.310088 0.828078 +vt 0.305543 0.839727 +vt 0.603332 0.147023 +vt 0.631561 0.161518 +vt 0.341779 0.830065 +vt 0.372009 0.820416 +vt 0.125744 0.534649 +vt 0.140665 0.520402 +vt 0.123033 0.546235 +vt 0.036114 0.440303 +vt 0.055590 0.439137 +vt 0.021463 0.447399 +vt 0.138977 0.549519 +vt 0.158144 0.545872 +vn 0.702628 -0.228828 0.673727 +vn 0.744530 -0.000946 0.667562 +vn 0.821741 -0.001953 0.569811 +vn 0.776666 -0.263192 0.572283 +vn 0.628681 -0.515580 0.582141 +vn 0.573046 -0.435255 0.694357 +vn 0.618030 -0.502579 0.604480 +vn 0.759575 -0.264351 0.594226 +vn 0.806085 -0.001007 0.591784 +vn -0.702628 -0.228828 0.673727 +vn -0.759575 -0.264351 0.594226 +vn -0.618030 -0.502579 0.604480 +vn -0.573046 -0.435255 0.694357 +vn -0.628681 -0.515580 0.582141 +vn -0.776666 -0.263192 0.572283 +vn -0.821741 -0.001953 0.569811 +vn -0.744530 -0.000946 0.667562 +vn -0.806085 -0.001007 0.591784 +vn 0.813959 -0.298746 0.498154 +vn 0.865261 -0.001373 0.501297 +vn 0.656545 -0.569659 0.494369 +vn 0.678762 -0.572985 0.459304 +vn 0.831935 -0.299051 0.467330 +vn 0.881466 -0.000488 0.472243 +vn -0.813959 -0.298746 0.498154 +vn -0.831935 -0.299051 0.467330 +vn -0.678762 -0.572985 0.459304 +vn -0.656545 -0.569659 0.494369 +vn -0.865261 -0.001373 0.501297 +vn -0.881466 -0.000488 0.472243 +vn 0.406262 -0.770928 0.490493 +vn 0.395215 -0.676229 0.621662 +vn 0.112339 -0.755150 0.645802 +vn 0.086734 -0.861873 0.499588 +vn 0.097751 -0.888424 0.448469 +vn 0.425947 -0.786645 0.446913 +vn -0.406262 -0.770928 0.490493 +vn -0.425947 -0.786645 0.446913 +vn -0.097751 -0.888424 0.448469 +vn -0.086734 -0.861873 0.499588 +vn -0.112339 -0.755150 0.645802 +vn -0.395215 -0.676229 0.621662 +vn 0.375835 -0.578753 0.723685 +vn 0.398541 -0.700583 0.591876 +vn 0.116977 -0.783868 0.609760 +vn 0.136601 -0.641163 0.755120 +vn -0.375835 -0.578753 0.723685 +vn -0.136601 -0.641163 0.755120 +vn -0.116977 -0.783868 0.609760 +vn -0.398541 -0.700583 0.591876 +vn -0.126438 -0.613758 0.779260 +vn -0.199194 -0.751244 0.629231 +vn -0.493759 -0.578539 0.649190 +vn -0.373547 -0.470656 0.799310 +vn -0.460891 -0.548357 0.697745 +vn -0.190802 -0.716514 0.670949 +vn 0.126438 -0.613758 0.779260 +vn 0.190802 -0.716514 0.670949 +vn 0.460891 -0.548357 0.697745 +vn 0.373547 -0.470656 0.799310 +vn 0.493759 -0.578539 0.649190 +vn 0.199194 -0.751244 0.629231 +vn -0.250557 -0.815119 0.522233 +vn -0.544816 -0.626118 0.557756 +vn -0.563097 -0.651204 0.508713 +vn -0.256233 -0.844874 0.469558 +vn 0.250557 -0.815119 0.522233 +vn 0.256233 -0.844874 0.469558 +vn 0.563097 -0.651204 0.508713 +vn 0.544816 -0.626118 0.557756 +vn -0.740043 -0.332652 0.584490 +vn -0.637928 -0.287179 0.714530 +vn -0.693930 -0.001129 0.720023 +vn -0.802972 -0.001556 0.595965 +vn -0.833247 -0.000397 0.552843 +vn -0.767418 -0.346934 0.539140 +vn 0.740043 -0.332652 0.584490 +vn 0.767418 -0.346934 0.539140 +vn 0.833247 -0.000397 0.552843 +vn 0.802972 -0.001556 0.595965 +vn 0.693930 -0.001129 0.720023 +vn 0.637928 -0.287179 0.714530 +vn -0.537706 -0.242714 0.807428 +vn -0.695853 -0.304788 0.650258 +vn -0.761956 -0.002441 0.647603 +vn -0.588061 -0.000977 0.808802 +vn 0.537706 -0.242714 0.807428 +vn 0.588061 -0.000977 0.808802 +vn 0.761956 -0.002441 0.647603 +vn 0.695853 -0.304788 0.650258 +vn -0.546037 0.239967 0.802606 +vn -0.709311 0.295450 0.639973 +vn -0.520798 0.579211 0.627094 +vn -0.391308 0.476699 0.787133 +vn -0.464522 0.542283 0.700064 +vn -0.639332 0.281961 0.715323 +vn 0.546037 0.239967 0.802606 +vn 0.639332 0.281961 0.715323 +vn 0.464522 0.542283 0.700064 +vn 0.391308 0.476699 0.787133 +vn 0.520798 0.579211 0.627094 +vn 0.709311 0.295450 0.639973 +vn -0.736900 0.323862 0.593341 +vn -0.538316 0.609912 0.581530 +vn -0.549242 0.636402 0.541520 +vn -0.761406 0.340892 0.551378 +vn 0.736900 0.323862 0.593341 +vn 0.761406 0.340892 0.551378 +vn 0.549242 0.636402 0.541520 +vn 0.538316 0.609912 0.581530 +vn -0.240150 0.794610 0.557573 +vn -0.191931 0.713370 0.673940 +vn 0.113468 0.752190 0.649068 +vn 0.093722 0.838130 0.537309 +vn 0.105930 0.859462 0.500046 +vn -0.239448 0.820978 0.518296 +vn 0.240150 0.794610 0.557573 +vn 0.239448 0.820978 0.518296 +vn -0.105930 0.859462 0.500046 +vn -0.093722 0.838130 0.537309 +vn -0.113468 0.752190 0.649068 +vn 0.191931 0.713370 0.673940 +vn -0.141057 0.634602 0.759819 +vn -0.220679 0.773247 0.594409 +vn 0.109226 0.813990 0.570452 +vn 0.132633 0.666555 0.733512 +vn 0.141057 0.634602 0.759819 +vn -0.132633 0.666555 0.733512 +vn -0.109226 0.813990 0.570452 +vn 0.220679 0.773247 0.594409 +vn 0.382397 0.598102 0.704276 +vn 0.406446 0.723075 0.558489 +vn 0.646077 0.517411 0.561083 +vn 0.584490 0.440382 0.681448 +vn 0.621296 0.496261 0.606342 +vn 0.397504 0.672292 0.624470 +vn -0.382397 0.598102 0.704276 +vn -0.397504 0.672292 0.624470 +vn -0.621296 0.496261 0.606342 +vn -0.584490 0.440382 0.681448 +vn -0.646077 0.517411 0.561083 +vn -0.406446 0.723075 0.558489 +vn 0.407208 0.748802 0.522904 +vn 0.655599 0.552446 0.514725 +vn 0.673513 0.557360 0.485488 +vn 0.423811 0.761650 0.490127 +vn -0.407208 0.748802 0.522904 +vn -0.423811 0.761650 0.490127 +vn -0.673513 0.557360 0.485488 +vn -0.655599 0.552446 0.514725 +vn 0.812494 0.290292 0.505478 +vn 0.760796 0.259560 0.594775 +vn 0.828669 0.293191 0.476760 +vn -0.812494 0.290292 0.505478 +vn -0.828669 0.293191 0.476760 +vn -0.760796 0.259560 0.594775 +vn 0.708518 0.226173 0.668447 +vn 0.785943 0.255776 0.562883 +vn -0.708518 0.226173 0.668447 +vn -0.785943 0.255776 0.562883 +vn 0.824183 0.271401 0.496994 +vn 0.863857 -0.002106 0.503677 +vn 0.675893 0.563616 0.474837 +vn 0.548784 0.361492 0.753746 +vn 0.645161 0.176244 0.743400 +vn 0.660970 -0.001709 0.750389 +vn -0.824183 0.271401 0.496994 +vn -0.645161 0.176244 0.743400 +vn -0.548784 0.361492 0.753746 +vn -0.675893 0.563616 0.474837 +vn -0.863857 -0.002106 0.503677 +vn -0.660970 -0.001709 0.750389 +vn 0.414014 0.792566 0.447645 +vn 0.078982 0.898923 0.430860 +vn 0.151891 0.613575 0.774865 +vn 0.380291 0.541185 0.749962 +vn -0.414014 0.792566 0.447645 +vn -0.380291 0.541185 0.749962 +vn -0.151891 0.613575 0.774865 +vn -0.078982 0.898923 0.430860 +vn -0.279702 0.845119 0.455519 +vn -0.604297 0.635365 0.480697 +vn -0.356517 0.427961 0.830470 +vn -0.123997 0.589801 0.797937 +vn 0.279702 0.845119 0.455519 +vn 0.123997 0.589801 0.797937 +vn 0.356517 0.427961 0.830470 +vn 0.604297 0.635365 0.480697 +vn -0.813898 0.334635 0.474929 +vn -0.887906 -0.002686 0.459944 +vn -0.581988 -0.002594 0.813166 +vn -0.531388 0.225166 0.816645 +vn 0.813898 0.334635 0.474929 +vn 0.531388 0.225166 0.816645 +vn 0.581988 -0.002594 0.813166 +vn 0.887906 -0.002686 0.459944 +vn -0.807276 -0.349498 0.475509 +vn -0.589953 -0.648976 0.480361 +vn -0.354289 -0.452528 0.818323 +vn -0.532456 -0.242286 0.810999 +vn 0.807276 -0.349498 0.475509 +vn 0.532456 -0.242286 0.810999 +vn 0.354289 -0.452528 0.818323 +vn 0.589953 -0.648976 0.480361 +vn -0.273812 -0.846767 0.456038 +vn 0.080294 -0.897336 0.433943 +vn 0.146611 -0.641591 0.752861 +vn -0.129795 -0.613849 0.778649 +vn 0.273812 -0.846767 0.456038 +vn 0.129795 -0.613849 0.778649 +vn -0.146611 -0.641591 0.752861 +vn -0.080294 -0.897336 0.433943 +vn 0.410382 -0.791955 0.452071 +vn 0.663991 -0.573199 0.480087 +vn 0.546373 -0.385266 0.743645 +vn 0.379864 -0.565935 0.731681 +vn -0.410382 -0.791955 0.452071 +vn -0.379864 -0.565935 0.731681 +vn -0.546373 -0.385266 0.743645 +vn -0.663991 -0.573199 0.480087 +vn 0.818628 -0.283395 0.499466 +vn 0.646107 -0.190893 0.738975 +vn -0.818628 -0.283395 0.499466 +vn -0.646107 -0.190893 0.738975 +vn 0.414655 -0.075259 0.906827 +vn 0.399304 -0.000946 0.916807 +vn 0.190924 -0.002625 0.981567 +vn 0.353343 -0.126255 0.926908 +vn -0.414655 -0.075259 0.906827 +vn -0.399304 -0.000946 0.916807 +vn -0.353343 -0.126255 0.926908 +vn -0.190924 -0.002625 0.981567 +vn 0.302194 -0.207068 0.930448 +vn 0.201788 -0.197821 0.959227 +vn -0.302194 -0.207068 0.930448 +vn -0.201788 -0.197821 0.959227 +vn 0.080477 -0.215522 0.973144 +vn 0.008667 -0.124638 0.992157 +vn -0.080477 -0.215522 0.973144 +vn -0.008667 -0.124638 0.992157 +vn -0.086825 -0.063814 0.994171 +vn -0.067965 -0.000488 0.997681 +vn 0.086825 -0.063814 0.994171 +vn 0.067965 -0.000488 0.997681 +vn -0.086001 0.058077 0.994598 +vn 0.009919 0.117069 0.993042 +vn 0.086001 0.058077 0.994598 +vn -0.009919 0.117069 0.993042 +vn 0.082675 0.203406 0.975585 +vn 0.202460 0.185369 0.961577 +vn -0.082675 0.203406 0.975585 +vn -0.202460 0.185369 0.961577 +vn 0.301309 0.195471 0.933256 +vn 0.352641 0.118686 0.928190 +vn -0.301309 0.195471 0.933256 +vn -0.352641 0.118686 0.928190 +vn 0.414106 0.069247 0.907559 +vn -0.414106 0.069247 0.907559 +vn 0.101260 -0.898770 0.426527 +vn 0.097354 -0.985443 0.139348 +vn 0.148595 -0.983032 0.107456 +vn 0.163762 -0.895932 0.412854 +vn 0.155339 -0.768944 0.620106 +vn 0.091342 -0.788354 0.608386 +vn 0.000000 -0.793664 0.608325 +vn 0.000000 -0.899777 0.436323 +vn 0.000000 -0.987457 0.157811 +vn -0.101260 -0.898770 0.426527 +vn -0.091342 -0.788354 0.608386 +vn -0.155339 -0.768944 0.620106 +vn -0.163762 -0.895932 0.412854 +vn -0.148595 -0.983032 0.107456 +vn -0.097354 -0.985443 0.139348 +vn 0.269112 -0.856258 0.440840 +vn 0.261757 -0.960234 0.096774 +vn 0.596606 -0.794824 0.110782 +vn 0.472793 -0.715720 0.513962 +vn 0.379040 -0.551775 0.742851 +vn 0.249580 -0.701102 0.667928 +vn -0.269112 -0.856258 0.440840 +vn -0.249580 -0.701102 0.667928 +vn -0.379040 -0.551775 0.742851 +vn -0.472793 -0.715720 0.513962 +vn -0.596606 -0.794824 0.110782 +vn -0.261757 -0.960234 0.096774 +vn 0.687613 -0.438643 0.578570 +vn 0.911008 -0.392804 0.125523 +vn 0.988800 -0.070467 0.131535 +vn 0.787652 -0.196081 0.584063 +vn 0.532762 -0.222114 0.816553 +vn 0.473128 -0.367229 0.800775 +vn -0.687613 -0.438643 0.578570 +vn -0.473128 -0.367229 0.800775 +vn -0.532762 -0.222114 0.816553 +vn -0.787652 -0.196081 0.584063 +vn -0.988800 -0.070467 0.131535 +vn -0.911008 -0.392804 0.125523 +vn 0.819910 -0.045137 0.570666 +vn 0.990966 0.060823 0.119358 +vn 0.985717 0.115085 0.122745 +vn 0.822443 0.042573 0.567217 +vn 0.582995 -0.012940 0.812342 +vn 0.569811 -0.100864 0.815546 +vn -0.819910 -0.045137 0.570666 +vn -0.569811 -0.100864 0.815546 +vn -0.582995 -0.012940 0.812342 +vn -0.822443 0.042573 0.567217 +vn -0.985717 0.115085 0.122745 +vn -0.990966 0.060823 0.119358 +vn 0.823603 0.097568 0.558672 +vn 0.981048 0.148167 0.124607 +vn 0.966369 0.215583 0.140049 +vn 0.829035 0.167577 0.533464 +vn 0.612690 0.085604 0.785668 +vn 0.590472 0.034791 0.806299 +vn -0.823603 0.097568 0.558672 +vn -0.590472 0.034791 0.806299 +vn -0.612690 0.085604 0.785668 +vn -0.829035 0.167577 0.533464 +vn -0.966369 0.215583 0.140049 +vn -0.981048 0.148167 0.124607 +vn 0.376049 -0.776391 0.505722 +vn 0.639485 -0.578784 0.505997 +vn 0.631184 -0.731529 0.257729 +vn 0.335704 -0.914762 0.224708 +vn 0.359386 -0.910428 0.204810 +vn 0.369854 -0.755303 0.540971 +vn 0.383312 -0.553758 0.739158 +vn 0.405866 -0.478866 0.778375 +vn 0.222449 -0.201544 0.953856 +vn -0.376049 -0.776391 0.505722 +vn -0.405866 -0.478866 0.778375 +vn -0.383312 -0.553758 0.739158 +vn -0.369854 -0.755303 0.540971 +vn -0.359386 -0.910428 0.204810 +vn -0.335704 -0.914762 0.224708 +vn -0.631184 -0.731529 0.257729 +vn -0.639485 -0.578784 0.505997 +vn -0.222449 -0.201544 0.953856 +vn 0.443587 -0.688955 0.573168 +vn 0.474654 -0.857418 0.198798 +vn 0.609302 -0.770562 0.186926 +vn 0.570544 -0.589099 0.572192 +vn 0.494156 -0.431806 0.754540 +vn 0.414258 -0.524247 0.743980 +vn -0.443587 -0.688955 0.573168 +vn -0.414258 -0.524247 0.743980 +vn -0.494156 -0.431806 0.754540 +vn -0.570544 -0.589099 0.572192 +vn -0.609302 -0.770562 0.186926 +vn -0.474654 -0.857418 0.198798 +vn 0.683340 -0.479904 0.550157 +vn 0.748680 -0.646260 0.147526 +vn 0.895779 -0.427473 0.121677 +vn 0.732322 -0.391614 0.557024 +vn 0.584826 -0.320688 0.745048 +vn 0.569659 -0.354442 0.741508 +vn -0.683340 -0.479904 0.550157 +vn -0.569659 -0.354442 0.741508 +vn -0.584826 -0.320688 0.745048 +vn -0.732322 -0.391614 0.557024 +vn -0.895779 -0.427473 0.121677 +vn -0.748680 -0.646260 0.147526 +vn 0.737266 -0.304788 0.602893 +vn 0.975402 -0.151616 0.159856 +vn 0.934965 0.283181 0.213569 +vn 0.746300 -0.055361 0.663259 +vn 0.487716 -0.293344 0.822199 +vn 0.534257 -0.312326 0.785485 +vn -0.737266 -0.304788 0.602893 +vn -0.534257 -0.312326 0.785485 +vn -0.487716 -0.293344 0.822199 +vn -0.746300 -0.055361 0.663259 +vn -0.934965 0.283181 0.213569 +vn -0.975402 -0.151616 0.159856 +vn 0.639821 0.326090 0.695883 +vn 0.659658 0.715781 0.229041 +vn 0.472213 0.865291 0.168004 +vn 0.527757 0.548540 0.648488 +vn 0.353099 -0.046693 0.934416 +vn 0.438765 -0.154241 0.885250 +vn -0.639821 0.326090 0.695883 +vn -0.438765 -0.154241 0.885250 +vn -0.353099 -0.046693 0.934416 +vn -0.527757 0.548540 0.648488 +vn -0.472213 0.865291 0.168004 +vn -0.659658 0.715781 0.229041 +vn 0.518601 0.602802 0.606311 +vn 0.512772 0.846828 0.141179 +vn 0.588946 0.793542 0.152837 +vn 0.551195 0.563891 0.614948 +vn 0.305002 0.028565 0.951903 +vn 0.308786 0.016785 0.950957 +vn -0.518601 0.602802 0.606311 +vn -0.308786 0.016785 0.950957 +vn -0.305002 0.028565 0.951903 +vn -0.551195 0.563891 0.614948 +vn -0.588946 0.793542 0.152837 +vn -0.512772 0.846828 0.141179 +vn 0.535295 0.554613 0.637013 +vn 0.588519 0.790490 0.169439 +vn 0.314859 0.932188 0.178411 +vn 0.331889 0.642659 0.690512 +vn 0.258614 0.102695 0.960479 +vn 0.308603 0.051515 0.949767 +vn -0.535295 0.554613 0.637013 +vn -0.308603 0.051515 0.949767 +vn -0.258614 0.102695 0.960479 +vn -0.331889 0.642659 0.690512 +vn -0.314859 0.932188 0.178411 +vn -0.588519 0.790490 0.169439 +vn -0.072085 0.670247 0.738609 +vn -0.204352 0.961180 0.185247 +vn -0.669118 0.726371 0.156896 +vn -0.467086 0.521805 0.713767 +vn -0.048372 0.074313 0.996033 +vn 0.107334 0.122379 0.986633 +vn 0.072085 0.670247 0.738609 +vn -0.107334 0.122379 0.986633 +vn 0.048372 0.074313 0.996033 +vn 0.467086 0.521805 0.713767 +vn 0.669118 0.726371 0.156896 +vn 0.204352 0.961180 0.185247 +vn -0.661824 0.379559 0.646443 +vn -0.862850 0.493942 0.107089 +vn -0.842006 0.529923 0.100711 +vn -0.677358 0.403363 0.615162 +vn -0.127689 0.001282 0.991791 +vn -0.103122 0.022492 0.994385 +vn 0.661824 0.379559 0.646443 +vn 0.103122 0.022492 0.994385 +vn 0.127689 0.001282 0.991791 +vn 0.677358 0.403363 0.615162 +vn 0.842006 0.529923 0.100711 +vn 0.862850 0.493942 0.107089 +vn -0.508835 0.551195 0.661214 +vn -0.607227 0.777795 0.162114 +vn 0.000000 0.975646 0.219306 +vn 0.000000 0.666799 0.745232 +vn 0.000000 -0.060488 0.998138 +vn -0.110080 0.026826 0.993530 +vn 0.508835 0.551195 0.661214 +vn 0.110080 0.026826 0.993530 +vn 0.607227 0.777795 0.162114 +vn 0.361126 -0.297250 0.883847 +vn 0.339518 -0.307047 0.889035 +vn 0.302316 -0.228248 0.925443 +vn 0.322275 -0.232215 0.917692 +vn 0.286660 -0.247475 0.925504 +vn 0.304483 -0.303201 0.902951 +vn -0.361126 -0.297250 0.883847 +vn -0.304483 -0.303201 0.902951 +vn -0.286660 -0.247475 0.925504 +vn -0.322275 -0.232215 0.917692 +vn -0.302316 -0.228248 0.925443 +vn -0.339518 -0.307047 0.889035 +vn 0.213721 -0.326029 0.920865 +vn 0.209662 -0.271767 0.939238 +vn 0.122135 -0.268166 0.955565 +vn 0.124485 -0.349864 0.928465 +vn -0.213721 -0.326029 0.920865 +vn -0.124485 -0.349864 0.928465 +vn -0.122135 -0.268166 0.955565 +vn -0.209662 -0.271767 0.939238 +vn 0.064577 -0.372417 0.925779 +vn 0.108188 -0.213935 0.970824 +vn 0.180120 -0.183996 0.966277 +vn 0.055727 -0.407514 0.911466 +vn -0.064577 -0.372417 0.925779 +vn -0.055727 -0.407514 0.911466 +vn -0.180120 -0.183996 0.966277 +vn -0.108188 -0.213935 0.970824 +vn 0.053041 -0.461562 0.885495 +vn 0.192083 -0.271920 0.942930 +vn 0.152776 -0.334452 0.929929 +vn 0.071841 -0.471908 0.878689 +vn -0.053041 -0.461562 0.885495 +vn -0.071841 -0.471908 0.878689 +vn -0.152776 -0.334452 0.929929 +vn -0.192083 -0.271920 0.942930 +vn 0.160405 -0.412763 0.896573 +vn 0.175787 -0.264229 0.948271 +vn 0.276498 -0.159490 0.947661 +vn 0.259651 -0.305307 0.916166 +vn -0.160405 -0.412763 0.896573 +vn -0.259651 -0.305307 0.916166 +vn -0.276498 -0.159490 0.947661 +vn -0.175787 -0.264229 0.948271 +vn 0.370861 -0.236457 0.898068 +vn 0.378155 -0.146825 0.913999 +vn 0.442640 -0.200476 0.873989 +vn 0.447859 -0.234565 0.862758 +vn -0.370861 -0.236457 0.898068 +vn -0.447859 -0.234565 0.862758 +vn -0.442640 -0.200476 0.873989 +vn -0.378155 -0.146825 0.913999 +vn 0.452254 -0.264138 0.851863 +vn 0.459487 -0.281838 0.842250 +vn 0.438124 -0.367443 0.820338 +vn 0.417951 -0.328410 0.847011 +vn -0.452254 -0.264138 0.851863 +vn -0.417951 -0.328410 0.847011 +vn -0.438124 -0.367443 0.820338 +vn -0.459487 -0.281838 0.842250 +vn 0.377239 -0.383160 0.843104 +vn 0.365307 -0.419843 0.830805 +vn 0.275399 -0.364513 0.889523 +vn 0.348949 -0.318552 0.881314 +vn -0.377239 -0.383160 0.843104 +vn -0.348949 -0.318552 0.881314 +vn -0.275399 -0.364513 0.889523 +vn -0.365307 -0.419843 0.830805 +vn 0.338481 -0.136174 0.931059 +vn 0.204169 -0.239418 0.949187 +vn 0.094852 -0.116398 0.988647 +vn 0.177343 0.033418 0.983551 +vn -0.338481 -0.136174 0.931059 +vn -0.177343 0.033418 0.983551 +vn -0.094852 -0.116398 0.988647 +vn -0.204169 -0.239418 0.949187 +vn -0.055269 0.122837 0.990875 +vn -0.074313 -0.043031 0.996277 +vn -0.147954 -0.087100 0.985137 +vn -0.079257 0.017029 0.996704 +vn 0.000000 0.041017 0.999146 +vn -0.158422 0.075228 0.984497 +vn 0.055269 0.122837 0.990875 +vn 0.158422 0.075228 0.984497 +vn 0.079257 0.017029 0.996704 +vn 0.147954 -0.087100 0.985137 +vn 0.074313 -0.043031 0.996277 +vn 0.259468 -0.291025 0.920835 +vn 0.226875 -0.202857 0.952544 +vn 0.186041 -0.259163 0.947722 +vn 0.129154 -0.162084 0.978271 +vn -0.259468 -0.291025 0.920835 +vn -0.186041 -0.259163 0.947722 +vn -0.226875 -0.202857 0.952544 +vn -0.129154 -0.162084 0.978271 +vn 0.115818 -0.236366 0.964721 +vn 0.020539 -0.147801 0.988769 +vn 0.000000 -0.275155 0.961364 +vn 0.000000 -0.246376 0.969146 +vn 0.040773 -0.215949 0.975524 +vn -0.075320 -0.164678 0.983459 +vn -0.115818 -0.236366 0.964721 +vn -0.040773 -0.215949 0.975524 +vn -0.020539 -0.147801 0.988769 +vn 0.075320 -0.164678 0.983459 +vn -0.014710 -0.146702 0.989044 +vn 0.000000 -0.149754 0.988708 +vn -0.126865 -0.161229 0.978698 +vn 0.014710 -0.146702 0.989044 +vn 0.126865 -0.161229 0.978698 +vn 0.070284 -0.702017 0.708670 +vn 0.134465 -0.664174 0.735343 +vn 0.071474 -0.528581 0.845820 +vn 0.026521 -0.547014 0.836665 +vn 0.000000 -0.548997 0.835810 +vn 0.000000 -0.710440 0.703726 +vn -0.070284 -0.702017 0.708670 +vn -0.026521 -0.547014 0.836665 +vn -0.071474 -0.528581 0.845820 +vn -0.134465 -0.664174 0.735343 +vn 0.217627 -0.571978 0.790826 +vn 0.311380 -0.418317 0.853236 +vn 0.229713 -0.334361 0.913999 +vn 0.144993 -0.458571 0.876736 +vn -0.217627 -0.571978 0.790826 +vn -0.144993 -0.458571 0.876736 +vn -0.229713 -0.334361 0.913999 +vn -0.311380 -0.418317 0.853236 +vn 0.353099 -0.284188 0.891354 +vn 0.362377 -0.194220 0.911557 +vn 0.203925 -0.139592 0.968963 +vn 0.262490 -0.223548 0.938658 +vn -0.353099 -0.284188 0.891354 +vn -0.262490 -0.223548 0.938658 +vn -0.203925 -0.139592 0.968963 +vn -0.362377 -0.194220 0.911557 +vn 0.360149 -0.013428 0.932768 +vn 0.362774 0.017914 0.931700 +vn 0.170934 -0.008209 0.985229 +vn 0.175909 -0.038148 0.983642 +vn 0.187933 -0.050172 0.980895 +vn 0.368816 -0.043062 0.928495 +vn -0.360149 -0.013428 0.932768 +vn -0.368816 -0.043062 0.928495 +vn -0.187933 -0.050172 0.980895 +vn -0.175909 -0.038148 0.983642 +vn -0.170934 -0.008209 0.985229 +vn -0.362774 0.017914 0.931700 +vn 0.371868 -0.108249 0.921934 +vn 0.204077 -0.078494 0.975768 +vn -0.371868 -0.108249 0.921934 +vn -0.204077 -0.078494 0.975768 +vn 0.051637 -0.013306 0.998566 +vn 0.181982 -0.007080 0.983245 +vn 0.368725 -0.294595 0.881588 +vn 0.137120 -0.292978 0.946226 +vn 0.000000 -0.278146 0.960509 +vn 0.000000 -0.011170 0.999908 +vn 0.000000 -0.017365 0.999847 +vn 0.048891 -0.015168 0.998688 +vn -0.051637 -0.013306 0.998566 +vn -0.048891 -0.015168 0.998688 +vn -0.137120 -0.292978 0.946226 +vn -0.368725 -0.294595 0.881588 +vn -0.181982 -0.007080 0.983245 +vn 0.049776 -0.049593 0.997497 +vn 0.053468 -0.049196 0.997345 +vn 0.000000 -0.053133 0.998566 +vn 0.000000 -0.048097 0.998840 +vn -0.049776 -0.049593 0.997497 +vn -0.053468 -0.049196 0.997345 +vn 0.060335 -0.050630 0.996887 +vn 0.000000 -0.048982 0.998779 +vn 0.000000 -0.219092 0.975677 +vn 0.061586 -0.160375 0.985107 +vn -0.060335 -0.050630 0.996887 +vn -0.061586 -0.160375 0.985107 +vn 0.810083 -0.520646 0.269478 +vn 0.659139 -0.328501 0.676443 +vn 0.806879 -0.153996 0.570238 +vn 0.989288 -0.119633 0.083438 +vn 0.965361 -0.144719 0.217017 +vn 0.759514 -0.577013 0.300241 +vn 0.506821 -0.753075 0.419477 +vn 0.544420 -0.686453 0.482009 +vn -0.810083 -0.520646 0.269478 +vn -0.544420 -0.686453 0.482009 +vn -0.506821 -0.753075 0.419477 +vn -0.759514 -0.577013 0.300241 +vn -0.965361 -0.144719 0.217017 +vn -0.989288 -0.119633 0.083438 +vn -0.806879 -0.153996 0.570238 +vn -0.659139 -0.328501 0.676443 +vn 0.952116 0.305338 -0.015046 +vn 0.711783 0.053468 0.700308 +vn 0.188299 0.327921 0.925718 +vn 0.689993 0.722953 -0.034791 +vn 0.677145 0.730949 0.084475 +vn 0.940306 0.302744 0.155339 +vn -0.952116 0.305338 -0.015046 +vn -0.940306 0.302744 0.155339 +vn -0.677145 0.730949 0.084475 +vn -0.689993 0.722953 -0.034791 +vn -0.188299 0.327921 0.925718 +vn -0.711783 0.053468 0.700308 +vn 0.151280 0.975982 0.156652 +vn -0.139348 0.337718 0.930845 +vn 0.000000 0.307138 0.951628 +vn -0.381909 0.794244 0.472518 +vn -0.362163 0.904599 0.224769 +vn 0.169103 0.981475 0.089755 +vn -0.151280 0.975982 0.156652 +vn -0.169103 0.981475 0.089755 +vn 0.362163 0.904599 0.224769 +vn 0.381909 0.794244 0.472518 +vn 0.139348 0.337718 0.930845 +vn -0.562883 0.662496 0.494156 +vn 0.000000 0.564135 0.825678 +vn 0.000000 0.759239 0.650777 +vn 0.000000 0.951170 0.308573 +vn 0.000000 0.960356 0.278726 +vn -0.630390 0.724021 0.279916 +vn 0.562883 0.662496 0.494156 +vn 0.630390 0.724021 0.279916 +vn 0.301340 -0.732719 0.610126 +vn 0.000000 -0.752556 0.658498 +vn 0.319376 -0.804498 0.500748 +vn 0.000000 -0.850154 0.526505 +vn -0.301340 -0.732719 0.610126 +vn -0.319376 -0.804498 0.500748 +vn 0.230171 -0.645100 0.728568 +vn 0.000000 -0.657582 0.753349 +vn 0.346294 -0.669454 0.657155 +vn 0.207953 -0.566973 0.797021 +vn 0.134922 -0.503952 0.853114 +vn 0.000000 -0.476363 0.879208 +vn -0.230171 -0.645100 0.728568 +vn -0.134922 -0.503952 0.853114 +vn -0.207953 -0.566973 0.797021 +vn -0.346294 -0.669454 0.657155 +vn -0.430891 0.679769 0.593463 +vn 0.000000 0.728080 0.685476 +vn 0.000000 0.138005 0.990417 +vn -0.149205 0.407788 0.900784 +vn -0.142949 0.526994 0.837733 +vn -0.276009 0.759453 0.589068 +vn 0.430891 0.679769 0.593463 +vn 0.276009 0.759453 0.589068 +vn 0.142949 0.526994 0.837733 +vn 0.149205 0.407788 0.900784 +vn 0.147801 0.804193 0.575640 +vn 0.089755 0.494522 0.864498 +vn 0.316141 0.417035 0.852107 +vn 0.547441 0.603656 0.579516 +vn -0.147801 0.804193 0.575640 +vn -0.547441 0.603656 0.579516 +vn -0.316141 0.417035 0.852107 +vn -0.089755 0.494522 0.864498 +vn 0.738151 0.266640 0.619678 +vn 0.341075 0.213202 0.915525 +vn 0.308206 -0.132298 0.942045 +vn 0.732963 -0.157720 0.661702 +vn -0.738151 0.266640 0.619678 +vn -0.732963 -0.157720 0.661702 +vn -0.308206 -0.132298 0.942045 +vn -0.341075 0.213202 0.915525 +vn 0.541887 -0.547990 0.637165 +vn 0.226051 -0.456496 0.860500 +vn -0.541887 -0.547990 0.637165 +vn -0.226051 -0.456496 0.860500 +vn 0.062929 0.234931 0.969939 +vn 0.043458 -0.059755 0.997253 +vn -0.062929 0.234931 0.969939 +vn -0.043458 -0.059755 0.997253 +vn 0.057711 -0.344737 0.936918 +vn 0.000000 -0.300943 0.953612 +vn -0.057711 -0.344737 0.936918 +vn -0.217780 -0.045137 0.974944 +vn 0.000000 0.003052 0.999969 +vn -0.110630 -0.207984 0.971831 +vn 0.217780 -0.045137 0.974944 +vn 0.110630 -0.207984 0.971831 +vn 0.296396 -0.239326 0.924558 +vn 0.646657 -0.139744 0.749840 +vn 0.829463 0.004578 0.558489 +vn 0.728111 -0.196020 0.656789 +vn -0.296396 -0.239326 0.924558 +vn -0.728111 -0.196020 0.656789 +vn -0.829463 0.004578 0.558489 +vn -0.646657 -0.139744 0.749840 +vn 0.593005 -0.108005 0.797876 +vn 0.470168 -0.018891 0.882351 +vn 0.713187 0.139805 0.686880 +vn 0.784692 0.079257 0.614765 +vn -0.593005 -0.108005 0.797876 +vn -0.784692 0.079257 0.614765 +vn -0.713187 0.139805 0.686880 +vn -0.470168 -0.018891 0.882351 +vn 0.393689 0.037416 0.918455 +vn 0.653523 0.137974 0.744194 +vn -0.393689 0.037416 0.918455 +vn -0.653523 0.137974 0.744194 +vn 0.836787 0.247383 0.488388 +vn 0.940306 0.303110 0.154668 +vn 0.931883 0.327677 0.155492 +vn 0.857723 0.269082 0.438032 +vn -0.836787 0.247383 0.488388 +vn -0.857723 0.269082 0.438032 +vn -0.931883 0.327677 0.155492 +vn -0.940306 0.303110 0.154668 +vn 0.889706 0.228065 0.395398 +vn 0.942228 0.295877 0.156926 +vn 0.945036 0.280862 0.167302 +vn 0.915891 0.182318 0.357555 +vn -0.889706 0.228065 0.395398 +vn -0.915891 0.182318 0.357555 +vn -0.945036 0.280862 0.167302 +vn -0.942228 0.295877 0.156926 +vn 0.903287 -0.131199 0.408429 +vn 0.968047 -0.106754 0.226875 +vn -0.903287 -0.131199 0.408429 +vn -0.968047 -0.106754 0.226875 +vn 0.086398 -0.624805 0.775964 +vn -0.029145 -0.399731 0.916135 +vn 0.000000 -0.701529 0.712607 +vn 0.000000 -0.954924 0.296762 +vn 0.114475 -0.940580 0.319651 +vn -0.385876 -0.804651 0.451216 +vn -0.086398 -0.624805 0.775964 +vn -0.114475 -0.940580 0.319651 +vn 0.029145 -0.399731 0.916135 +vn 0.385876 -0.804651 0.451216 +vn -0.235115 -0.263222 0.935606 +vn -0.268319 -0.152867 0.951109 +vn -0.882229 -0.229377 0.411115 +vn -0.871975 0.194006 0.449385 +vn 0.235115 -0.263222 0.935606 +vn 0.882229 -0.229377 0.411115 +vn 0.268319 -0.152867 0.951109 +vn 0.871975 0.194006 0.449385 +vn -0.278787 -0.087436 0.956359 +vn -0.235023 0.025391 0.971648 +vn -0.710685 0.485427 0.509140 +vn -0.471603 0.701071 0.534806 +vn 0.278787 -0.087436 0.956359 +vn 0.710685 0.485427 0.509140 +vn 0.235023 0.025391 0.971648 +vn 0.471603 0.701071 0.534806 +vn -0.117710 0.118748 0.985900 +vn 0.000000 0.157262 0.987548 +vn -0.203192 0.812983 0.545640 +vn 0.000000 0.837458 0.546464 +vn 0.117710 0.118748 0.985900 +vn 0.203192 0.812983 0.545640 +vn -0.190344 0.835902 0.514756 +vn 0.000000 0.848506 0.529160 +vn -0.441786 0.782098 0.439436 +vn -0.283273 0.403424 0.870022 +vn -0.117740 0.377331 0.918546 +vn 0.000000 0.374004 0.927396 +vn 0.190344 0.835902 0.514756 +vn 0.117740 0.377331 0.918546 +vn 0.283273 0.403424 0.870022 +vn 0.441786 0.782098 0.439436 +vn -0.717185 0.632710 0.292062 +vn -0.926328 0.333995 0.174230 +vn -0.899045 0.302957 0.316019 +vn -0.550249 0.375317 0.745842 +vn 0.717185 0.632710 0.292062 +vn 0.550249 0.375317 0.745842 +vn 0.899045 0.302957 0.316019 +vn 0.926328 0.333995 0.174230 +vn -0.953703 -0.224860 0.199591 +vn -0.436445 -0.853481 0.284646 +vn -0.263375 -0.733696 0.626301 +vn -0.748772 -0.273293 0.603809 +vn 0.953703 -0.224860 0.199591 +vn 0.748772 -0.273293 0.603809 +vn 0.263375 -0.733696 0.626301 +vn 0.436445 -0.853481 0.284646 +vn 0.112491 -0.943907 0.310434 +vn 0.000000 -0.944823 0.327555 +vn 0.000000 -0.694723 0.719230 +vn 0.088046 -0.720023 0.688314 +vn -0.112491 -0.943907 0.310434 +vn -0.088046 -0.720023 0.688314 +vn 0.018799 -0.282723 0.958983 +vn 0.000000 -0.267281 0.963591 +vn 0.001862 -0.297555 0.954680 +vn -0.018799 -0.282723 0.958983 +vn -0.001862 -0.297555 0.954680 +vn -0.465896 -0.095767 0.879604 +vn 0.465896 -0.095767 0.879604 +vn -0.261605 -0.178777 0.948454 +vn -0.217139 -0.122898 0.968352 +vn -0.298502 -0.207038 0.931669 +vn -0.013153 -0.028687 0.999481 +vn 0.092990 -0.056795 0.994018 +vn 0.138279 -0.059999 0.988556 +vn 0.261605 -0.178777 0.948454 +vn -0.092990 -0.056795 0.994018 +vn 0.013153 -0.028687 0.999481 +vn 0.298502 -0.207038 0.931669 +vn 0.217139 -0.122898 0.968352 +vn -0.138279 -0.059999 0.988556 +vn -0.148350 -0.068087 0.986572 +vn -0.067995 -0.045351 0.996643 +vn 0.155950 -0.054353 0.986236 +vn 0.162053 -0.069796 0.984283 +vn 0.148350 -0.068087 0.986572 +vn -0.155950 -0.054353 0.986236 +vn 0.067995 -0.045351 0.996643 +vn -0.162053 -0.069796 0.984283 +vn 0.005524 -0.036653 0.999298 +vn 0.069430 -0.011597 0.997497 +vn 0.153691 -0.082430 0.984649 +vn 0.131748 -0.059999 0.989441 +vn -0.005524 -0.036653 0.999298 +vn -0.153691 -0.082430 0.984649 +vn -0.069430 -0.011597 0.997497 +vn -0.131748 -0.059999 0.989441 +vn -0.253121 -0.301431 0.919248 +vn -0.108188 -0.461409 0.880520 +vn 0.010407 -0.254494 0.967009 +vn -0.081484 -0.125309 0.988739 +vn 0.253121 -0.301431 0.919248 +vn 0.081484 -0.125309 0.988739 +vn -0.010407 -0.254494 0.967009 +vn 0.108188 -0.461409 0.880520 +vn 0.037568 -0.534654 0.844203 +vn 0.186346 -0.554064 0.811335 +vn 0.209449 -0.299264 0.930876 +vn 0.117405 -0.307413 0.944273 +vn -0.037568 -0.534654 0.844203 +vn -0.117405 -0.307413 0.944273 +vn -0.209449 -0.299264 0.930876 +vn -0.186346 -0.554064 0.811335 +vn 0.360393 -0.526597 0.769890 +vn 0.479415 -0.437269 0.760857 +vn 0.365703 -0.161596 0.916562 +vn 0.311472 -0.246803 0.917600 +vn -0.360393 -0.526597 0.769890 +vn -0.311472 -0.246803 0.917600 +vn -0.365703 -0.161596 0.916562 +vn -0.479415 -0.437269 0.760857 +vn 0.509262 -0.320627 0.798639 +vn 0.491165 -0.203009 0.847072 +vn 0.310862 -0.056795 0.948729 +vn 0.357707 -0.085299 0.929899 +vn -0.509262 -0.320627 0.798639 +vn -0.357707 -0.085299 0.929899 +vn -0.310862 -0.056795 0.948729 +vn -0.491165 -0.203009 0.847072 +vn 0.460250 -0.109989 0.880917 +vn 0.425031 -0.052095 0.903653 +vn 0.242164 -0.060823 0.968322 +vn 0.263680 -0.061098 0.962645 +vn -0.460250 -0.109989 0.880917 +vn -0.263680 -0.061098 0.962645 +vn -0.242164 -0.060823 0.968322 +vn -0.425031 -0.052095 0.903653 +vn 0.387738 -0.025880 0.921384 +vn 0.401471 0.034669 0.915189 +vn 0.346110 -0.079379 0.934812 +vn 0.283303 -0.067721 0.956603 +vn -0.387738 -0.025880 0.921384 +vn -0.283303 -0.067721 0.956603 +vn -0.346110 -0.079379 0.934812 +vn -0.401471 0.034669 0.915189 +vn 0.428449 0.203955 0.880215 +vn 0.363475 0.340465 0.867122 +vn 0.298685 0.113559 0.947539 +vn 0.393689 -0.024262 0.918912 +vn -0.428449 0.203955 0.880215 +vn -0.393689 -0.024262 0.918912 +vn -0.298685 0.113559 0.947539 +vn -0.363475 0.340465 0.867122 +vn 0.219398 0.286538 0.932585 +vn 0.153050 0.142674 0.977844 +vn 0.107395 0.172155 0.979186 +vn 0.128117 0.198492 0.971679 +vn -0.219398 0.286538 0.932585 +vn -0.128117 0.198492 0.971679 +vn -0.107395 0.172155 0.979186 +vn -0.153050 0.142674 0.977844 +vn 0.170660 0.080355 0.982025 +vn 0.152257 0.064943 0.986175 +vn 0.137211 0.094607 0.985992 +vn 0.160375 0.141301 0.976867 +vn -0.170660 0.080355 0.982025 +vn -0.160375 0.141301 0.976867 +vn -0.137211 0.094607 0.985992 +vn -0.152257 0.064943 0.986175 +vn 0.113102 0.030427 0.993103 +vn 0.113804 0.006561 0.993469 +vn -0.113102 0.030427 0.993103 +vn -0.113804 0.006561 0.993469 +vn 0.270608 -0.284249 0.919736 +vn 0.226051 -0.191931 0.954985 +vn 0.397351 -0.314310 0.862117 +vn 0.488113 -0.426557 0.761406 +vn 0.330943 -0.419019 0.845485 +vn 0.260292 -0.334666 0.905667 +vn -0.270608 -0.284249 0.919736 +vn -0.330943 -0.419019 0.845485 +vn -0.488113 -0.426557 0.761406 +vn -0.397351 -0.314310 0.862117 +vn -0.226051 -0.191931 0.954985 +vn -0.260292 -0.334666 0.905667 +vn 0.195196 -0.165593 0.966674 +vn 0.042787 -0.259590 0.964751 +vn 0.211554 -0.315836 0.924894 +vn 0.032899 -0.464797 0.884762 +vn -0.195196 -0.165593 0.966674 +vn -0.211554 -0.315836 0.924894 +vn -0.042787 -0.259590 0.964751 +vn -0.032899 -0.464797 0.884762 +vn -0.048921 -0.412000 0.909848 +vn 0.027650 -0.570574 0.820734 +vn -0.111759 -0.677816 0.726646 +vn -0.107700 -0.811182 0.574755 +vn 0.048921 -0.412000 0.909848 +vn 0.111759 -0.677816 0.726646 +vn -0.027650 -0.570574 0.820734 +vn 0.107700 -0.811182 0.574755 +vn 0.084536 -0.644581 0.759819 +vn 0.008942 -0.549821 0.835200 +vn -0.073183 -0.811975 0.579058 +vn -0.133641 -0.676046 0.724601 +vn -0.084536 -0.644581 0.759819 +vn 0.073183 -0.811975 0.579058 +vn -0.008942 -0.549821 0.835200 +vn 0.133641 -0.676046 0.724601 +vn -0.126774 -0.301431 0.945006 +vn -0.197241 -0.108707 0.974273 +vn -0.303690 -0.372570 0.876888 +vn -0.386670 -0.114383 0.915067 +vn 0.126774 -0.301431 0.945006 +vn 0.303690 -0.372570 0.876888 +vn 0.197241 -0.108707 0.974273 +vn 0.386670 -0.114383 0.915067 +vn -0.153111 0.025513 0.987854 +vn -0.060823 0.190924 0.979705 +vn -0.337535 0.070559 0.938627 +vn -0.226417 0.283303 0.931883 +vn 0.153111 0.025513 0.987854 +vn 0.337535 0.070559 0.938627 +vn 0.060823 0.190924 0.979705 +vn 0.226417 0.283303 0.931883 +vn 0.005951 0.304239 0.952574 +vn 0.045167 0.351115 0.935209 +vn -0.160772 0.446089 0.880398 +vn -0.125309 0.555132 0.822230 +vn -0.005951 0.304239 0.952574 +vn 0.160772 0.446089 0.880398 +vn -0.045167 0.351115 0.935209 +vn 0.125309 0.555132 0.822230 +vn 0.127873 0.354625 0.926206 +vn 0.236335 0.345408 0.908170 +vn -0.000763 0.616901 0.787011 +vn 0.192267 0.617420 0.762749 +vn -0.127873 0.354625 0.926206 +vn 0.000763 0.616901 0.787011 +vn -0.236335 0.345408 0.908170 +vn -0.192267 0.617420 0.762749 +vn 0.308939 0.358501 0.880917 +vn 0.335368 0.382122 0.861080 +vn 0.326395 0.601337 0.729270 +vn 0.402081 0.591449 0.698904 +vn -0.308939 0.358501 0.880917 +vn -0.326395 0.601337 0.729270 +vn -0.335368 0.382122 0.861080 +vn -0.402081 0.591449 0.698904 +vn 0.389050 0.384259 0.837214 +vn 0.534898 0.279977 0.797143 +vn 0.515946 0.514359 0.684957 +vn 0.676565 0.330302 0.658132 +vn -0.389050 0.384259 0.837214 +vn -0.515946 0.514359 0.684957 +vn -0.534898 0.279977 0.797143 +vn -0.676565 0.330302 0.658132 +vn 0.527604 -0.273049 0.804376 +vn 0.622272 -0.186132 0.760308 +vn 0.765069 -0.241066 0.597064 +vn 0.648152 -0.360881 0.670522 +vn -0.527604 -0.273049 0.804376 +vn -0.648152 -0.360881 0.670522 +vn -0.765069 -0.241066 0.597064 +vn -0.622272 -0.186132 0.760308 +vn 0.668783 -0.082888 0.738792 +vn 0.676351 0.002106 0.736564 +vn 0.806848 0.011963 0.590625 +vn 0.811151 -0.097079 0.576708 +vn -0.668783 -0.082888 0.738792 +vn -0.811151 -0.097079 0.576708 +vn -0.806848 0.011963 0.590625 +vn -0.676351 0.002106 0.736564 +vn 0.644093 0.114261 0.756340 +vn 0.774621 0.137913 0.617145 +vn -0.644093 0.114261 0.756340 +vn -0.774621 0.137913 0.617145 +vn -0.505081 0.858516 -0.088290 +vn 0.000000 0.999878 0.013855 +vn -0.746269 0.605304 -0.276864 +vn -0.497360 0.863094 -0.087497 +vn -0.351115 0.871151 0.343181 +vn 0.000000 0.878750 0.477218 +vn 0.505081 0.858516 -0.088290 +vn 0.351115 0.871151 0.343181 +vn 0.497360 0.863094 -0.087497 +vn 0.746269 0.605304 -0.276864 +vn -0.791742 0.472396 -0.387219 +vn -0.644093 0.648366 -0.405835 +vn -0.500351 0.452437 -0.738151 +vn -0.511338 0.377941 -0.771783 +vn 0.791742 0.472396 -0.387219 +vn 0.511338 0.377941 -0.771783 +vn 0.500351 0.452437 -0.738151 +vn 0.644093 0.648366 -0.405835 +vn -0.244026 0.879971 -0.407483 +vn 0.232704 0.890439 -0.391064 +vn 0.082522 0.628529 -0.773370 +vn -0.226386 0.551347 -0.802942 +vn 0.244026 0.879971 -0.407483 +vn 0.226386 0.551347 -0.802942 +vn -0.082522 0.628529 -0.773370 +vn -0.232704 0.890439 -0.391064 +vn 0.467757 0.801263 -0.372997 +vn 0.440931 0.839595 -0.317179 +vn 0.155065 0.854091 -0.496445 +vn 0.120731 0.563433 -0.817255 +vn -0.467757 0.801263 -0.372997 +vn -0.120731 0.563433 -0.817255 +vn -0.155065 0.854091 -0.496445 +vn -0.440931 0.839595 -0.317179 +vn 0.391461 0.891324 -0.228614 +vn 0.375439 0.909665 -0.177435 +vn 0.361827 0.909024 -0.206641 +vn 0.303110 0.910794 -0.280221 +vn -0.391461 0.891324 -0.228614 +vn -0.303110 0.910794 -0.280221 +vn -0.361827 0.909024 -0.206641 +vn -0.375439 0.909665 -0.177435 +vn 0.528886 0.825526 -0.196875 +vn 0.853084 0.460738 -0.244728 +vn 0.807184 0.518357 -0.282327 +vn 0.501938 0.828883 -0.246895 +vn -0.528886 0.825526 -0.196875 +vn -0.501938 0.828883 -0.246895 +vn -0.807184 0.518357 -0.282327 +vn -0.853084 0.460738 -0.244728 +vn 0.971374 0.002319 -0.237403 +vn 0.898373 -0.398968 -0.183538 +vn 0.937559 -0.344340 -0.048463 +vn 0.980651 0.075594 -0.180517 +vn -0.971374 0.002319 -0.237403 +vn -0.980651 0.075594 -0.180517 +vn -0.937559 -0.344340 -0.048463 +vn -0.898373 -0.398968 -0.183538 +vn 0.719077 -0.682333 -0.131443 +vn 0.578265 -0.808924 -0.105930 +vn 0.621387 -0.782037 0.047487 +vn 0.778100 -0.627796 0.020264 +vn -0.719077 -0.682333 -0.131443 +vn -0.778100 -0.627796 0.020264 +vn -0.621387 -0.782037 0.047487 +vn -0.578265 -0.808924 -0.105930 +vn 0.459853 -0.882473 -0.098819 +vn 0.342631 -0.934935 -0.091922 +vn 0.422193 -0.904386 0.061525 +vn 0.496261 -0.866848 0.047670 +vn -0.459853 -0.882473 -0.098819 +vn -0.496261 -0.866848 0.047670 +vn -0.422193 -0.904386 0.061525 +vn -0.342631 -0.934935 -0.091922 +vn 0.238777 -0.534837 -0.810480 +vn 0.209296 -0.259468 -0.942778 +vn 0.000000 -0.250649 -0.968047 +vn 0.000000 -0.511399 -0.859310 +vn 0.000000 -0.786798 -0.617176 +vn 0.285134 -0.784204 -0.551073 +vn 0.645039 -0.633320 -0.427473 +vn 0.504624 -0.480880 -0.716971 +vn 0.340556 -0.236152 -0.910062 +vn -0.238777 -0.534837 -0.810480 +vn -0.504624 -0.480880 -0.716971 +vn -0.645039 -0.633320 -0.427473 +vn -0.285134 -0.784204 -0.551073 +vn -0.209296 -0.259468 -0.942778 +vn -0.340556 -0.236152 -0.910062 +vn 0.175726 -0.141453 -0.974212 +vn 0.130833 -0.248421 -0.959746 +vn 0.000000 -0.286630 -0.958007 +vn 0.000000 -0.159459 -0.987182 +vn 0.220435 -0.098758 -0.970367 +vn 0.138737 -0.172582 -0.975158 +vn -0.175726 -0.141453 -0.974212 +vn -0.220435 -0.098758 -0.970367 +vn -0.130833 -0.248421 -0.959746 +vn -0.138737 -0.172582 -0.975158 +vn 0.077181 -0.463210 -0.882839 +vn 0.057894 -0.754051 -0.654225 +vn 0.000000 -0.782281 -0.622883 +vn 0.000000 -0.504929 -0.863155 +vn 0.062502 -0.372387 -0.925962 +vn 0.046327 -0.694968 -0.717521 +vn -0.077181 -0.463210 -0.882839 +vn -0.062502 -0.372387 -0.925962 +vn -0.057894 -0.754051 -0.654225 +vn -0.046327 -0.694968 -0.717521 +vn 0.078799 -0.966521 -0.244118 +vn 0.101199 -0.949919 -0.295541 +vn 0.000000 -0.976318 -0.216254 +vn -0.078799 -0.966521 -0.244118 +vn -0.101199 -0.949919 -0.295541 +vn 0.211432 -0.911527 -0.352702 +vn 0.604419 -0.677328 -0.419385 +vn 0.134678 -0.614338 -0.777429 +vn 0.408521 -0.468001 -0.783593 +vn -0.211432 -0.911527 -0.352702 +vn -0.134678 -0.614338 -0.777429 +vn -0.604419 -0.677328 -0.419385 +vn -0.408521 -0.468001 -0.783593 +vn 0.885556 -0.204413 -0.417066 +vn 0.930631 0.077364 -0.357646 +vn 0.555773 -0.135075 -0.820276 +vn 0.611133 0.051668 -0.789819 +vn -0.885556 -0.204413 -0.417066 +vn -0.555773 -0.135075 -0.820276 +vn -0.930631 0.077364 -0.357646 +vn -0.611133 0.051668 -0.789819 +vn 0.929411 0.136906 -0.342662 +vn 0.932859 0.142796 -0.330668 +vn 0.668264 0.097812 -0.737449 +vn 0.741050 0.065981 -0.668142 +vn -0.929411 0.136906 -0.342662 +vn -0.668264 0.097812 -0.737449 +vn -0.932859 0.142796 -0.330668 +vn -0.741050 0.065981 -0.668142 +vn 0.334391 -0.015107 -0.942289 +vn 0.224799 -0.069185 -0.971923 +vn 0.511826 -0.112339 -0.851680 +vn -0.334391 -0.015107 -0.942289 +vn -0.511826 -0.112339 -0.851680 +vn -0.224799 -0.069185 -0.971923 +vn 0.138066 -0.257668 -0.956298 +vn -0.138066 -0.257668 -0.956298 +vn 0.734458 -0.242225 -0.633931 +vn 0.886502 -0.270272 -0.375500 +vn 0.928983 0.054781 -0.365978 +vn 0.844508 0.023957 -0.534959 +vn -0.734458 -0.242225 -0.633931 +vn -0.844508 0.023957 -0.534959 +vn -0.928983 0.054781 -0.365978 +vn -0.886502 -0.270272 -0.375500 +vn 0.942167 0.143651 -0.302713 +vn 0.951659 0.199347 -0.233558 +vn -0.942167 0.143651 -0.302713 +vn -0.951659 0.199347 -0.233558 +vn 0.983551 0.149571 0.101169 +vn 0.982940 0.180456 -0.034913 +vn 0.941069 -0.327708 0.083407 +vn 0.893460 -0.355846 0.273995 +vn 0.810053 -0.288949 0.510178 +vn 0.957060 0.182775 0.224891 +vn -0.983551 0.149571 0.101169 +vn -0.957060 0.182775 0.224891 +vn -0.810053 -0.288949 0.510178 +vn -0.893460 -0.355846 0.273995 +vn -0.941069 -0.327708 0.083407 +vn -0.982940 0.180456 -0.034913 +vn 0.960540 0.237526 -0.144658 +vn 0.982849 -0.017487 -0.183416 +vn -0.960540 0.237526 -0.144658 +vn -0.982849 -0.017487 -0.183416 +vn 0.963408 -0.150548 0.221656 +vn 0.612262 -0.787164 0.074007 +vn 0.769280 -0.447340 0.456099 +vn 0.488052 -0.863704 0.125614 +vn -0.963408 -0.150548 0.221656 +vn -0.769280 -0.447340 0.456099 +vn -0.612262 -0.787164 0.074007 +vn -0.488052 -0.863704 0.125614 +vn 0.306284 -0.949522 -0.067415 +vn 0.385022 -0.912259 0.139561 +vn -0.306284 -0.949522 -0.067415 +vn -0.385022 -0.912259 0.139561 +vn 0.286752 -0.493240 -0.821253 +vn 0.000000 -0.499283 -0.866421 +vn 0.000000 -0.258156 -0.966094 +vn 0.288797 -0.271310 -0.918119 +vn 0.412061 -0.299722 -0.860439 +vn 0.418378 -0.496597 -0.760460 +vn 0.452223 -0.685965 -0.569994 +vn 0.276925 -0.705466 -0.652364 +vn 0.000000 -0.719779 -0.694174 +vn -0.286752 -0.493240 -0.821253 +vn -0.276925 -0.705466 -0.652364 +vn -0.452223 -0.685965 -0.569994 +vn -0.418378 -0.496597 -0.760460 +vn -0.412061 -0.299722 -0.860439 +vn -0.288797 -0.271310 -0.918119 +vn 0.268380 -0.842799 -0.466475 +vn 0.000000 -0.864620 -0.502396 +vn 0.476150 -0.788720 -0.388745 +vn 0.482253 -0.849330 -0.214545 +vn 0.260842 -0.922483 -0.284463 +vn 0.000000 -0.949736 -0.312998 +vn -0.268380 -0.842799 -0.466475 +vn -0.260842 -0.922483 -0.284463 +vn -0.482253 -0.849330 -0.214545 +vn -0.476150 -0.788720 -0.388745 +vn 0.272622 -0.948973 -0.158330 +vn 0.000000 -0.982391 -0.186682 +vn 0.513932 -0.854030 -0.080386 +vn 0.599872 -0.800073 -0.004547 +vn 0.298746 -0.944731 -0.134770 +vn 0.000000 -0.986053 -0.166265 +vn -0.272622 -0.948973 -0.158330 +vn -0.298746 -0.944731 -0.134770 +vn -0.599872 -0.800073 -0.004547 +vn -0.513932 -0.854030 -0.080386 +vn 0.314982 -0.910886 -0.266549 +vn 0.000000 -0.948271 -0.317423 +vn 0.655751 -0.741020 -0.144444 +vn -0.314982 -0.910886 -0.266549 +vn -0.655751 -0.741020 -0.144444 +vn 0.916898 -0.382458 -0.114078 +vn 0.810053 -0.578295 0.096652 +vn -0.916898 -0.382458 -0.114078 +vn -0.810053 -0.578295 0.096652 +vn 0.837550 -0.514420 0.183905 +vn 0.962828 -0.236457 0.130467 +vn 0.656911 -0.724540 0.208563 +vn 0.692953 -0.705496 0.148350 +vn 0.897031 -0.422987 0.127995 +vn 0.978484 -0.154546 0.136479 +vn -0.837550 -0.514420 0.183905 +vn -0.897031 -0.422987 0.127995 +vn -0.692953 -0.705496 0.148350 +vn -0.656911 -0.724540 0.208563 +vn -0.962828 -0.236457 0.130467 +vn -0.978484 -0.154546 0.136479 +vn 0.288552 -0.043245 -0.956450 +vn 0.000000 -0.011048 -0.999908 +vn 0.000000 0.319987 -0.947417 +vn 0.295999 0.283822 -0.912015 +vn 0.434156 0.214789 -0.874844 +vn 0.420698 -0.107517 -0.900784 +vn -0.288552 -0.043245 -0.956450 +vn -0.420698 -0.107517 -0.900784 +vn -0.434156 0.214789 -0.874844 +vn -0.295999 0.283822 -0.912015 +vn 0.147130 0.950682 0.272958 +vn 0.000000 0.963225 0.268624 +vn 0.000000 0.824610 0.565661 +vn 0.177679 0.804682 0.566454 +vn 0.422620 0.734001 0.531571 +vn 0.387707 0.884182 0.260537 +vn 0.356822 0.933988 0.016968 +vn 0.133305 0.990936 0.015534 +vn 0.000000 0.999939 0.010834 +vn -0.147130 0.950682 0.272958 +vn -0.133305 0.990936 0.015534 +vn -0.356822 0.933988 0.016968 +vn -0.387707 0.884182 0.260537 +vn -0.422620 0.734001 0.531571 +vn -0.177679 0.804682 0.566454 +vn 0.151311 0.959624 -0.237068 +vn 0.000000 0.971221 -0.238044 +vn 0.344554 0.908902 -0.234840 +vn 0.359935 0.767052 -0.531053 +vn 0.211371 0.823267 -0.526780 +vn 0.000000 0.847011 -0.531510 +vn -0.151311 0.959624 -0.237068 +vn -0.211371 0.823267 -0.526780 +vn -0.359935 0.767052 -0.531053 +vn -0.344554 0.908902 -0.234840 +vn 0.273568 0.593371 -0.756981 +vn 0.000000 0.628010 -0.778191 +vn 0.404309 0.527024 -0.747459 +vn -0.273568 0.593371 -0.756981 +vn -0.404309 0.527024 -0.747459 +vn 0.551958 0.832759 -0.042329 +vn 0.435133 0.900021 0.024720 +vn 0.830073 0.553514 -0.067568 +vn 0.827845 0.512711 0.227424 +vn 0.570269 0.749840 0.335337 +vn 0.518967 0.752251 0.405896 +vn -0.551958 0.832759 -0.042329 +vn -0.570269 0.749840 0.335337 +vn -0.827845 0.512711 0.227424 +vn -0.830073 0.553514 -0.067568 +vn -0.435133 0.900021 0.024720 +vn -0.518967 0.752251 0.405896 +vn 0.552629 0.637471 0.536821 +vn 0.569964 0.611957 0.548265 +vn 0.806818 0.427686 0.407514 +vn 0.836085 0.447737 0.316965 +vn 0.629475 0.658742 0.412000 +vn 0.641011 0.653615 0.402264 +vn -0.552629 0.637471 0.536821 +vn -0.629475 0.658742 0.412000 +vn -0.836085 0.447737 0.316965 +vn -0.806818 0.427686 0.407514 +vn -0.569964 0.611957 0.548265 +vn -0.641011 0.653615 0.402264 +vn 0.708090 0.686544 0.164922 +vn 0.670644 0.723197 0.164922 +vn 0.879086 0.464949 0.104831 +vn 0.901608 0.429914 -0.047243 +vn 0.742759 0.668722 -0.032960 +vn 0.671621 0.740074 -0.034059 +vn -0.708090 0.686544 0.164922 +vn -0.742759 0.668722 -0.032960 +vn -0.901608 0.429914 -0.047243 +vn -0.879086 0.464949 0.104831 +vn -0.670644 0.723197 0.164922 +vn -0.671621 0.740074 -0.034059 +vn 0.756340 0.605823 -0.246803 +vn 0.650349 0.706229 -0.279641 +vn 0.909421 0.365398 -0.198462 +vn 0.871395 0.300211 -0.387921 +vn 0.737114 0.439436 -0.513321 +vn 0.599506 0.554643 -0.576983 +vn -0.756340 0.605823 -0.246803 +vn -0.737114 0.439436 -0.513321 +vn -0.871395 0.300211 -0.387921 +vn -0.909421 0.365398 -0.198462 +vn -0.650349 0.706229 -0.279641 +vn -0.599506 0.554643 -0.576983 +vn 0.700430 0.207892 -0.682730 +vn 0.863552 0.163060 -0.477096 +vn 0.686392 0.052278 -0.725333 +vn 0.645894 -0.041200 -0.762261 +vn 0.581469 0.013855 -0.813440 +vn 0.581927 0.305002 -0.753838 +vn -0.700430 0.207892 -0.682730 +vn -0.581927 0.305002 -0.753838 +vn -0.581469 0.013855 -0.813440 +vn -0.645894 -0.041200 -0.762261 +vn -0.686392 0.052278 -0.725333 +vn -0.863552 0.163060 -0.477096 +vn 0.487533 0.429731 -0.760002 +vn 0.514939 0.118656 -0.848933 +vn 0.494400 0.667928 -0.556230 +vn -0.487533 0.429731 -0.760002 +vn -0.494400 0.667928 -0.556230 +vn -0.514939 0.118656 -0.848933 +vn 0.546007 0.797845 -0.255531 +vn 0.587054 0.809503 -0.007202 +vn -0.546007 0.797845 -0.255531 +vn -0.587054 0.809503 -0.007202 +vn 0.617512 0.759880 0.203070 +vn 0.636219 0.635090 0.438002 +vn -0.617512 0.759880 0.203070 +vn -0.636219 0.635090 0.438002 +vn 0.615406 0.552629 0.561998 +vn 0.433485 0.604114 0.668630 +vn 0.370983 0.745781 0.553270 +vn 0.538408 0.729637 0.421552 +vn -0.615406 0.552629 0.561998 +vn -0.538408 0.729637 0.421552 +vn -0.370983 0.745781 0.553270 +vn -0.433485 0.604114 0.668630 +vn 0.376568 0.926267 0.014100 +vn 0.182409 0.981872 0.051424 +vn -0.376568 0.926267 0.014100 +vn -0.182409 0.981872 0.051424 +vn 0.209052 0.657765 0.723594 +vn 0.000000 0.682516 0.730827 +vn 0.000000 0.610889 0.791681 +vn 0.193762 0.700705 0.686605 +vn -0.209052 0.657765 0.723594 +vn -0.193762 0.700705 0.686605 +vn -0.207953 0.341136 -0.916684 +vn -0.198553 0.775750 -0.598926 +vn 0.207953 0.341136 -0.916684 +vn 0.198553 0.775750 -0.598926 +vn 0.028169 0.936552 0.349315 +vn -0.045198 0.741386 0.669515 +vn -0.028169 0.936552 0.349315 +vn 0.045198 0.741386 0.669515 +vn -0.103214 0.565844 0.817988 +vn 0.000000 0.515732 0.856716 +vn 0.103214 0.565844 0.817988 +vn 0.988647 0.143651 0.043428 +vn 0.969390 0.150731 0.193640 +vn -0.988647 0.143651 0.043428 +vn -0.969390 0.150731 0.193640 +vn 0.961150 0.141972 0.236671 +vn 0.991089 -0.112064 0.071688 +vn 0.996094 -0.087863 0.005982 +vn 0.972930 0.178503 0.146702 +vn -0.961150 0.141972 0.236671 +vn -0.972930 0.178503 0.146702 +vn -0.996094 -0.087863 0.005982 +vn -0.991089 -0.112064 0.071688 +vn 0.976745 0.214362 0.000549 +vn 0.997345 0.067721 -0.026521 +vn 0.862911 0.481582 0.152989 +vn 0.974273 0.205939 -0.091464 +vn -0.976745 0.214362 0.000549 +vn -0.974273 0.205939 -0.091464 +vn -0.862911 0.481582 0.152989 +vn -0.997345 0.067721 -0.026521 +vn 0.958953 0.179296 -0.219642 +vn 0.659688 0.631062 -0.408063 +vn -0.958953 0.179296 -0.219642 +vn -0.659688 0.631062 -0.408063 +vn 0.634510 -0.772881 -0.002594 +vn 0.677480 -0.727989 0.104923 +vn 0.611896 -0.775109 -0.157231 +vn 0.552232 -0.817194 -0.164861 +vn 0.554521 -0.831813 0.023713 +vn 0.574145 -0.803827 0.155492 +vn -0.634510 -0.772881 -0.002594 +vn -0.554521 -0.831813 0.023713 +vn -0.552232 -0.817194 -0.164861 +vn -0.611896 -0.775109 -0.157231 +vn -0.677480 -0.727989 0.104923 +vn -0.574145 -0.803827 0.155492 +vn 0.431562 -0.900662 0.050020 +vn 0.514512 -0.853725 0.079958 +vn 0.484573 -0.859371 0.163091 +vn 0.372662 -0.912870 -0.166662 +vn 0.220649 -0.975311 -0.008881 +vn -0.431562 -0.900662 0.050020 +vn -0.372662 -0.912870 -0.166662 +vn -0.484573 -0.859371 0.163091 +vn -0.514512 -0.853725 0.079958 +vn -0.220649 -0.975311 -0.008881 +vn 0.510849 -0.837336 0.194555 +vn 0.517472 -0.832362 0.198401 +vn -0.510849 -0.837336 0.194555 +vn -0.517472 -0.832362 0.198401 +vn 0.636128 -0.723289 0.268624 +vn 0.531968 -0.730094 0.428877 +vn 0.691885 -0.690512 0.210791 +vn -0.636128 -0.723289 0.268624 +vn -0.691885 -0.690512 0.210791 +vn -0.531968 -0.730094 0.428877 +vn 0.719932 -0.671804 0.174139 +vn -0.719932 -0.671804 0.174139 +vn 0.479995 -0.700980 0.527421 +vn -0.479995 -0.700980 0.527421 +vn 0.553697 -0.316263 -0.770287 +vn 0.538865 -0.290139 -0.790796 +vn 0.330943 -0.613880 -0.716636 +vn 0.439894 -0.608448 -0.660482 +vn 0.568682 -0.533830 -0.625782 +vn 0.555193 -0.280313 -0.783044 +vn -0.553697 -0.316263 -0.770287 +vn -0.555193 -0.280313 -0.783044 +vn -0.568682 -0.533830 -0.625782 +vn -0.439894 -0.608448 -0.660482 +vn -0.330943 -0.613880 -0.716636 +vn -0.538865 -0.290139 -0.790796 +vn 0.506241 -0.193304 -0.840419 +vn 0.513321 -0.365490 -0.776452 +vn -0.506241 -0.193304 -0.840419 +vn -0.513321 -0.365490 -0.776452 +vn 0.352123 -0.829249 -0.433973 +vn 0.124088 -0.887814 -0.443129 +vn 0.560656 -0.740715 -0.370067 +vn -0.352123 -0.829249 -0.433973 +vn -0.560656 -0.740715 -0.370067 +vn -0.124088 -0.887814 -0.443129 +vn 0.612964 -0.717734 -0.330302 +vn 0.591662 -0.625507 -0.508560 +vn -0.612964 -0.717734 -0.330302 +vn -0.591662 -0.625507 -0.508560 +vn 0.521714 -0.487045 -0.700400 +vn -0.521714 -0.487045 -0.700400 +vn 0.209479 0.534135 0.818995 +vn 0.309488 0.497574 0.810297 +vn -0.128636 0.958678 0.253670 +vn -0.277871 0.920347 0.275124 +vn -0.451857 0.830683 0.325175 +vn 0.052919 0.487991 0.871212 +vn 0.519364 -0.143529 0.842372 +vn 0.585803 -0.145634 0.797235 +vn 0.565172 -0.212806 0.797021 +vn -0.209479 0.534135 0.818995 +vn -0.585803 -0.145634 0.797235 +vn -0.519364 -0.143529 0.842372 +vn -0.052919 0.487991 0.871212 +vn 0.451857 0.830683 0.325175 +vn 0.277871 0.920347 0.275124 +vn 0.128636 0.958678 0.253670 +vn -0.309488 0.497574 0.810297 +vn -0.565172 -0.212806 0.797021 +vn 0.368633 0.426740 0.825800 +vn 0.088748 0.954375 0.285012 +vn 0.474837 -0.253914 0.842616 +vn 0.286019 -0.227882 0.930692 +vn 0.416242 0.313120 0.853633 +vn 0.432173 0.832484 0.346629 +vn -0.368633 0.426740 0.825800 +vn -0.416242 0.313120 0.853633 +vn -0.286019 -0.227882 0.930692 +vn -0.474837 -0.253914 0.842616 +vn -0.088748 0.954375 0.285012 +vn -0.432173 0.832484 0.346629 +vn 0.384899 0.142399 0.911893 +vn 0.719260 0.472427 0.509323 +vn 0.015687 -0.158208 0.987274 +vn -0.158818 -0.063173 0.985260 +vn 0.330943 0.009430 0.943571 +vn 0.762993 0.105686 0.637684 +vn -0.384899 0.142399 0.911893 +vn -0.330943 0.009430 0.943571 +vn 0.158818 -0.063173 0.985260 +vn -0.015687 -0.158208 0.987274 +vn -0.719260 0.472427 0.509323 +vn -0.762993 0.105686 0.637684 +vn 0.335917 -0.072848 0.939055 +vn 0.735893 -0.192053 0.649251 +vn -0.209998 0.093936 0.973144 +vn -0.082522 0.330973 0.940001 +vn 0.414380 -0.113132 0.903012 +vn 0.699118 -0.451277 0.554582 +vn -0.335917 -0.072848 0.939055 +vn -0.414380 -0.113132 0.903012 +vn 0.082522 0.330973 0.940001 +vn 0.209998 0.093936 0.973144 +vn -0.735893 -0.192053 0.649251 +vn -0.699118 -0.451277 0.554582 +vn 0.520920 -0.197363 0.830439 +vn 0.605914 -0.676687 0.418226 +vn 0.182531 0.440687 0.878872 +vn 0.453230 0.337626 0.824946 +vn 0.592914 -0.341716 0.729148 +vn 0.473220 -0.824915 0.309122 +vn -0.520920 -0.197363 0.830439 +vn -0.592914 -0.341716 0.729148 +vn -0.453230 0.337626 0.824946 +vn -0.182531 0.440687 0.878872 +vn -0.605914 -0.676687 0.418226 +vn -0.473220 -0.824915 0.309122 +vn 0.539781 -0.447951 0.712699 +vn 0.318339 -0.905057 0.281961 +vn 0.548692 0.202307 0.811151 +vn 0.358654 0.326518 0.874477 +vn 0.265175 -0.352886 0.897275 +vn 0.067537 -0.934385 0.349773 +vn -0.539781 -0.447951 0.712699 +vn -0.265175 -0.352886 0.897275 +vn -0.358654 0.326518 0.874477 +vn -0.548692 0.202307 0.811151 +vn -0.318339 -0.905057 0.281961 +vn -0.067537 -0.934385 0.349773 +vn 0.363628 0.683462 0.632923 +vn 0.127232 0.795526 0.592364 +vn -0.150975 0.949828 0.273812 +vn 0.124302 0.922849 0.364483 +vn 0.148930 0.913938 0.377453 +vn 0.288919 0.722434 0.628132 +vn -0.363628 0.683462 0.632923 +vn -0.288919 0.722434 0.628132 +vn -0.148930 0.913938 0.377453 +vn -0.124302 0.922849 0.364483 +vn 0.150975 0.949828 0.273812 +vn -0.127232 0.795526 0.592364 +vn -0.234443 0.799249 0.553362 +vn -0.574297 0.610431 0.545457 +vn -0.779595 0.625935 0.019868 +vn -0.486496 0.860500 0.151006 +vn 0.234443 0.799249 0.553362 +vn 0.486496 0.860500 0.151006 +vn 0.779595 0.625935 0.019868 +vn 0.574297 0.610431 0.545457 +vn -0.769890 0.263863 0.581042 +vn -0.704611 -0.087863 0.704093 +vn -0.990295 -0.073580 0.117740 +vn -0.952635 0.303598 -0.016480 +vn 0.769890 0.263863 0.581042 +vn 0.952635 0.303598 -0.016480 +vn 0.990295 -0.073580 0.117740 +vn 0.704611 -0.087863 0.704093 +vn -0.387768 -0.376843 0.841151 +vn 0.100284 -0.528642 0.842860 +vn -0.094821 -0.757225 0.646168 +vn -0.738731 -0.525468 0.422071 +vn 0.387768 -0.376843 0.841151 +vn 0.738731 -0.525468 0.422071 +vn 0.094821 -0.757225 0.646168 +vn -0.100284 -0.528642 0.842860 +vn 0.422437 -0.542375 0.726157 +vn 0.569414 -0.503067 0.650105 +vn 0.529191 -0.653615 0.541002 +vn 0.346049 -0.718528 0.603259 +vn -0.422437 -0.542375 0.726157 +vn -0.346049 -0.718528 0.603259 +vn -0.529191 -0.653615 0.541002 +vn -0.569414 -0.503067 0.650105 +vn 0.654408 -0.438581 0.615894 +vn 0.652272 -0.404614 0.640919 +vn 0.695608 -0.531571 0.483261 +vn 0.647786 -0.578509 0.495621 +vn -0.654408 -0.438581 0.615894 +vn -0.647786 -0.578509 0.495621 +vn -0.695608 -0.531571 0.483261 +vn -0.652272 -0.404614 0.640919 +vn 0.736076 -0.673910 0.063051 +vn 0.844966 -0.534532 -0.016541 +vn 0.465987 -0.659810 0.589465 +vn 0.719077 0.184545 0.669942 +vn 0.905606 -0.420331 0.056154 +vn 0.906552 -0.403455 -0.123905 +vn -0.736076 -0.673910 0.063051 +vn -0.905606 -0.420331 0.056154 +vn -0.719077 0.184545 0.669942 +vn -0.465987 -0.659810 0.589465 +vn -0.844966 -0.534532 -0.016541 +vn -0.906552 -0.403455 -0.123905 +vn 0.072939 -0.280648 0.957030 +vn -0.086459 -0.935301 0.343089 +vn 0.180700 0.506149 0.843287 +vn -0.072939 -0.280648 0.957030 +vn -0.180700 0.506149 0.843287 +vn 0.086459 -0.935301 0.343089 +vn 0.937071 -0.347606 -0.032167 +vn 0.937071 -0.333140 -0.104312 +vn -0.937071 -0.347606 -0.032167 +vn -0.937071 -0.333140 -0.104312 +vn 0.196753 0.375072 0.905850 +vn -0.321055 0.893460 0.313974 +vn 0.838160 0.062502 0.541795 +vn 0.692587 -0.287454 0.661550 +vn 0.500412 -0.212104 0.839381 +vn -0.196753 0.375072 0.905850 +vn -0.500412 -0.212104 0.839381 +vn -0.692587 -0.287454 0.661550 +vn -0.838160 0.062502 0.541795 +vn 0.321055 0.893460 0.313974 +vn 0.170232 0.840114 0.514969 +vn 0.101382 0.954955 0.278817 +vn 0.516526 0.734611 0.439924 +vn 0.482498 0.642048 0.595752 +vn -0.170232 0.840114 0.514969 +vn -0.482498 0.642048 0.595752 +vn -0.516526 0.734611 0.439924 +vn -0.101382 0.954955 0.278817 +vn 0.701376 0.176153 0.690664 +vn 0.808008 0.000305 0.589129 +vn 0.766289 -0.015839 0.642262 +vn 0.690451 0.137425 0.710166 +vn 0.930479 -0.143223 0.337138 +vn 0.879299 0.032075 0.475112 +vn -0.701376 0.176153 0.690664 +vn -0.879299 0.032075 0.475112 +vn -0.930479 -0.143223 0.337138 +vn -0.690451 0.137425 0.710166 +vn -0.766289 -0.015839 0.642262 +vn -0.808008 0.000305 0.589129 +vn 0.634571 0.390851 0.666707 +vn 0.598041 0.631001 0.494095 +vn 0.923490 0.029298 0.382427 +vn 0.895505 0.003876 0.445021 +vn 0.697745 0.361339 0.618488 +vn 0.567370 0.646229 0.510300 +vn -0.634571 0.390851 0.666707 +vn -0.697745 0.361339 0.618488 +vn -0.895505 0.003876 0.445021 +vn -0.923490 0.029298 0.382427 +vn -0.598041 0.631001 0.494095 +vn -0.567370 0.646229 0.510300 +vn 0.859279 -0.428602 0.279122 +vn 0.799005 -0.537950 0.268654 +vn 0.724265 -0.574358 0.381481 +vn 0.768731 -0.471847 0.431684 +vn 0.885067 -0.408612 0.222755 +vn 0.912687 -0.390545 0.119999 +vn -0.859279 -0.428602 0.279122 +vn -0.912687 -0.390545 0.119999 +vn -0.885067 -0.408612 0.222755 +vn -0.768731 -0.471847 0.431684 +vn -0.724265 -0.574358 0.381481 +vn -0.799005 -0.537950 0.268654 +vn 0.690695 -0.430616 0.580920 +vn 0.618641 -0.408277 0.671194 +vn 0.845790 -0.350261 0.402387 +vn 0.698721 -0.538987 0.470351 +vn 0.689261 -0.521226 0.503159 +vn -0.690695 -0.430616 0.580920 +vn -0.698721 -0.538987 0.470351 +vn -0.845790 -0.350261 0.402387 +vn -0.618641 -0.408277 0.671194 +vn -0.689261 -0.521226 0.503159 +vn 0.607532 -0.405286 0.683096 +vn 0.694205 -0.520005 0.497635 +vn -0.607532 -0.405286 0.683096 +vn -0.694205 -0.520005 0.497635 +vn 0.982055 -0.147588 0.117283 +vn 0.952727 -0.303751 0.002106 +vn -0.982055 -0.147588 0.117283 +vn -0.952727 -0.303751 0.002106 +vn 0.926328 -0.372692 -0.054415 +vn 0.941984 -0.332560 -0.044923 +vn -0.926328 -0.372692 -0.054415 +vn -0.941984 -0.332560 -0.044923 +vn 0.977569 -0.182928 0.104068 +vn -0.977569 -0.182928 0.104068 +vn 0.707999 -0.549516 0.443525 +vn 0.690878 -0.544816 0.475173 +vn 0.714774 -0.555223 0.425184 +vn 0.584887 -0.375927 0.718680 +vn 0.609638 -0.346934 0.712699 +vn 0.619343 -0.281106 0.733055 +vn -0.707999 -0.549516 0.443525 +vn -0.609638 -0.346934 0.712699 +vn -0.584887 -0.375927 0.718680 +vn -0.714774 -0.555223 0.425184 +vn -0.690878 -0.544816 0.475173 +vn -0.619343 -0.281106 0.733055 +vn 0.705802 -0.572039 0.417829 +vn 0.687246 -0.607318 0.398541 +vn 0.475661 -0.408002 0.779260 +vn 0.536027 -0.392132 0.747581 +vn -0.705802 -0.572039 0.417829 +vn -0.536027 -0.392132 0.747581 +vn -0.475661 -0.408002 0.779260 +vn -0.687246 -0.607318 0.398541 +vn 0.730583 -0.570421 0.375225 +vn 0.885372 0.034120 0.463576 +vn 0.619587 -0.055605 0.782922 +vn 0.497299 -0.348430 0.794488 +vn -0.730583 -0.570421 0.375225 +vn -0.497299 -0.348430 0.794488 +vn -0.619587 -0.055605 0.782922 +vn -0.885372 0.034120 0.463576 +vn 0.570269 0.679434 0.461623 +vn 0.590411 0.667165 0.454146 +vn 0.422071 0.390790 0.817988 +vn 0.428846 0.399457 0.810205 +vn -0.570269 0.679434 0.461623 +vn -0.428846 0.399457 0.810205 +vn -0.422071 0.390790 0.817988 +vn -0.590411 0.667165 0.454146 +vn 0.795618 0.299814 0.526353 +vn 0.839259 -0.140477 0.525224 +vn 0.426160 0.141331 0.893521 +vn 0.512314 0.218146 0.830622 +vn -0.795618 0.299814 0.526353 +vn -0.512314 0.218146 0.830622 +vn -0.426160 0.141331 0.893521 +vn -0.839259 -0.140477 0.525224 +vn 0.811670 -0.029969 0.583300 +vn 0.569933 0.671621 0.473312 +vn 0.196142 0.751152 0.630299 +vn 0.401044 0.303232 0.864406 +vn -0.811670 -0.029969 0.583300 +vn -0.401044 0.303232 0.864406 +vn -0.196142 0.751152 0.630299 +vn -0.569933 0.671621 0.473312 +vn 0.020386 0.969848 0.242744 +vn 0.047304 0.951781 0.303079 +vn 0.115604 0.781182 0.613453 +vn -0.127476 0.869442 0.477248 +vn -0.020386 0.969848 0.242744 +vn 0.127476 0.869442 0.477248 +vn -0.115604 0.781182 0.613453 +vn -0.047304 0.951781 0.303079 +vn 0.638417 -0.564226 0.523484 +vn 0.522507 -0.634632 0.569353 +vn 0.593188 -0.200720 0.779626 +vn 0.527177 -0.185858 0.829157 +vn -0.638417 -0.564226 0.523484 +vn -0.593188 -0.200720 0.779626 +vn -0.522507 -0.634632 0.569353 +vn -0.527177 -0.185858 0.829157 +vn 0.311045 -0.738121 0.598621 +vn -0.181371 -0.756493 0.628285 +vn 0.399609 -0.227363 0.888028 +vn 0.221595 -0.208228 0.952635 +vn -0.311045 -0.738121 0.598621 +vn -0.399609 -0.227363 0.888028 +vn 0.181371 -0.756493 0.628285 +vn -0.221595 -0.208228 0.952635 +vn -0.682760 -0.473373 0.556536 +vn -0.892361 -0.070894 0.445692 +vn 0.053926 -0.077456 0.995514 +vn 0.008545 0.006623 0.999939 +vn 0.682760 -0.473373 0.556536 +vn -0.053926 -0.077456 0.995514 +vn 0.892361 -0.070894 0.445692 +vn -0.008545 0.006623 0.999939 +vn -0.846126 0.296640 0.442732 +vn -0.630207 0.621174 0.465773 +vn 0.063662 0.051057 0.996643 +vn 0.142338 0.143925 0.979278 +vn 0.846126 0.296640 0.442732 +vn -0.063662 0.051057 0.996643 +vn 0.630207 0.621174 0.465773 +vn -0.142338 0.143925 0.979278 +vn -0.330302 0.830805 0.447890 +vn -0.041536 0.910733 0.410840 +vn 0.250374 0.260567 0.932401 +vn 0.380749 0.392041 0.837428 +vn 0.330302 0.830805 0.447890 +vn -0.250374 0.260567 0.932401 +vn 0.041536 0.910733 0.410840 +vn -0.380749 0.392041 0.837428 +vn 0.115299 0.922727 0.367718 +vn 0.433882 0.528275 0.729820 +vn -0.115299 0.922727 0.367718 +vn -0.433882 0.528275 0.729820 +vn 0.190069 0.106021 0.976012 +vn 0.184973 0.080081 0.979461 +vn 0.071474 0.275521 0.958617 +vn 0.256203 0.189581 0.947844 +vn 0.223090 0.083560 0.971191 +vn 0.200720 0.009705 0.979583 +vn -0.190069 0.106021 0.976012 +vn -0.223090 0.083560 0.971191 +vn -0.256203 0.189581 0.947844 +vn -0.071474 0.275521 0.958617 +vn -0.184973 0.080081 0.979461 +vn -0.200720 0.009705 0.979583 +vn 0.330729 0.049165 0.942412 +vn 0.287027 0.000153 0.957884 +vn 0.426984 0.070040 0.901517 +vn 0.458724 -0.036988 0.887783 +vn 0.373791 -0.001068 0.927488 +vn 0.342174 -0.009735 0.939573 +vn -0.330729 0.049165 0.942412 +vn -0.373791 -0.001068 0.927488 +vn -0.458724 -0.036988 0.887783 +vn -0.426984 0.070040 0.901517 +vn -0.287027 0.000153 0.957884 +vn -0.342174 -0.009735 0.939573 +vn 0.358135 -0.030854 0.933134 +vn 0.353832 -0.002441 0.935270 +vn 0.421094 -0.110385 0.900235 +vn 0.385754 -0.160710 0.908475 +vn 0.308817 -0.040498 0.950255 +vn 0.319712 0.044679 0.946440 +vn -0.358135 -0.030854 0.933134 +vn -0.308817 -0.040498 0.950255 +vn -0.385754 -0.160710 0.908475 +vn -0.421094 -0.110385 0.900235 +vn -0.353832 -0.002441 0.935270 +vn -0.319712 0.044679 0.946440 +vn 0.319590 0.010529 0.947478 +vn 0.307443 0.165899 0.936979 +vn 0.417768 -0.135441 0.898373 +vn 0.496597 -0.014313 0.867855 +vn 0.432875 0.131718 0.891751 +vn 0.374279 0.302072 0.876705 +vn -0.319590 0.010529 0.947478 +vn -0.432875 0.131718 0.891751 +vn -0.496597 -0.014313 0.867855 +vn -0.417768 -0.135441 0.898373 +vn -0.307443 0.165899 0.936979 +vn -0.374279 0.302072 0.876705 +vn 0.404675 0.175359 0.897458 +vn 0.389996 0.311075 0.866665 +vn 0.435591 0.013337 0.900021 +vn -0.404675 0.175359 0.897458 +vn -0.435591 0.013337 0.900021 +vn -0.389996 0.311075 0.866665 +vn 0.431257 -0.077639 0.898862 +vn 0.386761 -0.107608 0.915860 +vn -0.431257 -0.077639 0.898862 +vn -0.386761 -0.107608 0.915860 +vn 0.310953 -0.111362 0.943846 +vn 0.221564 -0.101260 0.969848 +vn -0.310953 -0.111362 0.943846 +vn -0.221564 -0.101260 0.969848 +vn 0.209540 -0.015351 0.977660 +vn -0.209540 -0.015351 0.977660 +vn -0.088900 0.548936 0.831111 +vn 0.228919 0.393719 0.890255 +vn 0.088900 0.548936 0.831111 +vn -0.228919 0.393719 0.890255 +vn 0.514298 0.133152 0.847194 +vn 0.520341 -0.017182 0.853755 +vn -0.514298 0.133152 0.847194 +vn -0.520341 -0.017182 0.853755 +vn 0.454390 -0.122684 0.882290 +vn 0.441420 -0.177038 0.879635 +vn -0.454390 -0.122684 0.882290 +vn -0.441420 -0.177038 0.879635 +vn 0.484085 -0.142033 0.863399 +vn 0.520737 0.011444 0.853603 +vn -0.484085 -0.142033 0.863399 +vn -0.520737 0.011444 0.853603 +vn 0.492141 0.201575 0.846828 +vn 0.423444 0.324931 0.845637 +vn -0.492141 0.201575 0.846828 +vn -0.423444 0.324931 0.845637 +vn 0.392621 0.359020 0.846706 +vn -0.392621 0.359020 0.846706 +vn -0.026399 -0.935240 -0.352977 +vn 0.137211 -0.908963 -0.393567 +vn -0.098086 -0.943632 -0.316080 +vn -0.183935 -0.532579 -0.826136 +vn -0.344218 -0.434950 -0.832026 +vn -0.224647 -0.413709 -0.882229 +vn 0.026399 -0.935240 -0.352977 +vn 0.344218 -0.434950 -0.832026 +vn 0.183935 -0.532579 -0.826136 +vn 0.098086 -0.943632 -0.316080 +vn -0.137211 -0.908963 -0.393567 +vn 0.224647 -0.413709 -0.882229 +vn 0.424421 -0.837733 -0.343577 +vn 0.734916 -0.653279 -0.181860 +vn 0.031709 -0.412824 -0.910245 +vn 0.423048 -0.386914 -0.819330 +vn -0.424421 -0.837733 -0.343577 +vn -0.031709 -0.412824 -0.910245 +vn -0.734916 -0.653279 -0.181860 +vn -0.423048 -0.386914 -0.819330 +vn 0.952635 -0.293619 0.078890 +vn 0.984252 0.134922 0.114139 +vn 0.760125 -0.172033 -0.626545 +vn 0.931089 0.104984 -0.349284 +vn -0.952635 -0.293619 0.078890 +vn -0.760125 -0.172033 -0.626545 +vn -0.984252 0.134922 0.114139 +vn -0.931089 0.104984 -0.349284 +vn 0.799799 0.574877 -0.172643 +vn 0.294778 0.852626 -0.431379 +vn 0.620319 0.322001 -0.715171 +vn 0.097324 0.416272 -0.903989 +vn -0.799799 0.574877 -0.172643 +vn -0.620319 0.322001 -0.715171 +vn -0.294778 0.852626 -0.431379 +vn -0.097324 0.416272 -0.903989 +vn -0.187536 0.859859 -0.474776 +vn -0.405438 0.807031 -0.429273 +vn -0.277871 0.341594 -0.897824 +vn -0.439253 0.320627 -0.839167 +vn 0.187536 0.859859 -0.474776 +vn 0.277871 0.341594 -0.897824 +vn 0.405438 0.807031 -0.429273 +vn 0.439253 0.320627 -0.839167 +vn -0.505356 0.789941 -0.347209 +vn -0.597308 0.761711 -0.250954 +vn -0.515336 0.340556 -0.786401 +vn -0.456252 0.414350 -0.787469 +vn 0.505356 0.789941 -0.347209 +vn 0.515336 0.340556 -0.786401 +vn 0.597308 0.761711 -0.250954 +vn 0.456252 0.414350 -0.787469 +vn -0.434492 -0.022065 -0.900388 +vn -0.370830 -0.020356 -0.928465 +vn -0.142460 -0.078219 -0.986694 +vn 0.434492 -0.022065 -0.900388 +vn 0.142460 -0.078219 -0.986694 +vn 0.370830 -0.020356 -0.928465 +vn -0.210334 -0.024171 -0.977325 +vn 0.006409 -0.019349 -0.999786 +vn 0.210334 -0.024171 -0.977325 +vn -0.006409 -0.019349 -0.999786 +vn 0.483657 0.054659 -0.873531 +vn -0.483657 0.054659 -0.873531 +vn -0.350017 0.872494 -0.340922 +vn 0.213660 0.358959 -0.908536 +vn 0.350017 0.872494 -0.340922 +vn -0.213660 0.358959 -0.908536 +vn 0.348430 -0.203070 -0.915067 +vn 0.121982 -0.595965 -0.793664 +vn -0.348430 -0.203070 -0.915067 +vn -0.121982 -0.595965 -0.793664 +vn -0.093081 -0.918058 -0.385296 +vn 0.093081 -0.918058 -0.385296 +usemtl (null) +s 1 +f 1/1/1 504/2/2 1552/3/3 +f 1/1/1 1552/3/3 501/4/4 +f 1/1/1 501/4/4 1506/5/5 +f 1/1/1 1506/5/5 502/6/6 +f 1/1/1 502/6/6 1508/7/7 +f 1/1/1 1508/7/7 503/8/8 +f 1/1/1 503/8/8 1550/9/9 +f 1/1/1 1550/9/9 504/2/2 +f 2/10/10 508/11/11 1509/12/12 +f 2/10/10 1509/12/12 505/13/13 +f 2/10/10 505/13/13 1507/14/14 +f 2/10/10 1507/14/14 506/15/15 +f 2/10/10 506/15/15 1553/16/16 +f 2/10/10 1553/16/16 507/17/17 +f 2/10/10 507/17/17 1551/18/18 +f 2/10/10 1551/18/18 508/11/11 +f 3/19/19 511/20/20 1550/9/9 +f 3/19/19 1550/9/9 503/8/8 +f 3/19/19 503/8/8 1508/7/7 +f 3/19/19 1508/7/7 509/21/21 +f 3/19/19 509/21/21 1510/22/22 +f 3/19/19 1510/22/22 510/23/23 +f 3/19/19 510/23/23 1548/24/24 +f 3/19/19 1548/24/24 511/20/20 +f 4/25/25 514/26/26 1511/27/27 +f 4/25/25 1511/27/27 512/28/28 +f 4/25/25 512/28/28 1509/12/12 +f 4/25/25 1509/12/12 508/11/11 +f 4/25/25 508/11/11 1551/18/18 +f 4/25/25 1551/18/18 513/29/29 +f 4/25/25 513/29/29 1549/30/30 +f 4/25/25 1549/30/30 514/26/26 +f 5/31/31 509/21/21 1508/7/7 +f 5/31/31 1508/7/7 515/32/32 +f 5/33/31 515/34/32 1514/35/33 +f 5/33/31 1514/35/33 516/36/34 +f 5/31/31 516/37/34 1512/38/35 +f 5/31/31 1512/38/35 517/39/36 +f 5/31/31 517/39/36 1510/22/22 +f 5/31/31 1510/22/22 509/21/21 +f 6/40/37 520/41/38 1513/42/39 +f 6/40/37 1513/42/39 518/43/40 +f 6/40/37 518/43/40 1515/44/41 +f 6/40/37 1515/44/41 519/45/42 +f 6/40/37 519/45/42 1509/12/12 +f 6/40/37 1509/12/12 512/28/28 +f 6/40/37 512/28/28 1511/27/27 +f 6/40/37 1511/27/27 520/41/38 +f 7/46/43 502/6/6 1506/5/5 +f 7/46/43 1506/5/5 521/47/44 +f 7/48/43 521/49/44 1516/50/45 +f 7/48/43 1516/50/45 522/51/46 +f 7/48/43 522/51/46 1514/35/33 +f 7/48/43 1514/35/33 515/34/32 +f 7/46/43 515/32/32 1508/7/7 +f 7/46/43 1508/7/7 502/6/6 +f 8/52/47 519/45/42 1515/44/41 +f 8/52/47 1515/44/41 523/53/48 +f 8/52/47 523/53/48 1517/54/49 +f 8/52/47 1517/54/49 524/55/50 +f 8/52/47 524/55/50 1507/14/14 +f 8/52/47 1507/14/14 505/13/13 +f 8/52/47 505/13/13 1509/12/12 +f 8/52/47 1509/12/12 519/45/42 +f 9/56/51 522/51/46 1516/50/45 +f 9/56/51 1516/50/45 525/57/52 +f 9/56/51 525/57/52 1518/58/53 +f 9/56/51 1518/58/53 526/59/54 +f 9/56/51 526/59/54 1520/60/55 +f 9/56/51 1520/60/55 527/61/56 +f 9/56/51 527/61/56 1514/35/33 +f 9/56/51 1514/35/33 522/51/46 +f 10/62/57 530/63/58 1521/64/59 +f 10/62/57 1521/64/59 528/65/60 +f 10/62/57 528/65/60 1519/66/61 +f 10/62/57 1519/66/61 529/67/62 +f 10/62/57 529/67/62 1517/54/49 +f 10/62/57 1517/54/49 523/53/48 +f 10/62/57 523/53/48 1515/44/41 +f 10/62/57 1515/44/41 530/63/58 +f 11/68/63 516/36/34 1514/35/33 +f 11/68/63 1514/35/33 527/61/56 +f 11/68/63 527/61/56 1520/60/55 +f 11/68/63 1520/60/55 531/69/64 +f 11/68/63 531/69/64 1522/70/65 +f 11/68/63 1522/70/65 532/71/66 +f 11/68/63 532/71/66 1512/72/35 +f 11/68/63 1512/72/35 516/36/34 +f 12/73/67 534/74/68 1523/75/69 +f 12/73/67 1523/75/69 533/76/70 +f 12/73/67 533/76/70 1521/77/59 +f 12/73/67 1521/77/59 530/78/58 +f 12/79/67 530/63/58 1515/44/41 +f 12/79/67 1515/44/41 518/43/40 +f 12/79/67 518/43/40 1513/42/39 +f 12/79/67 1513/42/39 534/80/68 +f 13/81/71 531/69/64 1520/60/55 +f 13/81/71 1520/60/55 535/82/72 +f 13/81/71 535/82/72 1526/83/73 +f 13/81/71 1526/83/73 536/84/74 +f 13/81/71 536/84/74 1524/85/75 +f 13/81/71 1524/85/75 537/86/76 +f 13/81/71 537/86/76 1522/70/65 +f 13/81/71 1522/70/65 531/69/64 +f 14/87/77 540/88/78 1525/89/79 +f 14/87/77 1525/89/79 538/90/80 +f 14/87/77 538/90/80 1527/91/81 +f 14/87/77 1527/91/81 539/92/82 +f 14/87/77 539/92/82 1521/77/59 +f 14/87/77 1521/77/59 533/76/70 +f 14/87/77 533/76/70 1523/75/69 +f 14/87/77 1523/75/69 540/88/78 +f 15/93/83 526/59/54 1518/58/53 +f 15/93/83 1518/58/53 541/94/84 +f 15/93/83 541/94/84 1528/95/85 +f 15/93/83 1528/95/85 542/96/86 +f 15/93/83 542/96/86 1526/83/73 +f 15/93/83 1526/83/73 535/82/72 +f 15/93/83 535/82/72 1520/60/55 +f 15/93/83 1520/60/55 526/59/54 +f 16/97/87 539/92/82 1527/91/81 +f 16/97/87 1527/91/81 543/98/88 +f 16/97/87 543/98/88 1529/99/89 +f 16/97/87 1529/99/89 544/100/90 +f 16/101/87 544/102/90 1519/66/61 +f 16/101/87 1519/66/61 528/65/60 +f 16/101/87 528/65/60 1521/64/59 +f 16/101/87 1521/64/59 539/103/82 +f 17/104/91 542/96/86 1528/95/85 +f 17/104/91 1528/95/85 545/105/92 +f 17/104/91 545/105/92 1530/106/93 +f 17/104/91 1530/106/93 546/107/94 +f 17/104/91 546/107/94 1532/108/95 +f 17/104/91 1532/108/95 547/109/96 +f 17/104/91 547/109/96 1526/83/73 +f 17/104/91 1526/83/73 542/96/86 +f 18/110/97 550/111/98 1533/112/99 +f 18/110/97 1533/112/99 548/113/100 +f 18/110/97 548/113/100 1531/114/101 +f 18/110/97 1531/114/101 549/115/102 +f 18/110/97 549/115/102 1529/116/89 +f 18/110/97 1529/116/89 543/117/88 +f 18/110/97 543/117/88 1527/118/81 +f 18/110/97 1527/118/81 550/111/98 +f 19/119/103 536/120/74 1526/121/73 +f 19/119/103 1526/121/73 547/122/96 +f 19/119/103 547/122/96 1532/123/95 +f 19/119/103 1532/123/95 551/124/104 +f 19/119/103 551/124/104 1534/125/105 +f 19/119/103 1534/125/105 552/126/106 +f 19/119/103 552/126/106 1524/127/75 +f 19/119/103 1524/127/75 536/120/74 +f 20/128/107 554/129/108 1535/130/109 +f 20/128/107 1535/130/109 553/131/110 +f 20/128/107 553/131/110 1533/112/99 +f 20/128/107 1533/112/99 550/111/98 +f 20/128/107 550/111/98 1527/118/81 +f 20/128/107 1527/118/81 538/132/80 +f 20/133/107 538/90/80 1525/89/79 +f 20/133/107 1525/89/79 554/134/108 +f 21/135/111 551/124/104 1532/123/95 +f 21/135/111 1532/123/95 555/136/112 +f 21/137/111 555/138/112 1538/139/113 +f 21/137/111 1538/139/113 556/140/114 +f 21/137/111 556/140/114 1536/141/115 +f 21/137/111 1536/141/115 557/142/116 +f 21/135/111 557/143/116 1534/125/105 +f 21/135/111 1534/125/105 551/124/104 +f 22/144/117 560/145/118 1537/146/119 +f 22/144/117 1537/146/119 558/147/120 +f 22/144/117 558/147/120 1539/148/121 +f 22/144/117 1539/148/121 559/149/122 +f 22/144/117 559/149/122 1533/112/99 +f 22/144/117 1533/112/99 553/131/110 +f 22/144/117 553/131/110 1535/130/109 +f 22/144/117 1535/130/109 560/145/118 +f 23/150/123 546/151/94 1530/152/93 +f 23/150/123 1530/152/93 561/153/124 +f 23/150/123 561/153/124 1540/154/125 +f 23/150/123 1540/154/125 562/155/126 +f 23/150/123 562/155/126 1538/139/113 +f 23/150/123 1538/139/113 555/138/112 +f 23/150/123 555/138/112 1532/156/95 +f 23/150/123 1532/156/95 546/151/94 +f 24/157/127 559/149/122 1539/148/121 +f 24/157/127 1539/148/121 563/158/128 +f 24/157/127 563/158/128 1541/159/129 +f 24/157/127 1541/159/129 564/160/130 +f 24/157/127 564/160/130 1531/114/101 +f 24/157/127 1531/114/101 548/113/100 +f 24/157/127 548/113/100 1533/112/99 +f 24/157/127 1533/112/99 559/149/122 +f 25/161/131 562/155/126 1540/154/125 +f 25/161/131 1540/154/125 565/162/132 +f 25/161/131 565/162/132 1542/163/133 +f 25/161/131 1542/163/133 566/164/134 +f 25/161/131 566/164/134 1544/165/135 +f 25/161/131 1544/165/135 567/166/136 +f 25/161/131 567/166/136 1538/139/113 +f 25/161/131 1538/139/113 562/155/126 +f 26/167/137 570/168/138 1545/169/139 +f 26/167/137 1545/169/139 568/170/140 +f 26/167/137 568/170/140 1543/171/141 +f 26/167/137 1543/171/141 569/172/142 +f 26/173/137 569/174/142 1541/159/129 +f 26/173/137 1541/159/129 563/158/128 +f 26/173/137 563/158/128 1539/148/121 +f 26/173/137 1539/148/121 570/175/138 +f 27/176/143 556/140/114 1538/139/113 +f 27/176/143 1538/139/113 567/166/136 +f 27/176/143 567/166/136 1544/165/135 +f 27/176/143 1544/165/135 571/177/144 +f 27/176/143 571/177/144 1546/178/145 +f 27/176/143 1546/178/145 572/179/146 +f 27/176/143 572/179/146 1536/141/115 +f 27/176/143 1536/141/115 556/140/114 +f 28/180/147 574/181/148 1547/182/149 +f 28/180/147 1547/182/149 573/183/150 +f 28/180/147 573/183/150 1545/169/139 +f 28/180/147 1545/169/139 570/168/138 +f 28/184/147 570/175/138 1539/148/121 +f 28/184/147 1539/148/121 558/147/120 +f 28/184/147 558/147/120 1537/146/119 +f 28/184/147 1537/146/119 574/185/148 +f 29/186/151 571/177/144 1544/165/135 +f 29/186/151 1544/165/135 575/187/152 +f 29/188/151 575/189/152 1550/9/9 +f 29/188/151 1550/9/9 511/20/20 +f 29/188/151 511/20/20 1548/24/24 +f 29/188/151 1548/24/24 576/190/153 +f 29/186/151 576/191/153 1546/178/145 +f 29/186/151 1546/178/145 571/177/144 +f 30/192/154 578/193/155 1549/194/30 +f 30/192/154 1549/194/30 513/195/29 +f 30/192/154 513/195/29 1551/196/18 +f 30/192/154 1551/196/18 577/197/156 +f 30/192/154 577/197/156 1545/169/139 +f 30/192/154 1545/169/139 573/183/150 +f 30/192/154 573/183/150 1547/182/149 +f 30/192/154 1547/182/149 578/193/155 +f 31/198/157 566/164/134 1542/163/133 +f 31/198/157 1542/163/133 579/199/158 +f 31/200/157 579/201/158 1552/3/3 +f 31/200/157 1552/3/3 504/2/2 +f 31/200/157 504/2/2 1550/9/9 +f 31/200/157 1550/9/9 575/189/152 +f 31/198/157 575/187/152 1544/165/135 +f 31/198/157 1544/165/135 566/164/134 +f 32/202/159 577/203/156 1551/18/18 +f 32/202/159 1551/18/18 507/17/17 +f 32/202/159 507/17/17 1553/16/16 +f 32/202/159 1553/16/16 580/204/160 +f 32/205/159 580/206/160 1543/171/141 +f 32/205/159 1543/171/141 568/170/140 +f 32/205/159 568/170/140 1545/169/139 +f 32/205/159 1545/169/139 577/197/156 +f 33/207/161 583/208/162 1552/3/3 +f 33/207/161 1552/3/3 579/201/158 +f 33/209/161 579/199/158 1542/163/133 +f 33/209/161 1542/163/133 581/210/163 +f 33/209/161 581/210/163 1556/211/164 +f 33/209/161 1556/211/164 582/212/165 +f 33/207/161 582/213/165 1554/214/166 +f 33/207/161 1554/214/166 583/208/162 +f 34/215/167 586/216/168 1557/217/169 +f 34/215/167 1557/217/169 584/218/170 +f 34/215/167 584/218/170 1543/171/141 +f 34/215/167 1543/171/141 580/206/160 +f 34/215/167 580/206/160 1553/219/16 +f 34/215/167 1553/219/16 585/220/171 +f 34/215/167 585/220/171 1555/221/172 +f 34/215/167 1555/221/172 586/216/168 +f 35/222/173 581/210/163 1542/163/133 +f 35/222/173 1542/163/133 565/162/132 +f 35/222/173 565/162/132 1540/154/125 +f 35/222/173 1540/154/125 587/223/174 +f 35/222/173 587/223/174 1558/224/175 +f 35/222/173 1558/224/175 588/225/176 +f 35/222/173 588/225/176 1556/211/164 +f 35/222/173 1556/211/164 581/210/163 +f 36/226/177 590/227/178 1559/228/179 +f 36/226/177 1559/228/179 589/229/180 +f 36/226/177 589/229/180 1541/159/129 +f 36/226/177 1541/159/129 569/174/142 +f 36/230/177 569/172/142 1543/171/141 +f 36/230/177 1543/171/141 584/218/170 +f 36/230/177 584/218/170 1557/217/169 +f 36/230/177 1557/217/169 590/231/178 +f 37/232/181 587/223/174 1540/154/125 +f 37/232/181 1540/154/125 561/153/124 +f 37/233/181 561/234/124 1530/235/93 +f 37/233/181 1530/235/93 591/236/182 +f 37/233/181 591/236/182 1560/237/183 +f 37/233/181 1560/237/183 592/238/184 +f 37/232/181 592/239/184 1558/224/175 +f 37/232/181 1558/224/175 587/223/174 +f 38/240/185 594/241/186 1561/242/187 +f 38/240/185 1561/242/187 593/243/188 +f 38/240/185 593/243/188 1531/114/101 +f 38/240/185 1531/114/101 564/160/130 +f 38/240/185 564/160/130 1541/159/129 +f 38/240/185 1541/159/129 589/229/180 +f 38/240/185 589/229/180 1559/228/179 +f 38/240/185 1559/228/179 594/241/186 +f 39/244/189 591/236/182 1530/235/93 +f 39/244/189 1530/235/93 545/245/92 +f 39/244/189 545/245/92 1528/246/85 +f 39/244/189 1528/246/85 595/247/190 +f 39/244/189 595/247/190 1562/248/191 +f 39/244/189 1562/248/191 596/249/192 +f 39/244/189 596/249/192 1560/237/183 +f 39/244/189 1560/237/183 591/236/182 +f 40/250/193 598/251/194 1563/252/195 +f 40/250/193 1563/252/195 597/253/196 +f 40/250/193 597/253/196 1529/99/89 +f 40/250/193 1529/99/89 549/254/102 +f 40/255/193 549/115/102 1531/114/101 +f 40/255/193 1531/114/101 593/243/188 +f 40/255/193 593/243/188 1561/242/187 +f 40/255/193 1561/242/187 598/256/194 +f 41/257/197 595/247/190 1528/246/85 +f 41/257/197 1528/246/85 541/258/84 +f 41/259/197 541/94/84 1518/58/53 +f 41/259/197 1518/58/53 599/260/198 +f 41/259/197 599/260/198 1564/261/199 +f 41/259/197 1564/261/199 600/262/200 +f 41/259/197 600/262/200 1562/263/191 +f 41/259/197 1562/263/191 595/264/190 +f 42/265/201 602/266/202 1565/267/203 +f 42/265/201 1565/267/203 601/268/204 +f 42/265/201 601/268/204 1519/269/61 +f 42/265/201 1519/269/61 544/100/90 +f 42/265/201 544/100/90 1529/99/89 +f 42/265/201 1529/99/89 597/253/196 +f 42/265/201 597/253/196 1563/252/195 +f 42/265/201 1563/252/195 602/266/202 +f 43/270/205 599/260/198 1518/58/53 +f 43/270/205 1518/58/53 525/57/52 +f 43/271/205 525/272/52 1516/273/45 +f 43/271/205 1516/273/45 603/274/206 +f 43/270/205 603/275/206 1568/276/207 +f 43/270/205 1568/276/207 604/277/208 +f 43/270/205 604/277/208 1564/261/199 +f 43/270/205 1564/261/199 599/260/198 +f 44/278/209 606/279/210 1569/280/211 +f 44/278/209 1569/280/211 605/281/212 +f 44/278/209 605/281/212 1517/54/49 +f 44/278/209 1517/54/49 529/67/62 +f 44/282/209 529/283/62 1519/269/61 +f 44/282/209 1519/269/61 601/268/204 +f 44/282/209 601/268/204 1565/267/203 +f 44/282/209 1565/267/203 606/284/210 +f 45/285/213 603/286/206 1516/287/45 +f 45/285/213 1516/287/45 521/47/44 +f 45/285/213 521/47/44 1506/5/5 +f 45/285/213 1506/5/5 607/288/214 +f 45/285/213 607/288/214 1570/289/215 +f 45/285/213 1570/289/215 608/290/216 +f 45/291/213 608/292/216 1568/276/207 +f 45/291/213 1568/276/207 603/275/206 +f 46/293/217 610/294/218 1571/295/219 +f 46/293/217 1571/295/219 609/296/220 +f 46/293/217 609/296/220 1507/14/14 +f 46/293/217 1507/14/14 524/55/50 +f 46/297/217 524/298/50 1517/299/49 +f 46/297/217 1517/299/49 605/271/212 +f 46/293/217 605/281/212 1569/280/211 +f 46/293/217 1569/280/211 610/294/218 +f 47/300/221 607/288/214 1506/5/5 +f 47/300/221 1506/5/5 501/4/4 +f 47/300/221 501/4/4 1552/3/3 +f 47/300/221 1552/3/3 583/208/162 +f 47/300/221 583/208/162 1554/214/166 +f 47/300/221 1554/214/166 611/301/222 +f 47/300/221 611/301/222 1570/289/215 +f 47/300/221 1570/289/215 607/288/214 +f 48/302/223 612/303/224 1555/304/172 +f 48/302/223 1555/304/172 585/305/171 +f 48/306/223 585/220/171 1553/219/16 +f 48/306/223 1553/219/16 506/307/15 +f 48/302/223 506/15/15 1507/14/14 +f 48/302/223 1507/14/14 609/296/220 +f 48/302/223 609/296/220 1571/295/219 +f 48/302/223 1571/295/219 612/303/224 +f 49/308/225 614/309/226 1566/310/227 +f 49/308/225 1566/310/227 613/311/228 +f 49/308/225 613/311/228 1570/312/215 +f 49/308/225 1570/312/215 611/313/222 +f 49/308/225 611/313/222 1554/314/166 +f 49/308/225 1554/314/166 614/309/226 +f 50/315/229 616/316/230 1555/304/172 +f 50/315/229 1555/304/172 612/303/224 +f 50/315/229 612/303/224 1571/295/219 +f 50/315/229 1571/295/219 615/317/231 +f 50/315/229 615/317/231 1567/318/232 +f 50/315/229 1567/318/232 616/316/230 +f 51/319/233 617/320/234 1568/276/207 +f 51/319/233 1568/276/207 608/292/216 +f 51/319/233 608/292/216 1570/312/215 +f 51/319/233 1570/312/215 613/311/228 +f 51/319/233 613/311/228 1566/310/227 +f 51/319/233 1566/310/227 617/320/234 +f 52/321/235 618/322/236 1567/318/232 +f 52/321/235 1567/318/232 615/317/231 +f 52/321/235 615/317/231 1571/295/219 +f 52/321/235 1571/295/219 610/294/218 +f 52/321/235 610/294/218 1569/280/211 +f 52/321/235 1569/280/211 618/322/236 +f 53/323/237 617/320/234 1566/310/227 +f 53/323/237 1566/310/227 619/324/238 +f 53/323/237 619/324/238 1564/261/199 +f 53/323/237 1564/261/199 604/277/208 +f 53/323/237 604/277/208 1568/276/207 +f 53/323/237 1568/276/207 617/320/234 +f 54/325/239 618/322/236 1569/280/211 +f 54/325/239 1569/280/211 606/279/210 +f 54/325/239 606/279/210 1565/326/203 +f 54/325/239 1565/326/203 620/327/240 +f 54/325/239 620/327/240 1567/318/232 +f 54/325/239 1567/318/232 618/322/236 +f 55/328/241 619/324/238 1566/310/227 +f 55/328/241 1566/310/227 621/329/242 +f 55/328/241 621/329/242 1562/263/191 +f 55/328/241 1562/263/191 600/262/200 +f 55/328/241 600/262/200 1564/261/199 +f 55/328/241 1564/261/199 619/324/238 +f 56/330/243 620/327/240 1565/326/203 +f 56/330/243 1565/326/203 602/331/202 +f 56/330/243 602/331/202 1563/332/195 +f 56/330/243 1563/332/195 622/333/244 +f 56/330/243 622/333/244 1567/318/232 +f 56/330/243 1567/318/232 620/327/240 +f 57/334/245 621/329/242 1566/310/227 +f 57/334/245 1566/310/227 623/335/246 +f 57/334/245 623/335/246 1560/336/183 +f 57/334/245 1560/336/183 596/337/192 +f 57/334/245 596/337/192 1562/263/191 +f 57/334/245 1562/263/191 621/329/242 +f 58/338/247 622/333/244 1563/332/195 +f 58/338/247 1563/332/195 598/339/194 +f 58/338/247 598/339/194 1561/340/187 +f 58/338/247 1561/340/187 624/341/248 +f 58/338/247 624/341/248 1567/318/232 +f 58/338/247 1567/318/232 622/333/244 +f 59/342/249 623/335/246 1566/310/227 +f 59/342/249 1566/310/227 625/343/250 +f 59/342/249 625/343/250 1558/344/175 +f 59/342/249 1558/344/175 592/345/184 +f 59/342/249 592/345/184 1560/336/183 +f 59/342/249 1560/336/183 623/335/246 +f 60/346/251 624/341/248 1561/340/187 +f 60/346/251 1561/340/187 594/347/186 +f 60/346/251 594/347/186 1559/348/179 +f 60/346/251 1559/348/179 626/349/252 +f 60/346/251 626/349/252 1567/318/232 +f 60/346/251 1567/318/232 624/341/248 +f 61/350/253 625/343/250 1566/310/227 +f 61/350/253 1566/310/227 627/351/254 +f 61/352/253 627/353/254 1556/211/164 +f 61/352/253 1556/211/164 588/225/176 +f 61/352/253 588/225/176 1558/224/175 +f 61/352/253 1558/224/175 625/354/250 +f 62/355/255 626/349/252 1559/348/179 +f 62/355/255 1559/348/179 590/356/178 +f 62/355/255 590/356/178 1557/357/169 +f 62/355/255 1557/357/169 628/358/256 +f 62/355/255 628/358/256 1567/318/232 +f 62/355/255 1567/318/232 626/349/252 +f 63/359/257 627/351/254 1566/310/227 +f 63/359/257 1566/310/227 614/309/226 +f 63/359/257 614/309/226 1554/314/166 +f 63/359/257 1554/314/166 582/360/165 +f 63/359/257 582/360/165 1556/361/164 +f 63/359/257 1556/361/164 627/351/254 +f 64/362/258 628/358/256 1557/357/169 +f 64/362/258 1557/357/169 586/363/168 +f 64/362/258 586/363/168 1555/304/172 +f 64/362/258 1555/304/172 616/316/230 +f 64/362/258 616/316/230 1567/318/232 +f 64/362/258 1567/318/232 628/358/256 +f 65/364/259 632/365/260 1594/366/261 +f 65/364/259 1594/366/261 629/367/262 +f 65/368/259 629/369/262 1679/370/263 +f 65/368/259 1679/370/263 630/371/264 +f 65/368/259 630/371/264 1681/372/265 +f 65/368/259 1681/372/265 631/373/266 +f 65/364/259 631/374/266 1596/375/267 +f 65/364/259 1596/375/267 632/365/260 +f 66/376/268 631/373/266 1681/372/265 +f 66/376/268 1681/372/265 633/377/269 +f 66/376/268 633/377/269 1680/378/270 +f 66/376/268 1680/378/270 634/379/271 +f 66/380/268 634/381/271 1595/382/272 +f 66/380/268 1595/382/272 635/383/273 +f 66/380/268 635/383/273 1596/375/267 +f 66/380/268 1596/375/267 631/374/266 +f 67/384/274 638/385/275 1592/386/276 +f 67/384/274 1592/386/276 636/387/277 +f 67/388/274 636/389/277 1677/390/278 +f 67/388/274 1677/390/278 637/391/279 +f 67/388/274 637/391/279 1679/370/263 +f 67/388/274 1679/370/263 629/369/262 +f 67/392/274 629/367/262 1594/366/261 +f 67/392/274 1594/366/261 638/393/275 +f 68/394/280 634/379/271 1680/378/270 +f 68/394/280 1680/378/270 639/395/281 +f 68/394/280 639/395/281 1678/396/282 +f 68/394/280 1678/396/282 640/397/283 +f 68/398/280 640/399/283 1593/400/284 +f 68/398/280 1593/400/284 641/401/285 +f 68/398/280 641/401/285 1595/382/272 +f 68/398/280 1595/382/272 634/381/271 +f 69/402/286 644/403/287 1590/404/288 +f 69/402/286 1590/404/288 642/405/289 +f 69/402/286 642/405/289 1675/406/290 +f 69/402/286 1675/406/290 643/407/291 +f 69/402/286 643/407/291 1677/408/278 +f 69/402/286 1677/408/278 636/387/277 +f 69/402/286 636/387/277 1592/386/276 +f 69/402/286 1592/386/276 644/403/287 +f 70/409/292 640/397/283 1678/396/282 +f 70/409/292 1678/396/282 645/410/293 +f 70/409/292 645/410/293 1676/411/294 +f 70/409/292 1676/411/294 646/412/295 +f 70/409/292 646/412/295 1591/413/296 +f 70/409/292 1591/413/296 647/414/297 +f 70/409/292 647/414/297 1593/415/284 +f 70/409/292 1593/415/284 640/397/283 +f 71/416/298 650/417/299 1588/418/300 +f 71/416/298 1588/418/300 648/419/301 +f 71/416/298 648/419/301 1673/420/302 +f 71/416/298 1673/420/302 649/421/303 +f 71/416/298 649/421/303 1675/406/290 +f 71/416/298 1675/406/290 642/405/289 +f 71/416/298 642/405/289 1590/404/288 +f 71/416/298 1590/404/288 650/417/299 +f 72/422/304 646/412/295 1676/411/294 +f 72/422/304 1676/411/294 651/423/305 +f 72/422/304 651/423/305 1674/424/306 +f 72/422/304 1674/424/306 652/425/307 +f 72/426/304 652/427/307 1589/428/308 +f 72/426/304 1589/428/308 653/429/309 +f 72/426/304 653/429/309 1591/430/296 +f 72/426/304 1591/430/296 646/431/295 +f 73/432/310 656/433/311 1586/434/312 +f 73/432/310 1586/434/312 654/435/313 +f 73/432/310 654/435/313 1671/436/314 +f 73/432/310 1671/436/314 655/437/315 +f 73/432/310 655/437/315 1673/420/302 +f 73/432/310 1673/420/302 648/419/301 +f 73/432/310 648/419/301 1588/418/300 +f 73/432/310 1588/418/300 656/433/311 +f 74/438/316 652/425/307 1674/424/306 +f 74/438/316 1674/424/306 657/439/317 +f 74/438/316 657/439/317 1672/440/318 +f 74/438/316 1672/440/318 658/441/319 +f 74/442/316 658/443/319 1587/444/320 +f 74/442/316 1587/444/320 659/445/321 +f 74/442/316 659/445/321 1589/428/308 +f 74/442/316 1589/428/308 652/427/307 +f 75/446/322 663/447/323 1584/448/324 +f 75/446/322 1584/448/324 660/449/325 +f 75/446/322 660/449/325 1597/450/326 +f 75/446/322 1597/450/326 661/451/327 +f 75/446/322 661/451/327 1651/452/328 +f 75/446/322 1651/452/328 662/453/329 +f 75/446/322 662/453/329 1669/454/330 +f 75/446/322 1669/454/330 663/447/323 +f 76/455/331 667/456/332 1652/457/333 +f 76/455/331 1652/457/333 664/458/334 +f 76/455/331 664/458/334 1598/459/335 +f 76/455/331 1598/459/335 665/460/336 +f 76/461/331 665/462/336 1585/463/337 +f 76/461/331 1585/463/337 666/464/338 +f 76/455/331 666/465/338 1670/466/339 +f 76/455/331 1670/466/339 667/456/332 +f 77/467/340 661/451/327 1597/450/326 +f 77/467/340 1597/450/326 668/468/341 +f 77/467/340 668/468/341 1599/469/342 +f 77/467/340 1599/469/342 669/470/343 +f 77/467/340 669/470/343 1653/471/344 +f 77/467/340 1653/471/344 670/472/345 +f 77/473/340 670/474/345 1651/475/328 +f 77/473/340 1651/475/328 661/476/327 +f 78/477/346 673/478/347 1654/479/348 +f 78/477/346 1654/479/348 671/480/349 +f 78/477/346 671/480/349 1600/481/350 +f 78/477/346 1600/481/350 672/482/351 +f 78/477/346 672/482/351 1598/459/335 +f 78/477/346 1598/459/335 664/458/334 +f 78/477/346 664/458/334 1652/457/333 +f 78/477/346 1652/457/333 673/478/347 +f 79/483/352 669/470/343 1599/469/342 +f 79/483/352 1599/469/342 674/484/353 +f 79/483/352 674/484/353 1601/485/354 +f 79/483/352 1601/485/354 675/486/355 +f 79/483/352 675/486/355 1655/487/356 +f 79/483/352 1655/487/356 676/488/357 +f 79/483/352 676/488/357 1653/471/344 +f 79/483/352 1653/471/344 669/470/343 +f 80/489/358 679/490/359 1656/491/360 +f 80/489/358 1656/491/360 677/492/361 +f 80/489/358 677/492/361 1602/493/362 +f 80/489/358 1602/493/362 678/494/363 +f 80/489/358 678/494/363 1600/481/350 +f 80/489/358 1600/481/350 671/480/349 +f 80/489/358 671/480/349 1654/479/348 +f 80/489/358 1654/479/348 679/490/359 +f 81/495/364 675/486/355 1601/485/354 +f 81/495/364 1601/485/354 680/496/365 +f 81/495/364 680/496/365 1603/497/366 +f 81/495/364 1603/497/366 681/498/367 +f 81/495/364 681/498/367 1657/499/368 +f 81/495/364 1657/499/368 682/500/369 +f 81/495/364 682/500/369 1655/487/356 +f 81/495/364 1655/487/356 675/486/355 +f 82/501/370 685/502/371 1658/503/372 +f 82/501/370 1658/503/372 683/504/373 +f 82/501/370 683/504/373 1604/505/374 +f 82/501/370 1604/505/374 684/506/375 +f 82/501/370 684/506/375 1602/493/362 +f 82/501/370 1602/493/362 677/492/361 +f 82/501/370 677/492/361 1656/491/360 +f 82/501/370 1656/491/360 685/502/371 +f 83/507/376 681/508/367 1603/509/366 +f 83/507/376 1603/509/366 686/510/377 +f 83/507/376 686/510/377 1605/511/378 +f 83/507/376 1605/511/378 687/512/379 +f 83/507/376 687/512/379 1659/513/380 +f 83/507/376 1659/513/380 688/514/381 +f 83/515/376 688/516/381 1657/499/368 +f 83/515/376 1657/499/368 681/498/367 +f 84/517/382 691/518/383 1660/519/384 +f 84/517/382 1660/519/384 689/520/385 +f 84/521/382 689/522/385 1606/523/386 +f 84/521/382 1606/523/386 690/524/387 +f 84/521/382 690/524/387 1604/525/374 +f 84/521/382 1604/525/374 683/526/373 +f 84/517/382 683/504/373 1658/503/372 +f 84/517/382 1658/503/372 691/518/383 +f 85/527/388 687/512/379 1605/511/378 +f 85/527/388 1605/511/378 692/528/389 +f 85/527/388 692/528/389 1607/529/390 +f 85/527/388 1607/529/390 693/530/391 +f 85/527/388 693/530/391 1661/531/392 +f 85/527/388 1661/531/392 694/532/393 +f 85/527/388 694/532/393 1659/513/380 +f 85/527/388 1659/513/380 687/512/379 +f 86/533/394 697/534/395 1662/535/396 +f 86/533/394 1662/535/396 695/536/397 +f 86/537/394 695/538/397 1608/539/398 +f 86/537/394 1608/539/398 696/540/399 +f 86/537/394 696/540/399 1606/523/386 +f 86/537/394 1606/523/386 689/522/385 +f 86/533/394 689/520/385 1660/519/384 +f 86/533/394 1660/519/384 697/534/395 +f 87/541/400 693/530/391 1607/529/390 +f 87/541/400 1607/529/390 698/542/401 +f 87/541/400 698/542/401 1609/543/402 +f 87/541/400 1609/543/402 699/544/403 +f 87/541/400 699/544/403 1663/545/404 +f 87/541/400 1663/545/404 700/546/405 +f 87/541/400 700/546/405 1661/531/392 +f 87/541/400 1661/531/392 693/530/391 +f 88/547/406 703/548/407 1664/549/408 +f 88/547/406 1664/549/408 701/550/409 +f 88/551/406 701/552/409 1610/553/410 +f 88/551/406 1610/553/410 702/554/411 +f 88/551/406 702/554/411 1608/539/398 +f 88/551/406 1608/539/398 695/538/397 +f 88/547/406 695/536/397 1662/535/396 +f 88/547/406 1662/535/396 703/548/407 +f 89/555/412 699/544/403 1609/543/402 +f 89/555/412 1609/543/402 704/556/413 +f 89/557/412 704/558/413 1611/559/414 +f 89/557/412 1611/559/414 705/560/415 +f 89/561/412 705/562/415 1665/563/416 +f 89/561/412 1665/563/416 706/564/417 +f 89/555/412 706/565/417 1663/545/404 +f 89/555/412 1663/545/404 699/544/403 +f 90/566/418 709/567/419 1666/568/420 +f 90/566/418 1666/568/420 707/569/421 +f 90/566/418 707/569/421 1612/570/422 +f 90/566/418 1612/570/422 708/571/423 +f 90/566/418 708/571/423 1610/572/410 +f 90/566/418 1610/572/410 701/573/409 +f 90/574/418 701/550/409 1664/549/408 +f 90/574/418 1664/549/408 709/575/419 +f 91/576/424 705/560/415 1611/559/414 +f 91/576/424 1611/559/414 710/577/425 +f 91/576/424 710/577/425 1613/578/426 +f 91/576/424 1613/578/426 711/579/427 +f 91/580/424 711/581/427 1667/582/428 +f 91/580/424 1667/582/428 712/583/429 +f 91/580/424 712/583/429 1665/563/416 +f 91/580/424 1665/563/416 705/562/415 +f 92/584/430 715/585/431 1668/586/432 +f 92/584/430 1668/586/432 713/587/433 +f 92/584/430 713/587/433 1614/588/434 +f 92/584/430 1614/588/434 714/589/435 +f 92/584/430 714/589/435 1612/570/422 +f 92/584/430 1612/570/422 707/569/421 +f 92/584/430 707/569/421 1666/568/420 +f 92/584/430 1666/568/420 715/585/431 +f 93/590/436 711/579/427 1613/578/426 +f 93/590/436 1613/578/426 716/591/437 +f 93/590/436 716/591/437 1572/592/438 +f 93/590/436 1572/592/438 717/593/439 +f 93/594/436 717/595/439 1573/596/440 +f 93/594/436 1573/596/440 718/597/441 +f 93/594/436 718/597/441 1667/582/428 +f 93/594/436 1667/582/428 711/581/427 +f 94/598/442 720/599/443 1573/600/440 +f 94/598/442 1573/600/440 717/601/439 +f 94/598/442 717/601/439 1572/602/438 +f 94/598/442 1572/602/438 719/603/444 +f 94/598/442 719/603/444 1614/588/434 +f 94/598/442 1614/588/434 713/587/433 +f 94/598/442 713/587/433 1668/586/432 +f 94/598/442 1668/586/432 720/599/443 +f 95/604/445 723/605/446 1615/606/447 +f 95/604/445 1615/606/447 721/607/448 +f 95/604/445 721/607/448 1633/608/449 +f 95/604/445 1633/608/449 722/609/450 +f 95/604/445 722/609/450 1665/563/416 +f 95/604/445 1665/563/416 712/583/429 +f 95/604/445 712/583/429 1667/582/428 +f 95/604/445 1667/582/428 723/605/446 +f 96/610/451 715/611/431 1666/612/420 +f 96/610/451 1666/612/420 724/613/452 +f 96/610/451 724/613/452 1634/614/453 +f 96/610/451 1634/614/453 725/615/454 +f 96/610/451 725/615/454 1616/616/455 +f 96/610/451 1616/616/455 726/617/456 +f 96/610/451 726/617/456 1668/618/432 +f 96/610/451 1668/618/432 715/611/431 +f 97/619/457 722/609/450 1633/608/449 +f 97/619/457 1633/608/449 727/620/458 +f 97/619/457 727/620/458 1684/621/459 +f 97/619/457 1684/621/459 728/622/460 +f 97/619/457 728/622/460 1663/623/404 +f 97/619/457 1663/623/404 706/564/417 +f 97/619/457 706/564/417 1665/563/416 +f 97/619/457 1665/563/416 722/609/450 +f 98/624/461 709/575/419 1664/549/408 +f 98/624/461 1664/549/408 729/625/462 +f 98/624/461 729/625/462 1685/626/463 +f 98/624/461 1685/626/463 730/627/464 +f 98/624/461 730/627/464 1634/614/453 +f 98/624/461 1634/614/453 724/613/452 +f 98/624/461 724/613/452 1666/612/420 +f 98/624/461 1666/612/420 709/575/419 +f 99/628/465 732/629/466 1631/630/467 +f 99/628/465 1631/630/467 731/631/468 +f 99/628/465 731/631/468 1661/632/392 +f 99/628/465 1661/632/392 700/633/405 +f 99/628/465 700/633/405 1663/623/404 +f 99/628/465 1663/623/404 728/622/460 +f 99/628/465 728/622/460 1684/621/459 +f 99/628/465 1684/621/459 732/629/466 +f 100/634/469 729/625/462 1664/549/408 +f 100/634/469 1664/549/408 703/548/407 +f 100/634/469 703/548/407 1662/535/396 +f 100/634/469 1662/535/396 733/635/470 +f 100/634/469 733/635/470 1632/636/471 +f 100/634/469 1632/636/471 734/637/472 +f 100/634/469 734/637/472 1685/626/463 +f 100/634/469 1685/626/463 729/625/462 +f 101/638/473 736/639/474 1629/640/475 +f 101/638/473 1629/640/475 735/641/476 +f 101/638/473 735/641/476 1659/642/380 +f 101/638/473 1659/642/380 694/643/393 +f 101/638/473 694/643/393 1661/632/392 +f 101/638/473 1661/632/392 731/631/468 +f 101/638/473 731/631/468 1631/630/467 +f 101/638/473 1631/630/467 736/639/474 +f 102/644/477 733/635/470 1662/535/396 +f 102/644/477 1662/535/396 697/534/395 +f 102/644/477 697/534/395 1660/519/384 +f 102/644/477 1660/519/384 737/645/478 +f 102/644/477 737/645/478 1630/646/479 +f 102/644/477 1630/646/479 738/647/480 +f 102/644/477 738/647/480 1632/636/471 +f 102/644/477 1632/636/471 733/635/470 +f 103/648/481 740/649/482 1627/650/483 +f 103/648/481 1627/650/483 739/651/484 +f 103/648/481 739/651/484 1657/652/368 +f 103/648/481 1657/652/368 688/653/381 +f 103/648/481 688/653/381 1659/642/380 +f 103/648/481 1659/642/380 735/641/476 +f 103/648/481 735/641/476 1629/640/475 +f 103/648/481 1629/640/475 740/649/482 +f 104/654/485 737/645/478 1660/519/384 +f 104/654/485 1660/519/384 691/518/383 +f 104/654/485 691/518/383 1658/503/372 +f 104/654/485 1658/503/372 741/655/486 +f 104/654/485 741/655/486 1628/656/487 +f 104/654/485 1628/656/487 742/657/488 +f 104/654/485 742/657/488 1630/646/479 +f 104/654/485 1630/646/479 737/645/478 +f 105/658/489 744/659/490 1625/660/491 +f 105/658/489 1625/660/491 743/661/492 +f 105/658/489 743/661/492 1655/662/356 +f 105/658/489 1655/662/356 682/663/369 +f 105/658/489 682/663/369 1657/652/368 +f 105/658/489 1657/652/368 739/651/484 +f 105/658/489 739/651/484 1627/650/483 +f 105/658/489 1627/650/483 744/659/490 +f 106/664/493 741/655/486 1658/503/372 +f 106/664/493 1658/503/372 685/502/371 +f 106/664/493 685/502/371 1656/491/360 +f 106/664/493 1656/491/360 745/665/494 +f 106/664/493 745/665/494 1626/666/495 +f 106/664/493 1626/666/495 746/667/496 +f 106/664/493 746/667/496 1628/656/487 +f 106/664/493 1628/656/487 741/655/486 +f 107/668/497 748/669/498 1623/670/499 +f 107/668/497 1623/670/499 747/671/500 +f 107/668/497 747/671/500 1653/672/344 +f 107/668/497 1653/672/344 676/673/357 +f 107/668/497 676/673/357 1655/662/356 +f 107/668/497 1655/662/356 743/661/492 +f 107/668/497 743/661/492 1625/660/491 +f 107/668/497 1625/660/491 748/669/498 +f 108/674/501 745/665/494 1656/491/360 +f 108/674/501 1656/491/360 679/490/359 +f 108/674/501 679/490/359 1654/479/348 +f 108/674/501 1654/479/348 749/675/502 +f 108/674/501 749/675/502 1624/676/503 +f 108/674/501 1624/676/503 750/677/504 +f 108/674/501 750/677/504 1626/666/495 +f 108/674/501 1626/666/495 745/665/494 +f 109/678/505 752/679/506 1621/680/507 +f 109/678/505 1621/680/507 751/681/508 +f 109/678/505 751/681/508 1651/475/328 +f 109/678/505 1651/475/328 670/474/345 +f 109/678/505 670/474/345 1653/672/344 +f 109/678/505 1653/672/344 747/671/500 +f 109/678/505 747/671/500 1623/670/499 +f 109/678/505 1623/670/499 752/679/506 +f 110/682/509 749/675/502 1654/479/348 +f 110/682/509 1654/479/348 673/478/347 +f 110/682/509 673/478/347 1652/457/333 +f 110/682/509 1652/457/333 753/683/510 +f 110/682/509 753/683/510 1622/684/511 +f 110/682/509 1622/684/511 754/685/512 +f 110/682/509 754/685/512 1624/676/503 +f 110/682/509 1624/676/503 749/675/502 +f 111/686/513 756/687/514 1619/688/515 +f 111/686/513 1619/688/515 755/689/516 +f 111/686/513 755/689/516 1669/690/330 +f 111/686/513 1669/690/330 662/691/329 +f 111/686/513 662/691/329 1651/475/328 +f 111/686/513 1651/475/328 751/681/508 +f 111/686/513 751/681/508 1621/680/507 +f 111/686/513 1621/680/507 756/687/514 +f 112/692/517 753/683/510 1652/457/333 +f 112/692/517 1652/457/333 667/456/332 +f 112/692/517 667/456/332 1670/466/339 +f 112/692/517 1670/466/339 757/693/518 +f 112/692/517 757/693/518 1620/694/519 +f 112/692/517 1620/694/519 758/695/520 +f 112/692/517 758/695/520 1622/684/511 +f 112/692/517 1622/684/511 753/683/510 +f 113/696/521 755/689/516 1619/688/515 +f 113/696/521 1619/688/515 759/697/522 +f 113/696/521 759/697/522 1686/698/523 +f 113/696/521 1686/698/523 760/699/524 +f 113/696/521 760/699/524 1682/700/525 +f 113/696/521 1682/700/525 761/701/526 +f 113/696/521 761/701/526 1669/690/330 +f 113/696/521 1669/690/330 755/689/516 +f 114/702/527 764/703/528 1682/700/525 +f 114/702/527 1682/700/525 762/704/529 +f 114/702/527 762/704/529 1687/705/530 +f 114/702/527 1687/705/530 763/706/531 +f 114/702/527 763/706/531 1620/694/519 +f 114/702/527 1620/694/519 757/693/518 +f 114/702/527 757/693/518 1670/466/339 +f 114/702/527 1670/466/339 764/703/528 +f 115/707/532 766/708/533 1615/606/447 +f 115/707/532 1615/606/447 723/605/446 +f 115/707/532 723/605/446 1667/582/428 +f 115/707/532 1667/582/428 718/597/441 +f 115/707/532 718/597/441 1573/596/440 +f 115/707/532 1573/596/440 765/709/534 +f 115/707/532 765/709/534 1617/710/535 +f 115/707/532 1617/710/535 766/708/533 +f 116/711/536 768/712/537 1573/596/440 +f 116/711/536 1573/596/440 720/713/443 +f 116/711/536 720/713/443 1668/618/432 +f 116/711/536 1668/618/432 726/617/456 +f 116/711/536 726/617/456 1616/616/455 +f 116/711/536 1616/616/455 767/714/538 +f 116/711/536 767/714/538 1618/715/539 +f 116/711/536 1618/715/539 768/712/537 +f 117/716/540 771/717/541 1617/710/535 +f 117/716/540 1617/710/535 765/709/534 +f 117/716/540 765/709/534 1573/596/440 +f 117/716/540 1573/596/440 769/718/542 +f 117/716/540 769/718/542 1683/719/543 +f 117/716/540 1683/719/543 770/720/544 +f 117/716/540 770/720/544 1688/721/545 +f 117/716/540 1688/721/545 771/717/541 +f 118/722/546 773/723/547 1683/719/543 +f 118/722/546 1683/719/543 769/718/542 +f 118/722/546 769/718/542 1573/596/440 +f 118/722/546 1573/596/440 768/712/537 +f 118/722/546 768/712/537 1618/715/539 +f 118/722/546 1618/715/539 772/724/548 +f 118/722/546 772/724/548 1689/725/549 +f 118/722/546 1689/725/549 773/723/547 +f 119/726/550 775/727/551 1682/700/525 +f 119/726/550 1682/700/525 760/699/524 +f 119/726/550 760/699/524 1686/698/523 +f 119/726/550 1686/698/523 774/728/552 +f 119/726/550 774/728/552 1688/721/545 +f 119/726/550 1688/721/545 770/720/544 +f 119/726/550 770/720/544 1683/719/543 +f 119/726/550 1683/719/543 775/727/551 +f 120/729/553 773/723/547 1689/725/549 +f 120/729/553 1689/725/549 776/730/554 +f 120/729/553 776/730/554 1687/705/530 +f 120/729/553 1687/705/530 762/704/529 +f 120/729/553 762/704/529 1682/700/525 +f 120/729/553 1682/700/525 775/727/551 +f 120/729/553 775/727/551 1683/719/543 +f 120/729/553 1683/719/543 773/723/547 +f 121/731/555 779/732/556 1640/733/557 +f 121/731/555 1640/733/557 777/734/558 +f 121/731/555 777/734/558 1642/735/559 +f 121/731/555 1642/735/559 778/736/560 +f 121/731/555 778/736/560 1681/372/265 +f 121/731/555 1681/372/265 630/371/264 +f 121/731/555 630/371/264 1679/370/263 +f 121/731/555 1679/370/263 779/732/556 +f 122/737/561 633/377/269 1681/372/265 +f 122/737/561 1681/372/265 778/736/560 +f 122/737/561 778/736/560 1642/735/559 +f 122/737/561 1642/735/559 780/738/562 +f 122/737/561 780/738/562 1641/739/563 +f 122/737/561 1641/739/563 781/740/564 +f 122/737/561 781/740/564 1680/378/270 +f 122/737/561 1680/378/270 633/377/269 +f 123/741/565 783/742/566 1638/743/567 +f 123/741/565 1638/743/567 782/744/568 +f 123/741/565 782/744/568 1640/733/557 +f 123/741/565 1640/733/557 779/732/556 +f 123/741/565 779/732/556 1679/370/263 +f 123/741/565 1679/370/263 637/391/279 +f 123/741/565 637/391/279 1677/390/278 +f 123/741/565 1677/390/278 783/742/566 +f 124/745/569 639/395/281 1680/378/270 +f 124/745/569 1680/378/270 781/740/564 +f 124/745/569 781/740/564 1641/739/563 +f 124/745/569 1641/739/563 784/746/570 +f 124/745/569 784/746/570 1639/747/571 +f 124/745/569 1639/747/571 785/748/572 +f 124/745/569 785/748/572 1678/396/282 +f 124/745/569 1678/396/282 639/395/281 +f 125/749/573 787/750/574 1636/751/575 +f 125/749/573 1636/751/575 786/752/576 +f 125/749/573 786/752/576 1638/743/567 +f 125/749/573 1638/743/567 783/742/566 +f 125/749/573 783/742/566 1677/390/278 +f 125/749/573 1677/390/278 643/753/291 +f 125/749/573 643/753/291 1675/754/290 +f 125/749/573 1675/754/290 787/750/574 +f 126/755/577 645/410/293 1678/396/282 +f 126/755/577 1678/396/282 785/748/572 +f 126/755/577 785/748/572 1639/747/571 +f 126/755/577 1639/747/571 788/756/578 +f 126/755/577 788/756/578 1637/757/579 +f 126/755/577 1637/757/579 789/758/580 +f 126/755/577 789/758/580 1676/411/294 +f 126/755/577 1676/411/294 645/410/293 +f 127/759/581 655/760/315 1671/761/314 +f 127/759/581 1671/761/314 790/762/582 +f 127/759/581 790/762/582 1692/763/583 +f 127/759/581 1692/763/583 791/764/584 +f 127/759/581 791/764/584 1690/765/585 +f 127/759/581 1690/765/585 792/766/586 +f 127/759/581 792/766/586 1673/767/302 +f 127/759/581 1673/767/302 655/760/315 +f 128/768/587 795/769/588 1691/770/589 +f 128/768/587 1691/770/589 793/771/590 +f 128/768/587 793/771/590 1693/772/591 +f 128/768/587 1693/772/591 794/773/592 +f 128/768/587 794/773/592 1672/440/318 +f 128/768/587 1672/440/318 657/439/317 +f 128/768/587 657/439/317 1674/424/306 +f 128/768/587 1674/424/306 795/769/588 +f 129/774/593 796/775/594 1636/751/575 +f 129/774/593 1636/751/575 787/750/574 +f 129/774/593 787/750/574 1675/754/290 +f 129/774/593 1675/754/290 649/776/303 +f 129/774/593 649/776/303 1673/767/302 +f 129/774/593 1673/767/302 792/766/586 +f 129/774/593 792/766/586 1690/765/585 +f 129/774/593 1690/765/585 796/775/594 +f 130/777/595 795/769/588 1674/424/306 +f 130/777/595 1674/424/306 651/423/305 +f 130/777/595 651/423/305 1676/411/294 +f 130/777/595 1676/411/294 789/758/580 +f 130/777/595 789/758/580 1637/757/579 +f 130/777/595 1637/757/579 797/778/596 +f 130/777/595 797/778/596 1691/770/589 +f 130/777/595 1691/770/589 795/769/588 +f 131/779/597 801/780/598 1649/781/599 +f 131/779/597 1649/781/599 798/782/600 +f 131/779/597 798/782/600 1695/783/601 +f 131/779/597 1695/783/601 799/784/602 +f 131/779/597 799/784/602 1694/785/603 +f 131/779/597 1694/785/603 800/786/604 +f 131/779/597 800/786/604 1692/763/583 +f 131/779/597 1692/763/583 801/780/598 +f 132/787/605 804/788/606 1694/785/603 +f 132/787/605 1694/785/603 799/784/602 +f 132/787/605 799/784/602 1695/783/601 +f 132/787/605 1695/783/601 802/789/607 +f 132/787/605 802/789/607 1650/790/608 +f 132/787/605 1650/790/608 803/791/609 +f 132/787/605 803/791/609 1693/772/591 +f 132/787/605 1693/772/591 804/788/606 +f 133/792/610 806/793/611 1690/765/585 +f 133/792/610 1690/765/585 791/764/584 +f 133/792/610 791/764/584 1692/763/583 +f 133/792/610 1692/763/583 800/786/604 +f 133/792/610 800/786/604 1694/785/603 +f 133/792/610 1694/785/603 805/794/612 +f 133/792/610 805/794/612 1574/795/613 +f 133/792/610 1574/795/613 806/793/611 +f 134/796/614 805/794/612 1694/785/603 +f 134/796/614 1694/785/603 804/788/606 +f 134/796/614 804/788/606 1693/772/591 +f 134/796/614 1693/772/591 793/771/590 +f 134/796/614 793/771/590 1691/770/589 +f 134/796/614 1691/770/589 807/797/615 +f 134/796/614 807/797/615 1574/795/613 +f 134/796/614 1574/795/613 805/794/612 +f 135/798/616 809/799/617 1635/800/618 +f 135/798/616 1635/800/618 808/801/619 +f 135/798/616 808/801/619 1636/751/575 +f 135/798/616 1636/751/575 796/775/594 +f 135/798/616 796/775/594 1690/765/585 +f 135/798/616 1690/765/585 806/793/611 +f 135/798/616 806/793/611 1574/795/613 +f 135/798/616 1574/795/613 809/799/617 +f 136/802/620 807/797/615 1691/770/589 +f 136/802/620 1691/770/589 797/778/596 +f 136/802/620 797/778/596 1637/757/579 +f 136/802/620 1637/757/579 810/803/621 +f 136/802/620 810/803/621 1635/800/618 +f 136/802/620 1635/800/618 809/799/617 +f 136/802/620 809/799/617 1574/795/613 +f 136/802/620 1574/795/613 807/797/615 +f 137/804/622 814/805/623 1647/806/624 +f 137/804/622 1647/806/624 811/807/625 +f 137/804/622 811/807/625 1698/808/626 +f 137/804/622 1698/808/626 812/809/627 +f 137/804/622 812/809/627 1696/810/628 +f 137/804/622 1696/810/628 813/811/629 +f 137/804/622 813/811/629 1649/812/599 +f 137/804/622 1649/812/599 814/805/623 +f 138/813/630 818/814/631 1697/815/632 +f 138/813/630 1697/815/632 815/816/633 +f 138/813/630 815/816/633 1699/817/634 +f 138/813/630 1699/817/634 816/818/635 +f 138/813/630 816/818/635 1648/819/636 +f 138/813/630 1648/819/636 817/820/637 +f 138/821/630 817/822/637 1650/790/608 +f 138/821/630 1650/790/608 818/823/631 +f 139/824/638 821/825/639 1645/826/640 +f 139/824/638 1645/826/640 819/827/641 +f 139/824/638 819/827/641 1700/828/642 +f 139/824/638 1700/828/642 820/829/643 +f 139/830/638 820/831/643 1698/808/626 +f 139/830/638 1698/808/626 811/807/625 +f 139/830/638 811/807/625 1647/806/624 +f 139/830/638 1647/806/624 821/832/639 +f 140/833/644 816/834/635 1699/835/634 +f 140/833/644 1699/835/634 822/836/645 +f 140/833/644 822/836/645 1701/837/646 +f 140/833/644 1701/837/646 823/838/647 +f 140/833/644 823/838/647 1646/839/648 +f 140/833/644 1646/839/648 824/840/649 +f 140/833/644 824/840/649 1648/841/636 +f 140/833/644 1648/841/636 816/834/635 +f 141/842/650 827/843/651 1644/844/652 +f 141/842/650 1644/844/652 825/845/653 +f 141/842/650 825/845/653 1702/846/654 +f 141/842/650 1702/846/654 826/847/655 +f 141/842/650 826/847/655 1700/828/642 +f 141/842/650 1700/828/642 819/827/641 +f 141/842/650 819/827/641 1645/826/640 +f 141/842/650 1645/826/640 827/843/651 +f 142/848/656 823/838/647 1701/837/646 +f 142/848/656 1701/837/646 828/849/657 +f 142/850/656 828/851/657 1703/852/658 +f 142/850/656 1703/852/658 829/853/659 +f 142/850/656 829/853/659 1644/844/652 +f 142/850/656 1644/844/652 830/854/660 +f 142/848/656 830/855/660 1646/839/648 +f 142/848/656 1646/839/648 823/838/647 +f 143/856/661 833/857/662 1643/858/663 +f 143/856/661 1643/858/663 831/859/664 +f 143/860/661 831/861/664 1576/862/665 +f 143/860/661 1576/862/665 832/863/666 +f 143/860/661 832/863/666 1702/864/654 +f 143/860/661 1702/864/654 825/865/653 +f 143/866/661 825/867/653 1644/868/652 +f 143/866/661 1644/868/652 833/869/662 +f 144/870/667 829/853/659 1703/852/658 +f 144/870/667 1703/852/658 834/871/668 +f 144/870/667 834/871/668 1576/872/665 +f 144/870/667 1576/872/665 831/859/664 +f 144/870/667 831/859/664 1643/858/663 +f 144/870/667 1643/858/663 833/857/662 +f 144/870/667 833/857/662 1644/844/652 +f 144/870/667 1644/844/652 829/853/659 +f 145/873/669 836/874/670 1695/783/601 +f 145/873/669 1695/783/601 798/782/600 +f 145/873/669 798/782/600 1649/781/599 +f 145/873/669 1649/781/599 813/875/629 +f 145/876/669 813/811/629 1696/810/628 +f 145/876/669 1696/810/628 835/877/671 +f 145/876/669 835/877/671 1575/878/672 +f 145/876/669 1575/878/672 836/879/670 +f 146/880/673 837/881/674 1697/815/632 +f 146/880/673 1697/815/632 818/814/631 +f 146/882/673 818/823/631 1650/790/608 +f 146/882/673 1650/790/608 802/789/607 +f 146/882/673 802/789/607 1695/783/601 +f 146/882/673 1695/783/601 836/874/670 +f 146/880/673 836/883/670 1575/884/672 +f 146/880/673 1575/884/672 837/881/674 +f 147/885/675 840/886/676 1575/887/672 +f 147/885/675 1575/887/672 835/888/671 +f 147/885/675 835/888/671 1696/889/628 +f 147/885/675 1696/889/628 838/890/677 +f 147/885/675 838/890/677 1711/891/678 +f 147/885/675 1711/891/678 839/892/679 +f 147/885/675 839/892/679 1713/893/680 +f 147/885/675 1713/893/680 840/886/676 +f 148/894/681 842/895/682 1712/896/683 +f 148/894/681 1712/896/683 841/897/684 +f 148/894/681 841/897/684 1697/898/632 +f 148/894/681 1697/898/632 837/899/674 +f 148/894/681 837/899/674 1575/887/672 +f 148/894/681 1575/887/672 840/886/676 +f 148/894/681 840/886/676 1713/893/680 +f 148/894/681 1713/893/680 842/895/682 +f 149/900/685 832/863/666 1576/862/665 +f 149/900/685 1576/862/665 843/901/686 +f 149/902/685 843/903/686 1704/904/687 +f 149/902/685 1704/904/687 844/905/688 +f 149/902/685 844/905/688 1705/906/689 +f 149/902/685 1705/906/689 845/907/690 +f 149/900/685 845/908/690 1702/864/654 +f 149/900/685 1702/864/654 832/863/666 +f 150/909/691 847/910/692 1706/911/693 +f 150/909/691 1706/911/693 846/912/694 +f 150/909/691 846/912/694 1704/904/687 +f 150/909/691 1704/904/687 843/903/686 +f 150/909/691 843/903/686 1576/872/665 +f 150/909/691 1576/872/665 834/871/668 +f 150/909/691 834/871/668 1703/852/658 +f 150/909/691 1703/852/658 847/910/692 +f 151/913/695 826/847/655 1702/846/654 +f 151/913/695 1702/846/654 845/907/690 +f 151/913/695 845/907/690 1705/906/689 +f 151/913/695 1705/906/689 848/914/696 +f 151/913/695 848/914/696 1707/915/697 +f 151/913/695 1707/915/697 849/916/698 +f 151/913/695 849/916/698 1700/828/642 +f 151/913/695 1700/828/642 826/847/655 +f 152/917/699 851/918/700 1708/919/701 +f 152/917/699 1708/919/701 850/920/702 +f 152/917/699 850/920/702 1706/911/693 +f 152/917/699 1706/911/693 847/910/692 +f 152/917/699 847/910/692 1703/852/658 +f 152/917/699 1703/852/658 828/851/657 +f 152/921/699 828/849/657 1701/837/646 +f 152/921/699 1701/837/646 851/922/700 +f 153/923/703 820/829/643 1700/828/642 +f 153/923/703 1700/828/642 849/916/698 +f 153/923/703 849/916/698 1707/915/697 +f 153/923/703 1707/915/697 852/924/704 +f 153/923/703 852/924/704 1709/925/705 +f 153/923/703 1709/925/705 853/926/706 +f 153/927/703 853/928/706 1698/808/626 +f 153/927/703 1698/808/626 820/831/643 +f 154/929/707 855/930/708 1710/931/709 +f 154/929/707 1710/931/709 854/932/710 +f 154/929/707 854/932/710 1708/933/701 +f 154/929/707 1708/933/701 851/934/700 +f 154/935/707 851/922/700 1701/837/646 +f 154/935/707 1701/837/646 822/836/645 +f 154/935/707 822/836/645 1699/835/634 +f 154/935/707 1699/835/634 855/936/708 +f 155/937/711 812/809/627 1698/808/626 +f 155/937/711 1698/808/626 853/928/706 +f 155/938/711 853/939/706 1709/940/705 +f 155/938/711 1709/940/705 856/941/712 +f 155/938/711 856/941/712 1711/891/678 +f 155/938/711 1711/891/678 838/890/677 +f 155/937/711 838/942/677 1696/810/628 +f 155/937/711 1696/810/628 812/809/627 +f 156/943/713 841/897/684 1712/896/683 +f 156/943/713 1712/896/683 857/944/714 +f 156/943/713 857/944/714 1710/931/709 +f 156/943/713 1710/931/709 855/930/708 +f 156/943/713 855/930/708 1699/945/634 +f 156/943/713 1699/945/634 815/946/633 +f 156/943/713 815/946/633 1697/898/632 +f 156/943/713 1697/898/632 841/897/684 +f 157/947/715 844/948/688 1704/949/687 +f 157/947/715 1704/949/687 858/950/716 +f 157/947/715 858/950/716 1709/940/705 +f 157/947/715 1709/940/705 852/951/704 +f 157/952/715 852/924/704 1707/915/697 +f 157/952/715 1707/915/697 848/914/696 +f 157/947/715 848/953/696 1705/954/689 +f 157/947/715 1705/954/689 844/948/688 +f 158/955/717 850/956/702 1708/933/701 +f 158/955/717 1708/933/701 854/932/710 +f 158/955/717 854/932/710 1710/931/709 +f 158/955/717 1710/931/709 859/957/718 +f 158/955/717 859/957/718 1704/949/687 +f 158/955/717 1704/949/687 846/958/694 +f 158/959/717 846/912/694 1706/911/693 +f 158/959/717 1706/911/693 850/920/702 +f 159/960/719 858/950/716 1704/949/687 +f 159/960/719 1704/949/687 860/961/720 +f 159/960/719 860/961/720 1713/893/680 +f 159/960/719 1713/893/680 839/892/679 +f 159/960/719 839/892/679 1711/891/678 +f 159/960/719 1711/891/678 856/941/712 +f 159/960/719 856/941/712 1709/940/705 +f 159/960/719 1709/940/705 858/950/716 +f 160/962/721 857/944/714 1712/896/683 +f 160/962/721 1712/896/683 842/895/682 +f 160/962/721 842/895/682 1713/893/680 +f 160/962/721 1713/893/680 860/961/720 +f 160/962/721 860/961/720 1704/949/687 +f 160/962/721 1704/949/687 859/957/718 +f 160/962/721 859/957/718 1710/931/709 +f 160/962/721 1710/931/709 857/944/714 +f 161/963/722 862/964/723 1644/965/652 +f 161/963/722 1644/965/652 827/966/651 +f 161/963/722 827/966/651 1645/967/640 +f 161/963/722 1645/967/640 861/968/724 +f 161/963/722 861/968/724 1669/690/330 +f 161/963/722 1669/690/330 761/701/526 +f 161/963/722 761/701/526 1682/700/525 +f 161/963/722 1682/700/525 862/964/723 +f 162/969/725 764/703/528 1670/466/339 +f 162/969/725 1670/466/339 863/970/726 +f 162/969/725 863/970/726 1646/971/648 +f 162/969/725 1646/971/648 830/972/660 +f 162/969/725 830/972/660 1644/965/652 +f 162/969/725 1644/965/652 862/964/723 +f 162/969/725 862/964/723 1682/700/525 +f 162/969/725 1682/700/525 764/703/528 +f 163/973/727 861/968/724 1645/967/640 +f 163/973/727 1645/967/640 821/974/639 +f 163/973/727 821/974/639 1647/975/624 +f 163/973/727 1647/975/624 864/976/728 +f 163/977/727 864/978/728 1716/979/729 +f 163/977/727 1716/979/729 865/980/730 +f 163/973/727 865/981/730 1669/690/330 +f 163/973/727 1669/690/330 861/968/724 +f 164/982/731 867/983/732 1717/984/733 +f 164/982/731 1717/984/733 866/985/734 +f 164/982/731 866/985/734 1648/986/636 +f 164/982/731 1648/986/636 824/987/649 +f 164/982/731 824/987/649 1646/971/648 +f 164/982/731 1646/971/648 863/970/726 +f 164/982/731 863/970/726 1670/466/339 +f 164/982/731 1670/466/339 867/983/732 +f 165/988/735 864/978/728 1647/806/624 +f 165/988/735 1647/806/624 814/805/623 +f 165/989/735 814/990/623 1649/781/599 +f 165/989/735 1649/781/599 868/991/736 +f 165/988/735 868/992/736 1718/993/737 +f 165/988/735 1718/993/737 869/994/738 +f 165/988/735 869/994/738 1716/979/729 +f 165/988/735 1716/979/729 864/978/728 +f 166/995/739 871/996/740 1719/997/741 +f 166/995/739 1719/997/741 870/998/742 +f 166/995/739 870/998/742 1650/790/608 +f 166/995/739 1650/790/608 817/822/637 +f 166/995/739 817/822/637 1648/986/636 +f 166/995/739 1648/986/636 866/985/734 +f 166/995/739 866/985/734 1717/984/733 +f 166/995/739 1717/984/733 871/996/740 +f 167/999/743 868/991/736 1649/781/599 +f 167/999/743 1649/781/599 801/780/598 +f 167/999/743 801/780/598 1692/763/583 +f 167/999/743 1692/763/583 790/762/582 +f 167/999/743 790/762/582 1671/761/314 +f 167/999/743 1671/761/314 872/1000/744 +f 167/1001/743 872/1002/744 1718/1003/737 +f 167/1001/743 1718/1003/737 868/1004/736 +f 168/1005/745 873/1006/746 1672/440/318 +f 168/1005/745 1672/440/318 794/773/592 +f 168/1005/745 794/773/592 1693/772/591 +f 168/1005/745 1693/772/591 803/791/609 +f 168/1005/745 803/791/609 1650/790/608 +f 168/1005/745 1650/790/608 870/998/742 +f 168/1005/745 870/998/742 1719/997/741 +f 168/1005/745 1719/997/741 873/1006/746 +f 169/1007/747 654/435/313 1586/434/312 +f 169/1007/747 1586/434/312 874/1008/748 +f 169/1009/747 874/1010/748 1714/1011/749 +f 169/1009/747 1714/1011/749 875/1012/750 +f 169/1009/747 875/1012/750 1718/1003/737 +f 169/1009/747 1718/1003/737 872/1002/744 +f 169/1009/747 872/1002/744 1671/1013/314 +f 169/1009/747 1671/1013/314 654/1014/313 +f 170/1015/751 873/1016/746 1719/1017/741 +f 170/1015/751 1719/1017/741 876/1018/752 +f 170/1015/751 876/1018/752 1715/1019/753 +f 170/1015/751 1715/1019/753 877/1020/754 +f 170/1015/751 877/1020/754 1587/444/320 +f 170/1015/751 1587/444/320 658/443/319 +f 170/1015/751 658/443/319 1672/1021/318 +f 170/1015/751 1672/1021/318 873/1016/746 +f 171/1022/755 875/1023/750 1714/1024/749 +f 171/1022/755 1714/1024/749 878/1025/756 +f 171/1022/755 878/1025/756 1720/1026/757 +f 171/1022/755 1720/1026/757 879/1027/758 +f 171/1022/755 879/1027/758 1716/979/729 +f 171/1022/755 1716/979/729 869/994/738 +f 171/1022/755 869/994/738 1718/993/737 +f 171/1022/755 1718/993/737 875/1023/750 +f 172/1028/759 871/1029/740 1717/1030/733 +f 172/1028/759 1717/1030/733 880/1031/760 +f 172/1028/759 880/1031/760 1721/1032/761 +f 172/1028/759 1721/1032/761 881/1033/762 +f 172/1028/759 881/1033/762 1715/1019/753 +f 172/1028/759 1715/1019/753 876/1018/752 +f 172/1028/759 876/1018/752 1719/1017/741 +f 172/1028/759 1719/1017/741 871/1029/740 +f 173/1034/763 882/1035/764 1584/448/324 +f 173/1034/763 1584/448/324 663/447/323 +f 173/1034/763 663/447/323 1669/454/330 +f 173/1034/763 1669/454/330 865/980/730 +f 173/1034/763 865/980/730 1716/979/729 +f 173/1034/763 1716/979/729 879/1027/758 +f 173/1034/763 879/1027/758 1720/1026/757 +f 173/1034/763 1720/1026/757 882/1035/764 +f 174/1036/765 880/1031/760 1717/1030/733 +f 174/1036/765 1717/1030/733 867/1037/732 +f 174/1038/765 867/983/732 1670/466/339 +f 174/1038/765 1670/466/339 666/465/338 +f 174/1038/765 666/465/338 1585/1039/337 +f 174/1038/765 1585/1039/337 883/1040/766 +f 174/1036/765 883/1041/766 1721/1032/761 +f 174/1036/765 1721/1032/761 880/1031/760 +f 175/1042/767 886/1043/768 1636/751/575 +f 175/1042/767 1636/751/575 808/801/619 +f 175/1042/767 808/801/619 1635/800/618 +f 175/1042/767 1635/800/618 884/1044/769 +f 175/1042/767 884/1044/769 1577/1045/770 +f 175/1042/767 1577/1045/770 885/1046/771 +f 175/1042/767 885/1046/771 1727/1047/772 +f 175/1042/767 1727/1047/772 886/1043/768 +f 176/1048/773 888/1049/774 1577/1045/770 +f 176/1048/773 1577/1045/770 884/1044/769 +f 176/1048/773 884/1044/769 1635/800/618 +f 176/1048/773 1635/800/618 810/803/621 +f 176/1048/773 810/803/621 1637/757/579 +f 176/1048/773 1637/757/579 887/1050/775 +f 176/1048/773 887/1050/775 1728/1051/776 +f 176/1048/773 1728/1051/776 888/1049/774 +f 177/1052/777 890/1053/778 1638/743/567 +f 177/1052/777 1638/743/567 786/752/576 +f 177/1052/777 786/752/576 1636/751/575 +f 177/1052/777 1636/751/575 886/1043/768 +f 177/1052/777 886/1043/768 1727/1047/772 +f 177/1052/777 1727/1047/772 889/1054/779 +f 177/1052/777 889/1054/779 1725/1055/780 +f 177/1052/777 1725/1055/780 890/1053/778 +f 178/1056/781 892/1057/782 1728/1058/776 +f 178/1056/781 1728/1058/776 887/1059/775 +f 178/1060/781 887/1050/775 1637/757/579 +f 178/1060/781 1637/757/579 788/756/578 +f 178/1060/781 788/756/578 1639/747/571 +f 178/1060/781 1639/747/571 891/1061/783 +f 178/1056/781 891/1062/783 1726/1063/784 +f 178/1056/781 1726/1063/784 892/1057/782 +f 179/1064/785 894/1065/786 1640/733/557 +f 179/1064/785 1640/733/557 782/744/568 +f 179/1064/785 782/744/568 1638/743/567 +f 179/1064/785 1638/743/567 890/1053/778 +f 179/1064/785 890/1053/778 1725/1055/780 +f 179/1064/785 1725/1055/780 893/1066/787 +f 179/1067/785 893/1068/787 1723/1069/788 +f 179/1067/785 1723/1069/788 894/1070/786 +f 180/1071/789 896/1072/790 1726/1073/784 +f 180/1071/789 1726/1073/784 891/1074/783 +f 180/1075/789 891/1061/783 1639/747/571 +f 180/1075/789 1639/747/571 784/746/570 +f 180/1075/789 784/746/570 1641/739/563 +f 180/1075/789 1641/739/563 895/1076/791 +f 180/1071/789 895/1077/791 1724/1078/792 +f 180/1071/789 1724/1078/792 896/1072/790 +f 181/1079/793 898/1080/794 1642/735/559 +f 181/1079/793 1642/735/559 777/734/558 +f 181/1079/793 777/734/558 1640/733/557 +f 181/1079/793 1640/733/557 894/1065/786 +f 181/1081/793 894/1082/786 1723/1083/788 +f 181/1081/793 1723/1083/788 897/1084/795 +f 181/1081/793 897/1084/795 1722/1085/796 +f 181/1081/793 1722/1085/796 898/1086/794 +f 182/1087/797 899/1088/798 1724/1078/792 +f 182/1087/797 1724/1078/792 895/1077/791 +f 182/1089/797 895/1076/791 1641/739/563 +f 182/1089/797 1641/739/563 780/738/562 +f 182/1089/797 780/738/562 1642/735/559 +f 182/1089/797 1642/735/559 898/1080/794 +f 182/1087/797 898/1086/794 1722/1085/796 +f 182/1087/797 1722/1085/796 899/1088/798 +f 183/1090/799 902/1091/800 1722/1085/796 +f 183/1090/799 1722/1085/796 897/1084/795 +f 183/1092/799 897/1093/795 1723/1069/788 +f 183/1092/799 1723/1069/788 900/1094/801 +f 183/1090/799 900/1095/801 1734/1096/802 +f 183/1090/799 1734/1096/802 901/1097/803 +f 183/1090/799 901/1097/803 1736/1098/804 +f 183/1090/799 1736/1098/804 902/1091/800 +f 184/1099/805 904/1100/806 1735/1101/807 +f 184/1099/805 1735/1101/807 903/1102/808 +f 184/1099/805 903/1102/808 1724/1078/792 +f 184/1099/805 1724/1078/792 899/1088/798 +f 184/1099/805 899/1088/798 1722/1085/796 +f 184/1099/805 1722/1085/796 902/1091/800 +f 184/1099/805 902/1091/800 1736/1098/804 +f 184/1099/805 1736/1098/804 904/1100/806 +f 185/1103/809 900/1094/801 1723/1069/788 +f 185/1103/809 1723/1069/788 893/1068/787 +f 185/1103/809 893/1068/787 1725/1104/780 +f 185/1103/809 1725/1104/780 905/1105/810 +f 185/1103/809 905/1105/810 1732/1106/811 +f 185/1103/809 1732/1106/811 906/1107/812 +f 185/1103/809 906/1107/812 1734/1108/802 +f 185/1103/809 1734/1108/802 900/1094/801 +f 186/1109/813 908/1110/814 1733/1111/815 +f 186/1109/813 1733/1111/815 907/1112/816 +f 186/1109/813 907/1112/816 1726/1073/784 +f 186/1109/813 1726/1073/784 896/1072/790 +f 186/1109/813 896/1072/790 1724/1078/792 +f 186/1109/813 1724/1078/792 903/1102/808 +f 186/1109/813 903/1102/808 1735/1101/807 +f 186/1109/813 1735/1101/807 908/1110/814 +f 187/1113/817 905/1105/810 1725/1104/780 +f 187/1113/817 1725/1104/780 889/1114/779 +f 187/1115/817 889/1116/779 1727/1117/772 +f 187/1115/817 1727/1117/772 909/1118/818 +f 187/1115/817 909/1118/818 1730/1119/819 +f 187/1115/817 1730/1119/819 910/1120/820 +f 187/1113/817 910/1121/820 1732/1106/811 +f 187/1113/817 1732/1106/811 905/1105/810 +f 188/1122/821 912/1123/822 1731/1124/823 +f 188/1122/821 1731/1124/823 911/1125/824 +f 188/1122/821 911/1125/824 1728/1058/776 +f 188/1122/821 1728/1058/776 892/1057/782 +f 188/1122/821 892/1057/782 1726/1063/784 +f 188/1122/821 1726/1063/784 907/1126/816 +f 188/1122/821 907/1126/816 1733/1127/815 +f 188/1122/821 1733/1127/815 912/1123/822 +f 189/1128/825 909/1118/818 1727/1117/772 +f 189/1128/825 1727/1117/772 885/1129/771 +f 189/1128/825 885/1129/771 1577/1130/770 +f 189/1128/825 1577/1130/770 913/1131/826 +f 189/1132/825 913/1133/826 1729/1134/827 +f 189/1132/825 1729/1134/827 914/1135/828 +f 189/1132/825 914/1135/828 1730/1136/819 +f 189/1132/825 1730/1136/819 909/1137/818 +f 190/1138/829 915/1139/830 1729/1134/827 +f 190/1138/829 1729/1134/827 913/1133/826 +f 190/1140/829 913/1131/826 1577/1130/770 +f 190/1140/829 1577/1130/770 888/1141/774 +f 190/1140/829 888/1141/774 1728/1142/776 +f 190/1140/829 1728/1142/776 911/1143/824 +f 190/1138/829 911/1144/824 1731/1145/823 +f 190/1138/829 1731/1145/823 915/1139/830 +f 191/1146/831 914/1135/828 1729/1134/827 +f 191/1146/831 1729/1134/827 916/1147/832 +f 191/1146/831 916/1147/832 1736/1148/804 +f 191/1146/831 1736/1148/804 901/1149/803 +f 191/1146/831 901/1149/803 1734/1150/802 +f 191/1146/831 1734/1150/802 917/1151/833 +f 191/1146/831 917/1151/833 1730/1136/819 +f 191/1146/831 1730/1136/819 914/1135/828 +f 192/1152/834 918/1153/835 1735/1154/807 +f 192/1152/834 1735/1154/807 904/1155/806 +f 192/1152/834 904/1155/806 1736/1148/804 +f 192/1152/834 1736/1148/804 916/1147/832 +f 192/1152/834 916/1147/832 1729/1134/827 +f 192/1152/834 1729/1134/827 915/1139/830 +f 192/1152/834 915/1139/830 1731/1145/823 +f 192/1152/834 1731/1145/823 918/1153/835 +f 193/1156/836 910/1157/820 1730/1136/819 +f 193/1156/836 1730/1136/819 917/1151/833 +f 193/1156/836 917/1151/833 1734/1150/802 +f 193/1156/836 1734/1150/802 906/1158/812 +f 193/1159/836 906/1107/812 1732/1106/811 +f 193/1159/836 1732/1106/811 910/1121/820 +f 194/1160/837 912/1123/822 1733/1127/815 +f 194/1160/837 1733/1127/815 908/1161/814 +f 194/1162/837 908/1163/814 1735/1154/807 +f 194/1162/837 1735/1154/807 918/1153/835 +f 194/1162/837 918/1153/835 1731/1145/823 +f 194/1162/837 1731/1145/823 912/1164/822 +f 195/1165/838 921/1166/839 1688/721/545 +f 195/1165/838 1688/721/545 774/728/552 +f 195/1165/838 774/728/552 1686/698/523 +f 195/1165/838 1686/698/523 919/1167/840 +f 195/1165/838 919/1167/840 1739/1168/841 +f 195/1165/838 1739/1168/841 920/1169/842 +f 195/1165/838 920/1169/842 1737/1170/843 +f 195/1165/838 1737/1170/843 921/1166/839 +f 196/1171/844 924/1172/845 1740/1173/846 +f 196/1171/844 1740/1173/846 922/1174/847 +f 196/1171/844 922/1174/847 1687/705/530 +f 196/1171/844 1687/705/530 776/730/554 +f 196/1171/844 776/730/554 1689/725/549 +f 196/1171/844 1689/725/549 923/1175/848 +f 196/1171/844 923/1175/848 1738/1176/849 +f 196/1171/844 1738/1176/849 924/1172/845 +f 197/1177/850 926/1178/851 1617/710/535 +f 197/1177/850 1617/710/535 771/717/541 +f 197/1177/850 771/717/541 1688/721/545 +f 197/1177/850 1688/721/545 921/1166/839 +f 197/1177/850 921/1166/839 1737/1170/843 +f 197/1177/850 1737/1170/843 925/1179/852 +f 197/1177/850 925/1179/852 1759/1180/853 +f 197/1177/850 1759/1180/853 926/1178/851 +f 198/1181/854 928/1182/855 1738/1176/849 +f 198/1181/854 1738/1176/849 923/1175/848 +f 198/1181/854 923/1175/848 1689/725/549 +f 198/1181/854 1689/725/549 772/724/548 +f 198/1181/854 772/724/548 1618/715/539 +f 198/1181/854 1618/715/539 927/1183/856 +f 198/1181/854 927/1183/856 1760/1184/857 +f 198/1181/854 1760/1184/857 928/1182/855 +f 199/1185/858 930/1186/859 1615/606/447 +f 199/1185/858 1615/606/447 766/708/533 +f 199/1185/858 766/708/533 1617/710/535 +f 199/1185/858 1617/710/535 926/1178/851 +f 199/1185/858 926/1178/851 1759/1180/853 +f 199/1185/858 1759/1180/853 929/1187/860 +f 199/1185/858 929/1187/860 1761/1188/861 +f 199/1185/858 1761/1188/861 930/1186/859 +f 200/1189/862 932/1190/863 1760/1184/857 +f 200/1189/862 1760/1184/857 927/1183/856 +f 200/1189/862 927/1183/856 1618/715/539 +f 200/1189/862 1618/715/539 767/714/538 +f 200/1189/862 767/714/538 1616/616/455 +f 200/1189/862 1616/616/455 931/1191/864 +f 200/1189/862 931/1191/864 1762/1192/865 +f 200/1189/862 1762/1192/865 932/1190/863 +f 201/1193/866 919/1167/840 1686/698/523 +f 201/1193/866 1686/698/523 759/697/522 +f 201/1193/866 759/697/522 1619/688/515 +f 201/1193/866 1619/688/515 933/1194/867 +f 201/1193/866 933/1194/867 1757/1195/868 +f 201/1193/866 1757/1195/868 934/1196/869 +f 201/1193/866 934/1196/869 1739/1168/841 +f 201/1193/866 1739/1168/841 919/1167/840 +f 202/1197/870 936/1198/871 1758/1199/872 +f 202/1197/870 1758/1199/872 935/1200/873 +f 202/1197/870 935/1200/873 1620/694/519 +f 202/1197/870 1620/694/519 763/706/531 +f 202/1197/870 763/706/531 1687/705/530 +f 202/1197/870 1687/705/530 922/1174/847 +f 202/1197/870 922/1174/847 1740/1173/846 +f 202/1197/870 1740/1173/846 936/1198/871 +f 203/1201/874 933/1194/867 1619/688/515 +f 203/1201/874 1619/688/515 756/687/514 +f 203/1201/874 756/687/514 1621/680/507 +f 203/1201/874 1621/680/507 937/1202/875 +f 203/1201/874 937/1202/875 1755/1203/876 +f 203/1201/874 1755/1203/876 938/1204/877 +f 203/1201/874 938/1204/877 1757/1195/868 +f 203/1201/874 1757/1195/868 933/1194/867 +f 204/1205/878 940/1206/879 1756/1207/880 +f 204/1205/878 1756/1207/880 939/1208/881 +f 204/1205/878 939/1208/881 1622/684/511 +f 204/1205/878 1622/684/511 758/695/520 +f 204/1205/878 758/695/520 1620/694/519 +f 204/1205/878 1620/694/519 935/1200/873 +f 204/1205/878 935/1200/873 1758/1199/872 +f 204/1205/878 1758/1199/872 940/1206/879 +f 205/1209/882 937/1202/875 1621/680/507 +f 205/1209/882 1621/680/507 752/679/506 +f 205/1209/882 752/679/506 1623/670/499 +f 205/1209/882 1623/670/499 941/1210/883 +f 205/1209/882 941/1210/883 1753/1211/884 +f 205/1209/882 1753/1211/884 942/1212/885 +f 205/1209/882 942/1212/885 1755/1203/876 +f 205/1209/882 1755/1203/876 937/1202/875 +f 206/1213/886 944/1214/887 1754/1215/888 +f 206/1213/886 1754/1215/888 943/1216/889 +f 206/1213/886 943/1216/889 1624/676/503 +f 206/1213/886 1624/676/503 754/685/512 +f 206/1213/886 754/685/512 1622/684/511 +f 206/1213/886 1622/684/511 939/1208/881 +f 206/1213/886 939/1208/881 1756/1207/880 +f 206/1213/886 1756/1207/880 944/1214/887 +f 207/1217/890 941/1218/883 1623/1219/499 +f 207/1217/890 1623/1219/499 748/1220/498 +f 207/1221/890 748/669/498 1625/660/491 +f 207/1221/890 1625/660/491 945/1222/891 +f 207/1221/890 945/1222/891 1751/1223/892 +f 207/1221/890 1751/1223/892 946/1224/893 +f 207/1217/890 946/1225/893 1753/1226/884 +f 207/1217/890 1753/1226/884 941/1218/883 +f 208/1227/894 948/1228/895 1752/1229/896 +f 208/1227/894 1752/1229/896 947/1230/897 +f 208/1227/894 947/1230/897 1626/666/495 +f 208/1227/894 1626/666/495 750/677/504 +f 208/1227/894 750/677/504 1624/676/503 +f 208/1227/894 1624/676/503 943/1216/889 +f 208/1227/894 943/1216/889 1754/1215/888 +f 208/1227/894 1754/1215/888 948/1228/895 +f 209/1231/898 945/1222/891 1625/660/491 +f 209/1231/898 1625/660/491 744/659/490 +f 209/1231/898 744/659/490 1627/650/483 +f 209/1231/898 1627/650/483 949/1232/899 +f 209/1231/898 949/1232/899 1749/1233/900 +f 209/1231/898 1749/1233/900 950/1234/901 +f 209/1231/898 950/1234/901 1751/1223/892 +f 209/1231/898 1751/1223/892 945/1222/891 +f 210/1235/902 952/1236/903 1750/1237/904 +f 210/1235/902 1750/1237/904 951/1238/905 +f 210/1235/902 951/1238/905 1628/656/487 +f 210/1235/902 1628/656/487 746/667/496 +f 210/1235/902 746/667/496 1626/666/495 +f 210/1235/902 1626/666/495 947/1230/897 +f 210/1235/902 947/1230/897 1752/1229/896 +f 210/1235/902 1752/1229/896 952/1236/903 +f 211/1239/906 949/1232/899 1627/650/483 +f 211/1239/906 1627/650/483 740/649/482 +f 211/1239/906 740/649/482 1629/640/475 +f 211/1239/906 1629/640/475 953/1240/907 +f 211/1239/906 953/1240/907 1747/1241/908 +f 211/1239/906 1747/1241/908 954/1242/909 +f 211/1239/906 954/1242/909 1749/1233/900 +f 211/1239/906 1749/1233/900 949/1232/899 +f 212/1243/910 956/1244/911 1748/1245/912 +f 212/1243/910 1748/1245/912 955/1246/913 +f 212/1243/910 955/1246/913 1630/646/479 +f 212/1243/910 1630/646/479 742/657/488 +f 212/1243/910 742/657/488 1628/656/487 +f 212/1243/910 1628/656/487 951/1238/905 +f 212/1243/910 951/1238/905 1750/1237/904 +f 212/1243/910 1750/1237/904 956/1244/911 +f 213/1247/914 953/1240/907 1629/640/475 +f 213/1247/914 1629/640/475 736/639/474 +f 213/1247/914 736/639/474 1631/630/467 +f 213/1247/914 1631/630/467 957/1248/915 +f 213/1249/914 957/1250/915 1745/1251/916 +f 213/1249/914 1745/1251/916 958/1252/917 +f 213/1249/914 958/1252/917 1747/1253/908 +f 213/1249/914 1747/1253/908 953/1254/907 +f 214/1255/918 960/1256/919 1746/1257/920 +f 214/1255/918 1746/1257/920 959/1258/921 +f 214/1259/918 959/1260/921 1632/636/471 +f 214/1259/918 1632/636/471 738/647/480 +f 214/1259/918 738/647/480 1630/646/479 +f 214/1259/918 1630/646/479 955/1246/913 +f 214/1259/918 955/1246/913 1748/1245/912 +f 214/1259/918 1748/1245/912 960/1261/919 +f 215/1262/922 957/1248/915 1631/630/467 +f 215/1262/922 1631/630/467 732/629/466 +f 215/1262/922 732/629/466 1684/621/459 +f 215/1262/922 1684/621/459 961/1263/923 +f 215/1264/922 961/1265/923 1741/1266/924 +f 215/1264/922 1741/1266/924 962/1267/925 +f 215/1264/922 962/1267/925 1745/1251/916 +f 215/1264/922 1745/1251/916 957/1250/915 +f 216/1268/926 964/1269/927 1742/1270/928 +f 216/1268/926 1742/1270/928 963/1271/929 +f 216/1268/926 963/1271/929 1685/626/463 +f 216/1268/926 1685/626/463 734/637/472 +f 216/1268/926 734/637/472 1632/636/471 +f 216/1268/926 1632/636/471 959/1260/921 +f 216/1272/926 959/1273/921 1746/1274/920 +f 216/1272/926 1746/1274/920 964/1275/927 +f 217/1276/930 961/1263/923 1684/621/459 +f 217/1276/930 1684/621/459 727/620/458 +f 217/1276/930 727/620/458 1633/608/449 +f 217/1276/930 1633/608/449 965/1277/931 +f 217/1276/930 965/1277/931 1743/1278/932 +f 217/1276/930 1743/1278/932 966/1279/933 +f 217/1276/930 966/1279/933 1741/1280/924 +f 217/1276/930 1741/1280/924 961/1263/923 +f 218/1281/934 968/1282/935 1744/1283/936 +f 218/1281/934 1744/1283/936 967/1284/937 +f 218/1281/934 967/1284/937 1634/614/453 +f 218/1281/934 1634/614/453 730/627/464 +f 218/1281/934 730/627/464 1685/626/463 +f 218/1281/934 1685/626/463 963/1271/929 +f 218/1281/934 963/1271/929 1742/1270/928 +f 218/1281/934 1742/1270/928 968/1282/935 +f 219/1285/938 965/1277/931 1633/608/449 +f 219/1285/938 1633/608/449 721/607/448 +f 219/1285/938 721/607/448 1615/606/447 +f 219/1285/938 1615/606/447 930/1186/859 +f 219/1285/938 930/1186/859 1761/1188/861 +f 219/1285/938 1761/1188/861 969/1286/939 +f 219/1285/938 969/1286/939 1743/1278/932 +f 219/1285/938 1743/1278/932 965/1277/931 +f 220/1287/940 970/1288/941 1762/1192/865 +f 220/1287/940 1762/1192/865 931/1191/864 +f 220/1287/940 931/1191/864 1616/616/455 +f 220/1287/940 1616/616/455 725/615/454 +f 220/1287/940 725/615/454 1634/614/453 +f 220/1287/940 1634/614/453 967/1284/937 +f 220/1287/940 967/1284/937 1744/1283/936 +f 220/1287/940 1744/1283/936 970/1288/941 +f 221/1289/942 973/1290/943 1743/1278/932 +f 221/1289/942 1743/1278/932 969/1286/939 +f 221/1289/942 969/1286/939 1761/1188/861 +f 221/1289/942 1761/1188/861 971/1291/944 +f 221/1289/942 971/1291/944 1763/1292/945 +f 221/1289/942 1763/1292/945 972/1293/946 +f 221/1289/942 972/1293/946 1781/1294/947 +f 221/1289/942 1781/1294/947 973/1290/943 +f 222/1295/948 976/1296/949 1764/1297/950 +f 222/1295/948 1764/1297/950 974/1298/951 +f 222/1295/948 974/1298/951 1762/1192/865 +f 222/1295/948 1762/1192/865 970/1288/941 +f 222/1295/948 970/1288/941 1744/1283/936 +f 222/1295/948 1744/1283/936 975/1299/952 +f 222/1295/948 975/1299/952 1782/1300/953 +f 222/1295/948 1782/1300/953 976/1296/949 +f 223/1301/954 978/1302/955 1741/1280/924 +f 223/1301/954 1741/1280/924 966/1279/933 +f 223/1301/954 966/1279/933 1743/1278/932 +f 223/1301/954 1743/1278/932 973/1290/943 +f 223/1301/954 973/1290/943 1781/1294/947 +f 223/1301/954 1781/1294/947 977/1303/956 +f 223/1301/954 977/1303/956 1783/1304/957 +f 223/1301/954 1783/1304/957 978/1302/955 +f 224/1305/958 980/1306/959 1782/1300/953 +f 224/1305/958 1782/1300/953 975/1299/952 +f 224/1305/958 975/1299/952 1744/1283/936 +f 224/1305/958 1744/1283/936 968/1282/935 +f 224/1305/958 968/1282/935 1742/1270/928 +f 224/1305/958 1742/1270/928 979/1307/960 +f 224/1305/958 979/1307/960 1784/1308/961 +f 224/1305/958 1784/1308/961 980/1306/959 +f 225/1309/962 982/1310/963 1745/1311/916 +f 225/1309/962 1745/1311/916 962/1312/925 +f 225/1309/962 962/1312/925 1741/1280/924 +f 225/1309/962 1741/1280/924 978/1302/955 +f 225/1309/962 978/1302/955 1783/1304/957 +f 225/1309/962 1783/1304/957 981/1313/964 +f 225/1309/962 981/1313/964 1779/1314/965 +f 225/1309/962 1779/1314/965 982/1310/963 +f 226/1315/966 984/1316/967 1784/1308/961 +f 226/1315/966 1784/1308/961 979/1307/960 +f 226/1315/966 979/1307/960 1742/1270/928 +f 226/1315/966 1742/1270/928 964/1269/927 +f 226/1315/966 964/1269/927 1746/1317/920 +f 226/1315/966 1746/1317/920 983/1318/968 +f 226/1315/966 983/1318/968 1780/1319/969 +f 226/1315/966 1780/1319/969 984/1316/967 +f 227/1320/970 986/1321/971 1747/1241/908 +f 227/1320/970 1747/1241/908 958/1322/917 +f 227/1320/970 958/1322/917 1745/1311/916 +f 227/1320/970 1745/1311/916 982/1310/963 +f 227/1320/970 982/1310/963 1779/1314/965 +f 227/1320/970 1779/1314/965 985/1323/972 +f 227/1320/970 985/1323/972 1777/1324/973 +f 227/1320/970 1777/1324/973 986/1321/971 +f 228/1325/974 988/1326/975 1780/1319/969 +f 228/1325/974 1780/1319/969 983/1318/968 +f 228/1325/974 983/1318/968 1746/1317/920 +f 228/1325/974 1746/1317/920 960/1261/919 +f 228/1325/974 960/1261/919 1748/1245/912 +f 228/1325/974 1748/1245/912 987/1327/976 +f 228/1325/974 987/1327/976 1778/1328/977 +f 228/1325/974 1778/1328/977 988/1326/975 +f 229/1329/978 990/1330/979 1749/1233/900 +f 229/1329/978 1749/1233/900 954/1242/909 +f 229/1329/978 954/1242/909 1747/1241/908 +f 229/1329/978 1747/1241/908 986/1321/971 +f 229/1329/978 986/1321/971 1777/1324/973 +f 229/1329/978 1777/1324/973 989/1331/980 +f 229/1329/978 989/1331/980 1775/1332/981 +f 229/1329/978 1775/1332/981 990/1330/979 +f 230/1333/982 992/1334/983 1778/1328/977 +f 230/1333/982 1778/1328/977 987/1327/976 +f 230/1333/982 987/1327/976 1748/1245/912 +f 230/1333/982 1748/1245/912 956/1244/911 +f 230/1333/982 956/1244/911 1750/1237/904 +f 230/1333/982 1750/1237/904 991/1335/984 +f 230/1333/982 991/1335/984 1776/1336/985 +f 230/1333/982 1776/1336/985 992/1334/983 +f 231/1337/986 994/1338/987 1751/1223/892 +f 231/1337/986 1751/1223/892 950/1234/901 +f 231/1337/986 950/1234/901 1749/1233/900 +f 231/1337/986 1749/1233/900 990/1330/979 +f 231/1337/986 990/1330/979 1775/1332/981 +f 231/1337/986 1775/1332/981 993/1339/988 +f 231/1337/986 993/1339/988 1773/1340/989 +f 231/1337/986 1773/1340/989 994/1338/987 +f 232/1341/990 996/1342/991 1776/1336/985 +f 232/1341/990 1776/1336/985 991/1335/984 +f 232/1341/990 991/1335/984 1750/1237/904 +f 232/1341/990 1750/1237/904 952/1236/903 +f 232/1341/990 952/1236/903 1752/1229/896 +f 232/1341/990 1752/1229/896 995/1343/992 +f 232/1341/990 995/1343/992 1774/1344/993 +f 232/1341/990 1774/1344/993 996/1342/991 +f 233/1345/994 998/1346/995 1753/1211/884 +f 233/1345/994 1753/1211/884 946/1224/893 +f 233/1345/994 946/1224/893 1751/1223/892 +f 233/1345/994 1751/1223/892 994/1338/987 +f 233/1345/994 994/1338/987 1773/1340/989 +f 233/1345/994 1773/1340/989 997/1347/996 +f 233/1348/994 997/1349/996 1771/1350/997 +f 233/1348/994 1771/1350/997 998/1351/995 +f 234/1352/998 1000/1353/999 1774/1354/993 +f 234/1352/998 1774/1354/993 995/1355/992 +f 234/1356/998 995/1343/992 1752/1229/896 +f 234/1356/998 1752/1229/896 948/1228/895 +f 234/1356/998 948/1228/895 1754/1215/888 +f 234/1356/998 1754/1215/888 999/1357/1000 +f 234/1352/998 999/1358/1000 1772/1359/1001 +f 234/1352/998 1772/1359/1001 1000/1353/999 +f 235/1360/1002 1002/1361/1003 1755/1203/876 +f 235/1360/1002 1755/1203/876 942/1212/885 +f 235/1360/1002 942/1212/885 1753/1211/884 +f 235/1360/1002 1753/1211/884 998/1346/995 +f 235/1362/1002 998/1351/995 1771/1350/997 +f 235/1362/1002 1771/1350/997 1001/1363/1004 +f 235/1362/1002 1001/1363/1004 1769/1364/1005 +f 235/1362/1002 1769/1364/1005 1002/1365/1003 +f 236/1366/1006 1004/1367/1007 1772/1359/1001 +f 236/1366/1006 1772/1359/1001 999/1358/1000 +f 236/1368/1006 999/1357/1000 1754/1215/888 +f 236/1368/1006 1754/1215/888 944/1214/887 +f 236/1368/1006 944/1214/887 1756/1207/880 +f 236/1368/1006 1756/1207/880 1003/1369/1008 +f 236/1366/1006 1003/1370/1008 1770/1371/1009 +f 236/1366/1006 1770/1371/1009 1004/1367/1007 +f 237/1372/1010 1006/1373/1011 1757/1195/868 +f 237/1372/1010 1757/1195/868 938/1204/877 +f 237/1372/1010 938/1204/877 1755/1203/876 +f 237/1372/1010 1755/1203/876 1002/1361/1003 +f 237/1374/1010 1002/1365/1003 1769/1364/1005 +f 237/1374/1010 1769/1364/1005 1005/1375/1012 +f 237/1374/1010 1005/1375/1012 1767/1376/1013 +f 237/1374/1010 1767/1376/1013 1006/1377/1011 +f 238/1378/1014 1008/1379/1015 1770/1371/1009 +f 238/1378/1014 1770/1371/1009 1003/1370/1008 +f 238/1380/1014 1003/1369/1008 1756/1207/880 +f 238/1380/1014 1756/1207/880 940/1206/879 +f 238/1380/1014 940/1206/879 1758/1199/872 +f 238/1380/1014 1758/1199/872 1007/1381/1016 +f 238/1382/1014 1007/1383/1016 1768/1384/1017 +f 238/1382/1014 1768/1384/1017 1008/1385/1015 +f 239/1386/1018 1010/1387/1019 1739/1388/841 +f 239/1386/1018 1739/1388/841 934/1389/869 +f 239/1390/1018 934/1196/869 1757/1195/868 +f 239/1390/1018 1757/1195/868 1006/1373/1011 +f 239/1386/1018 1006/1377/1011 1767/1376/1013 +f 239/1386/1018 1767/1376/1013 1009/1391/1020 +f 239/1386/1018 1009/1391/1020 1785/1392/1021 +f 239/1386/1018 1785/1392/1021 1010/1387/1019 +f 240/1393/1022 1012/1394/1023 1768/1384/1017 +f 240/1393/1022 1768/1384/1017 1007/1383/1016 +f 240/1395/1022 1007/1381/1016 1758/1199/872 +f 240/1395/1022 1758/1199/872 936/1198/871 +f 240/1395/1022 936/1198/871 1740/1173/846 +f 240/1395/1022 1740/1173/846 1011/1396/1024 +f 240/1393/1022 1011/1397/1024 1786/1398/1025 +f 240/1393/1022 1786/1398/1025 1012/1394/1023 +f 241/1399/1026 971/1291/944 1761/1188/861 +f 241/1399/1026 1761/1188/861 929/1187/860 +f 241/1399/1026 929/1187/860 1759/1180/853 +f 241/1399/1026 1759/1180/853 1013/1400/1027 +f 241/1401/1026 1013/1402/1027 1765/1403/1028 +f 241/1401/1026 1765/1403/1028 1014/1404/1029 +f 241/1401/1026 1014/1404/1029 1763/1405/945 +f 241/1401/1026 1763/1405/945 971/1406/944 +f 242/1407/1030 1016/1408/1031 1766/1409/1032 +f 242/1407/1030 1766/1409/1032 1015/1410/1033 +f 242/1407/1030 1015/1410/1033 1760/1184/857 +f 242/1407/1030 1760/1184/857 932/1190/863 +f 242/1407/1030 932/1190/863 1762/1192/865 +f 242/1407/1030 1762/1192/865 974/1298/951 +f 242/1407/1030 974/1298/951 1764/1297/950 +f 242/1407/1030 1764/1297/950 1016/1408/1031 +f 243/1411/1034 1013/1400/1027 1759/1180/853 +f 243/1411/1034 1759/1180/853 925/1179/852 +f 243/1411/1034 925/1179/852 1737/1170/843 +f 243/1411/1034 1737/1170/843 1017/1412/1035 +f 243/1413/1034 1017/1414/1035 1787/1415/1036 +f 243/1413/1034 1787/1415/1036 1018/1416/1037 +f 243/1413/1034 1018/1416/1037 1765/1403/1028 +f 243/1413/1034 1765/1403/1028 1013/1402/1027 +f 244/1417/1038 1020/1418/1039 1788/1419/1040 +f 244/1417/1038 1788/1419/1040 1019/1420/1041 +f 244/1417/1038 1019/1420/1041 1738/1176/849 +f 244/1417/1038 1738/1176/849 928/1182/855 +f 244/1417/1038 928/1182/855 1760/1184/857 +f 244/1417/1038 1760/1184/857 1015/1410/1033 +f 244/1417/1038 1015/1410/1033 1766/1409/1032 +f 244/1417/1038 1766/1409/1032 1020/1418/1039 +f 245/1421/1042 1017/1412/1035 1737/1170/843 +f 245/1421/1042 1737/1170/843 920/1169/842 +f 245/1422/1042 920/1423/842 1739/1388/841 +f 245/1422/1042 1739/1388/841 1010/1387/1019 +f 245/1422/1042 1010/1387/1019 1785/1392/1021 +f 245/1422/1042 1785/1392/1021 1021/1424/1043 +f 245/1425/1042 1021/1426/1043 1787/1415/1036 +f 245/1425/1042 1787/1415/1036 1017/1414/1035 +f 246/1427/1044 1022/1428/1045 1786/1398/1025 +f 246/1427/1044 1786/1398/1025 1011/1397/1024 +f 246/1429/1044 1011/1396/1024 1740/1173/846 +f 246/1429/1044 1740/1173/846 924/1172/845 +f 246/1429/1044 924/1172/845 1738/1176/849 +f 246/1429/1044 1738/1176/849 1019/1420/1041 +f 246/1427/1044 1019/1430/1041 1788/1431/1040 +f 246/1427/1044 1788/1431/1040 1022/1428/1045 +f 247/1432/1046 1025/1433/1047 1572/592/438 +f 247/1432/1046 1572/592/438 716/591/437 +f 247/1432/1046 716/591/437 1613/578/426 +f 247/1432/1046 1613/578/426 1023/1434/1048 +f 247/1432/1046 1023/1434/1048 1789/1435/1049 +f 247/1432/1046 1789/1435/1049 1024/1436/1050 +f 247/1432/1046 1024/1436/1050 1578/1437/1051 +f 247/1432/1046 1578/1437/1051 1025/1433/1047 +f 248/1438/1052 1027/1439/1053 1790/1440/1054 +f 248/1438/1052 1790/1440/1054 1026/1441/1055 +f 248/1438/1052 1026/1441/1055 1614/588/434 +f 248/1438/1052 1614/588/434 719/603/444 +f 248/1438/1052 719/603/444 1572/602/438 +f 248/1438/1052 1572/602/438 1025/1442/1047 +f 248/1438/1052 1025/1442/1047 1578/1443/1051 +f 248/1438/1052 1578/1443/1051 1027/1439/1053 +f 249/1444/1056 1023/1434/1048 1613/578/426 +f 249/1444/1056 1613/578/426 710/577/425 +f 249/1444/1056 710/577/425 1611/559/414 +f 249/1444/1056 1611/559/414 1028/1445/1057 +f 249/1444/1056 1028/1445/1057 1791/1446/1058 +f 249/1444/1056 1791/1446/1058 1029/1447/1059 +f 249/1444/1056 1029/1447/1059 1789/1435/1049 +f 249/1444/1056 1789/1435/1049 1023/1434/1048 +f 250/1448/1060 1031/1449/1061 1792/1450/1062 +f 250/1448/1060 1792/1450/1062 1030/1451/1063 +f 250/1452/1060 1030/1453/1063 1612/570/422 +f 250/1452/1060 1612/570/422 714/589/435 +f 250/1452/1060 714/589/435 1614/588/434 +f 250/1452/1060 1614/588/434 1026/1441/1055 +f 250/1448/1060 1026/1454/1055 1790/1455/1054 +f 250/1448/1060 1790/1455/1054 1031/1449/1061 +f 251/1456/1064 1028/1445/1057 1611/559/414 +f 251/1456/1064 1611/559/414 704/558/413 +f 251/1457/1064 704/556/413 1609/543/402 +f 251/1457/1064 1609/543/402 1032/1458/1065 +f 251/1459/1064 1032/1460/1065 1793/1461/1066 +f 251/1459/1064 1793/1461/1066 1033/1462/1067 +f 251/1459/1064 1033/1462/1067 1791/1463/1058 +f 251/1459/1064 1791/1463/1058 1028/1464/1057 +f 252/1465/1068 1035/1466/1069 1794/1467/1070 +f 252/1465/1068 1794/1467/1070 1034/1468/1071 +f 252/1469/1068 1034/1470/1071 1610/572/410 +f 252/1469/1068 1610/572/410 708/571/423 +f 252/1469/1068 708/571/423 1612/570/422 +f 252/1469/1068 1612/570/422 1030/1453/1063 +f 252/1465/1068 1030/1451/1063 1792/1450/1062 +f 252/1465/1068 1792/1450/1062 1035/1466/1069 +f 253/1471/1072 1032/1458/1065 1609/543/402 +f 253/1471/1072 1609/543/402 698/542/401 +f 253/1471/1072 698/542/401 1607/529/390 +f 253/1471/1072 1607/529/390 1036/1472/1073 +f 253/1473/1072 1036/1474/1073 1795/1475/1074 +f 253/1473/1072 1795/1475/1074 1037/1476/1075 +f 253/1473/1072 1037/1476/1075 1793/1461/1066 +f 253/1473/1072 1793/1461/1066 1032/1460/1065 +f 254/1477/1076 1039/1478/1077 1796/1479/1078 +f 254/1477/1076 1796/1479/1078 1038/1480/1079 +f 254/1481/1076 1038/1482/1079 1608/539/398 +f 254/1481/1076 1608/539/398 702/554/411 +f 254/1481/1076 702/554/411 1610/553/410 +f 254/1481/1076 1610/553/410 1034/1483/1071 +f 254/1477/1076 1034/1468/1071 1794/1467/1070 +f 254/1477/1076 1794/1467/1070 1039/1478/1077 +f 255/1484/1080 1036/1472/1073 1607/529/390 +f 255/1484/1080 1607/529/390 692/528/389 +f 255/1484/1080 692/528/389 1605/511/378 +f 255/1484/1080 1605/511/378 1040/1485/1081 +f 255/1484/1080 1040/1485/1081 1797/1486/1082 +f 255/1484/1080 1797/1486/1082 1041/1487/1083 +f 255/1488/1080 1041/1489/1083 1795/1475/1074 +f 255/1488/1080 1795/1475/1074 1036/1474/1073 +f 256/1490/1084 1043/1491/1085 1798/1492/1086 +f 256/1490/1084 1798/1492/1086 1042/1493/1087 +f 256/1490/1084 1042/1493/1087 1606/523/386 +f 256/1490/1084 1606/523/386 696/540/399 +f 256/1490/1084 696/540/399 1608/539/398 +f 256/1490/1084 1608/539/398 1038/1482/1079 +f 256/1490/1084 1038/1482/1079 1796/1494/1078 +f 256/1490/1084 1796/1494/1078 1043/1491/1085 +f 257/1495/1088 1040/1485/1081 1605/511/378 +f 257/1495/1088 1605/511/378 686/510/377 +f 257/1495/1088 686/510/377 1603/509/366 +f 257/1495/1088 1603/509/366 1044/1496/1089 +f 257/1497/1088 1044/1498/1089 1799/1499/1090 +f 257/1497/1088 1799/1499/1090 1045/1500/1091 +f 257/1495/1088 1045/1501/1091 1797/1486/1082 +f 257/1495/1088 1797/1486/1082 1040/1485/1081 +f 258/1502/1092 1047/1503/1093 1800/1504/1094 +f 258/1502/1092 1800/1504/1094 1046/1505/1095 +f 258/1502/1092 1046/1505/1095 1604/525/374 +f 258/1502/1092 1604/525/374 690/524/387 +f 258/1502/1092 690/524/387 1606/523/386 +f 258/1502/1092 1606/523/386 1042/1493/1087 +f 258/1502/1092 1042/1493/1087 1798/1492/1086 +f 258/1502/1092 1798/1492/1086 1047/1503/1093 +f 259/1506/1096 1044/1507/1089 1603/497/366 +f 259/1506/1096 1603/497/366 680/496/365 +f 259/1506/1096 680/496/365 1601/485/354 +f 259/1506/1096 1601/485/354 1048/1508/1097 +f 259/1506/1096 1048/1508/1097 1801/1509/1098 +f 259/1506/1096 1801/1509/1098 1049/1510/1099 +f 259/1506/1096 1049/1510/1099 1799/1511/1090 +f 259/1506/1096 1799/1511/1090 1044/1507/1089 +f 260/1512/1100 1051/1513/1101 1802/1514/1102 +f 260/1512/1100 1802/1514/1102 1050/1515/1103 +f 260/1516/1100 1050/1517/1103 1602/1518/362 +f 260/1516/1100 1602/1518/362 684/1519/375 +f 260/1512/1100 684/1520/375 1604/525/374 +f 260/1512/1100 1604/525/374 1046/1505/1095 +f 260/1512/1100 1046/1505/1095 1800/1504/1094 +f 260/1512/1100 1800/1504/1094 1051/1513/1101 +f 261/1521/1104 1048/1508/1097 1601/485/354 +f 261/1521/1104 1601/485/354 674/484/353 +f 261/1521/1104 674/484/353 1599/469/342 +f 261/1521/1104 1599/469/342 1052/1522/1105 +f 261/1521/1104 1052/1522/1105 1803/1523/1106 +f 261/1521/1104 1803/1523/1106 1053/1524/1107 +f 261/1521/1104 1053/1524/1107 1801/1509/1098 +f 261/1521/1104 1801/1509/1098 1048/1508/1097 +f 262/1525/1108 1055/1526/1109 1804/1527/1110 +f 262/1525/1108 1804/1527/1110 1054/1528/1111 +f 262/1525/1108 1054/1528/1111 1600/1529/350 +f 262/1525/1108 1600/1529/350 678/1530/363 +f 262/1525/1108 678/1530/363 1602/1518/362 +f 262/1525/1108 1602/1518/362 1050/1517/1103 +f 262/1525/1108 1050/1517/1103 1802/1531/1102 +f 262/1525/1108 1802/1531/1102 1055/1526/1109 +f 263/1532/1112 1052/1522/1105 1599/469/342 +f 263/1532/1112 1599/469/342 668/468/341 +f 263/1532/1112 668/468/341 1597/450/326 +f 263/1532/1112 1597/450/326 1056/1533/1113 +f 263/1532/1112 1056/1533/1113 1805/1534/1114 +f 263/1532/1112 1805/1534/1114 1057/1535/1115 +f 263/1532/1112 1057/1535/1115 1803/1523/1106 +f 263/1532/1112 1803/1523/1106 1052/1522/1105 +f 264/1536/1116 1059/1537/1117 1806/1538/1118 +f 264/1536/1116 1806/1538/1118 1058/1539/1119 +f 264/1536/1116 1058/1539/1119 1598/1540/335 +f 264/1536/1116 1598/1540/335 672/1541/351 +f 264/1536/1116 672/1541/351 1600/1529/350 +f 264/1536/1116 1600/1529/350 1054/1528/1111 +f 264/1536/1116 1054/1528/1111 1804/1527/1110 +f 264/1536/1116 1804/1527/1110 1059/1537/1117 +f 265/1542/1120 1063/1543/1121 1813/1544/1122 +f 265/1542/1120 1813/1544/1122 1060/1545/1123 +f 265/1546/1120 1060/1547/1123 1814/1548/1124 +f 265/1546/1120 1814/1548/1124 1061/1549/1125 +f 265/1546/1120 1061/1549/1125 1833/1550/1126 +f 265/1546/1120 1833/1550/1126 1062/1551/1127 +f 265/1542/1120 1062/1552/1127 1843/1553/1128 +f 265/1542/1120 1843/1553/1128 1063/1543/1121 +f 266/1554/1129 1066/1555/1130 1834/1556/1131 +f 266/1554/1129 1834/1556/1131 1064/1557/1132 +f 266/1554/1129 1064/1557/1132 1814/1548/1124 +f 266/1554/1129 1814/1548/1124 1060/1547/1123 +f 266/1554/1129 1060/1547/1123 1813/1558/1122 +f 266/1554/1129 1813/1558/1122 1065/1559/1133 +f 266/1554/1129 1065/1559/1133 1844/1560/1134 +f 266/1554/1129 1844/1560/1134 1066/1555/1130 +f 267/1561/1135 1069/1562/1136 1812/1563/1137 +f 267/1561/1135 1812/1563/1137 1067/1564/1138 +f 267/1561/1135 1067/1564/1138 1813/1544/1122 +f 267/1561/1135 1813/1544/1122 1063/1543/1121 +f 267/1561/1135 1063/1543/1121 1843/1553/1128 +f 267/1561/1135 1843/1553/1128 1068/1565/1139 +f 267/1561/1135 1068/1565/1139 1841/1566/1140 +f 267/1561/1135 1841/1566/1140 1069/1562/1136 +f 268/1567/1141 1071/1568/1142 1844/1569/1134 +f 268/1567/1141 1844/1569/1134 1065/1570/1133 +f 268/1567/1141 1065/1570/1133 1813/1544/1122 +f 268/1567/1141 1813/1544/1122 1067/1564/1138 +f 268/1567/1141 1067/1564/1138 1812/1563/1137 +f 268/1567/1141 1812/1563/1137 1070/1571/1143 +f 268/1567/1141 1070/1571/1143 1842/1572/1144 +f 268/1567/1141 1842/1572/1144 1071/1568/1142 +f 269/1573/1145 1074/1574/1146 1811/1575/1147 +f 269/1573/1145 1811/1575/1147 1072/1576/1148 +f 269/1577/1145 1072/1578/1148 1812/1563/1137 +f 269/1577/1145 1812/1563/1137 1069/1562/1136 +f 269/1577/1145 1069/1562/1136 1841/1566/1140 +f 269/1577/1145 1841/1566/1140 1073/1579/1149 +f 269/1573/1145 1073/1580/1149 1845/1581/1150 +f 269/1573/1145 1845/1581/1150 1074/1574/1146 +f 270/1582/1151 1076/1583/1152 1842/1572/1144 +f 270/1582/1151 1842/1572/1144 1070/1571/1143 +f 270/1584/1151 1070/1585/1143 1812/1586/1137 +f 270/1584/1151 1812/1586/1137 1072/1576/1148 +f 270/1584/1151 1072/1576/1148 1811/1575/1147 +f 270/1584/1151 1811/1575/1147 1075/1587/1153 +f 270/1584/1151 1075/1587/1153 1846/1588/1154 +f 270/1584/1151 1846/1588/1154 1076/1589/1152 +f 271/1590/1155 1078/1591/1156 1594/366/261 +f 271/1590/1155 1594/366/261 632/365/260 +f 271/1590/1155 632/365/260 1596/375/267 +f 271/1590/1155 1596/375/267 1077/1592/1157 +f 271/1590/1155 1077/1592/1157 1811/1575/1147 +f 271/1590/1155 1811/1575/1147 1074/1574/1146 +f 271/1590/1155 1074/1574/1146 1845/1581/1150 +f 271/1590/1155 1845/1581/1150 1078/1591/1156 +f 272/1593/1158 1075/1587/1153 1811/1575/1147 +f 272/1593/1158 1811/1575/1147 1077/1592/1157 +f 272/1593/1158 1077/1592/1157 1596/375/267 +f 272/1593/1158 1596/375/267 635/383/273 +f 272/1593/1158 635/383/273 1595/382/272 +f 272/1593/1158 1595/382/272 1079/1594/1159 +f 272/1593/1158 1079/1594/1159 1846/1588/1154 +f 272/1593/1158 1846/1588/1154 1075/1587/1153 +f 273/1595/1160 1081/1596/1161 1592/386/276 +f 273/1595/1160 1592/386/276 638/385/275 +f 273/1597/1160 638/393/275 1594/366/261 +f 273/1597/1160 1594/366/261 1078/1591/1156 +f 273/1597/1160 1078/1591/1156 1845/1581/1150 +f 273/1597/1160 1845/1581/1150 1080/1598/1162 +f 273/1597/1160 1080/1598/1162 1839/1599/1163 +f 273/1597/1160 1839/1599/1163 1081/1600/1161 +f 274/1601/1164 1083/1602/1165 1846/1588/1154 +f 274/1601/1164 1846/1588/1154 1079/1594/1159 +f 274/1601/1164 1079/1594/1159 1595/382/272 +f 274/1601/1164 1595/382/272 641/401/285 +f 274/1601/1164 641/401/285 1593/400/284 +f 274/1601/1164 1593/400/284 1082/1603/1166 +f 274/1601/1164 1082/1603/1166 1840/1604/1167 +f 274/1601/1164 1840/1604/1167 1083/1602/1165 +f 275/1605/1168 1085/1606/1169 1590/404/288 +f 275/1605/1168 1590/404/288 644/403/287 +f 275/1605/1168 644/403/287 1592/386/276 +f 275/1605/1168 1592/386/276 1081/1596/1161 +f 275/1605/1168 1081/1596/1161 1839/1607/1163 +f 275/1605/1168 1839/1607/1163 1084/1608/1170 +f 275/1609/1168 1084/1610/1170 1835/1611/1171 +f 275/1609/1168 1835/1611/1171 1085/1612/1169 +f 276/1613/1172 1087/1614/1173 1840/1604/1167 +f 276/1613/1172 1840/1604/1167 1082/1603/1166 +f 276/1613/1172 1082/1603/1166 1593/400/284 +f 276/1613/1172 1593/400/284 647/1615/297 +f 276/1616/1172 647/1617/297 1591/430/296 +f 276/1616/1172 1591/430/296 1086/1618/1174 +f 276/1616/1172 1086/1618/1174 1836/1619/1175 +f 276/1616/1172 1836/1619/1175 1087/1620/1173 +f 277/1621/1176 1089/1622/1177 1588/418/300 +f 277/1621/1176 1588/418/300 650/417/299 +f 277/1621/1176 650/417/299 1590/404/288 +f 277/1621/1176 1590/404/288 1085/1606/1169 +f 277/1623/1176 1085/1612/1169 1835/1611/1171 +f 277/1623/1176 1835/1611/1171 1088/1624/1178 +f 277/1623/1176 1088/1624/1178 1837/1625/1179 +f 277/1623/1176 1837/1625/1179 1089/1626/1177 +f 278/1627/1180 1091/1628/1181 1836/1619/1175 +f 278/1627/1180 1836/1619/1175 1086/1618/1174 +f 278/1627/1180 1086/1618/1174 1591/430/296 +f 278/1627/1180 1591/430/296 653/429/309 +f 278/1627/1180 653/429/309 1589/428/308 +f 278/1627/1180 1589/428/308 1090/1629/1182 +f 278/1627/1180 1090/1629/1182 1838/1630/1183 +f 278/1627/1180 1838/1630/1183 1091/1628/1181 +f 279/1631/1184 1088/1624/1178 1835/1611/1171 +f 279/1631/1184 1835/1611/1171 1092/1632/1185 +f 279/1631/1184 1092/1632/1185 1841/1566/1140 +f 279/1631/1184 1841/1566/1140 1068/1565/1139 +f 279/1631/1184 1068/1565/1139 1843/1553/1128 +f 279/1631/1184 1843/1553/1128 1093/1633/1186 +f 279/1631/1184 1093/1633/1186 1837/1625/1179 +f 279/1631/1184 1837/1625/1179 1088/1624/1178 +f 280/1634/1187 1095/1635/1188 1844/1569/1134 +f 280/1634/1187 1844/1569/1134 1071/1568/1142 +f 280/1634/1187 1071/1568/1142 1842/1572/1144 +f 280/1634/1187 1842/1572/1144 1094/1636/1189 +f 280/1634/1187 1094/1636/1189 1836/1637/1175 +f 280/1634/1187 1836/1637/1175 1091/1638/1181 +f 280/1634/1187 1091/1638/1181 1838/1639/1183 +f 280/1634/1187 1838/1639/1183 1095/1635/1188 +f 281/1640/1190 1092/1632/1185 1835/1611/1171 +f 281/1640/1190 1835/1611/1171 1084/1610/1170 +f 281/1640/1190 1084/1610/1170 1839/1641/1163 +f 281/1640/1190 1839/1641/1163 1080/1642/1162 +f 281/1643/1190 1080/1598/1162 1845/1581/1150 +f 281/1643/1190 1845/1581/1150 1073/1580/1149 +f 281/1640/1190 1073/1579/1149 1841/1566/1140 +f 281/1640/1190 1841/1566/1140 1092/1632/1185 +f 282/1644/1191 1076/1589/1152 1846/1588/1154 +f 282/1644/1191 1846/1588/1154 1083/1602/1165 +f 282/1644/1191 1083/1602/1165 1840/1604/1167 +f 282/1644/1191 1840/1604/1167 1087/1614/1173 +f 282/1645/1191 1087/1646/1173 1836/1637/1175 +f 282/1645/1191 1836/1637/1175 1094/1636/1189 +f 282/1645/1191 1094/1636/1189 1842/1572/1144 +f 282/1645/1191 1842/1572/1144 1076/1583/1152 +f 283/1647/1192 1097/1648/1193 1831/1649/1194 +f 283/1647/1192 1831/1649/1194 1096/1650/1195 +f 283/1651/1192 1096/1652/1195 1837/1625/1179 +f 283/1651/1192 1837/1625/1179 1093/1633/1186 +f 283/1651/1192 1093/1633/1186 1843/1553/1128 +f 283/1651/1192 1843/1553/1128 1062/1552/1127 +f 283/1647/1192 1062/1653/1127 1833/1654/1126 +f 283/1647/1192 1833/1654/1126 1097/1648/1193 +f 284/1655/1196 1066/1555/1130 1844/1560/1134 +f 284/1655/1196 1844/1560/1134 1095/1656/1188 +f 284/1655/1196 1095/1656/1188 1838/1657/1183 +f 284/1655/1196 1838/1657/1183 1098/1658/1197 +f 284/1655/1196 1098/1658/1197 1832/1659/1198 +f 284/1655/1196 1832/1659/1198 1099/1660/1199 +f 284/1655/1196 1099/1660/1199 1834/1556/1131 +f 284/1655/1196 1834/1556/1131 1066/1555/1130 +f 285/1661/1200 1100/1662/1201 1586/434/312 +f 285/1661/1200 1586/434/312 656/433/311 +f 285/1661/1200 656/433/311 1588/418/300 +f 285/1661/1200 1588/418/300 1089/1622/1177 +f 285/1663/1200 1089/1626/1177 1837/1625/1179 +f 285/1663/1200 1837/1625/1179 1096/1652/1195 +f 285/1661/1200 1096/1650/1195 1831/1649/1194 +f 285/1661/1200 1831/1649/1194 1100/1662/1201 +f 286/1664/1202 1098/1665/1197 1838/1630/1183 +f 286/1664/1202 1838/1630/1183 1090/1629/1182 +f 286/1664/1202 1090/1629/1182 1589/428/308 +f 286/1664/1202 1589/428/308 659/445/321 +f 286/1664/1202 659/445/321 1587/444/320 +f 286/1664/1202 1587/444/320 1101/1666/1203 +f 286/1664/1202 1101/1666/1203 1832/1667/1198 +f 286/1664/1202 1832/1667/1198 1098/1665/1197 +f 287/1668/1204 878/1025/756 1714/1024/749 +f 287/1668/1204 1714/1024/749 1102/1669/1205 +f 287/1668/1204 1102/1669/1205 1847/1670/1206 +f 287/1668/1204 1847/1670/1206 1103/1671/1207 +f 287/1668/1204 1103/1671/1207 1849/1672/1208 +f 287/1668/1204 1849/1672/1208 1104/1673/1209 +f 287/1668/1204 1104/1673/1209 1720/1026/757 +f 287/1668/1204 1720/1026/757 878/1025/756 +f 288/1674/1210 1107/1675/1211 1850/1676/1212 +f 288/1674/1210 1850/1676/1212 1105/1677/1213 +f 288/1674/1210 1105/1677/1213 1848/1678/1214 +f 288/1674/1210 1848/1678/1214 1106/1679/1215 +f 288/1674/1210 1106/1679/1215 1715/1019/753 +f 288/1674/1210 1715/1019/753 881/1033/762 +f 288/1674/1210 881/1033/762 1721/1032/761 +f 288/1674/1210 1721/1032/761 1107/1675/1211 +f 289/1680/1216 874/1008/748 1586/434/312 +f 289/1680/1216 1586/434/312 1100/1662/1201 +f 289/1680/1216 1100/1662/1201 1831/1649/1194 +f 289/1680/1216 1831/1649/1194 1108/1681/1217 +f 289/1680/1216 1108/1681/1217 1847/1670/1206 +f 289/1680/1216 1847/1670/1206 1102/1669/1205 +f 289/1680/1216 1102/1669/1205 1714/1024/749 +f 289/1680/1216 1714/1024/749 874/1008/748 +f 290/1682/1218 1106/1679/1215 1848/1678/1214 +f 290/1682/1218 1848/1678/1214 1109/1683/1219 +f 290/1682/1218 1109/1683/1219 1832/1667/1198 +f 290/1682/1218 1832/1667/1198 1101/1666/1203 +f 290/1682/1218 1101/1666/1203 1587/444/320 +f 290/1682/1218 1587/444/320 877/1020/754 +f 290/1682/1218 877/1020/754 1715/1019/753 +f 290/1682/1218 1715/1019/753 1106/1679/1215 +f 291/1684/1220 1111/1685/1221 1584/448/324 +f 291/1684/1220 1584/448/324 882/1035/764 +f 291/1684/1220 882/1035/764 1720/1026/757 +f 291/1684/1220 1720/1026/757 1104/1673/1209 +f 291/1684/1220 1104/1673/1209 1849/1672/1208 +f 291/1684/1220 1849/1672/1208 1110/1686/1222 +f 291/1684/1220 1110/1686/1222 1851/1687/1223 +f 291/1684/1220 1851/1687/1223 1111/1685/1221 +f 292/1688/1224 1113/1689/1225 1850/1676/1212 +f 292/1688/1224 1850/1676/1212 1107/1675/1211 +f 292/1688/1224 1107/1675/1211 1721/1032/761 +f 292/1688/1224 1721/1032/761 883/1041/766 +f 292/1690/1224 883/1691/766 1585/463/337 +f 292/1690/1224 1585/463/337 1112/1692/1226 +f 292/1690/1224 1112/1692/1226 1852/1693/1227 +f 292/1690/1224 1852/1693/1227 1113/1694/1225 +f 293/1695/1228 660/449/325 1584/448/324 +f 293/1695/1228 1584/448/324 1111/1685/1221 +f 293/1695/1228 1111/1685/1221 1851/1687/1223 +f 293/1695/1228 1851/1687/1223 1114/1696/1229 +f 293/1697/1228 1114/1698/1229 1805/1699/1114 +f 293/1697/1228 1805/1699/1114 1056/1700/1113 +f 293/1697/1228 1056/1700/1113 1597/1701/326 +f 293/1697/1228 1597/1701/326 660/1702/325 +f 294/1703/1230 1058/1539/1119 1806/1538/1118 +f 294/1703/1230 1806/1538/1118 1115/1704/1231 +f 294/1703/1230 1115/1704/1231 1852/1693/1227 +f 294/1703/1230 1852/1693/1227 1112/1692/1226 +f 294/1703/1230 1112/1692/1226 1585/463/337 +f 294/1703/1230 1585/463/337 665/462/336 +f 294/1703/1230 665/462/336 1598/1540/335 +f 294/1703/1230 1598/1540/335 1058/1539/1119 +f 295/1705/1232 1119/1706/1233 1582/1707/1234 +f 295/1705/1232 1582/1707/1234 1116/1708/1235 +f 295/1705/1232 1116/1708/1235 1829/1709/1236 +f 295/1705/1232 1829/1709/1236 1117/1710/1237 +f 295/1711/1232 1117/1712/1237 1857/1713/1238 +f 295/1711/1232 1857/1713/1238 1118/1714/1239 +f 295/1711/1232 1118/1714/1239 1809/1715/1240 +f 295/1711/1232 1809/1715/1240 1119/1716/1233 +f 296/1717/1241 1122/1718/1242 1858/1719/1243 +f 296/1717/1241 1858/1719/1243 1120/1720/1244 +f 296/1717/1241 1120/1720/1244 1830/1721/1245 +f 296/1717/1241 1830/1721/1245 1121/1722/1246 +f 296/1717/1241 1121/1722/1246 1582/1723/1234 +f 296/1717/1241 1582/1723/1234 1119/1716/1233 +f 296/1717/1241 1119/1716/1233 1809/1715/1240 +f 296/1717/1241 1809/1715/1240 1122/1718/1242 +f 297/1724/1247 1125/1725/1248 1809/1715/1240 +f 297/1724/1247 1809/1715/1240 1118/1714/1239 +f 297/1724/1247 1118/1714/1239 1857/1713/1238 +f 297/1724/1247 1857/1713/1238 1123/1726/1249 +f 297/1724/1247 1123/1726/1249 1855/1727/1250 +f 297/1724/1247 1855/1727/1250 1124/1728/1251 +f 297/1724/1247 1124/1728/1251 1583/1729/1252 +f 297/1724/1247 1583/1729/1252 1125/1725/1248 +f 298/1730/1253 1127/1731/1254 1856/1732/1255 +f 298/1730/1253 1856/1732/1255 1126/1733/1256 +f 298/1730/1253 1126/1733/1256 1858/1719/1243 +f 298/1730/1253 1858/1719/1243 1122/1718/1242 +f 298/1730/1253 1122/1718/1242 1809/1715/1240 +f 298/1730/1253 1809/1715/1240 1125/1725/1248 +f 298/1730/1253 1125/1725/1248 1583/1729/1252 +f 298/1730/1253 1583/1729/1252 1127/1731/1254 +f 299/1734/1257 1130/1735/1258 1583/1729/1252 +f 299/1734/1257 1583/1729/1252 1124/1728/1251 +f 299/1736/1257 1124/1737/1251 1855/1738/1250 +f 299/1736/1257 1855/1738/1250 1128/1739/1259 +f 299/1736/1257 1128/1739/1259 1853/1740/1260 +f 299/1736/1257 1853/1740/1260 1129/1741/1261 +f 299/1734/1257 1129/1742/1261 1810/1743/1262 +f 299/1734/1257 1810/1743/1262 1130/1735/1258 +f 300/1744/1263 1132/1745/1264 1854/1746/1265 +f 300/1744/1263 1854/1746/1265 1131/1747/1266 +f 300/1744/1263 1131/1747/1266 1856/1732/1255 +f 300/1744/1263 1856/1732/1255 1127/1731/1254 +f 300/1744/1263 1127/1731/1254 1583/1729/1252 +f 300/1744/1263 1583/1729/1252 1130/1735/1258 +f 300/1744/1263 1130/1735/1258 1810/1743/1262 +f 300/1744/1263 1810/1743/1262 1132/1745/1264 +f 301/1748/1267 1134/1749/1268 1810/1743/1262 +f 301/1748/1267 1810/1743/1262 1129/1742/1261 +f 301/1750/1267 1129/1741/1261 1853/1740/1260 +f 301/1750/1267 1853/1740/1260 1133/1751/1269 +f 301/1750/1267 1133/1751/1269 1833/1654/1126 +f 301/1750/1267 1833/1654/1126 1061/1752/1125 +f 301/1748/1267 1061/1549/1125 1814/1548/1124 +f 301/1748/1267 1814/1548/1124 1134/1749/1268 +f 302/1753/1270 1064/1557/1132 1834/1556/1131 +f 302/1753/1270 1834/1556/1131 1135/1754/1271 +f 302/1753/1270 1135/1754/1271 1854/1746/1265 +f 302/1753/1270 1854/1746/1265 1132/1745/1264 +f 302/1753/1270 1132/1745/1264 1810/1743/1262 +f 302/1753/1270 1810/1743/1262 1134/1749/1268 +f 302/1753/1270 1134/1749/1268 1814/1548/1124 +f 302/1753/1270 1814/1548/1124 1064/1557/1132 +f 303/1755/1272 1108/1681/1217 1831/1649/1194 +f 303/1755/1272 1831/1649/1194 1097/1648/1193 +f 303/1755/1272 1097/1648/1193 1833/1654/1126 +f 303/1755/1272 1833/1654/1126 1133/1751/1269 +f 303/1755/1272 1133/1751/1269 1853/1740/1260 +f 303/1755/1272 1853/1740/1260 1136/1756/1273 +f 303/1755/1272 1136/1756/1273 1847/1670/1206 +f 303/1755/1272 1847/1670/1206 1108/1681/1217 +f 304/1757/1274 1137/1758/1275 1854/1746/1265 +f 304/1757/1274 1854/1746/1265 1135/1754/1271 +f 304/1757/1274 1135/1754/1271 1834/1556/1131 +f 304/1757/1274 1834/1556/1131 1099/1660/1199 +f 304/1759/1274 1099/1760/1199 1832/1667/1198 +f 304/1759/1274 1832/1667/1198 1109/1683/1219 +f 304/1757/1274 1109/1761/1219 1848/1762/1214 +f 304/1757/1274 1848/1762/1214 1137/1758/1275 +f 305/1763/1276 1140/1764/1277 1801/1509/1098 +f 305/1763/1276 1801/1509/1098 1053/1524/1107 +f 305/1763/1276 1053/1524/1107 1803/1523/1106 +f 305/1763/1276 1803/1523/1106 1138/1765/1278 +f 305/1763/1276 1138/1765/1278 1823/1766/1279 +f 305/1763/1276 1823/1766/1279 1139/1767/1280 +f 305/1763/1276 1139/1767/1280 1815/1768/1281 +f 305/1763/1276 1815/1768/1281 1140/1764/1277 +f 306/1769/1282 1143/1770/1283 1824/1771/1284 +f 306/1769/1282 1824/1771/1284 1141/1772/1285 +f 306/1769/1282 1141/1772/1285 1804/1527/1110 +f 306/1769/1282 1804/1527/1110 1055/1526/1109 +f 306/1769/1282 1055/1526/1109 1802/1531/1102 +f 306/1769/1282 1802/1531/1102 1142/1773/1286 +f 306/1769/1282 1142/1773/1286 1816/1774/1287 +f 306/1769/1282 1816/1774/1287 1143/1770/1283 +f 307/1775/1288 1146/1776/1289 1581/1777/1290 +f 307/1775/1288 1581/1777/1290 1144/1778/1291 +f 307/1775/1288 1144/1778/1291 1821/1779/1292 +f 307/1775/1288 1821/1779/1292 1145/1780/1293 +f 307/1775/1288 1145/1780/1293 1829/1709/1236 +f 307/1775/1288 1829/1709/1236 1116/1708/1235 +f 307/1775/1288 1116/1708/1235 1582/1707/1234 +f 307/1775/1288 1582/1707/1234 1146/1776/1289 +f 308/1781/1294 1121/1722/1246 1830/1721/1245 +f 308/1781/1294 1830/1721/1245 1147/1782/1295 +f 308/1783/1294 1147/1784/1295 1822/1785/1296 +f 308/1783/1294 1822/1785/1296 1148/1786/1297 +f 308/1783/1294 1148/1786/1297 1581/1777/1290 +f 308/1783/1294 1581/1777/1290 1146/1776/1289 +f 308/1783/1294 1146/1776/1289 1582/1707/1234 +f 308/1783/1294 1582/1707/1234 1121/1787/1246 +f 309/1788/1298 1152/1789/1299 1807/1790/1300 +f 309/1788/1298 1807/1790/1300 1149/1791/1301 +f 309/1788/1298 1149/1791/1301 1863/1792/1302 +f 309/1788/1298 1863/1792/1302 1150/1793/1303 +f 309/1788/1298 1150/1793/1303 1861/1794/1304 +f 309/1788/1298 1861/1794/1304 1151/1795/1305 +f 309/1788/1298 1151/1795/1305 1808/1796/1306 +f 309/1788/1298 1808/1796/1306 1152/1789/1299 +f 310/1797/1307 1155/1798/1308 1862/1799/1309 +f 310/1797/1307 1862/1799/1309 1153/1800/1310 +f 310/1801/1307 1153/1802/1310 1864/1803/1311 +f 310/1801/1307 1864/1803/1311 1154/1804/1312 +f 310/1801/1307 1154/1804/1312 1807/1790/1300 +f 310/1801/1307 1807/1790/1300 1152/1789/1299 +f 310/1801/1307 1152/1789/1299 1808/1796/1306 +f 310/1801/1307 1808/1796/1306 1155/1805/1308 +f 311/1806/1313 1158/1807/1314 1808/1796/1306 +f 311/1806/1313 1808/1796/1306 1151/1795/1305 +f 311/1806/1313 1151/1795/1305 1861/1794/1304 +f 311/1806/1313 1861/1794/1304 1156/1808/1315 +f 311/1809/1313 1156/1810/1315 1859/1811/1316 +f 311/1809/1313 1859/1811/1316 1157/1812/1317 +f 311/1809/1313 1157/1812/1317 1580/1813/1318 +f 311/1809/1313 1580/1813/1318 1158/1814/1314 +f 312/1815/1319 1160/1816/1320 1860/1817/1321 +f 312/1815/1319 1860/1817/1321 1159/1818/1322 +f 312/1815/1319 1159/1818/1322 1862/1799/1309 +f 312/1815/1319 1862/1799/1309 1155/1798/1308 +f 312/1819/1319 1155/1805/1308 1808/1796/1306 +f 312/1819/1319 1808/1796/1306 1158/1807/1314 +f 312/1820/1319 1158/1814/1314 1580/1813/1318 +f 312/1820/1319 1580/1813/1318 1160/1821/1320 +f 313/1822/1323 1162/1823/1324 1580/1813/1318 +f 313/1822/1323 1580/1813/1318 1157/1812/1317 +f 313/1822/1323 1157/1812/1317 1859/1811/1316 +f 313/1822/1323 1859/1811/1316 1161/1824/1325 +f 313/1822/1323 1161/1824/1325 1821/1779/1292 +f 313/1822/1323 1821/1779/1292 1144/1778/1291 +f 313/1822/1323 1144/1778/1291 1581/1777/1290 +f 313/1822/1323 1581/1777/1290 1162/1823/1324 +f 314/1825/1326 1148/1786/1297 1822/1785/1296 +f 314/1825/1326 1822/1785/1296 1163/1826/1327 +f 314/1825/1326 1163/1826/1327 1860/1827/1321 +f 314/1825/1326 1860/1827/1321 1160/1821/1320 +f 314/1825/1326 1160/1821/1320 1580/1813/1318 +f 314/1825/1326 1580/1813/1318 1162/1823/1324 +f 314/1825/1326 1162/1823/1324 1581/1777/1290 +f 314/1825/1326 1581/1777/1290 1148/1786/1297 +f 315/1828/1328 1166/1829/1329 1797/1486/1082 +f 315/1828/1328 1797/1486/1082 1045/1501/1091 +f 315/1828/1328 1045/1501/1091 1799/1830/1090 +f 315/1828/1328 1799/1830/1090 1164/1831/1330 +f 315/1828/1328 1164/1831/1330 1867/1832/1331 +f 315/1828/1328 1867/1832/1331 1165/1833/1332 +f 315/1828/1328 1165/1833/1332 1869/1834/1333 +f 315/1828/1328 1869/1834/1333 1166/1829/1329 +f 316/1835/1334 1169/1836/1335 1868/1837/1336 +f 316/1835/1334 1868/1837/1336 1167/1838/1337 +f 316/1835/1334 1167/1838/1337 1800/1504/1094 +f 316/1835/1334 1800/1504/1094 1047/1503/1093 +f 316/1835/1334 1047/1503/1093 1798/1492/1086 +f 316/1835/1334 1798/1492/1086 1168/1839/1338 +f 316/1835/1334 1168/1839/1338 1870/1840/1339 +f 316/1835/1334 1870/1840/1339 1169/1836/1335 +f 317/1841/1340 1172/1842/1341 1869/1834/1333 +f 317/1841/1340 1869/1834/1333 1165/1833/1332 +f 317/1841/1340 1165/1833/1332 1867/1832/1331 +f 317/1841/1340 1867/1832/1331 1170/1843/1342 +f 317/1841/1340 1170/1843/1342 1873/1844/1343 +f 317/1841/1340 1873/1844/1343 1171/1845/1344 +f 317/1841/1340 1171/1845/1344 1871/1846/1345 +f 317/1841/1340 1871/1846/1345 1172/1842/1341 +f 318/1847/1346 1175/1848/1347 1874/1849/1348 +f 318/1847/1346 1874/1849/1348 1173/1850/1349 +f 318/1847/1346 1173/1850/1349 1868/1837/1336 +f 318/1847/1346 1868/1837/1336 1169/1836/1335 +f 318/1847/1346 1169/1836/1335 1870/1840/1339 +f 318/1847/1346 1870/1840/1339 1174/1851/1350 +f 318/1847/1346 1174/1851/1350 1872/1852/1351 +f 318/1847/1346 1872/1852/1351 1175/1848/1347 +f 319/1853/1352 1178/1854/1353 1871/1846/1345 +f 319/1853/1352 1871/1846/1345 1171/1845/1344 +f 319/1853/1352 1171/1845/1344 1873/1844/1343 +f 319/1853/1352 1873/1844/1343 1176/1855/1354 +f 319/1853/1352 1176/1855/1354 1875/1856/1355 +f 319/1853/1352 1875/1856/1355 1177/1857/1356 +f 319/1853/1352 1177/1857/1356 1877/1858/1357 +f 319/1853/1352 1877/1858/1357 1178/1854/1353 +f 320/1859/1358 1181/1860/1359 1876/1861/1360 +f 320/1859/1358 1876/1861/1360 1179/1862/1361 +f 320/1859/1358 1179/1862/1361 1874/1849/1348 +f 320/1859/1358 1874/1849/1348 1175/1848/1347 +f 320/1859/1358 1175/1848/1347 1872/1852/1351 +f 320/1859/1358 1872/1852/1351 1180/1863/1362 +f 320/1859/1358 1180/1863/1362 1878/1864/1363 +f 320/1859/1358 1878/1864/1363 1181/1860/1359 +f 321/1865/1364 1184/1866/1365 1877/1858/1357 +f 321/1865/1364 1877/1858/1357 1177/1857/1356 +f 321/1865/1364 1177/1857/1356 1875/1856/1355 +f 321/1865/1364 1875/1856/1355 1182/1867/1366 +f 321/1868/1364 1182/1869/1366 1881/1870/1367 +f 321/1868/1364 1881/1870/1367 1183/1871/1368 +f 321/1868/1364 1183/1871/1368 1879/1872/1369 +f 321/1868/1364 1879/1872/1369 1184/1873/1365 +f 322/1874/1370 1187/1875/1371 1882/1876/1372 +f 322/1874/1370 1882/1876/1372 1185/1877/1373 +f 322/1874/1370 1185/1877/1373 1876/1861/1360 +f 322/1874/1370 1876/1861/1360 1181/1860/1359 +f 322/1874/1370 1181/1860/1359 1878/1864/1363 +f 322/1874/1370 1878/1864/1363 1186/1878/1374 +f 322/1874/1370 1186/1878/1374 1880/1879/1375 +f 322/1874/1370 1880/1879/1375 1187/1875/1371 +f 323/1880/1376 1190/1881/1377 1819/1882/1378 +f 323/1880/1376 1819/1882/1378 1188/1883/1379 +f 323/1880/1376 1188/1883/1379 1883/1884/1380 +f 323/1880/1376 1883/1884/1380 1189/1885/1381 +f 323/1880/1376 1189/1885/1381 1879/1872/1369 +f 323/1880/1376 1879/1872/1369 1183/1871/1368 +f 323/1880/1376 1183/1871/1368 1881/1870/1367 +f 323/1880/1376 1881/1870/1367 1190/1881/1377 +f 324/1886/1382 1187/1875/1371 1880/1879/1375 +f 324/1886/1382 1880/1879/1375 1191/1887/1383 +f 324/1888/1382 1191/1889/1383 1884/1890/1384 +f 324/1888/1382 1884/1890/1384 1192/1891/1385 +f 324/1886/1382 1192/1892/1385 1820/1893/1386 +f 324/1886/1382 1820/1893/1386 1193/1894/1387 +f 324/1886/1382 1193/1894/1387 1882/1876/1372 +f 324/1886/1382 1882/1876/1372 1187/1875/1371 +f 325/1895/1388 1195/1896/1389 1821/1779/1292 +f 325/1895/1388 1821/1779/1292 1161/1824/1325 +f 325/1895/1388 1161/1824/1325 1859/1811/1316 +f 325/1895/1388 1859/1811/1316 1194/1897/1390 +f 325/1895/1388 1194/1897/1390 1879/1872/1369 +f 325/1895/1388 1879/1872/1369 1189/1885/1381 +f 325/1895/1388 1189/1885/1381 1883/1884/1380 +f 325/1895/1388 1883/1884/1380 1195/1896/1389 +f 326/1898/1391 1191/1889/1383 1880/1899/1375 +f 326/1898/1391 1880/1899/1375 1196/1900/1392 +f 326/1898/1391 1196/1900/1392 1860/1827/1321 +f 326/1898/1391 1860/1827/1321 1163/1826/1327 +f 326/1898/1391 1163/1826/1327 1822/1785/1296 +f 326/1898/1391 1822/1785/1296 1197/1901/1393 +f 326/1898/1391 1197/1901/1393 1884/1890/1384 +f 326/1898/1391 1884/1890/1384 1191/1889/1383 +f 327/1902/1394 1194/1897/1390 1859/1811/1316 +f 327/1902/1394 1859/1811/1316 1156/1810/1315 +f 327/1903/1394 1156/1808/1315 1861/1794/1304 +f 327/1903/1394 1861/1794/1304 1198/1904/1395 +f 327/1903/1394 1198/1904/1395 1877/1858/1357 +f 327/1903/1394 1877/1858/1357 1184/1866/1365 +f 327/1902/1394 1184/1873/1365 1879/1872/1369 +f 327/1902/1394 1879/1872/1369 1194/1897/1390 +f 328/1905/1396 1186/1878/1374 1878/1864/1363 +f 328/1905/1396 1878/1864/1363 1199/1906/1397 +f 328/1905/1396 1199/1906/1397 1862/1799/1309 +f 328/1905/1396 1862/1799/1309 1159/1818/1322 +f 328/1905/1396 1159/1818/1322 1860/1817/1321 +f 328/1905/1396 1860/1817/1321 1196/1907/1392 +f 328/1905/1396 1196/1907/1392 1880/1879/1375 +f 328/1905/1396 1880/1879/1375 1186/1878/1374 +f 329/1908/1398 1198/1904/1395 1861/1794/1304 +f 329/1908/1398 1861/1794/1304 1150/1793/1303 +f 329/1908/1398 1150/1793/1303 1863/1792/1302 +f 329/1908/1398 1863/1792/1302 1200/1909/1399 +f 329/1908/1398 1200/1909/1399 1871/1846/1345 +f 329/1908/1398 1871/1846/1345 1178/1854/1353 +f 329/1908/1398 1178/1854/1353 1877/1858/1357 +f 329/1908/1398 1877/1858/1357 1198/1904/1395 +f 330/1910/1400 1180/1863/1362 1872/1852/1351 +f 330/1910/1400 1872/1852/1351 1201/1911/1401 +f 330/1910/1400 1201/1911/1401 1864/1912/1311 +f 330/1910/1400 1864/1912/1311 1153/1800/1310 +f 330/1910/1400 1153/1800/1310 1862/1799/1309 +f 330/1910/1400 1862/1799/1309 1199/1906/1397 +f 330/1910/1400 1199/1906/1397 1878/1864/1363 +f 330/1910/1400 1878/1864/1363 1180/1863/1362 +f 331/1913/1402 1200/1909/1399 1863/1792/1302 +f 331/1913/1402 1863/1792/1302 1202/1914/1403 +f 331/1913/1402 1202/1914/1403 1865/1915/1404 +f 331/1913/1402 1865/1915/1404 1203/1916/1405 +f 331/1913/1402 1203/1916/1405 1869/1834/1333 +f 331/1913/1402 1869/1834/1333 1172/1842/1341 +f 331/1913/1402 1172/1842/1341 1871/1846/1345 +f 331/1913/1402 1871/1846/1345 1200/1909/1399 +f 332/1917/1406 1174/1851/1350 1870/1840/1339 +f 332/1917/1406 1870/1840/1339 1204/1918/1407 +f 332/1917/1406 1204/1918/1407 1866/1919/1408 +f 332/1917/1406 1866/1919/1408 1205/1920/1409 +f 332/1917/1406 1205/1920/1409 1864/1912/1311 +f 332/1917/1406 1864/1912/1311 1201/1911/1401 +f 332/1917/1406 1201/1911/1401 1872/1852/1351 +f 332/1917/1406 1872/1852/1351 1174/1851/1350 +f 333/1921/1410 1206/1922/1411 1795/1475/1074 +f 333/1921/1410 1795/1475/1074 1041/1489/1083 +f 333/1923/1410 1041/1487/1083 1797/1486/1082 +f 333/1923/1410 1797/1486/1082 1166/1829/1329 +f 333/1923/1410 1166/1829/1329 1869/1834/1333 +f 333/1923/1410 1869/1834/1333 1203/1916/1405 +f 333/1923/1410 1203/1916/1405 1865/1915/1404 +f 333/1923/1410 1865/1915/1404 1206/1924/1411 +f 334/1925/1412 1204/1918/1407 1870/1840/1339 +f 334/1925/1412 1870/1840/1339 1168/1839/1338 +f 334/1925/1412 1168/1839/1338 1798/1492/1086 +f 334/1925/1412 1798/1492/1086 1043/1491/1085 +f 334/1925/1412 1043/1491/1085 1796/1494/1078 +f 334/1925/1412 1796/1494/1078 1207/1926/1413 +f 334/1925/1412 1207/1926/1413 1866/1919/1408 +f 334/1925/1412 1866/1919/1408 1204/1918/1407 +f 335/1927/1414 1209/1928/1415 1579/1929/1416 +f 335/1927/1414 1579/1929/1416 1208/1930/1417 +f 335/1927/1414 1208/1930/1417 1865/1915/1404 +f 335/1927/1414 1865/1915/1404 1202/1914/1403 +f 335/1927/1414 1202/1914/1403 1863/1792/1302 +f 335/1927/1414 1863/1792/1302 1149/1791/1301 +f 335/1927/1414 1149/1791/1301 1807/1790/1300 +f 335/1927/1414 1807/1790/1300 1209/1928/1415 +f 336/1931/1418 1154/1804/1312 1864/1803/1311 +f 336/1931/1418 1864/1803/1311 1205/1932/1409 +f 336/1931/1418 1205/1932/1409 1866/1933/1408 +f 336/1931/1418 1866/1933/1408 1210/1934/1419 +f 336/1931/1418 1210/1934/1419 1579/1929/1416 +f 336/1931/1418 1579/1929/1416 1209/1928/1415 +f 336/1931/1418 1209/1928/1415 1807/1790/1300 +f 336/1931/1418 1807/1790/1300 1154/1804/1312 +f 337/1935/1420 1211/1936/1421 1789/1937/1049 +f 337/1935/1420 1789/1937/1049 1029/1938/1059 +f 337/1935/1420 1029/1938/1059 1791/1463/1058 +f 337/1935/1420 1791/1463/1058 1033/1462/1067 +f 337/1935/1420 1033/1462/1067 1793/1461/1066 +f 337/1935/1420 1793/1461/1066 1037/1476/1075 +f 337/1935/1420 1037/1476/1075 1795/1475/1074 +f 337/1935/1420 1795/1475/1074 1211/1936/1421 +f 338/1939/1422 1039/1478/1077 1794/1467/1070 +f 338/1939/1422 1794/1467/1070 1035/1466/1069 +f 338/1939/1422 1035/1466/1069 1792/1450/1062 +f 338/1939/1422 1792/1450/1062 1031/1449/1061 +f 338/1939/1422 1031/1449/1061 1790/1455/1054 +f 338/1939/1422 1790/1455/1054 1212/1940/1423 +f 338/1939/1422 1212/1940/1423 1796/1479/1078 +f 338/1939/1422 1796/1479/1078 1039/1478/1077 +f 339/1941/1424 1213/1942/1425 1789/1943/1049 +f 339/1941/1424 1789/1943/1049 1211/1944/1421 +f 339/1945/1424 1211/1936/1421 1795/1475/1074 +f 339/1945/1424 1795/1475/1074 1206/1922/1411 +f 339/1941/1424 1206/1924/1411 1865/1915/1404 +f 339/1941/1424 1865/1915/1404 1208/1930/1417 +f 339/1941/1424 1208/1930/1417 1579/1929/1416 +f 339/1941/1424 1579/1929/1416 1213/1942/1425 +f 340/1946/1426 1210/1934/1419 1866/1933/1408 +f 340/1946/1426 1866/1933/1408 1207/1947/1413 +f 340/1948/1426 1207/1949/1413 1796/1479/1078 +f 340/1948/1426 1796/1479/1078 1212/1940/1423 +f 340/1946/1426 1212/1950/1423 1790/1440/1054 +f 340/1946/1426 1790/1440/1054 1214/1951/1427 +f 340/1946/1426 1214/1951/1427 1579/1929/1416 +f 340/1946/1426 1579/1929/1416 1210/1934/1419 +f 341/1952/1428 1215/1953/1429 1578/1443/1051 +f 341/1952/1428 1578/1443/1051 1024/1954/1050 +f 341/1952/1428 1024/1954/1050 1789/1943/1049 +f 341/1952/1428 1789/1943/1049 1213/1942/1425 +f 341/1952/1428 1213/1942/1425 1579/1929/1416 +f 341/1952/1428 1579/1929/1416 1215/1953/1429 +f 342/1955/1430 1215/1953/1429 1579/1929/1416 +f 342/1955/1430 1579/1929/1416 1214/1951/1427 +f 342/1955/1430 1214/1951/1427 1790/1440/1054 +f 342/1955/1430 1790/1440/1054 1027/1439/1053 +f 342/1955/1430 1027/1439/1053 1578/1443/1051 +f 342/1955/1430 1578/1443/1051 1215/1953/1429 +f 343/1956/1431 1164/1957/1330 1799/1511/1090 +f 343/1956/1431 1799/1511/1090 1049/1510/1099 +f 343/1956/1431 1049/1510/1099 1801/1509/1098 +f 343/1956/1431 1801/1509/1098 1140/1764/1277 +f 343/1956/1431 1140/1764/1277 1815/1768/1281 +f 343/1956/1431 1815/1768/1281 1216/1958/1432 +f 343/1959/1431 1216/1960/1432 1867/1832/1331 +f 343/1959/1431 1867/1832/1331 1164/1831/1330 +f 344/1961/1433 1217/1962/1434 1816/1963/1287 +f 344/1961/1433 1816/1963/1287 1142/1964/1286 +f 344/1961/1433 1142/1964/1286 1802/1514/1102 +f 344/1961/1433 1802/1514/1102 1051/1513/1101 +f 344/1961/1433 1051/1513/1101 1800/1504/1094 +f 344/1961/1433 1800/1504/1094 1167/1838/1337 +f 344/1961/1433 1167/1838/1337 1868/1837/1336 +f 344/1961/1433 1868/1837/1336 1217/1962/1434 +f 345/1965/1435 1216/1958/1432 1815/1768/1281 +f 345/1965/1435 1815/1768/1281 1218/1966/1436 +f 345/1965/1435 1218/1966/1436 1817/1967/1437 +f 345/1965/1435 1817/1967/1437 1219/1968/1438 +f 345/1965/1435 1219/1968/1438 1873/1969/1343 +f 345/1965/1435 1873/1969/1343 1170/1970/1342 +f 345/1965/1435 1170/1970/1342 1867/1971/1331 +f 345/1965/1435 1867/1971/1331 1216/1958/1432 +f 346/1972/1439 1173/1850/1349 1874/1849/1348 +f 346/1972/1439 1874/1849/1348 1220/1973/1440 +f 346/1972/1439 1220/1973/1440 1818/1974/1441 +f 346/1972/1439 1818/1974/1441 1221/1975/1442 +f 346/1972/1439 1221/1975/1442 1816/1963/1287 +f 346/1972/1439 1816/1963/1287 1217/1962/1434 +f 346/1972/1439 1217/1962/1434 1868/1837/1336 +f 346/1972/1439 1868/1837/1336 1173/1850/1349 +f 347/1976/1443 1219/1968/1438 1817/1967/1437 +f 347/1976/1443 1817/1967/1437 1222/1977/1444 +f 347/1976/1443 1222/1977/1444 1887/1978/1445 +f 347/1976/1443 1887/1978/1445 1223/1979/1446 +f 347/1976/1443 1223/1979/1446 1875/1980/1355 +f 347/1976/1443 1875/1980/1355 1176/1981/1354 +f 347/1976/1443 1176/1981/1354 1873/1969/1343 +f 347/1976/1443 1873/1969/1343 1219/1968/1438 +f 348/1982/1447 1179/1862/1361 1876/1861/1360 +f 348/1982/1447 1876/1861/1360 1224/1983/1448 +f 348/1982/1447 1224/1983/1448 1888/1984/1449 +f 348/1982/1447 1888/1984/1449 1225/1985/1450 +f 348/1982/1447 1225/1985/1450 1818/1974/1441 +f 348/1982/1447 1818/1974/1441 1220/1973/1440 +f 348/1982/1447 1220/1973/1440 1874/1849/1348 +f 348/1982/1447 1874/1849/1348 1179/1862/1361 +f 349/1986/1451 1226/1987/1452 1819/1988/1378 +f 349/1986/1451 1819/1988/1378 1190/1989/1377 +f 349/1986/1451 1190/1989/1377 1881/1990/1367 +f 349/1986/1451 1881/1990/1367 1182/1991/1366 +f 349/1986/1451 1182/1991/1366 1875/1980/1355 +f 349/1986/1451 1875/1980/1355 1223/1979/1446 +f 349/1986/1451 1223/1979/1446 1887/1978/1445 +f 349/1986/1451 1887/1978/1445 1226/1987/1452 +f 350/1992/1453 1224/1983/1448 1876/1861/1360 +f 350/1992/1453 1876/1861/1360 1185/1877/1373 +f 350/1992/1453 1185/1877/1373 1882/1876/1372 +f 350/1992/1453 1882/1876/1372 1193/1894/1387 +f 350/1992/1453 1193/1894/1387 1820/1893/1386 +f 350/1992/1453 1820/1893/1386 1227/1993/1454 +f 350/1992/1453 1227/1993/1454 1888/1984/1449 +f 350/1992/1453 1888/1984/1449 1224/1983/1448 +f 351/1994/1455 1230/1995/1456 1853/1740/1260 +f 351/1994/1455 1853/1740/1260 1128/1739/1259 +f 351/1994/1455 1128/1739/1259 1855/1738/1250 +f 351/1994/1455 1855/1738/1250 1228/1996/1457 +f 351/1994/1455 1228/1996/1457 1891/1997/1458 +f 351/1994/1455 1891/1997/1458 1229/1998/1459 +f 351/1994/1455 1229/1998/1459 1889/1999/1460 +f 351/1994/1455 1889/1999/1460 1230/1995/1456 +f 352/2000/1461 1233/2001/1462 1892/2002/1463 +f 352/2000/1461 1892/2002/1463 1231/2003/1464 +f 352/2000/1461 1231/2003/1464 1856/1732/1255 +f 352/2000/1461 1856/1732/1255 1131/1747/1266 +f 352/2000/1461 1131/1747/1266 1854/1746/1265 +f 352/2000/1461 1854/1746/1265 1232/2004/1465 +f 352/2000/1461 1232/2004/1465 1890/2005/1466 +f 352/2000/1461 1890/2005/1466 1233/2001/1462 +f 353/2006/1467 1236/2007/1468 1823/1766/1279 +f 353/2006/1467 1823/1766/1279 1234/2008/1469 +f 353/2006/1467 1234/2008/1469 1889/1999/1460 +f 353/2006/1467 1889/1999/1460 1229/1998/1459 +f 353/2006/1467 1229/1998/1459 1891/1997/1458 +f 353/2006/1467 1891/1997/1458 1235/2009/1470 +f 353/2006/1467 1235/2009/1470 1825/2010/1471 +f 353/2006/1467 1825/2010/1471 1236/2007/1468 +f 354/2011/1472 1239/2012/1473 1892/2002/1463 +f 354/2011/1472 1892/2002/1463 1233/2001/1462 +f 354/2011/1472 1233/2001/1462 1890/2005/1466 +f 354/2011/1472 1890/2005/1466 1237/2013/1474 +f 354/2011/1472 1237/2013/1474 1824/1771/1284 +f 354/2011/1472 1824/1771/1284 1238/2014/1475 +f 354/2011/1472 1238/2014/1475 1826/2015/1476 +f 354/2011/1472 1826/2015/1476 1239/2012/1473 +f 355/2016/1477 1138/1765/1278 1803/1523/1106 +f 355/2016/1477 1803/1523/1106 1057/1535/1115 +f 355/2016/1477 1057/1535/1115 1805/1534/1114 +f 355/2016/1477 1805/1534/1114 1240/2017/1478 +f 355/2016/1477 1240/2017/1478 1889/1999/1460 +f 355/2016/1477 1889/1999/1460 1234/2008/1469 +f 355/2016/1477 1234/2008/1469 1823/1766/1279 +f 355/2016/1477 1823/1766/1279 1138/1765/1278 +f 356/2018/1479 1237/2013/1474 1890/2005/1466 +f 356/2018/1479 1890/2005/1466 1241/2019/1480 +f 356/2018/1479 1241/2019/1480 1806/1538/1118 +f 356/2018/1479 1806/1538/1118 1059/1537/1117 +f 356/2018/1479 1059/1537/1117 1804/1527/1110 +f 356/2018/1479 1804/1527/1110 1141/1772/1285 +f 356/2018/1479 1141/1772/1285 1824/1771/1284 +f 356/2018/1479 1824/1771/1284 1237/2013/1474 +f 357/2020/1481 1240/2017/1478 1805/1534/1114 +f 357/2020/1481 1805/1534/1114 1242/2021/1482 +f 357/2020/1481 1242/2021/1482 1849/1672/1208 +f 357/2020/1481 1849/1672/1208 1103/1671/1207 +f 357/2020/1481 1103/1671/1207 1847/1670/1206 +f 357/2020/1481 1847/1670/1206 1243/2022/1483 +f 357/2020/1481 1243/2022/1483 1889/1999/1460 +f 357/2020/1481 1889/1999/1460 1240/2017/1478 +f 358/2023/1484 1245/2024/1485 1848/1762/1214 +f 358/2023/1484 1848/1762/1214 1105/2025/1213 +f 358/2026/1484 1105/817/1213 1850/2027/1212 +f 358/2026/1484 1850/2027/1212 1244/2028/1486 +f 358/2023/1484 1244/2029/1486 1806/1538/1118 +f 358/2023/1484 1806/1538/1118 1241/2019/1480 +f 358/2023/1484 1241/2019/1480 1890/2005/1466 +f 358/2023/1484 1890/2005/1466 1245/2024/1485 +f 359/2030/1487 1243/2022/1483 1847/1670/1206 +f 359/2030/1487 1847/1670/1206 1136/1756/1273 +f 359/2030/1487 1136/1756/1273 1853/1740/1260 +f 359/2030/1487 1853/1740/1260 1230/1995/1456 +f 359/2030/1487 1230/1995/1456 1889/1999/1460 +f 359/2030/1487 1889/1999/1460 1243/2022/1483 +f 360/2031/1488 1245/2024/1485 1890/2005/1466 +f 360/2031/1488 1890/2005/1466 1232/2004/1465 +f 360/2031/1488 1232/2004/1465 1854/1746/1265 +f 360/2031/1488 1854/1746/1265 1137/1758/1275 +f 360/2031/1488 1137/1758/1275 1848/1762/1214 +f 360/2031/1488 1848/1762/1214 1245/2024/1485 +f 361/2032/1489 1242/2021/1482 1805/1534/1114 +f 361/2032/1489 1805/1534/1114 1114/1696/1229 +f 361/2032/1489 1114/1696/1229 1851/1687/1223 +f 361/2032/1489 1851/1687/1223 1110/1686/1222 +f 361/2032/1489 1110/1686/1222 1849/1672/1208 +f 361/2032/1489 1849/1672/1208 1242/2021/1482 +f 362/2033/1490 1244/2028/1486 1850/2027/1212 +f 362/2033/1490 1850/2027/1212 1113/2034/1225 +f 362/2035/1490 1113/1694/1225 1852/1693/1227 +f 362/2035/1490 1852/1693/1227 1115/1704/1231 +f 362/2033/1490 1115/2036/1231 1806/2037/1118 +f 362/2033/1490 1806/2037/1118 1244/2028/1486 +f 363/2038/1491 1188/1883/1379 1819/1882/1378 +f 363/2038/1491 1819/1882/1378 1246/2039/1492 +f 363/2038/1491 1246/2039/1492 1827/2040/1493 +f 363/2038/1491 1827/2040/1493 1247/2041/1494 +f 363/2038/1491 1247/2041/1494 1885/2042/1495 +f 363/2038/1491 1885/2042/1495 1248/2043/1496 +f 363/2038/1491 1248/2043/1496 1883/1884/1380 +f 363/2038/1491 1883/1884/1380 1188/1883/1379 +f 364/2044/1497 1251/2045/1498 1886/2046/1499 +f 364/2044/1497 1886/2046/1499 1249/2047/1500 +f 364/2044/1497 1249/2047/1500 1828/2048/1501 +f 364/2044/1497 1828/2048/1501 1250/2049/1502 +f 364/2044/1497 1250/2049/1502 1820/2050/1386 +f 364/2044/1497 1820/2050/1386 1192/2051/1385 +f 364/2044/1497 1192/2051/1385 1884/2052/1384 +f 364/2044/1497 1884/2052/1384 1251/2045/1498 +f 365/2053/1503 1145/1780/1293 1821/1779/1292 +f 365/2053/1503 1821/1779/1292 1195/1896/1389 +f 365/2053/1503 1195/1896/1389 1883/1884/1380 +f 365/2053/1503 1883/1884/1380 1248/2043/1496 +f 365/2053/1503 1248/2043/1496 1885/2042/1495 +f 365/2053/1503 1885/2042/1495 1252/2054/1504 +f 365/2053/1503 1252/2054/1504 1829/1709/1236 +f 365/2053/1503 1829/1709/1236 1145/1780/1293 +f 366/2055/1505 1253/2056/1506 1886/2046/1499 +f 366/2055/1505 1886/2046/1499 1251/2045/1498 +f 366/2055/1505 1251/2045/1498 1884/2052/1384 +f 366/2055/1505 1884/2052/1384 1197/2057/1393 +f 366/2058/1505 1197/1901/1393 1822/1785/1296 +f 366/2058/1505 1822/1785/1296 1147/1784/1295 +f 366/2055/1505 1147/1782/1295 1830/1721/1245 +f 366/2055/1505 1830/1721/1245 1253/2056/1506 +f 367/2059/1507 1255/2060/1508 1825/2061/1471 +f 367/2059/1507 1825/2061/1471 1235/2062/1470 +f 367/2063/1507 1235/2009/1470 1891/1997/1458 +f 367/2063/1507 1891/1997/1458 1254/2064/1509 +f 367/2063/1507 1254/2064/1509 1885/2065/1495 +f 367/2063/1507 1885/2065/1495 1247/2066/1494 +f 367/2059/1507 1247/2067/1494 1827/2068/1493 +f 367/2059/1507 1827/2068/1493 1255/2060/1508 +f 368/2069/1510 1249/2047/1500 1886/2046/1499 +f 368/2069/1510 1886/2046/1499 1256/2070/1511 +f 368/2069/1510 1256/2070/1511 1892/2002/1463 +f 368/2069/1510 1892/2002/1463 1239/2012/1473 +f 368/2069/1510 1239/2012/1473 1826/2015/1476 +f 368/2069/1510 1826/2015/1476 1257/2071/1512 +f 368/2069/1510 1257/2071/1512 1828/2048/1501 +f 368/2069/1510 1828/2048/1501 1249/2047/1500 +f 369/2072/1513 1228/1996/1457 1855/1738/1250 +f 369/2072/1513 1855/1738/1250 1123/2073/1249 +f 369/2072/1513 1123/2073/1249 1857/2074/1238 +f 369/2072/1513 1857/2074/1238 1258/2075/1514 +f 369/2072/1513 1258/2075/1514 1885/2065/1495 +f 369/2072/1513 1885/2065/1495 1254/2064/1509 +f 369/2072/1513 1254/2064/1509 1891/1997/1458 +f 369/2072/1513 1891/1997/1458 1228/1996/1457 +f 370/2076/1515 1256/2070/1511 1886/2046/1499 +f 370/2076/1515 1886/2046/1499 1259/2077/1516 +f 370/2076/1515 1259/2077/1516 1858/1719/1243 +f 370/2076/1515 1858/1719/1243 1126/1733/1256 +f 370/2076/1515 1126/1733/1256 1856/1732/1255 +f 370/2076/1515 1856/1732/1255 1231/2003/1464 +f 370/2076/1515 1231/2003/1464 1892/2002/1463 +f 370/2076/1515 1892/2002/1463 1256/2070/1511 +f 371/2078/1517 1117/1710/1237 1829/1709/1236 +f 371/2078/1517 1829/1709/1236 1252/2054/1504 +f 371/2079/1517 1252/2080/1504 1885/2065/1495 +f 371/2079/1517 1885/2065/1495 1258/2075/1514 +f 371/2079/1517 1258/2075/1514 1857/2074/1238 +f 371/2079/1517 1857/2074/1238 1117/2081/1237 +f 372/2082/1518 1120/1720/1244 1858/1719/1243 +f 372/2082/1518 1858/1719/1243 1259/2077/1516 +f 372/2082/1518 1259/2077/1516 1886/2046/1499 +f 372/2082/1518 1886/2046/1499 1253/2056/1506 +f 372/2082/1518 1253/2056/1506 1830/1721/1245 +f 372/2082/1518 1830/1721/1245 1120/1720/1244 +f 373/2083/1519 1263/2084/1520 1905/2085/1521 +f 373/2083/1519 1905/2085/1521 1260/2086/1522 +f 373/2083/1519 1260/2086/1522 1893/2087/1523 +f 373/2083/1519 1893/2087/1523 1261/2088/1524 +f 373/2089/1519 1261/2090/1524 1919/2091/1525 +f 373/2089/1519 1919/2091/1525 1262/2092/1526 +f 373/2089/1519 1262/2092/1526 1907/2093/1527 +f 373/2089/1519 1907/2093/1527 1263/2094/1520 +f 374/2095/1528 1267/2096/1529 1920/2097/1530 +f 374/2095/1528 1920/2097/1530 1264/2098/1531 +f 374/2099/1528 1264/2100/1531 1894/2101/1532 +f 374/2099/1528 1894/2101/1532 1265/2102/1533 +f 374/2099/1528 1265/2102/1533 1906/2103/1534 +f 374/2099/1528 1906/2103/1534 1266/2104/1535 +f 374/2095/1528 1266/2105/1535 1908/2106/1536 +f 374/2095/1528 1908/2106/1536 1267/2096/1529 +f 375/2107/1537 1270/2108/1538 1905/2085/1521 +f 375/2107/1537 1905/2085/1521 1263/2084/1520 +f 375/2109/1537 1263/2094/1520 1907/2093/1527 +f 375/2109/1537 1907/2093/1527 1268/2110/1539 +f 375/2109/1537 1268/2110/1539 1909/2111/1540 +f 375/2109/1537 1909/2111/1540 1269/2112/1541 +f 375/2107/1537 1269/2113/1541 1903/2114/1542 +f 375/2107/1537 1903/2114/1542 1270/2108/1538 +f 376/2115/1543 1273/2116/1544 1910/2117/1545 +f 376/2115/1543 1910/2117/1545 1271/2118/1546 +f 376/2115/1543 1271/2118/1546 1908/2106/1536 +f 376/2115/1543 1908/2106/1536 1266/2105/1535 +f 376/2119/1543 1266/2104/1535 1906/2103/1534 +f 376/2119/1543 1906/2103/1534 1272/2120/1547 +f 376/2121/1543 1272/2122/1547 1904/2123/1548 +f 376/2121/1543 1904/2123/1548 1273/2124/1544 +f 377/2125/1549 1276/2126/1550 1903/2114/1542 +f 377/2125/1549 1903/2114/1542 1269/2113/1541 +f 377/2127/1549 1269/2112/1541 1909/2111/1540 +f 377/2127/1549 1909/2111/1540 1274/2128/1551 +f 377/2127/1549 1274/2128/1551 1911/2129/1552 +f 377/2127/1549 1911/2129/1552 1275/2130/1553 +f 377/2125/1549 1275/2131/1553 1901/2132/1554 +f 377/2125/1549 1901/2132/1554 1276/2126/1550 +f 378/2133/1555 1279/2134/1556 1912/2135/1557 +f 378/2133/1555 1912/2135/1557 1277/2136/1558 +f 378/2133/1555 1277/2136/1558 1910/2117/1545 +f 378/2133/1555 1910/2117/1545 1273/2116/1544 +f 378/2133/1555 1273/2116/1544 1904/2137/1548 +f 378/2133/1555 1904/2137/1548 1278/2138/1559 +f 378/2133/1555 1278/2138/1559 1902/2139/1560 +f 378/2133/1555 1902/2139/1560 1279/2134/1556 +f 379/2140/1561 1282/2141/1562 1901/2142/1554 +f 379/2140/1561 1901/2142/1554 1275/2130/1553 +f 379/2140/1561 1275/2130/1553 1911/2129/1552 +f 379/2140/1561 1911/2129/1552 1280/2143/1563 +f 379/2140/1561 1280/2143/1563 1913/2144/1564 +f 379/2140/1561 1913/2144/1564 1281/2145/1565 +f 379/2140/1561 1281/2145/1565 1899/2146/1566 +f 379/2140/1561 1899/2146/1566 1282/2141/1562 +f 380/2147/1567 1285/2148/1568 1914/2149/1569 +f 380/2147/1567 1914/2149/1569 1283/2150/1570 +f 380/2147/1567 1283/2150/1570 1912/2135/1557 +f 380/2147/1567 1912/2135/1557 1279/2134/1556 +f 380/2147/1567 1279/2134/1556 1902/2139/1560 +f 380/2147/1567 1902/2139/1560 1284/2151/1571 +f 380/2147/1567 1284/2151/1571 1900/2152/1572 +f 380/2147/1567 1900/2152/1572 1285/2148/1568 +f 381/2153/1573 1288/2154/1574 1899/2155/1566 +f 381/2153/1573 1899/2155/1566 1281/2156/1565 +f 381/2157/1573 1281/2145/1565 1913/2144/1564 +f 381/2157/1573 1913/2144/1564 1286/2158/1575 +f 381/2159/1573 1286/2160/1575 1915/2161/1576 +f 381/2159/1573 1915/2161/1576 1287/2162/1577 +f 381/2153/1573 1287/2163/1577 1897/2164/1578 +f 381/2153/1573 1897/2164/1578 1288/2154/1574 +f 382/2165/1579 1291/2166/1580 1916/2167/1581 +f 382/2165/1579 1916/2167/1581 1289/2168/1582 +f 382/2165/1579 1289/2168/1582 1914/2149/1569 +f 382/2165/1579 1914/2149/1569 1285/2148/1568 +f 382/2165/1579 1285/2148/1568 1900/2152/1572 +f 382/2165/1579 1900/2152/1572 1290/2169/1583 +f 382/2165/1579 1290/2169/1583 1898/2170/1584 +f 382/2165/1579 1898/2170/1584 1291/2166/1580 +f 383/2171/1585 1294/2172/1586 1897/2164/1578 +f 383/2171/1585 1897/2164/1578 1287/2163/1577 +f 383/2171/1585 1287/2163/1577 1915/2173/1576 +f 383/2171/1585 1915/2173/1576 1292/2174/1587 +f 383/2175/1585 1292/2176/1587 1917/2177/1588 +f 383/2175/1585 1917/2177/1588 1293/2178/1589 +f 383/2171/1585 1293/2179/1589 1895/2180/1590 +f 383/2171/1585 1895/2180/1590 1294/2172/1586 +f 384/2181/1591 1297/2182/1592 1918/2183/1593 +f 384/2181/1591 1918/2183/1593 1295/2184/1594 +f 384/2181/1591 1295/2184/1594 1916/2167/1581 +f 384/2181/1591 1916/2167/1581 1291/2166/1580 +f 384/2181/1591 1291/2166/1580 1898/2170/1584 +f 384/2181/1591 1898/2170/1584 1296/2185/1595 +f 384/2181/1591 1296/2185/1595 1896/2186/1596 +f 384/2181/1591 1896/2186/1596 1297/2182/1592 +f 385/2187/1597 1292/2188/1587 1915/2161/1576 +f 385/2187/1597 1915/2161/1576 1298/2189/1598 +f 385/2187/1597 1298/2189/1598 1925/2190/1599 +f 385/2187/1597 1925/2190/1599 1299/2191/1600 +f 385/2187/1597 1299/2191/1600 1923/2192/1601 +f 385/2187/1597 1923/2192/1601 1300/2193/1602 +f 385/2187/1597 1300/2193/1602 1917/2194/1588 +f 385/2187/1597 1917/2194/1588 1292/2188/1587 +f 386/2195/1603 1303/2196/1604 1924/2197/1605 +f 386/2195/1603 1924/2197/1605 1301/2198/1606 +f 386/2195/1603 1301/2198/1606 1926/2199/1607 +f 386/2195/1603 1926/2199/1607 1302/2200/1608 +f 386/2201/1603 1302/2202/1608 1916/2203/1581 +f 386/2201/1603 1916/2203/1581 1295/2204/1594 +f 386/2201/1603 1295/2204/1594 1918/2205/1593 +f 386/2201/1603 1918/2205/1593 1303/2206/1604 +f 387/2207/1609 1286/2160/1575 1913/2208/1564 +f 387/2207/1609 1913/2208/1564 1304/2209/1610 +f 387/2210/1609 1304/2211/1610 1927/2212/1611 +f 387/2210/1609 1927/2212/1611 1305/2213/1612 +f 387/2207/1609 1305/2214/1612 1925/2190/1599 +f 387/2207/1609 1925/2190/1599 1298/2189/1598 +f 387/2207/1609 1298/2189/1598 1915/2161/1576 +f 387/2207/1609 1915/2161/1576 1286/2160/1575 +f 388/2215/1613 1302/2200/1608 1926/2199/1607 +f 388/2215/1613 1926/2199/1607 1306/2216/1614 +f 388/2215/1613 1306/2216/1614 1928/2217/1615 +f 388/2215/1613 1928/2217/1615 1307/2218/1616 +f 388/2215/1613 1307/2218/1616 1914/2219/1569 +f 388/2215/1613 1914/2219/1569 1289/2220/1582 +f 388/2215/1613 1289/2220/1582 1916/2221/1581 +f 388/2215/1613 1916/2221/1581 1302/2200/1608 +f 389/2222/1617 1280/2143/1563 1911/2129/1552 +f 389/2222/1617 1911/2129/1552 1308/2223/1618 +f 389/2224/1617 1308/2225/1618 1929/2226/1619 +f 389/2224/1617 1929/2226/1619 1309/2227/1620 +f 389/2224/1617 1309/2227/1620 1927/2212/1611 +f 389/2224/1617 1927/2212/1611 1304/2211/1610 +f 389/2222/1617 1304/2228/1610 1913/2144/1564 +f 389/2222/1617 1913/2144/1564 1280/2143/1563 +f 390/2229/1621 1307/2218/1616 1928/2217/1615 +f 390/2229/1621 1928/2217/1615 1310/2230/1622 +f 390/2231/1621 1310/2232/1622 1930/2233/1623 +f 390/2231/1621 1930/2233/1623 1311/2234/1624 +f 390/2235/1621 1311/2236/1624 1912/2135/1557 +f 390/2235/1621 1912/2135/1557 1283/2150/1570 +f 390/2229/1621 1283/2237/1570 1914/2219/1569 +f 390/2229/1621 1914/2219/1569 1307/2218/1616 +f 391/2238/1625 1274/2128/1551 1909/2111/1540 +f 391/2238/1625 1909/2111/1540 1312/2239/1626 +f 391/2238/1625 1312/2239/1626 1931/2240/1627 +f 391/2238/1625 1931/2240/1627 1313/2241/1628 +f 391/2238/1625 1313/2241/1628 1929/2242/1619 +f 391/2238/1625 1929/2242/1619 1308/2223/1618 +f 391/2238/1625 1308/2223/1618 1911/2129/1552 +f 391/2238/1625 1911/2129/1552 1274/2128/1551 +f 392/2243/1629 1311/2234/1624 1930/2233/1623 +f 392/2243/1629 1930/2233/1623 1314/2244/1630 +f 392/2245/1629 1314/2246/1630 1932/2247/1631 +f 392/2245/1629 1932/2247/1631 1315/2248/1632 +f 392/2245/1629 1315/2248/1632 1910/2117/1545 +f 392/2245/1629 1910/2117/1545 1277/2136/1558 +f 392/2245/1629 1277/2136/1558 1912/2135/1557 +f 392/2245/1629 1912/2135/1557 1311/2236/1624 +f 393/2249/1633 1268/2250/1539 1907/2251/1527 +f 393/2249/1633 1907/2251/1527 1316/2252/1634 +f 393/2249/1633 1316/2252/1634 1933/2253/1635 +f 393/2249/1633 1933/2253/1635 1317/2254/1636 +f 393/2255/1633 1317/2256/1636 1931/2240/1627 +f 393/2255/1633 1931/2240/1627 1312/2239/1626 +f 393/2255/1633 1312/2239/1626 1909/2111/1540 +f 393/2255/1633 1909/2111/1540 1268/2110/1539 +f 394/2257/1637 1315/2248/1632 1932/2247/1631 +f 394/2257/1637 1932/2247/1631 1318/2258/1638 +f 394/2257/1637 1318/2258/1638 1934/2259/1639 +f 394/2257/1637 1934/2259/1639 1319/2260/1640 +f 394/2257/1637 1319/2260/1640 1908/2106/1536 +f 394/2257/1637 1908/2106/1536 1271/2118/1546 +f 394/2257/1637 1271/2118/1546 1910/2117/1545 +f 394/2257/1637 1910/2117/1545 1315/2248/1632 +f 395/2261/1641 1316/2252/1634 1907/2251/1527 +f 395/2261/1641 1907/2251/1527 1262/2262/1526 +f 395/2261/1641 1262/2262/1526 1919/2263/1525 +f 395/2261/1641 1919/2263/1525 1320/2264/1642 +f 395/2261/1641 1320/2264/1642 1921/2265/1643 +f 395/2261/1641 1921/2265/1643 1321/2266/1644 +f 395/2261/1641 1321/2266/1644 1933/2253/1635 +f 395/2261/1641 1933/2253/1635 1316/2252/1634 +f 396/2267/1645 1323/2268/1646 1922/2269/1647 +f 396/2267/1645 1922/2269/1647 1322/2270/1648 +f 396/2267/1645 1322/2270/1648 1920/2097/1530 +f 396/2267/1645 1920/2097/1530 1267/2096/1529 +f 396/2267/1645 1267/2096/1529 1908/2106/1536 +f 396/2267/1645 1908/2106/1536 1319/2260/1640 +f 396/2267/1645 1319/2260/1640 1934/2259/1639 +f 396/2267/1645 1934/2259/1639 1323/2268/1646 +f 397/2271/1649 1326/2272/1650 1823/1766/1279 +f 397/2271/1649 1823/1766/1279 1236/2007/1468 +f 397/2271/1649 1236/2007/1468 1825/2010/1471 +f 397/2271/1649 1825/2010/1471 1324/2273/1651 +f 397/2271/1649 1324/2273/1651 1949/2274/1652 +f 397/2271/1649 1949/2274/1652 1325/2275/1653 +f 397/2271/1649 1325/2275/1653 1947/2276/1654 +f 397/2271/1649 1947/2276/1654 1326/2272/1650 +f 398/2277/1655 1329/2278/1656 1950/2279/1657 +f 398/2277/1655 1950/2279/1657 1327/2280/1658 +f 398/2277/1655 1327/2280/1658 1826/2015/1476 +f 398/2277/1655 1826/2015/1476 1238/2014/1475 +f 398/2277/1655 1238/2014/1475 1824/1771/1284 +f 398/2277/1655 1824/1771/1284 1328/2281/1659 +f 398/2277/1655 1328/2281/1659 1948/2282/1660 +f 398/2277/1655 1948/2282/1660 1329/2278/1656 +f 399/2283/1661 1324/2284/1651 1825/2285/1471 +f 399/2283/1661 1825/2285/1471 1330/2286/1662 +f 399/2283/1661 1330/2286/1662 1895/2287/1590 +f 399/2283/1661 1895/2287/1590 1293/2178/1589 +f 399/2283/1661 1293/2178/1589 1917/2177/1588 +f 399/2283/1661 1917/2177/1588 1331/2288/1663 +f 399/2283/1661 1331/2288/1663 1949/2289/1652 +f 399/2283/1661 1949/2289/1652 1324/2284/1651 +f 400/2290/1664 1333/2291/1665 1918/2183/1593 +f 400/2290/1664 1918/2183/1593 1297/2182/1592 +f 400/2290/1664 1297/2182/1592 1896/2186/1596 +f 400/2290/1664 1896/2186/1596 1332/2292/1666 +f 400/2290/1664 1332/2292/1666 1826/2293/1476 +f 400/2290/1664 1826/2293/1476 1327/2294/1658 +f 400/2290/1664 1327/2294/1658 1950/2295/1657 +f 400/2290/1664 1950/2295/1657 1333/2291/1665 +f 401/2296/1667 1218/1966/1436 1815/1768/1281 +f 401/2296/1667 1815/1768/1281 1139/1767/1280 +f 401/2296/1667 1139/1767/1280 1823/1766/1279 +f 401/2296/1667 1823/1766/1279 1326/2272/1650 +f 401/2296/1667 1326/2272/1650 1947/2276/1654 +f 401/2296/1667 1947/2276/1654 1334/2297/1668 +f 401/2296/1667 1334/2297/1668 1817/1967/1437 +f 401/2296/1667 1817/1967/1437 1218/1966/1436 +f 402/2298/1669 1335/2299/1670 1948/2282/1660 +f 402/2298/1669 1948/2282/1660 1328/2281/1659 +f 402/2298/1669 1328/2281/1659 1824/1771/1284 +f 402/2298/1669 1824/1771/1284 1143/1770/1283 +f 402/2298/1669 1143/1770/1283 1816/1774/1287 +f 402/2298/1669 1816/1774/1287 1221/2300/1442 +f 402/2298/1669 1221/2300/1442 1818/2301/1441 +f 402/2298/1669 1818/2301/1441 1335/2299/1670 +f 403/2302/1671 1338/2303/1672 1887/2304/1445 +f 403/2302/1671 1887/2304/1445 1336/2305/1673 +f 403/2306/1671 1336/2307/1673 1935/2308/1674 +f 403/2306/1671 1935/2308/1674 1337/2309/1675 +f 403/2306/1671 1337/2309/1675 1919/2091/1525 +f 403/2306/1671 1919/2091/1525 1261/2090/1524 +f 403/2310/1671 1261/2311/1524 1893/2312/1523 +f 403/2310/1671 1893/2312/1523 1338/2313/1672 +f 404/2314/1676 1264/2098/1531 1920/2097/1530 +f 404/2314/1676 1920/2097/1530 1339/2315/1677 +f 404/2314/1676 1339/2315/1677 1936/2316/1678 +f 404/2314/1676 1936/2316/1678 1340/2317/1679 +f 404/2318/1676 1340/2319/1679 1888/2320/1449 +f 404/2318/1676 1888/2320/1449 1341/2321/1680 +f 404/2318/1676 1341/2321/1680 1894/2101/1532 +f 404/2318/1676 1894/2101/1532 1264/2100/1531 +f 405/2322/1681 1331/2323/1663 1917/2194/1588 +f 405/2322/1681 1917/2194/1588 1300/2193/1602 +f 405/2322/1681 1300/2193/1602 1923/2192/1601 +f 405/2322/1681 1923/2192/1601 1342/2324/1682 +f 405/2322/1681 1342/2324/1682 1945/2325/1683 +f 405/2322/1681 1945/2325/1683 1343/2326/1684 +f 405/2322/1681 1343/2326/1684 1949/2327/1652 +f 405/2322/1681 1949/2327/1652 1331/2323/1663 +f 406/2328/1685 1345/2329/1686 1946/2330/1687 +f 406/2328/1685 1946/2330/1687 1344/2331/1688 +f 406/2328/1685 1344/2331/1688 1924/2197/1605 +f 406/2328/1685 1924/2197/1605 1303/2196/1604 +f 406/2328/1685 1303/2196/1604 1918/2332/1593 +f 406/2328/1685 1918/2332/1593 1333/2333/1665 +f 406/2328/1685 1333/2333/1665 1950/2334/1657 +f 406/2328/1685 1950/2334/1657 1345/2329/1686 +f 407/2335/1689 1348/2336/1690 1943/2337/1691 +f 407/2335/1689 1943/2337/1691 1346/2338/1692 +f 407/2335/1689 1346/2338/1692 1951/2339/1693 +f 407/2335/1689 1951/2339/1693 1347/2340/1694 +f 407/2341/1689 1347/2342/1694 1949/2327/1652 +f 407/2341/1689 1949/2327/1652 1343/2326/1684 +f 407/2341/1689 1343/2326/1684 1945/2325/1683 +f 407/2341/1689 1945/2325/1683 1348/2343/1690 +f 408/2344/1695 1345/2345/1686 1950/2346/1657 +f 408/2344/1695 1950/2346/1657 1349/2347/1696 +f 408/2348/1695 1349/2349/1696 1952/2350/1697 +f 408/2348/1695 1952/2350/1697 1350/2351/1698 +f 408/2348/1695 1350/2351/1698 1944/2352/1699 +f 408/2348/1695 1944/2352/1699 1351/2353/1700 +f 408/2344/1695 1351/2354/1700 1946/2355/1687 +f 408/2344/1695 1946/2355/1687 1345/2345/1686 +f 409/2356/1701 1354/2357/1702 1939/2358/1703 +f 409/2356/1701 1939/2358/1703 1352/2359/1704 +f 409/2356/1701 1352/2359/1704 1951/2360/1693 +f 409/2356/1701 1951/2360/1693 1346/2361/1692 +f 409/2356/1701 1346/2361/1692 1943/2362/1691 +f 409/2356/1701 1943/2362/1691 1353/2363/1705 +f 409/2356/1701 1353/2363/1705 1941/2364/1706 +f 409/2356/1701 1941/2364/1706 1354/2357/1702 +f 410/2365/1707 1357/2366/1708 1944/2352/1699 +f 410/2365/1707 1944/2352/1699 1350/2351/1698 +f 410/2367/1707 1350/2368/1698 1952/2369/1697 +f 410/2367/1707 1952/2369/1697 1355/2370/1709 +f 410/2367/1707 1355/2370/1709 1940/2371/1710 +f 410/2367/1707 1940/2371/1710 1356/2372/1711 +f 410/2367/1707 1356/2372/1711 1942/2373/1712 +f 410/2367/1707 1942/2373/1712 1357/2374/1708 +f 411/2375/1713 1360/2376/1714 1937/2377/1715 +f 411/2375/1713 1937/2377/1715 1358/2378/1716 +f 411/2375/1713 1358/2378/1716 1953/2379/1717 +f 411/2375/1713 1953/2379/1717 1359/2380/1718 +f 411/2375/1713 1359/2380/1718 1951/2339/1693 +f 411/2375/1713 1951/2339/1693 1352/2381/1704 +f 411/2375/1713 1352/2381/1704 1939/2382/1703 +f 411/2375/1713 1939/2382/1703 1360/2376/1714 +f 412/2383/1719 1355/2384/1709 1952/2385/1697 +f 412/2383/1719 1952/2385/1697 1361/2386/1720 +f 412/2383/1719 1361/2386/1720 1954/2387/1721 +f 412/2383/1719 1954/2387/1721 1362/2388/1722 +f 412/2389/1719 1362/2390/1722 1938/2391/1723 +f 412/2389/1719 1938/2391/1723 1363/2392/1724 +f 412/2383/1719 1363/2393/1724 1940/2394/1710 +f 412/2383/1719 1940/2394/1710 1355/2384/1709 +f 413/2395/1725 1366/2396/1726 1935/2397/1674 +f 413/2395/1725 1935/2397/1674 1364/2398/1727 +f 413/2395/1725 1364/2398/1727 1953/2379/1717 +f 413/2395/1725 1953/2379/1717 1358/2378/1716 +f 413/2395/1725 1358/2378/1716 1937/2377/1715 +f 413/2395/1725 1937/2377/1715 1365/2399/1728 +f 413/2395/1725 1365/2399/1728 1955/2400/1729 +f 413/2395/1725 1955/2400/1729 1366/2396/1726 +f 414/2401/1730 1369/2402/1731 1938/2391/1723 +f 414/2401/1730 1938/2391/1723 1362/2390/1722 +f 414/2401/1730 1362/2390/1722 1954/2403/1721 +f 414/2401/1730 1954/2403/1721 1367/2404/1732 +f 414/2401/1730 1367/2404/1732 1936/2316/1678 +f 414/2401/1730 1936/2316/1678 1368/2405/1733 +f 414/2401/1730 1368/2405/1733 1956/2406/1734 +f 414/2401/1730 1956/2406/1734 1369/2402/1731 +f 415/2407/1735 1320/2264/1642 1919/2263/1525 +f 415/2407/1735 1919/2263/1525 1337/2408/1675 +f 415/2407/1735 1337/2408/1675 1935/2397/1674 +f 415/2407/1735 1935/2397/1674 1366/2396/1726 +f 415/2407/1735 1366/2396/1726 1955/2400/1729 +f 415/2407/1735 1955/2400/1729 1370/2409/1736 +f 415/2407/1735 1370/2409/1736 1921/2265/1643 +f 415/2407/1735 1921/2265/1643 1320/2264/1642 +f 416/2410/1737 1371/2411/1738 1956/2406/1734 +f 416/2410/1737 1956/2406/1734 1368/2405/1733 +f 416/2410/1737 1368/2405/1733 1936/2316/1678 +f 416/2410/1737 1936/2316/1678 1339/2315/1677 +f 416/2410/1737 1339/2315/1677 1920/2097/1530 +f 416/2410/1737 1920/2097/1530 1322/2270/1648 +f 416/2410/1737 1322/2270/1648 1922/2269/1647 +f 416/2410/1737 1922/2269/1647 1371/2411/1738 +f 417/2412/1739 1222/1977/1444 1817/1967/1437 +f 417/2412/1739 1817/1967/1437 1372/2413/1740 +f 417/2412/1739 1372/2413/1740 1953/2379/1717 +f 417/2412/1739 1953/2379/1717 1364/2398/1727 +f 417/2412/1739 1364/2398/1727 1935/2397/1674 +f 417/2412/1739 1935/2397/1674 1336/2414/1673 +f 417/2412/1739 1336/2414/1673 1887/1978/1445 +f 417/2412/1739 1887/1978/1445 1222/1977/1444 +f 418/2415/1741 1340/2317/1679 1936/2316/1678 +f 418/2415/1741 1936/2316/1678 1367/2404/1732 +f 418/2416/1741 1367/2417/1732 1954/2387/1721 +f 418/2416/1741 1954/2387/1721 1373/2418/1742 +f 418/2419/1741 1373/2420/1742 1818/1974/1441 +f 418/2419/1741 1818/1974/1441 1225/1985/1450 +f 418/2419/1741 1225/1985/1450 1888/1984/1449 +f 418/2419/1741 1888/1984/1449 1340/2421/1679 +f 419/2422/1743 1372/2413/1740 1817/1967/1437 +f 419/2422/1743 1817/1967/1437 1334/2297/1668 +f 419/2422/1743 1334/2297/1668 1947/2276/1654 +f 419/2422/1743 1947/2276/1654 1374/2423/1744 +f 419/2422/1743 1374/2423/1744 1951/2339/1693 +f 419/2422/1743 1951/2339/1693 1359/2380/1718 +f 419/2422/1743 1359/2380/1718 1953/2379/1717 +f 419/2422/1743 1953/2379/1717 1372/2413/1740 +f 420/2424/1745 1361/2386/1720 1952/2385/1697 +f 420/2424/1745 1952/2385/1697 1375/2425/1746 +f 420/2424/1745 1375/2425/1746 1948/2282/1660 +f 420/2424/1745 1948/2282/1660 1335/2299/1670 +f 420/2424/1745 1335/2299/1670 1818/2301/1441 +f 420/2424/1745 1818/2301/1441 1373/2418/1742 +f 420/2424/1745 1373/2418/1742 1954/2387/1721 +f 420/2424/1745 1954/2387/1721 1361/2386/1720 +f 421/2426/1747 1374/2423/1744 1947/2276/1654 +f 421/2426/1747 1947/2276/1654 1325/2275/1653 +f 421/2426/1747 1325/2275/1653 1949/2274/1652 +f 421/2426/1747 1949/2274/1652 1347/2340/1694 +f 421/2426/1747 1347/2340/1694 1951/2339/1693 +f 421/2426/1747 1951/2339/1693 1374/2423/1744 +f 422/2427/1748 1375/2428/1746 1952/2429/1697 +f 422/2427/1748 1952/2429/1697 1349/2347/1696 +f 422/2427/1748 1349/2347/1696 1950/2346/1657 +f 422/2427/1748 1950/2346/1657 1329/2430/1656 +f 422/2431/1748 1329/2278/1656 1948/2282/1660 +f 422/2431/1748 1948/2282/1660 1375/2425/1746 +f 423/2432/1749 1378/2433/1750 1921/2265/1643 +f 423/2432/1749 1921/2265/1643 1370/2409/1736 +f 423/2432/1749 1370/2409/1736 1955/2400/1729 +f 423/2432/1749 1955/2400/1729 1376/2434/1751 +f 423/2432/1749 1376/2434/1751 1957/2435/1752 +f 423/2432/1749 1957/2435/1752 1377/2436/1753 +f 423/2432/1749 1377/2436/1753 1981/2437/1754 +f 423/2432/1749 1981/2437/1754 1378/2433/1750 +f 424/2438/1755 1381/2439/1756 1958/2440/1757 +f 424/2438/1755 1958/2440/1757 1379/2441/1758 +f 424/2442/1755 1379/2443/1758 1956/2444/1734 +f 424/2442/1755 1956/2444/1734 1371/2445/1738 +f 424/2438/1755 1371/2411/1738 1922/2269/1647 +f 424/2438/1755 1922/2269/1647 1380/2446/1759 +f 424/2438/1755 1380/2446/1759 1982/2447/1760 +f 424/2438/1755 1982/2447/1760 1381/2439/1756 +f 425/2448/1761 1376/2434/1751 1955/2400/1729 +f 425/2448/1761 1955/2400/1729 1365/2399/1728 +f 425/2448/1761 1365/2399/1728 1937/2377/1715 +f 425/2448/1761 1937/2377/1715 1382/2449/1762 +f 425/2448/1761 1382/2449/1762 1967/2450/1763 +f 425/2448/1761 1967/2450/1763 1383/2451/1764 +f 425/2448/1761 1383/2451/1764 1957/2435/1752 +f 425/2448/1761 1957/2435/1752 1376/2434/1751 +f 426/2452/1765 1385/2453/1766 1968/2454/1767 +f 426/2452/1765 1968/2454/1767 1384/2455/1768 +f 426/2456/1765 1384/2457/1768 1938/2458/1723 +f 426/2456/1765 1938/2458/1723 1369/2459/1731 +f 426/2456/1765 1369/2459/1731 1956/2444/1734 +f 426/2456/1765 1956/2444/1734 1379/2443/1758 +f 426/2452/1765 1379/2441/1758 1958/2440/1757 +f 426/2452/1765 1958/2440/1757 1385/2453/1766 +f 427/2460/1769 1382/2449/1762 1937/2377/1715 +f 427/2460/1769 1937/2377/1715 1360/2376/1714 +f 427/2460/1769 1360/2376/1714 1939/2382/1703 +f 427/2460/1769 1939/2382/1703 1386/2461/1770 +f 427/2460/1769 1386/2461/1770 1965/2462/1771 +f 427/2460/1769 1965/2462/1771 1387/2463/1772 +f 427/2460/1769 1387/2463/1772 1967/2450/1763 +f 427/2460/1769 1967/2450/1763 1382/2449/1762 +f 428/2464/1773 1389/2465/1774 1966/2466/1775 +f 428/2464/1773 1966/2466/1775 1388/2467/1776 +f 428/2468/1773 1388/2469/1776 1940/2394/1710 +f 428/2468/1773 1940/2394/1710 1363/2393/1724 +f 428/2468/1773 1363/2393/1724 1938/2458/1723 +f 428/2468/1773 1938/2458/1723 1384/2457/1768 +f 428/2464/1773 1384/2455/1768 1968/2454/1767 +f 428/2464/1773 1968/2454/1767 1389/2465/1774 +f 429/2470/1777 1386/2471/1770 1939/2358/1703 +f 429/2470/1777 1939/2358/1703 1354/2357/1702 +f 429/2470/1777 1354/2357/1702 1941/2364/1706 +f 429/2470/1777 1941/2364/1706 1390/2472/1778 +f 429/2470/1777 1390/2472/1778 1963/2473/1779 +f 429/2470/1777 1963/2473/1779 1391/2474/1780 +f 429/2470/1777 1391/2474/1780 1965/2475/1771 +f 429/2470/1777 1965/2475/1771 1386/2471/1770 +f 430/2476/1781 1393/2477/1782 1964/2478/1783 +f 430/2476/1781 1964/2478/1783 1392/2479/1784 +f 430/2476/1781 1392/2479/1784 1942/2373/1712 +f 430/2476/1781 1942/2373/1712 1356/2372/1711 +f 430/2476/1781 1356/2372/1711 1940/2371/1710 +f 430/2476/1781 1940/2371/1710 1388/2480/1776 +f 430/2476/1781 1388/2480/1776 1966/2481/1775 +f 430/2476/1781 1966/2481/1775 1393/2477/1782 +f 431/2482/1785 1390/2472/1778 1941/2364/1706 +f 431/2482/1785 1941/2364/1706 1353/2363/1705 +f 431/2483/1785 1353/2484/1705 1943/2337/1691 +f 431/2483/1785 1943/2337/1691 1394/2485/1786 +f 431/2483/1785 1394/2485/1786 1961/2486/1787 +f 431/2483/1785 1961/2486/1787 1395/2487/1788 +f 431/2482/1785 1395/2488/1788 1963/2473/1779 +f 431/2482/1785 1963/2473/1779 1390/2472/1778 +f 432/2489/1789 1397/2490/1790 1962/2491/1791 +f 432/2489/1789 1962/2491/1791 1396/2492/1792 +f 432/2489/1789 1396/2492/1792 1944/2493/1699 +f 432/2489/1789 1944/2493/1699 1357/2374/1708 +f 432/2489/1789 1357/2374/1708 1942/2373/1712 +f 432/2489/1789 1942/2373/1712 1392/2479/1784 +f 432/2489/1789 1392/2479/1784 1964/2478/1783 +f 432/2489/1789 1964/2478/1783 1397/2490/1790 +f 433/2494/1793 1394/2485/1786 1943/2337/1691 +f 433/2494/1793 1943/2337/1691 1348/2336/1690 +f 433/2494/1793 1348/2336/1690 1945/2495/1683 +f 433/2494/1793 1945/2495/1683 1398/2496/1794 +f 433/2497/1793 1398/2498/1794 1959/2499/1795 +f 433/2497/1793 1959/2499/1795 1399/2500/1796 +f 433/2494/1793 1399/2501/1796 1961/2486/1787 +f 433/2494/1793 1961/2486/1787 1394/2485/1786 +f 434/2502/1797 1401/2503/1798 1960/2504/1799 +f 434/2502/1797 1960/2504/1799 1400/2505/1800 +f 434/2502/1797 1400/2505/1800 1946/2355/1687 +f 434/2502/1797 1946/2355/1687 1351/2354/1700 +f 434/2506/1797 1351/2353/1700 1944/2352/1699 +f 434/2506/1797 1944/2352/1699 1396/2507/1792 +f 434/2506/1797 1396/2507/1792 1962/2508/1791 +f 434/2506/1797 1962/2508/1791 1401/2509/1798 +f 435/2510/1801 1398/2498/1794 1945/2325/1683 +f 435/2510/1801 1945/2325/1683 1342/2324/1682 +f 435/2510/1801 1342/2324/1682 1923/2192/1601 +f 435/2510/1801 1923/2192/1601 1402/2511/1802 +f 435/2510/1801 1402/2511/1802 1979/2512/1803 +f 435/2510/1801 1979/2512/1803 1403/2513/1804 +f 435/2510/1801 1403/2513/1804 1959/2499/1795 +f 435/2510/1801 1959/2499/1795 1398/2498/1794 +f 436/2514/1805 1405/2515/1806 1980/2516/1807 +f 436/2514/1805 1980/2516/1807 1404/2517/1808 +f 436/2514/1805 1404/2517/1808 1924/2197/1605 +f 436/2514/1805 1924/2197/1605 1344/2331/1688 +f 436/2514/1805 1344/2331/1688 1946/2330/1687 +f 436/2514/1805 1946/2330/1687 1400/2518/1800 +f 436/2514/1805 1400/2518/1800 1960/2519/1799 +f 436/2514/1805 1960/2519/1799 1405/2515/1806 +f 437/2520/1809 1407/2521/1810 1933/2253/1635 +f 437/2520/1809 1933/2253/1635 1321/2266/1644 +f 437/2520/1809 1321/2266/1644 1921/2265/1643 +f 437/2520/1809 1921/2265/1643 1378/2433/1750 +f 437/2520/1809 1378/2433/1750 1981/2437/1754 +f 437/2520/1809 1981/2437/1754 1406/2522/1811 +f 437/2520/1809 1406/2522/1811 1969/2523/1812 +f 437/2520/1809 1969/2523/1812 1407/2521/1810 +f 438/2524/1813 1409/2525/1814 1982/2447/1760 +f 438/2524/1813 1982/2447/1760 1380/2446/1759 +f 438/2524/1813 1380/2446/1759 1922/2269/1647 +f 438/2524/1813 1922/2269/1647 1323/2268/1646 +f 438/2524/1813 1323/2268/1646 1934/2259/1639 +f 438/2524/1813 1934/2259/1639 1408/2526/1815 +f 438/2524/1813 1408/2526/1815 1970/2527/1816 +f 438/2524/1813 1970/2527/1816 1409/2525/1814 +f 439/2528/1817 1411/2529/1818 1931/2240/1627 +f 439/2528/1817 1931/2240/1627 1317/2256/1636 +f 439/2530/1817 1317/2254/1636 1933/2253/1635 +f 439/2530/1817 1933/2253/1635 1407/2521/1810 +f 439/2530/1817 1407/2521/1810 1969/2523/1812 +f 439/2530/1817 1969/2523/1812 1410/2531/1819 +f 439/2528/1817 1410/2532/1819 1971/2533/1820 +f 439/2528/1817 1971/2533/1820 1411/2529/1818 +f 440/2534/1821 1413/2535/1822 1970/2527/1816 +f 440/2534/1821 1970/2527/1816 1408/2526/1815 +f 440/2534/1821 1408/2526/1815 1934/2259/1639 +f 440/2534/1821 1934/2259/1639 1318/2258/1638 +f 440/2534/1821 1318/2258/1638 1932/2247/1631 +f 440/2534/1821 1932/2247/1631 1412/2536/1823 +f 440/2534/1821 1412/2536/1823 1972/2537/1824 +f 440/2534/1821 1972/2537/1824 1413/2535/1822 +f 441/2538/1825 1415/2539/1826 1929/2540/1619 +f 441/2538/1825 1929/2540/1619 1313/2541/1628 +f 441/2538/1825 1313/2541/1628 1931/2542/1627 +f 441/2538/1825 1931/2542/1627 1411/2543/1818 +f 441/2544/1825 1411/2529/1818 1971/2533/1820 +f 441/2544/1825 1971/2533/1820 1414/2545/1827 +f 441/2544/1825 1414/2545/1827 1973/2546/1828 +f 441/2544/1825 1973/2546/1828 1415/2547/1826 +f 442/2548/1829 1417/2549/1830 1972/2537/1824 +f 442/2548/1829 1972/2537/1824 1412/2536/1823 +f 442/2550/1829 1412/2551/1823 1932/2552/1631 +f 442/2550/1829 1932/2552/1631 1314/2244/1630 +f 442/2550/1829 1314/2244/1630 1930/2233/1623 +f 442/2550/1829 1930/2233/1623 1416/2553/1831 +f 442/2548/1829 1416/2554/1831 1974/2555/1832 +f 442/2548/1829 1974/2555/1832 1417/2549/1830 +f 443/2556/1833 1419/2557/1834 1927/2212/1611 +f 443/2556/1833 1927/2212/1611 1309/2227/1620 +f 443/2556/1833 1309/2227/1620 1929/2226/1619 +f 443/2556/1833 1929/2226/1619 1415/2558/1826 +f 443/2559/1833 1415/2547/1826 1973/2546/1828 +f 443/2559/1833 1973/2546/1828 1418/2560/1835 +f 443/2559/1833 1418/2560/1835 1975/2561/1836 +f 443/2559/1833 1975/2561/1836 1419/2562/1834 +f 444/2563/1837 1421/2564/1838 1974/2555/1832 +f 444/2563/1837 1974/2555/1832 1416/2554/1831 +f 444/2565/1837 1416/2553/1831 1930/2233/1623 +f 444/2565/1837 1930/2233/1623 1310/2232/1622 +f 444/2566/1837 1310/2567/1622 1928/2568/1615 +f 444/2566/1837 1928/2568/1615 1420/2569/1839 +f 444/2563/1837 1420/2570/1839 1976/2571/1840 +f 444/2563/1837 1976/2571/1840 1421/2564/1838 +f 445/2572/1841 1423/2573/1842 1925/2574/1599 +f 445/2572/1841 1925/2574/1599 1305/2213/1612 +f 445/2572/1841 1305/2213/1612 1927/2212/1611 +f 445/2572/1841 1927/2212/1611 1419/2557/1834 +f 445/2575/1841 1419/2576/1834 1975/2577/1836 +f 445/2575/1841 1975/2577/1836 1422/2578/1843 +f 445/2575/1841 1422/2578/1843 1977/2579/1844 +f 445/2575/1841 1977/2579/1844 1423/2580/1842 +f 446/2581/1845 1425/2582/1846 1976/2583/1840 +f 446/2581/1845 1976/2583/1840 1420/2584/1839 +f 446/2581/1845 1420/2584/1839 1928/2217/1615 +f 446/2581/1845 1928/2217/1615 1306/2216/1614 +f 446/2581/1845 1306/2216/1614 1926/2199/1607 +f 446/2581/1845 1926/2199/1607 1424/2585/1847 +f 446/2581/1845 1424/2585/1847 1978/2586/1848 +f 446/2581/1845 1978/2586/1848 1425/2582/1846 +f 447/2587/1849 1402/2511/1802 1923/2192/1601 +f 447/2587/1849 1923/2192/1601 1299/2191/1600 +f 447/2587/1849 1299/2191/1600 1925/2190/1599 +f 447/2587/1849 1925/2190/1599 1423/2580/1842 +f 447/2587/1849 1423/2580/1842 1977/2579/1844 +f 447/2587/1849 1977/2579/1844 1426/2588/1850 +f 447/2587/1849 1426/2588/1850 1979/2512/1803 +f 447/2587/1849 1979/2512/1803 1402/2511/1802 +f 448/2589/1851 1427/2590/1852 1978/2586/1848 +f 448/2589/1851 1978/2586/1848 1424/2585/1847 +f 448/2589/1851 1424/2585/1847 1926/2199/1607 +f 448/2589/1851 1926/2199/1607 1301/2198/1606 +f 448/2589/1851 1301/2198/1606 1924/2197/1605 +f 448/2589/1851 1924/2197/1605 1404/2517/1808 +f 448/2589/1851 1404/2517/1808 1980/2516/1807 +f 448/2589/1851 1980/2516/1807 1427/2590/1852 +f 449/2591/1853 1430/2592/1854 1963/2593/1779 +f 449/2591/1853 1963/2593/1779 1395/2594/1788 +f 449/2591/1853 1395/2594/1788 1961/2595/1787 +f 449/2591/1853 1961/2595/1787 1428/2596/1855 +f 449/2591/1853 1428/2596/1855 1985/2597/1856 +f 449/2591/1853 1985/2597/1856 1429/2598/1857 +f 449/2591/1853 1429/2598/1857 1983/2599/1858 +f 449/2591/1853 1983/2599/1858 1430/2592/1854 +f 450/2600/1859 1433/2601/1860 1986/2602/1861 +f 450/2600/1859 1986/2602/1861 1431/2603/1862 +f 450/2600/1859 1431/2603/1862 1962/2508/1791 +f 450/2600/1859 1962/2508/1791 1397/2604/1790 +f 450/2600/1859 1397/2604/1790 1964/2605/1783 +f 450/2600/1859 1964/2605/1783 1432/2606/1863 +f 450/2600/1859 1432/2606/1863 1984/2607/1864 +f 450/2600/1859 1984/2607/1864 1433/2601/1860 +f 451/2608/1865 1436/2609/1866 1983/2599/1858 +f 451/2608/1865 1983/2599/1858 1429/2598/1857 +f 451/2608/1865 1429/2598/1857 1985/2597/1856 +f 451/2608/1865 1985/2597/1856 1434/2610/1867 +f 451/2608/1865 1434/2610/1867 1987/2611/1868 +f 451/2608/1865 1987/2611/1868 1435/2612/1869 +f 451/2608/1865 1435/2612/1869 1989/2613/1870 +f 451/2608/1865 1989/2613/1870 1436/2609/1866 +f 452/2614/1871 1439/2615/1872 1988/2616/1873 +f 452/2614/1871 1988/2616/1873 1437/2617/1874 +f 452/2614/1871 1437/2617/1874 1986/2602/1861 +f 452/2614/1871 1986/2602/1861 1433/2601/1860 +f 452/2614/1871 1433/2601/1860 1984/2607/1864 +f 452/2614/1871 1984/2607/1864 1438/2618/1875 +f 452/2614/1871 1438/2618/1875 1990/2619/1876 +f 452/2614/1871 1990/2619/1876 1439/2615/1872 +f 453/2620/1877 1442/2621/1878 1989/2613/1870 +f 453/2620/1877 1989/2613/1870 1435/2612/1869 +f 453/2620/1877 1435/2612/1869 1987/2611/1868 +f 453/2620/1877 1987/2611/1868 1440/2622/1879 +f 453/2620/1877 1440/2622/1879 1993/2623/1880 +f 453/2620/1877 1993/2623/1880 1441/2624/1881 +f 453/2620/1877 1441/2624/1881 1991/2625/1882 +f 453/2620/1877 1991/2625/1882 1442/2621/1878 +f 454/2626/1883 1445/2627/1884 1994/2628/1885 +f 454/2626/1883 1994/2628/1885 1443/2629/1886 +f 454/2626/1883 1443/2629/1886 1988/2616/1873 +f 454/2626/1883 1988/2616/1873 1439/2615/1872 +f 454/2626/1883 1439/2615/1872 1990/2619/1876 +f 454/2626/1883 1990/2619/1876 1444/2630/1887 +f 454/2626/1883 1444/2630/1887 1992/2631/1888 +f 454/2626/1883 1992/2631/1888 1445/2627/1884 +f 455/2632/1889 1448/2633/1890 1991/2625/1882 +f 455/2632/1889 1991/2625/1882 1441/2624/1881 +f 455/2632/1889 1441/2624/1881 1993/2623/1880 +f 455/2632/1889 1993/2623/1880 1446/2634/1891 +f 455/2632/1889 1446/2634/1891 1995/2635/1892 +f 455/2632/1889 1995/2635/1892 1447/2636/1893 +f 455/2632/1889 1447/2636/1893 1997/2637/1894 +f 455/2632/1889 1997/2637/1894 1448/2633/1890 +f 456/2638/1895 1451/2639/1896 1996/2640/1897 +f 456/2638/1895 1996/2640/1897 1449/2641/1898 +f 456/2638/1895 1449/2641/1898 1994/2628/1885 +f 456/2638/1895 1994/2628/1885 1445/2627/1884 +f 456/2638/1895 1445/2627/1884 1992/2631/1888 +f 456/2638/1895 1992/2631/1888 1450/2642/1899 +f 456/2638/1895 1450/2642/1899 1998/2643/1900 +f 456/2638/1895 1998/2643/1900 1451/2639/1896 +f 457/2644/1901 1453/2645/1902 1969/2646/1812 +f 457/2644/1901 1969/2646/1812 1406/2647/1811 +f 457/2648/1901 1406/2649/1811 1981/2650/1754 +f 457/2648/1901 1981/2650/1754 1452/2651/1903 +f 457/2648/1901 1452/2651/1903 1991/2625/1882 +f 457/2648/1901 1991/2625/1882 1448/2633/1890 +f 457/2644/1901 1448/2652/1890 1997/2653/1894 +f 457/2644/1901 1997/2653/1894 1453/2645/1902 +f 458/2654/1904 1450/2642/1899 1992/2631/1888 +f 458/2654/1904 1992/2631/1888 1454/2655/1905 +f 458/2654/1904 1454/2655/1905 1982/2447/1760 +f 458/2654/1904 1982/2447/1760 1409/2525/1814 +f 458/2654/1904 1409/2525/1814 1970/2527/1816 +f 458/2654/1904 1970/2527/1816 1455/2656/1906 +f 458/2654/1904 1455/2656/1906 1998/2643/1900 +f 458/2654/1904 1998/2643/1900 1450/2642/1899 +f 459/2657/1907 1377/2658/1753 1957/2659/1752 +f 459/2657/1907 1957/2659/1752 1456/2660/1908 +f 459/2657/1907 1456/2660/1908 1989/2613/1870 +f 459/2657/1907 1989/2613/1870 1442/2621/1878 +f 459/2657/1907 1442/2621/1878 1991/2625/1882 +f 459/2657/1907 1991/2625/1882 1452/2651/1903 +f 459/2657/1907 1452/2651/1903 1981/2650/1754 +f 459/2657/1907 1981/2650/1754 1377/2658/1753 +f 460/2661/1909 1454/2655/1905 1992/2631/1888 +f 460/2661/1909 1992/2631/1888 1444/2630/1887 +f 460/2661/1909 1444/2630/1887 1990/2619/1876 +f 460/2661/1909 1990/2619/1876 1457/2662/1910 +f 460/2661/1909 1457/2662/1910 1958/2440/1757 +f 460/2661/1909 1958/2440/1757 1381/2439/1756 +f 460/2661/1909 1381/2439/1756 1982/2447/1760 +f 460/2661/1909 1982/2447/1760 1454/2655/1905 +f 461/2663/1911 1456/2660/1908 1957/2659/1752 +f 461/2663/1911 1957/2659/1752 1383/2664/1764 +f 461/2663/1911 1383/2664/1764 1967/2665/1763 +f 461/2663/1911 1967/2665/1763 1458/2666/1912 +f 461/2663/1911 1458/2666/1912 1983/2599/1858 +f 461/2663/1911 1983/2599/1858 1436/2609/1866 +f 461/2663/1911 1436/2609/1866 1989/2613/1870 +f 461/2663/1911 1989/2613/1870 1456/2660/1908 +f 462/2667/1913 1438/2618/1875 1984/2607/1864 +f 462/2667/1913 1984/2607/1864 1459/2668/1914 +f 462/2667/1913 1459/2668/1914 1968/2454/1767 +f 462/2667/1913 1968/2454/1767 1385/2453/1766 +f 462/2667/1913 1385/2453/1766 1958/2440/1757 +f 462/2667/1913 1958/2440/1757 1457/2662/1910 +f 462/2667/1913 1457/2662/1910 1990/2619/1876 +f 462/2667/1913 1990/2619/1876 1438/2618/1875 +f 463/2669/1915 1391/2670/1780 1963/2593/1779 +f 463/2669/1915 1963/2593/1779 1430/2592/1854 +f 463/2669/1915 1430/2592/1854 1983/2599/1858 +f 463/2669/1915 1983/2599/1858 1458/2666/1912 +f 463/2669/1915 1458/2666/1912 1967/2665/1763 +f 463/2669/1915 1967/2665/1763 1387/2671/1772 +f 463/2669/1915 1387/2671/1772 1965/2672/1771 +f 463/2669/1915 1965/2672/1771 1391/2670/1780 +f 464/2673/1916 1389/2465/1774 1968/2454/1767 +f 464/2673/1916 1968/2454/1767 1459/2668/1914 +f 464/2673/1916 1459/2668/1914 1984/2607/1864 +f 464/2673/1916 1984/2607/1864 1432/2606/1863 +f 464/2673/1916 1432/2606/1863 1964/2605/1783 +f 464/2673/1916 1964/2605/1783 1393/2674/1782 +f 464/2673/1916 1393/2674/1782 1966/2466/1775 +f 464/2673/1916 1966/2466/1775 1389/2465/1774 +f 465/2675/1917 1399/2500/1796 1959/2499/1795 +f 465/2675/1917 1959/2499/1795 1403/2513/1804 +f 465/2675/1917 1403/2513/1804 1979/2512/1803 +f 465/2675/1917 1979/2512/1803 1460/2676/1918 +f 465/2675/1917 1460/2676/1918 1985/2677/1856 +f 465/2675/1917 1985/2677/1856 1428/2678/1855 +f 465/2679/1917 1428/2596/1855 1961/2595/1787 +f 465/2679/1917 1961/2595/1787 1399/2680/1796 +f 466/2681/1919 1431/2682/1862 1986/2683/1861 +f 466/2681/1919 1986/2683/1861 1461/2684/1920 +f 466/2681/1919 1461/2684/1920 1980/2516/1807 +f 466/2681/1919 1980/2516/1807 1405/2515/1806 +f 466/2681/1919 1405/2515/1806 1960/2519/1799 +f 466/2681/1919 1960/2519/1799 1401/2685/1798 +f 466/2686/1919 1401/2509/1798 1962/2508/1791 +f 466/2686/1919 1962/2508/1791 1431/2603/1862 +f 467/2687/1921 1426/2588/1850 1977/2579/1844 +f 467/2687/1921 1977/2579/1844 1462/2688/1922 +f 467/2689/1921 1462/2690/1922 1987/2611/1868 +f 467/2689/1921 1987/2611/1868 1434/2610/1867 +f 467/2687/1921 1434/2691/1867 1985/2677/1856 +f 467/2687/1921 1985/2677/1856 1460/2676/1918 +f 467/2687/1921 1460/2676/1918 1979/2512/1803 +f 467/2687/1921 1979/2512/1803 1426/2588/1850 +f 468/2692/1923 1461/2693/1920 1986/2602/1861 +f 468/2692/1923 1986/2602/1861 1437/2617/1874 +f 468/2692/1923 1437/2617/1874 1988/2616/1873 +f 468/2692/1923 1988/2616/1873 1463/2694/1924 +f 468/2692/1923 1463/2694/1924 1978/2695/1848 +f 468/2692/1923 1978/2695/1848 1427/2696/1852 +f 468/2692/1923 1427/2696/1852 1980/2697/1807 +f 468/2692/1923 1980/2697/1807 1461/2693/1920 +f 469/2698/1925 1422/2699/1843 1975/2561/1836 +f 469/2698/1925 1975/2561/1836 1464/2700/1926 +f 469/2698/1925 1464/2700/1926 1993/2623/1880 +f 469/2698/1925 1993/2623/1880 1440/2622/1879 +f 469/2698/1925 1440/2622/1879 1987/2611/1868 +f 469/2698/1925 1987/2611/1868 1462/2690/1922 +f 469/2698/1925 1462/2690/1922 1977/2701/1844 +f 469/2698/1925 1977/2701/1844 1422/2699/1843 +f 470/2702/1927 1463/2694/1924 1988/2616/1873 +f 470/2702/1927 1988/2616/1873 1443/2629/1886 +f 470/2702/1927 1443/2629/1886 1994/2628/1885 +f 470/2702/1927 1994/2628/1885 1465/2703/1928 +f 470/2702/1927 1465/2703/1928 1976/2571/1840 +f 470/2702/1927 1976/2571/1840 1425/2704/1846 +f 470/2702/1927 1425/2704/1846 1978/2695/1848 +f 470/2702/1927 1978/2695/1848 1463/2694/1924 +f 471/2705/1929 1418/2560/1835 1973/2546/1828 +f 471/2705/1929 1973/2546/1828 1466/2706/1930 +f 471/2705/1929 1466/2706/1930 1995/2635/1892 +f 471/2705/1929 1995/2635/1892 1446/2634/1891 +f 471/2705/1929 1446/2634/1891 1993/2623/1880 +f 471/2705/1929 1993/2623/1880 1464/2700/1926 +f 471/2705/1929 1464/2700/1926 1975/2561/1836 +f 471/2705/1929 1975/2561/1836 1418/2560/1835 +f 472/2707/1931 1465/2703/1928 1994/2628/1885 +f 472/2707/1931 1994/2628/1885 1449/2641/1898 +f 472/2707/1931 1449/2641/1898 1996/2640/1897 +f 472/2707/1931 1996/2640/1897 1467/2708/1932 +f 472/2707/1931 1467/2708/1932 1974/2555/1832 +f 472/2707/1931 1974/2555/1832 1421/2564/1838 +f 472/2707/1931 1421/2564/1838 1976/2571/1840 +f 472/2707/1931 1976/2571/1840 1465/2703/1928 +f 473/2709/1933 1414/2710/1827 1971/2711/1820 +f 473/2709/1933 1971/2711/1820 1468/2712/1934 +f 473/2709/1933 1468/2712/1934 1997/2653/1894 +f 473/2709/1933 1997/2653/1894 1447/2713/1893 +f 473/2709/1933 1447/2713/1893 1995/2714/1892 +f 473/2709/1933 1995/2714/1892 1466/2715/1930 +f 473/2709/1933 1466/2715/1930 1973/2716/1828 +f 473/2709/1933 1973/2716/1828 1414/2710/1827 +f 474/2717/1935 1467/2708/1932 1996/2640/1897 +f 474/2717/1935 1996/2640/1897 1451/2639/1896 +f 474/2717/1935 1451/2639/1896 1998/2643/1900 +f 474/2717/1935 1998/2643/1900 1469/2718/1936 +f 474/2717/1935 1469/2718/1936 1972/2537/1824 +f 474/2717/1935 1972/2537/1824 1417/2549/1830 +f 474/2717/1935 1417/2549/1830 1974/2555/1832 +f 474/2717/1935 1974/2555/1832 1467/2708/1932 +f 475/2719/1937 1410/2720/1819 1969/2646/1812 +f 475/2719/1937 1969/2646/1812 1453/2645/1902 +f 475/2719/1937 1453/2645/1902 1997/2653/1894 +f 475/2719/1937 1997/2653/1894 1468/2712/1934 +f 475/2719/1937 1468/2712/1934 1971/2711/1820 +f 475/2719/1937 1971/2711/1820 1410/2720/1819 +f 476/2721/1938 1413/2535/1822 1972/2537/1824 +f 476/2721/1938 1972/2537/1824 1469/2718/1936 +f 476/2721/1938 1469/2718/1936 1998/2643/1900 +f 476/2721/1938 1998/2643/1900 1455/2656/1906 +f 476/2721/1938 1455/2656/1906 1970/2527/1816 +f 476/2721/1938 1970/2527/1816 1413/2535/1822 +f 477/2722/1939 1472/2723/1940 1897/2724/1578 +f 477/2722/1939 1897/2724/1578 1294/2725/1586 +f 477/2722/1939 1294/2725/1586 1895/2726/1590 +f 477/2722/1939 1895/2726/1590 1470/2727/1941 +f 477/2722/1939 1470/2727/1941 2009/2728/1942 +f 477/2722/1939 2009/2728/1942 1471/2729/1943 +f 477/2722/1939 1471/2729/1943 2007/2730/1944 +f 477/2722/1939 2007/2730/1944 1472/2723/1940 +f 478/2731/1945 1475/2732/1946 2010/2733/1947 +f 478/2731/1945 2010/2733/1947 1473/2734/1948 +f 478/2731/1945 1473/2734/1948 1896/2735/1596 +f 478/2731/1945 1896/2735/1596 1296/2736/1595 +f 478/2731/1945 1296/2736/1595 1898/2737/1584 +f 478/2731/1945 1898/2737/1584 1474/2738/1949 +f 478/2731/1945 1474/2738/1949 2008/2739/1950 +f 478/2731/1945 2008/2739/1950 1475/2732/1946 +f 479/2740/1951 1477/2741/1952 1899/2155/1566 +f 479/2740/1951 1899/2155/1566 1288/2154/1574 +f 479/2740/1951 1288/2154/1574 1897/2164/1578 +f 479/2740/1951 1897/2164/1578 1472/2742/1940 +f 479/2743/1951 1472/2723/1940 2007/2730/1944 +f 479/2743/1951 2007/2730/1944 1476/2744/1953 +f 479/2743/1951 1476/2744/1953 2005/2745/1954 +f 479/2743/1951 2005/2745/1954 1477/2746/1952 +f 480/2747/1955 1479/2748/1956 2008/2739/1950 +f 480/2747/1955 2008/2739/1950 1474/2738/1949 +f 480/2747/1955 1474/2738/1949 1898/2737/1584 +f 480/2747/1955 1898/2737/1584 1290/2749/1583 +f 480/2747/1955 1290/2749/1583 1900/2750/1572 +f 480/2747/1955 1900/2750/1572 1478/2751/1957 +f 480/2747/1955 1478/2751/1957 2006/2752/1958 +f 480/2747/1955 2006/2752/1958 1479/2748/1956 +f 481/2753/1959 1481/2754/1960 1901/2755/1554 +f 481/2753/1959 1901/2755/1554 1282/2756/1562 +f 481/2753/1959 1282/2756/1562 1899/2155/1566 +f 481/2753/1959 1899/2155/1566 1477/2741/1952 +f 481/2753/1959 1477/2741/1952 2005/2757/1954 +f 481/2753/1959 2005/2757/1954 1480/2758/1961 +f 481/2753/1959 1480/2758/1961 2003/2759/1962 +f 481/2753/1959 2003/2759/1962 1481/2754/1960 +f 482/2760/1963 1483/2761/1964 2006/2752/1958 +f 482/2760/1963 2006/2752/1958 1478/2751/1957 +f 482/2762/1963 1478/2763/1957 1900/2152/1572 +f 482/2762/1963 1900/2152/1572 1284/2151/1571 +f 482/2764/1963 1284/2765/1571 1902/2766/1560 +f 482/2764/1963 1902/2766/1560 1482/2767/1965 +f 482/2764/1963 1482/2767/1965 2004/2768/1966 +f 482/2764/1963 2004/2768/1966 1483/2769/1964 +f 483/2770/1967 1485/2771/1968 1903/2114/1542 +f 483/2770/1967 1903/2114/1542 1276/2126/1550 +f 483/2770/1967 1276/2126/1550 1901/2132/1554 +f 483/2770/1967 1901/2132/1554 1481/2772/1960 +f 483/2773/1967 1481/2754/1960 2003/2759/1962 +f 483/2773/1967 2003/2759/1962 1484/2774/1969 +f 483/2775/1967 1484/2776/1969 2001/2777/1970 +f 483/2775/1967 2001/2777/1970 1485/2778/1968 +f 484/2779/1971 1487/2780/1972 2004/2768/1966 +f 484/2779/1971 2004/2768/1966 1482/2767/1965 +f 484/2779/1971 1482/2767/1965 1902/2766/1560 +f 484/2779/1971 1902/2766/1560 1278/2781/1559 +f 484/2779/1971 1278/2781/1559 1904/2782/1548 +f 484/2779/1971 1904/2782/1548 1486/2783/1973 +f 484/2784/1971 1486/2785/1973 2002/2786/1974 +f 484/2784/1971 2002/2786/1974 1487/2787/1972 +f 485/2788/1975 1489/2789/1976 1905/2790/1521 +f 485/2788/1975 1905/2790/1521 1270/2791/1538 +f 485/2792/1975 1270/2108/1538 1903/2114/1542 +f 485/2792/1975 1903/2114/1542 1485/2771/1968 +f 485/2793/1975 1485/2778/1968 2001/2777/1970 +f 485/2793/1975 2001/2777/1970 1488/2794/1977 +f 485/2793/1975 1488/2794/1977 1999/2795/1978 +f 485/2793/1975 1999/2795/1978 1489/2796/1976 +f 486/2797/1979 1491/2798/1980 2002/2786/1974 +f 486/2797/1979 2002/2786/1974 1486/2785/1973 +f 486/2799/1979 1486/2800/1973 1904/2801/1548 +f 486/2799/1979 1904/2801/1548 1272/2120/1547 +f 486/2799/1979 1272/2120/1547 1906/2103/1534 +f 486/2799/1979 1906/2103/1534 1490/2802/1981 +f 486/2797/1979 1490/2803/1981 2000/2804/1982 +f 486/2797/1979 2000/2804/1982 1491/2798/1980 +f 487/2805/1983 1493/2806/1984 1893/2312/1523 +f 487/2805/1983 1893/2312/1523 1260/2807/1522 +f 487/2805/1983 1260/2807/1522 1905/2790/1521 +f 487/2805/1983 1905/2790/1521 1489/2789/1976 +f 487/2808/1983 1489/2796/1976 1999/2795/1978 +f 487/2808/1983 1999/2795/1978 1492/2809/1985 +f 487/2805/1983 1492/2810/1985 2011/2811/1986 +f 487/2805/1983 2011/2811/1986 1493/2806/1984 +f 488/2812/1987 1495/2813/1988 2000/2804/1982 +f 488/2812/1987 2000/2804/1982 1490/2803/1981 +f 488/2814/1987 1490/2802/1981 1906/2103/1534 +f 488/2814/1987 1906/2103/1534 1265/2102/1533 +f 488/2814/1987 1265/2102/1533 1894/2101/1532 +f 488/2814/1987 1894/2101/1532 1494/2815/1989 +f 488/2812/1987 1494/2816/1989 2012/2817/1990 +f 488/2812/1987 2012/2817/1990 1495/2813/1988 +f 489/2818/1991 1492/2809/1985 1999/2795/1978 +f 489/2818/1991 1999/2795/1978 1496/2819/1992 +f 489/2818/1991 1496/2819/1992 2007/2820/1944 +f 489/2818/1991 2007/2820/1944 1471/2821/1943 +f 489/2818/1991 1471/2821/1943 2009/2822/1942 +f 489/2818/1991 2009/2822/1942 1497/2823/1993 +f 489/2818/1991 1497/2823/1993 2011/2824/1986 +f 489/2818/1991 2011/2824/1986 1492/2809/1985 +f 490/2825/1994 1499/2826/1995 2010/2827/1947 +f 490/2825/1994 2010/2827/1947 1475/2828/1946 +f 490/2825/1994 1475/2828/1946 2008/2829/1950 +f 490/2825/1994 2008/2829/1950 1498/2830/1996 +f 490/2825/1994 1498/2830/1996 2000/2804/1982 +f 490/2825/1994 2000/2804/1982 1495/2813/1988 +f 490/2825/1994 1495/2813/1988 2012/2817/1990 +f 490/2825/1994 2012/2817/1990 1499/2826/1995 +f 491/2831/1997 1496/2819/1992 1999/2795/1978 +f 491/2831/1997 1999/2795/1978 1488/2794/1977 +f 491/2831/1997 1488/2794/1977 2001/2777/1970 +f 491/2831/1997 2001/2777/1970 1500/2832/1998 +f 491/2831/1997 1500/2832/1998 2005/2833/1954 +f 491/2831/1997 2005/2833/1954 1476/2834/1953 +f 491/2831/1997 1476/2834/1953 2007/2820/1944 +f 491/2831/1997 2007/2820/1944 1496/2819/1992 +f 492/2835/1999 1479/2836/1956 2006/2837/1958 +f 492/2835/1999 2006/2837/1958 1501/2838/2000 +f 492/2835/1999 1501/2838/2000 2002/2786/1974 +f 492/2835/1999 2002/2786/1974 1491/2798/1980 +f 492/2835/1999 1491/2798/1980 2000/2804/1982 +f 492/2835/1999 2000/2804/1982 1498/2830/1996 +f 492/2835/1999 1498/2830/1996 2008/2829/1950 +f 492/2835/1999 2008/2829/1950 1479/2836/1956 +f 493/2839/2001 1500/2832/1998 2001/2777/1970 +f 493/2839/2001 2001/2777/1970 1484/2776/1969 +f 493/2839/2001 1484/2776/1969 2003/2840/1962 +f 493/2839/2001 2003/2840/1962 1480/2841/1961 +f 493/2839/2001 1480/2841/1961 2005/2833/1954 +f 493/2839/2001 2005/2833/1954 1500/2832/1998 +f 494/2842/2002 1501/2838/2000 2006/2837/1958 +f 494/2842/2002 2006/2837/1958 1483/2843/1964 +f 494/2844/2002 1483/2769/1964 2004/2768/1966 +f 494/2844/2002 2004/2768/1966 1487/2780/1972 +f 494/2842/2002 1487/2787/1972 2002/2786/1974 +f 494/2842/2002 2002/2786/1974 1501/2838/2000 +f 495/2845/2003 1502/2846/2004 1819/1882/1378 +f 495/2845/2003 1819/1882/1378 1226/2847/1452 +f 495/2848/2003 1226/2849/1452 1887/1219/1445 +f 495/2848/2003 1887/1219/1445 1338/2313/1672 +f 495/2848/2003 1338/2313/1672 1893/2312/1523 +f 495/2848/2003 1893/2312/1523 1493/2806/1984 +f 495/2848/2003 1493/2806/1984 2011/2811/1986 +f 495/2848/2003 2011/2811/1986 1502/2850/2004 +f 496/2851/2005 1494/2815/1989 1894/2101/1532 +f 496/2851/2005 1894/2101/1532 1341/2321/1680 +f 496/2851/2005 1341/2321/1680 1888/2320/1449 +f 496/2851/2005 1888/2320/1449 1227/2852/1454 +f 496/2853/2005 1227/2854/1454 1820/2855/1386 +f 496/2853/2005 1820/2855/1386 1503/2856/2006 +f 496/2853/2005 1503/2856/2006 2012/2817/1990 +f 496/2853/2005 2012/2817/1990 1494/2816/1989 +f 497/2857/2007 1246/2039/1492 1819/1882/1378 +f 497/2857/2007 1819/1882/1378 1502/2846/2004 +f 497/2857/2007 1502/2846/2004 2011/2824/1986 +f 497/2857/2007 2011/2824/1986 1497/2823/1993 +f 497/2857/2007 1497/2823/1993 2009/2822/1942 +f 497/2857/2007 2009/2822/1942 1504/2858/2008 +f 497/2857/2007 1504/2858/2008 1827/2040/1493 +f 497/2857/2007 1827/2040/1493 1246/2039/1492 +f 498/2859/2009 1505/2860/2010 2010/2827/1947 +f 498/2859/2009 2010/2827/1947 1499/2826/1995 +f 498/2859/2009 1499/2826/1995 2012/2817/1990 +f 498/2859/2009 2012/2817/1990 1503/2856/2006 +f 498/2861/2009 1503/2862/2006 1820/2050/1386 +f 498/2861/2009 1820/2050/1386 1250/2049/1502 +f 498/2861/2009 1250/2049/1502 1828/2048/1501 +f 498/2861/2009 1828/2048/1501 1505/2863/2010 +f 499/2864/2011 1330/2865/1662 1825/2061/1471 +f 499/2864/2011 1825/2061/1471 1255/2060/1508 +f 499/2864/2011 1255/2060/1508 1827/2068/1493 +f 499/2864/2011 1827/2068/1493 1504/2866/2008 +f 499/2864/2011 1504/2866/2008 2009/2728/1942 +f 499/2864/2011 2009/2728/1942 1470/2727/1941 +f 499/2864/2011 1470/2727/1941 1895/2726/1590 +f 499/2864/2011 1895/2726/1590 1330/2865/1662 +f 500/2867/2012 1473/2734/1948 2010/2733/1947 +f 500/2867/2012 2010/2733/1947 1505/2863/2010 +f 500/2867/2012 1505/2863/2010 1828/2048/1501 +f 500/2867/2012 1828/2048/1501 1257/2071/1512 +f 500/2867/2012 1257/2071/1512 1826/2015/1476 +f 500/2867/2012 1826/2015/1476 1332/2868/1666 +f 500/2867/2012 1332/2868/1666 1896/2735/1596 +f 500/2867/2012 1896/2735/1596 1473/2734/1948 diff --git a/plugins/guacamole-oculus/example-oculus/data/textures/stones_diffuse.jpg b/plugins/guacamole-oculus/example-oculus/data/textures/stones_diffuse.jpg new file mode 100644 index 000000000..ad60085ee Binary files /dev/null and b/plugins/guacamole-oculus/example-oculus/data/textures/stones_diffuse.jpg differ diff --git a/plugins/guacamole-oculus/example-oculus/data/textures/stones_normal.jpg b/plugins/guacamole-oculus/example-oculus/data/textures/stones_normal.jpg new file mode 100644 index 000000000..44d5ca93f Binary files /dev/null and b/plugins/guacamole-oculus/example-oculus/data/textures/stones_normal.jpg differ diff --git a/plugins/guacamole-oculus/example-oculus/data/textures/stones_specular.jpg b/plugins/guacamole-oculus/example-oculus/data/textures/stones_specular.jpg new file mode 100644 index 000000000..9e0820d93 Binary files /dev/null and b/plugins/guacamole-oculus/example-oculus/data/textures/stones_specular.jpg differ diff --git a/plugins/guacamole-oculus/example-oculus/main.cpp b/plugins/guacamole-oculus/example-oculus/main.cpp new file mode 100644 index 000000000..85ac64b99 --- /dev/null +++ b/plugins/guacamole-oculus/example-oculus/main.cpp @@ -0,0 +1,242 @@ +/****************************************************************************** + * guacamole - delicious VR * + * * + * Copyright: (c) 2011-2013 Bauhaus-Universität Weimar * + * Contact: felix.lauer@uni-weimar.de / simon.schneegans@uni-weimar.de * + * * + * This program is free software: you can redistribute it and/or modify it * + * under the terms of the GNU General Public License as published by the Free * + * Software Foundation, either version 3 of the License, or (at your option) * + * any later version. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * + * for more details. * + * * + * You should have received a copy of the GNU General Public License along * + * with this program. If not, see . * + * * + ******************************************************************************/ + +#include +#include + +#include + +const std::string geometry("data/objects/monkey.obj"); +// const std::string geometry("data/objects/cube.obj"); + +std::vector> add_lights(gua::SceneGraph& graph, + int count) { + + std::vector> lights(count); + + for (int i(0); i < count; ++i) { + scm::math::vec3 randdir(gua::math::random::get(-1.f, 1.f), + gua::math::random::get(-1.f, 1.f), + gua::math::random::get(-1.f, 1.f)); + scm::math::normalize(randdir); + + gua::GeometryLoader loader; + auto sphere_geometry( + loader.create_geometry_from_file( + "sphere" + gua::string_utils::to_string(i), + "data/objects/light_sphere.obj", + "data/materials/White.gmd" + )); + + sphere_geometry->scale(0.04, 0.04, 0.04); + + lights[i] = graph.add_node("/", std::make_shared("light" + gua::string_utils::to_string(i))); + lights[i]->add_child(sphere_geometry); + lights[i]->translate(randdir[0], randdir[1], randdir[2]); + + auto light = lights[i]->add_child(std::make_shared("light")); + light->data.set_color(gua::utils::Color3f::random()); + } + + return lights; +} + +void setup_scene(gua::SceneGraph& graph, + std::shared_ptr const& root_monkey, + int depth_count) { + + if (depth_count > 0) { + gua::GeometryLoader loader; + + float offset(2.f); + std::vector directions = { + gua::math::vec3(0, offset, 0), + gua::math::vec3(0, -offset, 0), + gua::math::vec3(offset, 0, 0), + gua::math::vec3(-offset, 0, 0), + gua::math::vec3(0, 0, offset), + gua::math::vec3(0, 0, -offset) + }; + + for (auto direction: directions) { + auto monkey_geometry(loader.create_geometry_from_file( + "monkey", + geometry, + "data/materials/Stones.gmd" + )); + + auto monkey = root_monkey->add_child(monkey_geometry); + monkey->scale(0.5, 0.5, 0.5); + monkey->translate(direction[0], direction[1], direction[2]); + + setup_scene(graph, monkey, depth_count - 1); + } + } +} + +OVR::SensorFusion* init_oculus() { + OVR::System::Init(OVR::Log::ConfigureDefaultLog(OVR::LogMask_All)); + OVR::DeviceManager* device_manager = OVR::DeviceManager::Create(); + OVR::SensorDevice* sensor_device = device_manager->EnumerateDevices().CreateDevice(); + if (sensor_device) { + OVR::SensorFusion* sensor_fusion = new OVR::SensorFusion(); + sensor_fusion->AttachToSensor(sensor_device); + return sensor_fusion; + } + return nullptr; +} + +gua::math::mat4 const get_oculus_transform(OVR::SensorFusion* sensor) { + OVR::Quatf orient = sensor->GetPredictedOrientation(); + OVR::Matrix4f mat(orient.Inverted()); + return gua::math::mat4( mat.M[0][0], mat.M[0][1], mat.M[0][2], mat.M[0][3], + mat.M[1][0], mat.M[1][1], mat.M[1][2], mat.M[1][3], + mat.M[2][0], mat.M[2][1], mat.M[2][2], mat.M[2][3], + mat.M[3][0], mat.M[3][1], mat.M[3][2], mat.M[3][3]); +} + +int main(int argc, char** argv) { + + // initialize guacamole + gua::init(argc, argv); + + gua::ShadingModelDatabase::load_shading_models_from("data/materials/"); + gua::MaterialDatabase::load_materials_from("data/materials/"); + + // initialize Oculus SDK + OVR::SensorFusion* oculus_sensor = init_oculus(); + if (!oculus_sensor) return 1; // no oculus sensor found + + // setup scene + gua::SceneGraph graph("main_scenegraph"); + + gua::GeometryLoader loader; + + auto monkey_geometry(loader.create_geometry_from_file( + "root_ape", + geometry, + "data/materials/Stones.gmd" + )); + + auto root_monkey = graph.add_node("/", monkey_geometry); + root_monkey->scale(0.5, 0.5, 0.5); + + // depth monkey cube car + // 1 14.084 56 3.619.000 Vertices / 7 draw calls + // 2 74.444 296 19.129.000 Vertices / 37 draw calls + // 3 436.604 1.736 112.189.000 Vertices / 217 draw calls + // 4 2.609.564 10.376 Vertices / 1.297 draw calls + // 5 15.647.324 62.216 Vertices / 7.777 draw calls + // 6 93.873.884 373.256 Vertices / 46.657 draw calls + setup_scene(graph, root_monkey, 4); + + auto lights = add_lights(graph, 50); + + auto pos = graph.add_node("/", "pos"); + pos->translate(0, 0, 2); + auto nav = graph.add_node("/pos", "nav"); + + auto screen = graph.add_node("/pos/nav", "screen_l"); + screen->data.set_size(gua::math::vec2(0.08, 0.1)); + screen->translate(-0.04, 0, -0.05f); + + screen = graph.add_node("/pos/nav", "screen_r"); + screen->data.set_size(gua::math::vec2(0.08, 0.1)); + screen->translate(0.04, 0, -0.05f); + + auto eye = graph.add_node("/pos/nav", "eye_l"); + eye->translate(-0.032, 0, 0); + + eye = graph.add_node("/pos/nav", "eye_r"); + eye->translate(0.032, 0, 0); + + unsigned width = 1280/2; + unsigned height = 800; + + auto pipe = new gua::Pipeline(); + pipe->config.set_camera(gua::Camera("/pos/nav/eye_l", "/pos/nav/eye_r", "/pos/nav/screen_l", "/pos/nav/screen_r", "main_scenegraph")); + pipe->config.set_left_resolution(gua::math::vec2ui(width, height)); + pipe->config.set_right_resolution(gua::math::vec2ui(width, height)); + pipe->config.set_enable_fps_display(true); + pipe->config.set_enable_frustum_culling(true); + pipe->config.set_enable_stereo(true); + + pipe->config.set_enable_ssao(true); + pipe->config.set_ssao_intensity(2.f); + pipe->config.set_enable_fxaa(true); + pipe->config.set_enable_hdr(true); + pipe->config.set_hdr_key(5.f); + pipe->config.set_enable_bloom(true); + pipe->config.set_bloom_radius(10.f); + pipe->config.set_bloom_threshold(0.8f); + pipe->config.set_bloom_intensity(0.8f); + + + auto oculus_window(new gua::OculusWindow(":0.0")); + pipe->set_window(oculus_window); + + gua::Renderer renderer({ + pipe + }); + + gua::Timer timer; + timer.start(); + + double time(0); + float desired_frame_time(1.0 / 60.0); + gua::events::MainLoop loop; + + // application loop + gua::events::Ticker ticker(loop, desired_frame_time); + + ticker.on_tick.connect([&]() { + double frame_time(timer.get_elapsed()); + time += frame_time; + timer.reset(); + + std::function, int)> rotate; + rotate = [&](std::shared_ptr node, int depth) { + node->rotate(frame_time * (1+depth) * 0.5, 1, 1, 0); + for (auto child: node->get_children()) { + rotate(child, ++depth); + } + }; + + rotate(graph["/root_ape"], 1); + + for (int i = 0; i < lights.size(); ++i) { + lights[i]->rotate( + std::sin(time * (i * 0.1 + 0.5)) * frame_time * 2.5, 0, 1, 0); + } + + graph["/root_ape"]->rotate(15 * frame_time, 0, 1, 0); + //graph["/screen"]->rotate(20*frame_time, 0, 1, 0); + + nav->set_transform(get_oculus_transform(oculus_sensor)); + + renderer.queue_draw({&graph}); + }); + + loop.start(); + + return 0; +} + diff --git a/plugins/guacamole-oculus/include/gua/OculusWindow.hpp b/plugins/guacamole-oculus/include/gua/OculusWindow.hpp new file mode 100644 index 000000000..f321bf5ec --- /dev/null +++ b/plugins/guacamole-oculus/include/gua/OculusWindow.hpp @@ -0,0 +1,66 @@ +/****************************************************************************** + * guacamole - delicious VR * + * * + * Copyright: (c) 2011-2013 Bauhaus-Universität Weimar * + * Contact: felix.lauer@uni-weimar.de / simon.schneegans@uni-weimar.de * + * * + * This program is free software: you can redistribute it and/or modify it * + * under the terms of the GNU General Public License as published by the Free * + * Software Foundation, either version 3 of the License, or (at your option) * + * any later version. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * + * for more details. * + * * + * You should have received a copy of the GNU General Public License along * + * with this program. If not, see . * + * * + ******************************************************************************/ + +#ifndef GUA_OCULUS_WINDOW_HPP +#define GUA_OCULUS_WINDOW_HPP + +#if defined (_MSC_VER) + #if defined (GUA_OCULUS_LIBRARY) + #define GUA_OCULUS_DLL __declspec( dllexport ) + #else +#define GUA_OCULUS_DLL __declspec( dllimport ) + #endif +#else + #define GUA_OCULUS_DLL +#endif // #if defined(_MSC_VER) + +// guacamole headers +#include + +namespace gua { + +class GUA_OCULUS_DLL OculusWindow : public Window { + public: + + OculusWindow(std::string const& display); + virtual ~OculusWindow(); + + void create_shader(); + + void set_distortion(math::vec4 const& distortion); + void set_distortion(float distortion0, float distortion1, float distortion2, float distortion3); + + // virtual + void display(std::shared_ptr const& left_texture, + std::shared_ptr const& right_texture); + + private: + void display(std::shared_ptr const& texture, + math::vec2ui const& size, + math::vec2ui const& position, + bool left); + + math::vec4 distortion_; +}; + +} + +#endif // GUA_OCULUS_WINDOW_HPP diff --git a/plugins/guacamole-oculus/readme.md b/plugins/guacamole-oculus/readme.md new file mode 100644 index 000000000..09f692214 --- /dev/null +++ b/plugins/guacamole-oculus/readme.md @@ -0,0 +1 @@ +== Guacamole Material Editor == diff --git a/plugins/guacamole-oculus/src/gua/OculusWindow.cpp b/plugins/guacamole-oculus/src/gua/OculusWindow.cpp new file mode 100644 index 000000000..52db7326c --- /dev/null +++ b/plugins/guacamole-oculus/src/gua/OculusWindow.cpp @@ -0,0 +1,164 @@ +/****************************************************************************** + * guacamole - delicious VR * + * * + * Copyright: (c) 2011-2013 Bauhaus-Universität Weimar * + * Contact: felix.lauer@uni-weimar.de / simon.schneegans@uni-weimar.de * + * * + * This program is free software: you can redistribute it and/or modify it * + * under the terms of the GNU General Public License as published by the Free * + * Software Foundation, either version 3 of the License, or (at your option) * + * any later version. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * + * for more details. * + * * + * You should have received a copy of the GNU General Public License along * + * with this program. If not, see . * + * * + ******************************************************************************/ + +// class header +#include + +// external headers +#include + +namespace gua { + +OculusWindow::OculusWindow(std::string const& display): + Window(), + distortion_(4) { + + config.set_size(math::vec2ui(1280, 800)); + config.set_title("guacamole"); + config.set_display_name(display); + config.set_stereo_mode(StereoMode::SIDE_BY_SIDE); + config.set_left_resolution(math::vec2ui(1280/2, 800)); + config.set_left_position(math::vec2ui(0, 0)); + config.set_right_resolution(math::vec2ui(1280/2, 800)); + config.set_right_position(math::vec2ui(1280/2, 0)); + + // for now fixed distortion values TODO should be set dynamically by OVR + set_distortion(1.0, 0.22, 0.24, 0.0); + +} + +//////////////////////////////////////////////////////////////////////////////// + +OculusWindow::~OculusWindow() { + +} + +//////////////////////////////////////////////////////////////////////////////// + +void OculusWindow::create_shader() { + fullscreen_shader_.create_from_sources(R"( + #version 420 + #extension GL_NV_bindless_texture : require + + layout(location=0) in vec3 in_position; + + out vec2 tex_coord; + + void main() { + tex_coord = in_position.xy*0.5 + 0.5; + gl_Position = vec4(in_position, 1.0); + } + )", R"( + #version 420 + #extension GL_NV_bindless_texture : require + #extension GL_NV_gpu_shader5 : enable + + in vec2 tex_coord; + + uniform uvec2 sampler; + + // oculus parameters + uniform vec2 lens_center; + uniform vec2 scale; + uniform vec4 hmd_warp_param; + + layout (location = 0) out vec3 out_color; + + sampler2D get_tex(uvec2 handle) { + return sampler2D(uint64_t(handle.x) + uint64_t(handle.y) * 4294967295); + } + + vec2 hmd_warp(vec2 in_texcoord) { + vec2 theta = (in_texcoord - lens_center) * 2.0; // Scales to [-1, 1] + float rSq = theta.x * theta.x + theta.y * theta.y; + vec2 rvector = theta * (hmd_warp_param.x+hmd_warp_param.y*rSq + +hmd_warp_param.z*rSq*rSq + +hmd_warp_param.w*rSq*rSq*rSq); + return lens_center + scale * rvector; + } + + vec3 get_color() { + + vec2 tc = hmd_warp(tex_coord); + + if (tc.x < 0.0 || tc.y < 0.0 || tc.x > 1.0 || tc.y > 1.0 ) + return vec3(0); + + return vec3(texture2D( get_tex(sampler), tc).rgb); + } + + void main() { + out_color = get_color(); + } + )"); +} + +//////////////////////////////////////////////////////////////////////////////// + +void OculusWindow::set_distortion(math::vec4 const& distortion) { + distortion_ = distortion; +} + +//////////////////////////////////////////////////////////////////////////////// + +void OculusWindow::set_distortion(float distortion0, float distortion1, float distortion2, float distortion3) { + distortion_[0] = distortion0; + distortion_[1] = distortion1; + distortion_[2] = distortion2; + distortion_[3] = distortion3; +} + +//////////////////////////////////////////////////////////////////////////////// + +void OculusWindow::display(std::shared_ptr const& left_texture, + std::shared_ptr const& right_texture) { + + display(left_texture, config.get_left_resolution(), config.get_left_position(), true); + display(right_texture, config.get_right_resolution(), config.get_right_position(), false); +} + +//////////////////////////////////////////////////////////////////////////////// + +void OculusWindow::display(std::shared_ptr const& texture, + math::vec2ui const& size, + math::vec2ui const& position, + bool left) { + + + fullscreen_shader_.use(*get_context()); + fullscreen_shader_.set_uniform(*get_context(), texture, "sampler"); + + if (left) fullscreen_shader_.set_uniform(*get_context(), math::vec2(0.6f, 0.5f), "lens_center"); + else fullscreen_shader_.set_uniform(*get_context(), math::vec2(0.4f, 0.5f), "lens_center"); + + fullscreen_shader_.set_uniform(*get_context(), math::vec2(0.4f, 0.4f), "scale"); + fullscreen_shader_.set_uniform(*get_context(), distortion_, "hmd_warp_param"); + + get_context()->render_context->set_viewport(scm::gl::viewport(position, size)); + get_context()->render_context->set_depth_stencil_state(depth_stencil_state_); + + fullscreen_quad_->draw(get_context()->render_context); + + get_context()->render_context->reset_state_objects(); + fullscreen_shader_.unuse(*get_context()); +} + +} \ No newline at end of file diff --git a/resources/materials/gua_textured_quad.gmd b/resources/materials/gua_textured_quad.gmd index b63f91047..23e1955d3 100644 --- a/resources/materials/gua_textured_quad.gmd +++ b/resources/materials/gua_textured_quad.gmd @@ -3,6 +3,8 @@ "shading_model" : "gua_textured_quad", "uniforms" : { + "flip_x" : "0", + "flip_y" : "0", "texture" : "gua_default_texture" } } diff --git a/resources/materials/gua_textured_quad.gsd b/resources/materials/gua_textured_quad.gsd index 97f89673a..fbb4cf865 100644 --- a/resources/materials/gua_textured_quad.gsd +++ b/resources/materials/gua_textured_quad.gsd @@ -1,37 +1,39 @@ { - "final_shading_stage" : + "final_shading_stage" : { "body" : "gua_color = color;\n", "functions" : "", "outputs" : null, "uniforms" : null }, - "gbuffer_fragment_stage" : + "gbuffer_fragment_stage" : { - "body" : "gua_normal = varying_normal;\ncolor = texture2D(texture, varying_texcoord).rgb;", + "body" : "gua_normal = varying_normal;\nvec2 tex_coords = varying_texcoord;\n\nif (flip_x) tex_coords.x = 1.0 - varying_texcoord.x;\nif (flip_y) tex_coords.y = 1.0 - varying_texcoord.y;\n\ncolor = texture2D(texture, tex_coords).rgb;", "functions" : "", - "outputs" : + "outputs" : { "color" : "vec3" }, - "uniforms" : + "uniforms" : { + "flip_x" : "bool", + "flip_y" : "bool", "texture" : "sampler2D" } }, - "gbuffer_vertex_stage" : + "gbuffer_vertex_stage" : { "body" : "gua_position = gua_world_position;\nvarying_normal = gua_world_normal;\nvarying_texcoord = gua_texcoords;", "functions" : "", - "outputs" : + "outputs" : { "varying_normal" : "vec3", "varying_texcoord" : "vec2" }, "uniforms" : null }, - "lbuffer_stage" : + "lbuffer_stage" : { "body" : "", "functions" : "", diff --git a/resources/shaders/display_shader.frag b/resources/shaders/display_shader.frag index 80b8d9f04..97670d1f5 100644 --- a/resources/shaders/display_shader.frag +++ b/resources/shaders/display_shader.frag @@ -49,6 +49,20 @@ vec3 get_cyan() { return vec3(0.0, texture2D( get_tex(sampler), tex_coord).gb); } +subroutine( GetColorType ) +vec3 get_checker_even() { + if (mod(gl_FragCoord.x + gl_FragCoord.y, 2.0) == 0.0) + return vec3(texture2D( get_tex(sampler), tex_coord).rgb); + else discard; +} + +subroutine( GetColorType ) +vec3 get_checker_odd() { + if (mod(gl_FragCoord.x + gl_FragCoord.y, 2.0) == 1.0) + return vec3(texture2D( get_tex(sampler), tex_coord).rgb); + else discard; +} + subroutine( GetColorType ) vec3 get_full() { return vec3(texture2D( get_tex(sampler), tex_coord).rgb); diff --git a/resources/shaders/uber_shaders/common/get_depth.glsl b/resources/shaders/uber_shaders/common/get_depth.glsl index a0c4bba89..2cc88a159 100644 --- a/resources/shaders/uber_shaders/common/get_depth.glsl +++ b/resources/shaders/uber_shaders/common/get_depth.glsl @@ -6,3 +6,12 @@ float gua_get_depth() { vec2 frag_pos = gua_get_quad_coords(); return texture2D(gua_get_float_sampler(gua_depth_gbuffer_in), frag_pos).x * 2.0 - 1.0; } + +float gua_get_depth(sampler2D depth_texture, vec2 frag_pos) { + return texture2D(depth_texture, frag_pos).x * 2.0 - 1.0; +} + +float gua_get_depth(sampler2D depth_texture) { + vec2 frag_pos = gua_get_quad_coords(); + return texture2D(depth_texture, frag_pos).x * 2.0 - 1.0; +} diff --git a/resources/shaders/uber_shaders/common/get_position.glsl b/resources/shaders/uber_shaders/common/get_position.glsl index 1b06df21d..15275c817 100644 --- a/resources/shaders/uber_shaders/common/get_position.glsl +++ b/resources/shaders/uber_shaders/common/get_position.glsl @@ -8,3 +8,15 @@ vec3 gua_get_position(vec2 frag_pos) { vec3 gua_get_position() { return gua_get_position(gua_get_quad_coords()); } + +vec3 gua_get_position(sampler2D depth_texture, vec2 frag_pos) { + vec4 screen_space_pos = vec4(frag_pos * 2.0 - 1.0, gua_get_depth(depth_texture, frag_pos), 1.0); + vec4 h = gua_inverse_projection_view_matrix * screen_space_pos; + h /= h.w; + return h.xyz; +} + +vec3 gua_get_position(sampler2D depth_texture) { + return gua_get_position(depth_texture, gua_get_quad_coords()); +} + diff --git a/resources/shaders/uber_shaders/common/get_sampler_casts.glsl b/resources/shaders/uber_shaders/common/get_sampler_casts.glsl index 81d9563c7..497686179 100644 --- a/resources/shaders/uber_shaders/common/get_sampler_casts.glsl +++ b/resources/shaders/uber_shaders/common/get_sampler_casts.glsl @@ -17,3 +17,19 @@ sampler2D gua_get_double_sampler(uvec2 handle) { sampler2DShadow gua_get_shadow_sampler(uvec2 handle) { return sampler2DShadow(uint64_t(handle.x) | (uint64_t(handle.y) << 32UL)); } + +isampler3D gua_get_int_sampler3D(uvec2 handle) { + return isampler3D(uint64_t(handle.x) | (uint64_t(handle.y) << 32UL)); +} + +usampler3D gua_get_uint_sampler3D(uvec2 handle) { + return usampler3D(uint64_t(handle.x) | (uint64_t(handle.y) << 32UL)); +} + +sampler3D gua_get_float_sampler3D(uvec2 handle) { + return sampler3D(uint64_t(handle.x) | (uint64_t(handle.y) << 32UL)); +} + +sampler3D gua_get_double_sampler3D(uvec2 handle) { + return sampler3D(uint64_t(handle.x) | (uint64_t(handle.y) << 32UL)); +} \ No newline at end of file diff --git a/resources/shaders/uber_shaders/composite/compose.frag b/resources/shaders/uber_shaders/composite/compose.frag new file mode 100644 index 000000000..b39b0ca16 --- /dev/null +++ b/resources/shaders/uber_shaders/composite/compose.frag @@ -0,0 +1,145 @@ +/****************************************************************************** + * guacamole - delicious VR * + * * + * Copyright: (c) 2011-2013 Bauhaus-Universität Weimar * + * Contact: felix.lauer@uni-weimar.de / simon.schneegans@uni-weimar.de * + * * + * This program is free software: you can redistribute it and/or modify it * + * under the terms of the GNU General Public License as published by the Free * + * Software Foundation, either version 3 of the License, or (at your option) * + * any later version. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * + * for more details. * + * * + * You should have received a copy of the GNU General Public License along * + * with this program. If not, see . * + * * + ******************************************************************************/ + +@include "shaders/common/header.glsl" + +// input from gbuffer ---------------------------------------------------- +uniform uvec2 gua_depth_gbuffer_in; +uniform uvec2 gua_color_gbuffer_in; +uniform uvec2 gua_normal_gbuffer_in; +uniform uvec2 gua_ray_entry_in; + +uniform uvec2 volume_texture; +uniform uvec2 transfer_texture; +uniform float sampling_distance; +uniform vec3 volume_bounds; + + +// uniforms +@include "shaders/uber_shaders/common/get_sampler_casts.glsl" +@include "shaders/uber_shaders/common/gua_camera_uniforms.glsl" + + + + +// methods --------------------------------------------------------------------- + +// global gua_* methods +vec2 gua_get_quad_coords() { + return vec2(gl_FragCoord.x * gua_texel_width, gl_FragCoord.y * gua_texel_height); +} + +// write outputs --------------------------------------------------------------------- +layout(location=0) out vec3 gua_out_color; + +float get_depth_z(vec3 world_position) { + vec4 pos = gua_projection_matrix * gua_view_matrix * vec4(world_position, 1.0); + float ndc = pos.z/pos.w; + return ((gl_DepthRange.diff * ndc) + gl_DepthRange.near + gl_DepthRange.far) / 2.0; + +} + +float get_depth_linear(float depth_buffer_d) { + + float ndc = (depth_buffer_d * 2.0 - gl_DepthRange.near - gl_DepthRange.far)/gl_DepthRange.diff; + vec4 enit = vec4(gl_FragCoord.xy * 2.0 - vec2(1.0), ndc, 1.0); + vec4 enit_inv = (gua_inverse_projection_view_matrix * enit); + enit_inv /= enit_inv.w; + return enit_inv.z; +} + +bool +inside_volume_bounds(const in vec3 sampling_position) +{ + return ( all(greaterThanEqual(sampling_position, vec3(0.0))) + && all(lessThanEqual(sampling_position, volume_bounds))); +} + +vec4 get_raycast_color(vec3 gua_object_volume_position, + float d_gbuffer, + float d_volume){ + + mat4 gua_invers_model_matrix = inverse(gua_model_matrix); + vec3 object_ray = normalize(gua_object_volume_position - (gua_invers_model_matrix * vec4(gua_camera_position, 1.0)).xyz); + float d_step = abs(-1.0 * get_depth_linear(get_depth_z((gua_model_matrix * vec4(gua_object_volume_position + object_ray * sampling_distance, 1.0)).xyz)) - d_volume); + + vec3 obj_to_tex = vec3(1.0) / volume_bounds; + vec3 ray_increment = object_ray * sampling_distance; + vec3 sampling_pos = gua_object_volume_position + ray_increment; // test, increment just to be sure we are in the volume + + bool inside_volume = inside_volume_bounds(sampling_pos); + + vec4 color = vec4(0.0); + + int d_steps = int(abs(d_volume - d_gbuffer) / d_step); + int d_step_cur = 0; + + while (inside_volume && (d_step_cur < d_steps)) { + ++d_step_cur; + // get sample + float s = texture(gua_get_float_sampler3D(volume_texture), sampling_pos * obj_to_tex).x;//texture3D(volume_texture, sampling_pos * obj_to_tex).r; + vec4 src = texture2D(gua_get_float_sampler(transfer_texture), vec2(s, 0.5)); + + // increment ray + sampling_pos += ray_increment; + inside_volume = inside_volume_bounds(sampling_pos) && (color.a < 0.99f); + // compositing + float omda_sa = (1.0f - color.a) * src.a; + color.rgb += omda_sa * src.rgb; + color.a += omda_sa; + } + + return color; +} + + +// main ------------------------------------------------------------------------ +void main() { + + vec3 gua_object_volume_position = texture2D(gua_get_float_sampler(gua_ray_entry_in), gua_get_quad_coords()).xyz; + vec3 gua_world_volume_position = (gua_model_matrix * vec4(gua_object_volume_position, 1.0)).xyz; + + float d_gbuffer = texture2D(gua_get_float_sampler(gua_depth_gbuffer_in), gua_get_quad_coords()).x; + float d_volume = get_depth_z(gua_world_volume_position); + + d_gbuffer = -1.0 * get_depth_linear(d_gbuffer); + d_volume = -1.0 * get_depth_linear(d_volume); + + // compose + if(d_gbuffer > d_volume && + (gua_object_volume_position.x != 0.00 || + gua_object_volume_position.y != 0.00 || + gua_object_volume_position.z != 0.00)) + { + vec4 compositing_color = get_raycast_color(gua_object_volume_position, d_gbuffer, d_volume); + + vec3 gbuffer_color = texture2D(gua_get_float_sampler(gua_color_gbuffer_in), gua_get_quad_coords()).xyz; + + gua_out_color = gbuffer_color * (1.0 - compositing_color.a) + compositing_color.rgb; + } + else{ + gua_out_color = texture2D(gua_get_float_sampler(gua_color_gbuffer_in), gua_get_quad_coords()).xyz; + } + + + +} + diff --git a/resources/shaders/uber_shaders/composite/compose.vert b/resources/shaders/uber_shaders/composite/compose.vert new file mode 100644 index 000000000..11b51ce7d --- /dev/null +++ b/resources/shaders/uber_shaders/composite/compose.vert @@ -0,0 +1,33 @@ +/****************************************************************************** + * guacamole - delicious VR * + * * + * Copyright: (c) 2011-2013 Bauhaus-Universität Weimar * + * Contact: felix.lauer@uni-weimar.de / simon.schneegans@uni-weimar.de * + * * + * This program is free software: you can redistribute it and/or modify it * + * under the terms of the GNU General Public License as published by the Free * + * Software Foundation, either version 3 of the License, or (at your option) * + * any later version. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * + * for more details. * + * * + * You should have received a copy of the GNU General Public License along * + * with this program. If not, see . * + * * + ******************************************************************************/ + +@include "shaders/common/header.glsl" + +// uniforms +@include "shaders/uber_shaders/common/gua_camera_uniforms.glsl" + +// input +layout(location=0) in vec3 gua_in_position; + +void main() { + gl_Position = vec4(gua_in_position, 1.0); +} + diff --git a/resources/shaders/uber_shaders/composite/ray_generation.frag b/resources/shaders/uber_shaders/composite/ray_generation.frag new file mode 100644 index 000000000..f4aa41e03 --- /dev/null +++ b/resources/shaders/uber_shaders/composite/ray_generation.frag @@ -0,0 +1,34 @@ +/****************************************************************************** + * guacamole - delicious VR * + * * + * Copyright: (c) 2011-2013 Bauhaus-Universität Weimar * + * Contact: felix.lauer@uni-weimar.de / simon.schneegans@uni-weimar.de * + * * + * This program is free software: you can redistribute it and/or modify it * + * under the terms of the GNU General Public License as published by the Free * + * Software Foundation, either version 3 of the License, or (at your option) * + * any later version. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * + * for more details. * + * * + * You should have received a copy of the GNU General Public License along * + * with this program. If not, see . * + * * + ******************************************************************************/ + +@include "shaders/common/header.glsl" + +// input +in vec3 gua_position_varying; + +// write outputs +layout(location=0) out vec3 gua_out_color; + +// main ------------------------------------------------------------------------ +void main() { + gua_out_color = gua_position_varying; +} + diff --git a/resources/shaders/uber_shaders/composite/ray_generation.vert b/resources/shaders/uber_shaders/composite/ray_generation.vert new file mode 100644 index 000000000..9cc502889 --- /dev/null +++ b/resources/shaders/uber_shaders/composite/ray_generation.vert @@ -0,0 +1,42 @@ +/****************************************************************************** + * guacamole - delicious VR * + * * + * Copyright: (c) 2011-2013 Bauhaus-Universität Weimar * + * Contact: felix.lauer@uni-weimar.de / simon.schneegans@uni-weimar.de * + * * + * This program is free software: you can redistribute it and/or modify it * + * under the terms of the GNU General Public License as published by the Free * + * Software Foundation, either version 3 of the License, or (at your option) * + * any later version. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * + * for more details. * + * * + * You should have received a copy of the GNU General Public License along * + * with this program. If not, see . * + * * + ******************************************************************************/ + +@include "shaders/common/header.glsl" + +// uniforms +@include "shaders/uber_shaders/common/gua_camera_uniforms.glsl" + +// input +layout(location=0) in vec3 gua_in_position; + +// output +out vec3 gua_position_varying; + +void main() { + + gua_position_varying = gua_in_position; + + //vec3 gua_world_position = (gua_model_matrix * vec4(gua_in_position, 1.0)).xyz; + + gl_Position = gua_projection_matrix * gua_view_matrix * gua_model_matrix * vec4(gua_in_position.xyz, 1.0); + //gl_Position = vec4(gua_in_position, 1.0); +} + diff --git a/resources/shaders/uber_shaders/final/final.frag b/resources/shaders/uber_shaders/final/final.frag index aa6d723d3..d0a1a183a 100644 --- a/resources/shaders/uber_shaders/final/final.frag +++ b/resources/shaders/uber_shaders/final/final.frag @@ -34,8 +34,8 @@ uniform uvec2 gua_depth_gbuffer_in; @include "shaders/uber_shaders/common/gua_camera_uniforms.glsl" uniform vec3 gua_ambient_color; +uniform int gua_background_mode; uniform vec3 gua_background_color; -uniform bool gua_background_is_color; uniform uvec2 gua_background_texture; // material specific uniforms @@ -65,6 +65,11 @@ float gua_my_atan2(float a, float b) { } void gua_apply_background_texture() { + gua_float_gbuffer_out_0.rgb = texture2D( + gua_get_float_sampler(gua_background_texture), gua_quad_coords).xyz; +} + +void gua_apply_skymap_texture() { vec3 pos = gua_get_position(); vec3 view = normalize(pos - gua_camera_position); @@ -86,10 +91,15 @@ void gua_apply_background_color() { void main() { if (gua_get_material_id() == 0) { - if (gua_background_is_color) { - gua_apply_background_color(); - } else { - gua_apply_background_texture(); + switch (gua_background_mode) { + case 0: // color + gua_apply_background_color(); + break; + case 1: // skymap texture + gua_apply_skymap_texture(); + break; + default: // quad texture + gua_apply_background_texture(); } } else { diff --git a/resources/shaders/uber_shaders/gbuffer/mesh/mesh.frag b/resources/shaders/uber_shaders/gbuffer/mesh/mesh.frag index 25feffa4e..21ff03591 100644 --- a/resources/shaders/uber_shaders/gbuffer/mesh/mesh.frag +++ b/resources/shaders/uber_shaders/gbuffer/mesh/mesh.frag @@ -26,6 +26,8 @@ in vec3 gua_position_varying; @input_definition // uniforms +uniform bool gua_enable_global_clipping_plane; +uniform vec4 gua_global_clipping_plane; @include "shaders/uber_shaders/common/gua_camera_uniforms.glsl" // material specific uniforms @@ -37,6 +39,7 @@ in vec3 gua_position_varying; // methods --------------------------------------------------------------------- // global gua_* methods + vec2 gua_get_quad_coords() { return vec2(gl_FragCoord.x * gua_texel_width, gl_FragCoord.y * gua_texel_height); } @@ -51,11 +54,28 @@ vec3 gua_get_position() { return gua_position_varying; } +void gua_set_position(vec3 world_position) { + vec4 pos = gua_projection_matrix * gua_view_matrix * vec4(world_position, 1.0); + float ndc = pos.z/pos.w; + gl_FragDepth = (((gl_DepthRange.diff) * ndc) + gl_DepthRange.near + gl_DepthRange.far) / 2.0; +} + +void gua_clip_against_global_clipping_plane() { + if (gua_enable_global_clipping_plane) { + if (dot(gua_get_position(), gua_global_clipping_plane.xyz) + gua_global_clipping_plane.w < 0) { + discard; + } + } +} + // material specific methods @material_methods // main ------------------------------------------------------------------------ void main() { + gua_clip_against_global_clipping_plane(); + + gl_FragDepth = gl_FragCoord.z; // big switch, one case for each material @material_switch diff --git a/resources/shaders/uber_shaders/lighting/lighting.frag b/resources/shaders/uber_shaders/lighting/lighting.frag index 79d64720d..ff6b795a9 100644 --- a/resources/shaders/uber_shaders/lighting/lighting.frag +++ b/resources/shaders/uber_shaders/lighting/lighting.frag @@ -28,6 +28,9 @@ in vec3 gua_lightinfo1; in vec3 gua_lightinfo2; in float gua_lightinfo3; in mat4 gua_lightinfo4; +in mat4 gua_lightinfo5; +in mat4 gua_lightinfo6; +in mat4 gua_lightinfo7; // input from gbuffer uniform uvec2 gua_depth_gbuffer_in; @@ -36,6 +39,11 @@ uniform uvec2 gua_depth_gbuffer_in; // uniforms @include "shaders/uber_shaders/common/gua_camera_uniforms.glsl" +uniform mat4 gua_light_shadow_map_projection_view_matrix_0; +uniform mat4 gua_light_shadow_map_projection_view_matrix_1; +uniform mat4 gua_light_shadow_map_projection_view_matrix_2; +uniform mat4 gua_light_shadow_map_projection_view_matrix_3; + uniform vec3 gua_light_color; uniform float gua_light_falloff; uniform float gua_light_softness; @@ -103,13 +111,12 @@ float gua_get_shadow(vec4 smap_coords) { ); } -float gua_get_shadow() { +float gua_get_shadow(mat4 shadow_map_coords_matrix, vec2 lookup_offset) { if(!gua_light_casts_shadow) return 1.0; - mat4 shadow_map_coords_matrix = gua_lightinfo4; vec3 position = gua_get_position(); - vec4 smap_coords = shadow_map_coords_matrix * vec4(position, 1.0); + vec4 smap_coords = shadow_map_coords_matrix * vec4(position, 1.0) + vec4(lookup_offset, 0, 0); float sum = 0; int x, y; @@ -123,10 +130,16 @@ float gua_get_shadow() { return shadow; } -// base lighting calculations for point lights --------------------------------- +bool gua_is_inside_frustum(mat4 frustum, vec3 position) { + vec4 proj = frustum * vec4(position, 1.0); + proj /= proj.w; + return (abs(proj.x) <= 1 && abs(proj.y) <= 1 && abs(proj.z) <= 1); +} + subroutine void CalculateLightType(); subroutine uniform CalculateLightType compute_light; +// base lighting calculations for point lights --------------------------------- subroutine(CalculateLightType) void gua_calculate_point_light() { vec3 light_position = gua_lightinfo1; @@ -172,7 +185,7 @@ void gua_calculate_spot_light() { if (dot(gbuffer_normal, gua_light_direction) < 0) discard; - float shadow = gua_get_shadow(); + float shadow = gua_get_shadow(gua_lightinfo4, vec2(0)); if(shadow <= 0.0) discard; @@ -189,6 +202,38 @@ void gua_calculate_spot_light() { gua_light_intensity = radial_attenuation * length_attenuation * shadow; } +// base lighting calculations for point lights --------------------------------- +subroutine(CalculateLightType) +void gua_calculate_sun_light() { + vec3 light_direction = gua_lightinfo1; + vec3 gbuffer_normal = texture2D(gua_get_float_sampler(gua_float_gbuffer_in_1[0]), + gua_get_quad_coords()).xyz; + + gua_light_direction = light_direction; + gua_light_distance = 0.0; + + if (dot(gbuffer_normal, gua_light_direction) < 0) + discard; + + + vec3 position = gua_get_position(); + + float shadow = 1.0; + + if (gua_is_inside_frustum(gua_light_shadow_map_projection_view_matrix_0, position)) { + shadow = gua_get_shadow(gua_lightinfo4, vec2(0, 0)); + } else if (gua_is_inside_frustum(gua_light_shadow_map_projection_view_matrix_1, position)) { + shadow = gua_get_shadow(gua_lightinfo5, vec2(1, 0)); + } else if (gua_is_inside_frustum(gua_light_shadow_map_projection_view_matrix_2, position)) { + shadow = gua_get_shadow(gua_lightinfo6, vec2(0, 1)); + } else if (gua_is_inside_frustum(gua_light_shadow_map_projection_view_matrix_3, position)) { + shadow = gua_get_shadow(gua_lightinfo7, vec2(1, 1)); + } + + + gua_light_intensity = 1.0 * shadow; +} + // material specific methods @material_methods diff --git a/resources/shaders/uber_shaders/lighting/lighting.vert b/resources/shaders/uber_shaders/lighting/lighting.vert index 80bf3eaa3..d8e7d6383 100644 --- a/resources/shaders/uber_shaders/lighting/lighting.vert +++ b/resources/shaders/uber_shaders/lighting/lighting.vert @@ -29,20 +29,26 @@ layout(location=2) in vec3 gua_in_normal; // uniforms @include "shaders/uber_shaders/common/gua_camera_uniforms.glsl" -uniform mat4 gua_light_shadow_map_projection_view_matrix; +uniform mat4 gua_light_shadow_map_projection_view_matrix_0; +uniform mat4 gua_light_shadow_map_projection_view_matrix_1; +uniform mat4 gua_light_shadow_map_projection_view_matrix_2; +uniform mat4 gua_light_shadow_map_projection_view_matrix_3; // output out vec3 gua_lightinfo1; out vec3 gua_lightinfo2; out float gua_lightinfo3; out mat4 gua_lightinfo4; +out mat4 gua_lightinfo5; +out mat4 gua_lightinfo6; +out mat4 gua_lightinfo7; // BASE LIGHTING CALCULATIONS -------------------------------------------------- -// base lighting calculations for point lights subroutine void CalculateLightType(); subroutine uniform CalculateLightType compute_light; +// base lighting calculations for point lights subroutine( CalculateLightType ) void gua_calculate_point_light() { @@ -52,6 +58,9 @@ void gua_calculate_point_light() { gua_lightinfo1 = light_position; gua_lightinfo2 = vec3(0.0, 0.0, 0.0); gua_lightinfo3 = light_radius; + + vec3 position = (gua_model_matrix * vec4(gua_in_position, 1.0)).xyz; + gl_Position = gua_projection_matrix * gua_view_matrix * vec4(position, 1.0); } // base lighting calculations for spot lights @@ -66,17 +75,37 @@ void gua_calculate_spot_light() { vec3 light_position = (gua_model_matrix * vec4(0.0, 0.0, 0.0, 1.0)).xyz; vec3 beam_direction = (gua_model_matrix * vec4(0.0, 0.0, -1.0, 1.0)).xyz - light_position; float half_beam_angle = dot(normalize((gua_model_matrix * vec4(0.0, 0.5, -1.0, 0.0)).xyz), normalize(beam_direction)); - mat4 shadow_map_coords_mat = bias * gua_light_shadow_map_projection_view_matrix; + mat4 shadow_map_coords_mat = bias * gua_light_shadow_map_projection_view_matrix_0; gua_lightinfo1 = light_position; gua_lightinfo2 = beam_direction; gua_lightinfo3 = half_beam_angle; gua_lightinfo4 = shadow_map_coords_mat; + + vec3 position = (gua_model_matrix * vec4(gua_in_position, 1.0)).xyz; + gl_Position = gua_projection_matrix * gua_view_matrix * vec4(position, 1.0); +} + +// base lighting calculations for sun lights +subroutine( CalculateLightType ) +void gua_calculate_sun_light() { + + const mat4 bias = mat4(0.5, 0.0, 0.0, 0.0, + 0.0, 0.5, 0.0, 0.0, + 0.0, 0.0, 0.5, 0.0, + 0.5, 0.5, 0.5, 1.0); + + vec3 light_direction = normalize((gua_model_matrix * vec4(0.0, 0.0, 1.0, 0.0)).xyz); + gua_lightinfo1 = light_direction; + gua_lightinfo4 = bias * gua_light_shadow_map_projection_view_matrix_0; + gua_lightinfo5 = bias * gua_light_shadow_map_projection_view_matrix_1; + gua_lightinfo6 = bias * gua_light_shadow_map_projection_view_matrix_2; + gua_lightinfo7 = bias * gua_light_shadow_map_projection_view_matrix_3; + + gl_Position = vec4(gua_in_position, 1.0); } // main ------------------------------------------------------------------------ void main() { compute_light(); - vec3 position = (gua_model_matrix * vec4(gua_in_position, 1.0)).xyz; - gl_Position = gua_projection_matrix * gua_view_matrix * vec4(position, 1.0); } diff --git a/resources/shaders/uber_shaders/postfx/godrays.frag b/resources/shaders/uber_shaders/postfx/godrays.frag index 804cd330b..094092118 100644 --- a/resources/shaders/uber_shaders/postfx/godrays.frag +++ b/resources/shaders/uber_shaders/postfx/godrays.frag @@ -41,7 +41,7 @@ layout(location=0) out vec3 gua_out_color; subroutine( GetColorType ) float get_color_clamped(vec2 texcoords) { float depth = texture2D( gua_get_float_sampler(gua_ray_texture), texcoords).r * 2 -1; - float intensity = depth > gua_light_position_screen_space.z ? 1.0 : 0.0; + float intensity = depth >= gua_light_position_screen_space.z ? 1.0 : 0.0; intensity *= max(0.0, 1.0-length((gua_quad_coords - gua_light_position_screen_space.xy * 0.5 - 0.5)/vec2(1.0, gua_aspect_ratio))); return pow(intensity, 15.0); } diff --git a/resources/shaders/uber_shaders/postfx/godrays.vert b/resources/shaders/uber_shaders/postfx/godrays.vert index e4c7317e4..4189d257d 100644 --- a/resources/shaders/uber_shaders/postfx/godrays.vert +++ b/resources/shaders/uber_shaders/postfx/godrays.vert @@ -27,16 +27,39 @@ layout(location=2) in vec2 gua_in_texcoord; uniform mat4 gua_projection_matrix; uniform mat4 gua_view_matrix; -uniform vec3 gua_light_position; +uniform vec3 gua_light_position_direction; // output out vec3 gua_light_position_screen_space; out vec2 gua_quad_coords; +subroutine void CalculatePositionType(); +subroutine uniform CalculatePositionType compute_position; + +subroutine(CalculatePositionType) +void gua_calculate_by_direction() { + vec4 tmp = gua_view_matrix * vec4(gua_light_position_direction, 0.0); + + if (tmp.z > 0) { + // hide sun on wrong side + gua_light_position_screen_space = vec3(-10); + } else { + + tmp = gua_projection_matrix * tmp; + gua_light_position_screen_space = (tmp/tmp.w).xyz; + gua_light_position_screen_space = gua_light_position_screen_space/gua_light_position_screen_space.z; + } +} + +subroutine(CalculatePositionType) +void gua_calculate_by_position() { + vec4 tmp = gua_projection_matrix * gua_view_matrix * vec4(gua_light_position_direction, 1.0); + gua_light_position_screen_space = (tmp/tmp.w).xyz; +} + // body void main() { - gua_quad_coords = gua_in_texcoord; - vec4 tmp = gua_projection_matrix * gua_view_matrix * vec4(gua_light_position, 1.0); - gua_light_position_screen_space = (tmp/tmp.w).xyz; - gl_Position = vec4(gua_in_position, 1.0); + gua_quad_coords = gua_in_texcoord; + compute_position(); + gl_Position = vec4(gua_in_position, 1.0); } diff --git a/resources/shaders/uber_shaders/postfx/stage_03.frag b/resources/shaders/uber_shaders/postfx/stage_03.frag index 1a432df7b..2ca0a421c 100644 --- a/resources/shaders/uber_shaders/postfx/stage_03.frag +++ b/resources/shaders/uber_shaders/postfx/stage_03.frag @@ -106,14 +106,12 @@ void gua_apply_fxaa() { void apply_vignette() { - float hardness = gua_vignette_softness; - float offset = 0.5 - gua_vignette_coverage*0.5; - - float dist = length(gua_get_quad_coords() - vec2(0.5)); - float fac = (dist - offset)/hardness; - fac = 1.0 - pow(clamp(fac, 0.0, 1.0), 2); - - gua_out_color = gua_out_color * fac + (1.0 - fac) * gua_vignette_color; + // inigo quilez's great vigneting effect! + float a = -gua_vignette_coverage/gua_vignette_softness; + float b = 1.0/gua_vignette_softness; + vec2 q = gua_get_quad_coords(); + float fac = min(1, a + b*pow( 16.0*q.x*q.y*(1.0-q.x)*(1.0-q.y), 0.1 )); + gua_out_color = gua_out_color * fac + (1.0 - fac) * gua_vignette_color; } /////////////////////////////// main /////////////////////////////////// diff --git a/scripts/guacamole.sublime-project b/scripts/guacamole.sublime-project index e0faec1a9..f9df3120e 100644 --- a/scripts/guacamole.sublime-project +++ b/scripts/guacamole.sublime-project @@ -15,6 +15,13 @@ "file_regex": "^(..[^:]*):(.*)$", "working_dir": "${project_path}/..", "cmd": ["./scripts/make.sh"] + }, + { + "name": "guacamole-doc", + "file_regex": "^(..[^:]*):(.*)$", + "working_dir": "${project_path}/../doc/", + "shell" : "true", + "cmd": ["doxygen"] } ] } diff --git a/scripts/make.sh b/scripts/make.sh index 0aff1ef5a..1dfbbee04 100755 --- a/scripts/make.sh +++ b/scripts/make.sh @@ -1,5 +1,17 @@ #!/bin/sh -mkdir build +# get directory of script and cd to its parent +DIR="$( cd "$( dirname "$0" )" && pwd )" +cd $DIR/.. -cd build; cmake -DCMAKE_BUILD_TYPE=release ..; make -j16 && ( cd .. ) +# run initial cmake if neccessary +if [ ! -d "build" ]; then + mkdir build + cd build + cmake -DCMAKE_BUILD_TYPE=release .. + cd .. +fi + +# buil it! +cd build +make -j16 diff --git a/scripts/make_doc.sh b/scripts/make_doc.sh new file mode 100755 index 000000000..db908d9f9 --- /dev/null +++ b/scripts/make_doc.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +# get directory of script and cd to doc folder +DIR="$( cd "$( dirname "$0" )" && pwd )" +cd $DIR/../doc + +doxygen + +cp *.css doc/html +cp *.png doc/html diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d1ce0dc64..b6960a1fe 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -8,18 +8,17 @@ file(GLOB_RECURSE GUACAMOLE_SRC RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} LINK_DIRECTORIES(${LIB_PATHS}) -IF (UNIX) +INCLUDE_DIRECTORIES(guacamole ${INCLUDE_PATHS}) + ADD_LIBRARY( guacamole SHARED ${GUACAMOLE_SRC} ) -ELSEIF (WIN32) -ADD_LIBRARY( guacamole STATIC - ${GUACAMOLE_SRC} -) -ENDIF(UNIX) -INCLUDE_DIRECTORIES(guacamole ${INCLUDE_PATHS}) +IF (MSVC) + GET_WIN32_WINNT(WIN_VERSION) + SET_TARGET_PROPERTIES(guacamole PROPERTIES COMPILE_FLAGS "-D GUA_LIBRARY -D _WIN32_WINNT=${WIN_VERSION}") +ENDIF(MSVC) TARGET_LINK_LIBRARIES( guacamole debug ${LIBS} optimized ${LIBS}) -ADD_DEPENDENCIES(guacamole guarc) +ADD_DEPENDENCIES(guacamole guarc CompileResources) diff --git a/src/gua/databases/GeometryDatabase.cpp b/src/gua/databases/GeometryDatabase.cpp index 691ca4a87..b36e8582f 100644 --- a/src/gua/databases/GeometryDatabase.cpp +++ b/src/gua/databases/GeometryDatabase.cpp @@ -32,11 +32,6 @@ namespace gua { //////////////////////////////////////////////////////////////////////////////// -void GeometryDatabase::load(std::string const& id) { - // auto geo(new Geometry(id)); - // instance()->add(id, std::shared_ptr(geo)); -} - //////////////////////////////////////////////////////////////////////////////// } diff --git a/src/gua/databases/MaterialDatabase.cpp b/src/gua/databases/MaterialDatabase.cpp index 010fba9d4..1b9ccfe07 100644 --- a/src/gua/databases/MaterialDatabase.cpp +++ b/src/gua/databases/MaterialDatabase.cpp @@ -32,10 +32,9 @@ namespace gua { //////////////////////////////////////////////////////////////////////////////// -void MaterialDatabase::load_materials_from( - std::string const& path_to_materials) { +void MaterialDatabase::load_materials_from(std::string const& directory) { - gua::Directory dir(path_to_materials); + gua::Directory dir(directory); std::stringstream content(dir.get_content()); std::string parse_string; @@ -43,13 +42,18 @@ void MaterialDatabase::load_materials_from( unsigned suffix_pos = unsigned(parse_string.find(".gmd")); if (parse_string.length() - suffix_pos == 4) { - auto name(parse_string.substr(0, suffix_pos)); + auto name(dir.get_directory_name() + parse_string); + load_material(name); + } + } +} - auto mat = std::make_shared( - name, MaterialDescription(dir.get_directory_name() + parse_string)); +//////////////////////////////////////////////////////////////////////////////// - instance()->add(name, mat); - } +void MaterialDatabase::load_material(std::string const& filename) { + if (!instance()->is_supported(filename)) { + auto mat = std::make_shared(filename, filename); + instance()->add(filename, mat); } } diff --git a/src/gua/databases/ShadingModelDatabase.cpp b/src/gua/databases/ShadingModelDatabase.cpp index cc4633f31..cec1dffaa 100644 --- a/src/gua/databases/ShadingModelDatabase.cpp +++ b/src/gua/databases/ShadingModelDatabase.cpp @@ -33,9 +33,9 @@ namespace gua { //////////////////////////////////////////////////////////////////////////////// void ShadingModelDatabase::load_shading_models_from( - std::string const& path_to_shading_models) { + std::string const& directory) { - gua::Directory dir(path_to_shading_models); + gua::Directory dir(directory); std::stringstream content(dir.get_content()); std::string parse_string; @@ -43,16 +43,23 @@ void ShadingModelDatabase::load_shading_models_from( unsigned suffix_pos = unsigned(parse_string.find(".gsd")); if (parse_string.length() - suffix_pos == 4) { - auto name(parse_string.substr(0, suffix_pos)); - auto mod = std::make_shared(name, dir.get_directory_name() + parse_string); - - instance()->add(name, mod); + auto name(dir.get_directory_name() + parse_string); + load_shading_model(name); } } } //////////////////////////////////////////////////////////////////////////////// +void ShadingModelDatabase::load_shading_model(std::string const& filename) { + if (!instance()->is_supported(filename)) { + auto mod = std::make_shared(filename, filename); + instance()->add(filename, mod); + } +} + +//////////////////////////////////////////////////////////////////////////////// + void ShadingModelDatabase::reload_all() { for (auto const& date: data_) { date.second->reload(); diff --git a/src/gua/databases/TextureDatabase.cpp b/src/gua/databases/TextureDatabase.cpp index 7903faecb..da11fe04b 100644 --- a/src/gua/databases/TextureDatabase.cpp +++ b/src/gua/databases/TextureDatabase.cpp @@ -21,6 +21,8 @@ // class header #include +#include +#include // guacamole headers #include @@ -29,11 +31,22 @@ // external headers #include #include +#include +#include namespace gua { void TextureDatabase::load(std::string const& id) { - instance()->add(id, std::make_shared(id, true)); + boost::filesystem::path fp(id); + std::string extension(fp.extension().string()); + boost::algorithm::to_lower(extension); + + if (extension == ".png" || extension == ".jpg" || extension == ".bmp" || + extension == ".tif" || extension == ".tga") { + instance()->add(id, std::make_shared(id, true)); + } else if (extension == ".vol") { + instance()->add(id, std::make_shared(id, true)); + } } } diff --git a/src/gua/events/Ticker.cpp b/src/gua/events/Ticker.cpp index b486dbc97..a1da667b7 100644 --- a/src/gua/events/Ticker.cpp +++ b/src/gua/events/Ticker.cpp @@ -26,7 +26,7 @@ namespace gua { namespace events { - Ticker::Ticker(MainLoop& mainloop, double tick_time) + Ticker::Ticker(MainLoop& mainloop, double tick_time) : timer_(new boost::asio::deadline_timer(mainloop.io_service, boost::posix_time::microseconds(1000000.0*tick_time))), tick_time_(tick_time) { @@ -38,16 +38,25 @@ namespace gua { delete timer_; } - void Ticker::self_callback(int revents) - { - on_tick.emit(); + void Ticker::set_tick_time(double tick_time) { + tick_time_ = tick_time; + } + + double Ticker::get_tick_time() const { + return tick_time_; + } + + void Ticker::self_callback(int revents) + { async_wait(); + on_tick.emit(); } void Ticker::async_wait() { + timer_->expires_from_now(boost::posix_time::microseconds(1000000.0*tick_time_)); timer_->async_wait(boost::bind(&Ticker::self_callback, this, 0)); } - + } } diff --git a/src/gua/guacamole.cpp b/src/gua/guacamole.cpp index 8dc915dc9..5c1158cb5 100644 --- a/src/gua/guacamole.cpp +++ b/src/gua/guacamole.cpp @@ -42,7 +42,8 @@ void init(int argc, char** argv) { Resources::materials_gua_textured_quad_gsd, Resources::materials_gua_textured_quad_gmd); - gua::TextureDatabase::instance()->add("gua_default_texture", std::shared_ptr(new DefaultTexture())); + gua::TextureDatabase::instance()->add("gua_default_texture", std::shared_ptr(new DefaultTexture())); + gua::TextureDatabase::instance()->add("gua_loading_texture", std::shared_ptr(new LoadingTexture())); MeshLoader mesh_loader; diff --git a/src/gua/math/math.cpp b/src/gua/math/math.cpp index be46db045..545563a21 100644 --- a/src/gua/math/math.cpp +++ b/src/gua/math/math.cpp @@ -26,15 +26,23 @@ #include #include +#if ASSIMP_VERSION == 3 +#include +#else +#include +#endif + namespace gua { //////////////////////////////////////////////////////////////////////////////// -math::mat4 const math::compute_frustum(math::vec4 const& eye_position, +math::mat4 const math::compute_perspective_frustum(math::vec4 const& eye_position, math::mat4 const& screen_transform, float near_plane, float far_plane) { + math::mat4 frustum(math::mat4::identity()); + math::vec4 relative_eye_position(scm::math::inverse(screen_transform) * eye_position); @@ -42,8 +50,6 @@ math::mat4 const math::compute_frustum(math::vec4 const& eye_position, float ox(-relative_eye_position[0]); float oy(-relative_eye_position[1]); - math::mat4 frustum(math::mat4::identity()); - frustum[0] = 2 * d; frustum[5] = 2 * d; frustum[8] = 2 * ox; @@ -58,6 +64,34 @@ math::mat4 const math::compute_frustum(math::vec4 const& eye_position, //////////////////////////////////////////////////////////////////////////////// +math::mat4 const math::compute_orthographic_frustum(math::vec4 const& eye_position, + math::mat4 const& screen_transform, + float near_plane, + float far_plane) { + + math::mat4 frustum(math::mat4::identity()); + + + math::vec4 relative_eye_position(scm::math::inverse(screen_transform) * + eye_position); + + // float d(relative_eye_position[2]); + float ox(-relative_eye_position[0]); + float oy(-relative_eye_position[1]); + + frustum[0] = 2.0f; + frustum[5] = 2.0f; + frustum[10] = 2.0f / (near_plane - far_plane); + frustum[12] = -2.0f * ox; + frustum[13] = -2.0f * oy; + frustum[14] = (far_plane + near_plane) / (near_plane - far_plane); + frustum[15] = 1.f; + + return frustum; +} + +//////////////////////////////////////////////////////////////////////////////// + math::mat4 const math::mat_ai_to_scm(aiMatrix4x4 const& ai_mat) { math::mat4 scm_mat; @@ -76,6 +110,20 @@ math::mat4 const math::mat_ai_to_scm(aiMatrix4x4 const& ai_mat) { return scm_mat; } -//////////////////////////////////////////////////////////////////////////////// +std::tuple math::barycentric(math::vec3 const& a, + math::vec3 const& b, + math::vec3 const& c, + math::vec3 const& p) { + auto pa = a-p; + auto pb = b-p; + auto pc = c-p; + + auto inv2area = 1.0 / scm::math::length(scm::math::cross(a-b, a-c)); + auto a1 = inv2area * scm::math::length(scm::math::cross(pb, pc)); + auto a2 = inv2area * scm::math::length(scm::math::cross(pc, pa)); + auto a3 = 1.0 - a1 - a2; + + return std::make_tuple(a1,a2,a3); +} } diff --git a/src/gua/physics/CollisionShapeNode.cpp b/src/gua/physics/CollisionShapeNode.cpp index 13db87202..64bca182d 100644 --- a/src/gua/physics/CollisionShapeNode.cpp +++ b/src/gua/physics/CollisionShapeNode.cpp @@ -23,7 +23,7 @@ #include // guacamole headers -#include +#include #include namespace gua { @@ -49,7 +49,7 @@ CollisionShapeNode::~CollisionShapeNode() {} //////////////////////////////////////////////////////////////////////////////// std::shared_ptr CollisionShapeNode::copy() const { - return std::make_shared(get_name(), get_transform()); + return std::make_shared(get_name(), get_transform()); } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/gua/physics/ConvexHullShape.cpp b/src/gua/physics/ConvexHullShape.cpp index 6acbb536d..d940f2be6 100644 --- a/src/gua/physics/ConvexHullShape.cpp +++ b/src/gua/physics/ConvexHullShape.cpp @@ -152,13 +152,13 @@ void ConvexHullShape::build_from_geometry( for (auto const& n : node->get_children()) { auto gnode = std::dynamic_pointer_cast(n); if (gnode) { - geom_list.push_back(gnode->data.get_geometry()); + geom_list.push_back(gnode->get_geometry()); } } } else { auto gnode = std::dynamic_pointer_cast(node); if (gnode) { - geom_list.push_back(gnode->data.get_geometry()); + geom_list.push_back(gnode->get_geometry()); } } diff --git a/src/gua/physics/RigidBodyNode.cpp b/src/gua/physics/RigidBodyNode.cpp index d8c03bdab..01b0349e6 100644 --- a/src/gua/physics/RigidBodyNode.cpp +++ b/src/gua/physics/RigidBodyNode.cpp @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include // external headers @@ -391,7 +391,7 @@ void RigidBodyNode::sync_shapes(bool do_not_lock) { //////////////////////////////////////////////////////////////////////////////// std::shared_ptr RigidBodyNode::copy() const { - return std::make_shared(get_name(), get_transform()); + return std::make_shared(get_name(), get_transform()); } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/gua/physics/TriangleMeshShape.cpp b/src/gua/physics/TriangleMeshShape.cpp index 1f77a89e2..daa1641d9 100644 --- a/src/gua/physics/TriangleMeshShape.cpp +++ b/src/gua/physics/TriangleMeshShape.cpp @@ -32,7 +32,7 @@ // external headers #include -#include +#include namespace gua { namespace physics { @@ -169,7 +169,7 @@ void TriangleMeshShape::set_scaling(const math::vec3 & scaling) { auto gnode = std::dynamic_pointer_cast(node); if (gnode) { - geom_list.push_back(gnode->data.get_geometry()); + geom_list.push_back(gnode->get_geometry()); } for (auto const& n: node->get_children()) { diff --git a/src/gua/renderer/BuiltInTextures.cpp b/src/gua/renderer/BuiltInTextures.cpp index dc8a1793f..926395324 100644 --- a/src/gua/renderer/BuiltInTextures.cpp +++ b/src/gua/renderer/BuiltInTextures.cpp @@ -456,11 +456,11 @@ k\204\205ke\217\211p\\~Z\303\224{(s\224Jxs\256s\245\30{\204|vn\241\214s<\ NoiseTexture:: NoiseTexture() - : Texture(64, 64, scm::gl::FORMAT_RGB_8, {pixel_data}) + : Texture2D(64, 64, scm::gl::FORMAT_RGB_8, {pixel_data}) {} //////////////////////////////////////////////////////////////////////////////// -#if WIN32 +#if WIN32 unsigned char DefaultTexture::pixel_data[64 * 64 * 3 + 1] = "sEk\211|p\211|p\211|p\200vs\204\337s\200vs\200vs\214\177\214\204A\224\214\ \177\214\204A\224\211\211{B\252\214\211\211{\211\211{\204]{c\266\214s\211\ @@ -888,7 +888,7 @@ k\204\205ke\217\211p\\~Z\303\224{(s\224Jxs\256s\245\30{\204|vn\241\214s<\ \204s\224\204s\224\204s\204g\204\224]\224\203\246s\203\246s\203\246s~w\211\ ~w\211~w\211c\232s"; -#else +#else unsigned char DefaultTexture::pixel_data[256 * 256 * 3 + 1] = "????????????????????????????????????????????????????????????????????????\ ????????????????????????\225\225\225\225\225\225\225\225\225\225\225\225\ @@ -7733,14 +7733,482 @@ I?????????????????????????????????????????????\225\225\225\225\225\225\225\ ????????????????????????????????"; #endif +unsigned char LoadingTexture::pixel_data[128 * 39 * 3 + 1] = + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\3\3\3\33\33\35""226HIDUXIVYIIJD326\32" + "\31\33\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\1\1%$'XZJ" + "\213\230N\254\300N\273\322N\276\325N\276\325N\273\322N\254\300N\206\222O" + "KLF\25\25\25\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\10\10\10FFC\215\233N\273" + "\323N\273\322O\272\321N\273\322O\273\322O\273\322O\273\322O\272\321N\274" + "\323O\265\312NmsN\"\"$\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\14\14\13PQJ\253\277M\274\323" + "O\273\322O\273\322O\273\322O\273\322O\273\322O\273\322O\273\322O\273\322" + "O\273\322O\272\321N\274\323Nz\202O!!#\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\7\7\7PRJ\264\311N\272\321" + "O\273\322O\273\322O\273\322O\273\322O\273\322O\273\322O\273\322O\273\322" + "O\273\322O\273\322O\273\322O\272\321N\273\322NflM\21\21\21\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0CCA\250\273" + "N\273\322O\273\322O\273\322O\273\322O\273\322O\273\322O\273\322O\273\322" + "O\273\322O\273\322O\273\322O\273\322O\273\322O\273\322O\272\321N\262\310" + "NGHD\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0##&\214\230Q\276\324Q\273\322O\273\322O\273\322O\272\321N\276\325O\266" + "\315M\255\302K\265\313M\277\326P\273\322O\273\322O\273\322O\273\322O\273" + "\322O\273\322O\274\323O\210\224N\36\36\40\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\6\6\5Z]L\277\323T\275\323S\274\322Q\273\322" + "O\272\321N\265\313NemA665+*.)))DI-\231\253D\276\325P\273\322O\273\322O\273" + "\322O\273\322O\272\321N\267\315NJKE\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0%%(\234\250T\300\324V\277\322U\276\323S\274\322P\266" + "\314OQTC<;<777111,,,''&\37\37!~\214;\275\324O\273\322O\273\322O\273\322O" + "\273\322O\274\324O{\204P\22\22\22\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0OPG\302\323Y\301\323X\300\323W\277\322U\300\326SioLDDD???:" + "::444///***$$$\36\36\36\245\270G\272\321N\273\322O\273\322O\273\322O\272" + "\321O\244\266N,,0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\20\20\21" + "}\202U\306\327\\\303\323Y\302\323X\301\324W\234\251RHGLGGGBBB===777222,," + ",&&&!!!U].\276\325O\273\322O\273\322O\273\322O\273\322O\273\321NGHC\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0##&\243\255Z\306\325^\304\324\\" + "\303\324Y\304\327Y^aNLLLJJJDDD???999444///***$$$/1$\276\326P\273\322O\273" + "\322O\273\322O\273\322O\276\325NUWI\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0""447\275\310_\307\325_\306\325^\304\325\\\254\272WHHLMMMKKKGG" + "GBBB<<<777222,,,'''##!\267\315M\273\322O\273\322O\273\322O\273\322O\276\326" + "NY\\K\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\207\207\207\377\377\377\377\377\377\377" + "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\207\207\207\0\0" + "\0\0\0\0\0\0\0MMM\271\271\271\366\366\366\377\377\377\370\370\370\275\275" + "\275QQQ\0\0\0\0\0\0\0\0\0VVV\377\377\377\340\340\340\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\347\347\347\377\377\377OOO\0\0\0\326\326\326" + "\363\363\363\377\377\377\377\377\377\377\377\377\351\351\351\260\260\260" + "TTT\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\377\377\377\377\377\0\0\0\0\0" + "\0\0\0\0\377\377\377\377\377\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\15\15" + "\15\377\377\377\377\377\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0%%%\247\247\247" + "\356\356\356\377\377\377\377\377\377\357\357\357\304\304\304\216\216\216" + "\0\0\0\0\0\0""000\377\377\377\264\264\264\0\0\0\0\0\0""000\377\377\377\264" + "\264\264\0\0\0\0\0\0""000\377\377\377\264\264\264\0\0\0\0\0\0\0\0\0\0\0\0" + "FFC\311\325b\310\326b\307\325`\307\326^\207\217TLLLHHH}}}RRREEE???999444" + "///)))\"!#\261\307L\273\322O\273\322O\273\322O\273\322O\276\326NY\\K\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\177\177\177\377\377\377\277\277\277\177\177\177" + "\177\177\177\177\177\177\177\177\177\177\177\177???\0\0\0\1\1\1\305\305\305" + "\377\377\377\367\367\367\240\240\240\204\204\204\237\237\237\367\367\367" + "\377\377\377\310\310\310\1\1\1\0\0\0\0\0\0\377\377\377\377\377\377\33\33" + "\33\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0///\377\377\377\361\361\361\0\0\0" + "\0\0\0\377\377\377\377\377\377\200\200\200\177\177\177\211\211\211\250\250" + "\250\363\363\363\377\377\377\352\352\352(((\0\0\0\0\0\0\0\0\0\0\0\0\377\377" + "\377\377\377\377\0\0\0\0\0\0\0\0\0\377\377\377\377\377\377\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\266\266\266\376\376\376\377\377\377\0\0\0\0\0\0\0" + "\0\0\0\0\0ttt\377\377\377\377\377\377\267\267\267\207\207\207\205\205\205" + "\245\245\245\377\377\377\377\377\377\0\0\0\0\0\0rrr\377\377\377\377\377\377" + "\0\0\0\0\0\0rrr\377\377\377\377\377\377\0\0\0\0\0\0rrr\377\377\377\377\377" + "\377\0\0\0\0\0\0\0\0\0\1\1\1^`O\317\333f\312\325c\310\326b\311\327`x}RLL" + "Mnnn\377\377\377\341\341\341LLLBBB<<<777222,,,$#&\260\306L\273\322O\273\322" + "O\273\322O\273\322O\276\326NVYJ\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\177\177\177" + "\377\377\377\177\177\177\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\303\303" + "\303\377\377\377\255\255\255\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\255\255\255\377" + "\377\377\303\303\303\0\0\0\0\0\0\235\235\235\377\377\377\204\204\204\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\244\244\244\377\377\377}}}\0\0\0\0\0\0\377" + "\377\377\377\377\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0fff\377\377\377\377\377" + "\377\40\40\40\0\0\0\0\0\0\0\0\0\377\377\377\377\377\377\0\0\0\0\0\0\0\0\0" + "\377\377\377\377\377\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0CCC\377\377\377\377" + "\377\377\377\377\377\0\0\0\0\0\0\0\0\0NNN\377\377\377\361\361\361\33\33\33" + "\0\0\0\0\0\0\0\0\0\0\0\0\377\377\377\377\377\377\0\0\0\0\0\0\0\0\0rrr111" + "\0\0\0\0\0\0\0\0\0rrr111\0\0\0\0\0\0\0\0\0rrr111\0\0\0\0\0\0\0\0\0\2\2\2" + "ceP\321\333g\313\326d\312\325c\312\327b\177\205TKKL\224\224\224\377\377\377" + "\377\377\377\252\252\252BBB???999444...)))\265\313M\273\322O\273\322O\273" + "\322O\273\322O\274\324NNOF\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\177\177\177\377" + "\377\377\177\177\177\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0III\377\377\377\334" + "\334\334\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\334\334\334\377\377\377" + "GGG\0\0\0""666\377\377\377\353\353\353zzz\177\177\177\177\177\177\177\177" + "\177\177\177\177xxx\377\377\377\377\377\377\13\13\13\0\0\0\0\0\0\377\377" + "\377\377\377\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ccc\377\377\377\321\321" + "\321\0\0\0\0\0\0\0\0\0\377\377\377\377\377\377\0\0\0\0\0\0\0\0\0\377\377" + "\377\377\377\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\361\361\361\360\360\360\377" + "\377\377\377\377\377\0\0\0\0\0\0\0\0\0\355\355\355\377\377\377111\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\377\377\377\377\377\377\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\\^N\322\333i\314\327g\313\326d\312\326d\231\242YJJL\223" + "\223\223\377\377\377\376\376\376\373\373\373QQQBBB<<<77711123-\273\323O\273" + "\322O\273\322O\273\322O\273\322O\271\320NDDB\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\177\177\177\377\377\377\177\177\177\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\273\273\273\377\377\377VVV\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0X" + "XX\377\377\377\270\270\270\0\0\0\0\0\0\357\357\357\376\376\376\377\377\377" + "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\376\376\376" + "\266\266\266\0\0\0\0\0\0\0\0\0\377\377\377\377\377\377\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\355\355\355\377\377\377%%%\0\0\0\0\0\0\377\377\377" + "\377\377\377\0\0\0\0\0\0\0\0\0\377\377\377\377\377\377\0\0\0\0\0\0\0\0\0" + "\0\0\0\234\234\234\377\377\377YYY\377\377\377\377\377\377\0\0\0\0\0\0---" + "\377\377\377\333\333\333\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\377\377" + "\377\377\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0KLF\320\330k\316\327" + "i\314\327g\313\326e\275\310aJILuuu\377\377\377\377\377\377\377\377\377\201" + "\201\201DDD???:::444FI4\277\327P\273\322O\273\322O\273\322O\273\322O\263" + "\310N88:\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\177\177\177\377\377\377\177\177\177" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\366\366\366\377\377\377\17\17\17\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\20\20\20\377\377\377\365\365\365\0" + "\0\0\0\0\0\207\207\207\377\377\377\217\217\217\0\0\0\0\0\0\0\0\0\0\0\0\334" + "\334\334\377\377\377BBB\0\0\0\0\0\0\0\0\0\377\377\377\377\377\377\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\241\241\241\377\377\377eee\0\0\0\0\0\0" + "\377\377\377\377\377\377\0\0\0\0\0\0\0\0\0\377\377\377\377\377\377\0\0\0" + "\0\0\0\0\0\0""888\377\377\377\334\334\334\0\0\0\377\377\377\377\377\377\0" + "\0\0\0\0\0fff\377\377\377\232\232\232\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\377\377\377\377\377\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0""447\303" + "\311i\317\330j\315\327i\315\327f\317\333fmpRLLL\362\362\362\376\376\376\377" + "\377\377\227\227\227GGGAAA<<<667fn>\276\324Q\272\322O\273\322O\273\322O\272" + "\321N\247\272N,+/\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\177\177\177\377\377\377\177" + "\177\177\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\377\377\377\377\377\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\377\377\377\377\377" + "\0\0\0\0\0\0\37\37\37\377\377\377\375\375\375\0\0\0\0\0\0\0\0\0""444\377" + "\377\377\356\356\356\0\0\0\0\0\0\0\0\0\0\0\0\377\377\377\377\377\377\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\205\205\205\377\377\377|||\0\0\0\0" + "\0\0\377\377\377\377\377\377\0\0\0\0\0\0\0\0\0\377\377\377\377\377\377\0" + "\0\0\0\0\0\0\0\0\364\364\364\377\377\377###\0\0\0\377\377\377\377\377\377" + "\0\0\0\0\0\0zzz\377\377\377\203\203\203\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\207\207\207\207\207\207\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0!!$\247" + "\253c\321\330m\317\330k\316\327i\314\326g\267\300aKKK\205\205\205\377\377" + "\377\377\377\377hhhJJJDDD???669\225\242J\275\323R\274\321Q\272\322O\273\322" + "O\273\322O\225\245N\40\40\"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\177\177\177\377" + "\377\377\177\177\177\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\377\377\377" + "\377\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\377\377" + "\377\377\377\0\0\0\0\0\0\0\0\0\333\333\333\377\377\377III\0\0\0\0\0\0\250" + "\250\250\377\377\377zzz\0\0\0\0\0\0\0\0\0\0\0\0\377\377\377\377\377\377\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\216\216\216\377\377\377ttt\0\0\0" + "\0\0\0\377\377\377\377\377\377\0\0\0\0\0\0\0\0\0\377\377\377\377\377\377" + "\0\0\0\0\0\0\263\263\263\377\377\377\210\210\210\0\0\0\0\0\0\377\377\377" + "\377\377\377\0\0\0\0\0\0uuu\377\377\377\215\215\215\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\15\15" + "\15z|Z\324\333o\320\327l\317\330k\316\327h\317\331h\213\220YGGI^^^aaaKKK" + "LLLGGGBBBDE>\275\320U\276\323T\275\322R\274\321Q\273\322O\274\323O\200\212" + "O\22\22\23\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\177\177\177\377\377\377\177\177" + "\177\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\335\335\335\377\377\377,,,\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0...\377\377\377\334\334\334\0\0\0\0\0" + "\0\0\0\0rrr\377\377\377\260\260\260\0\0\0\2\2\2\377\377\377\377\377\377\11" + "\11\11\0\0\0\0\0\0\0\0\0\0\0\0\377\377\377\377\377\377\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\300\300\300\377\377\377KKK\0\0\0\0\0\0\377\377\377" + "\377\377\377\0\0\0\0\0\0\0\0\0\377\377\377\377\377\377\0\0\0bbb\377\377\377" + "\346\346\346\0\0\0\0\0\0\0\0\0\377\377\377\377\377\377\0\0\0\0\0\0LLL\377" + "\377\377\276\276\276\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0JJE\321\326o\322\330o\321\327" + "m\317\330k\316\327h\315\327h~\202VHHLMMMMMMLLLJJJA@D\211\223N\302\325X\300" + "\323V\276\323S\275\322R\274\321Q\276\326OdhM\4\4\4\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\177\177\177\377\377\377\177\177\177\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\213\213\213\377\377\377\217\217\217\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\221\221\221\377\377\377\210\210\210\0\0\0\0\0\0\0\0\0\13\13" + "\13\377\377\377\377\377\377\0\0\0ppp\377\377\377\263\263\263\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\377\377\377\377\377\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\17\17\17\377\377\377\377\377\377\0\0\0\0\0\0\0\0\0\377\377\377\377" + "\377\377\0\0\0\0\0\0\0\0\0\377\377\377\377\377\377\21\21\21\377\377\377\377" + "\377\377\"\"\"\0\0\0\0\0\0\0\0\0\377\377\377\377\377\377\0\0\0\0\0\0\0\0" + "\0\377\377\377\377\377\377\7\7\7\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0##&\250\253f\324\331p\322" + "\330n\321\327m\317\330k\316\327i\317\332h\233\242\\WXNHHLIILGFKy\177O\304" + "\325[\302\323Z\301\324X\300\323V\277\323T\275\323S\271\316PCCA\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\177\177\177\377\377\377\177\177\177\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\6\6\6\377\377\377\377\377\377%%%\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0%%%\377\377\377\377\377\377\5\5\5\0\0\0\0\0\0\0\0\0\0\0\0" + "\304\304\304\377\377\377RRR\345\345\345\377\377\377>>>\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\377\377\377\377\377\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\322\322\322\377\377\377{{{\0\0\0\0\0\0\0\0\0\377\377\377\377\377\377\0\0" + "\0\0\0\0\0\0\0\377\377\377\377\377\377\344\344\344\377\377\377ttt\0\0\0\0" + "\0\0\0\0\0\0\0\0\377\377\377\377\377\377\0\0\0\0\0\0\0\0\0\211\211\211\377" + "\377\377\273\273\273\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\7\7\7hiT\331\335s\323\331p\322\330" + "o\321\327m\317\327j\316\327i\316\327h\315\327f\264\275_\251\262\\\267\302" + "^\311\330_\305\324\\\304\324[\302\323Y\301\324X\300\323V\277\323T\241\260" + "Q('+\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\177\177\177\377\377\377\177\177" + "\177\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0FFF\377\377\377\377\377\377" + "sss\21\21\21\0\0\0\21\21\21rrr\377\377\377\377\377\377GGG\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0^^^\377\377\377\351\351\351\377\377\377\353\353\353\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\377\377\377\377\377\0\0\0\0\0\0\0\0\0\32" + "\32\32eee\354\354\354\377\377\377\257\257\257\0\0\0\0\0\0\0\0\0\0\0\0\377" + "\377\377\377\377\377\0\0\0\0\0\0\0\0\0\377\377\377\377\377\377\376\376\376" + "\310\310\310\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\377\377\377\377\377\0\0\0" + "\0\0\0\0\0\0\0\0\0\323\323\323\377\377\377\312\312\312888\0\0\0\0\0\0\36" + "\36\36nnnzzz\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0""114\273" + "\276l\324\331r\323\331q\322\330o\321\327m\317\327k\316\327j\315\326h\314" + "\327f\312\326d\311\326c\310\325a\306\325_\305\325\\\304\324\\\303\323Z\301" + "\324X\302\325Vy\200Q\17\17\20\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\177\177" + "\177\377\377\377\177\177\177\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0""111\336\336\336\377\377\377\377\377\377\377\377\377\377\377\377\377" + "\377\377\342\342\342333\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\377" + "\377\377\377\377\377\377\377www\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\377" + "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" + "\377\343\343\343[[[\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\377\377\377\377\377" + "\0\0\0\0\0\0\0\0\0\377\377\377\376\376\376\364\364\364\5\5\5\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\377\377\377\377\377\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\224\224\224\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" + "\377\377\377\324\324\324\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\15\15\15tuY\332\336u\325\331r\323\331p\322\330o\321\327m\320\327k" + "\316\327i\315\326h\314\327f\312\326d\311\326b\307\326a\307\325_\305\325]" + "\304\324\\\303\323Z\300\322XKMF\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "???\177\177\177???\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0(((fff{{{hhh,,,\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0aaa\177\177\177\205\205\205\14\14\14\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0===aaavvv}}}qqqWWW\35\35\35\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\207" + "\207\207\207\207\207\0\0\0\0\0\0\0\0\0\207\207\207\201\201\201%%%\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\207\207\207\207\207\207\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\3\3\3RRRuuuzzz]]]\40\40\40\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0""668\300\302o\326\331s\325\331r\323" + "\331q\322\330o\321\327l\320\330k\316\327j\315\326h\314\327e\312\326d\311" + "\326c\310\326a\307\325^\305\325]\304\325\\\236\251V%$'\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\15\15\16uvZ" + "\334\336w\326\332t\325\331r\324\331q\322\331o\321\330m\320\330l\316\327j" + "\315\326h\313\327f\313\326e\311\325c\310\326a\307\325^\311\330^cfP\7\7\7" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0""658\301\302p\327\331u\326\332t\325\331s\324\331q\322\331o\321" + "\330m\320\330k\316\327j\315\326h\314\327f\313\326d\311\325c\310\326a\252" + "\264Z//2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\15\15\15vvZ\335\337y\330\331v\326\332u\325\331" + "s\324\330q\322\331n\321\330n\320\330l\317\327j\315\326g\314\326g\313\326" + "e\314\330cdfP\11\11\11\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0""99:\307\307s\331\332w\330" + "\331v\326\332t\325\331s\324\330q\322\331o\321\330m\320\330l\317\327j\315" + "\326h\314\327g\236\246\\((+\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\16\16\16llW\334" + "\334z\331\332w\330\331w\326\331u\325\331s\324\330p\323\331o\321\330n\320" + "\330l\316\327i\306\317gLMH\2\2\2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0!!#\206" + "\206a\334\334z\331\332x\327\331v\327\331u\325\331s\324\330q\323\331p\321" + "\330m\322\331lsuV\24\24\25\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\"\"$ppY\310\310s\336\337z\330\332w\327\332u\326\332s\325\332q\321\326" + "o\201\204\\%%'\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\17\17\17::;rrZ\234\236f\254\255i\250\252g\212\214_RSK\34\34\36\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\11" + "\11\11\31\31\32!!#\37\37!\22\22\23\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0"; + +//////////////////////////////////////////////////////////////////////////////// + +LoadingTexture:: +LoadingTexture() + : Texture2D(128, 39, scm::gl::FORMAT_RGB_8, {pixel_data}) +{} + //////////////////////////////////////////////////////////////////////////////// DefaultTexture:: DefaultTexture() #if WIN32 - : Texture(64, 64, scm::gl::FORMAT_RGB_8, {pixel_data}) + : Texture2D(64, 64, scm::gl::FORMAT_RGB_8, {pixel_data}) #else - : Texture(256, 256, scm::gl::FORMAT_RGB_8, {pixel_data}) + : Texture2D(256, 256, scm::gl::FORMAT_RGB_8, {pixel_data}) #endif {} diff --git a/src/gua/renderer/CompositePass.cpp b/src/gua/renderer/CompositePass.cpp new file mode 100644 index 000000000..6789fb9b7 --- /dev/null +++ b/src/gua/renderer/CompositePass.cpp @@ -0,0 +1,272 @@ +/****************************************************************************** + * guacamole - delicious VR * + * * + * Copyright: (c) 2011-2013 Bauhaus-Universität Weimar * + * Contact: felix.lauer@uni-weimar.de / simon.schneegans@uni-weimar.de * + * * + * This program is free software: you can redistribute it and/or modify it * + * under the terms of the GNU General Public License as published by the Free * + * Software Foundation, either version 3 of the License, or (at your option) * + * any later version. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * + * for more details. * + * * + * You should have received a copy of the GNU General Public License along * + * with this program. If not, see . * + * * + ******************************************************************************/ + +// class header +#include + +// guacamole headers +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace gua { + +//////////////////////////////////////////////////////////////////////////////// + +CompositePass::CompositePass(Pipeline* pipeline) : + Pass(pipeline), + composite_shader_(new ShaderProgram), + ray_generation_shader_(new ShaderProgram), + volume_raygeneration_buffer_(nullptr) +{ + std::string vertex_shader (Resources::lookup_shader(Resources::shaders_uber_shaders_composite_compose_vert)); + std::string fragment_shader(Resources::lookup_shader(Resources::shaders_uber_shaders_composite_compose_frag)); + + composite_shader_->create_from_sources(vertex_shader, fragment_shader); + + std::string ray_generation_vertex_shader(Resources::lookup_shader(Resources::shaders_uber_shaders_composite_ray_generation_vert)); + std::string ray_generation_fragment_shader(Resources::lookup_shader(Resources::shaders_uber_shaders_composite_ray_generation_frag)); + + ray_generation_shader_->create_from_sources(ray_generation_vertex_shader, ray_generation_fragment_shader); +} + +//////////////////////////////////////////////////////////////////////////////// + +CompositePass::~CompositePass() { + + if (composite_shader_) { + delete composite_shader_; + } + + if (volume_raygeneration_buffer_) { + delete volume_raygeneration_buffer_; + } + + if (ray_generation_shader_) { + delete ray_generation_shader_; + } +} + +//////////////////////////////////////////////////////////////////////////////// + +void CompositePass::create(RenderContext const& ctx, std::vector> const& layers) { + + // reuse gbuffer from shading-pass + gbuffer_ = inputs_[Pipeline::PipelineStage::shading]; + + if (volume_raygeneration_buffer_) { + volume_raygeneration_buffer_->remove_buffers(ctx); + delete volume_raygeneration_buffer_; + } + + scm::gl::sampler_state_desc state(scm::gl::FILTER_MIN_MAG_LINEAR, + scm::gl::WRAP_CLAMP_TO_EDGE, + scm::gl::WRAP_CLAMP_TO_EDGE); + + std::vector> layer_3f_desc; + layer_3f_desc.push_back(std::make_pair(BufferComponent::F3, state)); + + volume_raygeneration_buffer_ = new GBuffer(layer_3f_desc, + pipeline_->config.get_left_resolution()[0], + pipeline_->config.get_left_resolution()[1]); + volume_raygeneration_buffer_->create(ctx); +} + +//////////////////////////////////////////////////////////////////////////////// + +/* virtual */ void CompositePass::rendering(SerializedScene const& scene, + RenderContext const& ctx, + CameraMode eye, + Camera const& camera, + FrameBufferObject* target) +{ + init_ressources(ctx); + + ctx.render_context->set_depth_stencil_state(depth_stencil_state_); + + // 1. render proxy geometry into fbo + volume_raygeneration_buffer_->bind(ctx); + { + scm::math::vec2f resolution(volume_raygeneration_buffer_->width(), volume_raygeneration_buffer_->height()); + ctx.render_context->set_viewport(scm::gl::viewport(math::vec2(0, 0), resolution)); + + volume_raygeneration_buffer_->clear_color_buffers(ctx, gua::utils::Color3f(0.0f, 0.0f, 0.0f)); + volume_raygeneration_buffer_->clear_depth_stencil_buffer(ctx); + + ///TODO: Toplevel + if (!scene.volumenodes_.empty()) + { + // gather input textures and set uniforms + Pass::set_camera_matrices(*ray_generation_shader_, camera, pipeline_->get_current_scene(eye), eye, ctx); + + ray_generation_shader_->set_uniform(ctx, 1.f / gbuffer_->get_eye_buffers()[eye == CameraMode::RIGHT ? 1 : 0]->width(), "gua_texel_width"); + ray_generation_shader_->set_uniform(ctx, 1.f / gbuffer_->get_eye_buffers()[eye == CameraMode::RIGHT ? 1 : 0]->height(), "gua_texel_height"); + + + volume_raygeneration_buffer_->clear_color_buffers(ctx, gua::utils::Color3f(0.0f, 0.0f, 0.0f)); + volume_raygeneration_buffer_->clear_depth_stencil_buffer(ctx); + + for (auto const& node : scene.volumenodes_) { + + auto volume = + std::static_pointer_cast(GeometryDatabase::instance()->lookup(node->data.get_volume())); + + if (volume) { + ray_generation_shader_->set_uniform( + ctx, node->get_world_transform(), "gua_model_matrix"); + + ray_generation_shader_->set_uniform( + ctx, 0, "volume_frag_id"); + + ray_generation_shader_->use(ctx); + { + volume->draw_proxy(ctx); + } + ray_generation_shader_->unuse(ctx); + } + } + } + } + volume_raygeneration_buffer_->unbind(ctx); + + scm::gl::context_all_guard cug(ctx.render_context); + + // 2. render fullscreen quad for compositing and volume ray castinG + Pass::set_camera_matrices(*composite_shader_, camera, pipeline_->get_current_scene(eye), eye, ctx); + + auto input_tex(inputs_[Pipeline::shading]->get_eye_buffers()[eye == CameraMode::RIGHT ? 1 : 0]->get_color_buffers(TYPE_FLOAT)[0]); + auto normal_tex(inputs_[Pipeline::geometry]->get_eye_buffers()[eye == CameraMode::RIGHT ? 1 : 0]->get_color_buffers(TYPE_FLOAT)[0]); + auto depth_tex(inputs_[Pipeline::geometry]->get_eye_buffers()[eye == CameraMode::RIGHT ? 1 : 0]->get_depth_buffer()); + + auto raygen_tex(volume_raygeneration_buffer_->get_color_buffers(TYPE_FLOAT)[0]); + + composite_shader_->set_uniform(ctx, input_tex, "gua_color_gbuffer_in"); + composite_shader_->set_uniform(ctx, normal_tex, "gua_normal_gbuffer_in"); + composite_shader_->set_uniform(ctx, depth_tex, "gua_depth_gbuffer_in"); + composite_shader_->set_uniform(ctx, raygen_tex, "gua_ray_entry_in"); + + composite_shader_->set_uniform(ctx, 1.f / gbuffer_->get_eye_buffers()[eye == CameraMode::RIGHT ? 1 : 0]->width(), "gua_texel_width"); + composite_shader_->set_uniform(ctx, 1.f / gbuffer_->get_eye_buffers()[eye == CameraMode::RIGHT ? 1 : 0]->height(), "gua_texel_height"); + + // bind target fbo and set viewport + target->bind(ctx); + ctx.render_context->set_viewport(scm::gl::viewport( + math::vec2(0, 0), + ::scm::math::vec2f(target->width(), target->height()))); + + if (!scene.volumenodes_.empty()){ + + for (auto const& node : scene.volumenodes_) { + + auto volume = + std::static_pointer_cast(GeometryDatabase::instance()->lookup(node->data.get_volume())); + + if (volume) { + composite_shader_->set_uniform( + ctx, node->get_world_transform(), "gua_model_matrix"); + + volume->set_uniforms(ctx, composite_shader_); + + composite_shader_->use(ctx); + { + fullscreen_quad_->draw(ctx.render_context); + } + composite_shader_->unuse(ctx); + } + } + + } + + target->unbind(ctx); + + ctx.render_context->reset_state_objects(); +} + +//////////////////////////////////////////////////////////////////////////////// + +void CompositePass::init_ressources(RenderContext const& ctx) { + + if (!depth_stencil_state_) { + depth_stencil_state_ = ctx.render_device->create_depth_stencil_state(false, false, scm::gl::COMPARISON_NEVER); + } + + if (!fullscreen_quad_) { + fullscreen_quad_ = scm::gl::quad_geometry_ptr(new scm::gl::quad_geometry(ctx.render_device, math::vec2(-1.f, -1.f), math::vec2(1.f, 1.f))); + } +} + +//////////////////////////////////////////////////////////////////////////////// + +/* virtual */ LayerMapping const* CompositePass::get_gbuffer_mapping() const { + throw std::runtime_error("no gbuffer mapping available for composite pass"); +} + +//////////////////////////////////////////////////////////////////////////////// + +void CompositePass::print_shaders(std::string const& directory, + std::string const& name) const { + composite_shader_->save_to_file(directory, name + "/composite_shader"); + ray_generation_shader_->save_to_file(directory, name + "/ray_generation_shader"); +} + +//////////////////////////////////////////////////////////////////////////////// + +bool CompositePass::pre_compile_shaders(RenderContext const& ctx) { + + if (composite_shader_) return composite_shader_->upload_to(ctx); + if (ray_generation_shader_) return ray_generation_shader_->upload_to(ctx); + + return false; +} + +//////////////////////////////////////////////////////////////////////////////// + +void CompositePass::render_scene(Camera const& camera, RenderContext const& ctx) { + + for (int i(0); i < gbuffer_->get_eye_buffers().size(); ++i) { + + FrameBufferObject* fbo(gbuffer_->get_eye_buffers()[i]); + + CameraMode eye(CameraMode::CENTER); + if (gbuffer_->get_eye_buffers().size() > 1 && i == 0) + eye = CameraMode::LEFT; + if (gbuffer_->get_eye_buffers().size() > 1 && i == 1) + eye = CameraMode::RIGHT; + + fbo->bind(ctx); + + ctx.render_context->set_viewport(scm::gl::viewport( + math::vec2(0, 0), ::scm::math::vec2f(fbo->width(), fbo->height()))); + + rendering(pipeline_->get_current_scene(eye), ctx, eye, camera, fbo); + + fbo->unbind(ctx); + } +} + +} diff --git a/src/gua/renderer/FinalPass.cpp b/src/gua/renderer/FinalPass.cpp index 33277d432..fa01bcd0e 100644 --- a/src/gua/renderer/FinalPass.cpp +++ b/src/gua/renderer/FinalPass.cpp @@ -69,10 +69,10 @@ void FinalPass::set_uniforms(SerializedScene const& scene, shader_->set_uniform( ctx, pipeline_->config.ambient_color(), "gua_ambient_color"); shader_->set_uniform(ctx, - pipeline_->config.background_texture().empty(), - "gua_background_is_color"); + static_cast(pipeline_->config.background_mode()), + "gua_background_mode"); - if (pipeline_->config.background_texture().empty()) + if (pipeline_->config.background_mode() == Pipeline::BackgroundMode::COLOR || pipeline_->config.background_texture() == "") shader_->set_uniform( ctx, pipeline_->config.background_color(), "gua_background_color"); else diff --git a/src/gua/renderer/FrameBufferObject.cpp b/src/gua/renderer/FrameBufferObject.cpp index 2fc141307..5f3ba892b 100644 --- a/src/gua/renderer/FrameBufferObject.cpp +++ b/src/gua/renderer/FrameBufferObject.cpp @@ -55,7 +55,7 @@ void FrameBufferObject::remove_attachments() { void FrameBufferObject::attach_color_buffer(RenderContext const& ctx, unsigned in_color_attachment, - std::shared_ptr const& buffer, + std::shared_ptr const& buffer, int mip_level, int z_slice) { @@ -79,7 +79,7 @@ void FrameBufferObject::attach_color_buffer(RenderContext const& ctx, void FrameBufferObject::attach_depth_stencil_buffer( RenderContext const& ctx, - std::shared_ptr const& buffer, + std::shared_ptr const& buffer, int mip_level, int z_slice) { @@ -163,7 +163,7 @@ void FrameBufferObject::set_viewport(RenderContext const& ctx) const { //////////////////////////////////////////////////////////////////////////////// -bool FrameBufferObject::set_size(std::shared_ptr const& buffer) { +bool FrameBufferObject::set_size(std::shared_ptr const& buffer) { if (width_ == 0 && height_ == 0) { width_ = buffer->width(); diff --git a/src/gua/renderer/Frustum.cpp b/src/gua/renderer/Frustum.cpp index 0b2585fef..f6412ce82 100644 --- a/src/gua/renderer/Frustum.cpp +++ b/src/gua/renderer/Frustum.cpp @@ -26,75 +26,83 @@ namespace gua { -Frustum::Frustum(math::mat4 const& camera_transform, - math::mat4 const& screen_transform, - float clip_near, - float clip_far) - : camera_position_(), +Frustum::Frustum() + : camera_transform_(math::mat4::identity()), + screen_transform_(math::mat4::identity()), projection_(math::mat4::identity()), view_(math::mat4::identity()), - planes_(6) { + planes_(6), + clip_near_(0), + clip_far_(0) {} - projection_ = math::compute_frustum( - camera_transform.column(3), screen_transform, clip_near, clip_far); +//////////////////////////////////////////////////////////////////////////////// - math::mat4 view_transform(screen_transform); - view_transform[12] = 0.f; - view_transform[13] = 0.f; - view_transform[14] = 0.f; - view_transform[15] = 1.f; +Frustum Frustum::perspective(math::mat4 const& camera_transform, + math::mat4 const& screen_transform, + float clip_near, + float clip_far) { - camera_position_ = math::vec3(camera_transform.column(3)[0], - camera_transform.column(3)[1], - camera_transform.column(3)[2]); + auto projection = math::compute_perspective_frustum( + camera_transform.column(3), screen_transform, clip_near, clip_far); - view_transform = - scm::math::make_translation(camera_position_) * view_transform; + Frustum result; - view_ = scm::math::inverse(view_transform); + result.projection_ = projection; + result.clip_near_ = clip_near; + result.clip_far_ = clip_far; - auto frustum(projection_ * view_); + init_frustum_members(camera_transform, screen_transform, result); - //store normals + return result; +} - //left plane - planes_[0] = math::vec4(frustum[3] + frustum[0], - frustum[7] + frustum[4], - frustum[11] + frustum[8], - frustum[15] + frustum[12]); +//////////////////////////////////////////////////////////////////////////////// - //right plane - planes_[1] = math::vec4(frustum[3] - frustum[0], - frustum[7] - frustum[4], - frustum[11] - frustum[8], - frustum[15] - frustum[12]); +Frustum Frustum::orthographic(math::mat4 const& camera_transform, + math::mat4 const& screen_transform, + float clip_near, + float clip_far) { - //bottom plane - planes_[2] = math::vec4(frustum[3] + frustum[1], - frustum[7] + frustum[5], - frustum[11] + frustum[9], - frustum[15] + frustum[13]); + auto projection = math::compute_orthographic_frustum( + camera_transform.column(3), screen_transform, clip_near, clip_far); - //top plane - planes_[3] = math::vec4(frustum[3] - frustum[1], - frustum[7] - frustum[5], - frustum[11] - frustum[9], - frustum[15] - frustum[13]); + Frustum result; - //near plane - planes_[4] = math::vec4(frustum[3] + frustum[2], - frustum[7] + frustum[6], - frustum[11] + frustum[10], - frustum[15] + frustum[14]); + result.projection_ = projection; + result.clip_near_ = clip_near; + result.clip_far_ = clip_far; - //far plane - planes_[5] = math::vec4(frustum[3] - frustum[2], - frustum[7] - frustum[6], - frustum[11] - frustum[10], - frustum[15] - frustum[14]); + init_frustum_members(camera_transform, screen_transform, result); + return result; } +//////////////////////////////////////////////////////////////////////////////// + +std::vector Frustum::get_corners() const { + std::vector tmp(8); + std::vector result(8); + + auto inverse_transform(scm::math::inverse(projection_ * view_)); + + tmp[0] = inverse_transform * math::vec4(-1, -1, -1, 1); + tmp[1] = inverse_transform * math::vec4(-1, -1, 1, 1); + tmp[2] = inverse_transform * math::vec4(-1, 1, -1, 1); + tmp[3] = inverse_transform * math::vec4(-1, 1, 1, 1); + tmp[4] = inverse_transform * math::vec4( 1, -1, -1, 1); + tmp[5] = inverse_transform * math::vec4( 1, -1, 1, 1); + tmp[6] = inverse_transform * math::vec4( 1, 1, -1, 1); + tmp[7] = inverse_transform * math::vec4( 1, 1, 1, 1); + + for (int i(0); i<8; ++i) { + result[i] = tmp[i]/tmp[i][3]; + } + + return result; +} + +//////////////////////////////////////////////////////////////////////////////// + bool Frustum::is_inside(math::BoundingBox const& bbox) const { auto distance = [](math::vec4 const & plane, math::vec3 const & point) { @@ -121,4 +129,66 @@ bool Frustum::is_inside(math::BoundingBox const& bbox) const { return true; } +//////////////////////////////////////////////////////////////////////////////// + +void Frustum::init_frustum_members(math::mat4 const& camera_transform, + math::mat4 const& screen_transform, + Frustum& frustum) { + + math::mat4 view_transform(screen_transform); + view_transform[12] = 0.f; + view_transform[13] = 0.f; + view_transform[14] = 0.f; + view_transform[15] = 1.f; + + frustum.camera_transform_ = camera_transform; + frustum.screen_transform_ = screen_transform; + + view_transform = + scm::math::make_translation(frustum.get_camera_position()) * view_transform; + + frustum.view_ = scm::math::inverse(view_transform); + + auto projection_view(frustum.projection_ * frustum.view_); + + //store normals + + //left plane + frustum.planes_[0] = math::vec4(projection_view[3] + projection_view[0], + projection_view[7] + projection_view[4], + projection_view[11] + projection_view[8], + projection_view[15] + projection_view[12]); + + //right plane + frustum.planes_[1] = math::vec4(projection_view[3] - projection_view[0], + projection_view[7] - projection_view[4], + projection_view[11] - projection_view[8], + projection_view[15] - projection_view[12]); + + //bottom plane + frustum.planes_[2] = math::vec4(projection_view[3] + projection_view[1], + projection_view[7] + projection_view[5], + projection_view[11] + projection_view[9], + projection_view[15] + projection_view[13]); + + //top plane + frustum.planes_[3] = math::vec4(projection_view[3] - projection_view[1], + projection_view[7] - projection_view[5], + projection_view[11] - projection_view[9], + projection_view[15] - projection_view[13]); + + //near plane + frustum.planes_[4] = math::vec4(projection_view[3] + projection_view[2], + projection_view[7] + projection_view[6], + projection_view[11] + projection_view[10], + projection_view[15] + projection_view[14]); + + //far plane + frustum.planes_[5] = math::vec4(projection_view[3] - projection_view[2], + projection_view[7] - projection_view[6], + projection_view[11] - projection_view[10], + projection_view[15] - projection_view[14]); +} + + } diff --git a/src/gua/renderer/FullscreenPass.cpp b/src/gua/renderer/FullscreenPass.cpp index 46d3fa00f..21dbe443c 100644 --- a/src/gua/renderer/FullscreenPass.cpp +++ b/src/gua/renderer/FullscreenPass.cpp @@ -67,7 +67,7 @@ void FullscreenPass::render_scene(Camera const& camera, RenderContext const& ctx fbo->bind(ctx); ctx.render_context->set_viewport(scm::gl::viewport( - math::vec2(0, 0), math::vec2(fbo->width(), fbo->height()))); + math::vec2(0, 0), math::vec2(float(fbo->width()), float(fbo->height())))); ctx.render_context->set_depth_stencil_state(depth_stencil_state_); rendering(camera, pipeline_->get_current_scene(eye), eye, ctx); diff --git a/src/gua/renderer/GBuffer.cpp b/src/gua/renderer/GBuffer.cpp index 527ac4fbb..cd8387996 100644 --- a/src/gua/renderer/GBuffer.cpp +++ b/src/gua/renderer/GBuffer.cpp @@ -167,10 +167,10 @@ GBuffer::GBuffer( height_(height), mipmap_layers_(mipmap_layers) { - color_buffers_[TYPE_INTEGER] = std::vector >(); - color_buffers_[TYPE_UNSIGNED] = std::vector >(); - color_buffers_[TYPE_HALF] = std::vector >(); - color_buffers_[TYPE_FLOAT] = std::vector >(); + color_buffers_[TYPE_INTEGER] = std::vector >(); + color_buffers_[TYPE_UNSIGNED] = std::vector >(); + color_buffers_[TYPE_HALF] = std::vector >(); + color_buffers_[TYPE_FLOAT] = std::vector >(); } void GBuffer::remove_buffers(RenderContext const& ctx) { @@ -194,12 +194,12 @@ void GBuffer::create(RenderContext const& ctx) { auto format = to_scm_data_format(type); if (format) { if (type == BufferComponent::DEPTH_16 || type == BufferComponent::DEPTH_24) { - depth_buffer_ = std::make_shared( + depth_buffer_ = std::make_shared( width_, height_, *format, mipmap_layers_, state); attach_depth_stencil_buffer(ctx, depth_buffer_); } else if (type != BufferComponent::NONE) { color_buffers_[enums::get_type(type)].push_back( - std::make_shared( width_, + std::make_shared( width_, height_, *format, mipmap_layers_, @@ -221,12 +221,12 @@ void GBuffer::create_UGLY(RenderContext const & ctx) { auto format = to_scm_data_format(type); if (format) { if (type == BufferComponent::DEPTH_16 || type == BufferComponent::DEPTH_24) { - depth_buffer_ = std::make_shared( + depth_buffer_ = std::make_shared( width_, height_, *format, mipmap_layers_, state); attach_depth_stencil_buffer(ctx, depth_buffer_); } else if (type != BufferComponent::NONE) { color_buffers_[enums::get_type(type)].push_back( - std::make_shared( width_, + std::make_shared( width_, height_, *format, mipmap_layers_, @@ -240,7 +240,7 @@ void GBuffer::create_UGLY(RenderContext const & ctx) { } } -std::vector > const& GBuffer::get_color_buffers( +std::vector > const& GBuffer::get_color_buffers( BufferComponentType type) const { return color_buffers_.find(type)->second; } diff --git a/src/gua/renderer/GBufferPass.cpp b/src/gua/renderer/GBufferPass.cpp index debf7f46e..04fcc2c28 100644 --- a/src/gua/renderer/GBufferPass.cpp +++ b/src/gua/renderer/GBufferPass.cpp @@ -32,7 +32,7 @@ #include #include -#define DEBUG_XFB_OUTPUT +// #define DEBUG_XFB_OUTPUT namespace gua { @@ -66,18 +66,17 @@ GBufferPass::~GBufferPass() { void GBufferPass::create( RenderContext const& ctx, - PipelineConfiguration const& config, std::vector > const& layers) { scm::gl::sampler_state_desc state(scm::gl::FILTER_MIN_MAG_MIP_NEAREST, - scm::gl::WRAP_CLAMP_TO_EDGE, - scm::gl::WRAP_CLAMP_TO_EDGE); + scm::gl::WRAP_MIRRORED_REPEAT, + scm::gl::WRAP_MIRRORED_REPEAT); auto tmp(layers); tmp.insert(tmp.begin(), std::make_pair(BufferComponent::DEPTH_24, state)); - Pass::create(ctx, config, tmp); + Pass::create(ctx, tmp); } @@ -132,19 +131,20 @@ void GBufferPass::rendering(SerializedScene const& scene, ctx.render_context->set_depth_stencil_state(depth_stencil_state_); - if (!scene.meshnodes_.empty() || scene.textured_quads_.empty() || (pipeline_->config.enable_bbox_display() && !scene.bounding_boxes_.empty())) { - mesh_shader_->set_material_uniforms( - scene.materials_, ShadingModel::GBUFFER_VERTEX_STAGE, ctx); - mesh_shader_->set_material_uniforms( - scene.materials_, ShadingModel::GBUFFER_FRAGMENT_STAGE, ctx); + mesh_shader_->set_material_uniforms( + scene.materials_, ShadingModel::GBUFFER_VERTEX_STAGE, ctx); + mesh_shader_->set_material_uniforms( + scene.materials_, ShadingModel::GBUFFER_FRAGMENT_STAGE, ctx); - Pass::bind_inputs(*mesh_shader_, eye, ctx); - Pass::set_camera_matrices(*mesh_shader_, - camera, - pipeline_->get_current_scene(eye), - eye, - ctx); - } + mesh_shader_->set_uniform(ctx, scene.enable_global_clipping_plane, "gua_enable_global_clipping_plane"); + mesh_shader_->set_uniform(ctx, scene.global_clipping_plane, "gua_global_clipping_plane"); + + Pass::bind_inputs(*mesh_shader_, eye, ctx); + Pass::set_camera_matrices(*mesh_shader_, + camera, + pipeline_->get_current_scene(eye), + eye, + ctx); if (!scene.meshnodes_.empty()) { @@ -154,19 +154,19 @@ void GBufferPass::rendering(SerializedScene const& scene, for (auto const& node : scene.meshnodes_) { auto geometry = - GeometryDatabase::instance()->lookup(node.data.get_geometry()); + GeometryDatabase::instance()->lookup(node->get_geometry()); auto material = - MaterialDatabase::instance()->lookup(node.data.get_material()); + MaterialDatabase::instance()->lookup(node->get_material()); if (material && geometry) { mesh_shader_->set_uniform( ctx, material->get_id(), "gua_material_id"); mesh_shader_->set_uniform( - ctx, node.transform, "gua_model_matrix"); + ctx, node->get_world_transform(), "gua_model_matrix"); mesh_shader_->set_uniform( ctx, scm::math::transpose( - scm::math::inverse(node.transform)), + scm::math::inverse(node->get_world_transform())), "gua_normal_matrix"); geometry->draw(ctx); @@ -188,8 +188,8 @@ void GBufferPass::rendering(SerializedScene const& scene, auto material = MaterialDatabase::instance()->lookup("gua_textured_quad"); - std::string texture_name(node.data.get_texture()); - if (node.data.get_is_stereo_texture()) { + std::string texture_name(node->data.get_texture()); + if (node->data.get_is_stereo_texture()) { if (eye == CameraMode::LEFT) { texture_name += "_left"; @@ -201,26 +201,36 @@ void GBufferPass::rendering(SerializedScene const& scene, if (TextureDatabase::instance()->is_supported(texture_name)) { auto texture = TextureDatabase::instance()->lookup(texture_name); - auto mapped( + auto mapped_texture( mesh_shader_->get_uniform_mapping()->get_mapping("gua_textured_quad", "texture")); - mesh_shader_->set_uniform(ctx, texture, mapped.first, mapped.second); + mesh_shader_->set_uniform(ctx, texture, mapped_texture.first, mapped_texture.second); + + auto mapped_flip_x( + mesh_shader_->get_uniform_mapping()->get_mapping("gua_textured_quad", "flip_x")); + + mesh_shader_->set_uniform(ctx, node->data.get_flip_x(), mapped_flip_x.first, mapped_flip_x.second); + + auto mapped_flip_y( + mesh_shader_->get_uniform_mapping()->get_mapping("gua_textured_quad", "flip_y")); + + mesh_shader_->set_uniform(ctx, node->data.get_flip_y(), mapped_flip_y.first, mapped_flip_y.second); if (material && geometry) { mesh_shader_->set_uniform( ctx, material->get_id(), "gua_material_id"); mesh_shader_->set_uniform( - ctx, node.transform, "gua_model_matrix"); + ctx, node->get_scaled_world_transform(), "gua_model_matrix"); mesh_shader_->set_uniform( ctx, scm::math::transpose( - scm::math::inverse(node.transform)), + scm::math::inverse(node->get_scaled_world_transform())), "gua_normal_matrix"); geometry->draw(ctx); } } else { - WARNING("Failed to render TexturedQuad: Texture \"%s\" not found!", texture_name.c_str()); + WARNING("Failed to render TexturedQuad: Texture2D \"%s\" not found!", texture_name.c_str()); } } } @@ -245,6 +255,10 @@ void GBufferPass::rendering(SerializedScene const& scene, nurbs_shader_->set_material_uniforms( scene.materials_, ShadingModel::GBUFFER_FRAGMENT_STAGE, ctx); + // TODO: add this functionality to NURBS! + // nurbs_shader_->set_uniform(ctx, scene.enable_global_clipping_plane, "gua_enable_global_clipping_plane"); + // nurbs_shader_->set_uniform(ctx, scene.global_clipping_plane, "gua_global_clipping_plane"); + nurbs_shader_->set_uniform(ctx, pipeline_->config.get_max_tesselation(), "gua_max_tesselation"); @@ -252,9 +266,9 @@ void GBufferPass::rendering(SerializedScene const& scene, for (auto const& node : scene.nurbsnodes_) { auto geometry = - GeometryDatabase::instance()->lookup(node.data.get_geometry()); + GeometryDatabase::instance()->lookup(node->get_geometry()); auto material = - MaterialDatabase::instance()->lookup(node.data.get_material()); + MaterialDatabase::instance()->lookup(node->get_material()); #ifdef DEBUG_XFB_OUTPUT scm::gl::transform_feedback_statistics_query_ptr q = ctx @@ -265,10 +279,10 @@ void GBufferPass::rendering(SerializedScene const& scene, nurbs_shader_->get_pre_shader().use(ctx); { nurbs_shader_->get_pre_shader() - .set_uniform(ctx, node.transform, "gua_model_matrix"); + .set_uniform(ctx, node->get_world_transform(), "gua_model_matrix"); nurbs_shader_->get_pre_shader().set_uniform( ctx, - scm::math::transpose(scm::math::inverse(node.transform)), + scm::math::transpose(scm::math::inverse(node->get_world_transform())), "gua_normal_matrix"); ctx.render_context->apply(); @@ -290,11 +304,11 @@ void GBufferPass::rendering(SerializedScene const& scene, nurbs_shader_->set_uniform( ctx, material->get_id(), "gua_material_id"); nurbs_shader_->set_uniform( - ctx, node.transform, "gua_model_matrix"); + ctx, node->get_world_transform(), "gua_model_matrix"); nurbs_shader_->set_uniform( ctx, scm::math::transpose( - scm::math::inverse(node.transform)), + scm::math::inverse(node->get_world_transform())), "gua_normal_matrix"); geometry->draw(ctx); @@ -344,15 +358,14 @@ void GBufferPass::rendering(SerializedScene const& scene, mesh_shader_->use(ctx); // re-use mesh_shader for (auto const& ray : scene.rays_) { - auto geometry = - GeometryDatabase::instance()->lookup(ray.data.get_geometry()); + auto geometry = GeometryDatabase::instance()->lookup("gua_ray_geometry"); mesh_shader_->set_uniform( ctx, bbox_material->get_id(), "gua_material_id"); - mesh_shader_->set_uniform(ctx, ray.transform, "gua_model_matrix"); + mesh_shader_->set_uniform(ctx, ray->get_world_transform(), "gua_model_matrix"); mesh_shader_->set_uniform( ctx, - scm::math::transpose(scm::math::inverse(ray.transform)), + scm::math::transpose(scm::math::inverse(ray->get_world_transform())), "gua_normal_matrix"); geometry->draw(ctx); diff --git a/src/gua/renderer/GeometryLoader.cpp b/src/gua/renderer/GeometryLoader.cpp index 105068a59..d7f942784 100644 --- a/src/gua/renderer/GeometryLoader.cpp +++ b/src/gua/renderer/GeometryLoader.cpp @@ -24,10 +24,12 @@ // guacamole headers #include -#include +#include #include #include +#include #include +#include #include // external headers @@ -45,6 +47,7 @@ std::unordered_map> GeometryLoader::GeometryLoader() : fileloaders_() { fileloaders_.push_back(new MeshLoader); fileloaders_.push_back(new NURBSLoader); + fileloaders_.push_back(new VolumeLoader); } //////////////////////////////////////////////////////////////////////////////// @@ -60,12 +63,7 @@ GeometryLoader::~GeometryLoader() { //////////////////////////////////////////////////////////////////////////////// -std::shared_ptr GeometryLoader::create_geometry_from_file - (std::string const& node_name, - std::string const& file_name, - std::string const& fallback_material, - unsigned flags) { - +std::shared_ptr GeometryLoader::load_geometry(std::string const& file_name, unsigned flags) { std::shared_ptr cached_node; std::string key(file_name + "_" + string_utils::to_string(flags)); @@ -80,7 +78,7 @@ std::shared_ptr GeometryLoader::create_geometry_from_file bool fileload_succeed = false; for (auto f : fileloaders_) { if (f->is_supported(file_name)) { - cached_node = f->load(file_name, fallback_material, flags); + cached_node = f->load(file_name, flags); cached_node->update_cache(); loaded_files_.insert(std::make_pair(key, cached_node)); @@ -113,15 +111,109 @@ std::shared_ptr GeometryLoader::create_geometry_from_file } } + return cached_node; +} + +//////////////////////////////////////////////////////////////////////////////// + +std::shared_ptr GeometryLoader::create_geometry_from_file + (std::string const& node_name, + std::string const& file_name, + std::string const& fallback_material, + unsigned flags) { + + auto cached_node(load_geometry(file_name, flags)); + if (cached_node) { auto copy(cached_node->deep_copy()); + + apply_fallback_material(copy, fallback_material); + copy->set_name(node_name); return copy; } - return std::make_shared(node_name); + return std::make_shared(node_name); } +//////////////////////////////////////////////////////////////////////////////// + +std::shared_ptr GeometryLoader::create_volume_from_file(std::string const& node_name, + std::string const& file_name, + unsigned flags) +{ + std::shared_ptr cached_node; + std::string key(file_name + "_" + string_utils::to_string(flags)); + + auto searched(loaded_files_.find(key)); + if (searched != loaded_files_.end()) { + cached_node = searched->second; + } else { + + bool fileload_succeed = false; + for (auto f : fileloaders_) { + if (f->is_supported(file_name)) { + cached_node = f->load(file_name, flags); + cached_node->update_cache(); + loaded_files_.insert(std::make_pair(key, cached_node)); + + // normalize volume position and rotation + if ( flags & VolumeLoader::NORMALIZE_POSITION + || flags & VolumeLoader::NORMALIZE_SCALE) { + auto bbox = cached_node->get_bounding_box(); + + if (flags & VolumeLoader::NORMALIZE_POSITION) { + auto center((bbox.min + bbox.max)*0.5); + cached_node->translate(-center); + } + + if (flags & VolumeLoader::NORMALIZE_SCALE) { + auto size(bbox.max - bbox.min); + auto max_size(std::max(std::max(size.x, size.y), + size.z)); + cached_node->scale(1.f / max_size); + } + + } + } + fileload_succeed = true; + break; + } + + if (!cached_node) { + WARNING("Unable to load %s: Volume Type is not supported!", + file_name.c_str()); + } + } + + if (cached_node) { + auto copy(cached_node->deep_copy()); + + copy->set_name(node_name); + return copy; + } + + return std::make_shared(node_name); +} + +//////////////////////////////////////////////////////////////////////////////// + +void GeometryLoader::apply_fallback_material(std::shared_ptr const& root, + std::string const& fallback_material) const { + + auto g_node(std::dynamic_pointer_cast(root)); + + if (g_node) { + if (g_node->get_material().empty()) { + g_node->set_material(fallback_material); + } + } + + for(auto& child: root->get_children()) { + apply_fallback_material(child, fallback_material); + } + +} //////////////////////////////////////////////////////////////////////////////// diff --git a/src/gua/renderer/GeometryPass.cpp b/src/gua/renderer/GeometryPass.cpp index c17866da7..ee61384c4 100644 --- a/src/gua/renderer/GeometryPass.cpp +++ b/src/gua/renderer/GeometryPass.cpp @@ -42,6 +42,7 @@ void GeometryPass::render_scene(Camera const& camera, RenderContext const& ctx) gbuffer_->clear(ctx); for (int i(0); i < gbuffer_->get_eye_buffers().size(); ++i) { + FrameBufferObject* fbo(gbuffer_->get_eye_buffers()[i]); CameraMode eye(CameraMode::CENTER); @@ -53,7 +54,7 @@ void GeometryPass::render_scene(Camera const& camera, RenderContext const& ctx) fbo->bind(ctx); ctx.render_context->set_viewport(scm::gl::viewport( - math::vec2(0, 0), math::vec2(fbo->width(), fbo->height()))); + math::vec2(0, 0), ::scm::math::vec2f(fbo->width(), fbo->height()))); rendering(pipeline_->get_current_scene(eye), ctx, eye, camera, fbo); diff --git a/src/gua/renderer/LayerMapping.cpp b/src/gua/renderer/LayerMapping.cpp index 3bbabb587..1a2686964 100644 --- a/src/gua/renderer/LayerMapping.cpp +++ b/src/gua/renderer/LayerMapping.cpp @@ -434,8 +434,8 @@ std::vector< } scm::gl::sampler_state_desc state(scm::gl::FILTER_ANISOTROPIC, - scm::gl::WRAP_CLAMP_TO_EDGE, - scm::gl::WRAP_CLAMP_TO_EDGE); + scm::gl::WRAP_MIRRORED_REPEAT, + scm::gl::WRAP_MIRRORED_REPEAT); result.push_back(std::make_pair(get_largest(output_sums), state)); } diff --git a/src/gua/renderer/LightingPass.cpp b/src/gua/renderer/LightingPass.cpp index bd8507032..6155c3151 100644 --- a/src/gua/renderer/LightingPass.cpp +++ b/src/gua/renderer/LightingPass.cpp @@ -40,11 +40,7 @@ LightingPass::LightingPass(Pipeline* pipeline) shader_(new LightingUberShader), light_sphere_(nullptr), light_cone_(nullptr), - serializer_(new Serializer), - shadow_map_mesh_shader_(new ShadowMapMeshShader), - shadow_map_nurbs_shader_(new ShadowMapNURBSShader), - shadow_map_(nullptr), - shadow_map_projection_view_matrix_(math::mat4::identity()) { + shadow_map_(pipeline) { light_sphere_ = GeometryDatabase::instance()->lookup("gua_light_sphere_proxy"); light_cone_ = GeometryDatabase::instance()->lookup("gua_light_cone_proxy"); } @@ -53,12 +49,6 @@ LightingPass::LightingPass(Pipeline* pipeline) //////////////////////////////////////////////////////////////////////////////// LightingPass::~LightingPass() { - if (shadow_map_mesh_shader_) - delete shadow_map_mesh_shader_; - if (shadow_map_nurbs_shader_) - delete shadow_map_nurbs_shader_; - if (serializer_) - delete serializer_; if (shader_) delete shader_; } @@ -70,6 +60,7 @@ void LightingPass::apply_material_mapping( std::set const& material_names, std::vector const& inputs) const { shader_->create(material_names, inputs); + shadow_map_.apply_material_mapping(material_names); } //////////////////////////////////////////////////////////////////////////////// @@ -83,17 +74,19 @@ LayerMapping const* LightingPass::get_gbuffer_mapping() const { /* virtual */ void LightingPass::print_shaders(std::string const& directory, std::string const& name) const { shader_->save_to_file(directory, name + "/lighting"); - shadow_map_mesh_shader_->save_to_file(directory, name + "/shadow/mesh"); - shadow_map_nurbs_shader_->save_to_file(directory, name + "/shadow/nurbs"); + shadow_map_.print_shaders(directory, name); } //////////////////////////////////////////////////////////////////////////////// bool LightingPass::pre_compile_shaders(RenderContext const& ctx) { - if (shader_) return shader_->upload_to(ctx); - if (shadow_map_mesh_shader_) return shadow_map_mesh_shader_->upload_to(ctx); - // if (shadow_map_nurbs_shader_) shadow_map_nurbs_shader_->upload_to(ctx); - return false; + + bool success(false); + + if (shader_) success = shader_->upload_to(ctx); + if (success) success = shadow_map_.pre_compile_shaders(ctx); + + return success; } //////////////////////////////////////////////////////////////////////////////// @@ -107,10 +100,14 @@ void LightingPass::rendering(SerializedScene const& scene, depth_stencil_state_ = ctx.render_device->create_depth_stencil_state(false, false); - if (!rasterizer_state_) - rasterizer_state_ = ctx.render_device + if (!rasterizer_state_front_) + rasterizer_state_front_ = ctx.render_device ->create_rasterizer_state(scm::gl::FILL_SOLID, scm::gl::CULL_FRONT); + if (!rasterizer_state_back_) + rasterizer_state_back_ = ctx.render_device + ->create_rasterizer_state(scm::gl::FILL_SOLID, scm::gl::CULL_BACK); + if (!blend_state_) blend_state_ = ctx.render_device->create_blend_state(true, scm::gl::FUNC_ONE, @@ -118,196 +115,181 @@ void LightingPass::rendering(SerializedScene const& scene, scm::gl::FUNC_ONE, scm::gl::FUNC_ONE); + if (!fullscreen_quad_) + fullscreen_quad_ = scm::gl::quad_geometry_ptr(new scm::gl::quad_geometry( + ctx.render_device, math::vec2(-1.f, -1.f), math::vec2(1.f, 1.f))); + ctx.render_context->set_depth_stencil_state(depth_stencil_state_); - ctx.render_context->set_rasterizer_state(rasterizer_state_); + ctx.render_context->set_rasterizer_state(rasterizer_state_back_); ctx.render_context->set_blend_state(blend_state_); shader_->set_material_uniforms( scene.materials_, ShadingModel::LIGHTING_STAGE, ctx); - shader_->set_subroutine(ctx, - scm::gl::STAGE_VERTEX_SHADER, - "compute_light", - "gua_calculate_point_light"); - - shader_->set_subroutine(ctx, - scm::gl::STAGE_FRAGMENT_SHADER, - "compute_light", - "gua_calculate_point_light"); - shader_->use(ctx); Pass::bind_inputs(*shader_, eye, ctx); Pass::set_camera_matrices( *shader_, camera, pipeline_->get_current_scene(eye), eye, ctx); - for (auto const& light : scene.point_lights_) { - shader_->set_uniform( - ctx, light.data.get_enable_diffuse_shading(), "gua_light_diffuse_enable"); - shader_->set_uniform(ctx, - light.data.get_enable_specular_shading(), - "gua_light_specular_enable"); - shader_->set_uniform(ctx, light.transform, "gua_model_matrix"); - shader_->set_uniform(ctx, light.data.get_color().vec3(), "gua_light_color"); - shader_->set_uniform(ctx, light.data.get_falloff(), "gua_light_falloff"); - shader_->set_uniform(ctx, false, "gua_light_casts_shadow"); - light_sphere_->draw(ctx); - } + // -------------------------- sun lights ----------------------------------- shader_->set_subroutine(ctx, scm::gl::STAGE_VERTEX_SHADER, "compute_light", - "gua_calculate_spot_light"); + "gua_calculate_sun_light"); shader_->set_subroutine(ctx, scm::gl::STAGE_FRAGMENT_SHADER, "compute_light", - "gua_calculate_spot_light"); + "gua_calculate_sun_light"); - for (auto const& light : scene.spot_lights_) { - if (light.data.get_enable_shadows()) { + + for (auto const& light : scene.sun_lights_) { + + if (light->data.get_enable_shadows()) { shader_->unuse(ctx); target->unbind(ctx); ctx.render_context->reset_state_objects(); - render_shadow_map(ctx, camera, light.transform, light.data.get_shadow_map_size()); + float split_0(0.f), split_1(0.f), split_2(0.f), split_3(0.f), split_4(0.f); + + if (light->data.get_shadow_cascaded_splits().size() == 5) { + + split_0 = light->data.get_shadow_cascaded_splits()[0]; + split_1 = light->data.get_shadow_cascaded_splits()[1]; + split_2 = light->data.get_shadow_cascaded_splits()[2]; + split_3 = light->data.get_shadow_cascaded_splits()[3]; + split_4 = light->data.get_shadow_cascaded_splits()[4]; + + } else { + WARNING("Exactly 5 splits have to be defined for cascaded shadow maps!"); + } + + shadow_map_.render_cascaded(ctx, scene.center_of_interest, scene.frustum, camera, + light->get_world_transform(), + light->data.get_shadow_map_size(), + split_0, split_1, split_2, split_3, split_4, + light->data.get_shadow_near_clipping_in_sun_direction()); shader_->use(ctx); target->bind(ctx); ctx.render_context->set_viewport(scm::gl::viewport( math::vec2(0, 0), - math::vec2(target->width(), target->height()))); + math::vec2(float(target->width()), float(target->height())))); ctx.render_context->set_depth_stencil_state(depth_stencil_state_); - ctx.render_context->set_rasterizer_state(rasterizer_state_); + ctx.render_context->set_rasterizer_state(rasterizer_state_back_); ctx.render_context->set_blend_state(blend_state_); - shader_->set_uniform( - ctx, shadow_map_->get_depth_buffer(), "gua_light_shadow_map"); + shader_->set_uniform(ctx, shadow_map_.get_buffer()->get_depth_buffer(), "gua_light_shadow_map"); - float shadow_map_portion(1.f * light.data.get_shadow_map_size() / shadow_map_->width()); - shader_->set_uniform( - ctx, shadow_map_portion, "gua_light_shadow_map_portion"); - - shader_->set_uniform(ctx, - shadow_map_projection_view_matrix_, - "gua_light_shadow_map_projection_view_matrix"); + float shadow_map_portion(1.f * light->data.get_shadow_map_size() / shadow_map_.get_buffer()->width()); + shader_->set_uniform(ctx, shadow_map_portion, "gua_light_shadow_map_portion"); + for (int i(0); i<4; ++i) { + shader_->set_uniform(ctx, shadow_map_.get_projection_view_matrices()[i], "gua_light_shadow_map_projection_view_matrix_" + string_utils::to_string(i)); + } } shader_->set_uniform( - ctx, light.data.get_enable_shadows(), "gua_light_casts_shadow"); - shader_->set_uniform( - ctx, light.data.get_enable_diffuse_shading(), "gua_light_diffuse_enable"); + ctx, light->data.get_enable_diffuse_shading(), "gua_light_diffuse_enable"); shader_->set_uniform(ctx, - light.data.get_enable_specular_shading(), + light->data.get_enable_specular_shading(), "gua_light_specular_enable"); - shader_->set_uniform(ctx, light.transform, "gua_model_matrix"); - shader_->set_uniform(ctx, light.data.get_color().vec3(), "gua_light_color"); - shader_->set_uniform(ctx, light.data.get_falloff(), "gua_light_falloff"); - shader_->set_uniform(ctx, light.data.get_softness(), "gua_light_softness"); + shader_->set_uniform(ctx, light->get_world_transform(), "gua_model_matrix"); + shader_->set_uniform(ctx, light->data.get_color().vec3(), "gua_light_color"); + shader_->set_uniform(ctx, light->data.get_enable_shadows(), "gua_light_casts_shadow"); shader_->set_uniform( - ctx, light.data.get_shadow_offset(), "gua_shadow_offset"); - light_cone_->draw(ctx); + ctx, light->data.get_shadow_offset(), "gua_shadow_offset"); + fullscreen_quad_->draw(ctx.render_context); } - shader_->unuse(ctx); + // ------------------------- point lights ---------------------------------- - ctx.render_context->reset_state_objects(); -} + ctx.render_context->set_rasterizer_state(rasterizer_state_front_); -//////////////////////////////////////////////////////////////////////////////// + shader_->set_subroutine(ctx, + scm::gl::STAGE_VERTEX_SHADER, + "compute_light", + "gua_calculate_point_light"); -void LightingPass::render_shadow_map(RenderContext const & ctx, - Camera const& scene_camera, - math::mat4 const & transform, - unsigned map_size) { + shader_->set_subroutine(ctx, + scm::gl::STAGE_FRAGMENT_SHADER, + "compute_light", + "gua_calculate_point_light"); - //check whether shadow map size is sufficient - if (shadow_map_ && shadow_map_->width() < map_size) { - shadow_map_->remove_buffers(ctx); - delete shadow_map_; - shadow_map_ = nullptr; - } - if (!shadow_map_) { - scm::gl::sampler_state_desc state; - state._compare_mode = scm::gl::TEXCOMPARE_COMPARE_REF_TO_TEXTURE; - -#if GUA_COMPILER == GUA_COMPILER_MSVC&& SCM_COMPILER_VER <= 1700 - std::vector > - gbuffer_desc; - gbuffer_desc.push_back(std::make_pair(BufferComponent::DEPTH_16, state)); - shadow_map_ = new GBuffer(gbuffer_desc, map_size, map_size); -#else - shadow_map_ = new GBuffer({ - { BufferComponent::DEPTH_16, state } - }, - map_size, - map_size); -#endif - shadow_map_->create(ctx); + for (auto const& light : scene.point_lights_) { + shader_->set_uniform( + ctx, light->data.get_enable_diffuse_shading(), "gua_light_diffuse_enable"); + shader_->set_uniform(ctx, + light->data.get_enable_specular_shading(), + "gua_light_specular_enable"); + shader_->set_uniform(ctx, light->get_world_transform(), "gua_model_matrix"); + shader_->set_uniform(ctx, light->data.get_color().vec3(), "gua_light_color"); + shader_->set_uniform(ctx, light->data.get_falloff(), "gua_light_falloff"); + shader_->set_uniform(ctx, false, "gua_light_casts_shadow"); + light_sphere_->draw(ctx); } - shadow_map_->bind(ctx); - - ctx.render_context->set_viewport(scm::gl::viewport( - math::vec2(0, 0), - math::vec2(map_size, map_size))); - shadow_map_->clear_depth_stencil_buffer(ctx); - - math::mat4 screen_transform(scm::math::make_translation(0.f, 0.f, -1.f)); - screen_transform = transform * screen_transform; - - Frustum shadow_frustum(transform, - screen_transform, - pipeline_->config.near_clip(), - pipeline_->config.far_clip()); + // -------------------------- spot lights ---------------------------------- + shader_->set_subroutine(ctx, + scm::gl::STAGE_VERTEX_SHADER, + "compute_light", + "gua_calculate_spot_light"); - SerializedScene scene; - serializer_->check(&scene, - pipeline_->get_current_graph(), - Camera("", "", scene_camera.render_mask), - shadow_frustum, - false, - false, - true); + shader_->set_subroutine(ctx, + scm::gl::STAGE_FRAGMENT_SHADER, + "compute_light", + "gua_calculate_spot_light"); - shadow_map_projection_view_matrix_ = - shadow_frustum.get_projection() * shadow_frustum.get_view(); + for (auto const& light : scene.spot_lights_) { + if (light->data.get_enable_shadows()) { + shader_->unuse(ctx); + target->unbind(ctx); + ctx.render_context->reset_state_objects(); - shadow_map_mesh_shader_->set_uniform( - ctx, shadow_map_projection_view_matrix_, "gua_projection_view_matrix"); - shadow_map_mesh_shader_->use(ctx); + shadow_map_.render(ctx, scene.center_of_interest, camera, light->get_world_transform(), light->data.get_shadow_map_size()); - // let derived class render all geometries - if (!shadow_map_depth_stencil_state_) - shadow_map_depth_stencil_state_ = - ctx.render_device->create_depth_stencil_state(true, true); + shader_->use(ctx); + target->bind(ctx); - if (!shadow_map_rasterizer_state_) - shadow_map_rasterizer_state_ = ctx.render_device - ->create_rasterizer_state(scm::gl::FILL_SOLID, scm::gl::CULL_NONE); + ctx.render_context->set_viewport(scm::gl::viewport( + math::vec2(0, 0), + math::vec2(float(target->width()), float(target->height())))); - ctx.render_context->set_depth_stencil_state(shadow_map_depth_stencil_state_); - ctx.render_context->set_rasterizer_state(shadow_map_rasterizer_state_); + ctx.render_context->set_depth_stencil_state(depth_stencil_state_); + ctx.render_context->set_rasterizer_state(rasterizer_state_front_); + ctx.render_context->set_blend_state(blend_state_); - for (auto const& node : scene.meshnodes_) { - auto geometry = GeometryDatabase::instance()->lookup(node.data.get_geometry()); + shader_->set_uniform(ctx, shadow_map_.get_buffer()->get_depth_buffer(), "gua_light_shadow_map"); - if (geometry) { - shadow_map_mesh_shader_->set_uniform( - ctx, node.transform, "gua_model_matrix"); - geometry->draw(ctx); + float shadow_map_portion(1.f * light->data.get_shadow_map_size() / shadow_map_.get_buffer()->width()); + shader_->set_uniform(ctx, shadow_map_portion, "gua_light_shadow_map_portion"); + shader_->set_uniform(ctx, shadow_map_.get_projection_view_matrices()[0], "gua_light_shadow_map_projection_view_matrix_0"); } - } - ctx.render_context->reset_state_objects(); + shader_->set_uniform( + ctx, light->data.get_enable_shadows(), "gua_light_casts_shadow"); + shader_->set_uniform( + ctx, light->data.get_enable_diffuse_shading(), "gua_light_diffuse_enable"); + shader_->set_uniform(ctx, + light->data.get_enable_specular_shading(), + "gua_light_specular_enable"); + shader_->set_uniform(ctx, light->get_world_transform(), "gua_model_matrix"); + shader_->set_uniform(ctx, light->data.get_color().vec3(), "gua_light_color"); + shader_->set_uniform(ctx, light->data.get_falloff(), "gua_light_falloff"); + shader_->set_uniform(ctx, light->data.get_softness(), "gua_light_softness"); + shader_->set_uniform( + ctx, light->data.get_shadow_offset(), "gua_shadow_offset"); + light_cone_->draw(ctx); + } - shadow_map_mesh_shader_->unuse(ctx); + shader_->unuse(ctx); - shadow_map_->unbind(ctx); + ctx.render_context->reset_state_objects(); } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/gua/renderer/Material.cpp b/src/gua/renderer/Material.cpp index 61d1657df..9470f33f4 100644 --- a/src/gua/renderer/Material.cpp +++ b/src/gua/renderer/Material.cpp @@ -79,7 +79,7 @@ std::unique_ptr create_from_string_and_type( string_utils::from_string(value)); break; - case UniformType::SAMPLER: + case UniformType::SAMPLER2D: return gua::make_unique >(value); break; @@ -114,10 +114,17 @@ void Material::reload() { void Material::load_description() { uniform_values_.clear(); - auto shading_model(ShadingModelDatabase::instance()->lookup( - description_.get_shading_model())); + std::string shading_model(description_.get_shading_model()); + std::shared_ptr mod; - for (auto& stage : shading_model->get_stages()) { + if (!ShadingModelDatabase::instance()->is_supported(shading_model)) { + mod = std::make_shared(shading_model, shading_model); + ShadingModelDatabase::instance()->add(shading_model, mod); + } else { + mod = ShadingModelDatabase::instance()->lookup(shading_model); + } + + for (auto& stage : mod->get_stages()) { for (auto const& uniform : stage.get_uniforms()) { std::string value(description_.get_uniforms()[uniform.first]); uniform_values_[uniform.first] = diff --git a/src/gua/renderer/MaterialDescription.cpp b/src/gua/renderer/MaterialDescription.cpp index 1df1467ea..03de5805f 100644 --- a/src/gua/renderer/MaterialDescription.cpp +++ b/src/gua/renderer/MaterialDescription.cpp @@ -70,6 +70,10 @@ void MaterialDescription::reload() { "File does not exist!", file_name_.c_str()); } + + PathParser p; + p.parse(file_name_); + shading_model_ = p.get_path(true) + shading_model_; } } diff --git a/src/gua/renderer/MaterialLoader.cpp b/src/gua/renderer/MaterialLoader.cpp index 6e915809a..28bc87eab 100644 --- a/src/gua/renderer/MaterialLoader.cpp +++ b/src/gua/renderer/MaterialLoader.cpp @@ -39,7 +39,7 @@ namespace gua { std::string const MaterialLoader::load_material( aiMaterial const* ai_material, - std::string const& name_prefix) const { + std::string const& file_name) const { auto get_color = [&](const char * pKey, unsigned int type, unsigned int idx)->std::string { @@ -71,12 +71,12 @@ std::string const MaterialLoader::load_material( aiString ai_material_name; ai_material->Get(AI_MATKEY_NAME, ai_material_name); - std::string material_name(name_prefix + "/" + ai_material_name.data); + std::string material_name("type='generated'&source='" + file_name + "'&name='" + ai_material_name.data + "'"); if (!MaterialDatabase::instance()->is_supported(material_name)) { PathParser path; - path.parse(name_prefix); + path.parse(file_name); std::string assets_directory(path.get_path(true)); unsigned capabilities = 0; @@ -250,7 +250,7 @@ std::string const MaterialLoader::load_shading_model( "); if (capabilities & (DIFFUSE_MAP | SPECULAR_MAP | EMIT_MAP | NORMAL_MAP | - SHININESS_MAP)) { + SHININESS_MAP | AMBIENT_MAP)) { model->get_gbuffer_vertex_stage().get_outputs()["varying_texcoords"] = BufferComponent::F2; @@ -262,15 +262,29 @@ std::string const MaterialLoader::load_shading_model( "); } + if (capabilities & DIFFUSE_MAP) { + + model->get_gbuffer_fragment_stage().get_uniforms()["diffuse_map"] = + UniformType::SAMPLER2D; + + gbuffer_fragment_body += std::string( + " \n\ + if (texture2D(diffuse_map, " + "varying_texcoords).a < 0.5) \n\ + discard; " + " \n\ + "); + } + if (capabilities & OPACITY_MAP) { model->get_gbuffer_fragment_stage().get_uniforms()["opacity_map"] = - UniformType::SAMPLER; + UniformType::SAMPLER2D; gbuffer_fragment_body += std::string( " \n\ if (texture2D(opacity_map, " - "varying_texcoords).r < 0.9) \n\ + "varying_texcoords).r < 0.5) \n\ discard; " " \n\ "); @@ -284,7 +298,7 @@ std::string const MaterialLoader::load_shading_model( BufferComponent::F3; model->get_gbuffer_fragment_stage().get_uniforms()["normal_map"] = - UniformType::SAMPLER; + UniformType::SAMPLER2D; gbuffer_vertex_body += std::string( " \n\ @@ -326,7 +340,7 @@ std::string const MaterialLoader::load_shading_model( std::string layer("gua_" + name); model->get_gbuffer_fragment_stage().get_uniforms()[texture] = - UniformType::SAMPLER; + UniformType::SAMPLER2D; model->get_gbuffer_fragment_stage().get_outputs()[layer] = layer_type; gbuffer_fragment_body += @@ -372,6 +386,12 @@ std::string const MaterialLoader::load_shading_model( "r", BufferComponent::F1, UniformType::FLOAT); + add_output(capabilities & AMBIENT_MAP, + capabilities & AMBIENT_COLOR, + "ambient", + "r", + BufferComponent::F1, + UniformType::VEC3); model->get_gbuffer_vertex_stage().set_body(gbuffer_vertex_body); model->get_gbuffer_fragment_stage().set_body(gbuffer_fragment_body); @@ -429,9 +449,13 @@ std::string const MaterialLoader::load_shading_model( else final_body += "vec3 my_emit_color = vec3(0.0);"; - final_body += " gua_color = my_diffuse_color * gua_light_diffuse + " - "(vec3(1.0) / (vec3(1.0) + gua_light_diffuse)) * " - "gua_ambient_color * my_diffuse_color;"; + if (capabilities & (AMBIENT_MAP | AMBIENT_COLOR)) + final_body += "float my_ambient_color = gua_ambient;"; + else + final_body += "float my_ambient_color = 0.5;"; + + final_body += "gua_color = my_diffuse_color * gua_light_diffuse;"; + final_body += "gua_color += gua_ambient_color * my_diffuse_color * my_ambient_color * (1.0 - min(1, max(max(gua_light_diffuse.r, gua_light_diffuse.g), gua_light_diffuse.b)));"; if (capabilities & (SPECULAR_COLOR | SPECULAR_MAP)) final_body += "gua_color += gua_light_specular;"; diff --git a/src/gua/renderer/MeshLoader.cpp b/src/gua/renderer/MeshLoader.cpp index 6d2b856b2..59380850d 100644 --- a/src/gua/renderer/MeshLoader.cpp +++ b/src/gua/renderer/MeshLoader.cpp @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include #include #include @@ -44,13 +44,12 @@ MeshLoader::MeshLoader() : node_counter_(0) {} std::shared_ptr MeshLoader::load(std::string const& file_name, - std::string const& fallback_material, unsigned flags) { node_counter_ = 0; TextFile file(file_name); - MESSAGE("Loading mesh file %s", file_name.c_str()); + // MESSAGE("Loading mesh file %s", file_name.c_str()); if (file.is_valid()) { auto importer = std::make_shared(); @@ -93,7 +92,8 @@ std::shared_ptr MeshLoader::load(std::string const& file_name, // new_node = std::make_shared(new GeometryNode("unnamed", // GeometryNode::Configuration("", ""), // math::mat4::identity())); - new_node = get_tree(importer, scene, scene->mRootNode, file_name, fallback_material, flags); + unsigned count(0); + new_node = get_tree(importer, scene, scene->mRootNode, file_name, flags, count); } else { WARNING("Failed to load object \"%s\": No valid root node contained!", @@ -133,6 +133,11 @@ std::vector const MeshLoader::load_from_buffer(char const* buffer_name, bool MeshLoader::is_supported(std::string const& file_name) const { auto point_pos(file_name.find_last_of(".")); Assimp::Importer importer; + + if (file_name.substr(point_pos + 1) == "raw"){ + return false; + } + return importer.IsExtensionSupported(file_name.substr(point_pos + 1)); } @@ -140,17 +145,16 @@ std::shared_ptr MeshLoader::get_tree(std::shared_ptr con aiScene const* ai_scene, aiNode* ai_root, std::string const& file_name, - std::string const& fallback_material, - unsigned flags) { + unsigned flags, unsigned& mesh_count) { // creates a geometry node and returns it auto load_geometry = [&](int i) { // load geometry - std::string mesh_name("mesh_" + string_utils::to_string(mesh_counter_++)); + std::string mesh_name("type=file&file=" + file_name + "&id=" + string_utils::to_string(mesh_count++) + "&flags=" + string_utils::to_string(flags)); GeometryDatabase::instance()->add(mesh_name, std::make_shared(ai_scene->mMeshes[ai_root->mMeshes[i]], importer, flags & GeometryLoader::MAKE_PICKABLE)); // load material - std::string material_name(fallback_material); + std::string material_name(""); unsigned material_index(ai_scene->mMeshes[ai_root->mMeshes[i]]->mMaterialIndex); if (material_index != 0 && flags & GeometryLoader::LOAD_MATERIALS) { @@ -160,8 +164,8 @@ std::shared_ptr MeshLoader::get_tree(std::shared_ptr con } auto result(std::make_shared(mesh_name)); - result->data.set_geometry(mesh_name); - result->data.set_material(material_name); + result->set_geometry(mesh_name); + result->set_material(material_name); return result; }; @@ -170,7 +174,7 @@ std::shared_ptr MeshLoader::get_tree(std::shared_ptr con if (ai_root->mNumChildren == 1 && ai_root->mNumMeshes == 0) { return get_tree( importer, ai_scene, ai_root->mChildren[0], - file_name, fallback_material, flags + file_name, flags, mesh_count ); } @@ -180,7 +184,7 @@ std::shared_ptr MeshLoader::get_tree(std::shared_ptr con } // else: there are multiple children and meshes - auto group(std::make_shared()); + auto group(std::make_shared()); for (unsigned i(0); i < ai_root->mNumMeshes; ++i) { group->add_child(load_geometry(i)); @@ -190,7 +194,7 @@ std::shared_ptr MeshLoader::get_tree(std::shared_ptr con group->add_child( get_tree( importer, ai_scene, ai_root->mChildren[i], - file_name, fallback_material, flags + file_name, flags, mesh_count ) ); } diff --git a/src/gua/renderer/NURBS.cpp b/src/gua/renderer/NURBS.cpp index 63b5e1fde..82d4dc1a4 100644 --- a/src/gua/renderer/NURBS.cpp +++ b/src/gua/renderer/NURBS.cpp @@ -118,7 +118,7 @@ void NURBS::upload_to(RenderContext const& context) const { scm::gl::FUNC_ONE, scm::gl::FUNC_ZERO); - //Initialize Texture Buffers + //Initialize Texture2D Buffers initialize_texture_buffers(context); //Initialize Vertex Data @@ -143,6 +143,8 @@ void NURBS::predraw(RenderContext const& context) const { scm::gl::context_image_units_guard cig(in_context); scm::gl::context_texture_units_guard ctg(in_context); + context.render_context->set_rasterizer_state(_rstate_ms_solid[context.id], 1.0f); + //Transform Feedback Stage Begins in_context->begin_transform_feedback(_transform_feedback[context.id], scm::gl::PRIMITIVE_POINTS); @@ -168,14 +170,13 @@ void NURBS::predraw(RenderContext const& context) const { in_context->bind_texture( _trim_pointdata_texture_buffer[context.id], _sstate[context.id], 11); - scm::gl::program_ptr p = in_context->current_program(); - p->uniform("parameter_texture", 5); - p->uniform("attribute_texture", 6); - p->uniform("trim_partition", 7); - p->uniform("trim_contourlist", 8); - p->uniform("trim_curvelist", 9); - p->uniform("trim_curvedata", 10); - p->uniform("trim_pointdata", 11); + in_context->current_program()->uniform_sampler("parameter_texture", 5); + in_context->current_program()->uniform_sampler("attribute_texture", 6); + in_context->current_program()->uniform_sampler("trim_partition", 7); + in_context->current_program()->uniform_sampler("trim_contourlist", 8); + in_context->current_program()->uniform_sampler("trim_curvelist", 9); + in_context->current_program()->uniform_sampler("trim_curvedata", 10); + in_context->current_program()->uniform_sampler("trim_pointdata", 11); in_context->apply(); @@ -221,6 +222,8 @@ void NURBS::draw(RenderContext const& context) const { scm::gl::context_image_units_guard cig1(in_context); scm::gl::context_texture_units_guard ctg1(in_context); + context.render_context->set_rasterizer_state(_rstate_ms_solid[context.id], 1.0f); + in_context->bind_vertex_array(_transform_feedback_vao[context.id]); in_context->bind_texture( @@ -238,14 +241,13 @@ void NURBS::draw(RenderContext const& context) const { in_context->bind_texture( _trim_pointdata_texture_buffer[context.id], _sstate[context.id], 11); - scm::gl::program_ptr p = in_context->current_program(); - p->uniform("parameter_texture", 5); - p->uniform("attribute_texture", 6); - p->uniform("trim_partition", 7); - p->uniform("trim_contourlist", 8); - p->uniform("trim_curvelist", 9); - p->uniform("trim_curvedata", 10); - p->uniform("trim_pointdata", 11); + in_context->current_program()->uniform_sampler("parameter_texture", 5); + in_context->current_program()->uniform_sampler("attribute_texture", 6); + in_context->current_program()->uniform_sampler("trim_partition", 7); + in_context->current_program()->uniform_sampler("trim_contourlist", 8); + in_context->current_program()->uniform_sampler("trim_curvelist", 9); + in_context->current_program()->uniform_sampler("trim_curvedata", 10); + in_context->current_program()->uniform_sampler("trim_pointdata", 11); in_context->apply(); diff --git a/src/gua/renderer/NURBSLoader.cpp b/src/gua/renderer/NURBSLoader.cpp index 500d1e766..efd565cf8 100644 --- a/src/gua/renderer/NURBSLoader.cpp +++ b/src/gua/renderer/NURBSLoader.cpp @@ -47,7 +47,6 @@ NURBSLoader::NURBSLoader() : LoaderBase(), _supported_file_extensions() { //////////////////////////////////////////////////////////////////////////////// /* virtual */ std::shared_ptr NURBSLoader::load(std::string const& file_name, - std::string const& fallback_material, unsigned flags) { try { igs_loader igsloader; @@ -65,8 +64,8 @@ std::shared_ptr NURBSLoader::load(std::string const& file_name, file_name, std::make_shared(bezier_object)); auto result = std::make_shared("unnamed_nurbs"); - result->data.geometry = file_name; - result->data.material = fallback_material; + result->set_geometry(file_name); + result->set_material(""); return result; diff --git a/src/gua/renderer/Pass.cpp b/src/gua/renderer/Pass.cpp index 1e7c66a33..315a3b1f8 100644 --- a/src/gua/renderer/Pass.cpp +++ b/src/gua/renderer/Pass.cpp @@ -38,7 +38,6 @@ Pass::Pass(Pipeline* pipeline) : gbuffer_(nullptr), pipeline_(pipeline) {} void Pass::create( RenderContext const& ctx, - PipelineConfiguration const& config, std::vector > const& layers) { @@ -46,7 +45,7 @@ void Pass::create( gbuffer_->remove_buffers(ctx); } - gbuffer_ = std::make_shared(ctx, config, layers); + gbuffer_ = std::make_shared(ctx, pipeline_->config, layers); } //////////////////////////////////////////////////////////////////////////////// @@ -107,26 +106,9 @@ void Pass::set_camera_matrices(ShaderProgram const& shader, CameraMode eye, RenderContext const& ctx) const { - auto view(scene.view_); - auto screen(scene.screen_); - - math::mat4 view_transform(view.transform); - if (eye == CameraMode::LEFT) { - scm::math::translate( - view_transform, -view.data.get_stereo_width() * 0.5f, 0.f, 0.f); - } else if (eye == CameraMode::RIGHT) { - scm::math::translate( - view_transform, view.data.get_stereo_width() * 0.5f, 0.f, 0.f); - } - - Frustum frustum(view_transform, - screen.transform, - pipeline_->config.near_clip(), - pipeline_->config.far_clip()); - - auto camera_position(frustum.get_camera_position()); - auto projection(frustum.get_projection()); - auto view_matrix(frustum.get_view()); + auto camera_position(scene.frustum.get_camera_position()); + auto projection(scene.frustum.get_projection()); + auto view_matrix(scene.frustum.get_view()); shader.set_uniform(ctx, camera_position, "gua_camera_position"); shader.set_uniform(ctx, projection, "gua_projection_matrix"); diff --git a/src/gua/renderer/Pipeline.cpp b/src/gua/renderer/Pipeline.cpp index af98dbeb5..dec7bfc71 100644 --- a/src/gua/renderer/Pipeline.cpp +++ b/src/gua/renderer/Pipeline.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -55,7 +56,8 @@ Pipeline::Pipeline() current_scenes_(2), passes_need_reload_(true), buffers_need_reload_(true), - last_shading_model_revision_(0) { + last_shading_model_revision_(0), + display_loading_screen_(true) { create_passes(); } @@ -76,10 +78,11 @@ void Pipeline::print_shaders(std::string const& directory) const { std::unique_lock lock(upload_mutex_); - passes_[0]->print_shaders(directory, "/0_gbuffer"); - passes_[1]->print_shaders(directory, "/1_lighting"); - passes_[2]->print_shaders(directory, "/2_final"); - passes_[3]->print_shaders(directory, "/3_postFX"); + passes_[PipelineStage::geometry]->print_shaders(directory, "/0_gbuffer"); + passes_[PipelineStage::lighting]->print_shaders(directory, "/1_lighting"); + passes_[PipelineStage::shading]->print_shaders(directory, "/2_final"); + passes_[PipelineStage::compositing]->print_shaders(directory, "/3_composite"); + passes_[PipelineStage::postfx]->print_shaders(directory, "/4_postFX"); } //////////////////////////////////////////////////////////////////////////////// @@ -111,6 +114,10 @@ void Pipeline::process(std::vector> const& sce float application_fps, float rendering_fps) { + if (!config.get_enabled()) { + return; + } + std::unique_lock lock(upload_mutex_); if (ShadingModel::current_revision != last_shading_model_revision_) { @@ -121,6 +128,7 @@ void Pipeline::process(std::vector> const& sce if (window_) { if (!window_->get_is_open()) { window_->open(); + window_->create_shader(); } set_context(window_->get_context()); @@ -154,92 +162,190 @@ void Pipeline::process(std::vector> const& sce return; } - if (passes_need_reload_) { - create_passes(); - } + if (display_loading_screen_) { + display_loading_screen_ = false; - if (buffers_need_reload_) { - create_buffers(); - } + if (window_) { + auto loading_texture(std::dynamic_pointer_cast(TextureDatabase::instance()->lookup("gua_loading_texture"))); + math::vec2ui loading_texture_size(loading_texture->width(), loading_texture->height()); - auto view_it((*current_graph_)[config.camera().view]); + if (config.get_enable_stereo()) { - if (!view_it) { - WARNING("Cannot render scene: No valid view specified"); - return; - } + auto tmp_left_resolution(window_->config.left_resolution()); + auto tmp_right_resolution(window_->config.right_resolution()); - auto screen_it((*current_graph_)[config.camera().screen]); + auto tmp_left_position(window_->config.left_position()); + auto tmp_right_position(window_->config.right_position()); + + window_->config.set_left_resolution(loading_texture_size); + window_->config.set_left_position(tmp_left_position + 0.5*(tmp_left_resolution - loading_texture_size)); + + window_->config.set_right_resolution(loading_texture_size); + window_->config.set_right_position(tmp_right_position + 0.5*(tmp_right_resolution - loading_texture_size)); + + window_->display(loading_texture, loading_texture); + + window_->config.set_left_position(tmp_left_position); + window_->config.set_left_resolution(tmp_left_resolution); + + window_->config.set_right_position(tmp_right_position); + window_->config.set_right_resolution(tmp_right_resolution); + + } else { + + auto tmp_left_resolution(window_->config.left_resolution()); + auto tmp_left_position(window_->config.left_position()); - if (!screen_it) { - WARNING("Cannot render scene: No valid screen specified"); - return; - } - auto view(std::dynamic_pointer_cast(view_it)); - auto screen(std::dynamic_pointer_cast(screen_it)); - - if (!config.get_enable_stereo()) { - - serializer_->check(¤t_scenes_[0], - current_graph_, - config.camera(), - Frustum(view->get_world_transform(), - screen->get_scaled_world_transform(), - config.near_clip(), - config.far_clip()), - config.enable_bbox_display(), - config.enable_ray_display(), - config.enable_frustum_culling()); + window_->config.set_left_resolution(loading_texture_size); + window_->config.set_left_position(tmp_left_position + 0.5*(tmp_left_resolution - loading_texture_size)); + + window_->display(loading_texture); + + window_->config.set_left_position(tmp_left_position); + window_->config.set_left_resolution(tmp_left_resolution); + + } + + window_->finish_frame(); + } + } else { - math::mat4 camera_transform(view->get_world_transform()); - scm::math::translate( - camera_transform, -view->data.get_stereo_width() * 0.5f, 0.f, 0.f); - - serializer_->check(¤t_scenes_[0], - current_graph_, - config.camera(), - Frustum(camera_transform, - screen->get_scaled_world_transform(), - config.near_clip(), - config.far_clip()), - config.enable_bbox_display(), - config.enable_ray_display(), - config.enable_frustum_culling()); - - camera_transform = view->get_world_transform(); - scm::math::translate( - camera_transform, view->data.get_stereo_width() * 0.5f, 0.f, 0.f); - - serializer_->check(¤t_scenes_[1], - current_graph_, - config.camera(), - Frustum(camera_transform, - screen->get_scaled_world_transform(), - config.near_clip(), - config.far_clip()), - config.enable_bbox_display(), - config.enable_ray_display(), - config.enable_frustum_culling()); - } + if (passes_need_reload_) { + create_passes(); + } - for (int i(0); i < passes_.size(); ++i) { - passes_[i]->render_scene(config.camera(), *context_); - } + if (buffers_need_reload_) { + create_buffers(); + } - if (window_) { - if (config.get_enable_stereo()) { - window_->display(passes_[3]->get_gbuffer()->get_eye_buffers()[0] - ->get_color_buffers(TYPE_FLOAT)[0], - passes_[3]->get_gbuffer()->get_eye_buffers()[1] - ->get_color_buffers(TYPE_FLOAT)[0]); + + if (!config.get_enable_stereo()) { + + auto eye((*current_graph_)[config.camera().eye_l]); + if (!eye) { + WARNING("Cannot render scene: No valid eye specified"); + return; + } + + auto screen_it((*current_graph_)[config.camera().screen_l]); + auto screen(std::dynamic_pointer_cast(screen_it)); + if (!screen) { + WARNING("Cannot render scene: No valid screen specified"); + return; + } + + if (config.camera().mode == Camera::ProjectionMode::PERSPECTIVE) { + current_scenes_[0].frustum = Frustum::perspective(eye->get_world_transform(), + screen->get_scaled_world_transform(), + config.near_clip(), + config.far_clip()); + } else { + current_scenes_[0].frustum = Frustum::orthographic(eye->get_world_transform(), + screen->get_scaled_world_transform(), + config.near_clip(), + config.far_clip()); + } + + current_scenes_[0].center_of_interest = eye->get_world_position(); + current_scenes_[0].enable_global_clipping_plane = config.get_enable_global_clipping_plane(); + current_scenes_[0].global_clipping_plane = config.get_global_clipping_plane(); + + serializer_->check(¤t_scenes_[0], + current_graph_, + config.camera().render_mask, + config.enable_bbox_display(), + config.enable_ray_display(), + config.enable_frustum_culling()); } else { - window_->display(passes_[3]->get_gbuffer()->get_eye_buffers()[0] - ->get_color_buffers(TYPE_FLOAT)[0]); + + + auto eye_l((*current_graph_)[config.camera().eye_l]); + if (!eye_l) { + WARNING("Cannot render scene: No valid left eye specified"); + return; + } + + auto eye_r((*current_graph_)[config.camera().eye_r]); + if (!eye_r) { + WARNING("Cannot render scene: No valid right eye specified"); + return; + } + + auto screen_it_l((*current_graph_)[config.camera().screen_l]); + auto screen_l(std::dynamic_pointer_cast(screen_it_l)); + if (!screen_l) { + WARNING("Cannot render scene: No valid left screen specified"); + return; + } + + auto screen_it_r((*current_graph_)[config.camera().screen_r]); + auto screen_r(std::dynamic_pointer_cast(screen_it_r)); + if (!screen_r) { + WARNING("Cannot render scene: No valid right screen specified"); + return; + } + + if (config.camera().mode == Camera::ProjectionMode::PERSPECTIVE) { + current_scenes_[0].frustum = Frustum::perspective(eye_l->get_world_transform(), + screen_l->get_scaled_world_transform(), + config.near_clip(), + config.far_clip()); + current_scenes_[1].frustum = Frustum::perspective(eye_r->get_world_transform(), + screen_r->get_scaled_world_transform(), + config.near_clip(), + config.far_clip()); + } else { + current_scenes_[0].frustum = Frustum::orthographic(eye_l->get_world_transform(), + screen_l->get_scaled_world_transform(), + config.near_clip(), + config.far_clip()); + current_scenes_[1].frustum = Frustum::orthographic(eye_r->get_world_transform(), + screen_r->get_scaled_world_transform(), + config.near_clip(), + config.far_clip()); + } + + current_scenes_[0].center_of_interest = eye_l->get_world_position(); + current_scenes_[0].enable_global_clipping_plane = config.get_enable_global_clipping_plane(); + current_scenes_[0].global_clipping_plane = config.get_global_clipping_plane(); + current_scenes_[1].center_of_interest = eye_r->get_world_position(); + current_scenes_[1].enable_global_clipping_plane = config.get_enable_global_clipping_plane(); + current_scenes_[1].global_clipping_plane = config.get_global_clipping_plane(); + + serializer_->check(¤t_scenes_[0], + current_graph_, + config.camera().render_mask, + config.enable_bbox_display(), + config.enable_ray_display(), + config.enable_frustum_culling()); + + serializer_->check(¤t_scenes_[1], + current_graph_, + config.camera().render_mask, + config.enable_bbox_display(), + config.enable_ray_display(), + config.enable_frustum_culling()); } - window_->finish_frame(); + for (auto pass : passes_) { + pass->render_scene(config.camera(), *context_); + } + + if (window_) { + if (config.get_enable_stereo()) { + window_->display(passes_[PipelineStage::postfx]->get_gbuffer()->get_eye_buffers()[0] + ->get_color_buffers(TYPE_FLOAT)[0], + passes_[PipelineStage::postfx]->get_gbuffer()->get_eye_buffers()[1] + ->get_color_buffers(TYPE_FLOAT)[0]); + } else { + window_->display(passes_[PipelineStage::postfx]->get_gbuffer()->get_eye_buffers()[0] + ->get_color_buffers(TYPE_FLOAT)[0]); + } + + window_->finish_frame(); + } } } @@ -259,7 +365,6 @@ void Pipeline::create_passes() { if (passes_need_reload_) { - auto materials(MaterialDatabase::instance()->list_all()); auto pre_pass = new GBufferPass(this); @@ -276,30 +381,35 @@ void Pipeline::create_passes() { auto final_pass = new FinalPass(this); final_pass->apply_material_mapping(materials, layer_mapping); + auto composite_pass = new CompositePass(this); + auto post_fx_pass = new PostFXPass(this); - bool compilation_succeeded = false; + bool compilation_succeeded = true; passes_need_reload_ = false; + std::vector new_passes; + new_passes.push_back(pre_pass); + new_passes.push_back(light_pass); + new_passes.push_back(final_pass); + new_passes.push_back(composite_pass); + new_passes.push_back(post_fx_pass); + // try compilation if context is already present if (context_) { - - if (pre_pass->pre_compile_shaders(*context_)) - if (light_pass->pre_compile_shaders(*context_)) - if (final_pass->pre_compile_shaders(*context_)) - if (post_fx_pass->pre_compile_shaders(*context_)) - - compilation_succeeded = true; - - } else { - compilation_succeeded = true; + for (auto pass : new_passes) { + if (!pass->pre_compile_shaders(*context_)) { + compilation_succeeded = false; + break; + } + } } if (compilation_succeeded) { - for (int i(0); i < passes_.size(); ++i) { - delete passes_[i]; + for (auto pass : passes_) { + delete pass; } passes_.clear(); @@ -307,16 +417,18 @@ void Pipeline::create_passes() { passes_.push_back(pre_pass); passes_.push_back(light_pass); passes_.push_back(final_pass); + passes_.push_back(composite_pass); passes_.push_back(post_fx_pass); buffers_need_reload_ = true; } else { - delete pre_pass; - delete light_pass; - delete final_pass; - delete post_fx_pass; + WARNING("Failed to recompile shaders!"); + + for (auto pass : new_passes) { + delete pass; + } } } } @@ -326,48 +438,39 @@ void Pipeline::create_passes() { void Pipeline::create_buffers() { if (buffers_need_reload_) { - passes_[0]->create(*context_, config, - passes_[0]->get_gbuffer_mapping()->get_layers()); - - passes_[1]->create(*context_, config, - passes_[1]->get_gbuffer_mapping()->get_layers()); std::vector> stereobuffers; - stereobuffers.push_back(passes_[0]->get_gbuffer()); - passes_[1]->set_inputs(stereobuffers); + passes_[PipelineStage::geometry]->create(*context_, passes_[PipelineStage::geometry]->get_gbuffer_mapping()->get_layers()); + stereobuffers.push_back(passes_[PipelineStage::geometry]->get_gbuffer()); - stereobuffers.push_back(passes_[1]->get_gbuffer()); + passes_[PipelineStage::lighting]->create(*context_, passes_[PipelineStage::lighting]->get_gbuffer_mapping()->get_layers()); + passes_[PipelineStage::lighting]->set_inputs(stereobuffers); + stereobuffers.push_back(passes_[PipelineStage::lighting]->get_gbuffer()); - passes_[2]->create(*context_, - config, - passes_[2]->get_gbuffer_mapping()->get_layers()); + passes_[PipelineStage::shading]->create(*context_, passes_[PipelineStage::shading]->get_gbuffer_mapping()->get_layers()); + passes_[PipelineStage::shading]->set_inputs(stereobuffers); + stereobuffers.push_back(passes_[PipelineStage::shading]->get_gbuffer()); - passes_[2]->set_inputs(stereobuffers); + passes_[PipelineStage::compositing]->set_inputs(stereobuffers); + passes_[PipelineStage::compositing]->create(*context_, {} ); + stereobuffers.push_back(passes_[PipelineStage::compositing]->get_gbuffer()); scm::gl::sampler_state_desc state(scm::gl::FILTER_MIN_MAG_LINEAR, - scm::gl::WRAP_REPEAT, - scm::gl::WRAP_REPEAT); - - #if GUA_COMPILER == GUA_COMPILER_MSVC&& SCM_COMPILER_VER <= 1700 - std::vector > - layer_desc; - layer_desc.push_back(std::make_pair(BufferComponent::F3, state)); - passes_[3]->create(*context_, config, layer_desc); - #else - passes_[3]->create(*context_, config, - { - { BufferComponent::F3, state } - }); - #endif - stereobuffers.push_back(passes_[2]->get_gbuffer()); - passes_[3]->set_inputs(stereobuffers); + scm::gl::WRAP_MIRRORED_REPEAT, + scm::gl::WRAP_MIRRORED_REPEAT); + + passes_[PipelineStage::postfx]->create(*context_, { { BufferComponent::F3, state } }); + passes_[PipelineStage::postfx]->set_inputs(stereobuffers); if (!config.get_enable_stereo()) { - TextureDatabase::instance()->add(config.output_texture_name(), passes_[3]->get_gbuffer()->get_eye_buffers()[0]->get_color_buffers(TYPE_FLOAT)[0]); + TextureDatabase::instance()->add(config.output_texture_name(), passes_[PipelineStage::postfx]->get_gbuffer()->get_eye_buffers()[0]->get_color_buffers(TYPE_FLOAT)[0]); + TextureDatabase::instance()->add(config.output_texture_name() + "_depth", passes_[PipelineStage::geometry]->get_gbuffer()->get_eye_buffers()[0]->get_depth_buffer()); } else { - TextureDatabase::instance()->add(config.output_texture_name() + "_left", passes_[3]->get_gbuffer()->get_eye_buffers()[0]->get_color_buffers(TYPE_FLOAT)[0]); - TextureDatabase::instance()->add(config.output_texture_name() + "_right", passes_[3]->get_gbuffer()->get_eye_buffers()[1]->get_color_buffers(TYPE_FLOAT)[0]); + TextureDatabase::instance()->add(config.output_texture_name() + "_left", passes_[PipelineStage::postfx]->get_gbuffer()->get_eye_buffers()[0]->get_color_buffers(TYPE_FLOAT)[0]); + TextureDatabase::instance()->add(config.output_texture_name() + "_right", passes_[PipelineStage::postfx]->get_gbuffer()->get_eye_buffers()[1]->get_color_buffers(TYPE_FLOAT)[0]); + TextureDatabase::instance()->add(config.output_texture_name() + "_depth_left", passes_[PipelineStage::geometry]->get_gbuffer()->get_eye_buffers()[0]->get_depth_buffer()); + TextureDatabase::instance()->add(config.output_texture_name() + "_depth_right", passes_[PipelineStage::geometry]->get_gbuffer()->get_eye_buffers()[1]->get_depth_buffer()); } diff --git a/src/gua/renderer/PostFXPass.cpp b/src/gua/renderer/PostFXPass.cpp index 8fee034f3..211a3819c 100644 --- a/src/gua/renderer/PostFXPass.cpp +++ b/src/gua/renderer/PostFXPass.cpp @@ -31,6 +31,8 @@ #include #include +#include + #define LUMINANCE_MAP_SIZE 512 namespace gua { @@ -166,10 +168,9 @@ PostFXPass::~PostFXPass() { //////////////////////////////////////////////////////////////////////////////// -void PostFXPass::create(RenderContext const& ctx, - PipelineConfiguration const& config, std::vector> const& layers) { - Pass::create(ctx, config, layers); + Pass::create(ctx, layers); for (auto p: godray_buffers_) { p->remove_buffers(ctx); @@ -200,8 +201,8 @@ void PostFXPass::create(RenderContext const& ctx, delete luminance_buffer_; } - ping_buffer_ = new StereoBuffer(ctx, config, layers); - pong_buffer_ = new StereoBuffer(ctx, config, layers); + ping_buffer_ = new StereoBuffer(ctx, pipeline_->config, layers); + pong_buffer_ = new StereoBuffer(ctx, pipeline_->config, layers); scm::gl::sampler_state_desc state(scm::gl::FILTER_MIN_MAG_LINEAR, scm::gl::WRAP_CLAMP_TO_EDGE, @@ -211,25 +212,25 @@ void PostFXPass::create(RenderContext const& ctx, layer_3f_desc.push_back(std::make_pair(BufferComponent::F3, state)); godray_buffers_.push_back(new GBuffer(layer_3f_desc, - config.get_left_resolution()[0]/2, - config.get_left_resolution()[1]/2)); + pipeline_->config.get_left_resolution()[0]/2, + pipeline_->config.get_left_resolution()[1]/2)); godray_buffers_.push_back(new GBuffer(layer_3f_desc, - config.get_left_resolution()[0]/2, - config.get_left_resolution()[1]/2)); + pipeline_->config.get_left_resolution()[0]/2, + pipeline_->config.get_left_resolution()[1]/2)); godray_buffers_.push_back(new GBuffer(layer_3f_desc, - config.get_left_resolution()[0]/2, - config.get_left_resolution()[1]/2)); + pipeline_->config.get_left_resolution()[0]/2, + pipeline_->config.get_left_resolution()[1]/2)); for (auto buffer: godray_buffers_) { buffer->create(ctx); } glow_buffers_.push_back(new GBuffer(layer_3f_desc, - config.get_left_resolution()[0]/2, - config.get_left_resolution()[1]/2)); + pipeline_->config.get_left_resolution()[0]/2, + pipeline_->config.get_left_resolution()[1]/2)); glow_buffers_.push_back(new GBuffer(layer_3f_desc, - config.get_left_resolution()[0]/2, - config.get_left_resolution()[1]/2)); + pipeline_->config.get_left_resolution()[0]/2, + pipeline_->config.get_left_resolution()[1]/2)); for (auto buffer: glow_buffers_) { buffer->create(ctx); @@ -288,11 +289,11 @@ void PostFXPass::render_scene(Camera const& camera, RenderContext const& ctx) { any_godrays = render_godrays(camera, pipeline_->get_current_scene(eye), eye, ctx); render_glow(eye, ctx); - auto input_tex(inputs_[2]->get_eye_buffers()[eye == CameraMode::RIGHT ? 1 : 0]->get_color_buffers(TYPE_FLOAT)[0]); + auto input_tex(inputs_[Pipeline::compositing]->get_eye_buffers()[eye == CameraMode::RIGHT ? 1 : 0]->get_color_buffers(TYPE_FLOAT)[0]); auto ping_tex(ping_buffer_->get_eye_buffers()[eye == CameraMode::RIGHT ? 1 : 0]->get_color_buffers(TYPE_FLOAT)[0]); auto pong_tex(pong_buffer_->get_eye_buffers()[eye == CameraMode::RIGHT ? 1 : 0]->get_color_buffers(TYPE_FLOAT)[0]); - auto normal_tex(inputs_[0]->get_eye_buffers()[eye == CameraMode::RIGHT ? 1 : 0]->get_color_buffers(TYPE_FLOAT)[0]); - auto depth_tex(inputs_[0]->get_eye_buffers()[eye == CameraMode::RIGHT ? 1 : 0]->get_depth_buffer()); + auto normal_tex(inputs_[Pipeline::geometry]->get_eye_buffers()[eye == CameraMode::RIGHT ? 1 : 0]->get_color_buffers(TYPE_FLOAT)[0]); + auto depth_tex(inputs_[Pipeline::geometry]->get_eye_buffers()[eye == CameraMode::RIGHT ? 1 : 0]->get_depth_buffer()); Pass::set_camera_matrices(*postfx_shaders_[0], camera, pipeline_->get_current_scene(eye), eye, ctx); @@ -429,7 +430,7 @@ bool PostFXPass::render_godrays(Camera const& camera, bool any_godrays(false); for (auto const& light: scene.point_lights_) { - if (light.data.get_enable_godrays()) { + if (light->data.get_enable_godrays()) { any_godrays = true; break; } @@ -437,7 +438,16 @@ bool PostFXPass::render_godrays(Camera const& camera, if (!any_godrays) { for (auto const& light: scene.spot_lights_) { - if (light.data.get_enable_godrays()) { + if (light->data.get_enable_godrays()) { + any_godrays = true; + break; + } + } + } + + if (!any_godrays) { + for (auto const& light: scene.sun_lights_) { + if (light->data.get_enable_godrays()) { any_godrays = true; break; } @@ -449,7 +459,7 @@ bool PostFXPass::render_godrays(Camera const& camera, if (any_godrays) { Pass::set_camera_matrices(*god_ray_shader_, camera, scene, eye, ctx); - auto depth_buffer(inputs_[0]->get_eye_buffers()[eye == CameraMode::RIGHT ? 1 : 0]->get_depth_buffer()); + auto depth_buffer(inputs_[Pipeline::geometry]->get_eye_buffers()[eye == CameraMode::RIGHT ? 1 : 0]->get_depth_buffer()); god_ray_shader_->set_uniform(ctx, 1.0f * godray_buffers_[0]->width() / godray_buffers_[0]->height(), "gua_aspect_ratio"); ctx.render_context->set_viewport(scm::gl::viewport( math::vec2(0.0f,0.0f), math::vec2(float(godray_buffers_[0]->width()), float(godray_buffers_[0]->height())))); @@ -491,22 +501,42 @@ bool PostFXPass::render_godrays(Camera const& camera, ctx.render_context->reset_state_objects(); }; + god_ray_shader_->set_subroutine(ctx, + scm::gl::STAGE_VERTEX_SHADER, + "compute_position", + "gua_calculate_by_position"); + for (auto const& light: scene.point_lights_) { - if (light.data.get_enable_godrays()) { - god_ray_shader_->set_uniform(ctx, light.data.get_color().vec3(), "gua_light_color"); - god_ray_shader_->set_uniform(ctx, math::vec3(light.transform.column(3)[0], - light.transform.column(3)[1], - light.transform.column(3)[2]), "gua_light_position"); + if (light->data.get_enable_godrays()) { + god_ray_shader_->set_uniform(ctx, light->data.get_color().vec3(), "gua_light_color"); + god_ray_shader_->set_uniform(ctx, math::vec3(light->get_world_transform().column(3)[0], + light->get_world_transform().column(3)[1], + light->get_world_transform().column(3)[2]), "gua_light_position_direction"); render(); } } for (auto const& light: scene.spot_lights_) { - if (light.data.get_enable_godrays()) { - god_ray_shader_->set_uniform(ctx, light.data.get_color().vec3(), "gua_light_color"); - god_ray_shader_->set_uniform(ctx, math::vec3(light.transform.column(3)[0], - light.transform.column(3)[1], - light.transform.column(3)[2]), "gua_light_position"); + if (light->data.get_enable_godrays()) { + god_ray_shader_->set_uniform(ctx, light->data.get_color().vec3(), "gua_light_color"); + god_ray_shader_->set_uniform(ctx, math::vec3(light->get_world_transform().column(3)[0], + light->get_world_transform().column(3)[1], + light->get_world_transform().column(3)[2]), "gua_light_position_direction"); + render(); + } + } + + god_ray_shader_->set_subroutine(ctx, + scm::gl::STAGE_VERTEX_SHADER, + "compute_position", + "gua_calculate_by_direction"); + + for (auto const& light: scene.sun_lights_) { + if (light->data.get_enable_godrays()) { + god_ray_shader_->set_uniform(ctx, light->data.get_color().vec3(), "gua_light_color"); + math::vec3 direction(0, 0, 1); + direction = light->get_world_transform() * direction; + god_ray_shader_->set_uniform(ctx, direction, "gua_light_position_direction"); render(); } } @@ -533,7 +563,7 @@ void PostFXPass::render_glow(CameraMode eye, RenderContext const& ctx) { glow_shader_->set_uniform(ctx, pipeline_->config.bloom_threshold(), "gua_glow_threshold"); - auto color_buffer(inputs_[2]->get_eye_buffers()[eye == CameraMode::RIGHT ? 1 : 0]->get_color_buffers(TYPE_FLOAT)[0]); + auto color_buffer(inputs_[Pipeline::compositing]->get_eye_buffers()[eye == CameraMode::RIGHT ? 1 : 0]->get_color_buffers(TYPE_FLOAT)[0]); ctx.render_context->set_viewport(scm::gl::viewport( math::vec2(0,0), math::vec2(float(glow_buffers_[0]->width()), float(glow_buffers_[0]->height())))); @@ -611,7 +641,7 @@ void PostFXPass::render_ssao(RenderContext const& ctx) { //////////////////////////////////////////////////////////////////////////////// void PostFXPass:: -render_hdr(RenderContext const& ctx, std::shared_ptr const& texture) { +render_hdr(RenderContext const& ctx, std::shared_ptr const& texture) { ctx.render_context->set_viewport(scm::gl::viewport( math::vec2(0,0), math::vec2(float(luminance_buffer_->width()), @@ -673,7 +703,7 @@ void PostFXPass::render_previews(CameraMode eye, RenderContext const& ctx) { preview_text_renderer_ = new TextRenderer(ctx, 12, font); } - std::vector>> previews; + std::vector>> previews; for (unsigned input(0); input < inputs_.size(); ++input) { diff --git a/src/gua/renderer/Renderer.cpp b/src/gua/renderer/Renderer.cpp index aff23f56d..f5f1f787c 100644 --- a/src/gua/renderer/Renderer.cpp +++ b/src/gua/renderer/Renderer.cpp @@ -42,6 +42,14 @@ std::shared_ptr garbage_collected_copy( return sgs; } +Renderer::~Renderer() { +#if USE_RAW_POINTER_RENDER_CLIENTS + for (auto rc : render_clients_) { + if (rc) delete rc; + } +#endif +} + Renderer::Renderer(std::vector const& pipelines) : render_clients_(), application_fps_(20) { @@ -51,8 +59,11 @@ Renderer::Renderer(std::vector const& pipelines) std::shared_ptr const & sg, float render_fps) { pipeline->process(*sg, this->application_fps_.fps, render_fps); }; - +#if USE_RAW_POINTER_RENDER_CLIENTS + render_clients_.push_back(new renderclient_t(fun)); +#else render_clients_.push_back(gua::make_unique(fun)); +#endif } } diff --git a/src/gua/renderer/Serializer.cpp b/src/gua/renderer/Serializer.cpp index 8ecaa0ac3..0f911d35e 100644 --- a/src/gua/renderer/Serializer.cpp +++ b/src/gua/renderer/Serializer.cpp @@ -24,18 +24,19 @@ // guacamole headers #include -#include #include #include #include #include -#include +#include +#include #include -#include +#include #include #include +#include #include #include #include @@ -49,12 +50,9 @@ namespace gua { Serializer::Serializer() : data_(nullptr), - current_camera_("", "", ""), current_render_mask_(""), - current_frustum_(math::mat4::identity(), - math::mat4::identity(), - 0.f, - 0.f), + current_frustum_(), + current_center_of_interest_(), draw_bounding_boxes_(false), draw_rays_(false), enable_frustum_culling_(false) {} @@ -63,8 +61,7 @@ Serializer::Serializer() void Serializer::check(SerializedScene* output, SceneGraph const* scene_graph, - Camera const& camera, - Frustum const& frustum, + std::string const& render_mask, bool draw_bounding_boxes, bool draw_rays, bool enable_frustum_culling) { @@ -73,21 +70,26 @@ void Serializer::check(SerializedScene* output, std::size_t mesh_count = data_->meshnodes_.size(); std::size_t nurbs_count = data_->nurbsnodes_.size(); + std::size_t volume_count = data_->volumenodes_.size(); std::size_t point_light_count = data_->point_lights_.size(); std::size_t spot_light_count = data_->spot_lights_.size(); + std::size_t sun_light_count = data_->sun_lights_.size(); std::size_t ray_count = data_->rays_.size(); std::size_t textured_quad_count = data_->textured_quads_.size(); data_->meshnodes_.clear(); data_->nurbsnodes_.clear(); + data_->volumenodes_.clear(); data_->point_lights_.clear(); data_->spot_lights_.clear(); + data_->sun_lights_.clear(); data_->textured_quads_.clear(); data_->bounding_boxes_.clear(); data_->rays_.clear(); draw_bounding_boxes_ = draw_bounding_boxes; draw_rays_ = draw_rays; + if (draw_bounding_boxes_) { data_->materials_.insert("gua_bounding_box"); data_->bounding_boxes_ @@ -106,22 +108,24 @@ void Serializer::check(SerializedScene* output, // reserving the old size might save some time data_->meshnodes_.reserve(mesh_count); data_->nurbsnodes_.reserve(nurbs_count); + data_->volumenodes_.reserve(nurbs_count); data_->point_lights_.reserve(point_light_count); data_->spot_lights_.reserve(spot_light_count); + data_->sun_lights_.reserve(sun_light_count); data_->textured_quads_.reserve(textured_quad_count); enable_frustum_culling_ = enable_frustum_culling; - current_camera_ = camera; - current_render_mask_ = Mask(current_camera_.render_mask); - current_frustum_ = frustum; + current_render_mask_ = Mask(render_mask); + current_frustum_ = output->frustum; + current_center_of_interest_ = output->center_of_interest; scene_graph->accept(*this); } //////////////////////////////////////////////////////////////////////// -/* virtual */ void Serializer::visit(GroupNode* node) { +/* virtual */ void Serializer::visit(Node* node) { if (is_visible(node)) { visit_children(node); } @@ -129,13 +133,28 @@ void Serializer::check(SerializedScene* output, //////////////////////////////////////////////////////////////////////// -/* virtual */ void Serializer::visit(ViewNode* node) { +/* virtual */ void Serializer::visit(LODNode* node) { if (is_visible(node)) { - if (node->get_path() == current_camera_.view) { - data_->view_ = make_serialized_node(node->get_world_transform(), node->data); + + float distance_to_camera(scm::math::length(node->get_world_position() - current_center_of_interest_)); + + unsigned child_index(0); + + if (!node->data.get_lod_distances().empty()) { + + child_index = node->get_children().size(); + + for (unsigned i(0); i < node->data.get_lod_distances().size(); ++i) { + if (node->data.get_lod_distances()[i] > distance_to_camera) { + child_index = i; + break; + } + } } - visit_children(node); + if (child_index < node->get_children().size()) { + node->get_children()[child_index]->accept(*this); + } } } @@ -144,29 +163,43 @@ void Serializer::check(SerializedScene* output, /* virtual */ void Serializer::visit(GeometryNode* node) { if (is_visible(node)) { - if (!node->data.get_geometry().empty() && !node->data.get_material().empty()) { + if (!node->get_geometry().empty() && !node->get_material().empty()) { add_bbox(node); std::shared_ptr mesh_ptr = std::dynamic_pointer_cast( - gua::GeometryDatabase::instance()->lookup(node->data.get_geometry())); + gua::GeometryDatabase::instance()->lookup(node->get_geometry())); if (mesh_ptr) { - data_->meshnodes_.push_back(make_serialized_node(node->get_world_transform(), node->data)); + data_->meshnodes_.push_back(node); } else { std::shared_ptr nurbs_ptr = std::dynamic_pointer_cast( - gua::GeometryDatabase::instance()->lookup(node->data.get_geometry())); + gua::GeometryDatabase::instance()->lookup(node->get_geometry())); if (nurbs_ptr) { - data_->nurbsnodes_.push_back(make_serialized_node(node->get_world_transform(), node->data)); + data_->nurbsnodes_.push_back(node); } } } - data_->materials_.insert(node->data.get_material()); + data_->materials_.insert(node->get_material()); + + visit_children(node); + } +} + +//////////////////////////////////////////////////////////////////////// + +/* virtual */ void Serializer::visit(VolumeNode* node) { + + if ( is_visible(node) ) { + if ( !node->data.get_volume().empty() ) { + add_bbox(node); + data_->volumenodes_.push_back(node); + } visit_children(node); } @@ -180,7 +213,7 @@ void Serializer::check(SerializedScene* output, add_bbox(node); - data_->point_lights_.push_back(make_serialized_node(node->get_world_transform(), node->data)); + data_->point_lights_.push_back(node); visit_children(node); } @@ -194,8 +227,7 @@ void Serializer::check(SerializedScene* output, add_bbox(node); - data_->spot_lights_ - .push_back(make_serialized_node(node->get_world_transform(), node->data)); + data_->spot_lights_.push_back(node); visit_children(node); } @@ -203,11 +235,10 @@ void Serializer::check(SerializedScene* output, //////////////////////////////////////////////////////////////////////// -/* virtual */ void Serializer::visit(ScreenNode* node) { +/* virtual */ void Serializer::visit(SunLightNode* node) { + if (is_visible(node)) { - if (node->get_path() == current_camera_.screen) { - data_->screen_ = make_serialized_node(node->get_scaled_world_transform(), node->data); - } + data_->sun_lights_.push_back(node); visit_children(node); } @@ -220,10 +251,7 @@ void Serializer::check(SerializedScene* output, if (is_visible(node)) { if (draw_rays_) { - GeometryNode::Configuration config; - config.set_geometry("gua_ray_geometry"); - config.set_material("gua_bounding_box"); - data_->rays_.push_back(make_serialized_node(node->get_world_transform(), config)); + data_->rays_.push_back(node); } visit_children(node); @@ -238,8 +266,7 @@ void Serializer::check(SerializedScene* output, add_bbox(node); - data_->textured_quads_ - .push_back(make_serialized_node(node->get_scaled_world_transform(), node->data)); + data_->textured_quads_.push_back(node); visit_children(node); } diff --git a/src/gua/renderer/ShaderProgram.cpp b/src/gua/renderer/ShaderProgram.cpp index 4eae21024..c05e32403 100644 --- a/src/gua/renderer/ShaderProgram.cpp +++ b/src/gua/renderer/ShaderProgram.cpp @@ -92,17 +92,9 @@ void ShaderProgram::create_from_files(std::string const & v_file, programs_.clear(); interleaved_stream_capture_.clear(); -#if GUA_COMPILER == GUA_COMPILER_MSVC&& SCM_COMPILER_VER <= 1600 - stages_.clear(); - stages_.push_back( - ShaderProgramStage(scm::gl::STAGE_VERTEX_SHADER, v_file, false)); - stages_.push_back( - ShaderProgramStage(scm::gl::STAGE_FRAGMENT_SHADER, f_file, false)); -#else stages_ = { ShaderProgramStage(scm::gl::STAGE_VERTEX_SHADER, v_file, false), ShaderProgramStage( scm::gl::STAGE_FRAGMENT_SHADER, f_file, false) }; -#endif } //////////////////////////////////////////////////////////////////////////////// @@ -118,17 +110,9 @@ void ShaderProgram::create_from_sources(std::string const & v_source, programs_.clear(); interleaved_stream_capture_.clear(); -#if GUA_COMPILER == GUA_COMPILER_MSVC&& SCM_COMPILER_VER <= 1600 - stages_.clear(); - stages_.push_back( - ShaderProgramStage(scm::gl::STAGE_VERTEX_SHADER, v_source, true)); - stages_.push_back( - ShaderProgramStage(scm::gl::STAGE_FRAGMENT_SHADER, f_source, true)); -#else stages_ = { ShaderProgramStage(scm::gl::STAGE_VERTEX_SHADER, v_source, true), ShaderProgramStage( scm::gl::STAGE_FRAGMENT_SHADER, f_source, true) }; -#endif } //////////////////////////////////////////////////////////////////////// diff --git a/src/gua/renderer/ShadowMap.cpp b/src/gua/renderer/ShadowMap.cpp new file mode 100644 index 000000000..954ad6f43 --- /dev/null +++ b/src/gua/renderer/ShadowMap.cpp @@ -0,0 +1,319 @@ +/****************************************************************************** + * guacamole - delicious VR * + * * + * Copyright: (c) 2011-2013 Bauhaus-Universität Weimar * + * Contact: felix.lauer@uni-weimar.de / simon.schneegans@uni-weimar.de * + * * + * This program is free software: you can redistribute it and/or modify it * + * under the terms of the GNU General Public License as published by the Free * + * Software Foundation, either version 3 of the License, or (at your option) * + * any later version. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * + * for more details. * + * * + * You should have received a copy of the GNU General Public License along * + * with this program. If not, see . * + * * + ******************************************************************************/ + +// class header +#include + +// guacamole headers +#include +#include +#include +#include +#include +#include +#include + +namespace gua { + +//////////////////////////////////////////////////////////////////////////////// + +ShadowMap::ShadowMap(Pipeline* pipeline) + : serializer_(new Serializer), + pipeline_(pipeline), + mesh_shader_(new GBufferMeshUberShader), + // nurbs_shader_(new GBufferNURBSUberShader), + buffer_(nullptr), + projection_view_matrices_() { +} + + +//////////////////////////////////////////////////////////////////////////////// + +ShadowMap::~ShadowMap() { + if (mesh_shader_) + delete mesh_shader_; + // if (nurbs_shader_) + // delete nurbs_shader_; + if (serializer_) + delete serializer_; +} + +//////////////////////////////////////////////////////////////////////////////// + +void ShadowMap::print_shaders(std::string const& directory, + std::string const& name) const { + mesh_shader_->save_to_file(directory, name + "/shadow/mesh"); + // nurbs_shader_->save_to_file(directory, name + "/shadow/nurbs"); +} + +//////////////////////////////////////////////////////////////////////////////// + +bool ShadowMap::pre_compile_shaders(RenderContext const& ctx) { + + bool success(false); + + if (mesh_shader_) success = mesh_shader_->upload_to(ctx); + // if (success && nurbs_shader_) success = nurbs_shader_->upload_to(ctx); + + return success; +} + + +//////////////////////////////////////////////////////////////////////////////// + +void ShadowMap::update_members(RenderContext const & ctx, unsigned map_size) { + //check whether shadow map size is sufficient + if (buffer_ && buffer_->width() < map_size) { + buffer_->remove_buffers(ctx); + delete buffer_; + buffer_ = nullptr; + } + + if (!buffer_) { + scm::gl::sampler_state_desc state; + state._compare_mode = scm::gl::TEXCOMPARE_COMPARE_REF_TO_TEXTURE; + + buffer_ = new GBuffer({{ BufferComponent::DEPTH_16, state }}, map_size, map_size); + buffer_->create(ctx); + } + + // let derived class render all geometries + if (!depth_stencil_state_) + depth_stencil_state_ = + ctx.render_device->create_depth_stencil_state(true, true); + + if (!rasterizer_state_) + rasterizer_state_ = ctx.render_device + ->create_rasterizer_state(scm::gl::FILL_SOLID, scm::gl::CULL_NONE); +} + +//////////////////////////////////////////////////////////////////////////////// + +void ShadowMap::apply_material_mapping(std::set const & + materials) const { + mesh_shader_->create(materials); + // nurbs_shader_->create(materials); +} + + +//////////////////////////////////////////////////////////////////////////////// + +void ShadowMap::render_geometry(RenderContext const & ctx, + math::vec3 const& center_of_interest, + Frustum const& shadow_frustum, + Camera const& scene_camera, + unsigned cascade) { + SerializedScene scene; + scene.frustum = shadow_frustum; + scene.center_of_interest = center_of_interest; + scene.enable_global_clipping_plane = pipeline_->config.get_enable_global_clipping_plane(); + scene.global_clipping_plane = pipeline_->config.get_global_clipping_plane(); + serializer_->check(&scene, + pipeline_->get_current_graph(), + scene_camera.render_mask, + false, + false, + true); + + projection_view_matrices_[cascade] = + shadow_frustum.get_projection() * shadow_frustum.get_view(); + + mesh_shader_->set_material_uniforms( + scene.materials_, ShadingModel::GBUFFER_VERTEX_STAGE, ctx); + mesh_shader_->set_material_uniforms( + scene.materials_, ShadingModel::GBUFFER_FRAGMENT_STAGE, ctx); + + mesh_shader_->set_uniform(ctx, scene.enable_global_clipping_plane, "gua_enable_global_clipping_plane"); + mesh_shader_->set_uniform(ctx, scene.global_clipping_plane, "gua_global_clipping_plane"); + + auto camera_position(scene.frustum.get_camera_position()); + auto projection(scene.frustum.get_projection()); + auto view_matrix(scene.frustum.get_view()); + + mesh_shader_->set_uniform(ctx, camera_position, "gua_camera_position"); + mesh_shader_->set_uniform(ctx, projection, "gua_projection_matrix"); + mesh_shader_->set_uniform(ctx, view_matrix, "gua_view_matrix"); + mesh_shader_->set_uniform(ctx, scm::math::inverse(projection * view_matrix), "gua_inverse_projection_view_matrix"); + + for (auto const& node : scene.meshnodes_) { + auto geometry = GeometryDatabase::instance()->lookup(node->get_geometry()); + auto material = MaterialDatabase::instance()->lookup(node->get_material()); + if (geometry) { + mesh_shader_->set_uniform( + ctx, material->get_id(), "gua_material_id"); + mesh_shader_->set_uniform( + ctx, node->get_world_transform(), "gua_model_matrix"); + mesh_shader_->set_uniform( + ctx, + scm::math::transpose( + scm::math::inverse(node->get_world_transform())), + "gua_normal_matrix"); + geometry->draw(ctx); + } + } +} + +//////////////////////////////////////////////////////////////////////////////// + +void ShadowMap::render(RenderContext const& ctx, + math::vec3 const& center_of_interest, + Camera const& scene_camera, + math::mat4 const& transform, + unsigned map_size) { + + // init members + update_members(ctx, map_size); + projection_view_matrices_ = std::vector(1); + + buffer_->bind(ctx); + buffer_->clear_depth_stencil_buffer(ctx); + + ctx.render_context->set_depth_stencil_state(depth_stencil_state_); + ctx.render_context->set_rasterizer_state(rasterizer_state_); + + + ctx.render_context->set_viewport(scm::gl::viewport( + math::vec2(0, 0), + math::vec2(map_size, map_size))); + + // calculate light frustum + math::mat4 screen_transform(scm::math::make_translation(0.f, 0.f, -1.f)); + screen_transform = transform * screen_transform; + + Frustum shadow_frustum = Frustum::perspective(transform, + screen_transform, + pipeline_->config.near_clip(), + pipeline_->config.far_clip()); + + mesh_shader_->set_uniform(ctx, 1.0f / map_size, "gua_texel_width"); + mesh_shader_->set_uniform(ctx, 1.0f / map_size, "gua_texel_height"); + + // render geometries + mesh_shader_->use(ctx); + render_geometry(ctx, center_of_interest, shadow_frustum, scene_camera, 0); + mesh_shader_->unuse(ctx); + + ctx.render_context->reset_state_objects(); + + buffer_->unbind(ctx); +} + +//////////////////////////////////////////////////////////////////////////////// + +void ShadowMap::render_cascaded(RenderContext const& ctx, + math::vec3 const& center_of_interest, + Frustum const& scene_frustum, + Camera const& scene_camera, + math::mat4 const& transform, + unsigned map_size, float split_0, + float split_1, float split_2, + float split_3, float split_4, + float near_clipping_in_sun_direction) { + + update_members(ctx, map_size*2); + projection_view_matrices_ = std::vector(4); + + buffer_->bind(ctx); + buffer_->clear_depth_stencil_buffer(ctx); + + ctx.render_context->set_depth_stencil_state(depth_stencil_state_); + ctx.render_context->set_rasterizer_state(rasterizer_state_); + + std::vector splits({ + split_0, split_1, split_2, split_3, split_4 + }); + + if (pipeline_->config.near_clip() > split_0 || pipeline_->config.far_clip() < split_4) { + WARNING("Splits of cascaded shadow maps are not inside clipping range! Fallback to equidistant splits used."); + float clipping_range(pipeline_->config.far_clip() - pipeline_->config.near_clip()); + splits = { + pipeline_->config.near_clip(), + pipeline_->config.near_clip() + clipping_range * 0.25f, + pipeline_->config.near_clip() + clipping_range * 0.5f, + pipeline_->config.near_clip() + clipping_range * 0.75f, + pipeline_->config.far_clip() + }; + } + + mesh_shader_->set_uniform(ctx, 1.0f / map_size, "gua_texel_width"); + mesh_shader_->set_uniform(ctx, 1.0f / map_size, "gua_texel_height"); + + for (int y(0); y<2; ++y) { + for (int x(0); x<2; ++x) { + + int cascade(y*2 + x); + + ctx.render_context->set_viewport(scm::gl::viewport( + math::vec2(x * map_size, y * map_size), + math::vec2(map_size, map_size))); + + Frustum cropped_frustum(Frustum::perspective( + scene_frustum.get_camera_transform(), + scene_frustum.get_screen_transform(), + splits[cascade], splits[cascade+1] + )); + + auto cropped_frustum_corners(cropped_frustum.get_corners()); + math::BoundingBox extends_in_sun_space; + + auto inverse_sun_transform(scm::math::inverse(transform)); + for (auto const& corner: cropped_frustum_corners) { + auto corner_in_sun_space(inverse_sun_transform * corner); + extends_in_sun_space.expandBy(corner_in_sun_space); + } + + auto size(extends_in_sun_space.max - extends_in_sun_space.min); + + auto center(math::vec3((extends_in_sun_space.min[0] + extends_in_sun_space.max[0])/2, + (extends_in_sun_space.min[1] + extends_in_sun_space.max[1])/2, + extends_in_sun_space.max[2] + near_clipping_in_sun_direction)); + + auto screen_in_sun_space(scm::math::make_translation(center) * scm::math::make_scale(size[0], size[1], 1.0f)); + + auto sun_screen_transform(transform * screen_in_sun_space); + auto sun_camera_transform(scm::math::make_translation(sun_screen_transform.column(3)[0], sun_screen_transform.column(3)[1], sun_screen_transform.column(3)[2])); + auto sun_camera_depth(transform * math::vec4(0, 0, size[2] + near_clipping_in_sun_direction, 0.0f)); + + auto shadow_frustum( + Frustum::orthographic( + sun_camera_transform, + sun_screen_transform, + 0, + scm::math::length(sun_camera_depth) + ) + ); + + // // render geometries + mesh_shader_->use(ctx); + render_geometry(ctx, center_of_interest, shadow_frustum, scene_camera, cascade); + mesh_shader_->unuse(ctx); + } + } + + ctx.render_context->reset_state_objects(); + + buffer_->unbind(ctx); + +} + +//////////////////////////////////////////////////////////////////////////////// + +} diff --git a/src/gua/renderer/StereoBuffer.cpp b/src/gua/renderer/StereoBuffer.cpp index 469872706..c994ab69e 100644 --- a/src/gua/renderer/StereoBuffer.cpp +++ b/src/gua/renderer/StereoBuffer.cpp @@ -34,7 +34,7 @@ namespace gua { StereoBuffer::StereoBuffer( RenderContext const& ctx, - PipelineConfiguration const& config, + Pipeline::Configuration const& config, std::vector > const& layers) { diff --git a/src/gua/renderer/Texture.cpp b/src/gua/renderer/Texture.cpp index e13e5982d..3418da24b 100644 --- a/src/gua/renderer/Texture.cpp +++ b/src/gua/renderer/Texture.cpp @@ -33,17 +33,11 @@ namespace gua { -//////////////////////////////////////////////////////////////////////////////// - -Texture::Texture(unsigned width, - unsigned height, - scm::gl::data_format color_format, +Texture::Texture(scm::gl::data_format color_format, std::vector const& data, unsigned mipmap_layers, scm::gl::sampler_state_desc const& state_descripton) - : width_(width), - height_(height), - mipmap_layers_(mipmap_layers), + : mipmap_layers_(mipmap_layers), color_format_(color_format), file_name_(""), data_(data), @@ -52,16 +46,10 @@ Texture::Texture(unsigned width, sampler_states_(), upload_mutex_() {} -//////////////////////////////////////////////////////////////////////////////// - -Texture::Texture(unsigned width, - unsigned height, - scm::gl::data_format color_format, +Texture::Texture(scm::gl::data_format color_format, unsigned mipmap_layers, scm::gl::sampler_state_desc const& state_descripton) - : width_(width), - height_(height), - mipmap_layers_(mipmap_layers), + : mipmap_layers_(mipmap_layers), color_format_(color_format), file_name_(""), state_descripton_(state_descripton), @@ -69,13 +57,10 @@ Texture::Texture(unsigned width, sampler_states_(), upload_mutex_() {} -//////////////////////////////////////////////////////////////////////////////// - Texture::Texture(std::string const& file, bool generate_mipmaps, scm::gl::sampler_state_desc const& state_descripton) - : width_(0), - height_(0), + : mipmap_layers_(generate_mipmaps ? 1 : 0), color_format_(scm::gl::FORMAT_NULL), file_name_(file), @@ -84,14 +69,10 @@ Texture::Texture(std::string const& file, sampler_states_(), upload_mutex_() {} -//////////////////////////////////////////////////////////////////////////////// - Texture::~Texture() { make_non_resident(); } -//////////////////////////////////////////////////////////////////////////////// - void Texture::generate_mipmaps(RenderContext const& context) { if (textures_.size() <= context.id || textures_[context.id] == 0) @@ -100,8 +81,6 @@ void Texture::generate_mipmaps(RenderContext const& context) { context.render_context->generate_mipmaps(textures_[context.id]); } -//////////////////////////////////////////////////////////////////////////////// - math::vec2ui const Texture::get_handle(RenderContext const& context) const { if (textures_.size() <= context.id || textures_[context.id] == 0) @@ -112,9 +91,7 @@ math::vec2ui const Texture::get_handle(RenderContext const& context) const { return math::vec2ui(handle & 0x00000000ffffffff, handle & 0xffffffff00000000); } -//////////////////////////////////////////////////////////////////////////////// - -scm::gl::texture_2d_ptr const& Texture::get_buffer( +scm::gl::texture_image_ptr const& Texture::get_buffer( RenderContext const& context) const { if (textures_.size() <= context.id || textures_[context.id] == 0) @@ -123,42 +100,24 @@ scm::gl::texture_2d_ptr const& Texture::get_buffer( return textures_[context.id]; } -//////////////////////////////////////////////////////////////////////////////// - void Texture::make_resident(RenderContext const& context) const { context.render_context ->make_resident(textures_[context.id], sampler_states_[context.id]); } -//////////////////////////////////////////////////////////////////////////////// - void Texture::make_non_resident(RenderContext const& context) const { - context.render_context->make_non_resident(textures_[context.id]); } -//////////////////////////////////////////////////////////////////////////////// - void Texture::make_non_resident() const { - for (int i(0); imake_non_resident(textures_[i]); } } -//////////////////////////////////////////////////////////////////////////////// - -unsigned Texture::width() const { return width_; } - -//////////////////////////////////////////////////////////////////////////////// - -unsigned Texture::height() const { return height_; } - -//////////////////////////////////////////////////////////////////////////////// - +#if 0 void Texture::upload_to(RenderContext const& context) const { - std::unique_lock lock(upload_mutex_); if (textures_.size() <= context.id) { @@ -198,7 +157,6 @@ void Texture::upload_to(RenderContext const& context) const { make_resident(context); } - -//////////////////////////////////////////////////////////////////////////////// +#endif } diff --git a/src/gua/renderer/Texture2D.cpp b/src/gua/renderer/Texture2D.cpp new file mode 100644 index 000000000..fdfa0caf5 --- /dev/null +++ b/src/gua/renderer/Texture2D.cpp @@ -0,0 +1,104 @@ +/****************************************************************************** + * guacamole - delicious VR * + * * + * Copyright: (c) 2011-2013 Bauhaus-Universität Weimar * + * Contact: felix.lauer@uni-weimar.de / simon.schneegans@uni-weimar.de * + * * + * This program is free software: you can redistribute it and/or modify it * + * under the terms of the GNU General Public License as published by the Free * + * Software Foundation, either version 3 of the License, or (at your option) * + * any later version. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * + * for more details. * + * * + * You should have received a copy of the GNU General Public License along * + * with this program. If not, see . * + * * + ******************************************************************************/ + +// class header +#include + +// guacamole headers +#include +#include +#include + +// external headers +#include +#include + +namespace gua { + +Texture2D::Texture2D(unsigned width, + unsigned height, + scm::gl::data_format color_format, + std::vector const& data, + unsigned mipmap_layers, + scm::gl::sampler_state_desc const& state_descripton) + : Texture(color_format, data, mipmap_layers, state_descripton), + width_(width), + height_(height) {} + +Texture2D::Texture2D(unsigned width, + unsigned height, + scm::gl::data_format color_format, + unsigned mipmap_layers, + scm::gl::sampler_state_desc const& state_descripton) + : Texture(color_format, mipmap_layers, state_descripton), + width_(width), + height_(height) {} + +Texture2D::Texture2D(std::string const& file, + bool generate_mipmaps, + scm::gl::sampler_state_desc const& state_descripton) + : Texture(file, generate_mipmaps, state_descripton), + width_(0), + height_(0) {} + +void Texture2D::upload_to(RenderContext const& context) const { + + std::unique_lock lock(upload_mutex_); + + if (textures_.size() <= context.id) { + textures_.resize(context.id + 1); + sampler_states_.resize(context.id + 1); + render_contexts_.resize(context.id + 1); + } + + if (file_name_ == "") { + + + if (data_.size() == 0) + textures_[context.id] = context.render_device->create_texture_2d( + math::vec2ui(width_, height_), color_format_, mipmap_layers_); + else + textures_[context.id] = context.render_device->create_texture_2d( + scm::gl::texture_2d_desc( + math::vec2ui(width_, height_), color_format_, mipmap_layers_), + color_format_, + data_); + } else { + // MESSAGE("Uploading texture file %s", file_name_.c_str()); + scm::gl::texture_loader loader; + textures_[context.id] = loader.load_texture_2d( + *context.render_device, file_name_, mipmap_layers_ > 0); + + if (textures_[context.id]) { + width_ = textures_[context.id]->dimensions()[0]; + height_ = textures_[context.id]->dimensions()[1]; + } + } + + sampler_states_[context.id] = + context.render_device->create_sampler_state(state_descripton_); + + render_contexts_[context.id] = context.render_context; + + make_resident(context); +} + +} diff --git a/src/gua/renderer/Texture3D.cpp b/src/gua/renderer/Texture3D.cpp new file mode 100644 index 000000000..7c0b1b1e8 --- /dev/null +++ b/src/gua/renderer/Texture3D.cpp @@ -0,0 +1,110 @@ +/****************************************************************************** + * guacamole - delicious VR * + * * + * Copyright: (c) 2011-2013 Bauhaus-Universität Weimar * + * Contact: felix.lauer@uni-weimar.de / simon.schneegans@uni-weimar.de * + * * + * This program is free software: you can redistribute it and/or modify it * + * under the terms of the GNU General Public License as published by the Free * + * Software Foundation, either version 3 of the License, or (at your option) * + * any later version. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * + * for more details. * + * * + * You should have received a copy of the GNU General Public License along * + * with this program. If not, see . * + * * + ******************************************************************************/ + +// class header +#include + +// guacamole headers +#include +#include +#include + +// external headers +#include +#include + +namespace gua { + +Texture3D::Texture3D(unsigned width, + unsigned height, + unsigned depth, + scm::gl::data_format color_format, + std::vector const& data, + unsigned mipmap_layers, + scm::gl::sampler_state_desc const& state_descripton) + : Texture(color_format, data, mipmap_layers, state_descripton), + width_(width), + height_(height), + depth_(depth) {} + +Texture3D::Texture3D(unsigned width, + unsigned height, + unsigned depth, + scm::gl::data_format color_format, + unsigned mipmap_layers, + scm::gl::sampler_state_desc const& state_descripton) + : Texture(color_format, mipmap_layers, state_descripton), + width_(width), + height_(height), + depth_(depth) {} + +Texture3D::Texture3D(std::string const& file, + bool generate_mipmaps, + scm::gl::sampler_state_desc const& state_descripton) + : Texture(file, generate_mipmaps, state_descripton), + width_(0), + height_(0), + depth_(0) {} + +void Texture3D::upload_to(RenderContext const& context) const { + + std::unique_lock lock(upload_mutex_); + + if (textures_.size() <= context.id) { + textures_.resize(context.id + 1); + sampler_states_.resize(context.id + 1); + render_contexts_.resize(context.id + 1); + } + + if (file_name_ == "") { + + + if (data_.size() == 0) + textures_[context.id] = context.render_device->create_texture_3d( + math::vec3ui(width_, height_, depth_), color_format_, mipmap_layers_); + else + textures_[context.id] = context.render_device->create_texture_3d( + scm::gl::texture_3d_desc( + math::vec3ui(width_, height_, depth_), color_format_, mipmap_layers_), + color_format_, + data_); + } else { + // MESSAGE("Uploading texture file %s", file_name_.c_str()); + scm::gl::volume_loader loader; + textures_[context.id] = loader.load_texture_3d( + *context.render_device, file_name_, mipmap_layers_ > 0); + + if (textures_[context.id]) { + width_ = textures_[context.id]->dimensions()[0]; + height_ = textures_[context.id]->dimensions()[1]; + depth_ = textures_[context.id]->dimensions()[2]; + } + } + + sampler_states_[context.id] = + context.render_device->create_sampler_state(state_descripton_); + + render_contexts_[context.id] = context.render_context; + + make_resident(context); +} + +} diff --git a/src/gua/renderer/UberShaderFactory.cpp b/src/gua/renderer/UberShaderFactory.cpp index 5b722c33c..6edd0bb4d 100644 --- a/src/gua/renderer/UberShaderFactory.cpp +++ b/src/gua/renderer/UberShaderFactory.cpp @@ -65,7 +65,16 @@ UberShaderFactory::UberShaderFactory( // store material specific main method calls std::stringstream call; call << "/* " << mat->get_name() << " */ "; - call << shading_model->get_name() << "_main("; + + auto name(shading_model->get_name()); + std::replace(name.begin(), name.end(), '/', '_'); + std::replace(name.begin(), name.end(), '\\', '_'); + std::replace(name.begin(), name.end(), '.', '_'); + std::replace(name.begin(), name.end(), '(', '_'); + std::replace(name.begin(), name.end(), ')', '_'); + std::replace(name.begin(), name.end(), ' ', '_'); + + call << name << "_main("; auto uniform(shading_model->get_stages()[stage].get_uniforms().begin()); @@ -75,7 +84,7 @@ UberShaderFactory::UberShaderFactory( auto mapped( uniform_mapping_.get_mapping(mat->get_name(), uniform->first)); - if (uniform->second == UniformType::SAMPLER) + if (uniform->second == UniformType::SAMPLER2D) call << "gua_get_float_sampler(" << mapped.first << "[" << mapped.second << "])"; else @@ -198,7 +207,16 @@ void UberShaderFactory::load_main_functions(std::shared_ptr const& // write main() method _main() ---------------------------- std::stringstream stream; - stream << "void " << model->get_name() << "_main("; + + auto name(model->get_name()); + std::replace(name.begin(), name.end(), '/', '_'); + std::replace(name.begin(), name.end(), '\\', '_'); + std::replace(name.begin(), name.end(), '.', '_'); + std::replace(name.begin(), name.end(), '(', '_'); + std::replace(name.begin(), name.end(), ')', '_'); + std::replace(name.begin(), name.end(), ' ', '_'); + + stream << "void " << name << "_main("; auto uniform(model->get_stages()[stage_].get_uniforms().begin()); diff --git a/src/gua/renderer/UniformMapping.cpp b/src/gua/renderer/UniformMapping.cpp index 259178937..5f1561aa5 100644 --- a/src/gua/renderer/UniformMapping.cpp +++ b/src/gua/renderer/UniformMapping.cpp @@ -89,7 +89,7 @@ std::string const UniformMapping::get_uniform_definition() const { int count(get_uniform_count(UniformType(t))); if (count > 0) { - if (UniformType(t) == UniformType::SAMPLER) { + if (UniformType(t) == UniformType::SAMPLER2D) { std::string type(enums::uniform_type_to_string(UniformType(t))); result << "uniform uvec2" << " gua_" << type << "s[" << count << "];" << std::endl; diff --git a/src/gua/renderer/Volume.cpp b/src/gua/renderer/Volume.cpp new file mode 100644 index 000000000..7dc3e196a --- /dev/null +++ b/src/gua/renderer/Volume.cpp @@ -0,0 +1,369 @@ +/****************************************************************************** +* guacamole - delicious VR * +* * +* Copyright: (c) 2011-2013 Bauhaus-Universität Weimar * +* Contact: felix.lauer@uni-weimar.de / simon.schneegans@uni-weimar.de * +* * +* This program is free software: you can redistribute it and/or modify it * +* under the terms of the GNU General Public License as published by the Free * +* Software Foundation, either version 3 of the License, or (at your option) * +* any later version. * +* * +* This program is distributed in the hope that it will be useful, but * +* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * +* for more details. * +* * +* You should have received a copy of the GNU General Public License along * +* with this program. If not, see . * +* * +******************************************************************************/ + +// class header +#include + +// guacamole headers +#include +#include +#include +#include + +// external headers +#if ASSIMP_VERSION == 3 +#include +#include +#else +#include +#include +#include +#endif + +#include +#include +#include + +namespace { + struct Vertex { + scm::math::vec3f pos; + scm::math::vec2f tex; + scm::math::vec3f normal; + scm::math::vec3f tangent; + scm::math::vec3f bitangent; + }; +} + +namespace gua { + + //////////////////////////////////////////////////////////////////////////////// + + Volume::Volume() + : _volume_boxes_ptr(), upload_mutex_() {} + + //////////////////////////////////////////////////////////////////////////////// + + Volume::Volume(std::string const& file_name) + : + _volume_file_path(file_name), + _volume_boxes_ptr(), + upload_mutex_() + { + scm::gl::volume_loader scm_volume_loader; + _volume_dimensions = scm_volume_loader.read_dimensions(file_name); + //scm::math::vec3ui volume_dimensions = scm::math::vec3ui(256, 256, 225); + + unsigned max_dimension_volume = scm::math::max(scm::math::max(_volume_dimensions.x, _volume_dimensions.y), _volume_dimensions.z); + + step_size(0.5f / (float)max_dimension_volume); + + _volume_dimensions_normalized = math::vec3((float)_volume_dimensions.x / (float)max_dimension_volume, + (float)_volume_dimensions.y / (float)max_dimension_volume, + (float)_volume_dimensions.z / (float)max_dimension_volume); + + //MESSAGE("%f %f %f", _volume_dimensions_normalized.x, _volume_dimensions_normalized.y, _volume_dimensions_normalized.z); + //getchar(); + + bounding_box_ = math::BoundingBox(math::vec3::zero(), _volume_dimensions_normalized); + + // initialize transfer functions ////////////////////////////////////////////////////////////// + _alpha_transfer.clear(); + _color_transfer.clear(); + +#if 0 + _alpha_transfer.add_stop(0, 1.0f); + _alpha_transfer.add_stop(0.45f, 0.0f); + _alpha_transfer.add_stop(0.50f, 0.0f); + _alpha_transfer.add_stop(0.55f, 0.0f); + _alpha_transfer.add_stop(1.0f, 1.0f); +#else + _alpha_transfer.add_stop(0.0f, 0.0f); + _alpha_transfer.add_stop(0.3f, 0.0f); + _alpha_transfer.add_stop(0.4f, 0.2f); + _alpha_transfer.add_stop(0.7f, 0.0f); + _alpha_transfer.add_stop(1.0f, 1.0f); +#endif + +#if 0 + // blue-white-red + _color_transfer.add_stop(0, scm::math::vec3f(1.0f, 0.0f, 0.0f)); + _color_transfer.add_stop(0.5, scm::math::vec3f(1.0f, 1.0f, 1.0f)); + _color_transfer.add_stop(1.0f, scm::math::vec3f(0.0f, 0.0f, 1.0f)); +#else + // blue-white-red + _color_transfer.add_stop(0.0f, scm::math::vec3f(0.0f, 0.0f, 0.0f)); + _color_transfer.add_stop(0.5f, scm::math::vec3f(0.4f, 0.0f, 0.4f)); + _color_transfer.add_stop(0.7f, scm::math::vec3f(1.0f, 1.0f, 1.0f)); + _color_transfer.add_stop(1.0f, scm::math::vec3f(1.0f, 1.0f, 1.0f)); +#endif + + } + + //////////////////////////////////////////////////////////////////////////////// + + void Volume::upload_to(RenderContext const& ctx) const { + + //if (!_volume_texture_ptr[ctx.id]) { + // WARNING("Unable to load Volume! Has no volume data."); + // return; + //} + + std::unique_lock lock(upload_mutex_); + + if (_volume_boxes_ptr.size() <= ctx.id){ + _volume_texture_ptr.resize(ctx.id + 1); + _transfer_texture_ptr.resize(ctx.id + 1); + _volume_boxes_ptr.resize(ctx.id + 1); + _sstate.resize(ctx.id + 1); + } + + //scm::gl::volume_loader scm_volume_loader; + + //texture_3d_ptr load_texture_3d(render_device& in_device, + // const std::string& in_image_path, + // bool in_create_mips, + // bool in_color_mips = false, + // const data_format in_force_internal_format = FORMAT_NULL); + + _volume_texture_ptr[ctx.id] = std::shared_ptr(new Texture3D(_volume_file_path));// scm_volume_loader.load_texture_3d(*(ctx.render_device.get()), _volume_file_path, false); + _volume_texture_ptr[ctx.id]->upload_to(ctx); + + //MESSAGE("%s loaded!", _volume_file_path.c_str()); + + //scm::gl::texture_loader scm_image_loader; + _transfer_texture_ptr[ctx.id] = create_color_map(ctx, 255, _alpha_transfer, _color_transfer); + _transfer_texture_ptr[ctx.id]->upload_to(ctx); + + //box_volume_geometry + _volume_boxes_ptr[ctx.id] = + scm::gl::box_volume_geometry_ptr(new scm::gl::box_volume_geometry(ctx.render_device, scm::math::vec3(0.0), _volume_dimensions_normalized)); + + _sstate[ctx.id] = ctx.render_device->create_sampler_state( + scm::gl::FILTER_MIN_MAG_MIP_LINEAR, scm::gl::WRAP_CLAMP_TO_EDGE); + } + + std::shared_ptr + Volume::create_color_map(RenderContext const& ctx, + unsigned in_size, + const scm::data::piecewise_function_1d& in_alpha, + const scm::data::piecewise_function_1d& in_color) const + { + using namespace scm::gl; + using namespace scm::math; + + scm::scoped_array color_lut; + scm::scoped_array alpha_lut; + + color_lut.reset(new vec3f[in_size]); + alpha_lut.reset(new float[in_size]); + + if (!scm::data::build_lookup_table(color_lut, in_color, in_size) + || !scm::data::build_lookup_table(alpha_lut, in_alpha, in_size)) { + std::cout << "Volume::create_color_map(): error during lookuptable generation" << std::endl; + return (std::shared_ptr(new Texture2D(in_size, 1))); + } + scm::scoped_array combined_lut; + + combined_lut.reset(new float[in_size * 4]); + + for (unsigned i = 0; i < in_size; ++i) { + combined_lut[i * 4] = color_lut[i].x; + combined_lut[i * 4 + 1] = color_lut[i].y; + combined_lut[i * 4 + 2] = color_lut[i].z; + combined_lut[i * 4 + 3] = alpha_lut[i]; + } + + //for (unsigned i = 0; i < in_size; ++i) { + // combined_lut[i * 4] = i; + // combined_lut[i * 4 + 1] = i; + // combined_lut[i * 4 + 2] = i; + // combined_lut[i * 4 + 3] = 1.0; + //} + + std::vector in_data; + in_data.push_back(combined_lut.get()); + + std::shared_ptr new_tex = + std::shared_ptr(new Texture2D(in_size, 1, FORMAT_RGBA_32F, in_data));// ctx.render_device->create_texture_2d(scm::math::vec2ui(in_size, 1), FORMAT_RGBA_8, 1, 1, 1, FORMAT_RGBA_32F, in_data); + + if (!new_tex) { + std::cerr << "Volume::create_color_map(): error during color map texture generation." << std::endl; + return (std::shared_ptr(new Texture2D(in_size, 1))); + } + else{ + //std::cout << "Volume::create_color_map(): color map texture generated." << std::endl; + return (new_tex); + } + } + + bool Volume::update_color_map(RenderContext const& ctx, + std::shared_ptr transfer_texture_ptr, + const scm::data::piecewise_function_1d& in_alpha, + const scm::data::piecewise_function_1d& in_color) const + { + using namespace scm::gl; + using namespace scm::math; + + scm::scoped_array color_lut; + scm::scoped_array alpha_lut; + + unsigned in_size = transfer_texture_ptr->width(); + + color_lut.reset(new vec3f[in_size]); + alpha_lut.reset(new float[in_size]); + + if (!scm::data::build_lookup_table(color_lut, in_color, in_size) + || !scm::data::build_lookup_table(alpha_lut, in_alpha, in_size)) { + MESSAGE("volume_data::update_color_alpha_map(): error during lookuptable generation"); + return false; + } + scm::scoped_array combined_lut; + + combined_lut.reset(new float[in_size * 4]); + + for (unsigned i = 0; i < in_size; ++i) { + combined_lut[i * 4] = color_lut[i].x; + combined_lut[i * 4 + 1] = color_lut[i].y; + combined_lut[i * 4 + 2] = color_lut[i].z; + combined_lut[i * 4 + 3] = alpha_lut[i]; + } + + //MESSAGE("generating color map texture data done."); + + //MESSAGE("uploading texture data ( size: %d KiB)...", static_cast(in_size * size_of_format(FORMAT_RGBA_32F)) / (1024.0)); + + texture_region ur(vec3ui(0u), vec3ui(in_size, 1, 1)); + bool res = ctx.render_context->update_sub_texture(transfer_texture_ptr->get_buffer(ctx), ur, 0u, FORMAT_RGBA_32F, combined_lut.get()); + + //MESSAGE("uploading texture data done."); + + if (!res) { + MESSAGE("Volume::update_color_alpha_map(): error during color map texture generation."); + return false; + } + + return true; + } + + //////////////////////////////////////////////////////////////////////////////// + + void Volume::draw(RenderContext const& ctx) const { + + // upload to GPU if neccessary + if (_volume_boxes_ptr.size() <= ctx.id || _volume_boxes_ptr[ctx.id] == nullptr) { + upload_to(ctx); + } + + if (_update_transfer_function){ + for (auto color_map_texture : _transfer_texture_ptr) + { + update_color_map(ctx, color_map_texture, _alpha_transfer, _color_transfer); + } + _update_transfer_function = false; + } + + scm::gl::context_vertex_input_guard vig(ctx.render_context); + + ctx.render_context->bind_texture( _volume_texture_ptr[ctx.id]->get_buffer(ctx), _sstate[ctx.id], 5); + ctx.render_context->bind_texture(_transfer_texture_ptr[ctx.id]->get_buffer(ctx), _sstate[ctx.id], 6); + scm::gl::program_ptr p = ctx.render_context->current_program(); + p->uniform_sampler("volume_texture", 5); + p->uniform_sampler("transfer_texture", 6); + p->uniform("sampling_distance", _step_size); + //p->uniform("iso_value", 0.8f); + p->uniform("volume_bounds", _volume_dimensions_normalized); + + ctx.render_context->apply(); + _volume_boxes_ptr[ctx.id]->draw(ctx.render_context); + } + + void Volume::draw_proxy(RenderContext const& ctx) const { + + // upload to GPU if neccessary + if (_volume_boxes_ptr.size() <= ctx.id || _volume_boxes_ptr[ctx.id] == nullptr) { + upload_to(ctx); + } + + scm::gl::context_vertex_input_guard vig(ctx.render_context); + + ctx.render_context->apply(); + _volume_boxes_ptr[ctx.id]->draw(ctx.render_context); + } + + void Volume::set_uniforms(RenderContext const& ctx, ShaderProgram* cs) const + { + if (_update_transfer_function){ + for (auto color_map_texture : _transfer_texture_ptr) + { + update_color_map(ctx, color_map_texture, _alpha_transfer, _color_transfer); + } + _update_transfer_function = false; + } + + //_volume_texture_ptr[ctx.id]->make_resident(ctx); + //_transfer_texture_ptr[ctx.id]->make_resident(ctx); + + if (!_transfer_texture_ptr[ctx.id]){ + std::cerr << "No Transfer Texture2D ptr!" << std::endl; + return; + } + + cs->set_uniform(ctx, _volume_texture_ptr[ctx.id], "volume_texture"); + cs->set_uniform(ctx, _transfer_texture_ptr[ctx.id], "transfer_texture"); + cs->set_uniform(ctx, _step_size, "sampling_distance"); + cs->set_uniform(ctx, _volume_dimensions_normalized, "volume_bounds"); + + //_volume_texture_ptr[ctx.id]->make_non_resident(ctx); + //_transfer_texture_ptr[ctx.id]->make_non_resident(ctx); + + } + + //////////////////////////////////////////////////////////////////////////////// + + void Volume::ray_test(Ray const& ray, PickResult::Options options, + Node* owner, std::set& hits) { + + //kd_tree_.ray_test(ray, mesh_, options, owner, hits); + } + + //////////////////////////////////////////////////////////////////////////////// + + float Volume::step_size() const + { + return _step_size; + } + + void Volume::step_size(const float in_step_size) + { + _step_size = in_step_size; + } + + void Volume::set_transfer_function(const scm::data::piecewise_function_1d& in_alpha, const scm::data::piecewise_function_1d& in_color) + { + _alpha_transfer.clear(); + _color_transfer.clear(); + + _alpha_transfer = in_alpha; + _color_transfer = in_color; + + _update_transfer_function = true; + } +} diff --git a/src/gua/renderer/VolumeLoader.cpp b/src/gua/renderer/VolumeLoader.cpp new file mode 100644 index 000000000..3b65e9c83 --- /dev/null +++ b/src/gua/renderer/VolumeLoader.cpp @@ -0,0 +1,142 @@ +/****************************************************************************** +* guacamole - delicious VR * +* * +* Copyright: (c) 2011-2013 Bauhaus-Universität Weimar * +* Contact: felix.lauer@uni-weimar.de / simon.schneegans@uni-weimar.de * +* * +* This program is free software: you can redistribute it and/or modify it * +* under the terms of the GNU General Public License as published by the Free * +* Software Foundation, either version 3 of the License, or (at your option) * +* any later version. * +* * +* This program is distributed in the hope that it will be useful, but * +* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * +* for more details. * +* * +* You should have received a copy of the GNU General Public License along * +* with this program. If not, see . * +* * +******************************************************************************/ + +// class header +#include "gua/renderer/VolumeLoader.hpp" + +// guacamole headers +#include +#include +#include +#include +#include +#include +#include +#include + + +#include +#include +#include + + +namespace gua { + + //////////////////////////////////////////////////////////////////////////////// + + std::unordered_map> + VolumeLoader::loaded_files_ = + std::unordered_map>(); + + //////////////////////////////////////////////////////////////////////////////// + VolumeLoader::VolumeLoader() : LoaderBase(), _supported_file_extensions() { + _supported_file_extensions.insert("raw"); + _supported_file_extensions.insert("vol"); + } + + //VolumeLoader::VolumeLoader() + // {} + + std::shared_ptr VolumeLoader::create_volume_from_file(std::string const& node_name, + std::string const& file_name, + unsigned flags) + { + + std::shared_ptr cached_node; + std::string key(file_name + "_" + string_utils::to_string(flags)); + + auto searched(loaded_files_.find(key)); + if (searched != loaded_files_.end()) { + + cached_node = searched->second; + + } + else { + + if (is_supported(file_name)) { + cached_node = load(file_name, flags); + cached_node->update_cache(); + loaded_files_.insert(std::make_pair(key, cached_node)); + + // normalize volume position and rotation + if (flags & VolumeLoader::NORMALIZE_POSITION || flags & VolumeLoader::NORMALIZE_SCALE) { + auto bbox = cached_node->get_bounding_box(); + + if (flags & VolumeLoader::NORMALIZE_POSITION) { + auto center((bbox.min + bbox.max)*0.5); + cached_node->translate(-center); + } + + if (flags & VolumeLoader::NORMALIZE_SCALE) { + auto size(bbox.max - bbox.min); + auto max_size(std::max(std::max(size.x, size.y), size.z)); + cached_node->scale(1.f / max_size); + } + + } + } + + if (!cached_node) { + + WARNING("Unable to load %s: Volume Type is not supported!", file_name.c_str()); + } + } + + if (cached_node) { + auto copy(cached_node->deep_copy()); + + copy->set_name(node_name); + return copy; + } + + return std::make_shared(node_name); + } + + std::shared_ptr VolumeLoader::load(std::string const& file_name, + unsigned flags) + { + try { + GeometryDatabase::instance()->add( + file_name, std::make_shared(file_name)); + + auto result = std::make_shared("unnamed_volume"); + result->data.set_volume(file_name); + + return result; + + } + catch (std::exception &e) { + WARNING("Warning: \"%s\" \n", e.what()); + WARNING("Failed to load Volume object \"%s\": ", file_name.c_str()); + return nullptr; + } + } + + bool VolumeLoader::is_supported(std::string const& file_name) const { + std::vector filename_decomposition = + gua::string_utils::split(file_name, '.'); + return filename_decomposition.empty() + ? false + : _supported_file_extensions.count(filename_decomposition.back()) > + 0; + } + +} diff --git a/src/gua/renderer/WarpMatrix.cpp b/src/gua/renderer/WarpMatrix.cpp index af6e7876c..2f2d9e620 100644 --- a/src/gua/renderer/WarpMatrix.cpp +++ b/src/gua/renderer/WarpMatrix.cpp @@ -33,12 +33,12 @@ namespace gua { //////////////////////////////////////////////////////////////////////////////// -WarpMatrix::WarpMatrix() : Texture(0, 0), data_() {} +WarpMatrix::WarpMatrix() : Texture2D(0, 0), data_() {} //////////////////////////////////////////////////////////////////////////////// WarpMatrix::WarpMatrix(std::string const& file_name) - : Texture(0, + : Texture2D(0, 0, scm::gl::FORMAT_RGBA_16F, 1, diff --git a/src/gua/renderer/Window.cpp b/src/gua/renderer/Window.cpp index bfef9c319..8f642ca4c 100644 --- a/src/gua/renderer/Window.cpp +++ b/src/gua/renderer/Window.cpp @@ -46,6 +46,12 @@ std::string subroutine_from_mode(Window::TextureDisplayMode mode) { case Window::CYAN: return "get_cyan"; break; + case Window::CHECKER_EVEN: + return "get_checker_even"; + break; + case Window::CHECKER_ODD: + return "get_checker_odd"; + break; default: return "get_full"; } @@ -124,6 +130,29 @@ void Window::open() { ctx_.id = last_context_id_++; + + + fullscreen_quad_ = scm::gl::quad_geometry_ptr(new scm::gl::quad_geometry( + ctx_.render_device, math::vec2(-1.f, -1.f), math::vec2(1.f, 1.f))); + + depth_stencil_state_ = ctx_.render_device + ->create_depth_stencil_state(false, false, scm::gl::COMPARISON_NEVER); + + blend_state_ = ctx_.render_device->create_blend_state(true, + scm::gl::FUNC_ONE, + scm::gl::FUNC_ONE, + scm::gl::FUNC_ONE, + scm::gl::FUNC_ONE); +} + +//////////////////////////////////////////////////////////////////////////////// + +bool Window::get_is_open() const { return ctx_.window != nullptr; } + +//////////////////////////////////////////////////////////////////////////////// + +void Window::create_shader() { + if (config.get_warp_matrix_red_right() == "" || config.get_warp_matrix_green_right() == "" || config.get_warp_matrix_blue_right() == "" || @@ -152,26 +181,10 @@ void Window::open() { Resources::lookup_shader(Resources::shaders_display_shader_warped_frag) ); } - - fullscreen_quad_ = scm::gl::quad_geometry_ptr(new scm::gl::quad_geometry( - ctx_.render_device, math::vec2(-1.f, -1.f), math::vec2(1.f, 1.f))); - - depth_stencil_state_ = ctx_.render_device - ->create_depth_stencil_state(false, false, scm::gl::COMPARISON_NEVER); - - blend_state_ = ctx_.render_device->create_blend_state(true, - scm::gl::FUNC_ONE, - scm::gl::FUNC_ONE, - scm::gl::FUNC_ONE, - scm::gl::FUNC_ONE); } //////////////////////////////////////////////////////////////////////////////// -bool Window::get_is_open() const { return ctx_.window != nullptr; } - -//////////////////////////////////////////////////////////////////////////////// - void Window::close() { if (get_is_open()) { @@ -205,7 +218,7 @@ void Window::finish_frame() const { //////////////////////////////////////////////////////////////////////////////// -void Window::display(std::shared_ptr const& center_texture) { +void Window::display(std::shared_ptr const& center_texture) { display(center_texture, config.get_left_resolution(), config.get_left_position(), Window::FULL, true, true); @@ -214,32 +227,38 @@ void Window::display(std::shared_ptr const& center_texture) { //////////////////////////////////////////////////////////////////////////////// -void Window::display(std::shared_ptr const& left_texture, - std::shared_ptr const& right_texture) { +void Window::display(std::shared_ptr const& left_texture, + std::shared_ptr const& right_texture) { switch (config.get_stereo_mode()) { - case StereoMode::MONO: - display(left_texture); - break; - case StereoMode::SIDE_BY_SIDE: - display(left_texture, config.get_left_resolution(), - config.get_left_position(), Window::FULL, true, true); - display(right_texture, config.get_right_resolution(), - config.get_right_position(), Window::FULL, false, true); - break; - case StereoMode::ANAGLYPH_RED_CYAN: - display(left_texture, config.get_left_resolution(), - config.get_left_position(), Window::RED, true, true); - display(right_texture, config.get_right_resolution(), - config.get_right_position(), Window::CYAN, false, false); - break; - case StereoMode::ANAGLYPH_RED_GREEN: - display(left_texture, config.get_left_resolution(), - config.get_left_position(), Window::RED, true, true); - display(right_texture, config.get_right_resolution(), - config.get_right_position(), Window::GREEN, false, false); - break; - } + case StereoMode::MONO: + display(left_texture); + break; + case StereoMode::SIDE_BY_SIDE: + display(left_texture, config.get_left_resolution(), + config.get_left_position(), Window::FULL, true, true); + display(right_texture, config.get_right_resolution(), + config.get_right_position(), Window::FULL, false, true); + break; + case StereoMode::ANAGLYPH_RED_CYAN: + display(left_texture, config.get_left_resolution(), + config.get_left_position(), Window::RED, true, true); + display(right_texture, config.get_right_resolution(), + config.get_right_position(), Window::CYAN, false, false); + break; + case StereoMode::ANAGLYPH_RED_GREEN: + display(left_texture, config.get_left_resolution(), + config.get_left_position(), Window::RED, true, true); + display(right_texture, config.get_right_resolution(), + config.get_right_position(), Window::GREEN, false, false); + break; + case StereoMode::CHECKERBOARD: + display(left_texture, config.get_left_resolution(), + config.get_left_position(), Window::CHECKER_EVEN, true, true); + display(right_texture, config.get_right_resolution(), + config.get_right_position(), Window::CHECKER_ODD, false, true); + break; + } } @@ -249,7 +268,7 @@ RenderContext* Window::get_context() { return &ctx_; } //////////////////////////////////////////////////////////////////////////////// -void Window::display(std::shared_ptr const& texture, +void Window::display(std::shared_ptr const& texture, math::vec2ui const& size, math::vec2ui const& position, TextureDisplayMode mode, @@ -260,13 +279,13 @@ void Window::display(std::shared_ptr const& texture, fullscreen_shader_.set_uniform(ctx_, texture, "sampler"); if (is_left) { - if (warpRL_) fullscreen_shader_.set_uniform(ctx_, std::dynamic_pointer_cast(warpRL_), "warpR"); - if (warpGL_) fullscreen_shader_.set_uniform(ctx_, std::dynamic_pointer_cast(warpGL_), "warpG"); - if (warpBL_) fullscreen_shader_.set_uniform(ctx_, std::dynamic_pointer_cast(warpBL_), "warpB"); + if (warpRL_) fullscreen_shader_.set_uniform(ctx_, std::dynamic_pointer_cast(warpRL_), "warpR"); + if (warpGL_) fullscreen_shader_.set_uniform(ctx_, std::dynamic_pointer_cast(warpGL_), "warpG"); + if (warpBL_) fullscreen_shader_.set_uniform(ctx_, std::dynamic_pointer_cast(warpBL_), "warpB"); } else { - if (warpRR_) fullscreen_shader_.set_uniform(ctx_, std::dynamic_pointer_cast(warpRR_), "warpR"); - if (warpGR_) fullscreen_shader_.set_uniform(ctx_, std::dynamic_pointer_cast(warpGR_), "warpG"); - if (warpBR_) fullscreen_shader_.set_uniform(ctx_, std::dynamic_pointer_cast(warpBR_), "warpB"); + if (warpRR_) fullscreen_shader_.set_uniform(ctx_, std::dynamic_pointer_cast(warpRR_), "warpR"); + if (warpGR_) fullscreen_shader_.set_uniform(ctx_, std::dynamic_pointer_cast(warpGR_), "warpG"); + if (warpBR_) fullscreen_shader_.set_uniform(ctx_, std::dynamic_pointer_cast(warpBR_), "warpB"); } std::string subroutine = subroutine_from_mode(mode); diff --git a/src/gua/renderer/enums.cpp b/src/gua/renderer/enums.cpp index 328f12a17..dd055cc7e 100644 --- a/src/gua/renderer/enums.cpp +++ b/src/gua/renderer/enums.cpp @@ -138,9 +138,13 @@ std::string uniform_type_to_string(UniformType type) { return "mat3"; case UniformType::MAT4: return "mat4"; - case UniformType::SAMPLER: + case UniformType::SAMPLER1D: + return "sampler1D"; + case UniformType::SAMPLER2D: return "sampler2D"; - case UniformType::CUBEMAP: + case UniformType::SAMPLER3D: + return "sampler3D"; + case UniformType::SAMPLERCUBE: return "samplerCube"; default: return "undefined"; @@ -166,10 +170,14 @@ boost::optional parse_uniform_type(std::string const& type) { return boost::make_optional(UniformType::MAT3); if (type == "mat4") return boost::make_optional(UniformType::MAT4); + if (type == "sampler1D") + return boost::make_optional(UniformType::SAMPLER1D); if (type == "sampler2D") - return boost::make_optional(UniformType::SAMPLER); + return boost::make_optional(UniformType::SAMPLER2D); + if (type == "sampler3D") + return boost::make_optional(UniformType::SAMPLER3D); if (type == "samplerCube") - return boost::make_optional(UniformType::CUBEMAP); + return boost::make_optional(UniformType::SAMPLERCUBE); return boost::optional(); } @@ -232,9 +240,13 @@ std::string get_default_value(UniformType type) { string_utils::replace(s, "\n", ";"); return s; } - case UniformType::SAMPLER: + case UniformType::SAMPLER1D: return "path/to/texture.png"; - case UniformType::CUBEMAP: + case UniformType::SAMPLER2D: + return "path/to/texture.png"; + case UniformType::SAMPLER3D: + return "path/to/volume.raw"; + case UniformType::SAMPLERCUBE: return "path/to/cubemap.png"; default: return "undefined"; @@ -271,9 +283,13 @@ bool is_valid_value(UniformType type, std::string& value) { return true; } return false; - case UniformType::SAMPLER: + case UniformType::SAMPLER1D: + return true; + case UniformType::SAMPLER2D: + return true; + case UniformType::SAMPLER3D: return true; - case UniformType::CUBEMAP: + case UniformType::SAMPLERCUBE: return true; default: return false; @@ -403,7 +419,7 @@ std::set list_uniform_types() { std::set result; for (int t(0); t < static_cast(UniformType::NONE); ++t) { - if (t != static_cast(UniformType::CUBEMAP)) + if (t != static_cast(UniformType::SAMPLERCUBE)) result.insert(uniform_type_to_string(static_cast(t))); } diff --git a/src/gua/scenegraph/GeometryNode.cpp b/src/gua/scenegraph/GeometryNode.cpp index 1b1acffed..fda38f939 100644 --- a/src/gua/scenegraph/GeometryNode.cpp +++ b/src/gua/scenegraph/GeometryNode.cpp @@ -25,6 +25,7 @@ // guacamole headers #include #include +#include #include #include #include @@ -33,157 +34,224 @@ namespace gua { GeometryNode::GeometryNode(std::string const& name, - Configuration const& configuration, + std::string const& geometry, + std::string const& material, math::mat4 const& transform) - : Node(name, transform), data(configuration) {} + : Node(name, transform), geometry_(geometry), material_(material), + geometry_changed_(false), material_changed_(false) {} /* virtual */ void GeometryNode::accept(NodeVisitor& visitor) { - visitor.visit(this); + visitor.visit(this); } +//////////////////////////////////////////////////////////////////////////////// + void GeometryNode::update_bounding_box() const { - if (data.get_geometry() != "") { - auto geometry_bbox(GeometryDatabase::instance()->lookup(data.get_geometry())->get_bounding_box()); - bounding_box_ = transform(geometry_bbox, world_transform_); + if (get_geometry() != "") { + auto geometry_bbox(GeometryDatabase::instance()->lookup(get_geometry())->get_bounding_box()); + bounding_box_ = transform(geometry_bbox, world_transform_); - for (auto child : get_children()) { - bounding_box_.expandBy(child->get_bounding_box()); - } - } - else { - Node::update_bounding_box(); + for (auto child : get_children()) { + bounding_box_.expandBy(child->get_bounding_box()); } + } + else { + Node::update_bounding_box(); + } } -void GeometryNode::ray_test_impl(RayNode const& ray, PickResult::Options options, - Mask const& mask, std::set& hits) { - - // first of all, check bbox - auto box_hits(ray.intersect(bounding_box_)); +//////////////////////////////////////////////////////////////////////////////// + +void GeometryNode::update_cache() { + + // The code below auto-loads a geometry if it's not already supported by + // the GeometryDatabase. It expects a geometry name like + // + // "type='file'&file='data/objects/monkey.obj'&id=0&flags=0" + + if (geometry_changed_) { + if (geometry_ != "") { + if (!GeometryDatabase::instance()->is_supported(geometry_)) { + auto params(string_utils::split(geometry_, '&')); + if (params.size() == 4) { + if (params[0] == "type=file") { + auto tmp_filename(string_utils::split(params[1], '=')); + auto tmp_flags(string_utils::split(params[3], '=')); + if (tmp_filename.size() == 2 && tmp_flags.size() == 2) { + std::string filename(tmp_filename[1]); + std::string flags_string(tmp_flags[1]); + unsigned flags(0); + std::stringstream sstr(flags_string); + sstr >> flags; + + GeometryLoader loader; + loader.load_geometry(filename, flags); + + } else { + WARNING("Failed to auto-load geometry %s: Failed to extract filename and/or loading flags!", geometry_.c_str()); + } + } else { + WARNING("Failed to auto-load geometry %s: Type is not supported!", geometry_.c_str()); + } + } else { + WARNING("Failed to auto-load geometry %s: The name does not contain a type, file, id and flag parameter!", geometry_.c_str()); + } + } + } - // ray did not intersect bbox -- therefore it wont intersect - if (box_hits.first == RayNode::END && box_hits.second == RayNode::END) { - return; + geometry_changed_ = false; } - // return if only first object shall be returned and the current first hit - // is in front of the bbox entry point and the ray does not start inside - // the bbox - if (options & PickResult::PICK_ONLY_FIRST_OBJECT - && hits.size() > 0 && hits.begin()->distance < box_hits.first - && box_hits.first != Ray::END) { + // The code below auto-loads a material if it's not already supported by + // the MaterialDatabase. It expects a material name like + // + // data/materials/Stones.gmd - return; + if (material_changed_) { + if (material_ != "") { + if (!MaterialDatabase::instance()->is_supported(material_)) { + auto mat = std::make_shared(material_, MaterialDescription(material_)); + MaterialDatabase::instance()->add(material_, mat); + } + } + + material_changed_ = false; } - // bbox is intersected, but check geometry only if mask tells us to check - if (data.get_geometry() != "" && mask.check(get_groups())) { - - auto geometry(GeometryDatabase::instance()->lookup(data.get_geometry())); - - if (geometry) { - - bool check_kd_tree(true); - - math::mat4 world_transform(get_world_transform()); - - // check for bounding box intersection of contained geometry if node - // has children (in this case, the bbox might be larger - // than the actual geometry) - if (has_children()) { - auto geometry_bbox(geometry->get_bounding_box()); - - math::BoundingBox inner_bbox; - inner_bbox.expandBy(world_transform * geometry_bbox.min); - inner_bbox.expandBy(world_transform * geometry_bbox.max); - inner_bbox.expandBy(world_transform * - math::vec3(geometry_bbox.min.x, - geometry_bbox.min.y, - geometry_bbox.max.z)); - inner_bbox.expandBy(world_transform * - math::vec3(geometry_bbox.min.x, - geometry_bbox.max.y, - geometry_bbox.min.z)); - inner_bbox.expandBy(world_transform * - math::vec3(geometry_bbox.min.x, - geometry_bbox.max.y, - geometry_bbox.max.z)); - inner_bbox.expandBy(world_transform * - math::vec3(geometry_bbox.max.x, - geometry_bbox.min.y, - geometry_bbox.max.z)); - inner_bbox.expandBy(world_transform * - math::vec3(geometry_bbox.max.x, - geometry_bbox.max.y, - geometry_bbox.min.z)); - inner_bbox.expandBy(world_transform * - math::vec3(geometry_bbox.max.x, - geometry_bbox.min.y, - geometry_bbox.min.z)); - - auto inner_hits(ray.intersect(inner_bbox)); - if (inner_hits.first == RayNode::END && - inner_hits.second == RayNode::END) - check_kd_tree = false; - } + Node::update_cache(); +} - if (check_kd_tree) { - Ray world_ray(ray.get_world_ray()); +//////////////////////////////////////////////////////////////////////////////// - math::mat4 ori_transform(scm::math::inverse(world_transform)); +void GeometryNode::ray_test_impl(RayNode const& ray, PickResult::Options options, + Mask const& mask, std::set& hits) { - math::vec4 ori(world_ray.origin_[0], - world_ray.origin_[1], - world_ray.origin_[2], - 1.0); - math::vec4 dir(world_ray.direction_[0], - world_ray.direction_[1], - world_ray.direction_[2], - 0.0); + // first of all, check bbox + auto box_hits(ray.intersect(bounding_box_)); + + // ray did not intersect bbox -- therefore it wont intersect + if (box_hits.first == RayNode::END && box_hits.second == RayNode::END) { + return; + } + + // return if only first object shall be returned and the current first hit + // is in front of the bbox entry point and the ray does not start inside + // the bbox + if (options & PickResult::PICK_ONLY_FIRST_OBJECT + && hits.size() > 0 && hits.begin()->distance < box_hits.first + && box_hits.first != Ray::END) { + + return; + } + + // bbox is intersected, but check geometry only if mask tells us to check + if (get_geometry() != "" && mask.check(get_groups())) { + + auto geometry(GeometryDatabase::instance()->lookup(get_geometry())); + + if (geometry) { + + bool check_kd_tree(true); + + math::mat4 world_transform(get_world_transform()); + + // check for bounding box intersection of contained geometry if node + // has children (in this case, the bbox might be larger + // than the actual geometry) + if (has_children()) { + auto geometry_bbox(geometry->get_bounding_box()); + + math::BoundingBox inner_bbox; + inner_bbox.expandBy(world_transform * geometry_bbox.min); + inner_bbox.expandBy(world_transform * geometry_bbox.max); + inner_bbox.expandBy(world_transform * + math::vec3(geometry_bbox.min.x, + geometry_bbox.min.y, + geometry_bbox.max.z)); + inner_bbox.expandBy(world_transform * + math::vec3(geometry_bbox.min.x, + geometry_bbox.max.y, + geometry_bbox.min.z)); + inner_bbox.expandBy(world_transform * + math::vec3(geometry_bbox.min.x, + geometry_bbox.max.y, + geometry_bbox.max.z)); + inner_bbox.expandBy(world_transform * + math::vec3(geometry_bbox.max.x, + geometry_bbox.min.y, + geometry_bbox.max.z)); + inner_bbox.expandBy(world_transform * + math::vec3(geometry_bbox.max.x, + geometry_bbox.max.y, + geometry_bbox.min.z)); + inner_bbox.expandBy(world_transform * + math::vec3(geometry_bbox.max.x, + geometry_bbox.min.y, + geometry_bbox.min.z)); + + auto inner_hits(ray.intersect(inner_bbox)); + if (inner_hits.first == RayNode::END && + inner_hits.second == RayNode::END) + check_kd_tree = false; + } - ori = ori_transform * ori; - dir = ori_transform * dir; + if (check_kd_tree) { + Ray world_ray(ray.get_world_ray()); - Ray object_ray(ori, dir, world_ray.t_max_); - geometry->ray_test(object_ray, options, this, hits); + math::mat4 ori_transform(scm::math::inverse(world_transform)); - float const inf(std::numeric_limits::max()); + math::vec4 ori(world_ray.origin_[0], + world_ray.origin_[1], + world_ray.origin_[2], + 1.0); + math::vec4 dir(world_ray.direction_[0], + world_ray.direction_[1], + world_ray.direction_[2], + 0.0); - if (options & PickResult::GET_WORLD_POSITIONS) { + ori = ori_transform * ori; + dir = ori_transform * dir; - for (auto& hit: hits) { - if (hit.world_position == math::vec3(inf, inf, inf)) { - auto transformed(world_transform * math::vec4(hit.position.x, hit.position.y, hit.position.z, 0.0)); - hit.world_position = scm::math::vec3(transformed.x, transformed.y, transformed.z); - } - } - } + Ray object_ray(ori, dir, world_ray.t_max_); + geometry->ray_test(object_ray, options, this, hits); - if (options & PickResult::GET_WORLD_NORMALS) { + float const inf(std::numeric_limits::max()); - math::mat4 normal_matrix(scm::math::inverse(scm::math::transpose(world_transform))); - for (auto& hit: hits) { - if (hit.world_normal == math::vec3(inf, inf, inf)) { - auto transformed(normal_matrix * math::vec4(hit.normal.x, hit.normal.y, hit.normal.z, 0.0)); - hit.world_normal = scm::math::normalize(scm::math::vec3(transformed.x, transformed.y, transformed.z)); - } - } - } + if (options & PickResult::GET_WORLD_POSITIONS) { + + for (auto& hit: hits) { + if (hit.world_position == math::vec3(inf, inf, inf)) { + auto transformed(world_transform * math::vec4(hit.position.x, hit.position.y, hit.position.z, 0.0)); + hit.world_position = scm::math::vec3(transformed.x, transformed.y, transformed.z); + } } + } + + if (options & PickResult::GET_WORLD_NORMALS) { + + math::mat4 normal_matrix(scm::math::inverse(scm::math::transpose(world_transform))); + for (auto& hit: hits) { + if (hit.world_normal == math::vec3(inf, inf, inf)) { + auto transformed(normal_matrix * math::vec4(hit.normal.x, hit.normal.y, hit.normal.z, 0.0)); + hit.world_normal = scm::math::normalize(scm::math::vec3(transformed.x, transformed.y, transformed.z)); + } + } + } } } + } - for (auto child : get_children()) { - // test for intersection with each child - child->ray_test_impl(ray, options, mask, hits); - } + for (auto child : get_children()) { + // test for intersection with each child + child->ray_test_impl(ray, options, mask, hits); + } } std::shared_ptr GeometryNode::copy() const { - return std::make_shared(get_name(), data, get_transform()); + return std::make_shared(get_name(), geometry_, material_, get_transform()); } } diff --git a/src/gua/scenegraph/ViewNode.cpp b/src/gua/scenegraph/LODNode.cpp similarity index 79% rename from src/gua/scenegraph/ViewNode.cpp rename to src/gua/scenegraph/LODNode.cpp index b6b31a319..d855e7a81 100644 --- a/src/gua/scenegraph/ViewNode.cpp +++ b/src/gua/scenegraph/LODNode.cpp @@ -20,26 +20,25 @@ ******************************************************************************/ // class header -#include +#include // guacamole headers -#include #include namespace gua { -ViewNode::ViewNode(std::string const& name, - Configuration const& configuration, - math::mat4 const& transform) - : Node(name, transform), data(configuration) {} +LODNode::LODNode(std::string const& name, Configuration const& configuration, math::mat4 const& transform) + : TransformNode(name, transform), data(configuration) {} -/* virtual */ void ViewNode::accept(NodeVisitor& visitor) { + +/* virtual */ void LODNode::accept(NodeVisitor& visitor) { visitor.visit(this); } -std::shared_ptr ViewNode::copy() const { - return std::make_shared(get_name(), data, get_transform()); +std::shared_ptr LODNode::copy() const { + return std::make_shared(get_name(), data, get_transform()); } + } diff --git a/src/gua/scenegraph/RayNode.cpp b/src/gua/scenegraph/RayNode.cpp index cc892c32b..9d96ef99e 100644 --- a/src/gua/scenegraph/RayNode.cpp +++ b/src/gua/scenegraph/RayNode.cpp @@ -43,8 +43,7 @@ RayNode::RayNode(std::string const& name, math::mat4 const& transform) std::pair RayNode::intersect( math::BoundingBox const& box) const { - - return get_world_ray().intersect(box); + return ::gua::intersect(get_world_ray(), box); } Ray const RayNode::get_world_ray() const { diff --git a/src/gua/scenegraph/SceneGraph.cpp b/src/gua/scenegraph/SceneGraph.cpp index e104b627c..1f9ffe18c 100644 --- a/src/gua/scenegraph/SceneGraph.cpp +++ b/src/gua/scenegraph/SceneGraph.cpp @@ -24,7 +24,7 @@ // guacamole headers #include -#include +#include #include #include #include @@ -36,7 +36,7 @@ namespace gua { SceneGraph::SceneGraph(std::string const& name) - : root_(new GroupNode("/", math::mat4::identity())), + : root_(new TransformNode("/", math::mat4::identity())), name_(name) {} SceneGraph::SceneGraph(SceneGraph const& graph) diff --git a/include/gua/renderer/SerializedNode.hpp b/src/gua/scenegraph/SunLightNode.cpp similarity index 61% rename from include/gua/renderer/SerializedNode.hpp rename to src/gua/scenegraph/SunLightNode.cpp index fd3dec3e4..730fb9fc9 100644 --- a/include/gua/renderer/SerializedNode.hpp +++ b/src/gua/scenegraph/SunLightNode.cpp @@ -19,49 +19,35 @@ * * ******************************************************************************/ -#ifndef GUA_SERIALIZED_NODE_HPP -#define GUA_SERIALIZED_NODE_HPP +// class header +#include -// guacamole headers -#include +// guacamole header +#include +#include +#include +#include namespace gua { -/** - * Stores information on a light for rendering. - * - * This is a struct used for serializing the graph. - * - * essentially the same as a std::pair - */ -template struct SerializedNode { +SunLightNode::SunLightNode(std::string const& name, + Configuration const& configuration, + math::mat4 const& transform) + : Node(name, transform), data(configuration) {} - SerializedNode() : transform(math::mat4::identity()), data() {} - - /** - * Constructor. - * - * This creates a new serialized node. - * - * \param transform The global transformation of this node. - * \param color The color of the light. - */ - SerializedNode(math::mat4 const& t, configuration_type const& d) - : transform(t), data(d) {} - - /** - * The global transformation of this node. - */ - math::mat4 transform; - configuration_type data; -}; +/* virtual */ void SunLightNode::accept(NodeVisitor& visitor) { + visitor.visit(this); +} -template -inline SerializedNode make_serialized_node(math::mat4 const& t, T const& d) -{ - return SerializedNode(t, d); +void SunLightNode::update_bounding_box() const { + bounding_box_ = math::BoundingBox( + math::vec3(std::numeric_limits::lowest()), + math::vec3(std::numeric_limits::max()) + ); } +std::shared_ptr SunLightNode::copy() const { + return std::make_shared(get_name(), data, get_transform()); } -#endif // GUA_SERIALIZED_NODE_HPP +} diff --git a/src/gua/scenegraph/GroupNode.cpp b/src/gua/scenegraph/TransformNode.cpp similarity index 84% rename from src/gua/scenegraph/GroupNode.cpp rename to src/gua/scenegraph/TransformNode.cpp index 96e076abb..d45af39a0 100644 --- a/src/gua/scenegraph/GroupNode.cpp +++ b/src/gua/scenegraph/TransformNode.cpp @@ -20,23 +20,23 @@ ******************************************************************************/ // class header -#include +#include // guacamole headers #include namespace gua { -GroupNode::GroupNode(std::string const& name, math::mat4 const& transform) +TransformNode::TransformNode(std::string const& name, math::mat4 const& transform) : Node(name, transform) {} -/* virtual */ void GroupNode::accept(NodeVisitor& visitor) { +/* virtual */ void TransformNode::accept(NodeVisitor& visitor) { visitor.visit(this); } -std::shared_ptr GroupNode::copy() const { - return std::make_shared(get_name(), get_transform()); +std::shared_ptr TransformNode::copy() const { + return std::make_shared(get_name(), get_transform()); } } diff --git a/src/gua/scenegraph/VolumeNode.cpp b/src/gua/scenegraph/VolumeNode.cpp new file mode 100644 index 000000000..1dd31b311 --- /dev/null +++ b/src/gua/scenegraph/VolumeNode.cpp @@ -0,0 +1,83 @@ +/****************************************************************************** + * guacamole - delicious VR * + * * + * Copyright: (c) 2011-2013 Bauhaus-Universität Weimar * + * Contact: felix.lauer@uni-weimar.de / simon.schneegans@uni-weimar.de * + * * + * This program is free software: you can redistribute it and/or modify it * + * under the terms of the GNU General Public License as published by the Free * + * Software Foundation, either version 3 of the License, or (at your option) * + * any later version. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * + * for more details. * + * * + * You should have received a copy of the GNU General Public License along * + * with this program. If not, see . * + * * + ******************************************************************************/ + +// class header +#include + +// guacamole headers +#include +#include +#include +#include +#include +#include + +namespace gua { + + ///////////////////////////////////////////////////////////////////////////// + + VolumeNode::VolumeNode(std::string const& name, + Configuration const& configuration, + math::mat4 const& transform) + : Node(name, transform), data(configuration) {} + + ///////////////////////////////////////////////////////////////////////////// + + /* virtual */ void VolumeNode::accept(NodeVisitor& visitor) { + visitor.visit(this); + } + + ///////////////////////////////////////////////////////////////////////////// + + void VolumeNode::update_bounding_box() const { + + if (data.get_volume() != "") { + + auto geometry_bbox(GeometryDatabase::instance()->lookup(data.get_volume())->get_bounding_box()); + bounding_box_ = transform(geometry_bbox, world_transform_); + + for (auto child : get_children()) { + bounding_box_.expandBy(child->get_bounding_box()); + } + } else { + Node::update_bounding_box(); + } + } + + ///////////////////////////////////////////////////////////////////////////// + + void VolumeNode::ray_test_impl(RayNode const& ray, PickResult::Options options, + Mask const& mask, std::set& hits) { + + // first of all, check bbox + auto box_hits(ray.intersect(bounding_box_)); + + return; + + } + + ///////////////////////////////////////////////////////////////////////////// + + std::shared_ptr VolumeNode::copy() const { + return std::make_shared(get_name(), data, get_transform()); + } + +} // namespace gua diff --git a/src/gua/utils/Color3f.cpp b/src/gua/utils/Color3f.cpp index 0aec2f4cc..50ba297cb 100644 --- a/src/gua/utils/Color3f.cpp +++ b/src/gua/utils/Color3f.cpp @@ -179,6 +179,13 @@ Color3f operator-(Color3f const& lhs, Color3f const& rhs) { return result; } +bool operator==(Color3f const& lhs, Color3f const& rhs) { + return lhs.r() == rhs.r() && + lhs.g() == rhs.g() && + lhs.b() == rhs.b(); + +} + std::ostream& operator<<(std::ostream& os, Color3f const& color) { os << color.r() << " " << color.g() << " " << color.b() << std::endl; return os; diff --git a/src/gua/utils/DotGenerator.cpp b/src/gua/utils/DotGenerator.cpp index 072025dd9..83c8fdb83 100644 --- a/src/gua/utils/DotGenerator.cpp +++ b/src/gua/utils/DotGenerator.cpp @@ -24,9 +24,9 @@ // guacamole headers #include -#include -#include +#include #include +#include #include #include #include @@ -82,7 +82,7 @@ void DotGenerator::parse_graph(SceneGraph const* graph) { } //////////////////////////////////////////////////////////////////////////////// -/* virtual */ void DotGenerator::visit(GroupNode* cam) { +/* virtual */ void DotGenerator::visit(TransformNode* cam) { pre_node_info(cam); std::string fillcolor("[fillcolor ="); @@ -96,36 +96,40 @@ void DotGenerator::parse_graph(SceneGraph const* graph) { } //////////////////////////////////////////////////////////////////////////////// -/* virtual */ void DotGenerator::visit(ViewNode* cam) { - pre_node_info(cam); +/* virtual */ void DotGenerator::visit(GeometryNode* geometry) { + pre_node_info(geometry); std::string fillcolor("[fillcolor ="); - fillcolor += " \"#AAFFAA\""; + fillcolor += " \"#CCCCCC\""; + if (geometry->get_geometry() != "") + parse_data_ += "| geometry: " + geometry->get_geometry(); + if (geometry->get_material() != "") + parse_data_ += "| material: " + geometry->get_material(); + fillcolor += "]"; - post_node_info(cam, fillcolor); + post_node_info(geometry, fillcolor); - for (auto child : cam->children_) + for (auto child : geometry->children_) child->accept(*this); } + //////////////////////////////////////////////////////////////////////////////// -/* virtual */ void DotGenerator::visit(GeometryNode* geometry) { - pre_node_info(geometry); +/* virtual */ void DotGenerator::visit(VolumeNode* volume) { + pre_node_info(volume); - std::string fillcolor("[fillcolor ="); - fillcolor += " \"#CCCCCC\""; - if (geometry->data.get_geometry() != "") - parse_data_ += "| geometry: " + geometry->data.get_geometry(); - if (geometry->data.get_material() != "") - parse_data_ += "| material: " + geometry->data.get_material(); + std::string fillcolor("[fillcolor ="); + fillcolor += " \"#CCEECC\""; + if (volume->data.get_volume() != "") + parse_data_ += "| volume: " + volume->data.get_volume(); - fillcolor += "]"; + fillcolor += "]"; - post_node_info(geometry, fillcolor); + post_node_info(volume, fillcolor); - for (auto child : geometry->children_) - child->accept(*this); + for (auto child : volume->children_) + child->accept(*this); } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/gua/utils/KDTree.cpp b/src/gua/utils/KDTree.cpp index 56311b327..7525afcd8 100644 --- a/src/gua/utils/KDTree.cpp +++ b/src/gua/utils/KDTree.cpp @@ -340,16 +340,21 @@ void KDTree::intersect_all(KDNode* node, if (intersection < Ray::END) { float const inf(std::numeric_limits::max()); - math::vec3 position(inf, inf, inf), normal(inf, inf, inf); + math::vec3 position(inf, inf, inf), + world_position(inf, inf, inf), + normal(inf, inf, inf), + world_normal(inf, inf, inf); math::vec2 tex_coords; if (options & PickResult::GET_POSITIONS + || options & PickResult::GET_WORLD_POSITIONS || options & PickResult::INTERPOLATE_NORMALS || options & PickResult::GET_TEXTURE_COORDS) { position = ray.origin_ + intersection * ray.direction_; } - if (options & PickResult::GET_NORMALS) { + if (options & PickResult::GET_NORMALS + || options & PickResult::GET_WORLD_NORMALS) { if (options & PickResult::INTERPOLATE_NORMALS) { normal = triangles[triangle.id_].get_normal_interpolated(mesh, position); @@ -364,8 +369,8 @@ void KDTree::intersect_all(KDNode* node, } hits.insert(PickResult(intersection, current_owner_, - position, position, - normal, normal, + position, world_position, + normal, world_normal, tex_coords)); } @@ -424,10 +429,10 @@ KDTree::LeafData::LeafData() : id_(-1), bbox_() {} KDTree::LeafData::LeafData(aiMesh* mesh, Triangle const & triangle, unsigned id) : id_(id), bbox_() { - for (auto i(0); i < 3; ++i) { - bbox_.expandBy(triangle.get_vertex(mesh, i)); - } + for (auto i(0); i < 3; ++i) { + bbox_.expandBy(triangle.get_vertex(mesh, i)); } +} KDTree::LeafData::LeafData(math::BoundingBox const & bbox, unsigned id) diff --git a/src/gua/utils/KDTreeUtils.cpp b/src/gua/utils/KDTreeUtils.cpp index 55d8afb26..3d9e33768 100644 --- a/src/gua/utils/KDTreeUtils.cpp +++ b/src/gua/utils/KDTreeUtils.cpp @@ -36,6 +36,33 @@ namespace gua { +namespace { + +// helper function to access mesh attributes +// no bounds checking! +// local to this translation unit +inline math::vec3 aiMesh_vertex(aiMesh* mesh, unsigned face, unsigned i) { + return math::vec3(mesh->mVertices[mesh->mFaces[face].mIndices[i]].x, + mesh->mVertices[mesh->mFaces[face].mIndices[i]].y, + mesh->mVertices[mesh->mFaces[face].mIndices[i]].z); +} + +inline math::vec3 aiMesh_normal(aiMesh* mesh, unsigned face, unsigned i) { + return math::vec3(mesh->mNormals[mesh->mFaces[face].mIndices[i]].x, + mesh->mNormals[mesh->mFaces[face].mIndices[i]].y, + mesh->mNormals[mesh->mFaces[face].mIndices[i]].z); +} + +inline math::vec2 aiMesh_texcoord(aiMesh* mesh, + unsigned face, + unsigned i, + unsigned j) { + return math::vec2(mesh->mTextureCoords[i][mesh->mFaces[face].mIndices[j]].x, + mesh->mTextureCoords[i][mesh->mFaces[face].mIndices[j]].y); +} + +} + // Ray ------------------------------------------------------------------------- const float Ray::END(std::numeric_limits::max()); @@ -45,11 +72,11 @@ Ray::Ray() : origin_(), direction_(), t_max_(-1.f) {} Ray::Ray(math::vec3 const& origin, math::vec3 const& direction, float t_max) : origin_(origin), direction_(direction), t_max_(t_max) {} -std::pair Ray::intersect( - math::BoundingBox const& box) const { +std::pair intersect(Ray const& ray, + math::BoundingBox const& box) { - math::vec3 t1((box.min - origin_) / direction_); - math::vec3 t2((box.max - origin_) / direction_); + math::vec3 t1((box.min - ray.origin_) / ray.direction_); + math::vec3 t2((box.max - ray.origin_) / ray.direction_); math::vec3 tmin1( std::min(t1[0], t2[0]), std::min(t1[1], t2[1]), std::min(t1[2], t2[2])); @@ -61,25 +88,25 @@ std::pair Ray::intersect( if (tmax >= tmin) { // there are two intersections - if (tmin > 0.0 && tmax < t_max_) + if (tmin > 0.0 && tmax < ray.t_max_) return std::make_pair(tmin, tmax); // there is only one intersection, the ray ends inside the box else if (tmin > 0.0) - return std::make_pair(tmin, END); + return std::make_pair(tmin, Ray::END); // there is only one intersection, the ray starts inside the box else - return std::make_pair(END, tmax); + return std::make_pair(Ray::END, tmax); } // there is no intersection - return std::make_pair(END, END); + return std::make_pair(Ray::END, Ray::END); } Ray const Ray::intersection(math::BoundingBox const& box) const { - auto hits(intersect(box)); + auto hits(intersect(*this,box)); // there are to hits -> clamp ray on both sides if (hits.first != END && hits.first != END) @@ -111,7 +138,7 @@ float Triangle::intersect(aiMesh* mesh, Ray const& ray) const { std::vector points(3); // math::vec3 normal(0, 0, 0); for (unsigned i = 0; i < 3; ++i) { - points[i] = get_vertex(mesh, i); + points[i] = aiMesh_vertex(mesh, face_id_, i); } // Find Triangle Normal @@ -164,17 +191,15 @@ float Triangle::intersect(aiMesh* mesh, Ray const& ray) const { math::vec3 Triangle::get_vertex(aiMesh* mesh, unsigned vertex_id) const { math::vec3 vertex; if (vertex_id < 3) { - vertex = math::vec3( - mesh->mVertices[mesh->mFaces[face_id_].mIndices[vertex_id]].x, - mesh->mVertices[mesh->mFaces[face_id_].mIndices[vertex_id]].y, - mesh->mVertices[mesh->mFaces[face_id_].mIndices[vertex_id]].z); + vertex = aiMesh_vertex(mesh,face_id_,vertex_id); } return vertex; } math::vec3 Triangle::get_normal(aiMesh* mesh) const { - math::vec3 normal; + math::vec3 normal(0, 0, 0); + if (mesh->HasNormals()) { for (unsigned i = 0; i < 3; ++i) { normal += math::vec3( @@ -182,29 +207,48 @@ math::vec3 Triangle::get_normal(aiMesh* mesh) const { mesh->mNormals[mesh->mFaces[face_id_].mIndices[i]].y, mesh->mNormals[mesh->mFaces[face_id_].mIndices[i]].z); } + + normal = scm::math::normalize(normal); } - return normal/3; + return normal; } -math::vec3 Triangle::get_normal_interpolated(aiMesh* mesh, math::vec3 const& position) const { - /// TODO: actually interpolate - return get_normal(mesh); +math::vec3 Triangle::get_normal_interpolated(aiMesh* mesh, + math::vec3 const& position) const { + math::vec3 normal(0, 0, 0); + + if (mesh->HasNormals()) { + normal = math::interpolate(position, + std::make_pair(aiMesh_vertex(mesh,face_id_,0), + aiMesh_normal(mesh,face_id_,0)), + std::make_pair(aiMesh_vertex(mesh,face_id_,1), + aiMesh_normal(mesh,face_id_,1)), + std::make_pair(aiMesh_vertex(mesh,face_id_,2), + aiMesh_normal(mesh,face_id_,2))); + normal = scm::math::normalize(normal); + } + + return normal; } -math::vec2 Triangle::get_texture_coords_interpolated(aiMesh* mesh, math::vec3 const& position) const { - /// TODO: actually interpolate - math::vec2 tex_coords; +math::vec2 Triangle::get_texture_coords_interpolated( + aiMesh* mesh, + math::vec3 const& position) const { + math::vec2 tex_coords(0, 0); + if (mesh->HasTextureCoords(0)) { - for (unsigned i = 0; i < 3; ++i) { - tex_coords += math::vec2( - mesh->mTextureCoords[0][mesh->mFaces[face_id_].mIndices[i]].x, - mesh->mTextureCoords[0][mesh->mFaces[face_id_].mIndices[i]].y); - } + tex_coords = math::interpolate(position, + std::make_pair(aiMesh_vertex(mesh,face_id_,0), + aiMesh_texcoord(mesh,face_id_,0,0)), + std::make_pair(aiMesh_vertex(mesh,face_id_,1), + aiMesh_texcoord(mesh,face_id_,0,1)), + std::make_pair(aiMesh_vertex(mesh,face_id_,2), + aiMesh_texcoord(mesh,face_id_,0,2)) + ); } - return tex_coords/3; + return tex_coords; } - } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 000000000..fcff287cb --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,14 @@ +find_package( UnitTest++ REQUIRED ) +include_directories ( + ../include + ${BOOST_INCLUDE_DIRS} + ${UNITTEST++_INCLUDE_DIR} + ) + +add_executable( runTests main.cpp testBoundingBox.cpp ) + +target_link_libraries( runTests + unittest++ + ${BOOST_LIBRARIES} + ${UNITTEST++_LIBRARIES} + )