diff --git a/.travis.yml b/.travis.yml index 687c7c43d..db9085fe4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,9 @@ env: # via the "travis encrypt" command using the project repo's public key - secure: "0ROQiFbsZo33ce2v5VjBxNljemh/HU70ntSSPygYwaDFymubts/62SixXVkbKNIFdrs3uYD6qeA/eMmpqXxLcs+PXNq5NrH7eSWw9oDIKMhq3NQH/IZLdRfXwihHimZ1qEs/TXyWlT2aC4rpBi1py3cJeTh1aBMlz4V/nm16iRAgc596ThNTuPDHa0F9/gZnwccI/Rr9VpiYn7vEBbuY9lYr43D0G3NuuQyvvlHShroH09fh6KyFOWIY38AQtnuVGNC1fIiAUk7TUqDqSBwhIrUV5saHbP0kca6DP32REkv//h4JwM76UHv+ntVEoK/UiztJHMkrw71gXYTyvIvlDBpT+IDoeIwUW2QFNQ5zJZI7FM8k0+oeK+F7k/mkffDzr1zww/PQoxqFBF0PoxAni/L9qkA4X2o1A6mRDbe9besp2LQG6Vniwj3bHpCId2QiiMrANVg0EAqkcL2mVFEaqZsh90qCkr1UDq4WQoYbXh0Fy3UnQpbuxDvCME8u03lwuv6ds/SBxc5cgKv7oWXgezaDg7/OCR+0lIAGuLqmNRD8Xw7a0WZGmSbYCHIZmeyFja2KuUvMiVCt8+QsyZr3e523DwBwnSj1BIYFRstMaSEJgu9B8rfTRRllOOKJXCQtdFVuGu8VI6PniSAkI6c535yOWzsuS8HwIkN2ll+Wn7E=" +language: cpp +cache: ccache + matrix: fast_finish: true include: @@ -12,14 +15,13 @@ matrix: dist: trusty language: cpp env: - # - CMAKECMD_ARGS="-DBUILD_OSG_EXAMPLES=ON -DBUILD_OSG_PLUGINS_BY_DEFAULT=ON -DBUILD_OSG_APPLICATIONS=ON" - - CMAKECMD_ARGS="-DBUILD_OSG_EXAMPLES=OFF -DBUILD_OSG_PLUGINS_BY_DEFAULT=ON -DBUILD_OSG_APPLICATIONS=ON" + - CMAKECMD_ARGS="-DBUILD_OSG_EXAMPLES=ON -DBUILD_OSG_PLUGINS_BY_DEFAULT=ON -DBUILD_OSG_APPLICATIONS=ON" + # - CMAKECMD_ARGS="-DBUILD_OSG_EXAMPLES=OFF -DBUILD_OSG_PLUGINS_BY_DEFAULT=ON -DBUILD_OSG_APPLICATIONS=ON" #- LLVM_VERSION=3.8 sudo: false cache: apt: true - directories: - - $HOME/.ccache + ccache: true compiler: #- clang - gcc @@ -29,8 +31,8 @@ matrix: name: "openscenegraph/OpenSceneGraph" description: "OpenSceneGraph build" notification_email: robert@openscenegraph.com - build_command_prepend: "cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_OSG_DEPRECATED_SERIALIZERS=OFF ." - build_command: "make -j 3" + build_command_prepend: "cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_OSG_DEPRECATED_SERIALIZERS=OFF -DBUILD_OSG_EXAMPLES=OFF ." + build_command: "make -j 4" branch_pattern: coverity_scan apt: sources: @@ -43,20 +45,23 @@ matrix: # OSX build - os: osx - language: cpp + before_install: + - brew update + install: + - brew install ccache + - export PATH="/usr/local/opt/ccache/libexec:$PATH" env: - CMAKECMD_ARGS="-DBUILD_OSG_EXAMPLES=OFF -DBUILD_OSG_PLUGINS_BY_DEFAULT=ON -DBUILD_OSG_APPLICATIONS=ON" - - os: osx - language: cpp - env: - - CMAKECMD_ARGS="-DBUILD_OSG_EXAMPLES=ON -DBUILD_OSG_PLUGINS_BY_DEFAULT=OFF -DBUILD_OSG_APPLICATIONS=OFF" -# script: -# - mkdir build -# - cd build -# - travis_wait 60 cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../product -DBUILD_OSG_EXAMPLES=ON .. -# - make install -j 3 + - os: osx + before_install: + - brew update + install: + - brew install ccache + - export PATH="/usr/local/opt/ccache/libexec:$PATH" + env: + - CMAKECMD_ARGS="-DBUILD_OSG_EXAMPLES=ON -DBUILD_OSG_PLUGINS_BY_DEFAULT=OFF -DBUILD_OSG_APPLICATIONS=OFF -DBUILD_OSG_DEPRECATED_SERIALIZERS=OFF" script: - if [ "${COVERITY_SCAN_BRANCH}" != 1 ]; then mkdir build && cd build && travis_wait 60 cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../product $CMAKECMD_ARGS ../ ; fi - - if [ -f CMakeCache.txt ]; then make -j3 ; fi + - if [ -f CMakeCache.txt ]; then make -j4 ; fi diff --git a/AUTHORS.txt b/AUTHORS.txt index 720da1a06..6bd66ef68 100644 --- a/AUTHORS.txt +++ b/AUTHORS.txt @@ -1,6 +1,6 @@ -OpenSceneGraph Library 3.5.7 +OpenSceneGraph Library 3.5.10 -566 Contributors: +568 Contributors: Firstname Surname ----------------- @@ -9,9 +9,9 @@ Stephan Huber Paul Martz Farshid Lashkari Mathias Fröhlich +Laurens Voerman Marco Jez Wang Rui -Laurens Voerman Jean-Sébastien Guay Ulrich Hertlein Mike Weiblen @@ -48,6 +48,7 @@ Magnus Kessler David Fries Tom Jolley Paul Melis +Jordi Torres Luc Frauciel Aurelien Albert Torben Dannhauer @@ -94,7 +95,6 @@ Fabien Lavignotte Thomas Hogarth Riccardo Corsi Melchior Franz -Jordi Torres Johannes Baeuerle Neil Hughes Martin Beckett @@ -111,6 +111,7 @@ Sondra Iverson Simon Julier Rune Schmidt Jensen Ravi Mathur +Ralf Habacker Rainer Oder Nico Kruithof Martin Aumueller @@ -126,7 +127,6 @@ Alexander Sinditskiy Vladimir Chebaev Thibault Genessay Sasa Bistrovic -Ralf Habacker Neil Groves Mikhail Izmestev Markus Trenkwalder @@ -145,6 +145,7 @@ Tanguy Fautr Sean Spicer Ryan Kawicki Richard Schmidt +Raymond de Vries Peter Hrenka Paul de Repentigny Nikolaus Hanekamp @@ -175,6 +176,7 @@ John Ivar Gustav Haapalahti Erik den Dekker Emmanuel Roche +Don Burns Domenico Mangieri Daniel Larimer Colin Dunlop @@ -226,7 +228,6 @@ Fabio Mierlo Doug McCorkle Donald Cipperly Don Leich -Don Burns Dietmar Funck Colin Cochran Christian Ruzicka @@ -254,7 +255,6 @@ Stephan Eilemann Stanislav Blinov Sergey Polischuk Roni Zanolli -Raymond de Vries Ralf Kern Piotr Gwiazdowski Pierre Haritchabalet @@ -362,6 +362,7 @@ Shuxing Xiao Shane Arnott Sergey Kurdakov Sebastien Kuntz +Sandro Mani Ruth Lang Ruben The Ruben Smelik @@ -538,6 +539,7 @@ Christian Noon Christian Kaser Christian Ehrlicher Chris McGlone +Chris Djali Carlos Garcea Bryce Eldridge Bruno Herbelin diff --git a/CMakeLists.txt b/CMakeLists.txt index 8f9645210..2bb3196b7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,3 +1,15 @@ +# +# OpenSceneGraph CMake build file +# +SET(OPENSCENEGRAPH_MAJOR_VERSION 3) +SET(OPENSCENEGRAPH_MINOR_VERSION 5) +SET(OPENSCENEGRAPH_PATCH_VERSION 10) +SET(OPENSCENEGRAPH_SOVERSION 153) + + +# set to 0 when not a release candidate, non zero means that any generated +# git tags will be treated as release candidates of given number +SET(OPENSCENEGRAPH_RELEASE_CANDIDATE 0) set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS TRUE) set_property(GLOBAL PROPERTY USE_FOLDERS ON) @@ -113,15 +125,6 @@ ENDIF() PROJECT(OpenSceneGraph) -SET(OPENSCENEGRAPH_MAJOR_VERSION 3) -SET(OPENSCENEGRAPH_MINOR_VERSION 5) -SET(OPENSCENEGRAPH_PATCH_VERSION 7) -SET(OPENSCENEGRAPH_SOVERSION 150) - -# set to 0 when not a release candidate, non zero means that any generated -# git tags will be treated as release candidates of given number -SET(OPENSCENEGRAPH_RELEASE_CANDIDATE 0) - SET(OPENSCENEGRAPH_VERSION ${OPENSCENEGRAPH_MAJOR_VERSION}.${OPENSCENEGRAPH_MINOR_VERSION}.${OPENSCENEGRAPH_PATCH_VERSION}) SET(OSG_PLUGINS osgPlugins-${OPENSCENEGRAPH_VERSION}) @@ -341,6 +344,10 @@ ENDIF() IF(WIN32 AND NOT ANDROID) + # Check window version + INCLUDE (OsgDetermineWinVersion) + get_WIN32_WINNT(WIN_VERSION) + ADD_DEFINITIONS(-D_WIN32_WINNT=${WIN_VERSION}) IF(MSVC) # This option is to enable the /MP switch for Visual Studio 2005 and above compilers @@ -468,6 +475,10 @@ OPTION(OSG_PROVIDE_READFILE "Set to ON for include/osgDB/ReadFile to provide the OPTION(OSG_USE_REF_PTR_IMPLICIT_OUTPUT_CONVERSION "Set to ON to use the ref_ptr<> T* operator() output conversion. " ON) OPTION(OSG_USE_REF_PTR_SAFE_DEREFERENCE "Set to ON to throw an exception whenever ref_ptr<> is dereferenced or called. " OFF) +OPTION(OSG_ENVVAR_SUPPORTED "Set to ON to build OpenSceneGraph with the OSG_ENVVAR_SUPPOERTED #define enabled to enable use of getenv() related functions." ON) + + + # Map the OPENGL_PROFILE to OSG_GL*_AVAILABLE settings SET(OPENGL_PROFILE "GL2" CACHE STRING "OpenGL Profile to use, choose from GL1, GL2, GL3, GLES1, GLES2, GLES3") @@ -738,6 +749,7 @@ IF(ANDROID) ELSE() # Common to all platforms except android: FIND_PACKAGE(Freetype) + FIND_PACKAGE(ilmbase) FIND_PACKAGE(Inventor) FIND_PACKAGE(Jasper) FIND_PACKAGE(OpenEXR) diff --git a/CMakeModules/FindFBX.cmake b/CMakeModules/FindFBX.cmake index ab0a2c2d8..b2f2ac1cb 100644 --- a/CMakeModules/FindFBX.cmake +++ b/CMakeModules/FindFBX.cmake @@ -60,9 +60,13 @@ SET(FBX_LIBNAME_DEBUG ${FBX_LIBNAME}d) SET( FBX_SEARCH_PATHS $ENV{FBX_DIR} + "$ENV{ProgramW6432}/Autodesk/FBX/FBX SDK/2018.1.1" + "$ENV{PROGRAMFILES}/Autodesk/FBX/FBX SDK/2018.1.1" "$ENV{ProgramW6432}/Autodesk/FBX/FBX SDK/2017.1" "$ENV{PROGRAMFILES}/Autodesk/FBX/FBX SDK/2017.1" "/Applications/Autodesk/FBX SDK/2017.1" + "$ENV{ProgramW6432}/Autodesk/FBX/FBX SDK/2016.1.2" + "$ENV{PROGRAMFILES}/Autodesk/FBX/FBX SDK/2016.1.2" "$ENV{ProgramW6432}/Autodesk/FBX/FBX SDK/2016.1.1" "$ENV{PROGRAMFILES}/Autodesk/FBX/FBX SDK/2016.1.1" "$ENV{ProgramW6432}/Autodesk/FBX/FBX SDK/2015.1" diff --git a/CMakeModules/FindLIBLAS.cmake b/CMakeModules/FindLIBLAS.cmake index 5b2236cb4..1c9a7ee01 100644 --- a/CMakeModules/FindLIBLAS.cmake +++ b/CMakeModules/FindLIBLAS.cmake @@ -94,14 +94,12 @@ macro(FIND_LIBLAS_LIBRARY MYLIBRARY MYLIBRARYNAME) endmacro(FIND_LIBLAS_LIBRARY LIBRARY LIBRARYNAME) FIND_LIBLAS_LIBRARY(LIBLAS_LIBRARY las) -FIND_LIBLAS_LIBRARY(LIBLASC_LIBRARY las_c) set(LIBLAS_FOUND "NO") -if(LIBLAS_LIBRARY AND LIBLASC_LIBRARY AND LIBLAS_INCLUDE_DIR) - +if(LIBLAS_LIBRARY AND LIBLAS_INCLUDE_DIR) FIND_PACKAGE(Boost) # used by LIBLAS if(Boost_FOUND) - set(LIBLAS_LIBRARIES ${LIBLAS_LIBRARY} ${LIBLASC_LIBRARY} ) + set(LIBLAS_LIBRARIES ${LIBLAS_LIBRARY} ) set(LIBLAS_FOUND "YES") endif() endif() diff --git a/CMakeModules/FindOpenEXR.cmake b/CMakeModules/FindOpenEXR.cmake index 743df98fb..233be972b 100644 --- a/CMakeModules/FindOpenEXR.cmake +++ b/CMakeModules/FindOpenEXR.cmake @@ -28,7 +28,7 @@ FIND_PATH(OPENEXR_INCLUDE_DIR OpenEXR/ImfIO.h # example: OPENEXR_FIND_VAR(OPENEXR_IlmImf_LIBRARY IlmImf) MACRO(OPENEXR_FIND_VAR varname libname) FIND_LIBRARY( ${varname} - NAMES ${libname} + NAMES ${libname} ${libname}-2_1 ${libname}-2_2 PATHS $ENV{OPENEXR_DIR}/lib $ENV{OPENEXR_DIR} @@ -52,13 +52,10 @@ MACRO(OPENEXR_FIND libname) ENDMACRO(OPENEXR_FIND) OPENEXR_FIND(IlmImf) -OPENEXR_FIND(IlmThread) -OPENEXR_FIND(Iex) -OPENEXR_FIND(Half) SET(OPENEXR_FOUND "NO") -IF(OPENEXR_INCLUDE_DIR AND OPENEXR_IlmImf_LIBRARY AND OPENEXR_IlmThread_LIBRARY AND OPENEXR_Iex_LIBRARY AND OPENEXR_Half_LIBRARY) - SET(OPENEXR_LIBRARIES ${OPENEXR_IlmImf_LIBRARY} ${OPENEXR_IlmThread_LIBRARY} ${OPENEXR_Half_LIBRARY} ${OPENEXR_Iex_LIBRARY} ) - SET(OPENEXR_LIBRARIES_VARS OPENEXR_IlmImf_LIBRARY OPENEXR_IlmThread_LIBRARY OPENEXR_Half_LIBRARY OPENEXR_Iex_LIBRARY ) +IF(OPENEXR_INCLUDE_DIR AND OPENEXR_IlmImf_LIBRARY) + SET(OPENEXR_LIBRARIES ${OPENEXR_IlmImf_LIBRARY} ) + SET(OPENEXR_LIBRARIES_VARS OPENEXR_IlmImf_LIBRARY ) SET(OPENEXR_FOUND "YES") -ENDIF(OPENEXR_INCLUDE_DIR AND OPENEXR_IlmImf_LIBRARY AND OPENEXR_IlmThread_LIBRARY AND OPENEXR_Iex_LIBRARY AND OPENEXR_Half_LIBRARY) +ENDIF(OPENEXR_INCLUDE_DIR AND OPENEXR_IlmImf_LIBRARY) diff --git a/CMakeModules/Findilmbase.cmake b/CMakeModules/Findilmbase.cmake new file mode 100644 index 000000000..4b076c7c9 --- /dev/null +++ b/CMakeModules/Findilmbase.cmake @@ -0,0 +1,63 @@ +# Locate ILMBASE +# This module defines +# ILMBASE_LIBRARY +# ILMBASE_FOUND, if false, do not try to link to ILMBASE +# ILMBASE_INCLUDE_DIR, where to find the headers +# +# $ILMBASE_DIR is an environment variable that would +# correspond to the ./configure --prefix=$ILMBASE_DIR +# +# Created by Robert Osfield. + + +FIND_PATH(ILMBASE_INCLUDE_DIR OpenEXR/ImathVec.h + $ENV{ILMBASE_DIR}/include + $ENV{ILMBASE_DIR} + ~/Library/Frameworks + /Library/Frameworks + /usr/local/include + /usr/include + /sw/include # Fink + /opt/local/include # DarwinPorts + /opt/csw/include # Blastwave + /opt/include + /usr/freeware/include +) + +# Macro to find ilmbase libraries +# example: ILMBASE_FIND_VAR(OPENEXR_IlmThread_LIBRARY IlmThread) +MACRO(ILMBASE_FIND_VAR varname libname) + FIND_LIBRARY( ${varname} + NAMES ${libname} ${libname}-2_1 ${libname}-2_2 + PATHS + $ENV{ILMBASE_DIR}/lib + $ENV{ILMBASE_DIR} + ~/Library/Frameworks + /Library/Frameworks + /usr/local/lib + /usr/lib + /sw/lib + /opt/local/lib + /opt/csw/lib + /opt/lib + /usr/freeware/lib64 + ) +ENDMACRO(ILMBASE_FIND_VAR) + +# Macro to find exr libraries (and debug versions) +# example: ILMBASE_FIND(OPENEXR_IlmThread_LIBRARY IlmThread) +MACRO(ILMBASE_FIND libname) + ILMBASE_FIND_VAR(ILMBASE_${libname}_LIBRARY ${libname}) + ILMBASE_FIND_VAR(ILMBASE_${libname}_LIBRARY_DEBUG ${libname}d) +ENDMACRO(ILMBASE_FIND) + +ILMBASE_FIND(IlmThread) +ILMBASE_FIND(Iex) +ILMBASE_FIND(Half) + +SET(ILMBASE_FOUND "NO") +IF(ILMBASE_INCLUDE_DIR AND ILMBASE_IlmThread_LIBRARY AND ILMBASE_Iex_LIBRARY AND ILMBASE_Half_LIBRARY) + SET(ILMBASE_LIBRARIES ${ILMBASE_IlmThread_LIBRARY} ${ILMBASE_Half_LIBRARY} ${ILMBASE_Iex_LIBRARY} ) + SET(ILMBASE_LIBRARIES_VARS ILMBASE_IlmThread_LIBRARY ILMBASE_Half_LIBRARY ILMBASE_Iex_LIBRARY ) + SET(ILMBASE_FOUND "YES") +ENDIF(ILMBASE_INCLUDE_DIR AND ILMBASE_IlmThread_LIBRARY AND ILMBASE_Iex_LIBRARY AND ILMBASE_Half_LIBRARY) diff --git a/CMakeModules/OsgDetermineWinVersion.cmake b/CMakeModules/OsgDetermineWinVersion.cmake new file mode 100644 index 000000000..9d7a0619d --- /dev/null +++ b/CMakeModules/OsgDetermineWinVersion.cmake @@ -0,0 +1,22 @@ +# - If Windows is used, this script sets the variable WIN32_WINNT to the corresponding windows version + +if (WIN32) + message(STATUS "Checking windows version...") + macro(get_WIN32_WINNT version) + if (CMAKE_SYSTEM_VERSION) + set(ver ${CMAKE_SYSTEM_VERSION}) + string(REGEX MATCH "^([0-9]+).([0-9])" ver ${ver}) + string(REGEX MATCH "^([0-9]+)" verMajor ${ver}) + # Check for Windows 10, b/c we'll need to convert to hex 'A'. + if ("${verMajor}" MATCHES "10") + set(verMajor "A") + string(REGEX REPLACE "^([0-9]+)" ${verMajor} ver ${ver}) + endif ("${verMajor}" MATCHES "10") + # Remove all remaining '.' characters. + string(REPLACE "." "" ver ${ver}) + # Prepend each digit with a zero. + string(REGEX REPLACE "([0-9A-Z])" "0\\1" ver ${ver}) + set(${version} "0x${ver}") + endif(CMAKE_SYSTEM_VERSION) + endmacro(get_WIN32_WINNT) +endif(WIN32) diff --git a/ChangeLog b/ChangeLog index 277fa4301..0564cefef 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,1660 @@ +Sun, 3 Dec 2017 11:17:34 +0000 +Author : Robert Osfield +Renamed chanels to array to be consistent with the rest of the usage + +Sun, 3 Dec 2017 11:12:20 +0000 +Author : OpenSceneGraph git repository +Merge pull request #398 from marchelbling/sharedarrayoptimizer-fixImprove SharedArrayOptimizer + +Sun, 3 Dec 2017 10:49:39 +0000 +Author : Robert Osfield +Removed redundent !ps + +Sun, 3 Dec 2017 09:49:09 +0000 +Author : Robert Osfield +Removed unused local variable and associated typedef + +Sun, 3 Dec 2017 09:45:37 +0000 +Author : Robert Osfield +Quietened down cppcheck false positive. + +Sun, 3 Dec 2017 09:38:32 +0000 +Author : Robert Osfield +Fixed leak and clean up formatting. + +Sun, 3 Dec 2017 09:34:43 +0000 +Author : Robert Osfield +From Jordi Torres, fixed leak and inappropriate read bug + +Sun, 3 Dec 2017 09:32:50 +0000 +Author : Robert Osfield +From Jordi Torres, removed unused local variable + +Sun, 3 Dec 2017 09:30:35 +0000 +Author : Robert Osfield +From Jordi Torres, fix indentation and removed redundent break; + +Sun, 3 Dec 2017 09:27:41 +0000 +Author : Robert Osfield +From Jordi Torres, added ref_ptr<> usage to quieten cppcheck false positive + +Sat, 2 Dec 2017 18:07:13 +0000 +Author : Robert Osfield +From Jordi Torres, removed unused local variables + +Sat, 2 Dec 2017 18:04:43 +0000 +Author : Robert Osfield +From Jordi Torres, removed unused local variables + +Sat, 2 Dec 2017 18:00:03 +0000 +Author : Robert Osfield +From Jordi Torres, Removed unused local variables + +Sat, 2 Dec 2017 17:58:17 +0000 +Author : Robert Osfield +From Jordi Torres, removed unused local variables + +Sat, 2 Dec 2017 17:52:47 +0000 +Author : Robert Osfield +From Jordi Torres, removed unused local variables + +Sat, 2 Dec 2017 17:42:53 +0000 +Author : Robert Osfield +Commented out unused local variables + +Sat, 2 Dec 2017 17:41:27 +0000 +Author : Robert Osfield +From Jordi Torres, removed unused local variable + +Sat, 2 Dec 2017 17:35:36 +0000 +Author : Robert Osfield +Fixed string parsing and substituion bugs isn substitudeEnvVars(..) + +Sat, 2 Dec 2017 17:08:14 +0000 +Author : Robert Osfield +From Jordi Torres, removed unused local variables + +Sat, 2 Dec 2017 16:49:47 +0000 +Author : Jordi Torres +same values in || so one of them not needed + +Sat, 2 Dec 2017 16:35:16 +0000 +Author : Robert Osfield +Improved readaibility of text by removing redundent indirection. + +Sat, 2 Dec 2017 16:20:34 +0000 +Author : Robert Osfield +Fixes for cppcheck reported issues + +Fri, 1 Dec 2017 12:26:00 +0100 +Author : Marc Helbling +Improve SharedArrayOptimizerWhen an array is shared within and outside a geometry, it's still worth it and safe +to recreate the reference within each individual geometry. + + +Thu, 30 Nov 2017 14:13:21 +0000 +Author : OpenSceneGraph git repository +Merge pull request #396 from bjornblissing/feature/DPIAwareScalingApplications declared as DPI-aware in the Windows environment + +Thu, 30 Nov 2017 14:12:05 +0000 +Author : OpenSceneGraph git repository +Added return to last line + +Thu, 30 Nov 2017 12:48:47 +0000 +Author : Robert Osfield +Quieted down dubug output + +Thu, 30 Nov 2017 13:00:54 +0100 +Author : Björn Blissing +Applications declared DPI-aware in the Windows environmentApplications that run on a Windows computer with desktop scaling enabled +gets scaled incorrectly since windows assumes that applications are +DPI-unaware unless declared otherwise. + +This change declares the application DPI-aware, thus not automatically +scaled by the operating system. + +The corresponding library call requires Windows 8.1 or later. + + +Thu, 30 Nov 2017 12:53:24 +0100 +Author : Björn Blissing +Added script to identify Windows versionAdded script to identify the Windows version used to compile the source. +Currently the windows version for Windows NT is hard coded into the +source. By running this CMake script the _WIN32_WINNT preprocessor +variable gets set to the corresponding windows version. + + +Thu, 30 Nov 2017 12:47:57 +0100 +Author : Björn Blissing +Removed unnecessary define in FileUtilsThe define of _WIN32_WINNT was added to handle an error case from MinGW +,as described in commit 712ca432196cd797cc3c265adb2847465551461f + +This was later giving warnings and thus undefined for MinGW by commit +3bf6fb1778687c45d389b91675b55f709ef1f67b + +Since the two operations cancel each other out, they should be removed. + + +Wed, 29 Nov 2017 21:20:10 +0000 +Author : Robert Osfield +Typo fix + +Wed, 29 Nov 2017 15:06:53 +0000 +Author : Robert Osfield +Update version to 3.5.10 + +Wed, 29 Nov 2017 14:49:00 +0000 +Author : Robert Osfield +Updated ChangeLog and AUTHORS for 3.5.9 dev release + +Wed, 29 Nov 2017 14:44:00 +0000 +Author : Robert Osfield +Fixed build with OSG_USE_REF_PTR_IMPLICIT_OUTPUT_CONVERSION set to OFF + +Wed, 29 Nov 2017 14:22:31 +0000 +Author : Robert Osfield +Introduced Drawable::CreateVertexArrayStateCallback to enable customization of how VertexArrayState objects.Added public accessors to the Drawable::VertexArrayStateList. + + +Wed, 29 Nov 2017 12:22:03 +0000 +Author : Robert Osfield +Added mapping of GLSL file extension to shader Type. + +Wed, 29 Nov 2017 10:40:42 +0000 +Author : Robert Osfield +Merge branch 'master' of https://github.com/openscenegraph/OpenSceneGraph + +Wed, 29 Nov 2017 10:40:20 +0000 +Author : Robert Osfield +Bummped the SO version + +Wed, 29 Nov 2017 10:38:52 +0000 +Author : OpenSceneGraph git repository +Merge pull request #394 from mathieu/masterMake the culling be disabled at the drawable level + +Wed, 29 Nov 2017 10:14:16 +0000 +Author : Robert Osfield +Merge branch 'mp3butcher-ComputeDispatch' + +Wed, 29 Nov 2017 10:11:35 +0000 +Author : Robert Osfield +Added back in serializer support for comput dispatch groups to retain backwards compatibility. + +Wed, 29 Nov 2017 11:05:53 +0100 +Author : Mathieu +Make the culling be disables at the drawable level not at the geode level + +Wed, 29 Nov 2017 09:30:56 +0000 +Author : Robert Osfield +Merge branch 'ComputeDispatch' of https://github.com/mp3butcher/OpenSceneGraph into mp3butcher-ComputeDispatch + +Wed, 29 Nov 2017 08:16:53 +0000 +Author : OpenSceneGraph git repository +Cleaned up code layout + +Wed, 29 Nov 2017 08:14:44 +0000 +Author : OpenSceneGraph git repository +Cleaned up code layout + +Wed, 29 Nov 2017 08:09:01 +0000 +Author : OpenSceneGraph git repository +Merge pull request #390 from filnet/readrefreplace more read*File() usage to readRef*File() + +Tue, 28 Nov 2017 20:31:09 +0100 +Author : Julien Valentin +override compile and createVAS in order to do nothing + +Tue, 28 Nov 2017 20:03:40 +0100 +Author : Julien Valentin +adapt SSBO example for ComputeDispatch but have strange runtime errors: 0(100) : error C7623: implicit narrowing of type from "vec3" to "float" 0(108) : error C7623: implicit narrowing of type from "vec3" to "float" + +Tue, 28 Nov 2017 19:51:31 +0100 +Author : Philippe Renon +replace more read*File() usage to readRef*File() + +Tue, 28 Nov 2017 18:08:08 +0000 +Author : Robert Osfield +Quietened down debug output + +Tue, 28 Nov 2017 18:05:59 +0000 +Author : Robert Osfield +Quietened down debug output + +Tue, 28 Nov 2017 18:04:26 +0000 +Author : Robert Osfield +Quitened down debug output + +Tue, 28 Nov 2017 17:39:32 +0100 +Author : Julien Valentin +numgroup removed but introduce a reto compatibility bug in Program serializer hope nobody use it + +Tue, 28 Nov 2017 17:30:04 +0100 +Author : Julien Valentin +add ComputeDispatch class revoke glDispatch in PCProgram::useProgram update example + +Tue, 28 Nov 2017 15:31:39 +0000 +Author : Robert Osfield +To the GLSL shader plugin added support forL #pragma include shaderfile.glsl + +To enable easier reuse of shaders + + +Mon, 27 Nov 2017 18:38:37 +0000 +Author : Robert Osfield +Replaced deprecated osg::Shader::reaDShaderFile()/loadShaderFromSource() usage + +Mon, 27 Nov 2017 18:36:41 +0000 +Author : Robert Osfield +Merge branch 'master' of https://github.com/openscenegraph/OpenSceneGraph + +Mon, 27 Nov 2017 18:28:15 +0000 +Author : Robert Osfield +Deprecated the osg::Shader::reaDShaderFile() and osg::Shader::loadShaderSourceFromFile() methods. Programmers should use osgDB::readRefShaderFile()/readShaderFile() instead. + +Mon, 27 Nov 2017 18:27:13 +0000 +Author : Robert Osfield +Added support for .cs, .compute, .tctrlm .teval extensions in the GLSL plugin + +Mon, 27 Nov 2017 15:54:39 +0000 +Author : OpenSceneGraph git repository +Merge pull request #387 from jtorresfabra/remove_custom_codeRemoves custom code added for sketchfab channel compression that shou… + +Mon, 27 Nov 2017 15:44:11 +0000 +Author : Robert Osfield +Refactored the MergeGeometry::mergeGroup(..) method to avoid O(N^2) issue with using removeChildren() on groups with very large numbers of children. + +Mon, 27 Nov 2017 15:41:54 +0000 +Author : Robert Osfield +Replaced read*File() usage to readRef*File() + +Mon, 27 Nov 2017 15:40:21 +0000 +Author : Robert Osfield +Added template addShader() method to make it easier to pass ref_ptr + +Mon, 27 Nov 2017 15:48:50 +0100 +Author : Jordi +Removes custom code added for sketchfab channel compression that should not be there + +Mon, 27 Nov 2017 11:10:48 +0000 +Author : Robert Osfield +Fixes for building with OSG_PROVIDE_READFILE to OFF + +Mon, 27 Nov 2017 11:05:31 +0000 +Author : Robert Osfield +Fixed build issues when compiling with OSG_PROVIDE_READFILE to OFF + +Mon, 27 Nov 2017 10:32:02 +0000 +Author : Robert Osfield +Build fix + +Wed, 22 Nov 2017 11:05:17 +0000 +Author : Robert Osfield +Removed use of local static to avoid threading issue. + +Tue, 21 Nov 2017 14:01:14 +0000 +Author : OpenSceneGraph git repository +Merge pull request #383 from anormann1974/patch-1Fixed missing initialization of B_ and N_ in constructor + +Tue, 21 Nov 2017 13:59:51 +0000 +Author : Robert Osfield +Fixed typo + +Tue, 21 Nov 2017 13:41:57 +0000 +Author : Robert Osfield +Added Text::getCharacterCorners(...) method to help applications that want to find out the positions of characters being rendered. + +Tue, 21 Nov 2017 13:54:45 +0100 +Author : Andre Normann +Fixed missing initialization of B_ and N_ in constructor + +Mon, 20 Nov 2017 12:49:20 +0000 +Author : Robert Osfield +Moved the version to 3.5.9 and the version setting code to top of CMake file + +Tue, 14 Nov 2017 15:04:05 +0000 +Author : Robert Osfield +Updated ChangeLog and AUTHORS file for 3.5.8 dev release + +Tue, 14 Nov 2017 10:38:18 +0000 +Author : Raymond de Vries +attached fixes for configuring and building the osgPlugin exr with Visual Studio and using out-of-the-box builds of ilmbase and openexr, i.e. without manual/extra config for using these 2 libs with the OSG.Previously, the assumption was made that ilmbase and openexr were installed in a common directory and hence the header files and libs were both found in that common directory. That is not consistent with other libs and this submission makes it consistent and therefore the OSG configures out of the box. I made this work for ilmbase-2.1.0.tar.gz / openexr-2.1.0.tar.gz and ilmbase-2.2.0.tar.gz / openexr-2.2.0.tar.gz + + +Mon, 13 Nov 2017 13:08:39 +0000 +Author : Robert Osfield +Fixed typo + +Mon, 13 Nov 2017 13:06:12 +0000 +Author : Robert Osfield +Fixed CoverityScan reported errors + +Mon, 13 Nov 2017 12:49:33 +0000 +Author : Robert Osfield +FIxed two CoverityScan detected memory leaks + +Mon, 13 Nov 2017 10:24:31 +0000 +Author : Andre Normann +Attached is a fix in GLExtension, which is based on latest git version, that fixes the usage of uniform buffer objects on macOS. Under macOS core OpenGL features aren't exported as extension. OpenGL 3.1 includes the GL_ARB_uniform_buffer_object as core feature for example. On macOS a simple osg::isGLExtensionSupported() call would fail. It is required to use the isGLExtensionOrVersionSupported() method. This is what my fix does. + +Sat, 11 Nov 2017 14:50:55 +0000 +Author : Robert Osfield +Updated SO version to 152 to reflect the resent API changes to osgAnimation. + +Sat, 11 Nov 2017 14:43:10 +0000 +Author : OpenSceneGraph git repository +Merge pull request #382 from openscenegraph/osganimationOsganimation improvements + +Sat, 11 Nov 2017 13:27:43 +0000 +Author : OpenSceneGraph git repository +Build fix + +Sat, 11 Nov 2017 13:08:42 +0000 +Author : OpenSceneGraph git repository +Readbility improvements and updating version to 152 + +Sat, 11 Nov 2017 13:04:34 +0000 +Author : OpenSceneGraph git repository +Added versioning to the new serialization additions + +Sat, 11 Nov 2017 13:00:56 +0000 +Author : OpenSceneGraph git repository +Code readability improvements + +Sat, 11 Nov 2017 12:58:52 +0000 +Author : OpenSceneGraph git repository +Code readability improvements + +Sat, 11 Nov 2017 12:54:28 +0000 +Author : OpenSceneGraph git repository +Code readability improvements + +Sat, 11 Nov 2017 12:46:48 +0000 +Author : OpenSceneGraph git repository +Code readability improvement + +Sat, 11 Nov 2017 12:45:55 +0000 +Author : OpenSceneGraph git repository +Small readability improvements + +Sat, 11 Nov 2017 12:42:34 +0000 +Author : OpenSceneGraph git repository +Fix of incorrect Program assignment bug and coding style + +Sat, 11 Nov 2017 12:33:44 +0000 +Author : OpenSceneGraph git repository +coding style/readability fixes + +Sat, 11 Nov 2017 12:29:45 +0000 +Author : OpenSceneGraph git repository +coding style/readability fixes + +Sat, 11 Nov 2017 12:27:56 +0000 +Author : OpenSceneGraph git repository +coding style/readability fixes + +Sat, 11 Nov 2017 12:24:27 +0000 +Author : OpenSceneGraph git repository +coding style fix + +Sat, 11 Nov 2017 11:17:34 +0000 +Author : Robert Osfield +Restructed the ref counting of the rawImageRec structure so that it's done with a separate refImageRec struct so it doesn't interfer with the writing of the rawImageRec as a header when writing to .rgb + +Sat, 11 Nov 2017 10:19:09 +0000 +Author : Andreas Ekstrand +I have implemented readObject to make loading objects from SceneLoader in the LWS plugin work. I'm not sure about other implications from changes leading up to this problem (readRefFile instead of readNodeFile in SceneLoader) but this fix works for me. + +Fri, 10 Nov 2017 17:12:20 +0000 +Author : Robert Osfield +Fixed handling of GL_TEXTURE_CUBE_MAP when using glTextureStorage. + +Fri, 10 Nov 2017 17:00:52 +0000 +Author : OpenSceneGraph git repository +Merge pull request #381 from openscenegraph/revert-379-osganimbugfixRevert " following guidance from OpenGL Common Mistakes:" + +Fri, 10 Nov 2017 16:58:29 +0000 +Author : OpenSceneGraph git repository +Revert " following guidance from OpenGL Common Mistakes:" + +Fri, 10 Nov 2017 14:49:54 +0000 +Author : OpenSceneGraph git repository +Merge pull request #379 from mp3butcher/osganimbugfixFixed handling of mipmaps + +Fri, 10 Nov 2017 13:36:52 +0000 +Author : OpenSceneGraph git repository +Merge pull request #380 from mp3butcher/MDI7add funcs to read GZ Objects from a stream + +Fri, 10 Nov 2017 12:41:21 +0000 +Author : Robert Osfield +Fixed crash in copy constructor due to copy and paste/typo. + +Wed, 8 Nov 2017 15:57:34 +0100 +Author : Julien Valentin +replace string with stringstream (avoid a string copy at read) + +Wed, 8 Nov 2017 15:40:11 +0100 +Author : Julien Valentin +add funcs to read Object from a GZ stream + +Mon, 6 Nov 2017 20:49:23 +0000 +Author : Robert Osfield +Added Pawel's origin commit message into the osggpucull source as it examples a lot about how the example works + +Mon, 6 Nov 2017 19:53:38 +0000 +Author : Robert Osfield +Temporary workaround for the regression of intersection tests with osgText::Text. Added a local vertex array that is transformed by the last applied text matrix. + +Sat, 4 Nov 2017 17:28:14 +0100 +Author : Julien Valentin + following guidance from OpenGL Common Mistakes: mipmaps should be upload with glTexImage2D and not glTexSubImage2D + +Fri, 3 Nov 2017 09:55:42 +0000 +Author : Robert Osfield +Added check for malloc returning a valid pointer + +Fri, 3 Nov 2017 09:49:50 +0000 +Author : Robert Osfield +Added an explict null termination of buffer to address Coverity Scan reported issue + +Thu, 2 Nov 2017 18:43:05 +0000 +Author : Robert Osfield +Added check for a valud positions pointer + +Thu, 2 Nov 2017 18:39:11 +0000 +Author : Robert Osfield +Fuxed missing initializers + +Thu, 2 Nov 2017 16:39:32 +0000 +Author : Robert Osfield +Changed the key binding for opening and editor to edit presentation to 'E' and to trigger update the presentation by pressing 'e' + +Thu, 2 Nov 2017 11:51:03 +0000 +Author : Robert Osfield +Fixed copy and paste error + +Thu, 2 Nov 2017 11:48:39 +0000 +Author : Robert Osfield +Moved memset to after check for null memory pointer + +Thu, 2 Nov 2017 11:42:25 +0000 +Author : Robert Osfield +Cleaned up getEnvVar usage + +Thu, 2 Nov 2017 10:43:41 +0000 +Author : Robert Osfield +Replaced getenv usage with safer osg::getEnvVar + +Thu, 2 Nov 2017 10:02:34 +0000 +Author : Robert Osfield +Fixed warning + +Thu, 2 Nov 2017 10:00:28 +0000 +Author : Robert Osfield +Replaced getenv calls with safer osg::getEnvVar usage + +Wed, 1 Nov 2017 17:38:33 +0000 +Author : Robert Osfield +Moved getenv usage across to safer osg::getEnvVar() usage + +Wed, 1 Nov 2017 16:43:32 +0000 +Author : Robert Osfield +Added safety check for getenv parsing to prevent overflow attacks via getenv. + +Wed, 1 Nov 2017 14:45:27 +0000 +Author : Robert Osfield +Moved from getenv to osg::getEnvVar usage + +Wed, 1 Nov 2017 14:16:54 +0000 +Author : Robert Osfield +Made template function inline to avoid multiple declaration issues + +Wed, 1 Nov 2017 13:54:15 +0000 +Author : Robert Osfield +Replaced getenv(..) usage with osg::getEnvVar(..) + +Wed, 1 Nov 2017 13:32:47 +0000 +Author : Robert Osfield +Added OSG_ENVVAR_SUPPORTED cmake control and bool osg::getEnvVar(const char* name, T& value, ...) conviniece funcions to make it easier to implement optinal getenv reading code. + +Wed, 1 Nov 2017 11:35:05 +0000 +Author : Robert Osfield +Fixed Coverity Scane reported issue. + +Tue, 31 Oct 2017 17:59:13 +0000 +Author : OpenSceneGraph git repository +Merge pull request #378 from mp3butcher/osganimationupdate osganimationhardware example to use a common program + +Tue, 31 Oct 2017 17:55:59 +0000 +Author : Robert Osfield +Fixed unititialized memory variables and improved readability by adding spacing where appropriate + +Tue, 31 Oct 2017 17:43:39 +0000 +Author : Robert Osfield +Added missing initializers + +Tue, 31 Oct 2017 17:39:34 +0000 +Author : Robert Osfield +Fixed CovertiScan reported uninitialized member variable + +Tue, 31 Oct 2017 17:02:31 +0000 +Author : Robert Osfield +Fixed Coverity Scan reported issue + +Tue, 31 Oct 2017 18:00:06 +0100 +Author : Julien Valentin +update example to use a common program + +Tue, 31 Oct 2017 16:46:42 +0000 +Author : Robert Osfield +Replace c char array with std::string to address Coverity scan reported issue + +Tue, 31 Oct 2017 15:55:24 +0000 +Author : Robert Osfield +Fixed Coverity Scan reported memory leaks + +Tue, 31 Oct 2017 15:47:49 +0000 +Author : Robert Osfield +Fixed Coverity reported memory leak + +Tue, 31 Oct 2017 14:55:41 +0000 +Author : Robert Osfield +Reinstated two stage OSX build, and disabled part of the coverity_scan build to attempt to get it running without timeout. + +Tue, 31 Oct 2017 12:32:45 +0000 +Author : Robert Osfield +Upped the number of threads used in build to try and improve build speed + +Tue, 31 Oct 2017 10:01:52 +0000 +Author : Robert Osfield +Simplified build for OSX now that trais builds are running faster. + +Mon, 30 Oct 2017 15:53:56 +0000 +Author : Robert Osfield +Merge branch 'master' into osganimation + +Mon, 30 Oct 2017 14:36:41 +0000 +Author : Robert Osfield +From Raymond de Vires, added support for 2018 and 2016 versions of FBX. + +Mon, 30 Oct 2017 14:36:41 +0000 +Author : Robert Osfield +From Raymond de Vires, added support for 2018 and 2016 versions of FBX. + +Mon, 30 Oct 2017 14:22:10 +0000 +Author : Robert Osfield +From Raymond de Vires, Windows build fix + +Mon, 30 Oct 2017 14:05:45 +0000 +Author : Robert Osfield +Updated ChangeLog and AUTHORS + +Mon, 30 Oct 2017 13:40:50 +0000 +Author : Robert Osfield +Quitened down the DisplaySettings::setShaderHint() output for NONE. + +Mon, 30 Oct 2017 09:32:04 +0000 +Author : Robert Osfield +Merged support for StateSet::DefineList from shader_pipeline branch + +Mon, 30 Oct 2017 08:37:19 +0000 +Author : OpenSceneGraph git repository +Merge pull request #375 from mp3butcher/osganimationreformat AStyle (with codeblocks) + +Fri, 27 Oct 2017 21:02:43 +0200 +Author : Julien Valentin +reformat with the help of AStyle reformat tool (codeblocks) + +Fri, 27 Oct 2017 18:14:04 +0100 +Author : Robert Osfield +Fixed build error when building wiht OSG_USE_REF_PTR_IMPLICIT_OUTPUT_CONVERSION=OFF + +Fri, 27 Oct 2017 17:15:38 +0100 +Author : OpenSceneGraph git repository +Merge pull request #374 from mp3butcher/osganimationfix InfluenceMap "remove useless bones" method + +Fri, 27 Oct 2017 17:14:43 +0100 +Author : OpenSceneGraph git repository +Merge branch 'osganimation' into osganimation + +Fri, 27 Oct 2017 14:19:13 +0100 +Author : Robert Osfield +Fixed build errors when compiling with OSG_USE_REF_PTR_IMPLICIT_OUTPUT_CONVERSION set to OFF + +Fri, 27 Oct 2017 14:41:29 +0200 +Author : Julien Valentin +fix InfluenceMap "remove useless bones" method + +Fri, 27 Oct 2017 13:48:52 +0100 +Author : Robert Osfield +Build fix for when compiling with OSG_USE_REF_PTR_IMPLICIT_OUTPUT_CONVERSION set to OFF + +Fri, 27 Oct 2017 13:48:52 +0100 +Author : Robert Osfield +Build fix for when compiling with OSG_USE_REF_PTR_IMPLICIT_OUTPUT_CONVERSION set to OFF + +Fri, 27 Oct 2017 13:19:52 +0100 +Author : Robert Osfield +Fixed warning + +Fri, 27 Oct 2017 13:17:47 +0100 +Author : Robert Osfield +From Farshid Lashkari, "fix for the Collada loader to check for some NULL attributes." + +Fri, 27 Oct 2017 12:54:10 +0100 +Author : Robert Osfield +Merge branch 'master' into osganimation + +Fri, 27 Oct 2017 09:33:24 +0100 +Author : OpenSceneGraph git repository +Merge pull request #373 from LaurensVoerman/noStdMaxuse osg::maximum, not std::max + +Fri, 27 Oct 2017 09:41:28 +0200 +Author : Laurens Voerman +use osg::maximum, not std::max + +Thu, 26 Oct 2017 14:26:01 +0100 +Author : OpenSceneGraph git repository +Merge pull request #372 from openscenegraph/text_improvementsText improvements, introducing implementation of Signed Distance Function texture generation and new shaders for outlines and shadows replacing old multi-pass approach + +Thu, 26 Oct 2017 12:08:00 +0100 +Author : Robert Osfield +Updated from OpenSceneGraph-Data/shader/text.frag to add fixes to handling of vertexColor's alpha values + +Thu, 26 Oct 2017 12:03:56 +0100 +Author : Robert Osfield +Added update of glyph representation to ensure all the glyphs are assigned to the required GlyphTextures + +Thu, 26 Oct 2017 12:02:56 +0100 +Author : Robert Osfield +Added command line parsing to aid with testing of osgText by allowing osgText::FadeText to be created with various options + +Wed, 25 Oct 2017 16:29:25 +0100 +Author : Robert Osfield +Added optimization for text where the colour alpha value is 0.0, returning early to aovid any GL calls. + +Wed, 25 Oct 2017 16:13:26 +0100 +Author : Robert Osfield +Fixed pre compilation osg::Program state leaking into the main scene graph rendering + +Tue, 24 Oct 2017 16:04:14 +0100 +Author : Robert Osfield +Added stats handler + +Tue, 24 Oct 2017 15:14:23 +0100 +Author : Robert Osfield +Updated from OpenSceneGraph-Data/shaders/text.frag to address GLSL int to float conversion warning + +Tue, 24 Oct 2017 14:46:13 +0100 +Author : Robert Osfield +Added DisplaySettings:s/getgTextShaderTechnique() and OSG_TEXT_SHADER_TECHNIQUE env var support to DisplaySettings. Added using of DisplaySettings:getgTextShaderTechnique() to Text default constructor. Added better debug output control in Text.cpp + +Tue, 24 Oct 2017 12:34:48 +0100 +Author : Robert Osfield +Improved the Text::_shaderTechnique default setting using OSG_TEXT_SHADER_TECHNIQUE env var, options are ALL_FEATURES, GREYSCALE, SIGNED_DISTANCE_FIELD, SDF, NO_TEXT_SHADER, NONE. + +Tue, 24 Oct 2017 12:07:13 +0100 +Author : Robert Osfield +Quitened down debug info + +Tue, 24 Oct 2017 11:36:00 +0100 +Author : Robert Osfield +Fixed Glyph::TextureInfo assignment bug + +Mon, 23 Oct 2017 16:07:24 +0100 +Author : Robert Osfield +Renamed text_sdf.frag to text.frag and removed text_greyscale_frag. Cleaned up setup of osgText::ShaderTechnique adding a NO_SHADER_TECHNIQUE option. + +Mon, 23 Oct 2017 14:50:35 +0100 +Author : Robert Osfield +Restructed the way that GlyphTexture is set up to better support control of osgText::ShaderTechnique from osgText::Text + +Mon, 23 Oct 2017 09:06:55 +0100 +Author : OpenSceneGraph git repository +Merge pull request #371 from hwiesmann/masterRemoval of compiler warning for Cocoa builds + +Mon, 23 Oct 2017 09:05:34 +0100 +Author : OpenSceneGraph git repository +Merge pull request #370 from siu/master-travisCcacheFix ccache on travis + +Sun, 22 Oct 2017 22:13:46 +0200 +Author : Hartwig +BUG FIX - Addition of missing #endif directive + +Sun, 22 Oct 2017 15:04:33 +0200 +Author : Hartwig +Replacement of commas with semicolons + +Sun, 22 Oct 2017 13:47:51 +0200 +Author : Hartwig +Removal of compiler warning for Cocoa builds + +Fri, 20 Oct 2017 14:09:11 +0200 +Author : David Siñuela Pastor +Install ccache on MacOsNote that brew update must be run before any brew install command or +it will fail, see https://github.com/travis-ci/travis-ci/issues/8552. + + +Wed, 18 Oct 2017 12:20:35 +0200 +Author : David Siñuela Pastor +Fix ccache configuration in travisUse ccache as explained in https://docs.travis-ci.com/user/caching/#ccache-cache + + +Sat, 21 Oct 2017 10:08:41 +0100 +Author : Robert Osfield +Added Text::s/getShaderTechnique() + +Fri, 20 Oct 2017 17:03:25 +0100 +Author : Robert Osfield +Moved osgText::GlyphTechnique::Features enum to osgText::ShaderTechinque enum to make it's roll clearer + +Fri, 20 Oct 2017 14:14:14 +0100 +Author : Robert Osfield +Merge branch 'master' into text_improvements + +Fri, 20 Oct 2017 11:52:48 +0100 +Author : Robert Osfield +From Ralf Habacker, patch refactoring struct ObjOptionsStruct in obj plugin into a real class, which is a preparation for further obj related patches. + +Fri, 20 Oct 2017 11:37:41 +0100 +Author : Robert Osfield +Added built-in support for lighting.vert + +Fri, 20 Oct 2017 10:18:21 +0100 +Author : Robert Osfield +Updated shaders from OpenSceneGraph-Data/shaders + +Thu, 19 Oct 2017 20:57:25 +0100 +Author : Robert Osfield +Moved the assignment of the ModifiedCount to before GL texture calls. + +Thu, 19 Oct 2017 12:39:22 +0100 +Author : Robert Osfield +Implemented --single command line option that creates a single osg::DrawElementsUInt primitive set instead of using MultiDrawIndirect. + +Thu, 19 Oct 2017 12:06:59 +0100 +Author : Robert Osfield +Improved spacing to make code more readable + +Thu, 19 Oct 2017 11:57:53 +0100 +Author : Robert Osfield +Build fixes with ref_ptr<> autoconversion disabled + +Thu, 19 Oct 2017 11:06:23 +0100 +Author : Robert Osfield +Fixed placement of { and spacing to make the code more readable and consistent with the rest of the OSG + +Wed, 18 Oct 2017 10:11:43 +0100 +Author : Robert Osfield +Implemented inplace replacement + +Tue, 17 Oct 2017 17:11:12 +0200 +Author : David Siñuela Pastor +Do not break systems with cr as line endings + +Mon, 16 Oct 2017 11:52:54 +0100 +Author : Robert Osfield +Fixed warning + +Mon, 16 Oct 2017 10:47:47 +0100 +Author : Robert Osfield +Fixed GLX EGL build + +Mon, 16 Oct 2017 10:38:33 +0100 +Author : Robert Osfield +Removed inappropriate tabs&spaces + +Mon, 16 Oct 2017 10:16:49 +0100 +Author : OpenSceneGraph git repository +Merge pull request #364 from mp3butcher/osganimbugfixadd osg::Program::BindUniformBlockList serialization + +Mon, 16 Oct 2017 10:12:19 +0100 +Author : Robert Osfield +Fixed build error + +Mon, 16 Oct 2017 10:08:18 +0100 +Author : Robert Osfield +Moved bracket to be consistent with the rest of the OSG + +Mon, 16 Oct 2017 10:00:49 +0100 +Author : OpenSceneGraph git repository +Merge pull request #366 from LaurensVoerman/rotateDXTadd support for dxt compressed images to createImageWithOrientationConversion + +Mon, 16 Oct 2017 09:58:29 +0100 +Author : OpenSceneGraph git repository +Merge pull request #367 from LaurensVoerman/compression_astccopySubImage support for block compressed images, added support for astc compressed type. + +Mon, 16 Oct 2017 09:49:47 +0100 +Author : Robert Osfield +Fixed indentation + +Mon, 16 Oct 2017 09:45:37 +0100 +Author : OpenSceneGraph git repository +Merge pull request #365 from LaurensVoerman/login2modified present3D and osgvnc to allow multiple --login arguments like osgViewer. + +Sat, 14 Oct 2017 09:06:37 +0100 +Author : Robert Osfield +Changed the precision setting of #pargma(tic) shader composition define setup to address GLES compatibility issues + +Sat, 14 Oct 2017 09:03:08 +0100 +Author : Robert Osfield +Improved the formating of GLSL source that is passed to OpenGL to make debugging shaders easier. + +Fri, 13 Oct 2017 17:03:31 +0100 +Author : Robert Osfield +Cleaned up support for GL3 build + +Fri, 13 Oct 2017 16:54:04 +0200 +Author : Laurens Voerman +copySubImage support for block compressed images, added support for astc compressed type. + +Fri, 13 Oct 2017 13:01:57 +0100 +Author : Robert Osfield +Removed the glyph image outline support as it's no longer required. + +Fri, 13 Oct 2017 11:42:25 +0100 +Author : Robert Osfield +Deprecated Text:BackdropImplementation, removing the backend as it no longer required when using shaders for backdrop effects + +Fri, 13 Oct 2017 08:40:58 +0100 +Author : Robert Osfield +Removed old multipass implemenmtations of backdrops as effect is now fully implememted in shaders + +Thu, 12 Oct 2017 17:19:24 +0200 +Author : Julien Valentin +add osg::Program::BindUniformBlock serialization + +Thu, 12 Oct 2017 18:45:38 +0100 +Author : Robert Osfield +Updated from OpenSceneGraph-Data/shaders/text_sdf.frag to add support for SHADOW + +Thu, 12 Oct 2017 16:44:40 +0100 +Author : Robert Osfield +Merge branch 'master' into text_improvements + +Thu, 12 Oct 2017 17:38:16 +0200 +Author : Laurens Voerman +add support for dxt compressed images to createImageWithOrientationConversion + +Thu, 12 Oct 2017 17:21:10 +0200 +Author : Laurens Voerman +modified present3D to allow multiple --login arguments like osgViewer, added --login option to osgvnc example + +Thu, 12 Oct 2017 15:52:42 +0100 +Author : OpenSceneGraph git repository +Merge pull request #363 from LaurensVoerman/dxtcGetcoloradded dxtc support in Image::getColor, Image::isImageTranscent testdxt3 and dxt5 + +Thu, 12 Oct 2017 13:49:57 +0200 +Author : Laurens Voerman +added dxtc support in Image::getColor, enhanced Image::isImageTranslucent to test opacity of dxt3 and dxt5 images + +Thu, 12 Oct 2017 11:12:47 +0100 +Author : Robert Osfield +Updated text_sdf_frag.cpp from OpenSceneGraph-Data changes that add outline generation for non SIGNED_DISTANCE_FIELD text. + +Tue, 10 Oct 2017 09:21:34 +0100 +Author : Robert Osfield +Merge branch 'master' into text_improvements + +Mon, 9 Oct 2017 12:33:06 +0100 +Author : Robert Osfield +Updated ChangeLog + +Mon, 9 Oct 2017 12:25:40 +0100 +Author : Robert Osfield +Updated version number + +Mon, 9 Oct 2017 12:23:45 +0100 +Author : Robert Osfield +Updated AUTHORS + +Mon, 9 Oct 2017 10:03:21 +0100 +Author : OpenSceneGraph git repository +Merge pull request #359 from eligovision/OpenSceneGraph_glesAdded defines: GL_ALPHA4/8/12/16 in osg/Image, this will fix compilat… + +Mon, 9 Oct 2017 10:02:51 +0100 +Author : OpenSceneGraph git repository +Merge pull request #358 from eligovision/OpenSceneGraph_optimizerVertexAttribDivisor compare function fix: index must be compared + +Fri, 6 Oct 2017 18:03:36 +0100 +Author : Robert Osfield +Added explictly unbinding of VBO for setInterleavedArrays(). + +Fri, 6 Oct 2017 17:47:19 +0100 +Author : Robert Osfield +Added VertexArrayState::ArrayDispatch::className() method and implementation for each ArrayDispatch subclass to help with debugging + +Fri, 6 Oct 2017 17:37:50 +0300 +Author : Konstantin S. Matveyev +Added defines: GL_ALPHA4/8/12/16 in osg/Image, this will fix compilation error while building for GLES2 + +Fri, 6 Oct 2017 14:33:07 +0300 +Author : Konstantin S. Matveyev +VertexAttribDivisor compare function fix: index must be compared + +Thu, 5 Oct 2017 16:56:30 +0100 +Author : Robert Osfield +Improved the readability of recent changes by adding spaces, {} and moving { onto separate lines to keep things consistent with the rest of the OSG. + +Thu, 5 Oct 2017 16:43:54 +0100 +Author : OpenSceneGraph git repository +Merge pull request #357 from mp3butcher/osganimationfix normalization bug (happen too early ) + +Thu, 5 Oct 2017 16:31:45 +0100 +Author : OpenSceneGraph git repository +Merge pull request #354 from eligovision/OpenSceneGraph_intersectionLineSegmentIntersector fixed: intersection ratio remaped to the range… + +Thu, 5 Oct 2017 16:30:21 +0100 +Author : OpenSceneGraph git repository +Merge pull request #353 from eligovision/OpenSceneGraph_iotellg call removed from StreamOperator's checkStream function, becaus… + +Thu, 5 Oct 2017 16:29:37 +0100 +Author : OpenSceneGraph git repository +Merge pull request #355 from denyskoch/patch-1Fix loading of 16bit PNG images + +Thu, 5 Oct 2017 15:59:26 +0100 +Author : Robert Osfield +Fixed spacing to make it consistent with the rest of the OSG and make it easier to read. + +Thu, 5 Oct 2017 15:57:02 +0100 +Author : OpenSceneGraph git repository +Merge pull request #351 from LaurensVoerman/vncHostPwVNC: try to find password for host if no password for host:port is found + +Thu, 5 Oct 2017 15:37:03 +0100 +Author : Robert Osfield +Added support for multiple --login url username password entries to osgviewer + +Thu, 5 Oct 2017 15:02:17 +0100 +Author : OpenSceneGraph git repository +Merge pull request #348 from eligovision/OpenSceneGraph_serializersosg serializers fixed for static build, ShaderAttribute wrapper added + +Thu, 5 Oct 2017 12:45:47 +0100 +Author : Robert Osfield +Steamlined the handling of osg::Geometry + +Thu, 5 Oct 2017 12:15:23 +0100 +Author : OpenSceneGraph git repository +Merge pull request #346 from LaurensVoerman/FindLIBLASremoved las_c library from FindLIBLAS.cmake, it's not used by the osgplugin. + +Thu, 5 Oct 2017 12:14:03 +0100 +Author : Robert Osfield +Merge branch 'master' into text_improvements + +Wed, 4 Oct 2017 18:06:42 +0100 +Author : Robert Osfield +Improvements to the Signed Distance Field implementation. + +Wed, 4 Oct 2017 05:42:33 +0200 +Author : Julien Valentin +fix normalization bug (happen too early )minor bug + +bla + + +Fri, 29 Sep 2017 20:21:13 +0100 +Author : Robert Osfield +Simplified and improved the glyph margin computation and usage + +Fri, 29 Sep 2017 10:39:02 +0100 +Author : Robert Osfield +Improved SDF generation + +Fri, 29 Sep 2017 10:25:04 +0100 +Author : Robert Osfield +Added setting of the FontResolution of the DefaultFont + +Fri, 29 Sep 2017 10:20:59 +0100 +Author : Robert Osfield +Added command line support for specifying "default" for osgText::DefaultFont + +Fri, 29 Sep 2017 09:54:43 +0100 +Author : Robert Osfield +Improved the setup of the --counter test + +Thu, 28 Sep 2017 11:09:18 +0200 +Author : Denys Koch +Fix loading of 16bit PNG imagesWhen a 16bit PNG image is loaded, the internalTextureFormat is set to unsized (i.e pixelFormat) constant. This results in 8 Bit Texture2D + +Wed, 27 Sep 2017 11:09:22 +0100 +Author : Robert Osfield +Fixed update of GlyphTexture Image when copying new Glyph image's to it. + +Tue, 26 Sep 2017 15:32:41 +0100 +Author : Robert Osfield +UPdated from OpenSceneGraph-Data with handling of non textured text decoration + +Tue, 26 Sep 2017 12:51:03 +0100 +Author : Robert Osfield +Updated shader from OpenSceneGraph-Data/shaders to add fade out for SDF and non SDF pathways + +Tue, 26 Sep 2017 10:57:09 +0100 +Author : Robert Osfield +Updated wiht OpenSceneGraph-Data/shader version that introduced use of textureLOD to reduce aliasing artifacts with SDF + +Tue, 26 Sep 2017 10:44:14 +0100 +Author : Robert Osfield +Updated shaders using latest OpenSceneGraph-Data/shader versions + +Tue, 26 Sep 2017 10:42:47 +0100 +Author : Robert Osfield +Improvements to SDF and outline generation + +Fri, 22 Sep 2017 12:22:58 +0100 +Author : Robert Osfield +Fixed rendering old sytel outline + +Fri, 22 Sep 2017 11:38:43 +0300 +Author : Konstantin S. Matveyev +LineSegmentIntersector fixed: intersection ratio remaped to the range of LineSegment => correct order in multiset of intersections + +Sun, 17 Sep 2017 18:48:32 +0300 +Author : konstantin.matveyev +tellg call removed from StreamOperator's checkStream function, because reading of files (readNodeFile etc.) with tellg on 'every iter' is approximately 100 times slower on Emscripten platform + +Fri, 22 Sep 2017 07:56:30 +0100 +Author : OpenSceneGraph git repository +Merge pull request #352 from remoe/patch-3addShader fix + +Fri, 22 Sep 2017 08:39:38 +0200 +Author : Remo E +addShader fix + +Thu, 21 Sep 2017 16:04:10 +0100 +Author : Robert Osfield +Removed debug output + +Thu, 21 Sep 2017 16:01:27 +0100 +Author : Robert Osfield +Added assignStateSet() to Text::setBackgroundColor() + +Thu, 21 Sep 2017 15:52:07 +0100 +Author : Robert Osfield +Added support for toggling on use of the new SignedDistanceFunction function now built into osgText, just use --sdf to enable. + +Thu, 21 Sep 2017 15:41:21 +0100 +Author : Robert Osfield +Removed debug info + +Thu, 21 Sep 2017 16:33:14 +0200 +Author : Laurens Voerman +VNC: try to find password for host if no password for host:port is found + +Thu, 21 Sep 2017 14:35:31 +0100 +Author : Robert Osfield +Moved enabling/disabling of SDF so it's done regardless of whether a backdrop is used. + +Thu, 21 Sep 2017 14:32:17 +0100 +Author : Robert Osfield +Umproved SDF computation. + +Wed, 20 Sep 2017 16:51:30 +0100 +Author : Robert Osfield +Removed no longer used code paths + +Wed, 20 Sep 2017 15:51:03 +0100 +Author : Robert Osfield +Added support for only enabling SignedDistanceField shader path when font resolution is greater than 16. + +Wed, 20 Sep 2017 14:30:23 +0100 +Author : Robert Osfield +cleaned up exmple + +Wed, 20 Sep 2017 14:29:05 +0100 +Author : Robert Osfield +Added Text::assignStateSet() and usage to make sure the correct StateSet is setup for each combination of backdrop settings + +Wed, 20 Sep 2017 11:02:06 +0100 +Author : Robert Osfield +Updated text_sdf.frag shader to handle GLES2+ versions + +Wed, 20 Sep 2017 11:01:04 +0100 +Author : Robert Osfield +Added commented out debug output to make it easier to test in future + +Tue, 19 Sep 2017 17:07:59 +0100 +Author : Robert Osfield +Fixed OSG_PRECISION_FLOAT usage + +Tue, 19 Sep 2017 17:01:58 +0100 +Author : Robert Osfield +Fixed X11 GLES2 build + +Tue, 19 Sep 2017 16:35:28 +0100 +Author : Robert Osfield +Added osgText/shaders to support greyscale and Signed Distance Field based text + +Mon, 18 Sep 2017 18:09:15 +0100 +Author : Robert Osfield +Added support for subsititing $VAR_NAME entries in shaders to enable writing shaders that work across GLSL versions. + +Fri, 15 Sep 2017 15:14:19 +0100 +Author : Robert Osfield +Added constant sizeing vs changing label size relatve to font resolution, controlled by --constant-size and --scale-size command line options. + +Fri, 15 Sep 2017 12:14:37 +0300 +Author : Konstantin S. Matveyev +osg serializers fixed for static build, ShaderAttribute wrapper added + +Thu, 14 Sep 2017 15:58:38 +0100 +Author : Robert Osfield +Impprovide the computation of the Signed Distance Field + +Wed, 13 Sep 2017 11:09:56 +0100 +Author : Robert Osfield +Fixed of shadow + +Wed, 13 Sep 2017 11:08:51 +0100 +Author : Robert Osfield +Added --shadow-* command line variants to provide full control over the position of the text shadow + +Tue, 12 Sep 2017 19:13:01 +0100 +Author : Robert Osfield +Added setting of the Text::BackdropImplementation type to USE_SHADERS when setting up shaders + +Tue, 12 Sep 2017 16:03:35 +0100 +Author : Robert Osfield +Changed the margin computation to properly account of the Signed Distance Function data + +Tue, 12 Sep 2017 11:50:47 +0100 +Author : Robert Osfield +Shifted set up of osgText related StateSet from osgText::Font into into osg::TextBase/Text to enable grater control over state required for specific Text implementations + +Tue, 12 Sep 2017 09:19:33 +0200 +Author : Laurens Voerman +removed las_c library from FindLIBLAS.cmake, it's not used by the osg plugin. + +Fri, 8 Sep 2017 17:03:15 +0100 +Author : Robert Osfield +Added extra command line paramter and osgText::Font settings to add better control of osgText::GlyphTexture generation to support signed distance field and outline image data. + +Fri, 8 Sep 2017 17:02:38 +0100 +Author : Robert Osfield +Added setting of the original font reoslution to the created Glyph + +Fri, 8 Sep 2017 16:59:43 +0100 +Author : Robert Osfield +Add support for generating outline and signed distance field channels in a RGBA packed GlyphTexture Image. + +Wed, 6 Sep 2017 16:53:54 +0100 +Author : Robert Osfield +Added KeyHandler for toggling "SIGNED_DISTANCE_FIELD" and "OUTLINE" #pragma(tic) shader defines to control the different shader paths.Keys to press are 'd' for toggle SIGNED_DISTANCE_FIELD and 'o' for OUTLINE. + + +Wed, 6 Sep 2017 10:40:05 +0100 +Author : Robert Osfield +To control the GlyphTexture Min/MagFilter values Added --min and --mag filter with LINEAR, NEAREST and LINEAR_MIPMAP_LINER options for values + +Mon, 4 Sep 2017 15:35:01 +0100 +Author : OpenSceneGraph git repository +Merge pull request #340 from mp3butcher/osganimationadd a new method on VertexInfluenceMap and the serializer for MorphTransforfHW + +Mon, 4 Sep 2017 15:21:26 +0100 +Author : OpenSceneGraph git repository +Merge pull request #344 from eligovision/OpenSceneGraph_text3dText3D dynamic changing fix + +Mon, 4 Sep 2017 15:20:54 +0100 +Author : OpenSceneGraph git repository +Merge pull request #345 from eligovision/OpenSceneGraph_example_text3dexample_osgtext3d: more options for testing + +Mon, 4 Sep 2017 12:04:37 +0200 +Author : Julien Valentin +add DSO scope in modified XXXTransformHardware serializers + +Mon, 4 Sep 2017 11:44:30 +0300 +Author : Konstantin S. Matveyev +example_osgtext3d: more options for testing + +Mon, 4 Sep 2017 11:29:50 +0300 +Author : Konstantin S. Matveyev +Text3D dynamic changing fix + +Mon, 4 Sep 2017 08:36:49 +0100 +Author : OpenSceneGraph git repository +Merge pull request #341 from scrawl/cullingactive_fixLineSegmentIntersector: respect the 'cullingActive' flag for bounding box check + +Mon, 4 Sep 2017 02:27:54 +0200 +Author : Julien Valentin +cleanup + +Sun, 3 Sep 2017 17:37:06 +0200 +Author : Julien Valentin +make preparedata skeleton independant (as it was with the Rig::buildInfluenceSet) no more divergence with master i think + +Sun, 3 Sep 2017 14:15:36 +0000 +Author : scrawl +LineSegmentIntersector: respect the 'cullingActive' flag when testing drawable bounding box + +Fri, 1 Sep 2017 20:03:05 +0200 +Author : Julien Valentin +Merge remote-tracking branch 'upstream/master' into osganimation + +Fri, 1 Sep 2017 19:13:01 +0200 +Author : Julien Valentin +update serializer with new properties + +Fri, 1 Sep 2017 18:08:37 +0200 +Author : Julien Valentin +add MorphTransformHardware serializer + +Fri, 1 Sep 2017 18:04:32 +0200 +Author : Julien Valentin +Merge remote-tracking branch 'upstream/osganimation' into osganimation + +Fri, 1 Sep 2017 17:48:28 +0200 +Author : Julien Valentin +add void InfluenceMap::removeUnexpressedBones(Skeleton &skel) const; a bit experimental but work well without further process on my test set + +Fri, 1 Sep 2017 16:46:38 +0100 +Author : OpenSceneGraph git repository +Merge pull request #338 from mp3butcher/osganimationclean and bugfix + +Fri, 1 Sep 2017 15:50:47 +0100 +Author : OpenSceneGraph git repository +Merge pull request #337 from mp3butcher/osganimbugfixfix a bug in how vertexattributes are filled + +Fri, 1 Sep 2017 16:23:49 +0200 +Author : Julien Valentin +remove utility classes BoneWeight and IndexWeight in order to avoid unnecessary symbols (but decrease a bit clarity of the code) + +Fri, 1 Sep 2017 15:12:10 +0200 +Author : Julien Valentin +cleanup + +Fri, 1 Sep 2017 01:43:00 +0200 +Author : Julien Valentin +a functional cleanup + +Thu, 31 Aug 2017 16:35:05 +0200 +Author : Julien Valentin +clean and bugfixes + +Thu, 31 Aug 2017 14:32:39 +0100 +Author : OpenSceneGraph git repository +Merge pull request #333 from mp3butcher/osganimationosgAnimation: change animationdata owner from riggeometry to rigtransformimplementations + +Thu, 31 Aug 2017 13:49:27 +0200 +Author : Julien Valentin +few cleanup + +Thu, 31 Aug 2017 13:30:24 +0200 +Author : Julien Valentin +revert s/VertexIndexWeight/IndexWeight/ + +Thu, 31 Aug 2017 13:29:42 +0200 +Author : Julien Valentin +fix example + +Wed, 30 Aug 2017 23:15:01 +0200 +Author : Julien Valentin +fix a bug in how vertexattributes are filled + +Wed, 30 Aug 2017 23:01:21 +0200 +Author : Julien Valentin +I found the damn bug in RigTransformHW + +Wed, 30 Aug 2017 20:36:34 +0200 +Author : Julien Valentin +rehabilit an init method to ensure morphing po setted before skinning po in case of rigeom source that are morphgeom + +Wed, 30 Aug 2017 17:43:29 +0100 +Author : Robert Osfield +Added --shader filename command line parsing and associated set up of osg::Program to allow shaders to be passed into example to customize rendering + +Wed, 30 Aug 2017 16:22:25 +0100 +Author : Robert Osfield +Added --interval value commnad line option for setting the Font::setGlyphInterval() to experimentation of clamping of glyph images to user specified intervals in the glyph texture + +Wed, 30 Aug 2017 16:21:03 +0100 +Author : Robert Osfield +Added osgText::Font::s/getGlyphInterval(int) and GlyphTexture::s/getGlyphInterval(int) and internal support for clmapping positions of glyph images an defined intervals, defaults to 1. + +Wed, 30 Aug 2017 17:07:11 +0200 +Author : Julien Valentin +add parameter to XXXTranformHW to customize reserved texture attribs and vertex attribs + +Wed, 30 Aug 2017 15:46:19 +0200 +Author : Julien Valentin +add a guard (if dirty) on uniform update + +Wed, 30 Aug 2017 15:13:54 +0200 +Author : Julien Valentin +readd VertexInfluence whenever it's bad named and kinda useless + +Wed, 30 Aug 2017 14:59:31 +0200 +Author : Julien Valentin +readd buildVertexInfluenceSet for backward compat + +Wed, 30 Aug 2017 13:21:32 +0200 +Author : Julien Valentin +cleanup + +Wed, 30 Aug 2017 12:55:45 +0200 +Author : Julien Valentin +uncomment normalization in rigtransformxxx + +Wed, 30 Aug 2017 12:09:54 +0200 +Author : Julien Valentin +add and comment out normlization in rigtransformXXX + +Wed, 30 Aug 2017 10:50:26 +0100 +Author : Robert Osfield +Added --margin texel_width and --margin-ration ratio to control the spacing between glyphs in the font. + +Wed, 30 Aug 2017 10:16:18 +0100 +Author : Robert Osfield +Added --test command line option that sets up all the sizes and font settings required for a useufl unit test. + +Wed, 30 Aug 2017 11:12:17 +0200 +Author : Julien Valentin +refactor: remove totally VertexInfluence (renamed BoneInfluenceList) everywhere + +Tue, 29 Aug 2017 17:32:14 +0100 +Author : Robert Osfield +Removed debug messages + +Tue, 29 Aug 2017 17:19:26 +0100 +Author : Robert Osfield +Added TextSettings struct to manage values used to set up the text. with the addition of following command line parameters: --outline // enable outlne --shadow // enable shadow --offset ratio // set the backdrop offset --text-color r g b a // set the text body color --bd-color r g b a // set the shadow/outline color --bg-color r g b a // window background color -o filename // write create subgraph to disk using specified filename + +Tue, 29 Aug 2017 17:32:19 +0200 +Author : Julien Valentin +swap priority in BonePtrWeight comparator< yeild the same VG set + +Tue, 29 Aug 2017 17:24:35 +0200 +Author : Julien Valentin +cleanup + +Tue, 29 Aug 2017 15:10:05 +0200 +Author : Julien Valentin +remove virtual qualifier for deprecated method + +Tue, 29 Aug 2017 14:47:56 +0200 +Author : Julien Valentin +add MorphTransformHW for RigGeometry sources that are MorphGeometry + +Tue, 29 Aug 2017 14:11:44 +0200 +Author : Julien Valentin +set defaut implementation at creation + +Tue, 29 Aug 2017 13:48:06 +0100 +Author : Robert Osfield +Added --ortho command line option to toggle use of orthographic camera or default perspective one + +Tue, 29 Aug 2017 12:21:14 +0100 +Author : Robert Osfield +Added argument parsing to viewer constructor + +Tue, 29 Aug 2017 10:51:06 +0100 +Author : OpenSceneGraph git repository +Merge pull request #334 from mathieu/ValidateProgramTooEarlyUnder macOS the glValidateProgram reports too many errors + +Tue, 29 Aug 2017 11:34:27 +0200 +Author : Mathieu MARACHE +Under macOS the glValidateProgram reports too many false negatives (errors) about missing buffers, etc..From the internet https://stackoverflow.com/questions/15335510/opengl-glvalidateprogram-error-on-mac-os-x : +« […] The purpose of glValidateProgram is not to use it as an added "check" step after linking the program, because the GL and application state is hardly ready for actually using that program at this point, probably it's even before we get around to initializing the default framebuffer (its bitdepth, its multisample buffers, etc), and that's what the error hints at. + +An appropriate place to call glValidateProgram would be right before you make a real render call. » + +Tue, 29 Aug 2017 02:55:40 +0200 +Author : Julien Valentin +few refactoring and fixes + +Tue, 29 Aug 2017 00:34:26 +0200 +Author : Julien Valentin +readd the 2 methods in InfluenceMap just in case + +Tue, 29 Aug 2017 00:09:38 +0200 +Author : Julien Valentin +cleanup + +Tue, 29 Aug 2017 00:07:07 +0200 +Author : Julien Valentin +remove VertexInfluenceSet + +Mon, 28 Aug 2017 18:42:22 +0200 +Author : Julien Valentin +add 2 method to VertexInfluenceMap: normalize and cullInfluenceCountPerVertex + +Mon, 28 Aug 2017 18:27:23 +0200 +Author : Julien Valentin +comply with refactoring + +Mon, 28 Aug 2017 18:16:30 +0200 +Author : Julien Valentin +total removal of the old path + +Mon, 28 Aug 2017 18:02:52 +0200 +Author : Julien Valentin +remove default order for BoneWeight and restore old sort func (behaviors differs) + +Mon, 28 Aug 2017 16:28:30 +0100 +Author : OpenSceneGraph git repository +Merge pull request #332 from denyskoch/fix-boundingsphere-inequality-operatorFix flawed BoundingSphere inequality operator + +Mon, 28 Aug 2017 17:13:48 +0200 +Author : Julien Valentin +clean unused + +Mon, 28 Aug 2017 17:13:23 +0200 +Author : Julien Valentin +fix the example + +Mon, 28 Aug 2017 16:46:01 +0200 +Author : Julien Valentin +remove old path and add few fixes + +Mon, 28 Aug 2017 16:02:00 +0200 +Author : Julien Valentin +minor fixes removed unused + +Mon, 28 Aug 2017 15:59:13 +0200 +Author : Julien Valentin +reroot to rigtransform::prepareData old path to rig::buildvertexinfluence + +Mon, 28 Aug 2017 15:44:09 +0200 +Author : Julien Valentin +remove unused + +Mon, 28 Aug 2017 15:41:14 +0200 +Author : Julien Valentin +add prepareData for RigTransformHW + +Mon, 28 Aug 2017 15:40:04 +0200 +Author : Julien Valentin +minor changes+fix + +Mon, 28 Aug 2017 15:27:46 +0200 +Author : Julien Valentin +add default constructor for IndexWeight with invalid indices + +Mon, 28 Aug 2017 14:25:12 +0200 +Author : Julien Valentin +add prepareData for rigttransform software + +Mon, 28 Aug 2017 14:34:39 +0200 +Author : Denys Koch +Fix flawed BoundingSphere inequality operator + +Mon, 28 Aug 2017 14:23:15 +0200 +Author : Julien Valentin +few refactoring + +Mon, 28 Aug 2017 13:18:37 +0100 +Author : OpenSceneGraph git repository +Merge pull request #331 from mp3butcher/osganimationOsganimation fix a bug introduced when readding transformsoftwareMethod + +Mon, 28 Aug 2017 13:34:06 +0200 +Author : Julien Valentin +Merge remote-tracking branch 'upstream/osganimation' into osganimation + +Mon, 28 Aug 2017 05:22:14 +0200 +Author : Julien Valentin +fix a bug introduced when readding transformsoftwareMethod + +Mon, 28 Aug 2017 10:28:18 +0100 +Author : Robert Osfield +Merge branch 'osganimation' of https://github.com/mp3butcher/OpenSceneGraph into osganimation + +Mon, 28 Aug 2017 10:02:27 +0100 +Author : OpenSceneGraph git repository +Merge pull request #330 from mathieu/ProgramFixFunctionAvailableCoreProfileosg::Program::isFixedFunction() should'nt return true if fixed function unavailable + +Mon, 28 Aug 2017 09:44:10 +0200 +Author : Mathieu MARACHE +osg::Program::isFixedFunction() should'nt return true fixed function is unavailable, even if _shaderList.empty() is true + +Mon, 28 Aug 2017 05:22:14 +0200 +Author : Julien Valentin +fix a bug introduced when readding transformsoftwareMethod + +Mon, 28 Aug 2017 05:17:17 +0200 +Author : Julien Valentin +add a new prepareData method to the interface + +Mon, 28 Aug 2017 04:51:52 +0200 +Author : Julien Valentin +MorphTransformHardware using TBO added + +Mon, 28 Aug 2017 04:42:51 +0200 +Author : Julien Valentin +readd virtual void transformSoftwareMethod() for retrocompatibity + +Sun, 27 Aug 2017 18:08:09 +0100 +Author : OpenSceneGraph git repository +Merge pull request #327 from kornerr/masterFix Emscripten build errors + +Sun, 27 Aug 2017 18:07:21 +0100 +Author : OpenSceneGraph git repository +Merge pull request #328 from scrawl/group-docsFix docs for Group::addChild to match implementation + +Sun, 27 Aug 2017 02:14:12 +0200 +Author : Julien Valentin +replace VertexInfluence to BoneInfluenceList and VertexIndexWeight to IndexWeightfix in example + + +Sun, 27 Aug 2017 00:10:52 +0200 +Author : Julien Valentin +remove unused code and remove a commented section + +Sat, 26 Aug 2017 23:05:52 +0200 +Author : Julien Valentin +update serializers + +Sat, 26 Aug 2017 20:37:10 +0200 +Author : Julien Valentin +refactoring and fixes only change in design: decouplage between MorphGeometry and MorphTransform technique no real change in behavior (i hope) + +Sat, 26 Aug 2017 19:25:00 +0300 +Author : Michael Kapelko +Fix Emscripten build errors + +Sat, 26 Aug 2017 11:30:55 +0000 +Author : scrawl +Fix docs for Group::addChild to match implementationChecking for duplicates is only done if ENSURE_CHILD_IS_UNIQUE is defined, but this is never defined anywhere. + +Fri, 25 Aug 2017 14:49:38 +0100 +Author : OpenSceneGraph git repository +Merge pull request #326 from emminizer/glcore3_cmakefixSETUP_EXE in CMake now uses same define for including the GLCORE head… + +Fri, 25 Aug 2017 14:48:42 +0100 +Author : OpenSceneGraph git repository +Merge pull request #325 from emminizer/msvc2015_exportfixRemoved inappropriate use of OSG_EXPORT on DefaultIndirectCommandDrawArrays and De… + +Fri, 25 Aug 2017 09:04:05 -0400 +Author : Daniel Emminizer +SETUP_EXE in CMake now uses same define for including the GLCORE headers as SETUP_LIBRARY and SETUP_PLUGIN. Fixes Windows build errors for applications. + +Fri, 25 Aug 2017 08:55:25 -0400 +Author : Daniel Emminizer +No longer using OSG_EXPORT on DefaultIndirectCommandDrawArrays and DefaultIndirectCommandDrawElements, fixing compile errors in MSVC 2015. + +Fri, 25 Aug 2017 10:04:40 +0100 +Author : OpenSceneGraph git repository +Merge pull request #324 from mp3butcher/osganimationAdd extensions + +Fri, 25 Aug 2017 00:19:22 +0200 +Author : Julien Valentin +Add extensions + +Thu, 24 Aug 2017 15:13:14 +0100 +Author : Robert Osfield +Cleaned up warnings and removed assorts. + +Thu, 24 Aug 2017 13:55:56 +0100 +Author : OpenSceneGraph git repository +Merge pull request #322 from mp3butcher/MDI7fix osggpucull to fit both new BIB and MDI + +Thu, 24 Aug 2017 14:15:09 +0200 +Author : Julien Valentin +fix osggpucull to fit both new BIB and MDI + +Thu, 24 Aug 2017 11:17:43 +0100 +Author : Robert Osfield +Bumped SO version to reflect changes in ABI + +Thu, 24 Aug 2017 11:08:38 +0100 +Author : OpenSceneGraph git repository +Merge pull request #321 from LaurensVoerman/tgaMissingColormapfix gcc/VC compile warnings, reject color mapped tga files with missing colormap. + +Thu, 24 Aug 2017 11:33:23 +0200 +Author : Laurens Voerman +fix gcc/VC compile warnings, reject color mapped tga files with missing colormap. + +Thu, 24 Aug 2017 10:33:44 +0100 +Author : OpenSceneGraph git repository +Merge pull request #320 from mp3butcher/MDI7MultiDrawIndirect + +Thu, 24 Aug 2017 11:26:23 +0200 +Author : Julien Valentin +Merge remote-tracking branch 'upstream/master' into MDI7 + +Thu, 24 Aug 2017 09:53:32 +0100 +Author : OpenSceneGraph git repository +Merge pull request #318 from mp3butcher/osganimationchange the design of BufferIndexBinding to work with BufferData instead of BufferObject +matrix transpose + +Thu, 24 Aug 2017 10:29:19 +0200 +Author : Julien Valentin +comply with osg::BufferIndexBinding new design (a miss) + +Wed, 23 Aug 2017 23:42:12 +0200 +Author : Julien Valentin +change the design of BufferIndexBinding to work with BufferData instead of BufferObject allow convenient BufferData abstraction + serialization of BufferIndexBinding + +Wed, 23 Aug 2017 19:06:25 +0200 +Author : Julien Valentin +add a transpose method for 4x4 and a transpose3x3 to transpose only orthogonal part of a mat4x4 + +Wed, 23 Aug 2017 15:26:07 +0100 +Author : Robert Osfield +Fixed underflow issue + +Wed, 23 Aug 2017 14:51:18 +0100 +Author : Robert Osfield +Fixed comparison to properly handle texture coordinates being assigned + +Wed, 23 Aug 2017 14:48:04 +0100 +Author : OpenSceneGraph git repository +Merge pull request #314 from LaurensVoerman/notify2reduce the need to reallocate the std::ostream buffer behind osg::Notify + +Wed, 23 Aug 2017 14:39:35 +0100 +Author : Robert Osfield +Warning fixes + +Tue, 22 Aug 2017 15:23:47 +0200 +Author : Laurens Voerman +reduce the need to reallocate the std::ostream buffer behind osg::Notify (causing multitreading issues) by pre-allocating 4095 bytes. + +Wed, 23 Aug 2017 08:54:10 +0100 +Author : OpenSceneGraph git repository +Merge pull request #315 from kornerr/masterFix stat64 build issue with NDK 15 by definining it as stat for Android + +Tue, 22 Aug 2017 22:49:56 +0300 +Author : Michael Kapelko +Fix stat64 build issue with NDK 15 by definining at stat for Android + +Tue, 22 Aug 2017 12:04:18 +0100 +Author : Robert Osfield +Updated ChangeLog + Tue, 22 Aug 2017 09:04:49 +0100 Author : Robert Osfield Added catch for controbutors list @@ -165,18 +1822,122 @@ Mon, 7 Aug 2017 16:32:44 +0100 Author : Robert Osfield Added link to ABI tracker +Sun, 6 Aug 2017 15:30:27 +0100 +Author : OpenSceneGraph git repository +Merge pull request #294 from mp3butcher/MDI6add resize methods method in IndirectCommandArrays ..etc.. + +Sat, 5 Aug 2017 18:03:27 +0200 +Author : Julien Valentin +update IndirectCommandArrays interfaces and default impl to use DrawElements like semantic + +Wed, 2 Aug 2017 22:10:02 +0200 +Author : Julien Valentin +add MDI support + +Wed, 2 Aug 2017 21:50:25 +0200 +Author : Julien Valentin +add resize methods method in CommandArrays (it allows user to work without casting to the concrete class result of MDI.getCommandArray()) move getTotalDataSize in CommandArrays interfaces comply with other DrawElementsXXX removing parameters in mdi constructors and add several method ( allow use of osgUtil::DrawElementTypeSimplifer on these) + +Tue, 1 Aug 2017 07:54:37 +0100 +Author : OpenSceneGraph git repository +Merge pull request #293 from mp3butcher/MDI6fix a bug in MDI serializer + +Tue, 1 Aug 2017 02:18:15 +0200 +Author : Julien Valentin +fix a bug in MDI serializer + Mon, 31 Jul 2017 13:38:18 +0100 Author : Robert Osfield Merged #pragmatic shader fix from OpenSceneGraph-3.4 branch. +Mon, 31 Jul 2017 08:09:16 +0100 +Author : OpenSceneGraph git repository +Merge pull request #287 from mp3butcher/MDI6correct a bug and make MDI example more conservative + +Mon, 31 Jul 2017 03:15:03 +0200 +Author : Julien Valentin +fix a bug : indices pre incremented should be post + +Mon, 31 Jul 2017 03:08:52 +0200 +Author : Julien Valentin +Add arguments, command line usage and use DrawElementsUInt for classic case + +Mon, 31 Jul 2017 02:43:50 +0200 +Author : Julien Valentin +correct a bug and make it more conservative + +Sun, 30 Jul 2017 15:40:17 +0100 +Author : OpenSceneGraph git repository +Merge pull request #285 from mp3butcher/MDI6add a very simple example for mdi with basevertex + +Sun, 30 Jul 2017 10:15:32 +0200 +Author : Julien Valentin +add a very simple example for mdi with basevertex + Fri, 28 Jul 2017 17:17:25 +0100 Author : Robert Osfield Updated version number, ChangeLog and AUTHORS file for 3.5.7 developer release +Fri, 28 Jul 2017 14:34:59 +0100 +Author : Robert Osfield +Added missing break statements + +Fri, 28 Jul 2017 14:32:56 +0100 +Author : Robert Osfield +Improved readability and consistency with the rest OSG by adding/removing spaces and brackets where appropriate. + +Fri, 28 Jul 2017 13:30:36 +0100 +Author : Robert Osfield +Improved the readability and consistency with the rest of the OSG by inserting/removing spaces and line spacing. + Fri, 28 Jul 2017 10:27:47 +0100 Author : OpenSceneGraph git repository Merge pull request #267 from kornerr/masterAdd osgemscripten example +Fri, 28 Jul 2017 08:46:30 +0100 +Author : OpenSceneGraph git repository +Merge pull request #278 from mp3butcher/MDI2Mdi + +Thu, 27 Jul 2017 12:27:55 +0200 +Author : mp3butcher +set DIBO of the drawcommandarray directly in their interface constructor it makes osggpu use case lighter + drawcommandarray can't exist without a BO + +Thu, 27 Jul 2017 12:00:41 +0200 +Author : mp3butcher +Promote PrimitiveSetIndirect's VBO to a target explicited DIBO (in order to benefit from BOSet queue management) + +Thu, 27 Jul 2017 10:26:43 +0100 +Author : OpenSceneGraph git repository +Merge pull request #277 from mp3butcher/MDI2PrimitiveSetIndirect cleanup + serializers + +Thu, 27 Jul 2017 01:54:25 +0200 +Author : mp3butcher +add DrawIndirectBufferObject as State variable in order to minimize call to glBindBuffer(GL_DRAW_INDIRECT_BUFFER,X) TODO: Promote PrimitiveSetIndirect's VBO to target explicited DIBO (in order to benefit from BOSet queue management) + +Thu, 27 Jul 2017 01:40:04 +0200 +Author : mp3butcher +remove deprecated DrawIndirectBufferBinding + +Thu, 27 Jul 2017 01:08:37 +0200 +Author : mp3butcher +fix some errors during renaming and cleanup code + +Wed, 26 Jul 2017 23:38:20 +0200 +Author : mp3butcher +add untested serializers for PrimitiveSetIndirect + +Wed, 26 Jul 2017 23:36:55 +0200 +Author : mp3butcher +some renaming and harmonisations with osg metamodel convention + +Wed, 26 Jul 2017 20:46:09 +0100 +Author : Robert Osfield +Merge branch 'MDI2' of https://github.com/mp3butcher/OpenSceneGraph into MultiDrawIndirect + +Wed, 26 Jul 2017 20:25:41 +0200 +Author : mp3butcher +first commit for Indirect Draw integration in osg users will have to implement interfaces for their custom drawcommandarrays add a lot of new primitive set + few defines integration is made in osggpucull + Wed, 26 Jul 2017 12:54:37 +0100 Author : Robert Osfield Replaced FindOurDCMTK.cmake usage with FindDCMTK.cmake diff --git a/applications/osgconv/osgconv.cpp b/applications/osgconv/osgconv.cpp index 8c5ba420d..a324dd0ee 100644 --- a/applications/osgconv/osgconv.cpp +++ b/applications/osgconv/osgconv.cpp @@ -740,7 +740,7 @@ int main( int argc, char **argv ) while(arguments.read("--addMissingColours") || arguments.read("--addMissingColors")) { addMissingColours = true; } bool do_overallNormal = false; - while(arguments.read("--overallNormal") || arguments.read("--overallNormal")) { do_overallNormal = true; } + while(arguments.read("--overallNormal")) { do_overallNormal = true; } bool enableObjectCache = false; while(arguments.read("--enable-object-cache")) { enableObjectCache = true; } diff --git a/applications/osgversion/Contributors.cpp b/applications/osgversion/Contributors.cpp index 86a585b87..9d42686cc 100644 --- a/applications/osgversion/Contributors.cpp +++ b/applications/osgversion/Contributors.cpp @@ -275,7 +275,12 @@ const char* invalidNames[] = "I", "TriangleFunctor", "PrimitiveFunctor", - "OpenMW" + "OpenMW", + "StreamOperator", + "SceneLoader", + "OpenGL", + "FindLIBLAS", + "MinGW" }; @@ -699,7 +704,9 @@ NameCorrection nameCorrections[] = {"WeSee", "", "Alois", "Wismer"}, {"We", "See", - "Alois", "Wismer"} + "Alois", "Wismer"}, + {"AnyOldName3", "", + "Chris", "Djali"} }; diff --git a/applications/osgviewer/osgviewer.cpp b/applications/osgviewer/osgviewer.cpp index d790d3873..0d7919687 100644 --- a/applications/osgviewer/osgviewer.cpp +++ b/applications/osgviewer/osgviewer.cpp @@ -74,14 +74,10 @@ int main(int argc, char** argv) std::string url, username, password; while(arguments.read("--login",url, username, password)) { - if (!osgDB::Registry::instance()->getAuthenticationMap()) - { - osgDB::Registry::instance()->setAuthenticationMap(new osgDB::AuthenticationMap); - osgDB::Registry::instance()->getAuthenticationMap()->addAuthenticationDetails( - url, - new osgDB::AuthenticationDetails(username, password) - ); - } + osgDB::Registry::instance()->getOrCreateAuthenticationMap()->addAuthenticationDetails( + url, + new osgDB::AuthenticationDetails(username, password) + ); } std::string device; diff --git a/applications/present3D/ReadShowFile.cpp b/applications/present3D/ReadShowFile.cpp index 147a54bda..474660cb5 100644 --- a/applications/present3D/ReadShowFile.cpp +++ b/applications/present3D/ReadShowFile.cpp @@ -256,7 +256,7 @@ osg::ref_ptr p3d::readShowFiles(osg::ArgumentParser& arguments,const nodeList.push_back(node); // make sure that this presentation isn't cached - osgDB::Registry::instance()->removeFromObjectCache( arguments[pos] ); + osgDB::Registry::instance()->removeFromObjectCache( arguments[pos], local_options.get()); } } } diff --git a/applications/present3D/present3D.cpp b/applications/present3D/present3D.cpp index 0e0c6abec..24318d9ec 100644 --- a/applications/present3D/present3D.cpp +++ b/applications/present3D/present3D.cpp @@ -336,14 +336,10 @@ int main( int argc, char **argv ) std::string url, username, password; while(arguments.read("--login",url, username, password)) { - if (!osgDB::Registry::instance()->getAuthenticationMap()) - { - osgDB::Registry::instance()->setAuthenticationMap(new osgDB::AuthenticationMap); - osgDB::Registry::instance()->getAuthenticationMap()->addAuthenticationDetails( - url, - new osgDB::AuthenticationDetails(username, password) - ); - } + osgDB::Registry::instance()->getOrCreateAuthenticationMap()->addAuthenticationDetails( + url, + new osgDB::AuthenticationDetails(username, password) + ); } diff --git a/examples/osgAndroidExampleGLES1/jni/OsgMainApp.cpp b/examples/osgAndroidExampleGLES1/jni/OsgMainApp.cpp index c1d930c55..bddcb75df 100644 --- a/examples/osgAndroidExampleGLES1/jni/OsgMainApp.cpp +++ b/examples/osgAndroidExampleGLES1/jni/OsgMainApp.cpp @@ -23,7 +23,7 @@ void OsgMainApp::loadModels(){ newModel = _vModelsToLoad[i]; osg::notify(osg::ALWAYS)<<"Loading: "< loadedModel = osgDB::readNodeFile(newModel.filename); + osg::ref_ptr loadedModel = osgDB::readRefNodeFile(newModel.filename); if (loadedModel == 0) { osg::notify(osg::ALWAYS)<<"Model not loaded"< loadedModel = osgDB::readNodeFile(newModel.filename); + osg::ref_ptr loadedModel = osgDB::readRefNodeFile(newModel.filename); if (loadedModel == 0) { osg::notify(osg::ALWAYS)<<"Model not loaded"< #include #include -#include +#include #include #include #include @@ -167,6 +167,7 @@ class ComputeNode : public osg::PositionAttitudeTransform public: + osg::ref_ptr _computeDispatch; osg::ref_ptr _computeProgram; osg::ref_ptr _computeShader; //compute and write position data in SSBO @@ -200,15 +201,12 @@ public: ComputeNode() { - const char* envOsgFilePath = getenv("OSG_FILE_PATH"); - std::stringstream computeshaderpath; computeshaderpath << envOsgFilePath << "/shaders/osgssboComputeShader.cs"; - _computeShaderSourcePath = computeshaderpath.str(); - std::stringstream vertexshaderpath; vertexshaderpath << envOsgFilePath << "/shaders/osgssboVertexShader.vs"; - _vertexShaderSourcePath = vertexshaderpath.str(); - std::stringstream geometryshaderpath; geometryshaderpath << envOsgFilePath << "/shaders/osgssboGeometryShader.gs"; - _geometryShaderSourcePath = geometryshaderpath.str(); - std::stringstream fragmentshaderpath; fragmentshaderpath << envOsgFilePath << "/shaders/osgssboFragmentShader.fs"; - _fragmentShaderSourcePath = fragmentshaderpath.str(); + _computeShaderSourcePath = "shaders/osgssboComputeShader.cs"; + _vertexShaderSourcePath = "shaders/osgssboVertexShader.vs"; + _geometryShaderSourcePath = "shaders/osgssboGeometryShader.gs"; + _fragmentShaderSourcePath = "shaders/osgssboFragmentShader.fs"; + _computeDispatch=new osg::ComputeDispatch(); + addChild(_computeDispatch); } }; @@ -243,7 +241,7 @@ public: if (_computeNode->_computeShader.valid()) { runningSource = _computeNode->_computeShader->getShaderSource(); - reloadedshader = osg::Shader::readShaderFile(osg::Shader::COMPUTE, _computeNode->_computeShaderSourcePath); + reloadedshader = osgDB::readRefShaderFile(osg::Shader::COMPUTE, _computeNode->_computeShaderSourcePath); reloadedstring = reloadedshader->getShaderSource(); if (!osgDB::equalCaseInsensitive(runningSource.c_str(), reloadedstring.c_str())) @@ -258,7 +256,7 @@ public: { runningSource = _computeNode->_vertexShader->getShaderSource(); - reloadedshader = osg::Shader::readShaderFile(osg::Shader::VERTEX, _computeNode->_vertexShaderSourcePath); + reloadedshader = osgDB::readRefShaderFile(osg::Shader::VERTEX, _computeNode->_vertexShaderSourcePath); reloadedstring = reloadedshader->getShaderSource(); if (!osgDB::equalCaseInsensitive(runningSource.c_str(), reloadedstring.c_str())) @@ -274,7 +272,7 @@ public: if (_computeNode->_geometryShader.valid()) { runningSource = _computeNode->_geometryShader->getShaderSource(); - reloadedshader = osg::Shader::readShaderFile(osg::Shader::GEOMETRY, _computeNode->_geometryShaderSourcePath); + reloadedshader = osgDB::readRefShaderFile(osg::Shader::GEOMETRY, _computeNode->_geometryShaderSourcePath); reloadedstring = reloadedshader->getShaderSource(); if (!osgDB::equalCaseInsensitive(runningSource.c_str(), reloadedstring.c_str())) @@ -288,7 +286,7 @@ public: if (_computeNode->_fragmentShader.valid()) { runningSource = _computeNode->_fragmentShader->getShaderSource(); - reloadedshader = osg::Shader::readShaderFile(osg::Shader::FRAGMENT, _computeNode->_fragmentShaderSourcePath); + reloadedshader = osgDB::readRefShaderFile(osg::Shader::FRAGMENT, _computeNode->_fragmentShaderSourcePath); reloadedstring = reloadedshader->getShaderSource(); if (!osgDB::equalCaseInsensitive(runningSource.c_str(), reloadedstring.c_str())) @@ -473,7 +471,6 @@ void ComputeNode::addDataMonitor(osg::Vec3 placement, osg::Vec3 relativePlacemen pat->setName(labelCaption); text->setText(pat->getName()); text->setBackdropType(osgText::Text::OUTLINE); - text->setBackdropImplementation(osgText::Text::POLYGON_OFFSET); text->setBackdropOffset(0.05f); text->setBackdropColor(osg::Vec4(0.0f, 0.0f, 0.0f, 1.0f)); @@ -518,13 +515,13 @@ void ComputeNode::addComputationResultsRenderTree() _computationResultsRenderProgram = new osg::Program; - _vertexShader = osg::Shader::readShaderFile(osg::Shader::VERTEX, _vertexShaderSourcePath); + _vertexShader = osgDB::readRefShaderFile(osg::Shader::VERTEX, _vertexShaderSourcePath); _computationResultsRenderProgram->addShader(_vertexShader.get()); - _geometryShader = osg::Shader::readShaderFile(osg::Shader::GEOMETRY, _geometryShaderSourcePath); + _geometryShader = osgDB::readRefShaderFile(osg::Shader::GEOMETRY, _geometryShaderSourcePath); _computationResultsRenderProgram->addShader(_geometryShader.get()); - _fragmentShader = osg::Shader::readShaderFile(osg::Shader::FRAGMENT, _fragmentShaderSourcePath); + _fragmentShader = osgDB::readRefShaderFile(osg::Shader::FRAGMENT, _fragmentShaderSourcePath); _computationResultsRenderProgram->addShader(_fragmentShader.get()); @@ -628,8 +625,8 @@ void ComputeNode::initComputingSetup() { _computeProgram = new osg::Program; - _computeProgram->setComputeGroups((NUM_ELEMENTS_X / WORK_GROUP_SIZE) <= 1 ? 1 : (NUM_ELEMENTS_X / WORK_GROUP_SIZE), (NUM_ELEMENTS_Y / WORK_GROUP_SIZE) <= 1 ? 1 : (NUM_ELEMENTS_Y / WORK_GROUP_SIZE), 1); - _computeShader = osg::Shader::readShaderFile(osg::Shader::COMPUTE, _computeShaderSourcePath); + _computeDispatch->setComputeGroups((NUM_ELEMENTS_X / WORK_GROUP_SIZE) <= 1 ? 1 : (NUM_ELEMENTS_X / WORK_GROUP_SIZE), (NUM_ELEMENTS_Y / WORK_GROUP_SIZE) <= 1 ? 1 : (NUM_ELEMENTS_Y / WORK_GROUP_SIZE), 1); + _computeShader = osgDB::readRefShaderFile(osg::Shader::COMPUTE, _computeShaderSourcePath); _computeProgram->addShader(_computeShader.get()); setDataVariance(osg::Object::DYNAMIC); @@ -773,7 +770,7 @@ void ComputeNode::initComputingSetup() _dataArray->setBufferObject(_ssbo.get()); - _ssbb = new osg::ShaderStorageBufferBinding(0, _dataArray, 0, blockSize); + _ssbb = new osg::ShaderStorageBufferBinding(0, _dataArray.get(), 0, blockSize); statesetComputation->setAttributeAndModes(_ssbb.get(), osg::StateAttribute::ON); diff --git a/examples/osganimationhardware/osganimationhardware.cpp b/examples/osganimationhardware/osganimationhardware.cpp index afd56015c..1cb05473f 100644 --- a/examples/osganimationhardware/osganimationhardware.cpp +++ b/examples/osganimationhardware/osganimationhardware.cpp @@ -28,6 +28,8 @@ #include #include #include +#include +#include #include #include @@ -40,89 +42,100 @@ static unsigned int getRandomValueinRange(unsigned int v) } -osg::ref_ptr program; +osg::ref_ptr CommonProgram; // show how to override the default RigTransformHardware for customized usage struct MyRigTransformHardware : public osgAnimation::RigTransformHardware { - - void operator()(osgAnimation::RigGeometry& geom) + int _maxmatrix; + MyRigTransformHardware() : _maxmatrix(99){} + virtual bool init(osgAnimation::RigGeometry& rig) { - if (_needInit) - if (!init(geom)) - return; - computeMatrixPaletteUniform(geom.getMatrixFromSkeletonToGeometry(), geom.getInvMatrixFromSkeletonToGeometry()); - } - - bool init(osgAnimation::RigGeometry& geom) - { - osg::Vec3Array* pos = dynamic_cast(geom.getVertexArray()); - if (!pos) { - osg::notify(osg::WARN) << "RigTransformHardware no vertex array in the geometry " << geom.getName() << std::endl; + if(_perVertexInfluences.empty()) + { + prepareData(rig); return false; } - - if (!geom.getSkeleton()) { - osg::notify(osg::WARN) << "RigTransformHardware no skeleting set in geometry " << geom.getName() << std::endl; + if(!rig.getSkeleton()) return false; - } osgAnimation::BoneMapVisitor mapVisitor; - geom.getSkeleton()->accept(mapVisitor); - osgAnimation::BoneMap bm = mapVisitor.getBoneMap(); + rig.getSkeleton()->accept(mapVisitor); + osgAnimation::BoneMap boneMap = mapVisitor.getBoneMap(); - if (!createPalette(pos->size(),bm, geom.getVertexInfluenceSet().getVertexToBoneList())) + if (!buildPalette(boneMap,rig) ) return false; - int attribIndex = 11; - int nbAttribs = getNumVertexAttrib(); + osg::Geometry& source = *rig.getSourceGeometry(); + osg::Vec3Array* positionSrc = dynamic_cast(source.getVertexArray()); - // use a global program for all avatar - if (!program.valid()) { - program = new osg::Program; - program->setName("HardwareSkinning"); - if (!_shader.valid()) - _shader = osg::Shader::readShaderFile(osg::Shader::VERTEX,"shaders/skinning.vert"); + if (!positionSrc) + { + OSG_WARN << "RigTransformHardware no vertex array in the geometry " << rig.getName() << std::endl; + return false; + } - if (!_shader.valid()) { - osg::notify(osg::WARN) << "RigTransformHardware can't load VertexShader" << std::endl; + // copy shallow from source geometry to rig + rig.copyFrom(source); + + osg::ref_ptr vertexshader; + osg::ref_ptr stateset = rig.getOrCreateStateSet(); + if(!CommonProgram.valid()) + { + CommonProgram = new osg::Program; + CommonProgram->setName("HardwareSkinning"); + + //set default source if _shader is not user setted + if (!vertexshader.valid()) + { + vertexshader = osgDB::readRefShaderFile(osg::Shader::VERTEX,"skinning.vert"); + } + + if (!vertexshader.valid()) + { + OSG_WARN << "RigTransformHardware can't load VertexShader" << std::endl; return false; } // replace max matrix by the value from uniform { - std::string str = _shader->getShaderSource(); + std::string str = vertexshader->getShaderSource(); std::string toreplace = std::string("MAX_MATRIX"); std::size_t start = str.find(toreplace); - std::stringstream ss; - ss << getMatrixPaletteUniform()->getNumElements(); - str.replace(start, toreplace.size(), ss.str()); - _shader->setShaderSource(str); - osg::notify(osg::INFO) << "Shader " << str << std::endl; - } - - program->addShader(_shader.get()); - - for (int i = 0; i < nbAttribs; i++) - { - std::stringstream ss; - ss << "boneWeight" << i; - program->addBindAttribLocation(ss.str(), attribIndex + i); - - osg::notify(osg::INFO) << "set vertex attrib " << ss.str() << std::endl; + if (std::string::npos != start) + { + std::stringstream ss; + ss << _maxmatrix;//getMatrixPaletteUniform()->getNumElements(); + str.replace(start, toreplace.size(), ss.str()); + vertexshader->setShaderSource(str); + } + else + { + OSG_WARN<< "MAX_MATRIX not found in Shader! " << str << std::endl; + } + OSG_INFO << "Shader " << str << std::endl; } + CommonProgram->addShader(vertexshader.get()); } - for (int i = 0; i < nbAttribs; i++) + + unsigned int nbAttribs = getNumVertexAttrib(); + for (unsigned int i = 0; i < nbAttribs; i++) { std::stringstream ss; ss << "boneWeight" << i; - geom.setVertexAttribArray(attribIndex + i, getVertexAttrib(i)); + CommonProgram->addBindAttribLocation(ss.str(), _minAttribIndex + i); + rig.setVertexAttribArray(_minAttribIndex + i, getVertexAttrib(i)); + OSG_INFO << "set vertex attrib " << ss.str() << std::endl; } - osg::ref_ptr ss = new osg::StateSet; - ss->addUniform(getMatrixPaletteUniform()); - ss->addUniform(new osg::Uniform("nbBonesPerVertex", getNumBonesPerVertex())); - ss->setAttributeAndModes(program.get()); - geom.setStateSet(ss.get()); + + stateset->removeUniform("nbBonesPerVertex"); + stateset->addUniform(new osg::Uniform("nbBonesPerVertex",_bonesPerVertex)); + + stateset->removeUniform("matrixPalette"); + stateset->addUniform(_uniformMatrixPalette); + + stateset->setAttribute(CommonProgram.get()); + _needInit = false; return true; } @@ -133,6 +146,7 @@ struct MyRigTransformHardware : public osgAnimation::RigTransformHardware struct SetupRigGeometry : public osg::NodeVisitor { bool _hardware; + SetupRigGeometry( bool hardware = true) : osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN), _hardware(hardware) {} void apply(osg::Geode& geode) @@ -142,10 +156,15 @@ struct SetupRigGeometry : public osg::NodeVisitor } void apply(osg::Drawable& geom) { - if (_hardware) { + if (_hardware) + { osgAnimation::RigGeometry* rig = dynamic_cast(&geom); if (rig) + { rig->setRigTransformImplementation(new MyRigTransformHardware); + osgAnimation::MorphGeometry *morph=dynamic_cast(rig->getSourceGeometry()); + if(morph)morph->setMorphTransformImplementation(new osgAnimation::MorphTransformHardware); + } } #if 0 @@ -169,7 +188,8 @@ osg::Group* createCharacterInstance(osg::Group* character, bool hardware) osgAnimation::BasicAnimationManager* anim = dynamic_cast(animationManager); const osgAnimation::AnimationList& list = animationManager->getAnimationList(); int v = getRandomValueinRange(list.size()); - if (list[v]->getName() == std::string("MatIpo_ipo")) { + if (list[v]->getName() == std::string("MatIpo_ipo")) + { anim->playAnimation(list[v].get()); v = (v + 1)%list.size(); } @@ -193,7 +213,10 @@ int main (int argc, char* argv[]) bool hardware = true; int maxChar = 10; - while (psr.read("--software")) { hardware = false; } + while (psr.read("--software")) + { + hardware = false; + } while (psr.read("--number", maxChar)) {} osg::ref_ptr node = osgDB::readRefNodeFiles(psr); @@ -243,9 +266,10 @@ int main (int argc, char* argv[]) double xChar = maxChar; double yChar = xChar * 9.0/16; - for (double i = 0.0; i < xChar; i++) { - for (double j = 0.0; j < yChar; j++) { - + for (double i = 0.0; i < xChar; i++) + { + for (double j = 0.0; j < yChar; j++) + { osg::ref_ptr c = createCharacterInstance(root.get(), hardware); osg::MatrixTransform* tr = new osg::MatrixTransform; tr->setMatrix(osg::Matrix::translate( 2.0 * (i - xChar * .5), @@ -257,7 +281,6 @@ int main (int argc, char* argv[]) } std::cout << "created " << xChar * yChar << " instance" << std::endl; - return viewer.run(); } diff --git a/examples/osganimationskinning/osganimationskinning.cpp b/examples/osganimationskinning/osganimationskinning.cpp index 7bfa9b017..2536353a6 100644 --- a/examples/osganimationskinning/osganimationskinning.cpp +++ b/examples/osganimationskinning/osganimationskinning.cpp @@ -134,13 +134,10 @@ void initVertexMap(osgAnimation::Bone* b0, osgAnimation::RigGeometry* geom, osg::Vec3Array* array) { - osgAnimation::VertexInfluenceSet vertexesInfluences; osgAnimation::VertexInfluenceMap* vim = new osgAnimation::VertexInfluenceMap; - (*vim)[b0->getName()].setName(b0->getName()); (*vim)[b1->getName()].setName(b1->getName()); (*vim)[b2->getName()].setName(b2->getName()); - for (int i = 0; i < (int)array->size(); i++) { float val = (*array)[i][0]; diff --git a/examples/osgcomputeshaders/osgcomputeshaders.cpp b/examples/osgcomputeshaders/osgcomputeshaders.cpp index 87073cfe5..7d87a7472 100644 --- a/examples/osgcomputeshaders/osgcomputeshaders.cpp +++ b/examples/osgcomputeshaders/osgcomputeshaders.cpp @@ -20,7 +20,7 @@ // This example can work only if GL version is 4.3 or greater #include -#include +#include #include #include #include @@ -57,14 +57,12 @@ int main( int argc, char** argv ) // The compute shader can't work with other kinds of shaders // It also requires the work group numbers. Setting them to 0 will disable the compute shader osg::ref_ptr computeProg = new osg::Program; - computeProg->setComputeGroups( 512/16, 512/16, 1 ); computeProg->addShader( new osg::Shader(osg::Shader::COMPUTE, computeSrc) ); // Create a node for outputting to the texture. // It is OK to have just an empty node here, but seems inbuilt uniforms like osg_FrameTime won't work then. // TODO: maybe we can have a custom drawable which also will implement glMemoryBarrier? - osg::ref_ptr sourceNode = osgDB::readRefNodeFile("axes.osgt"); - if ( !sourceNode ) sourceNode = new osg::Node; + osg::ref_ptr sourceNode = new osg::ComputeDispatch(512/16, 512/16, 1 ); sourceNode->setDataVariance( osg::Object::DYNAMIC ); sourceNode->getOrCreateStateSet()->setAttributeAndModes( computeProg.get() ); sourceNode->getOrCreateStateSet()->addUniform( new osg::Uniform("targetTex", (int)0) ); diff --git a/examples/osgdeferred/osgdeferred.cpp b/examples/osgdeferred/osgdeferred.cpp index 2343c438e..e7bbbf7e5 100644 --- a/examples/osgdeferred/osgdeferred.cpp +++ b/examples/osgdeferred/osgdeferred.cpp @@ -188,12 +188,12 @@ osg::ref_ptr createSceneRoom() { // Room. osg::ref_ptr room = new osg::MatrixTransform; - osg::ref_ptr roomModel = osgDB::readNodeFile("simpleroom.osgt"); + osg::ref_ptr roomModel = osgDB::readRefNodeFile("simpleroom.osgt"); room->addChild(roomModel); room->setMatrix(osg::Matrix::translate(0, 0, 1)); // Torus. osg::ref_ptr torus = new osg::MatrixTransform; - osg::ref_ptr torusModel = osgDB::readNodeFile("torus.osgt"); + osg::ref_ptr torusModel = osgDB::readRefNodeFile("torus.osgt"); torus->addChild(torusModel); setAnimationPath(torus, osg::Vec3(0, 0, 15), 6, 16); // Torus2. @@ -240,7 +240,7 @@ osg::Geode *createScreenQuad(float width, osg::Texture2D *createTexture(const std::string &fileName) { osg::ref_ptr texture = new osg::Texture2D; - texture->setImage(osgDB::readImageFile(fileName)); + texture->setImage(osgDB::readRefImageFile(fileName)); texture->setWrap(osg::Texture2D::WRAP_S, osg::Texture2D::REPEAT); texture->setWrap(osg::Texture2D::WRAP_T, osg::Texture2D::REPEAT); texture->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_LINEAR); @@ -292,8 +292,8 @@ osg::ref_ptr setShaderProgram(osg::ref_ptr pass, const std::string& frag) { osg::ref_ptr program = new osg::Program; - program->addShader(osgDB::readShaderFile(vert)); - program->addShader(osgDB::readShaderFile(frag)); + program->addShader(osgDB::readRefShaderFile(vert)); + program->addShader(osgDB::readRefShaderFile(frag)); osg::ref_ptr ss = pass->getOrCreateStateSet(); ss->setAttributeAndModes( program.get(), @@ -313,7 +313,7 @@ int main() // Shadowed scene. osg::ref_ptr shadowMap = new osgShadow::SoftShadowMap; shadowMap->setJitteringScale(16); - shadowMap->addShader(osgDB::readShaderFile("shaders/pass1Shadow.frag")); + shadowMap->addShader(osgDB::readRefShaderFile("shaders/pass1Shadow.frag")); shadowMap->setLight(light.get()); osg::ref_ptr shadowedScene = new osgShadow::ShadowedScene; shadowedScene->setShadowTechnique(shadowMap.get()); diff --git a/examples/osgfadetext/osgfadetext.cpp b/examples/osgfadetext/osgfadetext.cpp index 37b0eafe2..308b482b6 100644 --- a/examples/osgfadetext/osgfadetext.cpp +++ b/examples/osgfadetext/osgfadetext.cpp @@ -121,10 +121,70 @@ osg::Node* createFadeText(osg::EllipsoidModel* ellipsoid) } -int main(int, char**) +class TextSettings : public osg::NodeVisitor { +public: + TextSettings(osg::ArgumentParser& arguments): + osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN), + _backdropTypeSet(false), + _backdropType(osgText::Text::NONE), + _shaderTechniqueSet(false), + _shaderTechnique(osgText::GREYSCALE) + { + if (arguments.read("--outline")) + { + _backdropTypeSet = true; + _backdropType = osgText::Text::OUTLINE; + } + if (arguments.read("--sdf")) + { + _shaderTechniqueSet = true; + _shaderTechnique = osgText::SIGNED_DISTANCE_FIELD; + } + if (arguments.read("--all")) + { + _shaderTechniqueSet = true; + _shaderTechnique = osgText::ALL_FEATURES; + } + if (arguments.read("--greyscale")) + { + _shaderTechniqueSet = true; + _shaderTechnique = osgText::GREYSCALE; + } + if (arguments.read("--no-shader")) + { + _shaderTechniqueSet = true; + _shaderTechnique = osgText::NO_TEXT_SHADER; + } + } + + void apply(osg::Drawable& drawable) + { + osgText::Text* text = dynamic_cast(&drawable); + if (text) + { + if (_backdropTypeSet) + { + text->setBackdropType(_backdropType); + text->setBackdropOffset(0.1f); + text->setBackdropColor(osg::Vec4(1.0f, 0.0f, 0.0f, 1.0f)); + } + if (_shaderTechniqueSet) text->setShaderTechnique(_shaderTechnique); + } + } + + bool _backdropTypeSet; + osgText::Text::BackdropType _backdropType; + bool _shaderTechniqueSet; + osgText::ShaderTechnique _shaderTechnique; +}; + +int main(int argc, char** argv) +{ + osg::ArgumentParser arguments(&argc, argv); + // construct the viewer. - osgViewer::Viewer viewer; + osgViewer::Viewer viewer(arguments); viewer.getCamera()->setComputeNearFarMode(osg::CullSettings::COMPUTE_NEAR_FAR_USING_PRIMITIVES); viewer.getCamera()->setNearFarRatio(0.00001f); @@ -144,6 +204,12 @@ int main(int, char**) csn->addChild(createFadeText(csn->getEllipsoidModel())); } + if (arguments.argc()>1) + { + TextSettings textSettings(arguments); + root->accept(textSettings); + } + viewer.setCameraManipulator(new osgGA::TerrainManipulator); return viewer.run(); diff --git a/examples/osgfont/osgfont.cpp b/examples/osgfont/osgfont.cpp index 9255bea0c..bad750798 100644 --- a/examples/osgfont/osgfont.cpp +++ b/examples/osgfont/osgfont.cpp @@ -3,6 +3,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -56,80 +59,367 @@ osg::Camera* createOrthoCamera(double width, double height) return camera; } -osgText::Text* createLabel(const std::string& l, const char* f, unsigned int size) +typedef std::list Sizes; + +struct TextSettings { - static osg::Vec3 pos(10.0f, 10.0f, 0.0f); + TextSettings(): + fontFilename("fonts/arial.ttf"), + minFilter(osg::Texture::LINEAR_MIPMAP_LINEAR), + magFilter(osg::Texture::LINEAR), + maxAnisotropy(16.0f), + shaderTechnique(osgText::GREYSCALE), + textColor(1.0f, 1.0f, 1.0f, 1.0f), + backdropType(osgText::Text::NONE), + backdropOffset(0.07f, 0.07f), + backdropColor(0.0f, 0.0f, 0.0f, 1.0f), + scaleFontSizeToFontResolution(false) + { + } + + void readFilterMode(const std::string& value, osg::Texture::FilterMode& filterMode) + { + if (value=="LINEAR") filterMode = osg::Texture::LINEAR; + else if (value=="NEAREST") filterMode = osg::Texture::NEAREST; + else if (value=="LINEAR_MIPMAP_LINEAR") filterMode = osg::Texture::LINEAR_MIPMAP_LINEAR; + } + + void read(osg::ArgumentParser& arguments) + { + if (arguments.read("--test")) + { + backgroundColor = osg::Vec4(1.0, 1.0, 1.0, 1.0); + + fontFilename = "fonts/arialbd.ttf"; + backdropType = osgText::Text::OUTLINE; + + sizes.clear(); + sizes.push_back(8); + sizes.push_back(16); + sizes.push_back(32); + sizes.push_back(64); + sizes.push_back(128); + } + + if (arguments.read("--GREYSCALE")) { shaderTechnique = osgText::GREYSCALE; } + if (arguments.read("--SIGNED_DISTANCE_FIELD")) { shaderTechnique = osgText::SIGNED_DISTANCE_FIELD; } + if (arguments.read("--ALL_FEATURES")) { shaderTechnique = osgText::ALL_FEATURES; } + + if (arguments.read("--font",fontFilename)) {} + + std::string value; + if (arguments.read("--min", value)) { readFilterMode(value, minFilter); } + if (arguments.read("--mag", value)) { readFilterMode(value, magFilter); } + + if (arguments.read("--anisotropy",maxAnisotropy)) {} + + + if (arguments.read("--outline")) backdropType = osgText::Text::OUTLINE; + if (arguments.read("--shadow")) backdropType = osgText::Text::DROP_SHADOW_BOTTOM_RIGHT; + if (arguments.read("--shadow-br")) backdropType = osgText::Text::DROP_SHADOW_BOTTOM_RIGHT; + if (arguments.read("--shadow-cr")) backdropType = osgText::Text::DROP_SHADOW_CENTER_RIGHT; + if (arguments.read("--shadow-tr")) backdropType = osgText::Text::DROP_SHADOW_TOP_RIGHT; + if (arguments.read("--shadow-bc")) backdropType = osgText::Text::DROP_SHADOW_BOTTOM_CENTER; + if (arguments.read("--shadow-tc")) backdropType = osgText::Text::DROP_SHADOW_TOP_CENTER; + if (arguments.read("--shadow-bl")) backdropType = osgText::Text::DROP_SHADOW_BOTTOM_LEFT; + if (arguments.read("--shadow-cl")) backdropType = osgText::Text::DROP_SHADOW_CENTER_LEFT; + if (arguments.read("--shadow-tl")) backdropType = osgText::Text::DROP_SHADOW_TOP_LEFT; + + + + float offset; + if (arguments.read("--offset", offset)) backdropOffset.set(offset, offset); + + if (arguments.read("--text-color", textColor.r(), textColor.g(), textColor.b(), textColor.a())) {} + if (arguments.read("--bd-color", backdropColor.r(), backdropColor.g(), backdropColor.b(), backdropColor.a())) {} + if (arguments.read("--bg-color", backgroundColor.r(), backgroundColor.g(), backgroundColor.b(), backgroundColor.a())) {} + + if (arguments.read("--constant-size")) scaleFontSizeToFontResolution = false; + if (arguments.read("--scale-size")) scaleFontSizeToFontResolution = true; + + } + + void setText(osgText::Text& text) + { + OSG_NOTICE<<"Settings::setText()"< font; + + if (fontFilename!="default") font = osgText::readRefFontFile(fontFilename); + + if (!font) font = osgText::Font::getDefaultFont(); + + font->setMinFilterHint(minFilter); + font->setMagFilterHint(magFilter); + font->setMaxAnisotropy(maxAnisotropy); + + text.setColor(textColor); + text.setBackdropType(backdropType); + text.setBackdropOffset(backdropOffset.x(), backdropOffset.y()); + text.setBackdropColor(backdropColor); + text.setShaderTechnique(shaderTechnique); + + text.setFont(font.get()); + + } + + std::string fontFilename; + osg::Texture::FilterMode minFilter; + osg::Texture::FilterMode magFilter; + float maxAnisotropy; + osgText::ShaderTechnique shaderTechnique; + + osg::Vec4 textColor; + osgText::Text::BackdropType backdropType; + osg::Vec2 backdropOffset; + osg::Vec4 backdropColor; + osg::Vec4 backgroundColor; + Sizes sizes; + bool scaleFontSizeToFontResolution; +}; + +osgText::Text* createLabel(const std::string& l, TextSettings& settings, unsigned int size, osg::Vec3& pos) +{ osgText::Text* label = new osgText::Text(); - osg::ref_ptr font = osgText::readRefFontFile(f); - label->setFont(font); - label->setCharacterSize(size); + settings.setText(*label); + + if (settings.scaleFontSizeToFontResolution) + { + label->setCharacterSize(size); + } + label->setFontResolution(size, size); - label->setColor(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f)); label->setPosition(pos); label->setAlignment(osgText::Text::LEFT_BOTTOM); // It seems to be important we do this last to get best results? label->setText(l); - textInfo(label); + // textInfo(label); - pos.y() += size + 10.0f; + pos.y() += label->getCharacterHeight()*2.0; return label; } -typedef std::list Sizes; +class KeyHandler : public osgGA::GUIEventHandler +{ +public: + + KeyHandler() {} + + ~KeyHandler() {} + + bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) + { + osgViewer::View* view = dynamic_cast(&aa); + if (!view) return false; + +#if 1 + osg::StateSet* stateset = view->getSceneData()->getOrCreateStateSet(); +#else + osg::StateSet* stateset = view->getCamera()->getOrCreateStateSet(); +#endif + switch(ea.getEventType()) + { + case(osgGA::GUIEventAdapter::KEYUP): + { + if (ea.getKey()=='d') + { + toggleDefine(stateset, "SIGNED_DISTANCE_FIELD"); + return true; + } + else if (ea.getKey()=='o') + { + toggleDefine(stateset, "OUTLINE"); + return true; + } + break; + } + default: + break; + } + return false; + } + + void toggleDefine(osg::StateSet* stateset, const std::string& define) + { + osg::StateSet::DefinePair* dp = stateset->getDefinePair(define); + if (dp) + { + OSG_NOTICE<<"Disabling "<removeDefine(define); + } + else + { + OSG_NOTICE<<"Enabling "<setDefine(define); + } + } +}; + int main(int argc, char** argv) { - osgViewer::Viewer viewer; osg::ArgumentParser args(&argc, argv); - - // Make sure we have the minimum args... - if(argc <= 2) - { - osg::notify(osg::FATAL) << "usage: " << args[0] << " fontfile size1 [size2 ...]" << std::endl; - - return 1; - } + osgViewer::Viewer viewer(args); - viewer.addEventHandler( new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()) ); + viewer.addEventHandler(new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet())); viewer.addEventHandler(new osgViewer::StatsHandler()); viewer.addEventHandler(new osgViewer::WindowSizeHandler()); + viewer.addEventHandler(new KeyHandler()); - osg::Group* group = new osg::Group(); - osg::Camera* camera = createOrthoCamera(1280.0f, 1024.0f); + TextSettings settings; + settings.backgroundColor = viewer.getCamera()->getClearColor(); - // Create the list of desired sizes. - Sizes sizes; + settings.read(args); - for(int i = 2; i < argc; i++) + viewer.getCamera()->setClearColor(settings.backgroundColor); + + osg::ref_ptr root = new osg::Group; + + bool split_screen = args.read("--split"); + + if (split_screen) { - if(!args.isNumber(i)) continue; + viewer.realize(); - sizes.push_back(std::atoi(args[i])); + // quite an dirty divusion of the master Camera's window if one is assigned. + if (viewer.getCamera()->getGraphicsContext()) + { + viewer.stopThreading(); + + osg::ref_ptr gc = viewer.getCamera()->getGraphicsContext(); + osg::ref_ptr traits = gc->getTraits(); + + // left half + { + osg::ref_ptr camera = new osg::Camera; + camera->setCullMask(0x1); + camera->setGraphicsContext(gc.get()); + camera->setViewport(new osg::Viewport(0,0, traits->width/2, traits->height)); + viewer.addSlave(camera.get(), osg::Matrixd::translate(1.0,0.0,0.0), osg::Matrixd::scale(2.0, 1.0, 1.0)); + } + + { + osg::ref_ptr camera = new osg::Camera; + camera->setCullMask(0x2); + camera->setGraphicsContext(gc.get()); + camera->setViewport(new osg::Viewport(traits->width/2+2,0, traits->width/2, traits->height)); + viewer.addSlave(camera.get(), osg::Matrixd::translate(-1.0,0.0,0.0), osg::Matrixd::scale(2.0, 1.0, 1.0)); + } + + viewer.getCamera()->setGraphicsContext(0); + + viewer.startThreading(); + } + else + { + split_screen = false; + } } - osg::Geode* geode = new osg::Geode(); + osg::ref_ptr transform = new osg::MatrixTransform; + transform->setMatrix(osg::Matrixd::rotate(osg::DegreesToRadians(90.0), 1.0, 0.0, 0.0)); + root->addChild(transform.get()); + root = transform; + + osg::ref_ptr program = new osg::Program; + std::string shaderFilename; + while(args.read("--shader", shaderFilename)) + { + osg::ref_ptr shader = osgDB::readRefShaderFile(shaderFilename); + if (shader.get()) + { + OSG_NOTICE<<"Loading shader "<addShader(shader.get()); + } + } + + if (program->getNumShaders()>0) + { + OSG_NOTICE<<"Using shaders"<getOrCreateStateSet()->setAttribute(program.get(), osg::StateAttribute::OVERRIDE | osg::StateAttribute::ON); + root->getOrCreateStateSet()->addUniform(new osg::Uniform("glyphTexture", 0)); + + settings.shaderTechnique = osgText::ALL_FEATURES; + } + + + std::string outputFilename; + if (args.read("-o", outputFilename)) {} + + if (args.argc() > 1) + { + settings.fontFilename = argv[1]; + + // Create the list of desired sizes. + for(int i = 2; i < args.argc(); i++) + { + if(!args.isNumber(i)) continue; + + settings.sizes.push_back(std::atoi(args[i])); + } + } + + if (settings.sizes.empty()) + { + settings.sizes.push_back(8); + settings.sizes.push_back(16); + settings.sizes.push_back(32); + settings.sizes.push_back(64); + } + + osg::ref_ptr geode = new osg::Geode(); + + osg::Vec3 pos(0.0f, 0.0f, 0.0f); // Add all of our osgText drawables. - for(Sizes::const_iterator i = sizes.begin(); i != sizes.end(); i++) + for(Sizes::const_iterator i = settings.sizes.begin(); i != settings.sizes.end(); i++) { std::stringstream ss; ss << *i << " 1234567890 abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - geode->addDrawable(createLabel(ss.str(), args[1], *i)); + geode->addDrawable(createLabel(ss.str(), settings, *i, pos)); } - camera->addChild(geode); + root->addChild(geode.get()); - group->addChild(camera); + if (split_screen) + { + geode->setNodeMask(0x1); - viewer.setSceneData(group); + osg::ref_ptr right_geode = new osg::Geode; + right_geode->setNodeMask(0x2); + + settings.shaderTechnique = osgText::GREYSCALE; + + pos.set(0.0f, 0.0f, 0.0f); + + for(Sizes::const_iterator i = settings.sizes.begin(); i != settings.sizes.end(); i++) + { + std::stringstream ss; + + ss << *i << " 1234567890 abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + + right_geode->addDrawable(createLabel(ss.str(), settings, *i, pos)); + } + + root->addChild(right_geode); + } + + + if (!outputFilename.empty()) + { + osgDB::writeNodeFile(*root, outputFilename); + return 0; + } + + viewer.setSceneData(root.get()); return viewer.run(); } diff --git a/examples/osgframerenderer/osgframerenderer.cpp b/examples/osgframerenderer/osgframerenderer.cpp index baf8f2c9c..7c0eddaf9 100644 --- a/examples/osgframerenderer/osgframerenderer.cpp +++ b/examples/osgframerenderer/osgframerenderer.cpp @@ -196,7 +196,11 @@ int main( int argc, char **argv ) newCameraProperty = true; cp = new gsc::CameraProperty; - osg::ref_ptr node = fc->getInputFileName().empty() ? 0 : osgDB::readNodeFile(fc->getInputFileName()); + osg::ref_ptr node; + if (!fc->getInputFileName().empty()) + { + osgDB::readRefNodeFile(fc->getInputFileName()); + } if (node.valid()) { cp->setToModel(node.get()); @@ -522,7 +526,7 @@ int main( int argc, char **argv ) gsc::CaptureSettings* fc = itr->get(); screenShot->_frameCapture = fc; - osg::ref_ptr model = osgDB::readNodeFile(fc->getInputFileName()); + osg::ref_ptr model = osgDB::readRefNodeFile(fc->getInputFileName()); if (!model) break; viewer.setSceneData(model.get()); diff --git a/examples/osggameoflife/GameOfLifePass.cpp b/examples/osggameoflife/GameOfLifePass.cpp index 0cab6f16f..1e3490917 100644 --- a/examples/osggameoflife/GameOfLifePass.cpp +++ b/examples/osggameoflife/GameOfLifePass.cpp @@ -18,6 +18,7 @@ #include "GameOfLifePass.h" #include +#include #include ProcessPass::ProcessPass(osg::TextureRectangle *in_tex, @@ -110,16 +111,13 @@ void ProcessPass::setupCamera() void ProcessPass::setShader(std::string filename) { - std::string foundFile = osgDB::findDataFile(filename); - if (foundFile.empty()) + osg::ref_ptr fshader = osgDB::readRefShaderFile(osg::Shader::FRAGMENT, filename); + if (!fshader) { osg::notify(osg::NOTICE)<<"Could not file shader file: "< fshader = new osg::Shader( osg::Shader::FRAGMENT ); - fshader->loadShaderSourceFromFile(foundFile); - _FragmentProgram = 0; _FragmentProgram = new osg::Program; diff --git a/examples/osggpucull/osggpucull.cpp b/examples/osggpucull/osggpucull.cpp index 78650cc16..7b8bd8a1d 100644 --- a/examples/osggpucull/osggpucull.cpp +++ b/examples/osggpucull/osggpucull.cpp @@ -13,6 +13,137 @@ * */ + /** osggpucull example. + + A geometry instancing rendering algorithm consisting of two consequent phases : + + - first phase is a GLSL shader performing object culling and LOD picking ( a culling shader ). + Every culled object is represented as GL_POINT in the input osg::Geometry. + The output of the culling shader is a set of object LODs that need to be rendered. + The output is stored in texture buffer objects. No pixel is drawn to the screen + because GL_RASTERIZER_DISCARD mode is used. + + - second phase draws osg::Geometry containing merged LODs using glDrawArraysIndirect() + function. Information about quantity of instances to render, its positions and other + parameters is sourced from texture buffer objects filled in the first phase. + + The example uses various OpenGL 4.2 features such as texture buffer objects, + atomic counters, image units and functions defined in GL_ARB_shader_image_load_store + extension to achieve its goal and thus will not work on graphic cards with older OpenGL + versions. + + The example was tested on Linux and Windows with NVidia 570 and 580 cards. + The tests on AMD cards were not conducted ( due to lack of it ). + The tests were performed using OSG revision 14088. + + The main advantages of this rendering method : + - instanced rendering capable of drawing thousands of different objects with + almost no CPU intervention ( cull and draw times are close to 0 ms ). + - input objects may be sourced from any OSG graph ( for example - information about + object points may be stored in a PagedLOD graph. This way we may cover the whole + countries with trees, buildings and other objects ). + Furthermore if we create osgDB plugins that generate data on the fly, we may + generate information for every grass blade for that country. + - every object may have its own parameters and thus may be distinct from other objects + of the same type. + - relatively low memory footprint ( single object information is stored in a few + vertex attributes ). + - no GPU->CPU roundtrip typical for such methods ( method uses atomic counters + and glDrawArraysIndirect() function instead of OpenGL queries. This way + information about quantity of rendered objects never goes back to CPU. + The typical GPU->CPU roundtrip cost is about 2 ms ). + - this example also shows how to render dynamic objects ( objects that may change + its position ) with moving parts ( like car wheels or airplane propellers ) . + The obvious extension to that dynamic method would be the animated crowd rendering. + - rendered objects may be easily replaced ( there is no need to process the whole + OSG graphs, because these graphs store only positional information ). + + The main disadvantages of a method : + - the maximum quantity of objects to render must be known beforehand + ( because texture buffer objects holding data between phases have constant size ). + - OSG statistics are flawed ( they don't know anymore how many objects are drawn ). + - osgUtil::Intersection does not work + + Example application may be used to make some performance tests, so below you + will find some extended parameter description : + --skip-dynamic - skip rendering of dynamic objects if you only want to + observe static object statistics + --skip-static - the same for static objects + --dynamic-area-size - size of the area for dynamic rendering. Default = 1000 meters + ( square 1000m x 1000m ). Along with density defines + how many dynamic objects is there in the example. + --static-area-size - the same for static objects. Default = 2000 meters + ( square 2000m x 2000m ). + + Example application defines some parameters (density, LOD ranges, object's triangle count). + You may manipulate its values using below described modifiers: + --density-modifier - density modifier in percent. Default = 100%. + Density ( along with LOD ranges ) defines maximum + quantity of rendered objects. registerType() function + accepts maximum density ( in objects per square kilometer ) + as its parameter. + --lod-modifier - defines the LOD ranges. Default = 100%. + --triangle-modifier - defines the number of triangles in finally rendered objects. + Default = 100 %. + --instances-per-cell - for static rendering the application builds OSG graph using + InstanceCell class ( this class is a modified version of Cell class + from osgforest example - it builds simple quadtree from a list + of static instances ). This parameter defines maximum number + of instances in a single osg::Group in quadtree. + If, for example, you modify it to value=100, you will see + really big cull time in OSG statistics ( because resulting + tree generated by InstanceCell will be very deep ). + Default value = 4096 . + --export-objects - write object geometries and quadtree of instances to osgt files + for later analysis. + --use-multi-draw - use glMultiDrawArraysIndirect() instead of glDrawArraysIndirect() in a + draw shader. Thanks to this we may render all ( different ) objects + using only one draw call. Requires OpenGL version 4.3. + + This application is inspired by Daniel Rákos work : "GPU based dynamic geometry LOD" that + may be found under this address : http://rastergrid.com/blog/2010/10/gpu-based-dynamic-geometry-lod/ + There are however some differences : + - Daniel Rákos uses GL queries to count objects to render, while this example + uses atomic counters ( no GPU->CPU roundtrip ) + - this example does not use transform feedback buffers to store intermediate data + ( it uses texture buffer objects instead ). + - I use only the vertex shader to cull objects, whereas Daniel Rákos uses vertex shader + and geometry shader ( because only geometry shader can send more than one primitive + to transform feedback buffers ). + - objects in the example are drawn using glDrawArraysIndirect() function, + instead of glDrawElementsInstanced(). + + Finally there are some things to consider/discuss : + - the whole algorithm exploits nice OpenGL feature that any GL buffer + may be bound as any type of buffer ( in our example a buffer is once bound + as a texture buffer object, and later is bound as GL_DRAW_INDIRECT_BUFFER ). + osg::TextureBuffer class has one handy method to do that trick ( bindBufferAs() ), + and new primitive sets use osg::TextureBuffer as input. + For now I added new primitive sets to example ( DrawArraysIndirect and + MultiDrawArraysIndirect defined in examples/osggpucull/DrawIndirectPrimitiveSet.h ), + but if Robert will accept its current implementations ( I mean - primitive + sets that have osg::TextureBuffer in constructor ), I may add it to + osg/include/PrimitiveSet header. + - I used BufferTemplate class writen and published by Aurelien in submission forum + some time ago. For some reason this class never got into osg/include, but is + really needed during creation of UBOs, TBOs, and possibly SSBOs in the future. + I added std::vector specialization to that template class. + - I needed to create similar osg::Geometries with variable number of vertices + ( to create different LODs in my example ). For this reason I've written + some code allowing me to create osg::Geometries from osg::Shape descendants. + This code may be found in ShapeToGeometry.* files. Examples of use are in + osggpucull.cpp . The question is : should this code stay in example, or should + it be moved to osgUtil ? + - this remark is important for NVidia cards on Linux and Windows : if + you have "Sync to VBlank" turned ON in nvidia-settings and you want to see + real GPU times in OSG statistics window, you must set the power management + settings to "Prefer maximum performance", because when "Adaptive mode" is used, + the graphic card's clock may be slowed down by the driver during program execution + ( On Linux when OpenGL application starts in adaptive mode, clock should work + as fast as possible, but after one minute of program execution, the clock slows down ). + This happens when GPU time in OSG statistics window is shorter than 3 ms. +*/ + #include #include #include @@ -188,7 +319,7 @@ struct IndirectTarget } void endRegister(unsigned int index, unsigned int rowsPerInstance, GLenum pixelFormat, GLenum type, GLint internalFormat, bool useMultiDrawArraysIndirect ) { - indirectCommandTextureBuffer = new osg::TextureBuffer(indirectCommands); + indirectCommandTextureBuffer = new osg::TextureBuffer(indirectCommands.get()); indirectCommandTextureBuffer->setInternalFormat( GL_R32I ); indirectCommandTextureBuffer->bindToImageUnit(index, osg::Texture::READ_WRITE); indirectCommandTextureBuffer->setUnRefImageDataAfterApply(false); @@ -199,11 +330,12 @@ struct IndirectTarget { std::vector newPrimitiveSets; - for(unsigned int j=0;jsize(); ++j){ + for(unsigned int j=0;jsize(); ++j) + { osg::DrawArraysIndirect *ipr=new osg::DrawArraysIndirect( GL_TRIANGLES, j ); - ipr->setIndirectCommandArray( indirectCommands); + ipr->setIndirectCommandArray( indirectCommands.get()); newPrimitiveSets.push_back(ipr); - } + } geometryAggregator->getAggregatedGeometry()->removePrimitiveSet(0,geometryAggregator->getAggregatedGeometry()->getNumPrimitiveSets() ); @@ -215,7 +347,7 @@ struct IndirectTarget else // use glMultiDrawArraysIndirect() { osg::MultiDrawArraysIndirect *ipr=new osg::MultiDrawArraysIndirect( GL_TRIANGLES ); - ipr->setIndirectCommandArray( indirectCommands ); + ipr->setIndirectCommandArray( indirectCommands.get() ); geometryAggregator->getAggregatedGeometry()->removePrimitiveSet(0,geometryAggregator->getAggregatedGeometry()->getNumPrimitiveSets() ); geometryAggregator->getAggregatedGeometry()->addPrimitiveSet( ipr ); } @@ -236,6 +368,7 @@ struct IndirectTarget instanceTarget->bindToImageUnit(OSGGPUCULL_MAXIMUM_INDIRECT_TARGET_NUMBER+index, osg::Texture::READ_WRITE); } + void addIndirectCommandData( const std::string& uniformNamePrefix, int index, osg::StateSet* stateset ) { std::string uniformName = uniformNamePrefix + char( '0' + index ); @@ -245,6 +378,7 @@ struct IndirectTarget } + void addIndirectTargetData( bool cullPhase, const std::string& uniformNamePrefix, int index, osg::StateSet* stateset ) { std::string uniformName; @@ -257,6 +391,7 @@ struct IndirectTarget stateset->addUniform( uniform ); stateset->setTextureAttribute( OSGGPUCULL_MAXIMUM_INDIRECT_TARGET_NUMBER+index, instanceTarget.get() ); } + void addDrawProgram( const std::string& uniformBlockName, osg::StateSet* stateset ) { drawProgram->addBindUniformBlock(uniformBlockName, 1); @@ -286,6 +421,7 @@ struct GPUCullData instanceTypesUBB = new osg::UniformBufferBinding(1, instanceTypes.get(), 0, 0); } + void setUseMultiDrawArraysIndirect( bool value ) { useMultiDrawArraysIndirect = value; @@ -297,6 +433,7 @@ struct GPUCullData return; targets[index] = IndirectTarget( agv, targetDrawProgram ); } + bool registerType(unsigned int typeID, unsigned int targetID, osg::Node* node, const osg::Vec4& lodDistances, float maxDensityPerSquareKilometer ) { if( typeID >= instanceTypes->getData().size() ) @@ -328,6 +465,7 @@ struct GPUCullData target->second.maxTargetQuantity += maxQuantity; return true; } + // endRegister() method is called after all indirect targets and instance types are registered. // It creates indirect targets with pixel format and data type provided by user ( indirect targets may hold // different information about single instance depending on user's needs ( in our example : static rendering @@ -388,10 +526,12 @@ struct StaticInstance : position(m), extraParams(params), idParams(typeID,id,0,0) { } + osg::Vec3d getPosition() const { return position.getTrans(); } + osg::Matrixf position; osg::Vec4f extraParams; osg::Vec4i idParams; @@ -705,10 +845,12 @@ struct ResetTexturesCallback : public osg::StateSet::Callback ResetTexturesCallback() { } + void addTextureDirty( unsigned int texUnit ) { texUnitsDirty.push_back(texUnit); } + void addTextureDirtyParams( unsigned int texUnit ) { texUnitsDirtyParams.push_back(texUnit); @@ -748,6 +890,7 @@ struct InvokeMemoryBarrier : public osg::Drawable::DrawCallback : _barriers(barriers) { } + virtual void drawImplementation(osg::RenderInfo& renderInfo,const osg::Drawable* drawable) const { //DrawIndirectGLExtensions *ext = DrawIndirectGLExtensions::getExtensions( renderInfo.getContextID(), true ); @@ -836,11 +979,13 @@ osg::Group* createSimpleHouse( float detailRatio, const osg::Vec4& buildingColor osg::ref_ptr chimneyGeode = convertShapeToGeode( *chimney.get(), tessHints.get(), chimneyColor ); root->addChild( chimneyGeode.get() ); } + { osg::ref_ptr chimney = new osg::Cylinder( osg::Vec3( -5.5, 3.0, 16.5 ), 0.1, 1.0 ); osg::ref_ptr chimneyGeode = convertShapeToGeode( *chimney.get(), tessHints.get(), chimneyColor ); root->addChild( chimneyGeode.get() ); } + { osg::ref_ptr chimney = new osg::Cylinder( osg::Vec3( -5.0, 3.0, 16.25 ), 0.1, 0.5 ); osg::ref_ptr chimneyGeode = convertShapeToGeode( *chimney.get(), tessHints.get(), chimneyColor ); @@ -1183,6 +1328,7 @@ struct AnimateObjectsCallback : public osg::DrawableUpdateCallback for(; i<3*_quantityPerType; ++i) // speed of airplanes _speed.push_back( random( 10.0, 16.0 ) ); } + virtual void update(osg::NodeVisitor* nv, osg::Drawable* drawable) { if( nv->getVisitorType() != osg::NodeVisitor::UPDATE_VISITOR ) @@ -1213,6 +1359,7 @@ struct AnimateObjectsCallback : public osg::DrawableUpdateCallback setRotationUsingRotSpeed( i, 5, osg::Matrix::rotate( osg::DegreesToRadians(90.0), osg::Vec3(0.0,1.0,0.0)) * osg::Matrix::translate(0.0,2.0,-6.0), currentTime, 0.5 ); setRotationUsingRotSpeed( i, 6, osg::Matrix::rotate( osg::DegreesToRadians(90.0), osg::Vec3(0.0,1.0,0.0)) * osg::Matrix::translate(0.0,-2.0,-6.0), currentTime, -0.5 ); } + for(;i<2*_quantityPerType;++i) //update cars { nbbox.expandBy( updateObjectPosition( vertexArray, i, deltaTime ) ); @@ -1223,6 +1370,7 @@ struct AnimateObjectsCallback : public osg::DrawableUpdateCallback setRotationUsingRotSpeed( i, 3, osg::Matrix::rotate( osg::DegreesToRadians(90.0), osg::Vec3(1.0,0.0,0.0)) * osg::Matrix::translate(2.0,-1.8,1.0), currentTime, wheelRotSpeed ); setRotationUsingRotSpeed( i, 4, osg::Matrix::rotate( osg::DegreesToRadians(90.0), osg::Vec3(1.0,0.0,0.0)) * osg::Matrix::translate(-2.0,-1.8,1.0), currentTime, wheelRotSpeed ); } + for(;i<3*_quantityPerType;++i) // update airplanes { nbbox.expandBy( updateObjectPosition( vertexArray, i, deltaTime ) ); @@ -1251,6 +1399,7 @@ struct AnimateObjectsCallback : public osg::DrawableUpdateCallback (*vertexArray)[index] = newPosition; return newPosition; } + void setRotationUsingRotSpeed( unsigned int index, unsigned int boneIndex, const osg::Matrix& zeroMatrix, double currentTime, double rotSpeed ) { // setRotationUsingRotSpeed() is a very unoptimally written ( because it uses osg::Matrix::inverse() ), @@ -1473,12 +1622,16 @@ int main( int argc, char **argv ) if ( arguments.read("--skip-static") ) showStaticRendering = false; + if ( arguments.read("--skip-dynamic") ) showDynamicRendering = false; + if ( arguments.read("--export-objects") ) exportInstanceObjects = true; + if ( arguments.read("--use-multi-draw") ) useMultiDrawArraysIndirect = true; + arguments.read("--instances-per-cell",instancesPerCell); arguments.read("--static-area-size",staticAreaSize); arguments.read("--dynamic-area-size",dynamicAreaSize); diff --git a/examples/osglauncher/osglauncher.cpp b/examples/osglauncher/osglauncher.cpp index 00c98b42c..ce7e4c553 100644 --- a/examples/osglauncher/osglauncher.cpp +++ b/examples/osglauncher/osglauncher.cpp @@ -44,6 +44,7 @@ #include #include +#include #include #include @@ -424,6 +425,9 @@ int main( int argc, char **argv ) // add the handler for doing the picking viewer.addEventHandler(new PickHandler(&viewer,updateText.get())); + // add the stats handler + viewer.addEventHandler(new osgViewer::StatsHandler); + osg::Group* root = new osg::Group(); root->addChild( setupGraph() ); diff --git a/examples/osglogo/osglogo.cpp b/examples/osglogo/osglogo.cpp index 18699462d..f5161c041 100644 --- a/examples/osglogo/osglogo.cpp +++ b/examples/osglogo/osglogo.cpp @@ -41,6 +41,9 @@ #include + +static bool s_useSDF = false; + class MyBillboardTransform : public osg::PositionAttitudeTransform { public: @@ -147,6 +150,12 @@ osg:: Node* createTextBelow(const osg::BoundingBox& bb, const std::string& label text->setFont(font); text->setFontResolution(64,64); + + if (s_useSDF) + { + text->setShaderTechnique(osgText::ALL_FEATURES); + } + text->setAlignment(osgText::Text::CENTER_CENTER); text->setAxisAlignment(osgText::Text::XZ_PLANE); text->setPosition(bb.center()-osg::Vec3(0.0f,0.0f,(bb.zMax()-bb.zMin()))); @@ -174,48 +183,35 @@ osg:: Node* createTextLeft(const osg::BoundingBox& bb, const std::string& label, text->setFont(font); text->setFontResolution(110,120); + + if (s_useSDF) + { + text->setShaderTechnique(osgText::ALL_FEATURES); + } + text->setAlignment(osgText::Text::RIGHT_CENTER); text->setAxisAlignment(osgText::Text::XZ_PLANE); text->setCharacterSize((bb.zMax()-bb.zMin())*1.0f); + text->setPosition(bb.center()-osg::Vec3((bb.xMax()-bb.xMin()),-(bb.yMax()-bb.yMin())*0.5f,(bb.zMax()-bb.zMin())*0.1f)); - //text->setColor(osg::Vec4(0.37f,0.48f,0.67f,1.0f)); // Neil's original OSG colour text->setColor(osg::Vec4(0.20f,0.45f,0.60f,1.0f)); // OGL logo colour - text->setText(label); -#if 1 text->setBackdropType(osgText::Text::OUTLINE); -// text->setBackdropType(osgText::Text::DROP_SHADOW_BOTTOM_RIGHT); - - text->setBackdropImplementation(osgText::Text::POLYGON_OFFSET); -// text->setBackdropImplementation(osgText::Text::NO_DEPTH_BUFFER); -// text->setBackdropImplementation(osgText::Text::DEPTH_RANGE); -// text->setBackdropImplementation(osgText::Text::STENCIL_BUFFER); - - text->setBackdropOffset(0.05f); + text->setBackdropOffset(0.03f); text->setBackdropColor(osg::Vec4(0.0f, 0.0f, 0.5f, 1.0f)); -#endif - -#if 1 text->setColorGradientMode(osgText::Text::OVERALL); osg::Vec4 lightblue(0.30f,0.6f,0.90f,1.0f); osg::Vec4 blue(0.10f,0.30f,0.40f,1.0f); text->setColorGradientCorners(lightblue, blue, blue, lightblue); -#else - text->setColorGradientMode(osgText::Text::OVERALL); - osg::Vec4 light = osg::Vec4(0.0f, 1.0f, 1.0f, 1.0f); - osg::Vec4 dark = osg::Vec4(0.0f, 0.0f, 0.5f, 1.0f); - text->setColorGradientCorners(light, dark, dark, light); -// text->setColorGradientCorners(dark, light, light, dark); -#endif + + text->setText(label); geode->addDrawable( text ); if (!subscript.empty()) { - //osgText::Text* subscript = new osgText::Text(new osgText::TextureFont(font,45)); - osgText::Text* subscriptText = new osgText::Text; subscriptText->setFont(font); subscriptText->setText(subscript); @@ -353,9 +349,6 @@ osg:: Node* createBoxNo5No2(const osg::BoundingBox& bb,float chordRatio) osg:: Node* createBackdrop(const osg::Vec3& corner,const osg::Vec3& top,const osg::Vec3& right) { - - - osg::Geometry* geom = new osg::Geometry; osg::Vec3 normal = (corner-top)^(right-corner); @@ -475,6 +468,9 @@ int main( int argc, char **argv ) return 1; } + + while(arguments.read("--sdf")) { s_useSDF = true; } + std::string label = "OpenSceneGraph"; std::string subscript = ""; diff --git a/examples/osgmovie/osgmovie.cpp b/examples/osgmovie/osgmovie.cpp index 833a76091..523822ee2 100644 --- a/examples/osgmovie/osgmovie.cpp +++ b/examples/osgmovie/osgmovie.cpp @@ -438,7 +438,7 @@ int main(int argc, char** argv) if (arguments.read("-devices") || arguments.read("--devices")) { // Force load QuickTime plugin, probe video capability, exit - osgDB::readImageFile("devices.live"); + osgDB::readRefImageFile("devices.live"); return 1; } #endif diff --git a/examples/osgshaders/GL2Scene.cpp b/examples/osgshaders/GL2Scene.cpp index f06592983..17a38e8e2 100644 --- a/examples/osgshaders/GL2Scene.cpp +++ b/examples/osgshaders/GL2Scene.cpp @@ -37,7 +37,6 @@ #include #include #include -#include #include #include @@ -141,10 +140,10 @@ ModelInstance() static void LoadShaderSource( osg::Shader* shader, const std::string& fileName ) { - std::string fqFileName = osgDB::findDataFile(fileName); - if( fqFileName.length() != 0 ) + osg::ref_ptr loaded_shader = osgDB::readRefShaderFile(fileName); + if (loaded_shader) { - shader->loadShaderSourceFromFile( fqFileName.c_str() ); + shader->setShaderSource( loaded_shader->getShaderSource() ); } else { diff --git a/examples/osgsimpleMDI/osgsimpleMDI.cpp b/examples/osgsimpleMDI/osgsimpleMDI.cpp index be7bd2c31..94309b56b 100644 --- a/examples/osgsimpleMDI/osgsimpleMDI.cpp +++ b/examples/osgsimpleMDI/osgsimpleMDI.cpp @@ -69,10 +69,24 @@ int main( int argc, char**argv ) arguments.read("--numX",MAXX); arguments.read("--numY",MAXY); - bool MDIenable=true; + enum PrimtiveSetUsage + { + MultiDraw, + MultiplePrimitiveSets, + SinglePrimitiveSet + }; + + PrimtiveSetUsage usage = MultiDraw; if(arguments.read("--classic")) - { MDIenable=false; - OSG_WARN<<"disabling MDI"< geom=new osg::Geometry(); geom->setUseVertexBufferObjects(true); + osg::BoundingBox bb; bb.set(0,0,0,MAXX,0,MAXY); //set bounds by hand cause of the lack of support of basevertex in PrimitiveFunctors @@ -104,10 +119,10 @@ int main( int argc, char**argv ) osg::Vec3Array * verts=new osg::Vec3Array(); - - for(int j =0 ; jsize(); mdicommands->push_back(cmd); - for(int z=0; z<4; z++) { + for(int z=0; z<4; z++) + { verts->push_back(osg::Vec3(i,0,j)+myCoords[z]); mdi->addElement(myIndices[z]); } } } - geom->setVertexArray(verts); - if(MDIenable) { - geom->addPrimitiveSet(mdi); - } else - for(int i=0; isetElementBufferObject(ebo); - geom->addPrimitiveSet(dre); - for(int z=0; z<4; z++)myIndicesUI[z]+=4; + geom->setVertexArray(verts); + + switch(usage) + { + case(MultiDraw): + { + geom->addPrimitiveSet(mdi); + break; + } + case(MultiplePrimitiveSets): + { + for(int i=0; i dre = new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLE_STRIP,4,myIndicesUI); + dre->setElementBufferObject(ebo.get()); + geom->addPrimitiveSet(dre.get()); + for(int z=0; z<4; z++) myIndicesUI[z]+=4; + } + break; + } + case(SinglePrimitiveSet): + { + osg::ref_ptr primitives = new osg::DrawElementsUInt(GL_TRIANGLES); + primitives->setElementBufferObject(ebo.get()); + geom->addPrimitiveSet(primitives.get()); + + unsigned int vi = 0; + for(int i=0; ipush_back(vi); + primitives->push_back(vi+2); + primitives->push_back(vi+1); + primitives->push_back(vi+1); + primitives->push_back(vi+2); + primitives->push_back(vi+3); + vi += 4; + } + break; + } + } + root->addChild(geom); + osgViewer::Viewer viewer; viewer.addEventHandler(new osgViewer::StatsHandler); viewer.setSceneData( root ); diff --git a/examples/osgstaticviewer/osgstaticviewer.cpp b/examples/osgstaticviewer/osgstaticviewer.cpp index 80983bc70..e01a99cbe 100644 --- a/examples/osgstaticviewer/osgstaticviewer.cpp +++ b/examples/osgstaticviewer/osgstaticviewer.cpp @@ -170,7 +170,7 @@ int main(int argc, char** argv) } // load the data - osg::ref_ptr loadedModel = osgDB::readNodeFiles(arguments); + osg::ref_ptr loadedModel = osgDB::readRefNodeFiles(arguments); if (!loadedModel) { std::cout << arguments.getApplicationName() <<": No data loaded" << std::endl; diff --git a/examples/osgstereomatch/StereoMultipass.cpp b/examples/osgstereomatch/StereoMultipass.cpp index 90a71ba24..9601be94f 100644 --- a/examples/osgstereomatch/StereoMultipass.cpp +++ b/examples/osgstereomatch/StereoMultipass.cpp @@ -19,7 +19,7 @@ */ #include "StereoMultipass.h" -#include +#include #include SubtractPass::SubtractPass(osg::TextureRectangle *left_tex, @@ -132,8 +132,12 @@ void SubtractPass::createOutputTextures() void SubtractPass::setShader(std::string filename) { - osg::ref_ptr fshader = new osg::Shader( osg::Shader::FRAGMENT ); - fshader->loadShaderSourceFromFile(osgDB::findDataFile(filename)); + osg::ref_ptr fshader = osgDB::readRefShaderFile( osg::Shader::FRAGMENT, filename); + if (!fshader) + { + OSG_NOTICE<<"Warning: could not file shader file : "< fshader = new osg::Shader( osg::Shader::FRAGMENT ); - fshader->loadShaderSourceFromFile(osgDB::findDataFile(filename)); + osg::ref_ptr fshader = osgDB::readRefShaderFile( osg::Shader::FRAGMENT, filename); + if (!fshader) + { + OSG_NOTICE<<"Warning: could not file shader file : "< fshader = new osg::Shader( osg::Shader::FRAGMENT ); - fshader->loadShaderSourceFromFile(osgDB::findDataFile(filename)); + osg::ref_ptr fshader = osgDB::readRefShaderFile( osg::Shader::FRAGMENT, filename); + if (!fshader) + { + OSG_NOTICE<<"Warning: could not file shader file : "< fshader = new osg::Shader( osg::Shader::FRAGMENT ); - fshader->loadShaderSourceFromFile(osgDB::findDataFile(filename)); + osg::ref_ptr fshader = osgDB::readRefShaderFile( osg::Shader::FRAGMENT, filename); + if (!fshader) + { + OSG_NOTICE<<"Warning: could not file shader file : "< +#include #include StereoPass::StereoPass(osg::TextureRectangle *left_tex, @@ -129,8 +129,12 @@ void StereoPass::createOutputTextures() void StereoPass::setShader(std::string filename) { - osg::ref_ptr fshader = new osg::Shader( osg::Shader::FRAGMENT ); - fshader->loadShaderSourceFromFile(osgDB::findDataFile(filename)); + osg::ref_ptr fshader = osgDB::readRefShaderFile( osg::Shader::FRAGMENT, filename); + if (!fshader) + { + OSG_NOTICE<<"Warning: could not file shader file : "<setText(str.str()); @@ -670,7 +670,7 @@ int main(int argc, char** argv) text->setUpdateCallback(new TextCounterCallback()); text->setFont("fonts/times.ttf"); text->setAxisAlignment(osgText::Text::XZ_PLANE); - text->setText("This is a counter test"); + text->setText("Text Counter :"); viewer.setSceneData(text.get()); } diff --git a/examples/osgtext3D/osgtext3D.cpp b/examples/osgtext3D/osgtext3D.cpp index 62197139b..15bdbfdc2 100644 --- a/examples/osgtext3D/osgtext3D.cpp +++ b/examples/osgtext3D/osgtext3D.cpp @@ -250,7 +250,9 @@ int main(int argc, char** argv) } if (arguments.read("--add-axes")) - group->addChild(osgDB::readNodeFile("axes.osgt")); + { + group->addChild(osgDB::readRefNodeFile("axes.osgt")); + } std::string mode; if (arguments.read("--character-size-mode", mode)) diff --git a/examples/osgtransferfunction/osgtransferfunction.cpp b/examples/osgtransferfunction/osgtransferfunction.cpp index aad85e3e5..fe9e4813f 100644 --- a/examples/osgtransferfunction/osgtransferfunction.cpp +++ b/examples/osgtransferfunction/osgtransferfunction.cpp @@ -407,13 +407,12 @@ int main(int argc, char ** argv) osg::ArgumentParser arguments(&argc, argv); #if 0 - osg::ref_ptr myobject = new MyClass; myobject->getOrCreateUserDataContainer()->addUserObject(new osg::CallbackObject("myMethod")); myobject->myMethod(); - osg::ref_ptr se = osgDB::readFile("ScriptEngine.lua"); - osg::ref_ptr script = osgDB::readFile("script.lua"); + osg::ref_ptr se = osgDB::readRefFile("ScriptEngine.lua"); + osg::ref_ptr script = osgDB::readRefFile("script.lua"); osg::ref_ptr copyobject = new MyClass; copyobject->getOrCreateUserDataContainer()->addUserObject(new MyScriptCallback(se.get(), script.get(), "myMethod")); @@ -421,7 +420,7 @@ int main(int argc, char ** argv) #endif #if 0 - osg::ref_ptr object = osgDB::readNodeFile("load.lua"); + osg::ref_ptr object = osgDB::readRefNodeFile("load.lua"); if (object.valid()) { osg::CallbackObject* co = osg::getCallbackObject(object.get(), "method"); diff --git a/examples/osgviewerCocoa/ViewerCocoa.mm b/examples/osgviewerCocoa/ViewerCocoa.mm index aded53820..ea24ba825 100644 --- a/examples/osgviewerCocoa/ViewerCocoa.mm +++ b/examples/osgviewerCocoa/ViewerCocoa.mm @@ -432,7 +432,6 @@ static void Internal_SetAlpha(NSBitmapImageRep *imageRep, unsigned char alpha_va default_text->setAlignment(osgText::Text::CENTER_CENTER); default_text->setBackdropType(osgText::Text::OUTLINE); -// default_text->setBackdropImplementation(osgText::Text::POLYGON_OFFSET); default_text->setColor(osg::Vec4(1.0, 1.0, 0.0, 1.0)); default_text->setBackdropColor(osg::Vec4(0.0, 0.0, 0.0, 1.0)); default_text->setAxisAlignment(osgText::Text::XZ_PLANE); @@ -1194,7 +1193,7 @@ A -respondsToSelector: check has been used to provide compatibility with previou // int number_of_files = [file_names count]; // Exercise for the reader: Try loading all files in the array NSString* single_file = [file_names objectAtIndex:0]; - osg::ref_ptr loaded_model = osgDB::readNodeFile([single_file fileSystemRepresentation]); + osg::ref_ptr loaded_model = osgDB::readRefNodeFile([single_file fileSystemRepresentation]); if(!loaded_model) { NSLog(@"File: %@ failed to load", single_file); @@ -1213,7 +1212,7 @@ A -respondsToSelector: check has been used to provide compatibility with previou return NO; } NSString* file_path = [file_url path]; - osg::ref_ptr loaded_model = osgDB::readNodeFile([file_path fileSystemRepresentation]); + osg::ref_ptr loaded_model = osgDB::readRefNodeFile([file_path fileSystemRepresentation]); if(!loaded_model) { NSLog(@"URL: %@ failed to load, %@", file_url, file_path); diff --git a/examples/osgviewerFLTK/osgviewerFLTK.cpp b/examples/osgviewerFLTK/osgviewerFLTK.cpp index e43e9d539..3210148de 100644 --- a/examples/osgviewerFLTK/osgviewerFLTK.cpp +++ b/examples/osgviewerFLTK/osgviewerFLTK.cpp @@ -140,7 +140,7 @@ int main( int argc, char **argv ) osg::ArgumentParser arguments(&argc, argv); // load the scene. - osg::ref_ptr loadedModel = osgDB::readNodeFiles(arguments); + osg::ref_ptr loadedModel = osgDB::readRefNodeFiles(arguments); if (!loadedModel) { std::cout << argv[0] <<": No data loaded." << std::endl; diff --git a/examples/osgviewerFOX/FOX_OSG_MDIView.cpp b/examples/osgviewerFOX/FOX_OSG_MDIView.cpp index df6124e2e..9dccc0791 100644 --- a/examples/osgviewerFOX/FOX_OSG_MDIView.cpp +++ b/examples/osgviewerFOX/FOX_OSG_MDIView.cpp @@ -39,7 +39,7 @@ FOX_OSG_MDIView::FOX_OSG_MDIView(FXMDIClient *p, const FXString &name, viewer->setKeyEventSetsDone(0); // load the scene. - osg::ref_ptr loadedModel = osgDB::readNodeFile("cow.osgt"); + osg::ref_ptr loadedModel = osgDB::readRefNodeFile("cow.osgt"); if (!loadedModel) { return ; diff --git a/examples/osgviewerGTK/osgviewerGTK.cpp b/examples/osgviewerGTK/osgviewerGTK.cpp index 8c77071d5..810ba3b82 100644 --- a/examples/osgviewerGTK/osgviewerGTK.cpp +++ b/examples/osgviewerGTK/osgviewerGTK.cpp @@ -69,7 +69,7 @@ class ExampleOSGGTKDrawingArea : public OSGGTKDrawingArea { if(gtk_dialog_run(GTK_DIALOG(of)) == GTK_RESPONSE_ACCEPT) { char* file = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(of)); - osg::ref_ptr model = osgDB::readNodeFile(file); + osg::ref_ptr model = osgDB::readRefNodeFile(file); if(model.valid()) { setSceneData(model.get()); @@ -170,7 +170,7 @@ int main(int argc, char** argv) { if(da.createWidget(640, 480)) { if(argc >= 2) { - osg::ref_ptr model = osgDB::readNodeFile(argv[1]); + osg::ref_ptr model = osgDB::readRefNodeFile(argv[1]); if(model.valid()) da.setSceneData(model.get()); } diff --git a/examples/osgviewerIPhone/iphoneViewerAppDelegate.mm b/examples/osgviewerIPhone/iphoneViewerAppDelegate.mm index 05654eee9..fc328b2c3 100644 --- a/examples/osgviewerIPhone/iphoneViewerAppDelegate.mm +++ b/examples/osgviewerIPhone/iphoneViewerAppDelegate.mm @@ -337,7 +337,7 @@ private: _root->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF | osg::StateAttribute::OVERRIDE); //load and attach scene model - osg::ref_ptr model = osgDB::readNodeFile(osgDB::findDataFile("lz.osg")); + osg::ref_ptr model = osgDB::readRefNodeFile(osgDB::findDataFile("lz.osg")); if (!model) { osg::Geode* geode = new osg::Geode(); osg::ShapeDrawable* drawable = new osg::ShapeDrawable(new osg::Box(osg::Vec3(0,0,0), 1)); diff --git a/examples/osgviewerWX/osgviewerWX.cpp b/examples/osgviewerWX/osgviewerWX.cpp index c4a198a4d..aa6678638 100644 --- a/examples/osgviewerWX/osgviewerWX.cpp +++ b/examples/osgviewerWX/osgviewerWX.cpp @@ -69,7 +69,7 @@ bool wxOsgApp::OnInit() // load the scene. wxString fname(argv[1]); - osg::ref_ptr loadedModel = osgDB::readNodeFile(std::string(fname.mb_str())); + osg::ref_ptr loadedModel = osgDB::readRefNodeFile(std::string(fname.mb_str())); if (!loadedModel) { std::cout << argv[0] <<": No data loaded." << std::endl; diff --git a/examples/osgvnc/osgvnc.cpp b/examples/osgvnc/osgvnc.cpp index a286b59b0..52d424178 100644 --- a/examples/osgvnc/osgvnc.cpp +++ b/examples/osgvnc/osgvnc.cpp @@ -7,7 +7,7 @@ class EscapeHandler : public osgGA::GUIEventHandler { public: - + EscapeHandler() {} bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa) @@ -22,7 +22,7 @@ class EscapeHandler : public osgGA::GUIEventHandler { osgViewer::View* view = dynamic_cast(&aa); if (view) view->getViewerBase()->setDone(true); - + return true; } } @@ -37,6 +37,8 @@ class EscapeHandler : public osgGA::GUIEventHandler int main(int argc,char** argv) { osg::ArgumentParser arguments(&argc, argv); + arguments.getApplicationUsage()->addCommandLineOption("--login ", "Provide authentication information for http file access."); + arguments.getApplicationUsage()->addCommandLineOption("--password ", "Provide password for any vnc url on command line not mentioned in --login."); osgViewer::Viewer viewer(arguments); osgWidget::GeometryHints hints(osg::Vec3(0.0f,0.0f,0.0f), @@ -52,6 +54,15 @@ int main(int argc,char** argv) { } + std::string url, username; + while (arguments.read("--login", url, username, password)) + { + osgDB::Registry::instance()->getOrCreateAuthenticationMap()->addAuthenticationDetails( + url, + new osgDB::AuthenticationDetails(username, password) + ); + } + for(int i=1; igetAuthenticationMap()) osgDB::Registry::instance()->setAuthenticationMap(new osgDB::AuthenticationMap); - osgDB::Registry::instance()->getAuthenticationMap()->addAuthenticationDetails(hostname, new osgDB::AuthenticationDetails("", password)); + osgDB::AuthenticationMap* authenticationMap = osgDB::Registry::instance()->getOrCreateAuthenticationMap(); + const osgDB::AuthenticationDetails* details = authenticationMap->getAuthenticationDetails(hostname); + if (details == NULL) + { + authenticationMap->addAuthenticationDetails(hostname, new osgDB::AuthenticationDetails("", password)); + } } osg::ref_ptr vncClient = new osgWidget::VncClient; if (vncClient->connect(arguments[i], hints)) - { + { group->addChild(vncClient.get()); - + hints.position.x() += 1.1f; } } diff --git a/examples/osgwidgetlabel/osgwidgetlabel.cpp b/examples/osgwidgetlabel/osgwidgetlabel.cpp index 39d86fefe..a29320cdf 100644 --- a/examples/osgwidgetlabel/osgwidgetlabel.cpp +++ b/examples/osgwidgetlabel/osgwidgetlabel.cpp @@ -30,12 +30,6 @@ osgWidget::Label* createLabel(const std::string& l, unsigned int size=13) { label->setFontColor(1.0f, 1.0f, 1.0f, 1.0f); label->setLabel(l); - /* - text->setBackdropType(osgText::Text::DROP_SHADOW_BOTTOM_RIGHT); - text->setBackdropImplementation(osgText::Text::NO_DEPTH_BUFFER); - text->setBackdropOffset(0.2f); - */ - return label; } diff --git a/examples/osgwidgetshader/osgwidgetshader.cpp b/examples/osgwidgetshader/osgwidgetshader.cpp index b50fd985c..f6aa37786 100644 --- a/examples/osgwidgetshader/osgwidgetshader.cpp +++ b/examples/osgwidgetshader/osgwidgetshader.cpp @@ -1,7 +1,7 @@ // -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008 // $Id: osgwidgetshader.cpp 28 2008-03-26 15:26:48Z cubicool $ -#include +#include #include #include #include @@ -60,15 +60,9 @@ int main(int, char**) osg::Program* program = new osg::Program(); - program->addShader(osg::Shader::readShaderFile( - osg::Shader::VERTEX, - osgDB::findDataFile("osgWidget/osgwidgetshader-vert.glsl") - )); - program->addShader(osg::Shader::readShaderFile( - osg::Shader::FRAGMENT, - osgDB::findDataFile("osgWidget/osgwidgetshader-frag.glsl") - )); + program->addShader(osgDB::readRefShaderFile( osg::Shader::VERTEX, "osgWidget/osgwidgetshader-vert.glsl" ) ); + program->addShader(osgDB::readRefShaderFile( osg::Shader::FRAGMENT, "osgWidget/osgwidgetshader-frag.glsl" ) ); canvas->getGeode()->getOrCreateStateSet()->setAttribute(program); diff --git a/include/osg/ComputeDispatch b/include/osg/ComputeDispatch new file mode 100644 index 000000000..5e0ac6ffe --- /dev/null +++ b/include/osg/ComputeDispatch @@ -0,0 +1,55 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2014 Robert Osfield + * Copyright (C) 2017 Julien Valentin + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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 + * OpenSceneGraph Public License for more details. +*/ + +#ifndef OSG_COMPUTEDISPATCH +#define OSG_COMPUTEDISPATCH 1 + +#include + +#include + +namespace osg{ + class OSG_EXPORT ComputeDispatch : public osg::Drawable + { + public: + ComputeDispatch(GLint numGroupsX=0, GLint numGroupsY=0, GLint numGroupsZ=0): + Drawable(), + _numGroupsX(numGroupsX), + _numGroupsY(numGroupsY), + _numGroupsZ(numGroupsZ) + {} + + ComputeDispatch(const ComputeDispatch&,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY); + + META_Node(osg, ComputeDispatch); + + virtual void compileGLObjects(RenderInfo&) const {} + + virtual VertexArrayState* createVertexArrayStateImplememtation(RenderInfo&) const { return 0; } + + virtual void drawImplementation(RenderInfo& renderInfo) const; + + /** Set compute shader work groups */ + void setComputeGroups( GLint numGroupsX, GLint numGroupsY, GLint numGroupsZ ) { _numGroupsX=numGroupsX; _numGroupsY=numGroupsY; _numGroupsZ=numGroupsZ; } + + /** Get compute shader work groups */ + void getComputeGroups( GLint& numGroupsX, GLint& numGroupsY, GLint& numGroupsZ ) const{ numGroupsX=_numGroupsX; numGroupsY=_numGroupsY; numGroupsZ=_numGroupsZ; } + + protected: + GLint _numGroupsX, _numGroupsY, _numGroupsZ; + + }; +} +#endif + diff --git a/include/osg/DisplaySettings b/include/osg/DisplaySettings index 6821d14e9..0609cf0c6 100644 --- a/include/osg/DisplaySettings +++ b/include/osg/DisplaySettings @@ -20,6 +20,7 @@ #include #include +#include namespace osg { @@ -319,9 +320,15 @@ class OSG_EXPORT DisplaySettings : public osg::Referenced SHADER_GLES3 }; - void setShaderHint(ShaderHint hint) { _shaderHint = hint; } + /** set the ShaderHint to tells shader generating cdoes version to create. + * By default also OSG_GLSL_VERSION and OSG_PRECISION_FLOAT values that can get use directly in shaders using $OSG_GLSL_VERSION and $OSG_PRECISION_FLOAT respectively.*/ + void setShaderHint(ShaderHint hint, bool setShaderValues=true); ShaderHint getShaderHint() const { return _shaderHint; } + /** Set the TextShaderTechnique that is used in the Text default constructor to choose which osgText::ShaderTechnique to use.*/ + void setTextShaderTechnique(const std::string& str) { _textShaderTechnique = str; } + const std::string& getTextShaderTechnique() const { return _textShaderTechnique; } + void setKeystoneHint(bool enabled) { _keystoneHint = enabled; } bool getKeystoneHint() const { return _keystoneHint; } @@ -358,6 +365,11 @@ class OSG_EXPORT DisplaySettings : public osg::Referenced /** helper function for computing the right eye view matrix.*/ virtual osg::Matrixd computeRightEyeViewImplementation(const osg::Matrixd& view, double eyeSeperationScale=1.0) const; + + void setValue(const std::string& name, const std::string& value); + + bool getValue(const std::string& name, std::string& value, bool use_getenv_fallback=true) const; + protected: virtual ~DisplaySettings(); @@ -415,6 +427,7 @@ class OSG_EXPORT DisplaySettings : public osg::Referenced VertexBufferHint _vertexBufferHint; ShaderHint _shaderHint; + std::string _textShaderTechnique; bool _keystoneHint; FileNames _keystoneFileNames; @@ -422,6 +435,11 @@ class OSG_EXPORT DisplaySettings : public osg::Referenced OSXMenubarBehavior _OSXMenubarBehavior; + typedef std::map ValueMap; + + mutable OpenThreads::Mutex _valueMapMutex; + mutable ValueMap _valueMap; + }; } diff --git a/include/osg/Drawable b/include/osg/Drawable index acae9d2c3..9547659f5 100644 --- a/include/osg/Drawable +++ b/include/osg/Drawable @@ -278,7 +278,53 @@ class OSG_EXPORT Drawable : public Node */ virtual void compileGLObjects(RenderInfo& renderInfo) const; - virtual VertexArrayState* createVertexArrayState(RenderInfo& renderInfo) const; + + /** Callback class for overriding the default Drawable::createCreateVertexArrayStateImplementation().*/ + struct CreateVertexArrayStateCallback : public virtual osg::Object + { + CreateVertexArrayStateCallback() {} + + CreateVertexArrayStateCallback(const CreateVertexArrayStateCallback& rhs,const CopyOp& copyop): + Object(rhs, copyop) {} + + META_Object(osg, CreateVertexArrayStateCallback); + + /** do customized createVertexArrayState .*/ + virtual osg::VertexArrayState* createVertexArrayStateImplementation(osg::RenderInfo& renderInfo, const osg::Drawable* drawable) const + { + return drawable->createVertexArrayStateImplementation(renderInfo); + } + }; + + + /** Set the callback to override the default Drawable::createCreateVertexArrayStateImplementation().*/ + void setCreateVertexArrayStateCallback(CreateVertexArrayStateCallback* cb) { _createVertexArrayStateCallback = cb; } + + /** Get the callback that overrides the default Drawable::createCreateVertexArrayStateImplementation().*/ + CreateVertexArrayStateCallback* getCreateVertexArrayStateCallback() { return _createVertexArrayStateCallback.get(); } + + /** Get the const callback that overrides the default Drawable::createCreateVertexArrayStateImplementation().*/ + const CreateVertexArrayStateCallback* getCreateVertexArrayStateCallback() const { return _createVertexArrayStateCallback.get(); } + + + /** Craeate tje VertexArrayState object used to track vertex array and vertex array object state. This method will be called automatically during rendering setup so users should not call this themselves.*/ + inline VertexArrayState* createVertexArrayState(RenderInfo& renderInfo) const + { + if (_createVertexArrayStateCallback.valid()) return _createVertexArrayStateCallback->createVertexArrayStateImplementation(renderInfo, this); + else return createVertexArrayStateImplementation(renderInfo); + } + + /** Implementaion of Craeate tje VertexArrayState object.*/ + virtual VertexArrayState* createVertexArrayStateImplementation(RenderInfo& renderInfo) const; + + typedef buffered_object< osg::ref_ptr > VertexArrayStateList; + + void setVertexArrayStateList(VertexArrayStateList& vasl) { _vertexArrayStateList = vasl; } + + VertexArrayStateList& getVertexArrayStateList() { return _vertexArrayStateList; } + + const VertexArrayStateList& getVertexArrayStateList() const { return _vertexArrayStateList; } + /** Set whether to use a mutex to ensure ref() and unref() are thread safe.*/ @@ -491,10 +537,10 @@ class OSG_EXPORT Drawable : public Node typedef osg::buffered_value GLObjectList; mutable GLObjectList _globjList; - typedef buffered_object< osg::ref_ptr > VertexArrayStateList; mutable VertexArrayStateList _vertexArrayStateList; ref_ptr _drawCallback; + ref_ptr _createVertexArrayStateCallback; }; #ifdef INLINE_DRAWABLE_DRAW diff --git a/include/osg/EnvVar b/include/osg/EnvVar new file mode 100644 index 000000000..6ef49266a --- /dev/null +++ b/include/osg/EnvVar @@ -0,0 +1,118 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2017 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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 + * OpenSceneGraph Public License for more details. +*/ + +#ifndef OSG_EnvVar +#define OSG_EnvVar 1 + +#include + +#ifdef OSG_ENVVAR_SUPPORTED + #include + #include +#endif + +namespace osg { + +inline unsigned int getClampedLength(const char* str, unsigned int maxNumChars=4096) +{ + unsigned int i = 0; + while(i +inline bool getEnvVar(const char* name, T& value) +{ +#ifdef OSG_ENVVAR_SUPPORTED + const char* ptr = getenv(name); + if (!ptr) return false; + + std::istringstream str(std::string(ptr, getClampedLength(ptr))); + str >> value; + return !str.fail(); +#else + return false; +#endif +} + +template<> +inline bool getEnvVar(const char* name, std::string& value) +{ +#ifdef OSG_ENVVAR_SUPPORTED + const char* ptr = getenv(name); + if (!ptr) return false; + + value.assign(ptr, getClampedLength(ptr)); + return true; +#else + return false; +#endif +} + +template +inline bool getEnvVar(const char* name, T1& value1, T2& value2) +{ +#ifdef OSG_ENVVAR_SUPPORTED + const char* ptr = getenv(name); + if (!ptr) return false; + + std::istringstream str(std::string(ptr, getClampedLength(ptr))); + str >> value1 >> value2; + return !str.fail(); +#else + return false; +#endif +} + +template +inline bool getEnvVar(const char* name, T1& value1, T2& value2, T3& value3) +{ +#ifdef OSG_ENVVAR_SUPPORTED + const char* ptr = getenv(name); + if (!ptr) return false; + + std::istringstream str(std::string(ptr, getClampedLength(ptr))); + str >> value1 >> value2 >> value3; + return !str.fail(); +#else + return false; +#endif +} + +template +inline bool getEnvVar(const char* name, T1& value1, T2& value2, T3& value3, T4& value4) +{ +#ifdef OSG_ENVVAR_SUPPORTED + const char* ptr = getenv(name); + if (!ptr) return false; + + std::istringstream str(std::string(ptr, getClampedLength(ptr))); + str >> value1 >> value2 >> value3 >> value4; + return !str.fail(); +#else + return false; +#endif +} + +} + +# endif diff --git a/include/osg/Geometry b/include/osg/Geometry index dd1094859..1fb8caea3 100644 --- a/include/osg/Geometry +++ b/include/osg/Geometry @@ -233,7 +233,7 @@ class OSG_EXPORT Geometry : public Drawable bool _containsDeprecatedData; - virtual VertexArrayState* createVertexArrayState(RenderInfo& renderInfo) const; + virtual VertexArrayState* createVertexArrayStateImplementation(RenderInfo& renderInfo) const; public: diff --git a/include/osg/Image b/include/osg/Image index 3a90175ea..4bf7df74b 100644 --- a/include/osg/Image +++ b/include/osg/Image @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -68,6 +69,10 @@ #endif #if defined(OSG_GLES1_AVAILABLE) || defined(OSG_GLES2_AVAILABLE) || defined(OSG_GLES3_AVAILABLE) || defined(OSG_GL3_AVAILABLE) + #define GL_ALPHA4 0x803B + #define GL_ALPHA8 0x803C + #define GL_ALPHA12 0x803D + #define GL_ALPHA16 0x803E #define GL_BITMAP 0x1A00 #define GL_COLOR_INDEX 0x1900 #define GL_INTENSITY12 0x804C @@ -114,6 +119,38 @@ #define GL_COMPRESSED_SIGNED_RG11_EAC 0x9273 #endif +#ifndef GL_KHR_texture_compression_astc_hdr +#define GL_KHR_texture_compression_astc_hdr 1 +#define GL_COMPRESSED_RGBA_ASTC_4x4_KHR 0x93B0 +#define GL_COMPRESSED_RGBA_ASTC_5x4_KHR 0x93B1 +#define GL_COMPRESSED_RGBA_ASTC_5x5_KHR 0x93B2 +#define GL_COMPRESSED_RGBA_ASTC_6x5_KHR 0x93B3 +#define GL_COMPRESSED_RGBA_ASTC_6x6_KHR 0x93B4 +#define GL_COMPRESSED_RGBA_ASTC_8x5_KHR 0x93B5 +#define GL_COMPRESSED_RGBA_ASTC_8x6_KHR 0x93B6 +#define GL_COMPRESSED_RGBA_ASTC_8x8_KHR 0x93B7 +#define GL_COMPRESSED_RGBA_ASTC_10x5_KHR 0x93B8 +#define GL_COMPRESSED_RGBA_ASTC_10x6_KHR 0x93B9 +#define GL_COMPRESSED_RGBA_ASTC_10x8_KHR 0x93BA +#define GL_COMPRESSED_RGBA_ASTC_10x10_KHR 0x93BB +#define GL_COMPRESSED_RGBA_ASTC_12x10_KHR 0x93BC +#define GL_COMPRESSED_RGBA_ASTC_12x12_KHR 0x93BD +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR 0x93D0 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR 0x93D1 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR 0x93D2 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR 0x93D3 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR 0x93D4 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR 0x93D5 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR 0x93D6 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR 0x93D7 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR 0x93D8 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR 0x93D9 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR 0x93DA +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR 0x93DB +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR 0x93DC +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR 0x93DD +#endif /* GL_KHR_texture_compression_astc_hdr */ + #ifndef GL_DEPTH_COMPONENT #define GL_DEPTH_COMPONENT 0x1902 #endif @@ -404,11 +441,17 @@ class OSG_EXPORT Image : public BufferData static bool isPackedType(GLenum type); static GLenum computePixelFormat(GLenum pixelFormat); static GLenum computeFormatDataType(GLenum pixelFormat); + + /** return the dimensions of a block of compressed pixels */ + static osg::Vec3i computeBlockFootprint(GLenum pixelFormat); + + /** return the size in bytes of a block of compressed pixels */ static unsigned int computeBlockSize(GLenum pixelFormat, GLenum packing); static unsigned int computeNumComponents(GLenum pixelFormat); static unsigned int computePixelSizeInBits(GLenum pixelFormat,GLenum type); static unsigned int computeRowWidthInBytes(int width,GLenum pixelFormat,GLenum type,int packing); static unsigned int computeImageSizeInBytes(int width,int height, int depth, GLenum pixelFormat, GLenum type, int packing = 1, int slice_packing = 1, int image_packing = 1); + static int roudUpToMultiple(int s, int pack); static int computeNearestPowerOfTwo(int s,float bias=0.5f); static int computeNumberOfMipmapLevels(int s,int t = 1, int r = 1); diff --git a/include/osg/PrimitiveSetIndirect b/include/osg/PrimitiveSetIndirect index bf7b1a5ce..bd724dab0 100644 --- a/include/osg/PrimitiveSetIndirect +++ b/include/osg/PrimitiveSetIndirect @@ -168,8 +168,8 @@ public: } /// get command array of this indirect primitive set - inline IndirectCommandDrawElements* getIndirectCommandArray() { return _indirectCommandArray; } - inline const IndirectCommandDrawElements* getIndirectCommandArray() const { return _indirectCommandArray; } + inline IndirectCommandDrawElements* getIndirectCommandArray() { return _indirectCommandArray.get(); } + inline const IndirectCommandDrawElements* getIndirectCommandArray() const { return _indirectCommandArray.get(); } ///Further methods are for advanced DI when you plan to use your own IndirectCommandElement (stride) ///or if you want to draw a particular command index of the IndirectCommandElement(FirstCommandToDraw) @@ -415,31 +415,48 @@ class OSG_EXPORT MultiDrawElementsIndirectUShort : public DrawElementsIndirectUS { public: MultiDrawElementsIndirectUShort(GLenum mode = 0/*,unsigned int firstCommand = 0, GLsizei stride = 0*/) : - DrawElementsIndirectUShort(mode),_count(0) { _primitiveType=(Type(MultiDrawElementsUShortIndirectPrimitiveType)); } + DrawElementsIndirectUShort(mode), + _count(0) + { + _primitiveType=(Type(MultiDrawElementsUShortIndirectPrimitiveType)); + } MultiDrawElementsIndirectUShort(const MultiDrawElementsIndirectUShort& mdi,const CopyOp& copyop=CopyOp::SHALLOW_COPY) : - DrawElementsIndirectUShort(mdi,copyop),_count(mdi._count) {} + DrawElementsIndirectUShort(mdi,copyop), + _count(mdi._count) + { + } + /** * \param mode One of osg::PrimitiveSet::Mode. Determines the type of primitives used. * \param no Number of intended elements. This will be the size of the underlying vector. * \param ptr Pointer to a GLunsigned int to copy index data from. */ MultiDrawElementsIndirectUShort(GLenum mode, unsigned int no, const GLushort* ptr) : - DrawElementsIndirectUShort(mode,no,ptr) - {_primitiveType=(Type(MultiDrawElementsUShortIndirectPrimitiveType));} + DrawElementsIndirectUShort(mode,no,ptr), + _count(0) + { + _primitiveType=(Type(MultiDrawElementsUShortIndirectPrimitiveType)); + } /** * \param mode One of osg::PrimitiveSet::Mode. Determines the type of primitives used. * \param no Number of intended elements. This will be the size of the underlying vector. */ MultiDrawElementsIndirectUShort(GLenum mode, unsigned int no) : - DrawElementsIndirectUShort(mode,no) - {_primitiveType=(Type(MultiDrawElementsUShortIndirectPrimitiveType));} + DrawElementsIndirectUShort(mode,no), + _count(0) + { + _primitiveType=(Type(MultiDrawElementsUShortIndirectPrimitiveType)); + } template MultiDrawElementsIndirectUShort(GLenum mode, InputIterator first,InputIterator last) : - DrawElementsIndirectUShort(mode,first,last) - {_primitiveType=(Type(MultiDrawElementsUShortIndirectPrimitiveType));} + DrawElementsIndirectUShort(mode,first,last), + _count(0) + { + _primitiveType=(Type(MultiDrawElementsUShortIndirectPrimitiveType)); + } virtual osg::Object* cloneType() const { return new MultiDrawElementsIndirectUShort(); } virtual osg::Object* clone(const osg::CopyOp& copyop) const { return new MultiDrawElementsIndirectUShort(*this,copyop); } @@ -467,31 +484,49 @@ class OSG_EXPORT MultiDrawElementsIndirectUByte : public DrawElementsIndirectUBy { public: MultiDrawElementsIndirectUByte(GLenum mode = 0) : - DrawElementsIndirectUByte(mode),_count(0) { _primitiveType=(Type(MultiDrawElementsUByteIndirectPrimitiveType)); } + DrawElementsIndirectUByte(mode), + _count(0) + { + _primitiveType=(Type(MultiDrawElementsUByteIndirectPrimitiveType)); + + } MultiDrawElementsIndirectUByte(const MultiDrawElementsIndirectUByte& mdi,const CopyOp& copyop=CopyOp::SHALLOW_COPY) : - DrawElementsIndirectUByte(mdi,copyop),_count(mdi._count) {} + DrawElementsIndirectUByte(mdi,copyop), + _count(mdi._count) + { + } + /** * \param mode One of osg::PrimitiveSet::Mode. Determines the type of primitives used. * \param no Number of intended elements. This will be the size of the underlying vector. * \param ptr Pointer to a GLunsigned int to copy index data from. */ MultiDrawElementsIndirectUByte(GLenum mode, unsigned int no, const GLubyte* ptr) : - DrawElementsIndirectUByte(mode,no,ptr) - {_primitiveType=(Type(MultiDrawElementsUByteIndirectPrimitiveType));} + DrawElementsIndirectUByte(mode,no,ptr), + _count(0) + { + _primitiveType=(Type(MultiDrawElementsUByteIndirectPrimitiveType)); + } /** * \param mode One of osg::PrimitiveSet::Mode. Determines the type of primitives used. * \param no Number of intended elements. This will be the size of the underlying vector. */ MultiDrawElementsIndirectUByte(GLenum mode, unsigned int no) : - DrawElementsIndirectUByte(mode,no) - {_primitiveType=(Type(MultiDrawElementsUByteIndirectPrimitiveType));} + DrawElementsIndirectUByte(mode,no), + _count(0) + { + _primitiveType=(Type(MultiDrawElementsUByteIndirectPrimitiveType)); + } template MultiDrawElementsIndirectUByte(GLenum mode, InputIterator first,InputIterator last) : - DrawElementsIndirectUByte(mode,first,last) - {_primitiveType=(Type(MultiDrawElementsUByteIndirectPrimitiveType));} + DrawElementsIndirectUByte(mode,first,last), + _count(0) + { + _primitiveType=(Type(MultiDrawElementsUByteIndirectPrimitiveType)); + } virtual osg::Object* cloneType() const { return new MultiDrawElementsIndirectUByte(); } virtual osg::Object* clone(const osg::CopyOp& copyop) const { return new MultiDrawElementsIndirectUByte(*this,copyop); } @@ -517,31 +552,47 @@ class OSG_EXPORT MultiDrawElementsIndirectUInt : public DrawElementsIndirectUInt { public: MultiDrawElementsIndirectUInt(GLenum mode = 0) : - DrawElementsIndirectUInt(mode),_count(0) { _primitiveType=(Type(MultiDrawElementsUIntIndirectPrimitiveType)); } + DrawElementsIndirectUInt(mode), + _count(0) + { + _primitiveType=(Type(MultiDrawElementsUIntIndirectPrimitiveType)); + } MultiDrawElementsIndirectUInt(const MultiDrawElementsIndirectUInt& mdi,const CopyOp& copyop=CopyOp::SHALLOW_COPY) : - DrawElementsIndirectUInt(mdi,copyop),_count(mdi._count) {} + DrawElementsIndirectUInt(mdi,copyop), + _count(mdi._count) + {} + /** * \param mode One of osg::PrimitiveSet::Mode. Determines the type of primitives used. * \param no Number of intended elements. This will be the size of the underlying vector. * \param ptr Pointer to a GLunsigned int to copy index data from. */ MultiDrawElementsIndirectUInt(GLenum mode, unsigned int no, const GLuint* ptr) : - DrawElementsIndirectUInt(mode,no,ptr) - {_primitiveType=(Type(MultiDrawElementsUIntIndirectPrimitiveType));} + DrawElementsIndirectUInt(mode,no,ptr), + _count(0) + { + _primitiveType=(Type(MultiDrawElementsUIntIndirectPrimitiveType)); + } /** * \param mode One of osg::PrimitiveSet::Mode. Determines the type of primitives used. * \param no Number of intended elements. This will be the size of the underlying vector. */ MultiDrawElementsIndirectUInt(GLenum mode, unsigned int no) : - DrawElementsIndirectUInt(mode,no) - {_primitiveType=(Type(MultiDrawElementsUIntIndirectPrimitiveType));} + DrawElementsIndirectUInt(mode,no), + _count(0) + { + _primitiveType=(Type(MultiDrawElementsUIntIndirectPrimitiveType)); + } template MultiDrawElementsIndirectUInt(GLenum mode, InputIterator first,InputIterator last) : - DrawElementsIndirectUInt(mode,first,last) - {_primitiveType=(Type(MultiDrawElementsUIntIndirectPrimitiveType));} + DrawElementsIndirectUInt(mode,first,last), + _count(0) + { + _primitiveType=(Type(MultiDrawElementsUIntIndirectPrimitiveType)); + } virtual osg::Object* cloneType() const { return new MultiDrawElementsIndirectUInt(); } virtual osg::Object* clone(const osg::CopyOp& copyop) const { return new MultiDrawElementsIndirectUInt(*this,copyop); } @@ -572,13 +623,19 @@ public: DrawArraysIndirect(GLenum mode=0, unsigned int firstcommand = 0, GLsizei stride = 0) : osg::PrimitiveSet(Type(DrawArraysIndirectPrimitiveType), mode), - _firstCommand(firstcommand), _stride(stride) { setIndirectCommandArray(new DefaultIndirectCommandDrawArrays); } + _firstCommand(firstcommand), + _stride(stride) + { + setIndirectCommandArray(new DefaultIndirectCommandDrawArrays); + } DrawArraysIndirect(const DrawArraysIndirect& dal,const CopyOp& copyop=CopyOp::SHALLOW_COPY) : osg::PrimitiveSet(dal,copyop), _firstCommand(dal._firstCommand), _stride(dal._stride), - _indirectCommandArray((DefaultIndirectCommandDrawArrays*)copyop( dal._indirectCommandArray.get())) {} + _indirectCommandArray((DefaultIndirectCommandDrawArrays*)copyop( dal._indirectCommandArray.get())) + { + } virtual osg::Object* cloneType() const { return new DrawArraysIndirect(); } virtual osg::Object* clone(const osg::CopyOp& copyop) const { return new DrawArraysIndirect(*this,copyop); } @@ -616,8 +673,8 @@ public: if(!dynamic_cast(_indirectCommandArray->getBufferObject())) _indirectCommandArray->setBufferObject(new DrawIndirectBufferObject()); } - inline const IndirectCommandDrawArrays* getIndirectCommandArray() const { return _indirectCommandArray; } - inline IndirectCommandDrawArrays* getIndirectCommandArray() { return _indirectCommandArray; } + inline const IndirectCommandDrawArrays* getIndirectCommandArray() const { return _indirectCommandArray.get(); } + inline IndirectCommandDrawArrays* getIndirectCommandArray() { return _indirectCommandArray.get(); } protected: @@ -635,10 +692,16 @@ class OSG_EXPORT MultiDrawArraysIndirect : public DrawArraysIndirect public: MultiDrawArraysIndirect(GLenum mode=0, unsigned int firstcommand = 0, unsigned int count = 0, GLsizei stride = 0) : - osg::DrawArraysIndirect(mode, firstcommand, stride), _count(count) { _primitiveType=Type(MultiDrawArraysIndirectPrimitiveType); } + osg::DrawArraysIndirect(mode, firstcommand, stride), + _count(count) + { + _primitiveType=Type(MultiDrawArraysIndirectPrimitiveType); + } MultiDrawArraysIndirect(const MultiDrawArraysIndirect& dal,const CopyOp& copyop=CopyOp::SHALLOW_COPY) : - osg::DrawArraysIndirect(dal,copyop), _count(dal._count) {} + osg::DrawArraysIndirect(dal,copyop), + _count(dal._count) + {} virtual osg::Object* cloneType() const { return new MultiDrawArraysIndirect(); } virtual osg::Object* clone(const osg::CopyOp& copyop) const { return new MultiDrawArraysIndirect(*this,copyop); } diff --git a/include/osg/Program b/include/osg/Program index 36aa7ed2f..e9e26829f 100644 --- a/include/osg/Program +++ b/include/osg/Program @@ -103,10 +103,6 @@ class OSG_EXPORT Program : public osg::StateAttribute void setParameter( GLenum pname, GLint value ); GLint getParameter( GLenum pname ) const; - /** Set/get compute shader work groups */ - void setComputeGroups( GLint numGroupsX, GLint numGroupsY, GLint numGroupsZ ); - void getComputeGroups( GLint& numGroupsX, GLint& numGroupsY, GLint& numGroupsZ ) const; - /** Add an attribute location binding. */ void addBindAttribLocation( const std::string& name, GLuint index ); @@ -439,12 +435,6 @@ class OSG_EXPORT Program : public osg::StateAttribute GLint _geometryInputType; GLint _geometryOutputType; - - /** Parameter maintained with glDispatchCompute */ - GLint _numGroupsX; - GLint _numGroupsY; - GLint _numGroupsZ; - /**TransformFeedBack**/ GLenum _feedbackmode; std::vector _feedbackout; diff --git a/include/osg/Shader b/include/osg/Shader index fdfbc3f7e..4347cf9a5 100644 --- a/include/osg/Shader +++ b/include/osg/Shader @@ -162,14 +162,13 @@ class OSG_EXPORT Shader : public osg::Object /** Get the const Shader's ShaderBinary, return NULL if none is assigned. */ const ShaderBinary* getShaderBinary() const { return _shaderBinary.get(); } - - /** Read shader source from file and then constructor shader of specified type. - * Return the resulting Shader or 0 if no valid shader source could be read.*/ +#ifdef OSG_USE_DEPRECATED_API + /** Deorecated use osgDB::readRefShaderFile().*/ static Shader* readShaderFile( Type type, const std::string& fileName ); - /** Load the Shader's source code text from a file. */ + /** Deorecated use osgDB::readRefShaderFile(). */ bool loadShaderSourceFromFile( const std::string& fileName ); - +#endif /** The code injection map used when generating the main shader during main shader composition.*/ typedef std::multimap CodeInjectionMap; diff --git a/include/osg/State b/include/osg/State index ee5415660..97b6fec2a 100644 --- a/include/osg/State +++ b/include/osg/State @@ -823,9 +823,12 @@ class OSG_EXPORT State : public Referenced * during rendering. */ inline void setDisplaySettings(DisplaySettings* vs) { _displaySettings = vs; } - /** Get the DisplaySettings */ + /** Get the const DisplaySettings */ inline const DisplaySettings* getDisplaySettings() const { return _displaySettings.get(); } + /** Get the const DisplaySettings that is current active DisplaySettings to be used by osg::State, - if DisplaySettings is not directly assigned then fallback to DisplaySettings::instance(). */ + inline const DisplaySettings* getActiveDisplaySettings() const { return _displaySettings.valid() ? _displaySettings.get() : osg::DisplaySettings::instance().get(); } + /** Set flag for early termination of the draw traversal.*/ diff --git a/include/osg/VertexArrayState b/include/osg/VertexArrayState index cfd8dae86..ce5956315 100644 --- a/include/osg/VertexArrayState +++ b/include/osg/VertexArrayState @@ -34,6 +34,8 @@ public: modifiedCount(0xffffffff), active(false) {} + virtual const char* className() const = 0; // { return "ArrayDispatch"; } + virtual void enable_and_dispatch(osg::State& /*state*/, const osg::Array* /*new_array*/) {} // = 0; virtual void enable_and_dispatch(osg::State& /*state*/, const osg::Array* /*new_array*/, const osg::GLBufferObject* /*vbo*/) {} // = 0; diff --git a/include/osg/VertexAttribDivisor b/include/osg/VertexAttribDivisor index 7b222cd38..a38b31da5 100644 --- a/include/osg/VertexAttribDivisor +++ b/include/osg/VertexAttribDivisor @@ -50,6 +50,7 @@ class OSG_EXPORT VertexAttribDivisor : public StateAttribute COMPARE_StateAttribute_Types(VertexAttribDivisor,sa) // compare each parameter in turn against the rhs. + COMPARE_StateAttribute_Parameter(_index) COMPARE_StateAttribute_Parameter(_divisor) return 0; // passed all the above comparison macros, must be equal. diff --git a/include/osgAnimation/AnimationManagerBase b/include/osgAnimation/AnimationManagerBase index bdc0c5c89..0c5b8ec36 100644 --- a/include/osgAnimation/AnimationManagerBase +++ b/include/osgAnimation/AnimationManagerBase @@ -42,6 +42,17 @@ namespace osgAnimation const AnimationList& getAnimationList() const { return _animations;} AnimationList& getAnimationList() { return _animations;} + //uniformisation of the API + inline Animation * getRegisteredAnimation(unsigned int i) { return _animations[i].get();} + inline unsigned int getNumRegisteredAnimations() const { return _animations.size();} + inline void addRegisteredAnimation(Animation* animation) + { + _needToLink = true; + _animations.push_back(animation); + buildTargetReference(); + } + void removeRegisteredAnimation(Animation* animation); + /** Callback method called by the NodeVisitor when visiting a node.*/ virtual void operator()(osg::Node* node, osg::NodeVisitor* nv); @@ -49,7 +60,6 @@ namespace osgAnimation this Operation must be done each frame */ void clearTargets(); - LinkVisitor* getOrCreateLinkVisitor(); void setLinkVisitor(LinkVisitor*); diff --git a/include/osgAnimation/MorphGeometry b/include/osgAnimation/MorphGeometry index 1a242efd7..ab6c1bc8f 100644 --- a/include/osgAnimation/MorphGeometry +++ b/include/osgAnimation/MorphGeometry @@ -17,6 +17,7 @@ #include #include +#include #include #include @@ -28,7 +29,8 @@ namespace osgAnimation public: - enum Method { + enum Method + { NORMALIZED, RELATIVE }; @@ -59,18 +61,45 @@ namespace osgAnimation virtual const char* libraryName() const { return "osgAnimation"; } virtual const char* className() const { return "MorphGeometry"; } - virtual void transformSoftwareMethod(); + // set implementation of rig method + inline void setMorphTransformImplementation(MorphTransform*mt) { _morphTransformImplementation=mt; } + inline MorphTransform* getMorphTransformImplementation() { return _morphTransformImplementation.get(); } + inline const MorphTransform* getMorphTransformImplementation() const { return _morphTransformImplementation.get(); } /** Set the morphing method. */ - void setMethod(Method method) { _method = method; } + inline void setMethod(Method method) { _method = method; } /** Get the morphing method. */ inline Method getMethod() const { return _method; } /** Set flag for morphing normals. */ - void setMorphNormals(bool morphNormals) { _morphNormals = morphNormals; } + inline void setMorphNormals(bool morphNormals) { _morphNormals = morphNormals; } /** Get the flag for morphing normals. */ inline bool getMorphNormals() const { return _morphNormals; } + /** Get the list of MorphTargets.*/ + inline const MorphTargetList& getMorphTargetList() const { return _morphTargets; } + + /** Get the list of MorphTargets. Warning if you modify this array you will have to call dirty() */ + inline MorphTargetList& getMorphTargetList() { return _morphTargets; } + + /** Return the \c MorphTarget at position \c i.*/ + inline const MorphTarget& getMorphTarget( unsigned int i ) const { return _morphTargets[i]; } + + /** Return the \c MorphTarget at position \c i.*/ + inline MorphTarget& getMorphTarget( unsigned int i ) { return _morphTargets[i]; } + + /** Set source of vertices for this morph geometry */ + inline void setVertexSource(osg::Vec3Array *v) { _positionSource=v; } + + /** Get source of vertices for this morph geometry */ + inline osg::Vec3Array * getVertexSource() const { return _positionSource.get(); } + + /** Set source of normals for this morph geometry */ + inline void setNormalSource(osg::Vec3Array *n) { _normalSource=n; } + + /** Get source of normals for this morph geometry */ + inline osg::Vec3Array * getNormalSource() const { return _normalSource.get(); } + /** Add a \c MorphTarget to the \c MorphGeometry. * If \c MorphTarget is not \c NULL and is not contained in the \c MorphGeometry * then increment its reference count, add it to the MorphTargets list and @@ -80,20 +109,30 @@ namespace osgAnimation * @param weight The weight to be added to the \c MorphGeometry. * @return \c true for success; \c false otherwise. */ - virtual void addMorphTarget( osg::Geometry *morphTarget, float weight = 1.0 ) { _morphTargets.push_back(MorphTarget(morphTarget, weight)); _dirty = true; } + virtual void addMorphTarget( osg::Geometry *morphTarget, float weight = 1.0 ) + { + _morphTargets.push_back(MorphTarget(morphTarget, weight)); + _dirty = true; + } - virtual void removeMorphTarget( osg::Geometry *morphTarget ) { - for(MorphTargetList::iterator iterator = _morphTargets.begin() ; iterator != _morphTargets.end() ; ++ iterator) { - if(iterator->getGeometry() == morphTarget) { + virtual void removeMorphTarget( osg::Geometry *morphTarget ) + { + for(MorphTargetList::iterator iterator = _morphTargets.begin() ; iterator != _morphTargets.end() ; ++ iterator) + { + if(iterator->getGeometry() == morphTarget) + { _morphTargets.erase(iterator); break; } } } - virtual void removeMorphTarget( const std::string& name ) { - for(MorphTargetList::iterator iterator = _morphTargets.begin() ; iterator != _morphTargets.end() ; ++ iterator) { - if(iterator->getGeometry() && iterator->getGeometry()->getName() == name) { + virtual void removeMorphTarget( const std::string& name ) + { + for(MorphTargetList::iterator iterator = _morphTargets.begin() ; iterator != _morphTargets.end() ; ++ iterator) + { + if(iterator->getGeometry() && iterator->getGeometry()->getName() == name) + { _morphTargets.erase(iterator); break; } @@ -101,7 +140,8 @@ namespace osgAnimation } - void setWeight(unsigned int index, float morphWeight) + /** update a morph target at index setting its current weight to morphWeight */ + inline void setWeight(unsigned int index, float morphWeight) { if (index < _morphTargets.size()) { @@ -111,29 +151,22 @@ namespace osgAnimation } /** Set the MorphGeometry dirty.*/ - void dirty() { _dirty = true; } + inline void dirty(bool b=true) { _dirty = b; } + inline bool isDirty() const { return _dirty; } - /** Get the list of MorphTargets.*/ - const MorphTargetList& getMorphTargetList() const { return _morphTargets; } - - /** Get the list of MorphTargets. Warning if you modify this array you will have to call dirty() */ - MorphTargetList& getMorphTargetList() { return _morphTargets; } - - /** Return the \c MorphTarget at position \c i.*/ - inline const MorphTarget& getMorphTarget( unsigned int i ) const { return _morphTargets[i]; } - - /** Return the \c MorphTarget at position \c i.*/ - inline MorphTarget& getMorphTarget( unsigned int i ) { return _morphTargets[i]; } + /** for retrocompatibility */ + void transformSoftwareMethod() { (*_morphTransformImplementation.get())(*this); } protected: + osg::ref_ptr _morphTransformImplementation; /// Do we need to recalculate the morphed geometry? bool _dirty; Method _method; MorphTargetList _morphTargets; - std::vector _positionSource; - std::vector _normalSource; + osg::ref_ptr _positionSource; + osg::ref_ptr _normalSource; /// Do we also morph between normals? bool _morphNormals; @@ -153,7 +186,8 @@ namespace osgAnimation void addTarget(const std::string& name) { _targetNames.push_back(name); } unsigned int getNumTarget() const { return _targetNames.size(); } const std::string& getTargetName(unsigned int index) { return _targetNames[index]; } - void removeTarget(const std::string& name) { + void removeTarget(const std::string& name) + { TargetNames::iterator found = std::find(_targetNames.begin(), _targetNames.end(), name); if(found != _targetNames.end()) _targetNames.erase(found); @@ -163,9 +197,7 @@ namespace osgAnimation const std::vector& getTargetNames() const { return _targetNames; } std::vector& getTargetNames() { return _targetNames; } - void setTargetNames(const TargetNames& targetNames) { - _targetNames.assign(targetNames.begin(), targetNames.end()); - } + void setTargetNames(const TargetNames& targetNames) { _targetNames.assign(targetNames.begin(), targetNames.end()); } /** Callback method called by the NodeVisitor when visiting a node.*/ virtual void operator()(osg::Node* node, osg::NodeVisitor* nv); @@ -195,11 +227,15 @@ namespace osgAnimation if (!geom) return; - geom->transformSoftwareMethod(); + if (!geom->getMorphTransformImplementation()) + { + geom->setMorphTransformImplementation( new MorphTransformSoftware); + } + + MorphTransform& implementation = *geom->getMorphTransformImplementation(); + (implementation)(*geom); } }; - - } #endif diff --git a/include/osgAnimation/MorphTransformHardware b/include/osgAnimation/MorphTransformHardware new file mode 100644 index 000000000..838fc99cf --- /dev/null +++ b/include/osgAnimation/MorphTransformHardware @@ -0,0 +1,65 @@ +/* -*-c++-*- + * Copyright (C) 2017 Julien Valentin + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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 + * OpenSceneGraph Public License for more details. + */ + +#ifndef OSGANIMATION_MORPH_TRANSFORM_HARDWARE +#define OSGANIMATION_MORPH_TRANSFORM_HARDWARE 1 + +#include +#include +#include +#include +#include +#include + +///texture unit reserved for morphtarget TBO +#define MORPHTRANSHW_DEFAULTMORPHTEXTUREUNIT 7 + +namespace osgAnimation +{ + class MorphGeometry; + + /// This class manage format for hardware morphing + class OSGANIMATION_EXPORT MorphTransformHardware : public MorphTransform + { + public: + + MorphTransformHardware(); + + MorphTransformHardware(const MorphTransformHardware& rth, const osg::CopyOp& copyop); + + META_Object(osgAnimation,MorphTransformHardware); + + virtual void operator()(MorphGeometry&); + + inline void setShader( osg::Shader*s ) { _shader=s; } + inline const osg::Shader * getShader() const { return _shader.get(); } + inline osg::Shader * getShader() { return _shader.get(); } + + ///texture unit reserved for morphtarget TBO default is 7 + void setReservedTextureUnit(unsigned int t) { _reservedTextureUnit=t; } + unsigned int getReservedTextureUnit() const { return _reservedTextureUnit; } + + protected: + + bool init(MorphGeometry&); + + osg::ref_ptr _uniformTargetsWeight; + osg::ref_ptr _shader; + + bool _needInit; + unsigned int _reservedTextureUnit; + }; +} + +#endif diff --git a/include/osgAnimation/MorphTransformSoftware b/include/osgAnimation/MorphTransformSoftware new file mode 100644 index 000000000..50546501a --- /dev/null +++ b/include/osgAnimation/MorphTransformSoftware @@ -0,0 +1,46 @@ +/* -*-c++-*- + * Copyright (C) 2009 Cedric Pinson + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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 + * OpenSceneGraph Public License for more details. + */ + +#ifndef OSGANIMATION_MORPHTRANSFORM_SOFTWARE +#define OSGANIMATION_MORPHTRANSFORM_SOFTWARE 1 + +#include +#include +#include +#include + +namespace osgAnimation +{ + + class MorphGeometry; + + /// This class manage format for software morphing + class OSGANIMATION_EXPORT MorphTransformSoftware : public MorphTransform + { + public: + MorphTransformSoftware():_needInit(true) {} + MorphTransformSoftware(const MorphTransformSoftware& rts,const osg::CopyOp& copyop): MorphTransform(rts, copyop), _needInit(true) {} + + META_Object(osgAnimation,MorphTransformSoftware) + + bool init(MorphGeometry&); + virtual void operator()(MorphGeometry&); + + protected: + bool _needInit; + + }; +} + +#endif diff --git a/include/osgAnimation/RigGeometry b/include/osgAnimation/RigGeometry index 74a5cf00f..f9a2b1887 100644 --- a/include/osgAnimation/RigGeometry +++ b/include/osgAnimation/RigGeometry @@ -23,7 +23,6 @@ namespace osgAnimation { - // The idea is to compute a bounding box with a factor x of the first step we compute the bounding box class OSGANIMATION_EXPORT RigComputeBoundingBoxCallback : public osg::Drawable::ComputeBoundingBoxCallback { @@ -37,8 +36,8 @@ namespace osgAnimation META_Object(osgAnimation, RigComputeBoundingBoxCallback); - void reset() { _computed = false; } + virtual osg::BoundingBox computeBound(const osg::Drawable& drawable) const; protected: mutable bool _computed; @@ -57,40 +56,36 @@ namespace osgAnimation META_Object(osgAnimation, RigGeometry); - void setInfluenceMap(VertexInfluenceMap* vertexInfluenceMap) { _vertexInfluenceMap = vertexInfluenceMap; } - const VertexInfluenceMap* getInfluenceMap() const { return _vertexInfluenceMap.get();} - VertexInfluenceMap* getInfluenceMap() { return _vertexInfluenceMap.get();} + inline void setInfluenceMap(VertexInfluenceMap* vertexInfluenceMap) { _vertexInfluenceMap = vertexInfluenceMap; } + inline const VertexInfluenceMap* getInfluenceMap() const { return _vertexInfluenceMap.get(); } + inline VertexInfluenceMap* getInfluenceMap() { return _vertexInfluenceMap.get(); } - const Skeleton* getSkeleton() const; - Skeleton* getSkeleton(); + inline const Skeleton* getSkeleton() const { return _root.get(); } + inline Skeleton* getSkeleton() { return _root.get(); } // will be used by the update callback to init correctly the rig mesh - void setSkeleton(Skeleton*); + inline void setSkeleton(Skeleton* root) { _root = root; } - void setNeedToComputeMatrix(bool state) { _needToComputeMatrix = state;} - bool getNeedToComputeMatrix() const { return _needToComputeMatrix;} - - - // this build the internal database about vertex influence and bones - void buildVertexInfluenceSet(); - const VertexInfluenceSet& getVertexInfluenceSet() const; + void setNeedToComputeMatrix(bool state) { _needToComputeMatrix = state; } + bool getNeedToComputeMatrix() const { return _needToComputeMatrix; } void computeMatrixFromRootSkeleton(); - // set implementation of rig method - void setRigTransformImplementation(RigTransform*); - RigTransform* getRigTransformImplementation(); - const RigTransform* getRigTransformImplementation() const { return _rigTransformImplementation.get(); } + inline RigTransform* getRigTransformImplementation() { return _rigTransformImplementation.get(); } + inline void setRigTransformImplementation(RigTransform* rig) { _rigTransformImplementation = rig; } + inline const RigTransform* getRigTransformImplementation() const { return _rigTransformImplementation.get(); } - virtual void drawImplementation(osg::RenderInfo& renderInfo) const; void update(); + void buildVertexInfluenceSet() { _rigTransformImplementation->prepareData(*this); } + const osg::Matrix& getMatrixFromSkeletonToGeometry() const; + const osg::Matrix& getInvMatrixFromSkeletonToGeometry() const; - osg::Geometry* getSourceGeometry(); - const osg::Geometry* getSourceGeometry() const; - void setSourceGeometry(osg::Geometry* geometry); + inline osg::Geometry* getSourceGeometry() { return _geometry.get(); } + inline const osg::Geometry* getSourceGeometry() const { return _geometry.get(); } + inline void setSourceGeometry(osg::Geometry* geometry) { _geometry = geometry; } void copyFrom(osg::Geometry& from); @@ -111,8 +106,6 @@ namespace osgAnimation osg::ref_ptr _geometry; osg::ref_ptr _rigTransformImplementation; - - VertexInfluenceSet _vertexInfluenceSet; osg::ref_ptr _vertexInfluenceMap; osg::Matrix _matrixFromSkeletonToGeometry; @@ -120,8 +113,7 @@ namespace osgAnimation osg::observer_ptr _root; bool _needToComputeMatrix; - - }; + }; struct UpdateRigGeometry : public osg::Drawable::UpdateCallback @@ -135,7 +127,8 @@ namespace osgAnimation META_Object(osgAnimation, UpdateRigGeometry); - virtual void update(osg::NodeVisitor* nv, osg::Drawable* drw) { + virtual void update(osg::NodeVisitor* nv, osg::Drawable* drw) + { RigGeometry* geom = dynamic_cast(drw); if(!geom) return; @@ -151,7 +144,7 @@ namespace osgAnimation osg::notify(osg::WARN) << "A RigGeometry did not find a parent skeleton for RigGeometry ( " << geom->getName() << " )" << std::endl; return; } - geom->buildVertexInfluenceSet(); + geom->getRigTransformImplementation()->prepareData(*geom); geom->setSkeleton(finder._root.get()); } @@ -161,7 +154,8 @@ namespace osgAnimation if(geom->getNeedToComputeMatrix()) geom->computeMatrixFromRootSkeleton(); - if(geom->getSourceGeometry()) { + if(geom->getSourceGeometry()) + { osg::Drawable::UpdateCallback * up = dynamic_cast(geom->getSourceGeometry()->getUpdateCallback()); if(up) up->update(nv, geom->getSourceGeometry()); diff --git a/include/osgAnimation/RigTransform b/include/osgAnimation/RigTransform index 66ae0a219..ba41b8db1 100644 --- a/include/osgAnimation/RigTransform +++ b/include/osgAnimation/RigTransform @@ -1,15 +1,15 @@ - /* -*-c++-*- - * Copyright (C) 2009 Cedric Pinson - * - * This library is open source and may be redistributed and/or modified under - * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or - * (at your option) any later version. The full license is in LICENSE file - * included with this distribution, and on the openscenegraph.org website. - * - * This library 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 - * OpenSceneGraph Public License for more details. +/* -*-c++-*- +* Copyright (C) 2009 Cedric Pinson +* +* This library is open source and may be redistributed and/or modified under +* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or +* (at your option) any later version. The full license is in LICENSE file +* included with this distribution, and on the openscenegraph.org website. +* +* This library 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 +* OpenSceneGraph Public License for more details. */ #ifndef OSGANIMATION_RIGTRANSFORM @@ -33,10 +33,31 @@ namespace osgAnimation virtual void operator()(RigGeometry&) {} + /// to call manually when a skeleton is reacheable from the rig + /// in order to prepare technic data before rendering + virtual bool prepareData(RigGeometry&) { return true; } + protected: virtual ~RigTransform() {} }; + class MorphGeometry; + + class MorphTransform : public osg::Object + { + public: + MorphTransform() {} + MorphTransform(const MorphTransform& org, const osg::CopyOp& copyop): + osg::Object(org, copyop) {} + + META_Object(osgAnimation,MorphTransform) + + virtual void operator()(MorphGeometry&) {} + + protected: + virtual ~MorphTransform() {} + + }; } diff --git a/include/osgAnimation/RigTransformHardware b/include/osgAnimation/RigTransformHardware index ce9006ddd..5b020f4a4 100644 --- a/include/osgAnimation/RigTransformHardware +++ b/include/osgAnimation/RigTransformHardware @@ -1,5 +1,6 @@ /* -*-c++-*- * Copyright (C) 2009 Cedric Pinson + * Copyright (C) 2017 Julien Valentin * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or @@ -22,6 +23,8 @@ #include #include +#define RIGTRANSHW_DEFAULT_FIRST_VERTATTRIB_TARGETTED 11 + namespace osgAnimation { class RigGeometry; @@ -37,54 +40,42 @@ namespace osgAnimation META_Object(osgAnimation,RigTransformHardware); - typedef osg::Matrix MatrixType; - typedef osgAnimation::Bone BoneType; typedef std::vector > BoneWeightAttribList; - typedef std::vector > BonePalette; - typedef std::map BoneNamePaletteIndex; - + typedef std::vector > BonePalette; + typedef std::map BoneNamePaletteIndex; typedef std::vector MatrixPalette; - struct IndexWeightEntry - { - int _boneIndex; - float _boneWeight; - IndexWeightEntry() { _boneIndex = 0; _boneWeight = 0;} - IndexWeightEntry(int index, float weight) { _boneIndex = index; _boneWeight = weight;} - int getIndex() const { return _boneIndex; } - float getWeight() const { return _boneWeight; } - }; - typedef std::vector > VertexIndexWeightList; + ///set the first Vertex Attribute Array index of the rig generated by this technic (default:11) + void setFirstVertexAttributeTarget(unsigned int i) { _minAttribIndex=i; } + unsigned int getFirstVertexAttributeTarget()const { return _minAttribIndex; } + void setShader(osg::Shader* shader) { _shader = shader; } + const osg::Shader* getShader() const { return _shader.get(); } + osg::Shader* getShader() { return _shader.get(); } - osg::Vec4Array* getVertexAttrib(int index); - int getNumVertexAttrib(); + osg::Vec4Array* getVertexAttrib(unsigned int index); + unsigned int getNumVertexAttrib() const { return _boneWeightAttribArrays.size(); } + + const unsigned int &getNumBonesPerVertex() const { return _bonesPerVertex; } + const unsigned int &getNumVertexes() const { return _nbVertices; } + + const BoneNamePaletteIndex& getBoneNameToPalette() { return _boneNameToPalette; } + const BonePalette& getBonePalette() { return _bonePalette; } + osg::Uniform* getMatrixPaletteUniform() { return _uniformMatrixPalette.get(); } - osg::Uniform* getMatrixPaletteUniform(); void computeMatrixPaletteUniform(const osg::Matrix& transformFromSkeletonToGeometry, const osg::Matrix& invTransformFromSkeletonToGeometry); - int getNumBonesPerVertex() const; - int getNumVertexes() const; - - bool createPalette(int nbVertexes, BoneMap boneMap, const VertexInfluenceSet::VertexIndexToBoneWeightMap& vertexIndexToBoneWeightMap); - + // update rig if needed virtual void operator()(RigGeometry&); - void setShader(osg::Shader*); - const BoneNamePaletteIndex& getBoneNameToPalette() { - return _boneNameToPalette; - } + // init/reset animations data + virtual bool prepareData(RigGeometry& ); protected: - bool init(RigGeometry&); + unsigned int _bonesPerVertex; + unsigned int _nbVertices; - BoneWeightAttribList createVertexAttribList(); - osg::Uniform* createVertexUniform(); - - int _bonesPerVertex; - int _nbVertexes; - VertexIndexWeightList _vertexIndexMatrixWeightList; BonePalette _bonePalette; BoneNamePaletteIndex _boneNameToPalette; BoneWeightAttribList _boneWeightAttribArrays; @@ -92,6 +83,13 @@ namespace osgAnimation osg::ref_ptr _shader; bool _needInit; + unsigned int _minAttribIndex; + bool buildPalette(const BoneMap& boneMap,const RigGeometry& rig); + + //on first update + virtual bool init(RigGeometry& ); + + std::vector _perVertexInfluences; }; } diff --git a/include/osgAnimation/RigTransformSoftware b/include/osgAnimation/RigTransformSoftware index 300e513fd..4424498ba 100644 --- a/include/osgAnimation/RigTransformSoftware +++ b/include/osgAnimation/RigTransformSoftware @@ -1,5 +1,6 @@ /* -*-c++-*- * Copyright (C) 2009 Cedric Pinson + * Copyright (C) 2017 Julien Valentin * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or @@ -36,36 +37,49 @@ namespace osgAnimation META_Object(osgAnimation,RigTransformSoftware) virtual void operator()(RigGeometry&); + //to call when a skeleton is reacheable from the rig to prepare technic data + virtual bool prepareData(RigGeometry&); - class BoneWeight + typedef std::pair LocalBoneIDWeight; + class BonePtrWeight: LocalBoneIDWeight { public: - BoneWeight(Bone* bone, float weight) : _bone(bone), _weight(weight) {} - const Bone* getBone() const { return _bone.get(); } - float getWeight() const { return _weight; } - void setWeight(float w) { _weight = w; } + BonePtrWeight(unsigned int id,float weight, Bone*bone=0 ): LocalBoneIDWeight(id,weight), _boneptr(bone) {} + BonePtrWeight(const BonePtrWeight &bw2): LocalBoneIDWeight(bw2.getBoneID(),bw2.getWeight()), _boneptr(bw2._boneptr.get()) {} + inline const float & getWeight() const { return second; } + inline void setWeight(float b) { second=b; } + inline const unsigned int & getBoneID() const { return first; } + inline void setBoneID(unsigned int b) { first=b; } + inline bool operator< (const BonePtrWeight &b1) const { + if (second > b1.second) return true; + if (second < b1.second) return false; + return (first > b1.first); + } + ///set Bone pointer + inline const Bone * getBonePtr() const { return _boneptr.get(); } + inline void setBonePtr(Bone*b) { _boneptr=b; } protected: - osg::observer_ptr _bone; - float _weight; + osg::observer_ptr< Bone > _boneptr; }; - typedef std::vector BoneWeightList; - typedef std::vector VertexList; + typedef std::vector BonePtrWeightList; - class UniqBoneSetVertexSet + /// map a set of boneinfluence to a list of vertex indices sharing this set + class VertexGroup { public: - BoneWeightList& getBones() { return _bones; } - VertexList& getVertexes() { return _vertexes; } + inline BonePtrWeightList& getBoneWeights() { return _boneweights; } - void resetMatrix() + inline IndexList& getVertices() { return _vertexes; } + + inline void resetMatrix() { _result.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1); } - void accummulateMatrix(const osg::Matrix& invBindMatrix, const osg::Matrix& matrix, osg::Matrix::value_type weight) + inline void accummulateMatrix(const osg::Matrix& invBindMatrix, const osg::Matrix& matrix, osg::Matrix::value_type weight) { osg::Matrix m = invBindMatrix * matrix; osg::Matrix::value_type* ptr = m.ptr(); @@ -86,20 +100,19 @@ namespace osgAnimation ptrresult[13] += ptr[13] * weight; ptrresult[14] += ptr[14] * weight; } - void computeMatrixForVertexSet() + inline void computeMatrixForVertexSet() { - if (_bones.empty()) + if (_boneweights.empty()) { - osg::notify(osg::WARN) << this << " RigTransformSoftware::UniqBoneSetVertexSet no bones found" << std::endl; + osg::notify(osg::WARN) << this << " RigTransformSoftware::VertexGroup no bones found" << std::endl; _result = osg::Matrix::identity(); return; } resetMatrix(); - int size = _bones.size(); - for (int i = 0; i < size; i++) + for(BonePtrWeightList::iterator bwit=_boneweights.begin(); bwit!=_boneweights.end(); ++bwit ) { - const Bone* bone = _bones[i].getBone(); + const Bone* bone = bwit->getBonePtr(); if (!bone) { osg::notify(osg::WARN) << this << " RigTransformSoftware::computeMatrixForVertexSet Warning a bone is null, skip it" << std::endl; @@ -107,68 +120,67 @@ namespace osgAnimation } const osg::Matrix& invBindMatrix = bone->getInvBindMatrixInSkeletonSpace(); const osg::Matrix& matrix = bone->getMatrixInSkeletonSpace(); - osg::Matrix::value_type w = _bones[i].getWeight(); + osg::Matrix::value_type w = bwit->getWeight(); accummulateMatrix(invBindMatrix, matrix, w); } } - const osg::Matrix& getMatrix() const { return _result;} + void normalize(); + inline const osg::Matrix& getMatrix() const { return _result; } protected: - BoneWeightList _bones; - VertexList _vertexes; + BonePtrWeightList _boneweights; + IndexList _vertexes; osg::Matrix _result; }; - - - template void compute(const osg::Matrix& transform, const osg::Matrix& invTransform, const V* src, V* dst) + template + inline void compute(const osg::Matrix& transform, const osg::Matrix& invTransform, const V* src, V* dst) { // the result of matrix mult should be cached to be used for vertexes transform and normal transform and maybe other computation - int size = _boneSetVertexSet.size(); - for (int i = 0; i < size; i++) + for(VertexGroupList::iterator itvg=_uniqVertexGroupList.begin(); itvg!=_uniqVertexGroupList.end(); ++itvg) { - UniqBoneSetVertexSet& uniq = _boneSetVertexSet[i]; + VertexGroup& uniq = *itvg; uniq.computeMatrixForVertexSet(); osg::Matrix matrix = transform * uniq.getMatrix() * invTransform; - const VertexList& vertexes = uniq.getVertexes(); - int vertexSize = vertexes.size(); - for (int j = 0; j < vertexSize; j++) + const IndexList& vertexes = uniq.getVertices(); + for(IndexList::const_iterator vertIDit=vertexes.begin(); vertIDit!=vertexes.end(); ++vertIDit) { - int idx = vertexes[j]; - dst[idx] = src[idx] * matrix; + dst[*vertIDit] = src[*vertIDit] * matrix; } + } } - - template void computeNormal(const osg::Matrix& transform, const osg::Matrix& invTransform, const V* src, V* dst) + template + inline void computeNormal(const osg::Matrix& transform, const osg::Matrix& invTransform, const V* src, V* dst) { - int size = _boneSetVertexSet.size(); - for (int i = 0; i < size; i++) + for(VertexGroupList::iterator itvg=_uniqVertexGroupList.begin(); itvg!=_uniqVertexGroupList.end(); ++itvg) { - UniqBoneSetVertexSet& uniq = _boneSetVertexSet[i]; + VertexGroup& uniq = *itvg; uniq.computeMatrixForVertexSet(); osg::Matrix matrix = transform * uniq.getMatrix() * invTransform; - const VertexList& vertexes = uniq.getVertexes(); - int vertexSize = vertexes.size(); - for (int j = 0; j < vertexSize; j++) + const IndexList& vertexes = uniq.getVertices(); + for(IndexList::const_iterator vertIDit=vertexes.begin(); vertIDit!=vertexes.end(); ++vertIDit) { - int idx = vertexes[j]; - dst[idx] = osg::Matrix::transform3x3(src[idx],matrix); + dst[*vertIDit] = osg::Matrix::transform3x3(src[*vertIDit],matrix); } } } protected: - bool init(RigGeometry&); - void initVertexSetFromBones(const BoneMap& map, const VertexInfluenceSet::UniqVertexSetToBoneSetList& influence); - std::vector _boneSetVertexSet; - bool _needInit; + virtual bool init(RigGeometry&); + std::map _invalidInfluence; + + typedef std::vector VertexGroupList; + VertexGroupList _uniqVertexGroupList; + + void buildMinimumUpdateSet(const RigGeometry&rig ); + }; } diff --git a/include/osgAnimation/VertexInfluence b/include/osgAnimation/VertexInfluence index 47941a43f..1bf1e6e01 100644 --- a/include/osgAnimation/VertexInfluence +++ b/include/osgAnimation/VertexInfluence @@ -1,5 +1,6 @@ /* -*-c++-*- * Copyright (C) 2008 Cedric Pinson + * Copyright (C) 2017 Julien Valentin * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or @@ -23,22 +24,31 @@ namespace osgAnimation { + class Skeleton; - // first is vertex index, and second the weight, the - typedef std::pair VertexIndexWeight; - typedef std::vector VertexList; - class OSGANIMATION_EXPORT VertexInfluence : public VertexList + // first is bonename, and second the weight + typedef std::pair BoneWeight; + // first is vertex index, and second the weight + typedef std::pair VertexIndexWeight; + // list of IndexWeight + typedef std::vector IndexWeightList; + // list of IndexWeight + typedef std::vector BoneWeightList; + // list of Index + typedef std::vector IndexList; + + //Bone influence list + class OSGANIMATION_EXPORT VertexInfluence : public IndexWeightList { public: - const std::string& getName() const { return _name;} - void setName(const std::string& name) { _name = name;} - + const std::string& getName() const { return _name; } + void setName(const std::string& name) { _name = name; } protected: // the name is the bone to link to std::string _name; }; - class VertexInfluenceMap : public std::map , public osg::Object + class VertexInfluenceMap : public std::map, public osg::Object { public: META_Object(osgAnimation, VertexInfluenceMap); @@ -46,61 +56,32 @@ namespace osgAnimation VertexInfluenceMap() {} VertexInfluenceMap(const osgAnimation::VertexInfluenceMap& org, const osg::CopyOp& copyop): std::map(org), - osg::Object(org, copyop) - {} - }; + osg::Object(org, copyop) {} + ///normalize per vertex weights given numvert of the attached mesh + void normalize(unsigned int numvert); - // this class manage VertexInfluence database by mesh - // reference bones per vertex ... - class OSGANIMATION_EXPORT VertexInfluenceSet - { - public: - typedef std::vector BoneToVertexList; + ///remove weakest influences in order to fit targetted numbonepervertex + void cullInfluenceCountPerVertex(unsigned int maxnumbonepervertex, float minweight=0, bool renormalize=true); - class BoneWeight + //compute PerVertexInfluenceList + void computePerVertexInfluenceList(std::vector& perVertexInfluenceList, unsigned int numvert) const; + + /// map a set of boneinfluence to a list of vertex indices sharing this set + class VertexGroup: public std::pair { public: - BoneWeight(const std::string& name, float weight) : _boneName(name), _weight(weight) {} - const std::string& getBoneName() const { return _boneName; } - float getWeight() const { return _weight; } - void setWeight(float weight) { _weight = weight; } - bool operator==(const BoneWeight& b) const { return (_boneName == b.getBoneName() && _weight == b.getWeight()); } - protected: - std::string _boneName; - float _weight; + inline const BoneWeightList& getBoneWeights() const { return first; } + inline void setBoneWeights( BoneWeightList& o ) { first=o; } + inline IndexList& vertIDs() { return second; } }; - typedef std::vector BoneWeightList; - typedef std::map VertexIndexToBoneWeightMap; + /// compute the minimal VertexGroup Set in which vertices shares the same influence set + void computeMinimalVertexGroupList(std::vector&uniqVertexGroupList, unsigned int numvert) const; - class UniqVertexSetToBoneSet - { - public: - void setBones(BoneWeightList& bones) { _bones = bones;} - const BoneWeightList& getBones() const { return _bones;} - std::vector& getVertexes() { return _vertexes;} - const std::vector& getVertexes() const { return _vertexes;} - protected: - std::vector _vertexes; - BoneWeightList _bones; // here we could limit matrix operation by caching (weight * matrix) - }; - - typedef std::vector UniqVertexSetToBoneSetList; - - const UniqVertexSetToBoneSetList& getUniqVertexSetToBoneSetList() const { return _uniqVertexSetToBoneSet;} - void addVertexInfluence(const VertexInfluence& v); - void buildVertex2BoneList(); - void buildUniqVertexSetToBoneSetList(); - void clear(); - - const VertexIndexToBoneWeightMap& getVertexToBoneList() const; - protected: - BoneToVertexList _bone2Vertexes; - VertexIndexToBoneWeightMap _vertex2Bones; - UniqVertexSetToBoneSetList _uniqVertexSetToBoneSet; + //Experimental removal of unexpressed bone from the skeleton + void removeUnexpressedBones(Skeleton &skel) const; }; - } #endif diff --git a/include/osgDB/DataTypes b/include/osgDB/DataTypes index 8d319e806..4b6a8bbca 100644 --- a/include/osgDB/DataTypes +++ b/include/osgDB/DataTypes @@ -134,7 +134,7 @@ public: : _name(copy._name), _indentDelta(copy._indentDelta) {} void set( const char* name, int delta=0 ) - { _name = name, _indentDelta = delta; } + { _name = name; _indentDelta = delta; } std::string _name; int _indentDelta; diff --git a/include/osgDB/Registry b/include/osgDB/Registry index 62d4ac884..87076dc81 100644 --- a/include/osgDB/Registry +++ b/include/osgDB/Registry @@ -366,6 +366,13 @@ class OSGDB_EXPORT Registry : public osg::Referenced /** Set the password map to be used by plugins when access files from secure locations.*/ void setAuthenticationMap(AuthenticationMap* authenticationMap) { _authenticationMap = authenticationMap; } + /** Get the password map to be used by plugins when access files from secure locations. Create a AuthenticationMap if one isn't already assigned.*/ + AuthenticationMap* getOrCreateAuthenticationMap() + { + if (!_authenticationMap) _authenticationMap = new AuthenticationMap; + return _authenticationMap.get(); + } + /** Get the password map to be used by plugins when access files from secure locations.*/ AuthenticationMap* getAuthenticationMap() { return _authenticationMap.get(); } diff --git a/include/osgParticle/ParticleSystem b/include/osgParticle/ParticleSystem index 4348cb075..099549501 100644 --- a/include/osgParticle/ParticleSystem +++ b/include/osgParticle/ParticleSystem @@ -265,7 +265,7 @@ namespace osgParticle * for all graphics contexts. */ virtual void releaseGLObjects(osg::State* state=0) const; - virtual osg::VertexArrayState* createVertexArrayState(osg::RenderInfo& renderInfo) const; + virtual osg::VertexArrayState* createVertexArrayStateImplemenation(osg::RenderInfo& renderInfo) const; void adjustEstimatedMaxNumOfParticles(int delta) { _estimatedMaxNumOfParticles += delta; } diff --git a/include/osgShadow/ShadowMap b/include/osgShadow/ShadowMap index cec66ac20..535ba9c4c 100644 --- a/include/osgShadow/ShadowMap +++ b/include/osgShadow/ShadowMap @@ -68,6 +68,8 @@ class OSGSHADOW_EXPORT ShadowMap : public ShadowTechnique /** Add a shader to internal list, will be used instead of the default ones */ inline void addShader(osg::Shader* shader) { _shaderList.push_back(shader); } + template void addShader( const osg::ref_ptr& shader ) { addShader(shader.get()); } + /** Reset internal shader list */ inline void clearShaderList() { _shaderList.clear(); } diff --git a/include/osgTerrain/GeometryPool b/include/osgTerrain/GeometryPool index bb8e1e34b..026cc01c5 100644 --- a/include/osgTerrain/GeometryPool +++ b/include/osgTerrain/GeometryPool @@ -66,7 +66,7 @@ class OSGTERRAIN_EXPORT SharedGeometry : public osg::Drawable const VertexToHeightFieldMapping& getVertexToHeightFieldMapping() const { return _vertexToHeightFieldMapping; } - osg::VertexArrayState* createVertexArrayState(osg::RenderInfo& renderInfo) const; + osg::VertexArrayState* createVertexArrayStateImplementation(osg::RenderInfo& renderInfo) const; void compileGLObjects(osg::RenderInfo& renderInfo) const; diff --git a/include/osgText/Font b/include/osgText/Font index 952a6fda4..ab4641c93 100644 --- a/include/osgText/Font +++ b/include/osgText/Font @@ -27,6 +27,7 @@ namespace osgText { // forward declare Font class Font; +class TextBase; #ifdef OSG_PROVIDE_READFILE /** Read a font from specified file. The filename may contain a path. @@ -84,13 +85,9 @@ public: static osg::ref_ptr& getDefaultFont(); - void setTexEnv(osg::TexEnv* texenv) { if (texenv) _texenv = texenv; } - inline osg::TexEnv* getTexEnv() { return _texenv.get(); } - inline const osg::TexEnv* getTexEnv() const { return _texenv.get(); } - - void setStateSet(osg::StateSet* stateset) { _stateset = stateset; } - osg::StateSet* getStateSet() { return _stateset.get(); } - const osg::StateSet* getStateSet() const { return _stateset.get(); } + typedef std::vector< osg::ref_ptr > StateSets; + StateSets& getCachedStateSets() { return _statesets; } + const StateSets& getCachedStateSets() const { return _statesets; } /** Get a kerning (adjustment of spacing of two adjacent character) for specified charcodes and a font resolution.*/ @@ -110,19 +107,6 @@ public: * return true on success, return false when not supported.*/ virtual bool getVerticalSize(float& ascender, float& descender) const { return _implementation ? _implementation->getVerticalSize(ascender, descender) : false; } - /** Set the margin around each glyph, - * to ensure that texture filtering doesn't bleed adjacent glyph's into each other. - * Default margin is 1 texels.*/ - void setGlyphImageMargin(unsigned int margin); - unsigned int getGlyphImageMargin() const; - - /** Set the margin ratio around each glyph, relative to the glyph's size. - * to ensure that texture filtering doesn't bleed adjacent glyph's into each other. - * Default margin is 0.05.*/ - void setGlyphImageMarginRatio(float margin); - float getGlyphImageMarginRatio() const; - - /** Set the size of texture to create to store the glyph images when rendering. * Note, this doesn't affect already created Texture Glhph's.*/ void setTextureSizeHint(unsigned int width,unsigned int height); @@ -140,6 +124,9 @@ public: void setMagFilterHint(osg::Texture::FilterMode mode); osg::Texture::FilterMode getMagFilterHint() const; + void setMaxAnisotropy(float anis) { _maxAnisotropy = anis; } + float getMaxAnisotropy() const { return _maxAnisotropy; } + unsigned int getFontDepth() const { return _depth; } void setNumberCurveSamples(unsigned int numSamples) { _numCurveSamples = numSamples; } @@ -170,13 +157,14 @@ public: typedef std::vector< osg::ref_ptr > GlyphTextureList; GlyphTextureList& getGlyphTextureList() { return _glyphTextureList; } + void assignGlyphToGlyphTexture(Glyph* glyph, ShaderTechnique shaderTechnique); + protected: virtual ~Font(); void addGlyph(const FontResolution& fontRes, unsigned int charcode, Glyph* glyph); - typedef std::vector< osg::ref_ptr > StateSetList; typedef std::map< unsigned int, osg::ref_ptr > GlyphMap; typedef std::map< unsigned int, osg::ref_ptr > Glyph3DMap; @@ -185,8 +173,7 @@ protected: mutable OpenThreads::Mutex _glyphMapMutex; - osg::ref_ptr _texenv; - osg::ref_ptr _stateset; + StateSets _statesets; FontSizeGlyphMap _sizeGlyphMap; GlyphTextureList _glyphTextureList; @@ -195,13 +182,12 @@ protected: // current active size of font FontResolution _fontSize; - unsigned int _margin; - float _marginRatio; unsigned int _textureWidthHint; unsigned int _textureHeightHint; osg::Texture::FilterMode _minFilterHint; osg::Texture::FilterMode _magFilterHint; + float _maxAnisotropy; unsigned int _depth; unsigned int _numCurveSamples; @@ -247,8 +233,6 @@ public: virtual bool getVerticalSize(float & /*ascender*/, float & /*descender*/) const { return false; } }; - - }; } diff --git a/include/osgText/Glyph b/include/osgText/Glyph index f08686841..2d1eafa05 100644 --- a/include/osgText/Glyph +++ b/include/osgText/Glyph @@ -30,15 +30,6 @@ #include -// GL_ALPHA is deprecated in GL3/GL4 core profile, use GL_RED and a shader in this case. See osgText example. -#if defined(OSG_GL3_AVAILABLE) && !defined(OSG_GL2_AVAILABLE) && !defined(OSG_GL1_AVAILABLE) -#define OSGTEXT_GLYPH_FORMAT GL_RED -#define OSGTEXT_GLYPH_INTERNALFORMAT GL_R8 -#else -#define OSGTEXT_GLYPH_FORMAT GL_ALPHA -#define OSGTEXT_GLYPH_INTERNALFORMAT GL_ALPHA -#endif - namespace osgText { class Font; @@ -47,6 +38,14 @@ class Glyph3D; class GlyphGeometry; class GlyphTexture; +enum ShaderTechnique +{ + NO_TEXT_SHADER = 0x0, + GREYSCALE = 0x1, + SIGNED_DISTANCE_FIELD = 0x2, + ALL_FEATURES = GREYSCALE | SIGNED_DISTANCE_FIELD +}; + class OSGTEXT_EXPORT Glyph : public osg::Image { public: @@ -58,6 +57,9 @@ public: unsigned int getGlyphCode() const { return _glyphCode; } + void setFontResolution(const FontResolution& fontRes) { _fontResolution = fontRes; } + const FontResolution& getFontResolution() const { return _fontResolution; } + void setWidth(float width) { _width = width; } float getWidth() const { return _width; } @@ -76,21 +78,33 @@ public: void setVerticalAdvance(float advance); float getVerticalAdvance() const; - void setTexture(GlyphTexture* texture); - GlyphTexture* getTexture(); - const GlyphTexture* getTexture() const; + struct TextureInfo : public osg::Referenced + { + TextureInfo(): + texture(0), + texelMargin(0.0f) {} - void setTexturePosition(int posX,int posY); - int getTexturePositionX() const; - int getTexturePositionY() const; + TextureInfo(GlyphTexture* tex, int x, int y, const osg::Vec2& mintc, const osg::Vec2& maxtc, float margin): + texture(tex), + texturePositionX(x), + texturePositionY(y), + minTexCoord(mintc), + maxTexCoord(maxtc), + texelMargin(margin) {} - void setMinTexCoord(const osg::Vec2& coord); - const osg::Vec2& getMinTexCoord() const; + GlyphTexture* texture; + int texturePositionX; + int texturePositionY; + osg::Vec2 minTexCoord; + osg::Vec2 maxTexCoord; + float texelMargin; + }; - void setMaxTexCoord(const osg::Vec2& coord); - const osg::Vec2& getMaxTexCoord() const; + void setTextureInfo(ShaderTechnique technique, TextureInfo* info); - void subload() const; + const TextureInfo* getTextureInfo(ShaderTechnique technique) const; + + TextureInfo* getOrCreateTextureInfo(ShaderTechnique technique); protected: @@ -99,6 +113,8 @@ protected: Font* _font; unsigned int _glyphCode; + FontResolution _fontResolution; + float _width; float _height; @@ -108,15 +124,8 @@ protected: osg::Vec2 _verticalBearing; float _verticalAdvance; - GlyphTexture* _texture; - int _texturePosX; - int _texturePosY; - osg::Vec2 _minTexCoord; - osg::Vec2 _maxTexCoord; - - typedef osg::buffered_value GLObjectList; - mutable GLObjectList _globjList; - + typedef std::vector< osg::ref_ptr > TextureInfoList; + TextureInfoList _textureInfoList; }; class OSGTEXT_EXPORT GlyphGeometry : public osg::Referenced @@ -253,12 +262,13 @@ public: /** return -1 if *this < *rhs, 0 if *this==*rhs, 1 if *this>*rhs.*/ virtual int compare(const osg::StateAttribute& rhs) const; - /** Set the margin around each glyph, to ensure that texture filtering doesn't bleed adjacent glyph's into each other.*/ - void setGlyphImageMargin(unsigned int margin) { _margin = margin; } - unsigned int getGlyphImageMargin() const { return _margin; } + void setShaderTechnique(ShaderTechnique technique) { _shaderTechnique = technique; } - void setGlyphImageMarginRatio(float margin) { _marginRatio = margin; } - float getGlyphImageMarginRatio() const { return _marginRatio; } + ShaderTechnique getShaderTechnique() const { return _shaderTechnique; } + + + int getEffectMargin(const Glyph* glyph); + int getTexelMargin(const Glyph* glyph); bool getSpaceForGlyph(Glyph* glyph, int& posX, int& posY); @@ -277,14 +287,13 @@ protected: virtual ~GlyphTexture(); + void copyGlyphImage(Glyph* glyph, Glyph::TextureInfo* info); - // parameter used to compute the size and position of empty space - // in the texture which could accommodate new glyphs. - int _margin; - float _marginRatio; - int _usedY; - int _partUsedX; - int _partUsedY; + ShaderTechnique _shaderTechnique; + + int _usedY; + int _partUsedX; + int _partUsedY; typedef std::vector< osg::ref_ptr > GlyphRefList; typedef std::vector< const Glyph* > GlyphPtrList; diff --git a/include/osgText/Text b/include/osgText/Text index db497792f..b2ae9c695 100644 --- a/include/osgText/Text +++ b/include/osgText/Text @@ -36,15 +36,12 @@ public: virtual const char* className() const { return "Text"; } virtual const char* libraryName() const { return "osgText"; } - virtual void setFont(Font* font=0) { setFont(osg::ref_ptr(font)); }; + /** Set the ShaderTechnique hint to specify what fatures in the text shaders to enable.*/ + void setShaderTechnique(ShaderTechnique technique); - /** Set the Font to use to render the text.*/ - virtual void setFont(osg::ref_ptr font); + /** Get the ShaderTechnique hint.*/ + ShaderTechnique getShaderTechnique() { return _shaderTechnique; } - /** Set the font, loaded from the specified front file, to use to render the text, - * setFont("") sets the use of the default font. - * See the osgText::readFontFile function for how the font file will be located. */ - virtual void setFont(const std::string& fontfile) { TextBase::setFont(fontfile); } /** * Turns off writing to the depth buffer when rendering text. This only affects text @@ -70,31 +67,6 @@ public: NONE }; - enum BackdropImplementation - { - /* No longer supported, naps to DELAYED_DEPTH_WRITES.*/ - POLYGON_OFFSET = 0, - - /* No longer supported, naps to DELAYED_DEPTH_WRITES.*/ - NO_DEPTH_BUFFER, - - /* No longer supported, naps to DELAYED_DEPTH_WRITES.*/ - DEPTH_RANGE, - - /* No longer supported, naps to DELAYED_DEPTH_WRITES.*/ - STENCIL_BUFFER, - - /* DELAYED_DEPTH_WRITES - * This mode renders all text with depth writes turned off, then - * again with depth writes on, but with the color buffer disabled. - * This should render text accurately for all graphics cards. The - * only downside is the additional pass to render to the depth - * buffer. But if you don't need the depth buffer updated for - * your, this extra pass can be disabled by calling - * enableDepthWrites(false).*/ - DELAYED_DEPTH_WRITES - }; - /** * BackdropType gives you a background shadow text behind your regular * text. This helps give text extra contrast which can be useful when @@ -149,18 +121,6 @@ public: const osg::Vec4& getBackdropColor() const { return _backdropColor; } - /** - * This specifies the underlying backdrop rendering implementation. - * Unfortunately, at this time, there is no "perfect" rendering solution - * so this function is provided to let you 'pick your poison'. Each - * implementation has trade-offs. See BackdropImplementation enum - * docs for details.*/ - void setBackdropImplementation(BackdropImplementation implementation); - - BackdropImplementation getBackdropImplementation() const { return _backdropImplementation; } - - - enum ColorGradientMode { SOLID = 0, // a.k.a. ColorGradients off @@ -222,9 +182,13 @@ public: virtual void accept(osg::PrimitiveFunctor& pf) const; + /** Get the coordinates of the character corners in local coordinates. Use Text::getMatrix() or Text::computeMatrix(..) to get the transform into model coordinates (see TextBase header.) */ + bool getCharacterCorners(unsigned int index, osg::Vec3& bottomLeft, osg::Vec3& bottomRight, osg::Vec3& topLeft, osg::Vec3& topRight) const; + /** Resize any per context GLObject buffers to specified size. */ virtual void resizeGLObjectBuffers(unsigned int maxSize); + /** If State is non-zero, this function releases OpenGL objects for * the specified graphics context. Otherwise, releases OpenGL objexts * for all graphics contexts. */ @@ -232,6 +196,20 @@ public: public: + /** deprecated, value ignored.*/ + enum BackdropImplementation + { + POLYGON_OFFSET = 0, + NO_DEPTH_BUFFER, + DEPTH_RANGE, + STENCIL_BUFFER, + DELAYED_DEPTH_WRITES + }; + + /** deprecated, value ignored.*/ + void setBackdropImplementation(BackdropImplementation) {} + /** deprecated, value should be ignored.*/ + BackdropImplementation getBackdropImplementation() const { return DELAYED_DEPTH_WRITES; } // internal structures, variable and methods used for rendering of characters. struct OSGTEXT_EXPORT GlyphQuads @@ -239,7 +217,7 @@ public: typedef std::vector Glyphs; Glyphs _glyphs; - Primitives _primitives; + osg::ref_ptr _primitives; GlyphQuads(); GlyphQuads(const GlyphQuads& gq); @@ -284,6 +262,8 @@ protected: virtual ~Text(); + virtual osg::StateSet* createStateSet(); + Font* getActiveFont(); const Font* getActiveFont() const; @@ -302,7 +282,6 @@ protected: virtual void computePositionsImplementation(); - void computeBackdropPositions(); void computeBackdropBoundingBox(); void computeBoundingBoxMargin(); @@ -314,10 +293,10 @@ protected: void drawImplementationSinglePass(osg::State& state, const osg::Vec4& colorMultiplier) const; + ShaderTechnique _shaderTechnique; bool _enableDepthWrites; BackdropType _backdropType; - BackdropImplementation _backdropImplementation; float _backdropHorizontalOffset; float _backdropVerticalOffset; diff --git a/include/osgText/TextBase b/include/osgText/TextBase index 64fe785f1..a674e3bd4 100644 --- a/include/osgText/TextBase +++ b/include/osgText/TextBase @@ -53,6 +53,9 @@ public: virtual void setFont(const std::string& fontfile); /** Get the font. Return 0 if default is being used.*/ + Font* getFont() { return _font.get(); } + + /** Get the const font. Return 0 if default is being used.*/ const Font* getFont() const { return _font.get(); } @@ -276,19 +279,23 @@ public: void getCoord(unsigned int i, osg::Vec2& c) const { c.set((*_coords)[i].x(), (*_coords)[i].y()); } void getCoord(unsigned int i, osg::Vec3& c) const { c = (*_coords)[i]; } - - /** Get the internal matrix used to provide positioning of text.*/ + /** Get the cached internal matrix used to provide positioning of text. The cached matrix is originally computed by computeMatrix(..). */ const osg::Matrix& getMatrix() const { return _matrix; } + /** compute the matrix that positions the text in model space for the given viewpoint.*/ + bool computeMatrix(osg::Matrix& matrix, osg::State* state=0) const; + protected: virtual ~TextBase(); + virtual osg::StateSet* createStateSet(); + + virtual void assignStateSet(); + void initArraysAndBuffers(); - osg::VertexArrayState* createVertexArrayState(osg::RenderInfo& renderInfo) const; - - bool computeMatrix(osg::Matrix& matrix, osg::State* state=0) const; + osg::VertexArrayState* createVertexArrayStateImplementation(osg::RenderInfo& renderInfo) const; void positionCursor(const osg::Vec2 & endOfLine_coords, osg::Vec2 & cursor, unsigned int linelength); String::iterator computeLastCharacterOnLine(osg::Vec2& cursor, String::iterator first,String::iterator last); diff --git a/include/osgUtil/GLObjectsVisitor b/include/osgUtil/GLObjectsVisitor index b9a130f3e..353bc3023 100644 --- a/include/osgUtil/GLObjectsVisitor +++ b/include/osgUtil/GLObjectsVisitor @@ -91,22 +91,33 @@ class OSGUTIL_EXPORT GLObjectsVisitor : public osg::NodeVisitor return _renderInfo; } + /** Set whether and how often OpenGL errors should be checked for, defaults to osg::State::ONCE_PER_ATTRIBUTE. */ + void setCheckForGLErrors(osg::State::CheckForGLErrors check) { _checkGLErrors = check; } + + /** Get whether and how often OpenGL errors should be checked for.*/ + osg::State::CheckForGLErrors getCheckForGLErrors() const { return _checkGLErrors; } + /** Simply traverse using standard NodeVisitor traverse method.*/ virtual void apply(osg::Node& node); void apply(osg::Drawable& drawable); void apply(osg::StateSet& stateset); + /** Do a compile traversal and then reset any state,*/ + void compile(osg::Node& node); + protected: typedef std::set DrawableAppliedSet; typedef std::set StatesSetAppliedSet; - Mode _mode; - osg::RenderInfo _renderInfo; - DrawableAppliedSet _drawablesAppliedSet; - StatesSetAppliedSet _stateSetAppliedSet; - osg::ref_ptr _lastCompiledProgram; + Mode _mode; + osg::RenderInfo _renderInfo; + osg::State::CheckForGLErrors _checkGLErrors; + + DrawableAppliedSet _drawablesAppliedSet; + StatesSetAppliedSet _stateSetAppliedSet; + osg::ref_ptr _lastCompiledProgram; }; diff --git a/include/osgUtil/RenderLeaf b/include/osgUtil/RenderLeaf index b1d36fb03..6e699602a 100644 --- a/include/osgUtil/RenderLeaf +++ b/include/osgUtil/RenderLeaf @@ -52,8 +52,8 @@ class OSGUTIL_EXPORT RenderLeaf : public osg::Referenced { _parent = 0; _drawable = drawable; - _projection = projection, - _modelview = modelview, + _projection = projection; + _modelview = modelview; _depth = depth; _dynamic = (drawable->getDataVariance()==osg::Object::DYNAMIC); _traversalNumber = traversalNumber; diff --git a/include/osgViewer/api/Win32/GraphicsHandleWin32 b/include/osgViewer/api/Win32/GraphicsHandleWin32 index f6ac8fa28..5959e6bf2 100644 --- a/include/osgViewer/api/Win32/GraphicsHandleWin32 +++ b/include/osgViewer/api/Win32/GraphicsHandleWin32 @@ -16,8 +16,17 @@ #include +// Fallback if not correctly detected in CMake macro #ifndef _WIN32_WINNT -#define _WIN32_WINNT 0x0500 +//#define _WIN32_WINNT 0x0A00 // Windows 10 +//#define _WIN32_WINNT 0x0603 // Windows 8.1 +//#define _WIN32_WINNT 0x0602 // Windows 8 +//#define _WIN32_WINNT 0x0601 // Windows 7 +//#define _WIN32_WINNT 0x0600 // Windows Server 2008 +//#define _WIN32_WINNT 0x0600 // Windows Vista +//#define _WIN32_WINNT 0x0502 // Windows Server 2003 with SP1, Windows XP with SP2 +//#define _WIN32_WINNT 0x0501 // Windows Server 2003, Windows XP +#define _WIN32_WINNT 0x0500 // Windows NT #endif #include diff --git a/include/osgViewer/api/X11/GraphicsWindowX11 b/include/osgViewer/api/X11/GraphicsWindowX11 index 1efb990fe..0af24fdb1 100644 --- a/include/osgViewer/api/X11/GraphicsWindowX11 +++ b/include/osgViewer/api/X11/GraphicsWindowX11 @@ -37,10 +37,11 @@ class OSGVIEWER_EXPORT GraphicsWindowX11 : public osgViewer::GraphicsWindow, pub _parent(0), _window(0), _visualInfo(0), - _fbConfig(0), #ifdef OSG_USE_EGL _eglDisplay(0), _eglSurface(0), + #else + _fbConfig(0), #endif _currentCursor(0), _initialized(false), @@ -54,7 +55,7 @@ class OSGVIEWER_EXPORT GraphicsWindowX11 : public osgViewer::GraphicsWindow, pub memset(_keyMap, 0, 32); init(); - + if (valid()) { setState( new osg::State ); @@ -72,7 +73,7 @@ class OSGVIEWER_EXPORT GraphicsWindowX11 : public osgViewer::GraphicsWindow, pub } } - + virtual bool isSameKindAs(const Object* object) const { return dynamic_cast(object)!=0; } virtual const char* libraryName() const { return "osgViewer"; } virtual const char* className() const { return "GraphicsWindowX11"; } @@ -129,35 +130,35 @@ class OSGVIEWER_EXPORT GraphicsWindowX11 : public osgViewer::GraphicsWindow, pub { WindowData(Window window): _window(window) {} - + Window _window; }; public: - + // X11 specific access functions Display* getEventDisplay() const { return _eventDisplay; } Display* getDisplayToUse() const ; - + Window& getParent() { return _parent; } Window& getWindow() { return _window; } Cursor getCurrentCursor() { return _currentCursor; } protected: - + ~GraphicsWindowX11(); - + Cursor getOrCreateCursor(MouseCursor mouseShape); - + bool createVisualInfo(); bool createWindow(); bool setWindow(Window window); - + void init(); bool checkAndSendEventFullScreenIfNeeded(Display* display, int x, int y, int width, int height, bool windowDecoration); @@ -171,23 +172,24 @@ class OSGVIEWER_EXPORT GraphicsWindowX11 : public osgViewer::GraphicsWindow, pub int getModifierMask() const; void syncLocks(); void flushKeyEvents(); - + bool _valid; Display* _eventDisplay; Window _parent; Window _window; XVisualInfo* _visualInfo; - GLXFBConfig _fbConfig; #ifdef OSG_USE_EGL EGLDisplay _eglDisplay; EGLSurface _eglSurface; + #else + GLXFBConfig _fbConfig; #endif Cursor _currentCursor; Atom _deleteWindow; - + bool _initialized; bool _realized; bool _ownsWindow; diff --git a/src/osg/ApplicationUsage.cpp b/src/osg/ApplicationUsage.cpp index ad2404089..26e4510ec 100644 --- a/src/osg/ApplicationUsage.cpp +++ b/src/osg/ApplicationUsage.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -317,10 +318,16 @@ void ApplicationUsage::writeEnvironmentSettings(std::ostream& output) std::string::size_type len = citr->first.find_first_of("\n\r\t "); if (len == std::string::npos) len = citr->first.size(); line.replace(optionPos,len,citr->first.substr(0,len)); - const char *cp = getenv(citr->first.substr(0, len).c_str()); - if (!cp) cp = "[not set]"; - else if (!*cp) cp = "[set]"; - line += std::string(cp) + "\n"; + + std::string value; + if (getEnvVar(citr->first.substr(0, len).c_str(), value)) + { + line += "[set]\n"; + } + else + { + line += "[not set]\n"; + } output << line; } diff --git a/src/osg/CMakeLists.txt b/src/osg/CMakeLists.txt index 845306551..5fc119403 100644 --- a/src/osg/CMakeLists.txt +++ b/src/osg/CMakeLists.txt @@ -55,6 +55,7 @@ SET(TARGET_H ${HEADER_PATH}/ColorMaski ${HEADER_PATH}/ColorMatrix ${HEADER_PATH}/ComputeBoundsVisitor + ${HEADER_PATH}/ComputeDispatch ${HEADER_PATH}/ContextData ${HEADER_PATH}/ConvexPlanarOccluder ${HEADER_PATH}/ConvexPlanarPolygon @@ -267,6 +268,7 @@ SET(TARGET_SRC ColorMaski.cpp ColorMatrix.cpp ComputeBoundsVisitor.cpp + ComputeDispatch.cpp ContextData.cpp ConvexPlanarOccluder.cpp ConvexPlanarPolygon.cpp diff --git a/src/osg/ComputeDispatch.cpp b/src/osg/ComputeDispatch.cpp new file mode 100644 index 000000000..c689bd95b --- /dev/null +++ b/src/osg/ComputeDispatch.cpp @@ -0,0 +1,16 @@ +#include + +using namespace osg; + +ComputeDispatch::ComputeDispatch(const ComputeDispatch&o,const osg::CopyOp& copyop): + Drawable(o,copyop), + _numGroupsX(o._numGroupsX), + _numGroupsY(o._numGroupsY), + _numGroupsZ(o._numGroupsZ) +{ +} + +void ComputeDispatch::drawImplementation(RenderInfo& renderInfo) const +{ + renderInfo.getState()->get()->glDispatchCompute(_numGroupsX, _numGroupsY, _numGroupsZ); +} diff --git a/src/osg/Config.in b/src/osg/Config.in index 3d52f9ca3..8f4c23359 100644 --- a/src/osg/Config.in +++ b/src/osg/Config.in @@ -34,5 +34,6 @@ #cmakedefine OSG_DISABLE_MSVC_WARNINGS #cmakedefine OSG_PROVIDE_READFILE #cmakedefine OSG_USE_DEPRECATED_API +#cmakedefine OSG_ENVVAR_SUPPORTED #endif diff --git a/src/osg/CullSettings.cpp b/src/osg/CullSettings.cpp index 370191787..78122bbb5 100644 --- a/src/osg/CullSettings.cpp +++ b/src/osg/CullSettings.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include @@ -97,25 +98,21 @@ void CullSettings::readEnvironmentalVariables() { OSG_INFO<<"CullSettings::readEnvironmentalVariables()"< #include #include +#include #include #include @@ -118,7 +119,8 @@ void DisplaySettings::setDisplaySettings(const DisplaySettings& vs) _swapMethod = vs._swapMethod; _vertexBufferHint = vs._vertexBufferHint; - _shaderHint = vs._shaderHint; + + setShaderHint(_shaderHint); _keystoneHint = vs._keystoneHint; _keystoneFileNames = vs._keystoneFileNames; @@ -250,23 +252,17 @@ void DisplaySettings::setDefaults() // _vertexBufferHint = VERTEX_ARRAY_OBJECT; #if defined(OSG_GLES3_AVAILABLE) - _shaderHint = SHADER_GLES3; - OSG_INFO<<"DisplaySettings::SHADER_GLES3"<", "Set the hint to what backend osg::Geometry implementation to use. NO_PREFERENCE | VERTEX_BUFFER_OBJECT | VERTEX_ARRAY_OBJECT"); +static ApplicationUsageProxy DisplaySetting_e33(ApplicationUsage::ENVIRONMENTAL_VARIABLE, + "OSG_TEXT_SHADER_TECHNIQUE ", + "Set the defafult osgText::ShaderTechnique. ALL_FEATURES | ALL | GREYSCALE | SIGNED_DISTANCE_FIELD | SDF | NO_TEXT_SHADER | NONE"); void DisplaySettings::readEnvironmentalVariables() { - const char* ptr = 0; - - if ((ptr = getenv("OSG_DISPLAY_TYPE")) != 0) + std::string value; + if (getEnvVar("OSG_DISPLAY_TYPE", value)) { - if (strcmp(ptr,"MONITOR")==0) + if (value=="MONITOR") { _displayType = MONITOR; } else - if (strcmp(ptr,"POWERWALL")==0) + if (value=="POWERWALL") { _displayType = POWERWALL; } else - if (strcmp(ptr,"REALITY_CENTER")==0) + if (value=="REALITY_CENTER") { _displayType = REALITY_CENTER; } else - if (strcmp(ptr,"HEAD_MOUNTED_DISPLAY")==0) + if (value=="HEAD_MOUNTED_DISPLAY") { _displayType = HEAD_MOUNTED_DISPLAY; } } - if( (ptr = getenv("OSG_STEREO_MODE")) != 0) + if (getEnvVar("OSG_STEREO_MODE", value)) { - if (strcmp(ptr,"QUAD_BUFFER")==0) + if (value=="QUAD_BUFFER") { _stereoMode = QUAD_BUFFER; } - else if (strcmp(ptr,"ANAGLYPHIC")==0) + else if (value=="ANAGLYPHIC") { _stereoMode = ANAGLYPHIC; } - else if (strcmp(ptr,"HORIZONTAL_SPLIT")==0) + else if (value=="HORIZONTAL_SPLIT") { _stereoMode = HORIZONTAL_SPLIT; } - else if (strcmp(ptr,"VERTICAL_SPLIT")==0) + else if (value=="VERTICAL_SPLIT") { _stereoMode = VERTICAL_SPLIT; } - else if (strcmp(ptr,"LEFT_EYE")==0) + else if (value=="LEFT_EYE") { _stereoMode = LEFT_EYE; } - else if (strcmp(ptr,"RIGHT_EYE")==0) + else if (value=="RIGHT_EYE") { _stereoMode = RIGHT_EYE; } - else if (strcmp(ptr,"HORIZONTAL_INTERLACE")==0) + else if (value=="HORIZONTAL_INTERLACE") { _stereoMode = HORIZONTAL_INTERLACE; } - else if (strcmp(ptr,"VERTICAL_INTERLACE")==0) + else if (value=="VERTICAL_INTERLACE") { _stereoMode = VERTICAL_INTERLACE; } - else if (strcmp(ptr,"CHECKERBOARD")==0) + else if (value=="CHECKERBOARD") { _stereoMode = CHECKERBOARD; } } - if( (ptr = getenv("OSG_STEREO")) != 0) + if (getEnvVar("OSG_STEREO", value)) { - if (strcmp(ptr,"OFF")==0) + if (value=="OFF") { _stereo = false; } else - if (strcmp(ptr,"ON")==0) + if (value=="ON") { _stereo = true; } } - if( (ptr = getenv("OSG_EYE_SEPARATION")) != 0) - { - _eyeSeparation = osg::asciiToFloat(ptr); - } + getEnvVar("OSG_EYE_SEPARATION", _eyeSeparation); + getEnvVar("OSG_SCREEN_WIDTH", _screenWidth); + getEnvVar("OSG_SCREEN_HEIGHT", _screenHeight); + getEnvVar("OSG_SCREEN_DISTANCE", _screenDistance); - if( (ptr = getenv("OSG_SCREEN_WIDTH")) != 0) + if (getEnvVar("OSG_SPLIT_STEREO_HORIZONTAL_EYE_MAPPING", value)) { - _screenWidth = osg::asciiToFloat(ptr); - } - - if( (ptr = getenv("OSG_SCREEN_HEIGHT")) != 0) - { - _screenHeight = osg::asciiToFloat(ptr); - } - - if( (ptr = getenv("OSG_SCREEN_DISTANCE")) != 0) - { - _screenDistance = osg::asciiToFloat(ptr); - } - - if( (ptr = getenv("OSG_SPLIT_STEREO_HORIZONTAL_EYE_MAPPING")) != 0) - { - if (strcmp(ptr,"LEFT_EYE_LEFT_VIEWPORT")==0) + if (value=="LEFT_EYE_LEFT_VIEWPORT") { _splitStereoHorizontalEyeMapping = LEFT_EYE_LEFT_VIEWPORT; } else - if (strcmp(ptr,"LEFT_EYE_RIGHT_VIEWPORT")==0) + if (value=="LEFT_EYE_RIGHT_VIEWPORT") { _splitStereoHorizontalEyeMapping = LEFT_EYE_RIGHT_VIEWPORT; } } - if( (ptr = getenv("OSG_SPLIT_STEREO_HORIZONTAL_SEPARATION")) != 0) - { - _splitStereoHorizontalSeparation = atoi(ptr); - } + getEnvVar("OSG_SPLIT_STEREO_HORIZONTAL_SEPARATION", _splitStereoHorizontalSeparation); - if( (ptr = getenv("OSG_SPLIT_STEREO_VERTICAL_EYE_MAPPING")) != 0) + if (getEnvVar("OSG_SPLIT_STEREO_VERTICAL_EYE_MAPPING", value)) { - if (strcmp(ptr,"LEFT_EYE_TOP_VIEWPORT")==0) + if (value=="LEFT_EYE_TOP_VIEWPORT") { _splitStereoVerticalEyeMapping = LEFT_EYE_TOP_VIEWPORT; } else - if (strcmp(ptr,"LEFT_EYE_BOTTOM_VIEWPORT")==0) + if (value=="LEFT_EYE_BOTTOM_VIEWPORT") { _splitStereoVerticalEyeMapping = LEFT_EYE_BOTTOM_VIEWPORT; } } - if( (ptr = getenv("OSG_SPLIT_STEREO_AUTO_ADJUST_ASPECT_RATIO")) != 0) + if (getEnvVar("OSG_SPLIT_STEREO_AUTO_ADJUST_ASPECT_RATIO", value)) { - if (strcmp(ptr,"OFF")==0) + if (value=="OFF") { _splitStereoAutoAdjustAspectRatio = false; } else - if (strcmp(ptr,"ON")==0) + if (value=="ON") { _splitStereoAutoAdjustAspectRatio = true; } } - if( (ptr = getenv("OSG_SPLIT_STEREO_VERTICAL_SEPARATION")) != 0) - { - _splitStereoVerticalSeparation = atoi(ptr); - } + getEnvVar("OSG_SPLIT_STEREO_VERTICAL_SEPARATION", _splitStereoVerticalSeparation); - if( (ptr = getenv("OSG_MAX_NUMBER_OF_GRAPHICS_CONTEXTS")) != 0) - { - _maxNumOfGraphicsContexts = atoi(ptr); - } + getEnvVar("OSG_MAX_NUMBER_OF_GRAPHICS_CONTEXTS", _maxNumOfGraphicsContexts); - if( (ptr = getenv("OSG_COMPILE_CONTEXTS")) != 0) + if (getEnvVar("OSG_COMPILE_CONTEXTS", value)) { - if (strcmp(ptr,"OFF")==0) + if (value=="OFF") { _compileContextsHint = false; } else - if (strcmp(ptr,"ON")==0) + if (value=="ON") { _compileContextsHint = true; } } - if( (ptr = getenv("OSG_SERIALIZE_DRAW_DISPATCH")) != 0) + if (getEnvVar("OSG_SERIALIZE_DRAW_DISPATCH", value)) { - if (strcmp(ptr,"OFF")==0) + if (value=="OFF") { _serializeDrawDispatch = false; } else - if (strcmp(ptr,"ON")==0) + if (value=="ON") { _serializeDrawDispatch = true; } } - if( (ptr = getenv("OSG_USE_SCENEVIEW_FOR_STEREO")) != 0) + if (getEnvVar("OSG_USE_SCENEVIEW_FOR_STEREO", value)) { - if (strcmp(ptr,"OFF")==0) + if (value=="OFF") { _useSceneViewForStereoHint = false; } else - if (strcmp(ptr,"ON")==0) + if (value=="ON") { _useSceneViewForStereoHint = true; } } - if( (ptr = getenv("OSG_NUM_DATABASE_THREADS")) != 0) - { - _numDatabaseThreadsHint = atoi(ptr); - } + getEnvVar("OSG_NUM_DATABASE_THREADS", _numDatabaseThreadsHint); - if( (ptr = getenv("OSG_NUM_HTTP_DATABASE_THREADS")) != 0) - { - _numHttpDatabaseThreadsHint = atoi(ptr); - } + getEnvVar("OSG_NUM_HTTP_DATABASE_THREADS", _numHttpDatabaseThreadsHint); - if( (ptr = getenv("OSG_MULTI_SAMPLES")) != 0) - { - _numMultiSamples = atoi(ptr); - } + getEnvVar("OSG_MULTI_SAMPLES", _numMultiSamples); - if( (ptr = getenv("OSG_TEXTURE_POOL_SIZE")) != 0) - { - _maxTexturePoolSize = atoi(ptr); - } + getEnvVar("OSG_TEXTURE_POOL_SIZE", _maxTexturePoolSize); - if( (ptr = getenv("OSG_BUFFER_OBJECT_POOL_SIZE")) != 0) - { - _maxBufferObjectPoolSize = atoi(ptr); - } + getEnvVar("OSG_BUFFER_OBJECT_POOL_SIZE", _maxBufferObjectPoolSize); { // Read implicit buffer attachments combinations for both render and resolve mask @@ -624,143 +583,141 @@ void DisplaySettings::readEnvironmentalVariables() for( unsigned int n = 0; n < sizeof( variable ) / sizeof( variable[0] ); n++ ) { - const char* env = getenv( variable[n] ); - if ( !env ) continue; - std::string str(env); + std::string str; + if (getEnvVar(variable[n], str)) + { + if(str.find("OFF")!=std::string::npos) *mask[n] = 0; - if(str.find("OFF")!=std::string::npos) *mask[n] = 0; + if(str.find("~DEFAULT")!=std::string::npos) *mask[n] ^= DEFAULT_IMPLICIT_BUFFER_ATTACHMENT; + else if(str.find("DEFAULT")!=std::string::npos) *mask[n] |= DEFAULT_IMPLICIT_BUFFER_ATTACHMENT; - if(str.find("~DEFAULT")!=std::string::npos) *mask[n] ^= DEFAULT_IMPLICIT_BUFFER_ATTACHMENT; - else if(str.find("DEFAULT")!=std::string::npos) *mask[n] |= DEFAULT_IMPLICIT_BUFFER_ATTACHMENT; + if(str.find("~COLOR")!=std::string::npos) *mask[n] ^= IMPLICIT_COLOR_BUFFER_ATTACHMENT; + else if(str.find("COLOR")!=std::string::npos) *mask[n] |= IMPLICIT_COLOR_BUFFER_ATTACHMENT; - if(str.find("~COLOR")!=std::string::npos) *mask[n] ^= IMPLICIT_COLOR_BUFFER_ATTACHMENT; - else if(str.find("COLOR")!=std::string::npos) *mask[n] |= IMPLICIT_COLOR_BUFFER_ATTACHMENT; + if(str.find("~DEPTH")!=std::string::npos) *mask[n] ^= IMPLICIT_DEPTH_BUFFER_ATTACHMENT; + else if(str.find("DEPTH")!=std::string::npos) *mask[n] |= (int)IMPLICIT_DEPTH_BUFFER_ATTACHMENT; - if(str.find("~DEPTH")!=std::string::npos) *mask[n] ^= IMPLICIT_DEPTH_BUFFER_ATTACHMENT; - else if(str.find("DEPTH")!=std::string::npos) *mask[n] |= (int)IMPLICIT_DEPTH_BUFFER_ATTACHMENT; - - if(str.find("~STENCIL")!=std::string::npos) *mask[n] ^= (int)IMPLICIT_STENCIL_BUFFER_ATTACHMENT; - else if(str.find("STENCIL")!=std::string::npos) *mask[n] |= (int)IMPLICIT_STENCIL_BUFFER_ATTACHMENT; + if(str.find("~STENCIL")!=std::string::npos) *mask[n] ^= (int)IMPLICIT_STENCIL_BUFFER_ATTACHMENT; + else if(str.find("STENCIL")!=std::string::npos) *mask[n] |= (int)IMPLICIT_STENCIL_BUFFER_ATTACHMENT; + } } } - if( (ptr = getenv("OSG_GL_VERSION")) != 0 || (ptr = getenv("OSG_GL_CONTEXT_VERSION")) != 0) + if (getEnvVar("OSG_GL_VERSION", value) || getEnvVar("OSG_GL_CONTEXT_VERSION", value)) { - _glContextVersion = ptr; + _glContextVersion = value; } - if( (ptr = getenv("OSG_GL_CONTEXT_FLAGS")) != 0) - { - _glContextFlags = atoi(ptr); - } + getEnvVar("OSG_GL_CONTEXT_FLAGS", _glContextFlags); - if( (ptr = getenv("OSG_GL_CONTEXT_PROFILE_MASK")) != 0) - { - _glContextProfileMask = atoi(ptr); - } + getEnvVar("OSG_GL_CONTEXT_PROFILE_MASK", _glContextProfileMask); - if ((ptr = getenv("OSG_SWAP_METHOD")) != 0) + if (getEnvVar("OSG_SWAP_METHOD", value)) { - if (strcmp(ptr,"DEFAULT")==0) + if (value=="DEFAULT") { _swapMethod = SWAP_DEFAULT; } else - if (strcmp(ptr,"EXCHANGE")==0) + if (value=="EXCHANGE") { _swapMethod = SWAP_EXCHANGE; } else - if (strcmp(ptr,"COPY")==0) + if (value=="COPY") { _swapMethod = SWAP_COPY; } else - if (strcmp(ptr,"UNDEFINED")==0) + if (value=="UNDEFINED") { _swapMethod = SWAP_UNDEFINED; } } - if ((ptr = getenv("OSG_SYNC_SWAP_BUFFERS")) != 0) + if (getEnvVar("OSG_SYNC_SWAP_BUFFERS", value)) { - if (strcmp(ptr,"OFF")==0) + if (value=="OFF") { _syncSwapBuffers = 0; } else - if (strcmp(ptr,"ON")==0) + if (value=="ON") { _syncSwapBuffers = 1; } else { - _syncSwapBuffers = atoi(ptr); + _syncSwapBuffers = atoi(value.c_str()); } } - if ((ptr = getenv("OSG_VERTEX_BUFFER_HINT")) != 0) + if (getEnvVar("OSG_VERTEX_BUFFER_HINT", value)) { - if (strcmp(ptr,"VERTEX_BUFFER_OBJECT")==0 || strcmp(ptr,"VBO")==0) + if (value=="VERTEX_BUFFER_OBJECT" || value=="VBO") { - OSG_NOTICE<<"OSG_VERTEX_BUFFER_HINT set to VERTEX_BUFFER_OBJECT"< lock(_valueMapMutex); + + _valueMap[name] = value; +} + +bool DisplaySettings::getValue(const std::string& name, std::string& value, bool use_env_fallback) const +{ + OpenThreads::ScopedLock lock(_valueMapMutex); + + ValueMap::iterator itr = _valueMap.find(name); + if (itr!=_valueMap.end()) + { + value = itr->second; + OSG_INFO<<"DisplaySettings::getValue("<assignAllDispatchers(); return vos; diff --git a/src/osg/GLExtensions.cpp b/src/osg/GLExtensions.cpp index ac57e8b2f..507f42e5b 100644 --- a/src/osg/GLExtensions.cpp +++ b/src/osg/GLExtensions.cpp @@ -15,6 +15,8 @@ #include #include #include +#include +#include #include #include @@ -65,6 +67,9 @@ static osg::buffered_object s_gluExtensionSetList; static osg::buffered_object s_gluRendererList; static osg::buffered_value s_gluInitializedList; +static ApplicationUsageProxy GLEXtension_e0(ApplicationUsage::ENVIRONMENTAL_VARIABLE, "OSG_GL_EXTENSION_DISABLE ", "Use space deliminarted list of GL extensions to disable associated GL extensions"); +static ApplicationUsageProxy GLEXtension_e1(ApplicationUsage::ENVIRONMENTAL_VARIABLE, "OSG_MAX_TEXTURE_SIZE ", "Clamp the maximum GL texture size to specified value."); + float osg::getGLVersionNumber() { // needs to be extended to do proper things with subversions like 1.5.1, etc. @@ -308,8 +313,7 @@ void osg::setGLExtensionDisableString(const std::string& disableString) std::string& osg::getGLExtensionDisableString() { - static const char* envVar = getenv("OSG_GL_EXTENSION_DISABLE"); - static std::string s_GLExtensionDisableString(envVar?envVar:"Nothing defined"); + static std::string s_GLExtensionDisableString(getEnvVar("OSG_GL_EXTENSION_DISABLE")); return s_GLExtensionDisableString; } @@ -464,13 +468,13 @@ GLExtensions::GLExtensions(unsigned int in_contextID): isVertexShaderSupported = validContext && (shadersBuiltIn || osg::isGLExtensionSupported(contextID,"GL_ARB_vertex_shader")); isFragmentShaderSupported = validContext && (shadersBuiltIn || osg::isGLExtensionSupported(contextID,"GL_ARB_fragment_shader")); isLanguage100Supported = validContext && (shadersBuiltIn || osg::isGLExtensionSupported(contextID,"GL_ARB_shading_language_100")); - isGeometryShader4Supported = validContext && (osg::isGLExtensionSupported(contextID,"GL_EXT_geometry_shader4") || osg::isGLExtensionSupported(contextID,"GL_OES_geometry_shader")); - isGpuShader4Supported = validContext && osg::isGLExtensionSupported(contextID,"GL_EXT_gpu_shader4"); - areTessellationShadersSupported = validContext && (osg::isGLExtensionSupported(contextID, "GL_ARB_tessellation_shader") || osg::isGLExtensionSupported(contextID,"GL_OES_tessellation_shader")); - isUniformBufferObjectSupported = validContext && osg::isGLExtensionSupported(contextID,"GL_ARB_uniform_buffer_object"); - isGetProgramBinarySupported = validContext && osg::isGLExtensionSupported(contextID,"GL_ARB_get_program_binary"); - isGpuShaderFp64Supported = validContext && osg::isGLExtensionSupported(contextID,"GL_ARB_gpu_shader_fp64"); - isShaderAtomicCountersSupported = validContext && osg::isGLExtensionSupported(contextID,"GL_ARB_shader_atomic_counters"); + isGeometryShader4Supported = validContext && (osg::isGLExtensionSupported(contextID,"GL_EXT_geometry_shader4") || osg::isGLExtensionSupported(contextID,"GL_OES_geometry_shader") || osg::isGLExtensionOrVersionSupported(contextID,"GL_ARB_geometry_shader4", 3.2f)); + isGpuShader4Supported = validContext && osg::isGLExtensionOrVersionSupported(contextID,"GL_EXT_gpu_shader4", 3.0f); + areTessellationShadersSupported = validContext && (osg::isGLExtensionOrVersionSupported(contextID, "GL_ARB_tessellation_shader", 4.0f) || osg::isGLExtensionSupported(contextID,"GL_OES_tessellation_shader")); + isUniformBufferObjectSupported = validContext && osg::isGLExtensionOrVersionSupported(contextID,"GL_ARB_uniform_buffer_object", 3.1f); + isGetProgramBinarySupported = validContext && osg::isGLExtensionOrVersionSupported(contextID,"GL_ARB_get_program_binary", 4.1f); + isGpuShaderFp64Supported = validContext && osg::isGLExtensionOrVersionSupported(contextID,"GL_ARB_gpu_shader_fp64", 4.0f); + isShaderAtomicCountersSupported = validContext && osg::isGLExtensionOrVersionSupported(contextID,"GL_ARB_shader_atomic_counters", 4.2f); isRectangleSupported = validContext && (OSG_GL3_FEATURES || @@ -900,16 +904,10 @@ GLExtensions::GLExtensions(unsigned int in_contextID): maxTextureSize=0; if (validContext) glGetIntegerv(GL_MAX_TEXTURE_SIZE,&maxTextureSize); - char *ptr; - if( (ptr = getenv("OSG_MAX_TEXTURE_SIZE")) != 0) + GLint osg_max_size = maxTextureSize; + if( (getEnvVar("OSG_MAX_TEXTURE_SIZE", osg_max_size)) && osg_max_size= 1.2f); isTextureStorageEnabled = validContext && ((glVersion >= 4.2f) || isGLExtensionSupported(contextID, "GL_ARB_texture_storage")); - if ( (ptr = getenv("OSG_GL_TEXTURE_STORAGE")) != 0 && isTextureStorageEnabled) - { - if (strcmp(ptr,"OFF")==0 || strcmp(ptr,"DISABLE")==0 ) isTextureStorageEnabled = false; - else isTextureStorageEnabled = true; - } + if (isTextureStorageEnabled) + { + std::string value; + if (getEnvVar("OSG_GL_TEXTURE_STORAGE", value)) + { + if (value=="OFF" || value=="DISABLE") isTextureStorageEnabled = false; + else isTextureStorageEnabled = true; + } + } // Texture3D extensions isTexture3DFast = validContext && (OSG_GL3_FEATURES || isGLExtensionSupported(contextID,"GL_EXT_texture3D")); @@ -946,6 +948,10 @@ GLExtensions::GLExtensions(unsigned int in_contextID): setGLExtensionFuncPtr(glTexSubImage3D, "glTexSubImage3D","glTexSubImage3DEXT", validContext); setGLExtensionFuncPtr(glCompressedTexImage3D, "glCompressedTexImage3D","glCompressedTexImage3DARB", validContext); setGLExtensionFuncPtr(glCompressedTexSubImage3D, "glCompressedTexSubImage3D","glCompressedTexSubImage3DARB", validContext); + + setGLExtensionFuncPtr(glTexImage3DMultisample, "glTexImage3DMultisample", validContext); + setGLExtensionFuncPtr(glGetMultisamplefv, "glGetMultisamplefv", validContext); + setGLExtensionFuncPtr(glCopyTexSubImage3D, "glCopyTexSubImage3D","glCopyTexSubImage3DEXT", validContext); setGLExtensionFuncPtr(glBeginConditionalRender, "glBeginConditionalRender", "glBeginConditionalRenderARB"); setGLExtensionFuncPtr(glEndConditionalRender, "glEndConditionalRender", "glEndConditionalRenderARB"); diff --git a/src/osg/Geometry.cpp b/src/osg/Geometry.cpp index aff29211b..068a9f7c0 100644 --- a/src/osg/Geometry.cpp +++ b/src/osg/Geometry.cpp @@ -570,16 +570,11 @@ void Geometry::setUseVertexBufferObjects(bool flag) DrawElementsList drawElementsList; getDrawElementsList(drawElementsList); - typedef std::vector VertexBufferObjectList; - typedef std::vector ElementBufferObjectList; - /*if (_useVertexBufferObjects)*/ { if (!arrayList.empty()) { - VertexBufferObjectList vboList; - osg::ref_ptr vbo; ArrayList::iterator vitr; @@ -604,8 +599,6 @@ void Geometry::setUseVertexBufferObjects(bool flag) if (!drawElementsList.empty()) { - ElementBufferObjectList eboList; - osg::ref_ptr ebo; DrawElementsList::iterator deitr; @@ -720,7 +713,7 @@ void Geometry::releaseGLObjects(State* state) const } -VertexArrayState* Geometry::createVertexArrayState(RenderInfo& renderInfo) const +VertexArrayState* Geometry::createVertexArrayStateImplementation(RenderInfo& renderInfo) const { State& state = *renderInfo.getState(); diff --git a/src/osg/GraphicsContext.cpp b/src/osg/GraphicsContext.cpp index b8fce4436..d02b30ce5 100644 --- a/src/osg/GraphicsContext.cpp +++ b/src/osg/GraphicsContext.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -153,10 +154,10 @@ std::string GraphicsContext::ScreenIdentifier::displayName() const void GraphicsContext::ScreenIdentifier::readDISPLAY() { - const char* ptr = 0; - if ((ptr=getenv("DISPLAY")) != 0) + std::string str; + if (getEnvVar("DISPLAY", str)) { - setScreenIdentifier(ptr); + setScreenIdentifier(str); } } diff --git a/src/osg/Image.cpp b/src/osg/Image.cpp index 1149acdc4..2c36d5af8 100644 --- a/src/osg/Image.cpp +++ b/src/osg/Image.cpp @@ -241,11 +241,17 @@ Image::Image(const Image& image,const CopyOp& copyop): { unsigned int size = image.getTotalSizeInBytesIncludingMipmaps(); setData(new unsigned char [size],USE_NEW_DELETE); - unsigned char* dest_ptr = _data; - for(DataIterator itr(&image); itr.valid(); ++itr) + if (unsigned char* dest_ptr = _data) { - memcpy(dest_ptr, itr.data(), itr.size()); - dest_ptr += itr.size(); + for(DataIterator itr(&image); itr.valid(); ++itr) + { + memcpy(dest_ptr, itr.data(), itr.size()); + dest_ptr += itr.size(); + } + } + else + { + OSG_WARN<<"Warning: Image::Image(const Image&, const CopyOp&) out of memory, no image copy made."<= GL_COMPRESSED_RGB_S3TC_DXT1_EXT && - pixelFormat <= GL_COMPRESSED_RGBA_S3TC_DXT5_EXT ) - { - width = (width + 3) & ~3; - height = (height + 3) & ~3; - } - - // 3dc ATI formats - // GL_COMPRESSED_RED_RGTC1_EXT 0x8DBB - // GL_COMPRESSED_SIGNED_RED_RGTC1_EXT 0x8DBC - // GL_COMPRESSED_RED_GREEN_RGTC2_EXT 0x8DBD - // GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT 0x8DBE - if( pixelFormat >= GL_COMPRESSED_RED_RGTC1_EXT && - pixelFormat <= GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT ) - { - width = (width + 3) & ~3; - height = (height + 3) & ~3; + int blockSize = computeBlockSize(pixelFormat, 0); + if (blockSize > 0) { + osg::Vec3i footprint = computeBlockFootprint(pixelFormat); + width = (width + footprint.x() - 1) / footprint.x(); + height = (height + footprint.y() - 1) / footprint.y(); + unsigned int size = blockSize * width; + size = roudUpToMultiple(size, packing); + size *= height; + size = roudUpToMultiple(size, slice_packing); + size *= depth; + size = roudUpToMultiple(size, image_packing); + return size; } // compute size of one row @@ -821,6 +984,13 @@ unsigned int Image::computeImageSizeInBytes(int width,int height, int depth, GLe return osg::maximum( size, computeBlockSize(pixelFormat, packing) ); } +int Image::roudUpToMultiple(int s, int pack) { + if (pack < 2) return s; + s += pack - 1; + s -= s % pack; + return s; +} + int Image::computeNearestPowerOfTwo(int s,float bias) { if ((s & (s-1))!=0) @@ -880,6 +1050,34 @@ bool Image::isCompressed() const case(GL_COMPRESSED_SIGNED_R11_EAC): case(GL_COMPRESSED_RG11_EAC): case(GL_COMPRESSED_SIGNED_RG11_EAC): + case (GL_COMPRESSED_RGBA_ASTC_4x4_KHR) : + case (GL_COMPRESSED_RGBA_ASTC_5x4_KHR) : + case (GL_COMPRESSED_RGBA_ASTC_5x5_KHR) : + case (GL_COMPRESSED_RGBA_ASTC_6x5_KHR) : + case (GL_COMPRESSED_RGBA_ASTC_6x6_KHR) : + case (GL_COMPRESSED_RGBA_ASTC_8x5_KHR) : + case (GL_COMPRESSED_RGBA_ASTC_8x6_KHR) : + case (GL_COMPRESSED_RGBA_ASTC_8x8_KHR) : + case (GL_COMPRESSED_RGBA_ASTC_10x5_KHR) : + case (GL_COMPRESSED_RGBA_ASTC_10x6_KHR) : + case (GL_COMPRESSED_RGBA_ASTC_10x8_KHR) : + case (GL_COMPRESSED_RGBA_ASTC_10x10_KHR) : + case (GL_COMPRESSED_RGBA_ASTC_12x10_KHR) : + case (GL_COMPRESSED_RGBA_ASTC_12x12_KHR) : + case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR) : + case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR) : + case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR) : + case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR) : + case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR) : + case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR) : + case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR) : + case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR) : + case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR) : + case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR) : + case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR) : + case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR) : + case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR) : + case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR) : return true; default: return false; @@ -1189,7 +1387,7 @@ void Image::readImageFromCurrentTexture(unsigned int contextID, bool copyMipMaps unsigned char* data = new unsigned char[total_size]; if (!data) { - OSG_WARN<<"Warning: Image::readImageFromCurrentTexture(..) out of memory, now image read."<s() & 0x3) || (source->t() & 0x3) || (s_offset & 0x3) || (t_offset & 0x3)) + { + OSG_WARN << "Error Image::copySubImage() did not succeed : size " << source->s() << "x" << source->t() << " or offset " << s_offset<< "," << t_offset << " not multiple of 4." << std::endl; + return; + } + } else { + if ((source->s() % footprint.x()) || (source->t() % footprint.y()) || (s_offset % footprint.x()) || (t_offset% footprint.y())) + { + OSG_WARN << "Error Image::copySubImage() did not succeed : size " << source->s() << "x" << source->t() << " or offset " << s_offset << "," << t_offset << " not multiple of footprint " << footprint.x() << "x" << footprint.y() << std::endl; + return; + } + } + unsigned int rowWidthInBlocks = (_s + footprint.x() - 1) / footprint.x(); + unsigned int blockSize = computeBlockSize(_pixelFormat, 0); + data_destination = _data + blockSize * (rowWidthInBlocks * t_offset + (s_offset / footprint.x())); + unsigned int copy_width = (osg::minimum(source->s(), _s - s_offset) + footprint.x() - 1) / footprint.x(); + unsigned int copy_height = (osg::minimum(source->t(), _t - t_offset) + footprint.y() - 1) / footprint.y(); + unsigned int dstRowStep = blockSize * rowWidthInBlocks; + unsigned int srcRowStep = blockSize * (source->_s + footprint.x() - 1) / footprint.x(); + const unsigned char* data_source = source->data(0, 0, 0); + for (unsigned int row = 0; row < copy_height; row += 1) { //copy blocks in a row, footprint.y() rows at a time + memcpy(data_destination, data_source, copy_width * blockSize); + data_source += srcRowStep; + data_destination += dstRowStep; + } + return; + } PixelStorageModes psm; psm.pack_alignment = _packing; psm.pack_row_length = _rowLength!=0 ? _rowLength : _s; @@ -1719,7 +1947,7 @@ bool Image::isImageTranslucent() const case(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT): case(GL_COMPRESSED_RGBA_S3TC_DXT3_EXT): case(GL_COMPRESSED_RGBA_S3TC_DXT5_EXT): - return dxtc_tool::CompressedImageTranslucent(_s, _t, _pixelFormat, _data); + return dxtc_tool::isCompressedImageTranslucent(_s, _t, _pixelFormat, _data); default: return false; } @@ -1919,18 +2147,29 @@ Vec4 _readColor(GLenum pixelFormat, T* data,float scale) Vec4 Image::getColor(unsigned int s,unsigned t,unsigned r) const { - const unsigned char* ptr = data(s,t,r); - - switch(_dataType) + if (isCompressed()) { - case(GL_BYTE): return _readColor(_pixelFormat, (char*)ptr, 1.0f/128.0f); - case(GL_UNSIGNED_BYTE): return _readColor(_pixelFormat, (unsigned char*)ptr, 1.0f/255.0f); - case(GL_SHORT): return _readColor(_pixelFormat, (short*)ptr, 1.0f/32768.0f); - case(GL_UNSIGNED_SHORT): return _readColor(_pixelFormat, (unsigned short*)ptr, 1.0f/65535.0f); - case(GL_INT): return _readColor(_pixelFormat, (int*)ptr, 1.0f/2147483648.0f); - case(GL_UNSIGNED_INT): return _readColor(_pixelFormat, (unsigned int*)ptr, 1.0f/4294967295.0f); - case(GL_FLOAT): return _readColor(_pixelFormat, (float*)ptr, 1.0f); - case(GL_DOUBLE): return _readColor(_pixelFormat, (double*)ptr, 1.0f); + if (dxtc_tool::isDXTC(_pixelFormat)) { + unsigned char color[4]; + if (dxtc_tool::CompressedImageGetColor(color, s, t, r, _s, _t, _r, _pixelFormat, _data)) { + return Vec4(((float)color[0]) / 255.0f, ((float)color[1]) / 255.0f, ((float)color[2]) / 255.0f, ((float)color[3]) / 255.0f ); + } + } + } + else + { + const unsigned char* ptr = data(s,t,r); + switch(_dataType) + { + case(GL_BYTE): return _readColor(_pixelFormat, (char*)ptr, 1.0f/128.0f); + case(GL_UNSIGNED_BYTE): return _readColor(_pixelFormat, (unsigned char*)ptr, 1.0f/255.0f); + case(GL_SHORT): return _readColor(_pixelFormat, (short*)ptr, 1.0f/32768.0f); + case(GL_UNSIGNED_SHORT): return _readColor(_pixelFormat, (unsigned short*)ptr, 1.0f/65535.0f); + case(GL_INT): return _readColor(_pixelFormat, (int*)ptr, 1.0f/2147483648.0f); + case(GL_UNSIGNED_INT): return _readColor(_pixelFormat, (unsigned int*)ptr, 1.0f/4294967295.0f); + case(GL_FLOAT): return _readColor(_pixelFormat, (float*)ptr, 1.0f); + case(GL_DOUBLE): return _readColor(_pixelFormat, (double*)ptr, 1.0f); + } } return Vec4(1.0f,1.0f,1.0f,1.0f); } diff --git a/src/osg/ImageUtils.cpp b/src/osg/ImageUtils.cpp index 6131630f6..de965b230 100644 --- a/src/osg/ImageUtils.cpp +++ b/src/osg/ImageUtils.cpp @@ -20,6 +20,7 @@ #include #include +#include "dxtctool.h" namespace osg { @@ -716,6 +717,49 @@ OSG_EXPORT osg::Image* createImageWithOrientationConversion(const osg::Image* sr unsigned int pixelSizeInBits = srcImage->getPixelSizeInBits(); unsigned int pixelSizeInBytes = pixelSizeInBits/8; unsigned int pixelSizeRemainder = pixelSizeInBits%8; + if (dxtc_tool::isDXTC(srcImage->getPixelFormat())) + { + unsigned int DXTblockSize = 8; + if ((srcImage->getPixelFormat() == GL_COMPRESSED_RGBA_S3TC_DXT3_EXT) || (srcImage->getPixelFormat() == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT)) DXTblockSize = 16; + unsigned int DXTblocksWidht = (srcImage->s() + 3) / 4;//width in 4x4 blocks + unsigned int DXTblocksHeight = (srcImage->t() + 3) / 4;//height in 4x4 blocks + unsigned int dst_DXTblocksWidht = (width + 3) / 4;//width in 4x4 blocks + unsigned int dst_DXTblocksHeight = (height + 3) / 4;//height in 4x4 blocks + + dstImage->allocateImage(width, height, depth, srcImage->getPixelFormat(), srcImage->getDataType()); + // copy across the pixels from the source image to the destination image. + if (depth != 1) + { + OSG_NOTICE << "Warning: createImageWithOrientationConversion(..) cannot handle dxt-compressed images with depth." << std::endl; + return const_cast(srcImage); + } + for (int l = 0; l> 2) + DXTblocksWidht * ((cp.y() >> 2) + (cp.z() >> 2) * DXTblocksHeight); + const unsigned char *src_block = srcImage->data() + src_blockIndex * DXTblockSize; + + unsigned int dst_blockIndex = (c >> 2) + dst_DXTblocksWidht * ((r >> 2) + (l >> 2) * dst_DXTblocksHeight); + unsigned char *dst_block = dstImage->data() + dst_blockIndex * DXTblockSize; + + memcpy((void *)dst_block, (void *)src_block, DXTblockSize); + osg::Vec3i srcSubOrigin(cp.x() & 0x7, cp.y() & 0x7, cp.z() & 0x7); + dxtc_tool::compressedBlockOrientationConversion(srcImage->getPixelFormat(),src_block, dst_block, srcSubOrigin, rowDelta, columnDelta); + + cp.x() += 4 * rowDelta.x(); + cp.y() += 4 * rowDelta.y(); + cp.z() += 4 * rowDelta.z(); + } + } + } + return dstImage.release(); + } if (pixelSizeRemainder!=0) { OSG_NOTICE<<"Warning: createImageWithOrientationConversion(..) cannot handle non byte aligned pixel formats."< #include +#include #include #include #include @@ -140,9 +141,8 @@ struct NotifySingleton _notifyLevel = osg::NOTICE; // Default value - char* OSGNOTIFYLEVEL=getenv("OSG_NOTIFY_LEVEL"); - if (!OSGNOTIFYLEVEL) OSGNOTIFYLEVEL=getenv("OSGNOTIFYLEVEL"); - if(OSGNOTIFYLEVEL) + std::string OSGNOTIFYLEVEL; + if(getEnvVar("OSG_NOTIFY_LEVEL", OSGNOTIFYLEVEL) || getEnvVar("OSGNOTIFYLEVEL", OSGNOTIFYLEVEL)) { std::string stringOSGNOTIFYLEVEL(OSGNOTIFYLEVEL); diff --git a/src/osg/Program.cpp b/src/osg/Program.cpp index 85c49a37d..b41d27b81 100644 --- a/src/osg/Program.cpp +++ b/src/osg/Program.cpp @@ -92,8 +92,7 @@ void Program::ProgramBinary::assign(unsigned int size, const unsigned char* data Program::Program() : _geometryVerticesOut(1), _geometryInputType(GL_TRIANGLES), - _geometryOutputType(GL_TRIANGLE_STRIP), - _numGroupsX(0), _numGroupsY(0), _numGroupsZ(0), _feedbackmode(GL_SEPARATE_ATTRIBS) + _geometryOutputType(GL_TRIANGLE_STRIP), _feedbackmode(GL_SEPARATE_ATTRIBS) { } @@ -133,10 +132,6 @@ Program::Program(const Program& rhs, const osg::CopyOp& copyop): _geometryInputType = rhs._geometryInputType; _geometryOutputType = rhs._geometryOutputType; - _numGroupsX = rhs._numGroupsX; - _numGroupsY = rhs._numGroupsY; - _numGroupsZ = rhs._numGroupsZ; - _feedbackmode=rhs._feedbackmode; _feedbackout=rhs._feedbackout; } @@ -173,15 +168,6 @@ int Program::compare(const osg::StateAttribute& sa) const if( _geometryOutputType < rhs._geometryOutputType ) return -1; if( rhs._geometryOutputType < _geometryOutputType ) return 1; - if( _numGroupsX < rhs._numGroupsX ) return -1; - if( rhs._numGroupsX < _numGroupsX ) return 1; - - if( _numGroupsY < rhs._numGroupsY ) return -1; - if( rhs._numGroupsY < _numGroupsY ) return 1; - - if( _numGroupsZ < rhs._numGroupsZ ) return -1; - if( rhs._numGroupsZ < _numGroupsZ ) return 1; - if(_feedbackoutvalidateProgram(); @@ -1109,8 +1080,4 @@ Program::ProgramBinary* Program::PerContextProgram::compileProgramBinary(osg::St void Program::PerContextProgram::useProgram() const { _extensions->glUseProgram( _glProgramHandle ); - if ( _program->_numGroupsX>0 && _program->_numGroupsY>0 && _program->_numGroupsZ>0 ) - { - _extensions->glDispatchCompute( _program->_numGroupsX, _program->_numGroupsY, _program->_numGroupsZ ); - } } diff --git a/src/osg/Shader.cpp b/src/osg/Shader.cpp index f255a2ddb..2b8481e42 100644 --- a/src/osg/Shader.cpp +++ b/src/osg/Shader.cpp @@ -89,6 +89,19 @@ struct NoneOf const char* _str; }; +// Replaces all occurrences of "from" with the contents of "to" +// It does only one pass, i.e. new matches created in a position before the current match are not replaced +void replaceAll(std::string& str, const std::string& from, const std::string& to) +{ + std::string::size_type pos = 0; + while ((pos = str.find(from, pos)) != std::string::npos) + { + str.replace(pos, from.length(), to); + + pos += to.length(); + } +} + } using namespace osg; @@ -301,7 +314,7 @@ void Shader::setShaderSource( const std::string& sourceText ) dirtyShader(); } - +#ifdef OSG_USE_DEPRECATED_API Shader* Shader::readShaderFile( Type type, const std::string& fileName ) { ref_ptr shader = new Shader(type); @@ -335,7 +348,7 @@ bool Shader::loadShaderSourceFromFile( const std::string& fileName ) delete [] text; return true; } - +#endif const char* Shader::getTypename() const { @@ -618,30 +631,32 @@ void Shader::PerContextShader::compileShader(osg::State& state) #endif std::string source = _shader->getShaderSource(); - if (_shader->getType()==osg::Shader::VERTEX && (state.getUseVertexAttributeAliasing() || state.getUseModelViewAndProjectionUniforms())) + // if (_shader->getType()==osg::Shader::VERTEX && (state.getUseVertexAttributeAliasing() || state.getUseModelViewAndProjectionUniforms())) { state.convertVertexShaderSourceToOsgBuiltIns(source); } - if (osg::getNotifyLevel()>=osg::INFO) - { - std::string sourceWithLineNumbers = insertLineNumbers(source); - OSG_INFO << "\nCompiling " << _shader->getTypename() - << " source:\n" << sourceWithLineNumbers << std::endl; - } - GLint compiled = GL_FALSE; - // OSG_NOTICE<<"Compiling PerContextShader "<getTypename() + << " source:\n" << sourceWithLineNumbers << std::endl; + } } else { + // Convert all windows line endings to \n + replaceAll(source, "\r\n", " \n"); std::string versionLine; unsigned int lineNum = 0; @@ -675,21 +690,40 @@ void Shader::PerContextShader::compileShader(osg::State& state) if (!versionLine.empty()) { - // OSG_NOTICE<<"Shader::PerContextShader::compileShader() : Found #version, lineNum = "<(versionLine.c_str()); sourceText[1] = reinterpret_cast(_defineStr.c_str()); sourceText[2] = reinterpret_cast(source.c_str()); _extensions->glShaderSource( _glShaderHandle, 3, sourceText, NULL ); + + if (osg::getNotifyLevel()>=osg::INFO) + { + std::string sourceWithLineNumbers = insertLineNumbers(versionLine+_defineStr+source); + OSG_INFO << "\nCompiling B: " << _shader->getTypename() + << " source:\n" << sourceWithLineNumbers << std::endl; + } + + // OSG_NOTICE<<" Version Line : ["<(_defineStr.c_str()); sourceText[1] = reinterpret_cast(source.c_str()); _extensions->glShaderSource( _glShaderHandle, 2, sourceText, NULL ); + + + if (osg::getNotifyLevel()>=osg::INFO) + { + std::string sourceWithLineNumbers = insertLineNumbers(_defineStr+source); + OSG_INFO << "\nCompiling C: " << _shader->getTypename() + << " source:\n" << sourceWithLineNumbers << std::endl; + } + + // OSG_NOTICE<<" DefineStr : ["<glCompileShader( _glShaderHandle ); diff --git a/src/osg/State.cpp b/src/osg/State.cpp index c652d4cc6..031f34872 100644 --- a/src/osg/State.cpp +++ b/src/osg/State.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -75,14 +76,17 @@ State::State(): _checkGLErrors = ONCE_PER_FRAME; - const char* str = getenv("OSG_GL_ERROR_CHECKING"); - if (str && (strcmp(str,"ONCE_PER_ATTRIBUTE")==0 || strcmp(str,"ON")==0 || strcmp(str,"on")==0)) + std::string str; + if (getEnvVar("OSG_GL_ERROR_CHECKING", str)) { - _checkGLErrors = ONCE_PER_ATTRIBUTE; - } - else if(str && (strcmp(str, "OFF") == 0 || strcmp(str, "off") == 0)) - { - _checkGLErrors = NEVER_CHECK_GL_ERRORS; + if (str=="ONCE_PER_ATTRIBUTE" || str=="ON" || str=="on") + { + _checkGLErrors = ONCE_PER_ATTRIBUTE; + } + else if (str=="OFF" || str=="off") + { + _checkGLErrors = NEVER_CHECK_GL_ERRORS; + } } _currentActiveTextureUnit=0; @@ -198,8 +202,8 @@ void State::initializeExtensionProcs() _forceVertexArrayObject = true; } - OSG_NOTICE<<"_forceVertexArrayObject = "<<_forceVertexArrayObject<getValue(var_str, value)) + { + str.replace(start_pos, num_chars, value); + } + else + { + str.erase(start_pos, num_chars); + } + } + + + void substitudeEnvVars(const osg::State& state, std::string& str) + { + std::string::size_type pos = 0; + while (posglTexStorage2D(target, numMipmapLevels, sizedInternalFormat, width, height); + if (getTextureTarget()==GL_TEXTURE_CUBE_MAP) + { + if (target==GL_TEXTURE_CUBE_MAP_POSITIVE_X) + { + extensions->glTexStorage2D(GL_TEXTURE_CUBE_MAP, numMipmapLevels, sizedInternalFormat, width, height); + } + } + else + { + extensions->glTexStorage2D(target, numMipmapLevels, sizedInternalFormat, width, height); + } if( !compressed_image ) { diff --git a/src/osg/Texture1D.cpp b/src/osg/Texture1D.cpp index 4fe3fda46..38327b07d 100644 --- a/src/osg/Texture1D.cpp +++ b/src/osg/Texture1D.cpp @@ -168,10 +168,10 @@ void Texture1D::apply(State& state) const } else if (_image.valid() && getModifiedCount(contextID) != _image->getModifiedCount()) { - applyTexImage1D(GL_TEXTURE_1D,_image.get(),state, _textureWidth, _numMipmapLevels); - // update the modified count to show that it is up to date. getModifiedCount(contextID) = _image->getModifiedCount(); + + applyTexImage1D(GL_TEXTURE_1D,_image.get(),state, _textureWidth, _numMipmapLevels); } } @@ -206,13 +206,13 @@ void Texture1D::apply(State& state) const applyTexParameters(GL_TEXTURE_1D,state); + // update the modified count to show that it is upto date. + getModifiedCount(contextID) = _image->getModifiedCount(); + applyTexImage1D(GL_TEXTURE_1D,_image.get(),state, _textureWidth, _numMipmapLevels); textureObject->setAllocated(_numMipmapLevels,_internalFormat,_textureWidth,1,1,0); - // update the modified count to show that it is up to date. - getModifiedCount(contextID) = _image->getModifiedCount(); - _textureObjectBuffer[contextID] = textureObject; // unref image data? diff --git a/src/osg/Texture2D.cpp b/src/osg/Texture2D.cpp index d73cebc37..1090f64e1 100644 --- a/src/osg/Texture2D.cpp +++ b/src/osg/Texture2D.cpp @@ -202,12 +202,11 @@ void Texture2D::apply(State& state) const } else if (_image.valid() && getModifiedCount(contextID) != _image->getModifiedCount()) { - applyTexImage2D_subload(state,GL_TEXTURE_2D,_image.get(), - _textureWidth, _textureHeight, _internalFormat, _numMipmapLevels); - // update the modified tag to show that it is up to date. getModifiedCount(contextID) = _image->getModifiedCount(); + applyTexImage2D_subload(state,GL_TEXTURE_2D,_image.get(), + _textureWidth, _textureHeight, _internalFormat, _numMipmapLevels); } else if (_readPBuffer.valid()) { @@ -224,6 +223,8 @@ void Texture2D::apply(State& state) const applyTexParameters(GL_TEXTURE_2D,state); + if (_image.valid()) getModifiedCount(contextID) = _image->getModifiedCount(); + _subloadCallback->load(*this,state); textureObject->setAllocated(_numMipmapLevels,_internalFormat,_textureWidth,_textureHeight,1,_borderWidth); @@ -235,7 +236,6 @@ void Texture2D::apply(State& state) const //glBindTexture( GL_TEXTURE_2D, handle ); // update the modified tag to show that it is up to date. - if (_image.valid()) getModifiedCount(contextID) = _image->getModifiedCount(); } else if (_image.valid() && _image->data()) { @@ -255,6 +255,9 @@ void Texture2D::apply(State& state) const applyTexParameters(GL_TEXTURE_2D,state); + // update the modified tag to show that it is up to date. + getModifiedCount(contextID) = image->getModifiedCount(); + if (textureObject->isAllocated() && image->supportsTextureSubloading()) { //OSG_NOTICE<<"Reusing texture object"<setAllocated(true); } - // update the modified tag to show that it is up to date. - getModifiedCount(contextID) = image->getModifiedCount(); - // unref image data? if (isSafeToUnrefImageData(state) && image->getDataVariance()==STATIC) { diff --git a/src/osg/Texture2DArray.cpp b/src/osg/Texture2DArray.cpp index 2f55e596c..b37051167 100644 --- a/src/osg/Texture2DArray.cpp +++ b/src/osg/Texture2DArray.cpp @@ -297,8 +297,8 @@ void Texture2DArray::apply(State& state) const { if (getModifiedCount(n,contextID) != image->getModifiedCount()) { - applyTexImage2DArray_subload(state, image, n, _textureWidth, _textureHeight, image->r(), _internalFormat, _numMipmapLevels); getModifiedCount(n,contextID) = image->getModifiedCount(); + applyTexImage2DArray_subload(state, image, n, _textureWidth, _textureHeight, image->r(), _internalFormat, _numMipmapLevels); } n += image->r(); } @@ -380,8 +380,8 @@ void Texture2DArray::apply(State& state) const { if (getModifiedCount(n,contextID) != image->getModifiedCount()) { - applyTexImage2DArray_subload(state, image, n, _textureWidth, _textureHeight, image->r(), _internalFormat, _numMipmapLevels); getModifiedCount(n,contextID) = image->getModifiedCount(); + applyTexImage2DArray_subload(state, image, n, _textureWidth, _textureHeight, image->r(), _internalFormat, _numMipmapLevels); } n += image->r(); } diff --git a/src/osg/Texture3D.cpp b/src/osg/Texture3D.cpp index 68e42fe42..5294b5a38 100644 --- a/src/osg/Texture3D.cpp +++ b/src/osg/Texture3D.cpp @@ -249,12 +249,12 @@ void Texture3D::apply(State& state) const } else if (_image.get() && getModifiedCount(contextID) != _image->getModifiedCount()) { - computeRequiredTextureDimensions(state,*_image,_textureWidth, _textureHeight, _textureDepth,_numMipmapLevels); - - applyTexImage3D(GL_TEXTURE_3D,_image.get(),state, _textureWidth, _textureHeight, _textureDepth,_numMipmapLevels); - // update the modified count to show that it is up to date. getModifiedCount(contextID) = _image->getModifiedCount(); + + computeRequiredTextureDimensions(state,*_image,_textureWidth, _textureHeight, _textureDepth,_numMipmapLevels); + + applyTexImage3D(GL_TEXTURE_3D,_image.get(),state, _textureWidth, _textureHeight, _textureDepth,_numMipmapLevels); } } @@ -291,6 +291,8 @@ void Texture3D::apply(State& state) const textureObject->bind(); + // update the modified count to show that it is up to date. + getModifiedCount(contextID) = _image->getModifiedCount(); applyTexParameters(GL_TEXTURE_3D,state); @@ -298,9 +300,6 @@ void Texture3D::apply(State& state) const textureObject->setAllocated(_numMipmapLevels,_internalFormat,_textureWidth,_textureHeight,_textureDepth,0); - // update the modified count to show that it is up to date. - getModifiedCount(contextID) = _image->getModifiedCount(); - // unref image data? if (isSafeToUnrefImageData(state) && _image->getDataVariance()==STATIC) { diff --git a/src/osg/TextureBuffer.cpp b/src/osg/TextureBuffer.cpp index d88646f3a..349b6e0bf 100644 --- a/src/osg/TextureBuffer.cpp +++ b/src/osg/TextureBuffer.cpp @@ -163,6 +163,8 @@ void TextureBuffer::apply(State& state) const const GLExtensions* extensions = state.get(); if(_bufferData.valid() &&_modifiedCount[contextID]!=_bufferData->getModifiedCount() ) { + _modifiedCount[contextID]=_bufferData->getModifiedCount() ; + GLBufferObject* glBufferObject = _bufferData->getBufferObject()->getOrCreateGLBufferObject(contextID); if (glBufferObject) { @@ -174,7 +176,6 @@ void TextureBuffer::apply(State& state) const } - _modifiedCount[contextID]=_bufferData->getModifiedCount() ; } textureObject->bind(); @@ -198,6 +199,8 @@ void TextureBuffer::apply(State& state) const { const GLExtensions* extensions = state.get(); + _modifiedCount[contextID] = _bufferData->getModifiedCount(); + textureObject = generateAndAssignTextureObject(contextID, GL_TEXTURE_BUFFER); textureObject->_profile._internalFormat=_internalFormat; textureObject->bind(); @@ -221,7 +224,6 @@ void TextureBuffer::apply(State& state) const textureObject->bind(); extensions->glTexBuffer(GL_TEXTURE_BUFFER, _internalFormat, glBufferObject->getGLObjectID()); - _modifiedCount[contextID] = _bufferData->getModifiedCount(); } } diff --git a/src/osg/TextureCubeMap.cpp b/src/osg/TextureCubeMap.cpp index 6e447e2e8..6618958a9 100644 --- a/src/osg/TextureCubeMap.cpp +++ b/src/osg/TextureCubeMap.cpp @@ -246,8 +246,8 @@ void TextureCubeMap::apply(State& state) const const osg::Image* image = _images[n].get(); if (image && getModifiedCount((Face)n,contextID) != image->getModifiedCount()) { - applyTexImage2D_subload( state, faceTarget[n], _images[n].get(), _textureWidth, _textureHeight, _internalFormat, _numMipmapLevels); getModifiedCount((Face)n,contextID) = image->getModifiedCount(); + applyTexImage2D_subload( state, faceTarget[n], _images[n].get(), _textureWidth, _textureHeight, _internalFormat, _numMipmapLevels); } } } @@ -297,6 +297,7 @@ void TextureCubeMap::apply(State& state) const const osg::Image* image = _images[n].get(); if (image) { + getModifiedCount((Face)n,contextID) = image->getModifiedCount(); if (textureObject->isAllocated()) { applyTexImage2D_subload( state, faceTarget[n], image, _textureWidth, _textureHeight, _internalFormat, _numMipmapLevels); @@ -305,7 +306,6 @@ void TextureCubeMap::apply(State& state) const { applyTexImage2D_load( state, faceTarget[n], image, _textureWidth, _textureHeight, _numMipmapLevels); } - getModifiedCount((Face)n,contextID) = image->getModifiedCount(); } diff --git a/src/osg/TextureRectangle.cpp b/src/osg/TextureRectangle.cpp index 87dbf6f9c..4a60e166d 100644 --- a/src/osg/TextureRectangle.cpp +++ b/src/osg/TextureRectangle.cpp @@ -204,10 +204,10 @@ void TextureRectangle::apply(State& state) const } else if (_image.valid() && getModifiedCount(contextID) != _image->getModifiedCount()) { - applyTexImage_subload(GL_TEXTURE_RECTANGLE, _image.get(), state, _textureWidth, _textureHeight, _internalFormat); - // update the modified count to show that it is up to date. getModifiedCount(contextID) = _image->getModifiedCount(); + + applyTexImage_subload(GL_TEXTURE_RECTANGLE, _image.get(), state, _textureWidth, _textureHeight, _internalFormat); } } else if (_subloadCallback.valid()) diff --git a/src/osg/VertexArrayState.cpp b/src/osg/VertexArrayState.cpp index 9f474fc0f..f0bc391d1 100644 --- a/src/osg/VertexArrayState.cpp +++ b/src/osg/VertexArrayState.cpp @@ -118,6 +118,8 @@ struct VertexArrayDispatch : public VertexArrayState::ArrayDispatch { VertexArrayDispatch() {} + virtual const char* className() const { return "VertexArrayDispatch"; } + virtual void enable_and_dispatch(osg::State&, const osg::Array* new_array) { VAS_NOTICE<<" VertexArrayDispatch::enable_and_dispatch("<getNumElements()<<")"<getNumElements()<<")"<getNumElements()<<")"<getNumElements()<<") unit="<getPreserveDataType()) @@ -469,6 +483,14 @@ struct VertexAttribArrayDispatch : public VertexArrayState::ArrayDispatch callVertexAttribPointer(ext, new_array, (const GLvoid *)(vbo->getOffset(new_array->getBufferIndex()))); } + virtual void enable_and_dispatch(osg::State& state, GLint size, GLenum type, GLsizei stride, const GLvoid *ptr, GLboolean normalized) + { + GLExtensions* ext = state.get(); + + ext->glEnableVertexAttribArray( unit ); + ext->glVertexAttribPointer(static_cast(unit), size, type, normalized, stride, ptr); + } + virtual void dispatch(osg::State& state, const osg::Array* new_array) { GLExtensions* ext = state.get(); @@ -699,40 +721,32 @@ void VertexArrayState::setArray(ArrayDispatch* vad, osg::State& state, const osg void VertexArrayState::setArray(ArrayDispatch* vad, osg::State& state, GLint size, GLenum type, GLsizei stride, const GLvoid *ptr, GLboolean normalized) { - if (ptr) - { + if(!vad->array){ + if (!vad->active) { vad->active = true; _activeDispatchers.push_back(vad); } - if (vad->array==0) - { - unbindVertexBufferObject(); - vad->enable_and_dispatch(state, size, type, stride, ptr, normalized); - } - else - { - unbindVertexBufferObject(); - vad->dispatch(state, size, type, stride, ptr, normalized); - } + vad->enable_and_dispatch(state, size, type, stride, ptr, normalized); - vad->array = 0; vad->modifiedCount = 0xffffffff; } - else if (vad->array) + else { disable(vad, state); } } -void VertexArrayState::setInterleavedArrays( osg::State& state, GLenum format, GLsizei stride, const GLvoid* pointer) +void VertexArrayState::setInterleavedArrays(osg::State& /*state*/, GLenum format, GLsizei stride, const GLvoid* pointer) { #if defined(OSG_GL_VERTEX_ARRAY_FUNCS_AVAILABLE) && !defined(OSG_GLES1_AVAILABLE) - lazyDisablingOfVertexAttributes(); - applyDisablingOfVertexAttributes(state); + unbindVertexBufferObject(); + + //lazyDisablingOfVertexAttributes(); + //applyDisablingOfVertexAttributes(state); glInterleavedArrays( format, stride, pointer); #else diff --git a/src/osg/dxtctool.cpp b/src/osg/dxtctool.cpp index 7e486972a..b8f9ed2b6 100644 --- a/src/osg/dxtctool.cpp +++ b/src/osg/dxtctool.cpp @@ -166,11 +166,28 @@ struct DXT1TexelsBlock unsigned short color_1; // extreme unsigned int texels4x4; // interpolated colors (2 bits per texel) }; - -bool CompressedImageTranslucent(size_t width, size_t height, GLenum format, void * imageData) +struct DXT3TexelsBlock { - // OSG_NOTICE<<"CompressedImageTranslucent("<> 2) * ((height + 3) >> 2); switch(format) { case(GL_COMPRESSED_RGB_S3TC_DXT1_EXT): @@ -182,9 +199,8 @@ bool CompressedImageTranslucent(size_t width, size_t height, GLenum format, void // Only do the check on the first mipmap level, and stop when we // see the first alpha texel - int i = (width*height)/16; - bool foundAlpha = false; - while ((!foundAlpha) && (i>0)) + int i = blockCount; + while (i>0) { // See if this block might contain transparent texels if (texelsBlock->color_0<=texelsBlock->color_1) @@ -192,7 +208,7 @@ bool CompressedImageTranslucent(size_t width, size_t height, GLenum format, void // Scan the texels block for the '11' bit pattern that // indicates a transparent texel int j = 0; - while ((!foundAlpha) && (j < 32)) + while (j < 32) { // Check for the '11' bit pattern on this texel if ( ((texelsBlock->texels4x4 >> j) & 0x03) == 0x03) @@ -214,11 +230,67 @@ bool CompressedImageTranslucent(size_t width, size_t height, GLenum format, void } case(GL_COMPRESSED_RGBA_S3TC_DXT3_EXT): - return true; - + { + const DXT3TexelsBlock *texelsBlock = reinterpret_cast(imageData); + // Only do the check on the first mipmap level, and stop when we see the first alpha texel + int i = blockCount; + while (i>0) + { + for (int j =0; j < 4; ++j) + if ( texelsBlock->alpha4[j] != 0xFFFF) //4 pixels at once + return true; //not fully opaque + // Next block + --i; + ++texelsBlock; + } + return false; + } case(GL_COMPRESSED_RGBA_S3TC_DXT5_EXT): - return true; + { + const DXT5TexelsBlock *texelsBlock = reinterpret_cast(imageData); + // Only do the check on the first mipmap level, and stop when we see the first alpha texel + int i = blockCount; + unsigned char alphaBlock[8]; + while (i>0) + { + bool eightStep = texelsBlock->alpha_0 > texelsBlock->alpha_1; + alphaBlock[0] = texelsBlock->alpha_0; + alphaBlock[1] = texelsBlock->alpha_1; + if (eightStep) { + if (texelsBlock->alpha_0 < 255) return true; //not fully opaque + alphaBlock[2] = (6 * alphaBlock[0] + 1 * alphaBlock[1] + 3) / 7; // bit code 010 + alphaBlock[3] = (5 * alphaBlock[0] + 2 * alphaBlock[1] + 3) / 7; // bit code 011 + alphaBlock[4] = (4 * alphaBlock[0] + 3 * alphaBlock[1] + 3) / 7; // bit code 100 + alphaBlock[5] = (3 * alphaBlock[0] + 4 * alphaBlock[1] + 3) / 7; // bit code 101 + alphaBlock[6] = (2 * alphaBlock[0] + 5 * alphaBlock[1] + 3) / 7; // bit code 110 + alphaBlock[7] = (1 * alphaBlock[0] + 6 * alphaBlock[1] + 3) / 7; // bit code 111 + } else { + alphaBlock[2] = (4 * alphaBlock[0] + 1 * alphaBlock[1] + 2) / 5; // bit code 010 + alphaBlock[3] = (3 * alphaBlock[0] + 2 * alphaBlock[1] + 2) / 5; // bit code 011 + alphaBlock[4] = (2 * alphaBlock[0] + 3 * alphaBlock[1] + 2) / 5; // bit code 100 + alphaBlock[5] = (1 * alphaBlock[0] + 4 * alphaBlock[1] + 2) / 5; // bit code 101 + alphaBlock[6] = 0; // bit code 110 + alphaBlock[7] = 255; // bit code 111 + } + int last_added_byte = 1; + unsigned short running_a_index = texelsBlock->alpha3[0] + (((unsigned short)texelsBlock->alpha3[last_added_byte]) << 8); + for (int j = 0; j < 16; ++j) { + unsigned char alphaIndex = running_a_index & 0x7; + if (alphaBlock[alphaIndex] < 255) return true; //not fully opaque + running_a_index >>= 3; + if ((3 * j / 8) == last_added_byte) { + ++last_added_byte; + //(&texelsBlock->alpha3[0]) to avoid gcc warning: array subscript is above array bounds [-Warray-bounds] + running_a_index += (((unsigned short)(&(texelsBlock->alpha3[0]))[last_added_byte]) << (8 - (3 * j & 0x7))); + } + } + // Next block + --i; + ++texelsBlock; + } + return false; + } default: break; } @@ -226,4 +298,361 @@ bool CompressedImageTranslucent(size_t width, size_t height, GLenum format, void return false; } +unsigned short interpolateColors21(unsigned short color1, unsigned short color2) { + unsigned short result = (((color1 >> 11) * 2 + (color2 >> 11) + 1) / 3) << 11; + result += (((color1 >> 5 & 0x3F) * 2 + (color2 >> 5 & 0x3F) + 1) / 3) << 5; + result += (((color1 & 0x1F) * 2 + (color2 & 0x1F) + 1) / 3); + return result; +} +unsigned short interpolateColors11(unsigned short color1, unsigned short color2) { + unsigned short result = (((color1 >> 11) + (color2 >> 11) ) / 2) << 11; + result += (((color1 >> 5 & 0x3F) + (color2 >> 5 & 0x3F)) / 2) << 5; + result += (((color1 & 0x1F) + (color2 & 0x1F) ) / 2); + return result; +} + +bool CompressedImageGetColor(unsigned char color[4], unsigned int s, unsigned int t, unsigned int r, int width, int height, int depth, GLenum format, unsigned char *imageData) +{ + unsigned short color16 = 0;//RGB 5:6:5 format + + + unsigned int slab4Count = (depth & ~0x3); //4*floor(d/4) + unsigned int col = (s >> 2);//(floor(x/4) + unsigned int row = (t >> 2);//(floor(y/4) + unsigned int blockWidth = (width + 3) >> 2;//ceil(w/4) + unsigned int blockHeight = (height + 3) >> 2;//ceil(h/4) + int blockNumber = col + blockWidth * row ; // block to jump to + + if (depth > 1) { +// https://www.opengl.org/registry/specs/NV/texture_compression_vtc.txt +// if (z >= 4*floor(d/4)) { +// blockIndex = blocksize * (ceil(w/4) * ceil(h/4) * 4*floor(d/4) + floor(x/4) + ceil(w/4) * (floor(y/4) + ceil(h/4) * (z-4*floor(d/4)) )); +// } else { +// blockIndex = blocksize * 4 * (floor(x/4) + ceil(w/4) * (floor(y/4) + ceil(h/4) * floor(z/4))); +// } +// note floor(a/4) = (a >> 2) +// note 4*floor(a/4) = a & ~0x3 +// note ceil(a/4) = ((a + 3) >> 2) +// +// rewrite: this describes the final blocks as consecutive 4x4x1 blocks - and thats not in the wording of the specs +// if (r >= slab4Count) { +// blockNumber = (blockWidth * blockHeight * slab4Count + col + blockWidth * (row + blockHeight * (r-slab4Count) )); +// } else { +// blockNumber = 4 * (col + blockWidth * (row + blockHeight * (r >> 2)) ); +// } + +// or in the version of the openGL specs: +// if (z >= 4*floor(d/4)) { +// blockIndex = blocksize * (ceil(w/4) * ceil(h/4) * 4*floor(d/4) + (z - 4*floor(d/4)) * ( (floor(x/4) + ceil(w/4) * (floor(y/4) ); +// } else { +// blockIndex = blocksize * 4 * (floor(x/4) + ceil(w/4) * (floor(y/4) + ceil(h/4) * floor(z/4))); +// } + + unsigned int sub_r = r & 0x3;//(r-slab4Count) + if (r >= slab4Count) { //slice number beyond 4x4x4 slabs + unsigned int blockDepth = depth & 0x3;// equals: depth - slab4Count;//depth of this final block: 1/2/3 in case of 4x4x1; 4x4x2 or 4x4x3 bricks + blockNumber = (blockWidth * blockHeight * slab4Count //jump full 4x4x4 slabs + + blockDepth * ( col + blockWidth * row ) + + sub_r); + } else { + blockNumber = 4 * (col + blockWidth * (row + blockHeight * (r >> 2)) ) + sub_r; + } + } + + int sub_s = s & 0x3; + int sub_t = t & 0x3; + switch (format) + { + case(GL_COMPRESSED_RGB_S3TC_DXT1_EXT) : + case(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) : + { + const DXT1TexelsBlock *texelsBlock = reinterpret_cast(imageData); + texelsBlock += blockNumber; //jump to block + char index = (texelsBlock->texels4x4 >> (2 * sub_s + 8 * sub_t)) & 0x3; //two bit "index value" + color[3] = 255; + switch (index) { + case 0: + color16 = texelsBlock->color_0; + break; + case 1: + color16 = texelsBlock->color_1; + break; + case 2: + if (texelsBlock->color_0 > texelsBlock->color_1) { + color16 = interpolateColors21(texelsBlock->color_0, texelsBlock->color_1); + } + else { + color16 = interpolateColors11(texelsBlock->color_0, texelsBlock->color_1); + } + break; + case 3: + if (texelsBlock->color_0 > texelsBlock->color_1) { + color16 = interpolateColors21(texelsBlock->color_1, texelsBlock->color_0); + } + else { + color16 = 0;//black + if (format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) color[3] = 0;//transparent + } + break; + } + break; + } + case(GL_COMPRESSED_RGBA_S3TC_DXT3_EXT) : + { + const DXT3TexelsBlock *texelsBlock = reinterpret_cast(imageData); + texelsBlock += blockNumber; //jump to block + color[3] = 17 * (texelsBlock->alpha4[sub_t] >> 4 * sub_s & 0xF); + char index = (texelsBlock->texels4x4 >> (2 * sub_s + 8 * sub_t)) & 0x3; //two bit "index value" + switch (index) { + case 0: + color16 = texelsBlock->color_0; + break; + case 1: + color16 = texelsBlock->color_1; + break; + case 2: + color16 = interpolateColors21(texelsBlock->color_0, texelsBlock->color_1); + break; + case 3: + color16 = interpolateColors21(texelsBlock->color_1, texelsBlock->color_0); + break; + } + break; + } + case(GL_COMPRESSED_RGBA_S3TC_DXT5_EXT) : + { + const DXT5TexelsBlock *texelsBlock = reinterpret_cast(imageData); + texelsBlock += blockNumber; //jump to block + char index = (texelsBlock->texels4x4 >> (2 * sub_s + 8 * sub_t)) & 0x3; //two bit "index value" + switch (index) { + case 0: + color16 = texelsBlock->color_0; + break; + case 1: + color16 = texelsBlock->color_1; + break; + case 2: + color16 = interpolateColors21(texelsBlock->color_0, texelsBlock->color_1); + break; + case 3: + color16 = interpolateColors21(texelsBlock->color_1, texelsBlock->color_0); + break; + } + char pixel = sub_s + 4 * sub_t;//pixel number in block: 0 - 15 + char firstBit = 3 * pixel;//least significant bit: range 0 - 45 + unsigned char alpha_index; + if ((firstBit & 0x7) < 6) { + alpha_index = texelsBlock->alpha3[firstBit >> 3] >> (firstBit & 0x7) & 0x7;//grab byte containing least significant bit; shift and get 3 bits + } else { + alpha_index = texelsBlock->alpha3[firstBit >> 3] >> (firstBit & 0x7); + alpha_index |= texelsBlock->alpha3[1 + (firstBit >> 3)] << (8 - (firstBit & 0x7)); + alpha_index &= 0x7; + } + if (alpha_index == 0) { + color[3] = texelsBlock->alpha_0; + } else { + if (alpha_index == 1) { + color[3] = texelsBlock->alpha_1; + } else { + if (texelsBlock->alpha_0 > texelsBlock->alpha_1) { + color[3] = ((unsigned short)texelsBlock->alpha_0 * (8 - alpha_index) + (unsigned short)texelsBlock->alpha_1 * (alpha_index - 1) + 3) / 7; + } else { + if (alpha_index < 6) { + color[3] = ((unsigned short)texelsBlock->alpha_0 * (6 - alpha_index) + (unsigned short)texelsBlock->alpha_1 * (alpha_index - 1) + 3) / 5; + } else { + if (alpha_index == 6) { + color[3] = 0; + } else { + color[3] = 255; + } + } + } + } + } + break; + } + default: + return false; + } + unsigned short colorChannel = color16 >> 11;//red - 5 bits + color[0] = colorChannel << 3 | colorChannel >> 2 ; + colorChannel = color16 >> 5 & 0x3F;//green - 6 bits + color[1] = colorChannel << 2 | colorChannel >> 3; + colorChannel = color16 & 0x1F;//blue - 5 bits + color[2] = colorChannel << 3 | colorChannel >> 2; + return true; +} +void compressedBlockOrientationConversion(const GLenum format, const unsigned char *src_block, unsigned char *dst_block, const osg::Vec3i& srcOrigin, const osg::Vec3i& rowDelta, const osg::Vec3i& columnDelta) +{ + unsigned int src_texels4x4; + unsigned int *dst_texels4x4 = NULL; + switch (format) + { + case(GL_COMPRESSED_RGB_S3TC_DXT1_EXT) : + case(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) : + { + const DXT1TexelsBlock *src_texelsBlock = reinterpret_cast(src_block); + //make a copy as source might be equal to destination + src_texels4x4 = src_texelsBlock->texels4x4; // interpolated colors (2 bits per texel) + DXT1TexelsBlock *dst_texelsBlock = reinterpret_cast(dst_block); + dst_texels4x4 = &dst_texelsBlock->texels4x4; + + break; + } + case(GL_COMPRESSED_RGBA_S3TC_DXT3_EXT) : + { + const DXT3TexelsBlock *src_texelsBlock = reinterpret_cast(src_block); + //make a copy as source might be equal to destination + src_texels4x4 = src_texelsBlock->texels4x4; // interpolated colors (2 bits per texel) + DXT3TexelsBlock *dst_texelsBlock = reinterpret_cast(dst_block); + dst_texels4x4 = &dst_texelsBlock->texels4x4; + unsigned short src_alpha4[4]; // alpha values (4 bits per texel) - 64 bits + + memcpy(src_alpha4, src_texelsBlock->alpha4, 4 * sizeof(unsigned short));//make a copy as source might be equal to destination + + memset(dst_texelsBlock->alpha4, 0, 4 * sizeof(unsigned short)); //clear + osg::Vec3i source_pixel(srcOrigin); + for (int r = 0; r<4; r++)//rows + { + for (int c = 0; c<4; c++)//columns + { + int sub_s = source_pixel.x() & 0x3; + int sub_t = source_pixel.y() & 0x3; + int shiftBits = 4 * sub_s; + unsigned int alpha_value = src_alpha4[sub_t] >> shiftBits & 0xf; //four bit alpha values + + shiftBits = 4 * c;//destination + alpha_value <<= shiftBits; + dst_texelsBlock->alpha4[r] |= alpha_value; + + source_pixel = source_pixel + rowDelta; + } + source_pixel = source_pixel + columnDelta; + } + break; + } + case(GL_COMPRESSED_RGBA_S3TC_DXT5_EXT) : + { + const DXT5TexelsBlock *src_texelsBlock = reinterpret_cast(src_block); + //make a copy as source might be equal to destination + src_texels4x4 = src_texelsBlock->texels4x4; // interpolated colors (2 bits per texel) + DXT5TexelsBlock *dst_texelsBlock = reinterpret_cast(dst_block); + dst_texels4x4 = &dst_texelsBlock->texels4x4; + + unsigned char src_alpha3[6]; // alpha index values (3 bits per texel) + + memcpy(src_alpha3, src_texelsBlock->alpha3, 6 * sizeof(unsigned char));//make a copy as source might be equal to destination + + memset(dst_texelsBlock->alpha3, 0, 6 * sizeof(unsigned char)); //clear + osg::Vec3i source_pixel(srcOrigin); + unsigned int last_added_byte = 1; + unsigned short running_a_index = src_texelsBlock->alpha3[0] + (((unsigned short)src_texelsBlock->alpha3[last_added_byte]) << 8); + unsigned int j = 0; + for (int r = 0; r<4; r++)//rows + { + for (int c = 0; c<4; c++)//columns + { + int sub_s = source_pixel.x() & 0x3; + int sub_t = source_pixel.y() & 0x3; + + unsigned char alphaIndex = running_a_index & 0x7; + //store alphaIndex in output position: + int shiftBits = 3 * sub_s + 12 * sub_t;//LSB + dst_texelsBlock->alpha3[shiftBits >> 3] |= alphaIndex << (shiftBits & 0x7); + if ((shiftBits & 0x7) > 5) { + dst_texelsBlock->alpha3[1 + (shiftBits >> 3)] |= alphaIndex >> (8 - (shiftBits & 0x7)); + } + + running_a_index >>= 3; + if ((3 * ++j / 8) == last_added_byte) { + ++last_added_byte; + //(&texelsBlock->alpha3[0]) to avoid gcc warning: array subscript is above array bounds [-Warray-bounds] + running_a_index += (((unsigned short)(&(src_texelsBlock->alpha3[0]))[last_added_byte]) << (8 - (3 * j & 0x7))); + } + source_pixel = source_pixel + rowDelta; + } + source_pixel = source_pixel + columnDelta; + } + break; + } + default: + return; + }//switch + + //all formats: rearrange the colors + *dst_texels4x4 = 0;//clear + osg::Vec3i source_pixel(srcOrigin); + for (int r = 0; r<4; r++)//rows + { + for (int c = 0; c<4; c++)//columns + { + int sub_s = source_pixel.x() & 0x3; + int sub_t = source_pixel.y() & 0x3; + int shiftBits = 2 * sub_s + 8 * sub_t; + unsigned int index = (src_texels4x4 >> (shiftBits)) & 0x3; //two bit "index value" + + shiftBits = 2 * c + 8 * r;//destination + index <<= shiftBits; + *dst_texels4x4 |= index; + + source_pixel = source_pixel + rowDelta; + } + source_pixel = source_pixel + columnDelta; + } +} + +void compressedBlockStripAlhpa(const GLenum format, const unsigned char *src_block, unsigned char *dst_block) { + unsigned int src_texels4x4; + char reshuffle[4] = { 1, 0, 3, 2 }; + switch (format) + { + default: + case(GL_COMPRESSED_RGB_S3TC_DXT1_EXT) : + case(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) : + { + const DXT1TexelsBlock *src_texelsBlock = reinterpret_cast(src_block); + //make a copy as source might be equal to destination + src_texels4x4 = src_texelsBlock->texels4x4; // interpolated colors (2 bits per texel) + DXT1TexelsBlock *dst_texelsBlock = reinterpret_cast(dst_block); + if (src_texelsBlock->color_0 > src_texelsBlock->color_1) { + // Four-color block + memcpy(dst_texelsBlock, src_texelsBlock, sizeof(DXT1TexelsBlock)); + } else { + dst_texelsBlock->color_0 = src_texelsBlock->color_1; + dst_texelsBlock->color_1 = src_texelsBlock->color_0; + dst_texelsBlock->texels4x4 = 0; + for (unsigned int shiftBits = 0; shiftBits < 32; shiftBits += 2) { + unsigned char index = src_texels4x4 >> shiftBits & 0x3; //two bit "index value" + dst_texelsBlock->texels4x4 |= reshuffle[index] << shiftBits; + } + + } + break; + } + case(GL_COMPRESSED_RGBA_S3TC_DXT3_EXT) : + case(GL_COMPRESSED_RGBA_S3TC_DXT5_EXT) : + { + const DXT3TexelsBlock *src_texelsBlock = reinterpret_cast(src_block); + //make a copy as source might be equal to destination + src_texels4x4 = src_texelsBlock->texels4x4; // interpolated colors (2 bits per texel) + DXT1TexelsBlock *dst_texelsBlock = reinterpret_cast(dst_block); + if (src_texelsBlock->color_0 > src_texelsBlock->color_1) { + // Four-color block + memcpy(dst_texelsBlock, src_texelsBlock, sizeof(DXT3TexelsBlock)); + } + else { + dst_texelsBlock->color_0 = src_texelsBlock->color_1; + dst_texelsBlock->color_1 = src_texelsBlock->color_0; + dst_texelsBlock->texels4x4 = 0; + for (unsigned int shiftBits = 0; shiftBits < 32; shiftBits += 2) { + unsigned char index = src_texels4x4 >> shiftBits & 0x3; //two bit "index value" + dst_texelsBlock->texels4x4 |= reshuffle[index] << shiftBits; + + } + + } + break; + } + } +} } // namespace dxtc_tool diff --git a/src/osg/dxtctool.h b/src/osg/dxtctool.h index f24cf9c90..304399d99 100644 --- a/src/osg/dxtctool.h +++ b/src/osg/dxtctool.h @@ -31,17 +31,18 @@ // Current version: 1.00 BETA 1 (27/08/2002) // // Comment: Only works with DXTC mode supported by OpenGL. -// (currently: DXT1/DXT3/DXT5) +// (currently: DXT1/DXT3/DXT5) // // History: - // ////////////////////////////////////////////////////////////////////// #ifndef DXTCTOOL_H -#define DXTCTOOL_H +#define DXTCTOOL_H #include #include +#include #if defined(_MSC_VER) @@ -78,10 +79,19 @@ bool isDXTC(GLenum pixelFormat); bool VerticalFlip(size_t Width, size_t Height, GLenum Format, void * pPixels); -bool CompressedImageTranslucent(size_t Width, size_t Height, GLenum Format, void * pPixels); +bool isCompressedImageTranslucent(size_t Width, size_t Height, GLenum Format, void * pPixels); +//interpolate RGB565 colors with 2/3 part color1 and 1/3 part color2 +unsigned short interpolateColors21(unsigned short color1, unsigned short color2); +//interpolate RGB565 colors with equal weights +unsigned short interpolateColors11(unsigned short color1, unsigned short color2); -// Class holding reference to DXTC image pixels +bool CompressedImageGetColor(unsigned char color[4], unsigned int s, unsigned int t, unsigned int r, int width, int height, int depth, GLenum format, unsigned char *imageData); + +void compressedBlockOrientationConversion(const GLenum format, const unsigned char *src_block, unsigned char *dst_block, const osg::Vec3i& srcOrigin, const osg::Vec3i& rowDelta, const osg::Vec3i& columnDelta); + +void compressedBlockStripAlhpa(const GLenum format, const unsigned char *src_block, unsigned char *dst_block); +// Class holding reference to DXTC image pixels class dxtc_pixels { public: @@ -102,7 +112,7 @@ protected: inline bool SupportedFormat() const; // Vertical flipping functions - void VFlip_DXT1() const; + void VFlip_DXT1() const; void VFlip_DXT3() const; void VFlip_DXT5() const; @@ -116,7 +126,7 @@ protected: inline void BVF_Alpha_DXT5_H2(void * const pBlock) const; // V. flip one alpha (DXT5) block with its virtual height == 2 inline void BVF_Alpha_DXT5_H4(void * const pBlock) const; // V. flip one alpha (DXT5) block with its virtual height == 4 inline void BVF_Alpha_DXT5(void * const pBlock1, void * const pBlock2) const; // V. flip and swap two alpha (DXT5) blocks, with their virtual height == 4 - + // Block localization functions inline void * GetBlock(size_t i, size_t j, size_t BlockSize) const; @@ -155,7 +165,7 @@ inline bool isDXTC(GLenum pixelFormat) } inline bool VerticalFlip(size_t Width, size_t Height, GLenum Format, void * pPixels) { - return (dxtc_pixels(Width, Height, Format, pPixels)).VFlip(); + return (dxtc_pixels(Width, Height, Format, pPixels)).VFlip(); } diff --git a/src/osg/glu/libtess/memalloc.cpp b/src/osg/glu/libtess/memalloc.cpp index b4527ea2c..e33f289d4 100644 --- a/src/osg/glu/libtess/memalloc.cpp +++ b/src/osg/glu/libtess/memalloc.cpp @@ -39,17 +39,6 @@ int __gl_memInit( size_t /*maxFast*/ ) { #ifndef NO_MALLOPT /* mallopt( M_MXFAST, maxFast );*/ -#ifdef MEMORY_DEBUG - mallopt( M_DEBUG, 1 ); -#endif #endif return 1; } - -#ifdef MEMORY_DEBUG -void *__gl_memAlloc( size_t n ) -{ - return memset( malloc( n ), 0xa5, n ); -} -#endif - diff --git a/src/osg/glu/libtess/memalloc.h b/src/osg/glu/libtess/memalloc.h index c2f969b8b..e495a1e7c 100644 --- a/src/osg/glu/libtess/memalloc.h +++ b/src/osg/glu/libtess/memalloc.h @@ -41,14 +41,8 @@ #define memFree free #define memInit __gl_memInit -/*extern void __gl_memInit( size_t );*/ extern int __gl_memInit( size_t ); -#ifndef MEMORY_DEBUG #define memAlloc malloc -#else -#define memAlloc __gl_memAlloc -extern void * __gl_memAlloc( size_t ); -#endif #endif diff --git a/src/osgAnimation/AnimationManagerBase.cpp b/src/osgAnimation/AnimationManagerBase.cpp index 1c47851a7..237b44203 100644 --- a/src/osgAnimation/AnimationManagerBase.cpp +++ b/src/osgAnimation/AnimationManagerBase.cpp @@ -101,7 +101,12 @@ void AnimationManagerBase::registerAnimation (Animation* animation) buildTargetReference(); } -void AnimationManagerBase::unregisterAnimation (Animation* animation) +void AnimationManagerBase::removeRegisteredAnimation(Animation* animation) +{ + unregisterAnimation(animation); +} + +void AnimationManagerBase::unregisterAnimation(Animation* animation) { AnimationList::iterator it = std::find(_animations.begin(), _animations.end(), animation); if (it != _animations.end()) diff --git a/src/osgAnimation/CMakeLists.txt b/src/osgAnimation/CMakeLists.txt index b0e920544..7a79b914d 100644 --- a/src/osgAnimation/CMakeLists.txt +++ b/src/osgAnimation/CMakeLists.txt @@ -34,6 +34,8 @@ SET(TARGET_H ${HEADER_PATH}/RigTransform ${HEADER_PATH}/RigTransformHardware ${HEADER_PATH}/RigTransformSoftware + ${HEADER_PATH}/MorphTransformHardware + ${HEADER_PATH}/MorphTransformSoftware ${HEADER_PATH}/Sampler ${HEADER_PATH}/Skeleton ${HEADER_PATH}/StackedMatrixElement @@ -75,6 +77,8 @@ SET(TARGET_SRC RigGeometry.cpp RigTransformHardware.cpp RigTransformSoftware.cpp + MorphTransformHardware.cpp + MorphTransformSoftware.cpp Skeleton.cpp StackedMatrixElement.cpp StackedQuaternionElement.cpp diff --git a/src/osgAnimation/MorphGeometry.cpp b/src/osgAnimation/MorphGeometry.cpp index 9735c06f9..964ff35a2 100644 --- a/src/osgAnimation/MorphGeometry.cpp +++ b/src/osgAnimation/MorphGeometry.cpp @@ -23,28 +23,31 @@ using namespace osgAnimation; MorphGeometry::MorphGeometry() : _dirty(false), _method(NORMALIZED), + _positionSource(0),_normalSource(0), _morphNormals(true) { setUseDisplayList(false); setUpdateCallback(new UpdateMorphGeometry); - setDataVariance(osg::Object::DYNAMIC); setUseVertexBufferObjects(true); + _morphTransformImplementation = new MorphTransformSoftware(); } -MorphGeometry::MorphGeometry(const osg::Geometry& b) : - osg::Geometry(b, osg::CopyOp::DEEP_COPY_ARRAYS), +MorphGeometry::MorphGeometry(const osg::Geometry& g) : + osg::Geometry(g, osg::CopyOp::DEEP_COPY_ARRAYS), _dirty(false), _method(NORMALIZED), + _positionSource(0),_normalSource(0), _morphNormals(true) { setUseDisplayList(false); setUpdateCallback(new UpdateMorphGeometry); - setDataVariance(osg::Object::DYNAMIC); setUseVertexBufferObjects(true); + _morphTransformImplementation = new MorphTransformSoftware(); } MorphGeometry::MorphGeometry(const MorphGeometry& b, const osg::CopyOp& copyop) : osg::Geometry(b,copyop), + _morphTransformImplementation(osg::clone(b._morphTransformImplementation.get(), copyop)), _dirty(b._dirty), _method(b._method), _morphTargets(b._morphTargets), @@ -56,151 +59,12 @@ MorphGeometry::MorphGeometry(const MorphGeometry& b, const osg::CopyOp& copyop) setUseVertexBufferObjects(true); } - -void MorphGeometry::transformSoftwareMethod() -{ - if (_dirty) - { - // See if we have an internal optimized geometry - osg::Geometry* morphGeometry = this; - - osg::Vec3Array* pos = dynamic_cast(morphGeometry->getVertexArray()); - - if(pos) - { - if ( _positionSource.size() != pos->size()) - { - _positionSource = std::vector(pos->begin(),pos->end()); - pos->setDataVariance(osg::Object::DYNAMIC); - } - - osg::Vec3Array* normal = dynamic_cast(morphGeometry->getNormalArray()); - bool normalmorphable = _morphNormals && normal; - if (normal && _normalSource.size() != normal->size()) - { - _normalSource = std::vector(normal->begin(),normal->end()); - normal->setDataVariance(osg::Object::DYNAMIC); - } - - - if (!_positionSource.empty()) - { - bool initialized = false; - if (_method == NORMALIZED) - { - // base * 1 - (sum of weights) + sum of (weight * target) - float baseWeight = 0; - for (unsigned int i=0; i < _morphTargets.size(); i++) - { - baseWeight += _morphTargets[i].getWeight(); - } - baseWeight = 1 - baseWeight; - - if (baseWeight != 0) - { - initialized = true; - for (unsigned int i=0; i < pos->size(); i++) - { - (*pos)[i] = _positionSource[i] * baseWeight; - } - if (normalmorphable) - { - for (unsigned int i=0; i < normal->size(); i++) - { - (*normal)[i] = _normalSource[i] * baseWeight; - } - } - } - } - else //if (_method == RELATIVE) - { - // base + sum of (weight * target) - initialized = true; - for (unsigned int i=0; i < pos->size(); i++) - { - (*pos)[i] = _positionSource[i]; - } - if (normalmorphable) - { - for (unsigned int i=0; i < normal->size(); i++) - { - (*normal)[i] = _normalSource[i]; - } - } - } - - for (unsigned int i=0; i < _morphTargets.size(); i++) - { - if (_morphTargets[i].getWeight() > 0) - { - // See if any the targets use the internal optimized geometry - osg::Geometry* targetGeometry = _morphTargets[i].getGeometry(); - - osg::Vec3Array* targetPos = dynamic_cast(targetGeometry->getVertexArray()); - osg::Vec3Array* targetNormals = dynamic_cast(targetGeometry->getNormalArray()); - normalmorphable = normalmorphable && targetNormals; - if(targetPos) - { - if (initialized) - { - // If vertices are initialized, add the morphtargets - for (unsigned int j=0; j < pos->size(); j++) - { - (*pos)[j] += (*targetPos)[j] * _morphTargets[i].getWeight(); - } - - if (normalmorphable) - { - for (unsigned int j=0; j < normal->size(); j++) - { - (*normal)[j] += (*targetNormals)[j] * _morphTargets[i].getWeight(); - } - } - } - else - { - // If not initialized, initialize with this morph target - initialized = true; - for (unsigned int j=0; j < pos->size(); j++) - { - (*pos)[j] = (*targetPos)[j] * _morphTargets[i].getWeight(); - } - - if (normalmorphable) - { - for (unsigned int j=0; j < normal->size(); j++) - { - (*normal)[j] = (*targetNormals)[j] * _morphTargets[i].getWeight(); - } - } - } - } - } - } - - pos->dirty(); - if (normalmorphable) - { - for (unsigned int j=0; j < normal->size(); j++) - { - (*normal)[j].normalize(); - } - normal->dirty(); - } - } - - dirtyBound(); - - } - _dirty = false; - } -} - UpdateMorph::UpdateMorph(const UpdateMorph& apc,const osg::CopyOp& copyop) : osg::Object(apc, copyop), osg::Callback(apc, copyop), AnimationUpdateCallback(apc, copyop) { + _targetNames=apc._targetNames; } UpdateMorph::UpdateMorph(const std::string& name) : AnimationUpdateCallback(name) @@ -243,8 +107,6 @@ void UpdateMorph::operator()(osg::Node* node, osg::NodeVisitor* nv) traverse(node,nv); } - - bool UpdateMorph::needLink() const { // the idea is to return true if nothing is linked diff --git a/src/osgAnimation/MorphTransformHardware.cpp b/src/osgAnimation/MorphTransformHardware.cpp new file mode 100644 index 000000000..f13ea715e --- /dev/null +++ b/src/osgAnimation/MorphTransformHardware.cpp @@ -0,0 +1,212 @@ +/* -*-c++-*- + * Copyright (C) 2017 Julien Valentin + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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 + * OpenSceneGraph Public License for more details. + */ + +#include +#include +#include +#include +#include +#include + +using namespace osgAnimation; + +MorphTransformHardware::MorphTransformHardware(): + _needInit(true), + _reservedTextureUnit(MORPHTRANSHW_DEFAULTMORPHTEXTUREUNIT) +{ +} + +MorphTransformHardware::MorphTransformHardware(const MorphTransformHardware& rth, const osg::CopyOp& copyop): + MorphTransform(rth, copyop), + _uniformTargetsWeight(rth._uniformTargetsWeight), + _shader(rth._shader), + _needInit(rth._needInit), + _reservedTextureUnit(rth._reservedTextureUnit) +{ +} + +bool MorphTransformHardware::init(MorphGeometry& morphGeometry) +{ + osg::Vec3Array* pos = dynamic_cast(morphGeometry.getVertexArray()); + + osg::Vec3Array * vertexSource = (morphGeometry.getVertexSource()); + osg::Vec3Array * normalSource = (morphGeometry.getNormalSource()); + morphGeometry.setDataVariance(osg::Object::STATIC); + ///check for correct morph configuration + ///(blender osgexport doesn't set sources so assume morphgeom arrays are sources) + if(pos) + { + pos->setDataVariance(osg::Object::STATIC); + ///check if source is setted correctly + if (!vertexSource|| vertexSource->size() != pos->size()) + { + vertexSource =(static_cast( pos->clone(osg::CopyOp::DEEP_COPY_ARRAYS))); + } + osg::Vec3Array* normal = dynamic_cast(morphGeometry.getNormalArray()); + bool normalmorphable = morphGeometry.getMorphNormals() && normal&&(normal->getBinding()==osg::Array::BIND_PER_VERTEX); + if(!normalmorphable) + { + OSG_WARN << "MorphTransformHardware::morph geometry "<setDataVariance(osg::Object::STATIC); + if (normalmorphable && (!normalSource || normalSource->size() != normal->size())) + { + normalSource =(static_cast( normal->clone(osg::CopyOp::DEEP_COPY_ARRAYS))); + } + } + + ///end check + morphGeometry.setVertexArray(morphGeometry.getVertexSource()); + morphGeometry.setNormalArray(morphGeometry.getNormalSource(),osg::Array::BIND_PER_VERTEX); + morphGeometry.setDataVariance(osg::Object::STATIC); + + //create one TBO for all morphtargets (pack vertex/normal) + osg::Vec3Array * morphTargets=new osg::Vec3Array ; + MorphGeometry::MorphTargetList & morphlist=morphGeometry.getMorphTargetList(); + for(MorphGeometry::MorphTargetList::const_iterator curmorph=morphlist.begin(); curmorph!=morphlist.end(); ++curmorph) + { + const osg::Geometry * morphtargetgeom= curmorph->getGeometry() ; + const osg::Vec3Array *varray=(osg::Vec3Array*)morphtargetgeom->getVertexArray(); + const osg::Vec3Array *narray=(osg::Vec3Array*)morphtargetgeom->getNormalArray(); + if(morphGeometry.getMethod()==MorphGeometry::RELATIVE) + { + for(unsigned int i=0; igetNumElements(); ++i) + { + morphTargets->push_back( (*varray)[i]); + morphTargets->push_back( (*narray)[i]); + } + } + else + { + //convert to RELATIVE as it involve less math in the VS than NORMALIZED + const osg::Vec3Array *ovarray=(osg::Vec3Array*)morphGeometry.getVertexArray(); + const osg::Vec3Array *onarray=(osg::Vec3Array*)morphGeometry.getNormalArray(); + for(unsigned int i=0; igetNumElements(); ++i) + { + morphTargets->push_back( (*varray)[i]- (*ovarray)[i] ); + morphTargets->push_back( (*narray)[i]- (*onarray)[i] ); + } + } + } + + osg::ref_ptr morphTargetsTBO=new osg::TextureBuffer(); + morphTargetsTBO->setBufferData(morphTargets); + morphTargetsTBO->setInternalFormat( GL_RGB32F_ARB ); + + //create TBO Texture handle + osg::ref_ptr morphTBOHandle=new osg::Uniform(osg::Uniform::SAMPLER_BUFFER,"morphTargets"); + morphTBOHandle->set((int)_reservedTextureUnit); + + //create dynamic uniform for morphtargets animation weights + _uniformTargetsWeight=new osg::Uniform(osg::Uniform::FLOAT,"morphWeights",morphlist.size()); + + + osg::ref_ptr program ; + osg::ref_ptr vertexshader; + osg::ref_ptr stateset = morphGeometry.getOrCreateStateSet(); + //grab geom source program and vertex shader if _shader is not setted + if(!_shader.valid() && (program = (osg::Program*)stateset->getAttribute(osg::StateAttribute::PROGRAM))) + { + for(unsigned int i=0;igetNumShaders();++i) + { + if(program->getShader(i)->getType()==osg::Shader::VERTEX) + { + // vertexshader=program->getShader(i); + program->removeShader(vertexshader); + } + } + } + + if (!program) + { + program = new osg::Program; + } + + program->setName("HardwareMorphing"); + //set default source if _shader is not user setted + if (!vertexshader.valid()) + { + if (!_shader.valid()) vertexshader = osgDB::readRefShaderFile(osg::Shader::VERTEX,"morphing.vert"); + else vertexshader=_shader; + } + + if (!vertexshader.valid()) + { + OSG_WARN << "RigTransformHardware can't load VertexShader" << std::endl; + return false; + } + + // replace max matrix by the value from uniform + { + std::string str = vertexshader->getShaderSource(); + std::string toreplace = std::string("MAX_MORPHWEIGHT"); + std::size_t start = str.find(toreplace); + if (std::string::npos == start) + { + // perhaps remanance from previous init (if saved after init) so reload shader + vertexshader = osgDB::readRefShaderFile(osg::Shader::VERTEX,"morphing.vert"); + if (!vertexshader.valid()) + { + OSG_WARN << "RigTransformHardware can't load VertexShader" << std::endl; + return false; + } + str = vertexshader->getShaderSource(); + start = str.find(toreplace); + } + if (std::string::npos != start) + { + std::stringstream ss; + ss << _uniformTargetsWeight->getNumElements(); + str.replace(start, toreplace.size(), ss.str()); + vertexshader->setShaderSource(str); + } + else + { + OSG_WARN << "MAX_MORPHWEIGHT not found in Shader! " << str << std::endl; + } + OSG_INFO << "Shader " << str << std::endl; + } + + program->addShader(vertexshader.get()); + //morphGeometry.setStateSet((osg::StateSet *) osg::CopyOp()(source.getOrCreateStateSet())); + + osg::ref_ptr ss = morphGeometry.getOrCreateStateSet(); + ss->addUniform(_uniformTargetsWeight); + ss->setTextureAttribute(_reservedTextureUnit,morphTargetsTBO); + ss->addUniform( morphTBOHandle); + ss->addUniform(new osg::Uniform("nbMorphVertex", morphGeometry.getVertexArray()->getNumElements())); + + ss->setAttributeAndModes(program.get()); + _needInit = false; + return true; +} + +void MorphTransformHardware::operator()(MorphGeometry& geom) +{ + if (_needInit && !init(geom)) return; + + if (geom.isDirty()) + { + ///upload new morph weights each update via uniform + int curimorph=0; + MorphGeometry::MorphTargetList & morphlist=geom.getMorphTargetList(); + for(MorphGeometry::MorphTargetList::const_iterator curmorph=morphlist.begin(); curmorph!=morphlist.end(); ++curmorph) + { + _uniformTargetsWeight->setElement(curimorph++, curmorph->getWeight()); + } + _uniformTargetsWeight->dirty(); + geom.dirty(false); + } +} diff --git a/src/osgAnimation/MorphTransformSoftware.cpp b/src/osgAnimation/MorphTransformSoftware.cpp new file mode 100644 index 000000000..1965a5ed1 --- /dev/null +++ b/src/osgAnimation/MorphTransformSoftware.cpp @@ -0,0 +1,181 @@ +/* -*-c++-*- + * Copyright (C) 2009 Cedric Pinson + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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 + * OpenSceneGraph Public License for more details. + */ + + +#include +#include +#include +#include + +using namespace osgAnimation; + + +bool MorphTransformSoftware::init(MorphGeometry& morphGeometry){ + + morphGeometry.setDataVariance(osg::Object::DYNAMIC); + osg::Vec3Array* pos = dynamic_cast(morphGeometry.getVertexArray()); + osg::Vec3Array * vertexSource = (morphGeometry.getVertexSource()); + osg::Vec3Array * normalSource = (morphGeometry.getNormalSource()); + + // See if we have an internal optimized geometry + + if(pos) + { + if (!vertexSource|| vertexSource->size() != pos->size()) + { + morphGeometry.setVertexSource(new osg::Vec3Array(pos->begin(),pos->end())); + pos->setDataVariance(osg::Object::DYNAMIC); + } + + osg::Vec3Array* normal = dynamic_cast(morphGeometry.getNormalArray()); + bool normalmorphable = morphGeometry.getMorphNormals() && normal; + morphGeometry.setMorphNormals(normalmorphable); + if (normalmorphable && (!normalSource || normalSource->size() != normal->size())) + { + morphGeometry.setNormalSource(new osg::Vec3Array(normal->begin(),normal->end())); + normal->setDataVariance(osg::Object::DYNAMIC); + } + }else return false; + + _needInit=false; + return true; +} + +void MorphTransformSoftware::operator()(MorphGeometry& morphGeometry) +{ + if (_needInit) + if (!init(morphGeometry)) + return; + if (morphGeometry.isDirty()) + { + osg::Vec3Array* pos = static_cast(morphGeometry.getVertexArray()); + osg::Vec3Array & vertexSource = *(morphGeometry.getVertexSource()); + osg::Vec3Array& normalSource = *(morphGeometry.getNormalSource()); + osg::Vec3Array* normal = static_cast(morphGeometry.getNormalArray()); + bool normalmorphable = morphGeometry.getMorphNormals() && normal; + + + if (!vertexSource.empty()) + { + bool initialized = false; + if (morphGeometry.getMethod() == MorphGeometry::NORMALIZED) + { + // base * 1 - (sum of weights) + sum of (weight * target) + float baseWeight = 0; + for (unsigned int i=0; i < morphGeometry.getMorphTargetList().size(); i++) + { + baseWeight += morphGeometry.getMorphTarget(i).getWeight(); + } + baseWeight = 1 - baseWeight; + + if (baseWeight != 0) + { + initialized = true; + for (unsigned int i=0; i < pos->size(); i++) + { + (*pos)[i] = vertexSource[i] * baseWeight; + } + if (normalmorphable) + { + for (unsigned int i=0; i < normal->size(); i++) + { + (*normal)[i] = normalSource[i] * baseWeight; + } + } + } + } + else //if (_method == RELATIVE) + { + // base + sum of (weight * target) + initialized = true; + for (unsigned int i=0; i < pos->size(); i++) + { + (*pos)[i] = vertexSource[i]; + } + if (normalmorphable) + { + for (unsigned int i=0; i < normal->size(); i++) + { + (*normal)[i] = normalSource[i]; + } + } + } + + for (unsigned int i=0; i < morphGeometry.getMorphTargetList().size(); i++) + { + if (morphGeometry.getMorphTarget(i).getWeight() > 0) + { + // See if any the targets use the internal optimized geometry + osg::Geometry* targetGeometry = morphGeometry.getMorphTarget(i).getGeometry(); + + osg::Vec3Array* targetPos = dynamic_cast(targetGeometry->getVertexArray()); + osg::Vec3Array* targetNormals = dynamic_cast(targetGeometry->getNormalArray()); + normalmorphable = normalmorphable && targetNormals; + if(targetPos) + { + if (initialized) + { + // If vertices are initialized, add the morphtargets + for (unsigned int j=0; j < pos->size(); j++) + { + (*pos)[j] += (*targetPos)[j] * morphGeometry.getMorphTarget(i).getWeight(); + } + + if (normalmorphable) + { + for (unsigned int j=0; j < normal->size(); j++) + { + (*normal)[j] += (*targetNormals)[j] * morphGeometry.getMorphTarget(i).getWeight(); + } + } + } + else + { + // If not initialized, initialize with this morph target + initialized = true; + for (unsigned int j=0; j < pos->size(); j++) + { + (*pos)[j] = (*targetPos)[j] * morphGeometry.getMorphTarget(i).getWeight(); + } + + if (normalmorphable) + { + for (unsigned int j=0; j < normal->size(); j++) + { + (*normal)[j] = (*targetNormals)[j] * morphGeometry.getMorphTarget(i).getWeight(); + } + } + } + } + } + } + + pos->dirty(); + if (normalmorphable) + { + for (unsigned int j=0; j < normal->size(); j++) + { + (*normal)[j].normalize(); + } + normal->dirty(); + } + } + + morphGeometry.dirtyBound(); + + + morphGeometry.dirty(false); + } + +} diff --git a/src/osgAnimation/RigGeometry.cpp b/src/osgAnimation/RigGeometry.cpp index 938629a97..1f3764b48 100644 --- a/src/osgAnimation/RigGeometry.cpp +++ b/src/osgAnimation/RigGeometry.cpp @@ -58,7 +58,8 @@ RigGeometry::RigGeometry() _needToComputeMatrix = true; _matrixFromSkeletonToGeometry = _invMatrixFromSkeletonToGeometry = osg::Matrix::identity(); // disable the computation of boundingbox for the rig mesh - setComputeBoundingBoxCallback(new RigComputeBoundingBoxCallback); + setComputeBoundingBoxCallback(new RigComputeBoundingBoxCallback()); + _rigTransformImplementation = new osgAnimation::RigTransformSoftware; } @@ -66,12 +67,15 @@ RigGeometry::RigGeometry() RigGeometry::RigGeometry(const RigGeometry& b, const osg::CopyOp& copyop) : osg::Geometry(b,copyop), _geometry(b._geometry), - _vertexInfluenceSet(b._vertexInfluenceSet), + _rigTransformImplementation(osg::clone(b._rigTransformImplementation.get(), copyop)), _vertexInfluenceMap(b._vertexInfluenceMap), _needToComputeMatrix(b._needToComputeMatrix) -{ +{ + _needToComputeMatrix = true; + _matrixFromSkeletonToGeometry = _invMatrixFromSkeletonToGeometry = osg::Matrix::identity(); // disable the computation of boundingbox for the rig mesh - setComputeBoundingBoxCallback(new RigComputeBoundingBoxCallback); + + setComputeBoundingBoxCallback(new RigComputeBoundingBoxCallback()); // we don't copy the RigImplementation yet. because the RigImplementation need to be initialized in a valid graph, with a skeleton ... // don't know yet what to do with a clone of a RigGeometry @@ -82,29 +86,6 @@ const osg::Matrix& RigGeometry::getMatrixFromSkeletonToGeometry() const { return const osg::Matrix& RigGeometry::getInvMatrixFromSkeletonToGeometry() const { return _invMatrixFromSkeletonToGeometry;} -void RigGeometry::drawImplementation(osg::RenderInfo& renderInfo) const -{ - osg::Geometry::drawImplementation(renderInfo); -} - -void RigGeometry::buildVertexInfluenceSet() -{ - if (!_vertexInfluenceMap.valid()) - { - OSG_WARN << "buildVertexInfluenceSet can't be called without VertexInfluence already set to the RigGeometry ( " << getName() << " ) " << std::endl; - return; - } - _vertexInfluenceSet.clear(); - for (osgAnimation::VertexInfluenceMap::iterator it = _vertexInfluenceMap->begin(); - it != _vertexInfluenceMap->end(); - ++it) - _vertexInfluenceSet.addVertexInfluence(it->second); - - _vertexInfluenceSet.buildVertex2BoneList(); - _vertexInfluenceSet.buildUniqVertexSetToBoneSetList(); - OSG_DEBUG << "uniq groups " << _vertexInfluenceSet.getUniqVertexSetToBoneSetList().size() << " for " << getName() << std::endl; -} - void RigGeometry::computeMatrixFromRootSkeleton() { if (!_root.valid()) @@ -116,61 +97,56 @@ void RigGeometry::computeMatrixFromRootSkeleton() osg::Matrix notRoot = _root->getMatrix(); _matrixFromSkeletonToGeometry = mtxList[0] * osg::Matrix::inverse(notRoot); _invMatrixFromSkeletonToGeometry = osg::Matrix::inverse(_matrixFromSkeletonToGeometry); - _needToComputeMatrix = false; + _needToComputeMatrix = false; } void RigGeometry::update() { - if (!getRigTransformImplementation()) - { - _rigTransformImplementation = new RigTransformSoftware; - } - - RigTransform& implementation = *getRigTransformImplementation(); + RigTransform& implementation = *_rigTransformImplementation; (implementation)(*this); } void RigGeometry::copyFrom(osg::Geometry& from) { - bool copyToSelf = (this==&from); + if (this==&from) return; osg::Geometry& target = *this; - if (!copyToSelf) target.setStateSet(from.getStateSet()); + target.setStateSet(from.getStateSet()); // copy over primitive sets. - if (!copyToSelf) target.getPrimitiveSetList() = from.getPrimitiveSetList(); + target.getPrimitiveSetList() = from.getPrimitiveSetList(); if (from.getVertexArray()) { - if (!copyToSelf) target.setVertexArray(from.getVertexArray()); + target.setVertexArray(from.getVertexArray()); } if (from.getNormalArray()) { - if (!copyToSelf) target.setNormalArray(from.getNormalArray()); + target.setNormalArray(from.getNormalArray()); } if (from.getColorArray()) { - if (!copyToSelf) target.setColorArray(from.getColorArray()); + target.setColorArray(from.getColorArray()); } if (from.getSecondaryColorArray()) { - if (!copyToSelf) target.setSecondaryColorArray(from.getSecondaryColorArray()); + target.setSecondaryColorArray(from.getSecondaryColorArray()); } if (from.getFogCoordArray()) { - if (!copyToSelf) target.setFogCoordArray(from.getFogCoordArray()); + target.setFogCoordArray(from.getFogCoordArray()); } for(unsigned int ti=0;ti + * Copyright (C) 2017 Julien Valentin * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or @@ -15,137 +16,53 @@ #include #include #include +#include #include using namespace osgAnimation; - -RigTransformHardware::RigTransformHardware() -{ - _needInit = true; - _bonesPerVertex = 0; - _nbVertexes = 0; -} +RigTransformHardware::RigTransformHardware(): + _bonesPerVertex (0), + _nbVertices (0), + _needInit (true), + _minAttribIndex(RIGTRANSHW_DEFAULT_FIRST_VERTATTRIB_TARGETTED) +{} RigTransformHardware::RigTransformHardware(const RigTransformHardware& rth, const osg::CopyOp& copyop): RigTransform(rth, copyop), _bonesPerVertex(rth._bonesPerVertex), - _nbVertexes(rth._nbVertexes), - _vertexIndexMatrixWeightList(rth._vertexIndexMatrixWeightList), + _nbVertices(rth._nbVertices), _bonePalette(rth._bonePalette), _boneNameToPalette(rth._boneNameToPalette), _boneWeightAttribArrays(rth._boneWeightAttribArrays), _uniformMatrixPalette(rth._uniformMatrixPalette), _shader(rth._shader), - _needInit(rth._needInit) + _needInit(rth._needInit), + _minAttribIndex(rth._minAttribIndex) { } -osg::Vec4Array* RigTransformHardware::getVertexAttrib(int index) +osg::Vec4Array* RigTransformHardware::getVertexAttrib(unsigned int index) { - if (index >= (int)_boneWeightAttribArrays.size()) + if (index >= _boneWeightAttribArrays.size()) return 0; return _boneWeightAttribArrays[index].get(); } -int RigTransformHardware::getNumVertexAttrib() -{ - return _boneWeightAttribArrays.size(); -} - -osg::Uniform* RigTransformHardware::getMatrixPaletteUniform() -{ - return _uniformMatrixPalette.get(); -} - - void RigTransformHardware::computeMatrixPaletteUniform(const osg::Matrix& transformFromSkeletonToGeometry, const osg::Matrix& invTransformFromSkeletonToGeometry) { - for (int i = 0; i < (int)_bonePalette.size(); i++) + for (unsigned int i = 0; i < _bonePalette.size(); ++i) { osg::ref_ptr bone = _bonePalette[i].get(); - const osg::Matrix& invBindMatrix = bone->getInvBindMatrixInSkeletonSpace(); - const osg::Matrix& boneMatrix = bone->getMatrixInSkeletonSpace(); - osg::Matrix resultBoneMatrix = invBindMatrix * boneMatrix; - osg::Matrix result = transformFromSkeletonToGeometry * resultBoneMatrix * invTransformFromSkeletonToGeometry; + const osg::Matrixf& invBindMatrix = bone->getInvBindMatrixInSkeletonSpace(); + const osg::Matrixf& boneMatrix = bone->getMatrixInSkeletonSpace(); + osg::Matrixf resultBoneMatrix = invBindMatrix * boneMatrix; + osg::Matrixf result = transformFromSkeletonToGeometry * resultBoneMatrix * invTransformFromSkeletonToGeometry; if (!_uniformMatrixPalette->setElement(i, result)) OSG_WARN << "RigTransformHardware::computeUniformMatrixPalette can't set uniform at " << i << " elements" << std::endl; } } - -int RigTransformHardware::getNumBonesPerVertex() const { return _bonesPerVertex;} -int RigTransformHardware::getNumVertexes() const { return _nbVertexes;} - -bool RigTransformHardware::createPalette(int nbVertexes, BoneMap boneMap, const VertexInfluenceSet::VertexIndexToBoneWeightMap& vertexIndexToBoneWeightMap) -{ - typedef std::map BoneNameCountMap; - BonePalette palette; - BoneNameCountMap boneNameCountMap; - - // init vertex attribute data - VertexIndexWeightList vertexIndexWeight; - vertexIndexWeight.resize(nbVertexes); - - int maxBonePerVertex = 0; - for (VertexInfluenceSet::VertexIndexToBoneWeightMap::const_iterator vit = vertexIndexToBoneWeightMap.begin(); vit != vertexIndexToBoneWeightMap.end(); ++vit) - { - int vertexIndex = vit->first; - const VertexInfluenceSet::BoneWeightList& boneWeightList = vit->second; - int bonesForThisVertex = 0; - for (VertexInfluenceSet::BoneWeightList::const_iterator it = boneWeightList.begin(); it != boneWeightList.end(); ++it) - { - const VertexInfluenceSet::BoneWeight& bw = *it; - if(fabs(bw.getWeight()) > 1e-2) // don't use bone with weight too small - { - if (boneNameCountMap.find(bw.getBoneName()) != boneNameCountMap.end()) - { - boneNameCountMap[bw.getBoneName()]++; - bonesForThisVertex++; // count max number of bones per vertexes - vertexIndexWeight[vertexIndex].push_back(IndexWeightEntry(_boneNameToPalette[bw.getBoneName()],bw.getWeight())); - } - else - { - if (boneMap.find(bw.getBoneName()) == boneMap.end()) - { - OSG_INFO << "RigTransformHardware::createPalette can't find bone " << bw.getBoneName() << " skip this influence" << std::endl; - continue; - } - boneNameCountMap[bw.getBoneName()] = 1; // for stats - bonesForThisVertex++; - palette.push_back(boneMap[bw.getBoneName()]); - _boneNameToPalette[bw.getBoneName()] = palette.size()-1; - vertexIndexWeight[vertexIndex].push_back(IndexWeightEntry(_boneNameToPalette[bw.getBoneName()],bw.getWeight())); - } - } - else - { - OSG_WARN << "RigTransformHardware::createPalette Bone " << bw.getBoneName() << " has a weight " << bw.getWeight() << " for vertex " << vertexIndex << " this bone will not be in the palette" << std::endl; - } - } - maxBonePerVertex = osg::maximum(maxBonePerVertex, bonesForThisVertex); - } - OSG_INFO << "RigTransformHardware::createPalette maximum number of bone per vertex is " << maxBonePerVertex << std::endl; - OSG_INFO << "RigTransformHardware::createPalette matrix palette has " << boneNameCountMap.size() << " entries" << std::endl; - - for (BoneNameCountMap::iterator it = boneNameCountMap.begin(); it != boneNameCountMap.end(); ++it) - { - OSG_INFO << "RigTransformHardware::createPalette Bone " << it->first << " is used " << it->second << " times" << std::endl; - } - - OSG_INFO << "RigTransformHardware::createPalette will use " << boneNameCountMap.size() * 4 << " uniforms" << std::endl; - - - _nbVertexes = nbVertexes; - _bonesPerVertex = maxBonePerVertex; - _bonePalette = palette; - _vertexIndexMatrixWeightList = vertexIndexWeight; - _uniformMatrixPalette = createVertexUniform(); - _boneWeightAttribArrays = createVertexAttribList(); - return true; -} - - // // create vertex attribute by 2 bones // vec4(boneIndex0, weight0, boneIndex1, weight1) @@ -154,133 +71,304 @@ bool RigTransformHardware::createPalette(int nbVertexes, BoneMap boneMap, const // the idea is to use this format to have a granularity smaller // than the 4 bones using two vertex attributes // -RigTransformHardware::BoneWeightAttribList RigTransformHardware::createVertexAttribList() -{ - BoneWeightAttribList arrayList; - int nbArray = static_cast(ceilf(getNumBonesPerVertex() * 0.5)); - if (!nbArray) - return arrayList; - arrayList.resize(nbArray); - for (int i = 0; i < nbArray; i++) +typedef std::vector > PerVertexInfList; + +///create normalized a set of Vertex Attribs given a PerVertexInfList and return the max num bone per vertex +unsigned int createVertexAttribList(const PerVertexInfList & perVertexInfluences, + RigTransformHardware::BoneWeightAttribList& boneWeightAttribArrays) +{ + short boneIndexInVec4; + unsigned int vertid = 0, + boneIndexInList; + IndexWeightList::size_type maxBonePerVertex = 0; + ///build vertex attrib arrays + //get maxBonePerVertex + for(PerVertexInfList::const_iterator vertinfit = perVertexInfluences.begin(); vertinfit != perVertexInfluences.end(); ++vertinfit) + maxBonePerVertex = osg::maximum(maxBonePerVertex, vertinfit->size()); + + OSG_INFO << "RigTransformHardware::createVertexAttribList maximum number of bone per vertex is " << maxBonePerVertex << std::endl; + + unsigned int nbArray = static_cast(ceilf( ((float)maxBonePerVertex) * 0.5f)); + + if (!nbArray) + return 0; + + ///create vertex attrib arrays + boneWeightAttribArrays.reserve(nbArray); + boneWeightAttribArrays.resize(nbArray); + for(unsigned int j = 0; j< nbArray; ++j) { - osg::ref_ptr array = new osg::Vec4Array(osg::Array::BIND_PER_VERTEX); - arrayList[i] = array; - int nbVertexes = getNumVertexes(); - array->resize(nbVertexes); - for (int j = 0; j < nbVertexes; j++) + osg::Vec4Array* vecattr = new osg::Vec4Array(osg::Array::BIND_PER_VERTEX); + vecattr->reserve(perVertexInfluences.size()); + vecattr->resize(perVertexInfluences.size()); + boneWeightAttribArrays[j] = vecattr; + } + + ///populate vertex attrib arrays + for(PerVertexInfList::const_iterator vertinfit = perVertexInfluences.begin(); + vertinfit != perVertexInfluences.end(); + ++vertinfit, ++vertid) + { + //sum for normalization + float sum = 0; + for(IndexWeightList::const_iterator iwit = vertinfit->begin(); iwit != vertinfit->end(); ++iwit) + sum+=iwit->second; + + if(sum< 1e-4) { - for (int b = 0; b < 2; b++) + OSG_WARN << "RigTransformHardware::createVertexAttribList Warning: vertex with zero sum weights: " <(_vertexIndexMatrixWeightList[j][boneIndexInList].getIndex()); - float boneWeight = _vertexIndexMatrixWeightList[j][boneIndexInList].getWeight(); - // fill the vec4 - (*array)[j][0 + boneIndexInVec4] = boneIndex; - (*array)[j][1 + boneIndexInVec4] = boneWeight; + boneIndexInVec4 = b*2; + boneIndexInList = j*2 + b; + if (boneIndexInList < (*vertinfit).size()) + { + float boneIndex = static_cast((*vertinfit)[boneIndexInList].first); + ///normalization here + float boneWeight = (*vertinfit)[boneIndexInList].second*sum; + dest[0 + boneIndexInVec4] = boneIndex; + dest[1 + boneIndexInVec4] = boneWeight; + } + else + { + dest[0 + boneIndexInVec4] = 0; + dest[1 + boneIndexInVec4] = 0; + } } } } } - return arrayList; + return maxBonePerVertex; } - -osg::Uniform* RigTransformHardware::createVertexUniform() +bool RigTransformHardware::prepareData(RigGeometry& rig) { - osg::Uniform* uniform = new osg::Uniform(osg::Uniform::FLOAT_MAT4, "matrixPalette", _bonePalette.size()); - return uniform; -} + _nbVertices = rig.getSourceGeometry()->getVertexArray()->getNumElements(); + const VertexInfluenceMap &vertexInfluenceMap = *rig.getInfluenceMap(); + _perVertexInfluences.reserve(_nbVertices); + _perVertexInfluences.resize(_nbVertices); - -void RigTransformHardware::setShader(osg::Shader* shader) -{ - _shader = shader; -} - -bool RigTransformHardware::init(RigGeometry& geom) -{ - osg::Geometry& source = *geom.getSourceGeometry(); - osg::Vec3Array* positionSrc = dynamic_cast(source.getVertexArray()); - if (!positionSrc) + unsigned int localboneid = 0; + for (VertexInfluenceMap::const_iterator boneinflistit = vertexInfluenceMap.begin(); + boneinflistit != vertexInfluenceMap.end(); + ++boneinflistit, ++localboneid) { - OSG_WARN << "RigTransformHardware no vertex array in the geometry " << geom.getName() << std::endl; + const IndexWeightList& boneinflist = boneinflistit->second; + const std::string& bonename = boneinflistit->first; + + for(IndexWeightList::const_iterator infit = boneinflist.begin(); infit!=boneinflist.end(); ++infit) + { + const VertexIndexWeight& iw = *infit; + const unsigned int &index = iw.first; + const float &weight = iw.second; + IndexWeightList & iwlist = _perVertexInfluences[index]; + + if(fabs(weight) > 1e-4) // don't use bone with weight too small + { + iwlist.push_back(VertexIndexWeight(localboneid,weight)); + } + else + { + OSG_WARN << "RigTransformHardware::prepareData Bone " << bonename << " has a weight " << weight << " for vertex " << index << " this bone will not be in the palette" << std::endl; + } + } + } + return true; +} + + +bool RigTransformHardware::buildPalette(const BoneMap& boneMap, const RigGeometry& rig) +{ + + typedef std::map BoneNameCountMap; + _boneWeightAttribArrays.resize(0); + _bonePalette.clear(); + _boneNameToPalette.clear(); + + IndexWeightList::size_type maxBonePerVertex = 0; + BoneNameCountMap boneNameCountMap; + + const VertexInfluenceMap &vertexInfluenceMap = *rig.getInfluenceMap(); + BoneNamePaletteIndex::iterator boneName2PaletteIndex; + + ///create local boneid to paletteindex + unsigned int paletteindex; + std::vector localid2bone; + localid2bone.reserve(vertexInfluenceMap.size()); + for (osgAnimation::VertexInfluenceMap::const_iterator perBoneinfit = vertexInfluenceMap.begin(); + perBoneinfit != vertexInfluenceMap.end(); + ++perBoneinfit) + { + const std::string& bonename = perBoneinfit->first; + + if (bonename.empty()) + { + OSG_WARN << "RigTransformHardware::VertexInfluenceMap contains unamed bone IndexWeightList" << std::endl; + } + BoneMap::const_iterator bmit = boneMap.find(bonename); + if (bmit == boneMap.end() ) + { + OSG_WARN << "RigTransformHardware Bone " << bonename << " not found, skip the influence group " << std::endl; + localid2bone.push_back(-1); + continue; + } + if ( (boneName2PaletteIndex = _boneNameToPalette.find(bonename)) != _boneNameToPalette.end()) + { + boneNameCountMap[bonename]++; + paletteindex = boneName2PaletteIndex->second ; + } + else + { + boneNameCountMap[bonename] = 1; // for stats + _boneNameToPalette[bonename] = _bonePalette.size() ; + paletteindex = _bonePalette.size() ; + _bonePalette.push_back(bmit->second); + } + localid2bone.push_back(paletteindex); + } + OSG_INFO << "RigTransformHardware::buildPalette matrix palette has " << boneNameCountMap.size() << " entries" << std::endl; + for (BoneNameCountMap::iterator it = boneNameCountMap.begin(); it != boneNameCountMap.end(); ++it) + { + OSG_INFO << "RigTransformHardware::buildPalette Bone " << it->first << " is used " << it->second << " times" << std::endl; + } + OSG_INFO << "RigTransformHardware::buildPalette will use " << boneNameCountMap.size() * 4 << " uniforms" << std::endl; + + ///set paletteindices + for( std::vector::iterator idwlistit = _perVertexInfluences.begin(); idwlistit!=_perVertexInfluences.end(); ++idwlistit) + { + for( IndexWeightList::iterator idwit = idwlistit->begin(); idwit!=idwlistit->end();) + { + if(localid2bone[idwit->first]<0) + idwit = idwlistit->erase(idwit); + else + { + idwit->first = localid2bone[idwit->first]; + ++idwit; + } + } + } + if( (_bonesPerVertex = createVertexAttribList(_perVertexInfluences, _boneWeightAttribArrays) ) < 1 ) + return false; + + _uniformMatrixPalette = new osg::Uniform(osg::Uniform::FLOAT_MAT4, "matrixPalette", _bonePalette.size()); + + _needInit = true; + return true; +} + +bool RigTransformHardware::init(RigGeometry& rig) +{ + if(_perVertexInfluences.empty()) + { + prepareData(rig); return false; } - - if (!geom.getSkeleton()) - { - OSG_WARN << "RigTransformHardware no skeleton set in geometry " << geom.getName() << std::endl; + if(!rig.getSkeleton()) return false; - } - - - // copy shallow from source geometry to rig - geom.copyFrom(source); - BoneMapVisitor mapVisitor; - geom.getSkeleton()->accept(mapVisitor); - BoneMap bm = mapVisitor.getBoneMap(); + rig.getSkeleton()->accept(mapVisitor); + BoneMap boneMap = mapVisitor.getBoneMap(); - if (!createPalette(positionSrc->size(),bm, geom.getVertexInfluenceSet().getVertexToBoneList())) + if (!buildPalette(boneMap,rig) ) return false; - osg::ref_ptr program = new osg::Program; - program->setName("HardwareSkinning"); - if (!_shader.valid()) - _shader = osg::Shader::readShaderFile(osg::Shader::VERTEX,"skinning.vert"); + osg::Geometry& source = *rig.getSourceGeometry(); + osg::Vec3Array* positionSrc = dynamic_cast(source.getVertexArray()); - if (!_shader.valid()) { + if (!positionSrc) + { + OSG_WARN << "RigTransformHardware no vertex array in the geometry " << rig.getName() << std::endl; + return false; + } + + // copy shallow from source geometry to rig + rig.copyFrom(source); + + osg::ref_ptr program ; + osg::ref_ptr vertexshader; + osg::ref_ptr stateset = rig.getOrCreateStateSet(); + + //grab geom source program and vertex shader if _shader is not setted + if(!_shader.valid() && (program = (osg::Program*)stateset->getAttribute(osg::StateAttribute::PROGRAM))) + { + for(unsigned int i = 0; igetNumShaders(); ++i) + if(program->getShader(i)->getType() == osg::Shader::VERTEX) + { + vertexshader = program->getShader(i); + program->removeShader(vertexshader); + } + } + else + { + program = new osg::Program; + program->setName("HardwareSkinning"); + } + //set default source if _shader is not user setted + if (!vertexshader.valid()) + { + if (!_shader.valid()) vertexshader = osgDB::readRefShaderFile(osg::Shader::VERTEX,"skinning.vert"); + else vertexshader = _shader; + } + + if (!vertexshader.valid()) + { OSG_WARN << "RigTransformHardware can't load VertexShader" << std::endl; return false; } // replace max matrix by the value from uniform { - std::string str = _shader->getShaderSource(); - std::string toreplace = std::string("MAX_MATRIX"); - std::size_t start = str.find(toreplace); - if (std::string::npos != start) { - std::stringstream ss; - ss << getMatrixPaletteUniform()->getNumElements(); - str.replace(start, toreplace.size(), ss.str()); - _shader->setShaderSource(str); - } - else - { - OSG_WARN << "MAX_MATRIX not found in Shader! " << str << std::endl; - } - OSG_INFO << "Shader " << str << std::endl; + std::string str = vertexshader->getShaderSource(); + std::string toreplace = std::string("MAX_MATRIX"); + std::size_t start = str.find(toreplace); + if (std::string::npos != start) + { + std::stringstream ss; + ss << getMatrixPaletteUniform()->getNumElements(); + str.replace(start, toreplace.size(), ss.str()); + vertexshader->setShaderSource(str); + } + else + { + OSG_WARN<< "MAX_MATRIX not found in Shader! " << str << std::endl; + } + OSG_INFO << "Shader " << str << std::endl; } - int attribIndex = 11; - int nbAttribs = getNumVertexAttrib(); - for (int i = 0; i < nbAttribs; i++) + unsigned int nbAttribs = getNumVertexAttrib(); + for (unsigned int i = 0; i < nbAttribs; i++) { std::stringstream ss; ss << "boneWeight" << i; - program->addBindAttribLocation(ss.str(), attribIndex + i); - geom.setVertexAttribArray(attribIndex + i, getVertexAttrib(i)); + program->addBindAttribLocation(ss.str(), _minAttribIndex + i); + rig.setVertexAttribArray(_minAttribIndex + i, getVertexAttrib(i)); OSG_INFO << "set vertex attrib " << ss.str() << std::endl; } - program->addShader(_shader.get()); - osg::ref_ptr ss = geom.getOrCreateStateSet(); - ss->addUniform(getMatrixPaletteUniform()); - ss->addUniform(new osg::Uniform("nbBonesPerVertex", getNumBonesPerVertex())); - ss->setAttributeAndModes(program.get()); + program->addShader(vertexshader.get()); + + stateset->removeUniform("nbBonesPerVertex"); + stateset->addUniform(new osg::Uniform("nbBonesPerVertex",_bonesPerVertex)); + + stateset->removeUniform("matrixPalette"); + stateset->addUniform(_uniformMatrixPalette); + + stateset->setAttribute(program.get()); _needInit = false; return true; } + void RigTransformHardware::operator()(RigGeometry& geom) { if (_needInit) diff --git a/src/osgAnimation/RigTransformSoftware.cpp b/src/osgAnimation/RigTransformSoftware.cpp index b9537cf8d..56f6c6477 100644 --- a/src/osgAnimation/RigTransformSoftware.cpp +++ b/src/osgAnimation/RigTransformSoftware.cpp @@ -1,5 +1,6 @@ /* -*-c++-*- * Copyright (C) 2009 Cedric Pinson + * Copyright (C) 2017 Julien Valentin * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or @@ -18,6 +19,8 @@ #include #include +#include + using namespace osgAnimation; RigTransformSoftware::RigTransformSoftware() @@ -33,128 +36,231 @@ RigTransformSoftware::RigTransformSoftware(const RigTransformSoftware& rts,const } -bool RigTransformSoftware::init(RigGeometry& geom) +void RigTransformSoftware::buildMinimumUpdateSet( const RigGeometry&rig ) { - if (!geom.getSkeleton()) + ///1 Create Index2Vec + unsigned int nbVertices=rig.getSourceGeometry()->getVertexArray()->getNumElements(); + const VertexInfluenceMap &vertexInfluenceMap = *rig.getInfluenceMap(); + std::vector perVertexInfluences; + perVertexInfluences.reserve(nbVertices); + perVertexInfluences.resize(nbVertices); + + unsigned int vimapBoneID = 0; + for (osgAnimation::VertexInfluenceMap::const_iterator perBoneinfit = vertexInfluenceMap.begin(); + perBoneinfit != vertexInfluenceMap.end(); + ++perBoneinfit,++vimapBoneID) + { + const IndexWeightList& inflist = perBoneinfit->second; + const std::string& bonename = perBoneinfit->first; + + if (bonename.empty()) + { + OSG_WARN << "RigTransformSoftware::VertexInfluenceMap contains unamed bone IndexWeightList" << std::endl; + } + for(IndexWeightList::const_iterator infit = inflist.begin(); infit!=inflist.end(); ++infit) + { + const VertexIndexWeight &iw = *infit; + const unsigned int &index = iw.first; + float weight = iw.second; + perVertexInfluences[index].push_back(BonePtrWeight(vimapBoneID, weight)); + } + } + + ///2 Create inverse mapping Vec2Vec from previous built Index2Vec + ///in order to minimize weighted matrices computation on update + _uniqVertexGroupList.clear(); + + typedef std::map UnifyBoneGroup; + UnifyBoneGroup unifyBuffer; + unsigned int vertexID = 0; + for (std::vector::iterator perVertinfit = perVertexInfluences.begin(); + perVertinfit!=perVertexInfluences.end(); + ++perVertinfit,++vertexID) + { + BonePtrWeightList &boneinfs = *perVertinfit; + // sort the vector to have a consistent key + std::sort(boneinfs.begin(), boneinfs.end() ); + // we use the vector as key to differentiate group + UnifyBoneGroup::iterator result = unifyBuffer.find(boneinfs); + if (result != unifyBuffer.end()) + result->second.getVertices().push_back(vertexID); + else + { + VertexGroup& vg = unifyBuffer[boneinfs]; + vg.getBoneWeights() = boneinfs; + vg.getVertices().push_back(vertexID); + } + } + + _uniqVertexGroupList.reserve(unifyBuffer.size()); + for (UnifyBoneGroup::const_iterator it = unifyBuffer.begin(); it != unifyBuffer.end(); ++it) + { + _uniqVertexGroupList.push_back(it->second); + } + OSG_INFO << "uniq groups " << _uniqVertexGroupList.size() << " for " << rig.getName() << std::endl; +} + + +bool RigTransformSoftware::prepareData(RigGeometry&rig) +{ + ///set geom as it source + if (rig.getSourceGeometry()) + rig.copyFrom(*rig.getSourceGeometry()); + + osg::Vec3Array* normalSrc = dynamic_cast(rig.getSourceGeometry()->getNormalArray()); + osg::Vec3Array* positionSrc = dynamic_cast(rig.getSourceGeometry()->getVertexArray()); + + if(!(positionSrc) || positionSrc->empty() ) + return false; + if(normalSrc && normalSrc->size() != positionSrc->size()) return false; - BoneMapVisitor mapVisitor; - geom.getSkeleton()->accept(mapVisitor); - BoneMap bm = mapVisitor.getBoneMap(); - initVertexSetFromBones(bm, geom.getVertexInfluenceSet().getUniqVertexSetToBoneSetList()); + /// setup Vertex and Normal arrays with copy of sources + rig.setVertexArray(new osg::Vec3Array); + osg::Vec3Array* positionDst = new osg::Vec3Array; + rig.setVertexArray(positionDst); + *positionDst = *positionSrc; + positionDst->setDataVariance(osg::Object::DYNAMIC); - if (geom.getSourceGeometry()) - geom.copyFrom(*geom.getSourceGeometry()); - geom.setVertexArray(0); - geom.setNormalArray(0); + if(normalSrc) + { + osg::Vec3Array* normalDst = new osg::Vec3Array; + *normalDst = *normalSrc; + rig.setNormalArray(normalDst, osg::Array::BIND_PER_VERTEX); + normalDst->setDataVariance(osg::Object::DYNAMIC); + } + + /// build minimal set of VertexGroup + buildMinimumUpdateSet(rig); + + return true; +} + +bool RigTransformSoftware::init(RigGeometry&rig) +{ + ///test if dataprepared + if(_uniqVertexGroupList.empty()) + { + prepareData(rig); + return false; + } + + if(!rig.getSkeleton()) + return false; + + ///get bonemap from skeleton + BoneMapVisitor mapVisitor; + rig.getSkeleton()->accept(mapVisitor); + BoneMap boneMap = mapVisitor.getBoneMap(); + VertexInfluenceMap & vertexInfluenceMap = *rig.getInfluenceMap(); + + ///create local bonemap + std::vector localid2bone; + localid2bone.reserve(vertexInfluenceMap.size()); + for (osgAnimation::VertexInfluenceMap::const_iterator perBoneinfit = vertexInfluenceMap.begin(); + perBoneinfit != vertexInfluenceMap.end(); + ++perBoneinfit) + { + const std::string& bonename = perBoneinfit->first; + + if (bonename.empty()) + { + OSG_WARN << "RigTransformSoftware::VertexInfluenceMap contains unamed bone IndexWeightList" << std::endl; + } + BoneMap::const_iterator bmit = boneMap.find(bonename); + if (bmit == boneMap.end() ) + { + if (_invalidInfluence.find(bonename) == _invalidInfluence.end()) + { + _invalidInfluence[bonename] = true; + OSG_WARN << "RigTransformSoftware Bone " << bonename << " not found, skip the influence group " << std::endl; + } + + localid2bone.push_back(0); + continue; + } + + Bone* bone = bmit->second.get(); + localid2bone.push_back(bone); + } + + ///fill bone ptr in the _uniqVertexGroupList + for(VertexGroupList::iterator itvg = _uniqVertexGroupList.begin(); itvg != _uniqVertexGroupList.end(); ++itvg) + { + VertexGroup& uniq = *itvg; + for(BonePtrWeightList::iterator bwit = uniq.getBoneWeights().begin(); bwit != uniq.getBoneWeights().end(); ) + { + Bone * b = localid2bone[bwit->getBoneID()]; + if(!b) + bwit = uniq.getBoneWeights().erase(bwit); + else + bwit++->setBonePtr(b); + } + } + + for(VertexGroupList::iterator itvg = _uniqVertexGroupList.begin(); itvg != _uniqVertexGroupList.end(); ++itvg) + { + itvg->normalize(); + } _needInit = false; + return true; } +void RigTransformSoftware::VertexGroup::normalize() +{ + osg::Matrix::value_type sum=0; + for(BonePtrWeightList::iterator bwit = _boneweights.begin(); bwit != _boneweights.end(); ++bwit ) + { + sum += bwit->getWeight(); + } + + if (sum < 1e-4) + { + OSG_WARN << "RigTransformSoftware::VertexGroup: warning try to normalize a zero sum vertexgroup" << std::endl; + } + else + { + for(BonePtrWeightList::iterator bwit = _boneweights.begin(); bwit != _boneweights.end(); ++bwit ) + { + bwit->setWeight(bwit->getWeight()/sum); + } + } +} + void RigTransformSoftware::operator()(RigGeometry& geom) { - if (_needInit) - if (!init(geom)) - return; + if (_needInit && !init(geom)) return; - if (!geom.getSourceGeometry()) { + if (!geom.getSourceGeometry()) + { OSG_WARN << this << " RigTransformSoftware no source geometry found on RigGeometry" << std::endl; return; } + osg::Geometry& source = *geom.getSourceGeometry(); osg::Geometry& destination = geom; - osg::Vec3Array* positionSrc = dynamic_cast(source.getVertexArray()); - osg::Vec3Array* positionDst = dynamic_cast(destination.getVertexArray()); - if (positionSrc ) - { - if (!positionDst || (positionDst->size() != positionSrc->size()) ) - { - if (!positionDst) - { - positionDst = new osg::Vec3Array; - positionDst->setDataVariance(osg::Object::DYNAMIC); - destination.setVertexArray(positionDst); - } - *positionDst = *positionSrc; - } - if (!positionDst->empty()) - { - compute(geom.getMatrixFromSkeletonToGeometry(), - geom.getInvMatrixFromSkeletonToGeometry(), - &positionSrc->front(), - &positionDst->front()); - positionDst->dirty(); - } - - } - + osg::Vec3Array* positionSrc = static_cast(source.getVertexArray()); + osg::Vec3Array* positionDst = static_cast(destination.getVertexArray()); osg::Vec3Array* normalSrc = dynamic_cast(source.getNormalArray()); - osg::Vec3Array* normalDst = dynamic_cast(destination.getNormalArray()); + osg::Vec3Array* normalDst = static_cast(destination.getNormalArray()); + + + compute(geom.getMatrixFromSkeletonToGeometry(), + geom.getInvMatrixFromSkeletonToGeometry(), + &positionSrc->front(), + &positionDst->front()); + positionDst->dirty(); + if (normalSrc ) { - if (!normalDst || (normalDst->size() != normalSrc->size()) ) - { - if (!normalDst) - { - normalDst = new osg::Vec3Array; - normalDst->setDataVariance(osg::Object::DYNAMIC); - destination.setNormalArray(normalDst, osg::Array::BIND_PER_VERTEX); - } - *normalDst = *normalSrc; - } - if (!normalDst->empty()) - { - computeNormal(geom.getMatrixFromSkeletonToGeometry(), - geom.getInvMatrixFromSkeletonToGeometry(), - &normalSrc->front(), - &normalDst->front()); - normalDst->dirty(); - } + computeNormal(geom.getMatrixFromSkeletonToGeometry(), + geom.getInvMatrixFromSkeletonToGeometry(), + &normalSrc->front(), + &normalDst->front()); + normalDst->dirty(); } } - -void RigTransformSoftware::initVertexSetFromBones(const BoneMap& map, const VertexInfluenceSet::UniqVertexSetToBoneSetList& influence) -{ - _boneSetVertexSet.clear(); - - int size = influence.size(); - _boneSetVertexSet.resize(size); - for (int i = 0; i < size; i++) - { - const VertexInfluenceSet::UniqVertexSetToBoneSet& inf = influence[i]; - int nbBones = inf.getBones().size(); - BoneWeightList& boneList = _boneSetVertexSet[i].getBones(); - - double sumOfWeight = 0; - for (int b = 0; b < nbBones; b++) - { - const std::string& bname = inf.getBones()[b].getBoneName(); - float weight = inf.getBones()[b].getWeight(); - BoneMap::const_iterator it = map.find(bname); - if (it == map.end() ) - { - if (_invalidInfluence.find(bname) != _invalidInfluence.end()) { - _invalidInfluence[bname] = true; - OSG_WARN << "RigTransformSoftware Bone " << bname << " not found, skip the influence group " <second.get(); - boneList.push_back(BoneWeight(bone, weight)); - sumOfWeight += weight; - } - // if a bone referenced by a vertexinfluence is missed it can make the sum less than 1.0 - // so we check it and renormalize the all weight bone - const double threshold = 1e-4; - if (!_boneSetVertexSet[i].getBones().empty() && - (sumOfWeight < 1.0 - threshold || sumOfWeight > 1.0 + threshold)) - { - for (int b = 0; b < (int)boneList.size(); b++) - boneList[b].setWeight(boneList[b].getWeight() / sumOfWeight); - } - _boneSetVertexSet[i].getVertexes() = inf.getVertexes(); - } -} diff --git a/src/osgAnimation/StatsHandler.cpp b/src/osgAnimation/StatsHandler.cpp index 3387beb27..161634ba2 100644 --- a/src/osgAnimation/StatsHandler.cpp +++ b/src/osgAnimation/StatsHandler.cpp @@ -409,7 +409,6 @@ struct ValueTextDrawCallback : public virtual osg::Drawable::DrawCallback if (!visitor) return; - std::string font("fonts/arial.ttf"); float leftPos = 10.0f; float characterSize = 20.0f; @@ -427,7 +426,7 @@ struct ValueTextDrawCallback : public virtual osg::Drawable::DrawCallback } const std::vector& channels = visitor->getChannels(); - std::map size; + // std::map size; for (int i = 0; i < (int)channels.size(); i++) { std::string name = channels[i]; if (_actions.find(name) == _actions.end()) { @@ -440,14 +439,14 @@ struct ValueTextDrawCallback : public virtual osg::Drawable::DrawCallback //_actions[name].touch(); } _actions[name]._group->setNodeMask(~osg::Node::NodeMask(0x0)); - size[name] = 0; + //size[name] = 0; pos.y() -= characterSize + graphSpacing; } pos.y() -= backgroundMargin; osg::Vec3Array* array = static_cast(_background->getVertexArray()); - float y = (*array)[0][1]; - y = y - (pos.y() + backgroundMargin); //(2 * backgroundMargin + (size.size() * (characterSize + graphSpacing))); + // float y = (*array)[0][1]; + // y = y - (pos.y() + backgroundMargin); //(2 * backgroundMargin + (size.size() * (characterSize + graphSpacing))); (*array)[1][1] = pos.y(); (*array)[2][1] = pos.y(); array->dirty(); diff --git a/src/osgAnimation/StatsVisitor.cpp b/src/osgAnimation/StatsVisitor.cpp index 48ee26797..d99b96967 100644 --- a/src/osgAnimation/StatsVisitor.cpp +++ b/src/osgAnimation/StatsVisitor.cpp @@ -77,10 +77,6 @@ void StatsActionVisitor::apply(ActionStripAnimation& action) if (isActive(action)) { _channels.push_back(action.getName()); - double value; - std::string name = action.getName(); - if (_stats->getAttribute(_frame, name, value)) - name += "+"; _stats->setAttribute(_frame, action.getName(), action.getAnimation()->getAnimation()->getWeight()); } } diff --git a/src/osgAnimation/VertexInfluence.cpp b/src/osgAnimation/VertexInfluence.cpp index ad1686277..75a7b22a6 100644 --- a/src/osgAnimation/VertexInfluence.cpp +++ b/src/osgAnimation/VertexInfluence.cpp @@ -1,5 +1,6 @@ /* -*-c++-*- * Copyright (C) 2008 Cedric Pinson + * Copyright (C) 2017 Julien Valentin * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or @@ -13,77 +14,162 @@ */ #include +#include +#include #include #include #include +#include using namespace osgAnimation; -void VertexInfluenceSet::addVertexInfluence(const VertexInfluence& v) { _bone2Vertexes.push_back(v); } -const VertexInfluenceSet::VertexIndexToBoneWeightMap& VertexInfluenceSet::getVertexToBoneList() const { return _vertex2Bones;} -// this class manage VertexInfluence database by mesh -// reference bones per vertex ... -void VertexInfluenceSet::buildVertex2BoneList() +struct invweight_ordered { - _vertex2Bones.clear(); - for (BoneToVertexList::const_iterator it = _bone2Vertexes.begin(); it != _bone2Vertexes.end(); ++it) + inline bool operator() (const BoneWeight& bw1, const BoneWeight& bw2) const { - const VertexInfluence& vi = (*it); - int size = vi.size(); - for (int i = 0; i < size; i++) + if (bw1.second > bw2.second)return true; + if (bw1.second < bw2.second)return false; + return(bw1.first < bw2.first); + } +}; + +void VertexInfluenceMap::normalize(unsigned int numvert) +{ + + typedef std::pair > PerVertWeights; + std::vector localstore; + localstore.resize(numvert); + for(VertexInfluenceMap::iterator mapit = this->begin(); mapit != this->end(); ++mapit) + { + IndexWeightList &curvecinf = mapit->second; + for(IndexWeightList::iterator curinf = curvecinf.begin(); curinf != curvecinf.end(); ++curinf) { - VertexIndexWeight viw = vi[i]; - int index = viw.first; - float weight = viw.second; - if (vi.getName().empty()) - OSG_WARN << "VertexInfluenceSet::buildVertex2BoneList warning vertex " << index << " is not assigned to a bone" << std::endl; - _vertex2Bones[index].push_back(BoneWeight(vi.getName(), weight)); + VertexIndexWeight& inf = *curinf; + localstore[inf.first].first += inf.second; + localstore[inf.first].second.push_back(&inf.second); } } - - // normalize weight per vertex - for (VertexIndexToBoneWeightMap::iterator it = _vertex2Bones.begin(); it != _vertex2Bones.end(); ++it) + + unsigned int vertid = 0; + for(std::vector::iterator itvert = localstore.begin(); + itvert != localstore.end(); + ++itvert, ++vertid) { - BoneWeightList& bones = it->second; - int size = bones.size(); - float sum = 0; - for (int i = 0; i < size; i++) - sum += bones[i].getWeight(); - if (sum < 1e-4) + PerVertWeights & weights = *itvert; + if(weights.first< 1e-4) { - OSG_WARN << "VertexInfluenceSet::buildVertex2BoneList warning the vertex " << it->first << " seems to have 0 weight, skip normalize for this vertex" << std::endl; + OSG_WARN << "VertexInfluenceMap::normalize warning the vertex " <::iterator itf = weights.second.begin(); itf != weights.second.end(); ++itf) + { + **itf *= mult; + } + } + } + +} +///remove weakest influences in order to fit targetted numbonepervertex +void VertexInfluenceMap::cullInfluenceCountPerVertex(unsigned int numbonepervertex,float minweight, bool renormalize) +{ + + typedef std::set BoneWeightOrdered; + std::map tempVec2Bones; + for(VertexInfluenceMap::iterator mapit = this->begin(); mapit != this->end(); ++mapit) + { + const std::string& bonename = mapit->first; + IndexWeightList &curvecinf = mapit->second; + for(IndexWeightList::iterator curinf = curvecinf.begin(); curinf != curvecinf.end(); ++curinf) + { + VertexIndexWeight& inf = *curinf; + if( bonename.empty()) + { + OSG_WARN << "VertexInfluenceSet::cullInfluenceCountPerVertex warning vertex " << inf.first << " is not assigned to a bone" << std::endl; + } + else if(inf.second>minweight) + { + tempVec2Bones[inf.first].insert(BoneWeight(bonename, inf.second)); + } + } + } + this->clear(); + for( std::map::iterator mapit = tempVec2Bones.begin(); mapit != tempVec2Bones.end(); ++mapit) + { + BoneWeightOrdered& bwset = mapit->second; + unsigned int newsize = numbonepervertexnewsize)bwset.erase(*bwset.rbegin()); + if(renormalize) + { + for(BoneWeightOrdered::iterator bwit = bwset.begin(); bwit != bwset.end(); ++bwit) + { + sum += bwit->second; + } + + if(sum > 1e-4) + { + sum = 1.0f/sum; + for(BoneWeightOrdered::iterator bwit = bwset.begin(); bwit != bwset.end(); ++bwit) + { + VertexInfluence & inf = (*this)[bwit->first]; + inf.push_back(VertexIndexWeight(mapit->first, bwit->second*sum)); + inf.setName(bwit->first); + } + } + } + else + { + for(BoneWeightOrdered::iterator bwit = bwset.begin(); bwit != bwset.end(); ++bwit) + { + VertexInfluence & inf = (*this)[bwit->first]; + inf.push_back(VertexIndexWeight(mapit->first,bwit->second)); + inf.setName(bwit->first); + } } } } - +void VertexInfluenceMap::computePerVertexInfluenceList(std::vector& vertex2Bones,unsigned int numvert)const +{ + vertex2Bones.resize(numvert); + for (osgAnimation::VertexInfluenceMap::const_iterator it = begin(); it != end(); ++it) + { + const IndexWeightList& inflist = it->second; + if (it->first.empty()) + { + OSG_WARN << "VertexInfluenceMap::computePerVertexInfluenceList contains unamed bone IndexWeightList" << std::endl; + } + + for(IndexWeightList::const_iterator infit = inflist.begin(); infit != inflist.end(); ++infit) + { + const VertexIndexWeight &iw = *infit; + const unsigned int &index = iw.first; + const float &weight = iw.second; + vertex2Bones[index].push_back(BoneWeight(it->first, weight));; + } + } +} // sort by name and weight -struct SortByNameAndWeight : public std::less +struct SortByNameAndWeight : public std::less { - bool operator()(const VertexInfluenceSet::BoneWeight& b0, - const VertexInfluenceSet::BoneWeight& b1) const + bool operator()(const BoneWeight& b0, const BoneWeight& b1) const { - if (b0.getBoneName() < b1.getBoneName()) + if (b0.first < b1.first) return true; - else if (b0.getBoneName() > b1.getBoneName()) + else if (b0.first > b1.first) return false; - if (b0.getWeight() < b1.getWeight()) - return true; - return false; + + return (b0.second < b1.second); } }; -struct SortByBoneWeightList : public std::less +struct SortByBoneWeightList : public std::less { - bool operator()(const VertexInfluenceSet::BoneWeightList& b0, - const VertexInfluenceSet::BoneWeightList& b1) const + bool operator()(const BoneWeightList& b0, + const BoneWeightList& b1) const { if (b0.size() < b1.size()) return true; @@ -93,8 +179,7 @@ struct SortByBoneWeightList : public std::less& uniqVertexGroupList, unsigned int numvert) const { - _bone2Vertexes.clear(); - _uniqVertexSetToBoneSet.clear(); -} - -void VertexInfluenceSet::buildUniqVertexSetToBoneSetList() -{ - _uniqVertexSetToBoneSet.clear(); - - typedef std::map UnifyBoneGroup; + uniqVertexGroupList.clear(); + std::vector vertex2Bones; + computePerVertexInfluenceList(vertex2Bones,numvert); + typedef std::map UnifyBoneGroup; UnifyBoneGroup unifyBuffer; - for (VertexIndexToBoneWeightMap::iterator it = _vertex2Bones.begin(); it != _vertex2Bones.end(); ++it) + unsigned int vertexID = 0; + for (std::vector::iterator it = vertex2Bones.begin(); it != vertex2Bones.end(); ++it,++vertexID) { - BoneWeightList bones = it->second; - int vertexIndex = it->first; - + BoneWeightList &boneweightlist = *it; // sort the vector to have a consistent key - std::sort(bones.begin(), bones.end(), SortByNameAndWeight()); - + std::sort(boneweightlist.begin(), boneweightlist.end(), SortByNameAndWeight()); + // we use the vector as key to differentiate group - UnifyBoneGroup::iterator result = unifyBuffer.find(bones); + UnifyBoneGroup::iterator result = unifyBuffer.find(boneweightlist); if (result == unifyBuffer.end()) - unifyBuffer[bones].setBones(bones); - unifyBuffer[bones].getVertexes().push_back(vertexIndex); + { + unifyBuffer[boneweightlist].setBoneWeights(boneweightlist); + } + + unifyBuffer[boneweightlist].vertIDs().push_back(vertexID); } - - _uniqVertexSetToBoneSet.reserve(unifyBuffer.size()); + + if(vertex2Bones.size() == unifyBuffer.size()) + { + OSG_WARN << "VertexInfluenceMap::computeMinimalVertexGroupList is useless no duplicate VertexGroup" << std::endl; + } + + uniqVertexGroupList.reserve(unifyBuffer.size()); for (UnifyBoneGroup::iterator it = unifyBuffer.begin(); it != unifyBuffer.end(); ++it) { - _uniqVertexSetToBoneSet.push_back(it->second); + uniqVertexGroupList.push_back(it->second); } } +//Experimental Bone removal stuff +typedef std::vector RigList; +class CollectRigVisitor : public osg::NodeVisitor +{ +public: + META_NodeVisitor(osgAnimation, CollectRigVisitor) + CollectRigVisitor(); + + void apply(osg::Geometry& node); + inline const RigList& getRigList() const{return _map;} + +protected: + RigList _map; +}; + +CollectRigVisitor::CollectRigVisitor() : osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) {} + +void CollectRigVisitor::apply(osg::Geometry& node) +{ + RigGeometry* rig = dynamic_cast(&node); + if ( rig ) + _map.push_back(rig); +} + +bool recursiveisUsefull( Bone* bone, std::set foundnames) +{ + for(unsigned int i=0; igetNumChildren(); ++i) + { + Bone* child = dynamic_cast< Bone* >(bone->getChild(i)); + if(child) + { + if( foundnames.find(child->getName()) != foundnames.end() ) + return true; + if( recursiveisUsefull(child,foundnames) ) + return true; + } + } + return false; +} + +void VertexInfluenceMap::removeUnexpressedBones(Skeleton &skel) const +{ + BoneMapVisitor mapVisitor; + skel.accept(mapVisitor); + + CollectRigVisitor rigvis; + skel.accept(rigvis); + + RigList rigs = rigvis.getRigList(); + BoneMap boneMap = mapVisitor.getBoneMap(); + + unsigned int removed=0; + Bone* child, *par; + + std::set usebones; + for(RigList::iterator rigit = rigs.begin(); rigit != rigs.end(); ++rigit) + { + for(VertexInfluenceMap::iterator mapit = (*rigit)->getInfluenceMap()->begin(); + mapit != (*rigit)->getInfluenceMap()->end(); + ++mapit) + { + usebones.insert((*mapit).first); + } + } + + for(BoneMap::iterator bmit = boneMap.begin(); bmit != boneMap.end();) + { + if(usebones.find(bmit->second->getName()) == usebones.end()) + { + if( !(par = bmit->second->getBoneParent()) ) + { + ++bmit; + continue; + } + + Bone * bone2rm = bmit->second.get(); + + if( recursiveisUsefull(bone2rm,usebones)) + { + ++bmit; + continue; + } + + ///Bone can be removed + ++ removed; + OSG_INFO<<"removing useless bone: "<< bone2rm->getName() <getNumChildren(); numchild++) + { + if( (child = dynamic_cast(bone2rm->getChild(numchild))) ) + { + if(par!=child &&child!=bone2rm) + { + par->addChild(child); + nodes.push_back(child); + } + } + } + + for(unsigned int i=0; iremoveChild(nodes[i]); + } + par->removeChild(bone2rm); + + ///rebuild bonemap after bone removal + BoneMapVisitor mapVis ; + skel.accept(mapVis); + boneMap = mapVis.getBoneMap(); + bmit = boneMap.begin(); + + } + else + { + ++bmit; + } + } + OSG_WARN<<"Number of bone removed "< #ifdef WIN32 -#if !defined(__MINGW32__) - #define _WIN32_WINNT 0x0500 -#endif #include #endif diff --git a/src/osgDB/InputStream.cpp b/src/osgDB/InputStream.cpp index e1cdb734d..4b3b8c2e2 100644 --- a/src/osgDB/InputStream.cpp +++ b/src/osgDB/InputStream.cpp @@ -709,7 +709,12 @@ osg::ref_ptr InputStream::readImage(bool readFromExternal) char* data = new char[size]; if ( !data ) throwException( "InputStream::readImage() Out of memory." ); - if ( getException() ) return NULL; + + if ( getException() ) + { + delete [] data; + return NULL; + } readCharArray( data, size ); image = new osg::Image; diff --git a/src/osgDB/OutputStream.cpp b/src/osgDB/OutputStream.cpp index a21b74fa2..8b28092f2 100644 --- a/src/osgDB/OutputStream.cpp +++ b/src/osgDB/OutputStream.cpp @@ -860,7 +860,6 @@ void OutputStream::writeSchema( std::ostream& fout ) ObjectWrapper::TypeList types; wrapper->writeSchema( properties, types ); - std::string propertiesString; unsigned int size = osg::minimum( properties.size(), types.size() ); for ( unsigned int i=0; irdstate()&_in->failbit) { OSG_NOTICE<<"InputIterator::checkStream() : _in->rdstate() "<<_in->rdstate()<<", "<<_in->failbit<tellg() = "<<_in->tellg()<addChild(meshTransform); - } else { + } + else + { meshTransform=group; // don't need the meshTransform node - note group can be NULL } @@ -619,18 +623,21 @@ osg::Node* ReaderWriter3DS::ReaderObject::processNode(StateSetMap& drawStateMap, { // add our geometry to group (where our children already are) // creates geometry under modifier node - processMesh(drawStateMap,meshTransform,mesh,meshAppliedMatPtr); + processMesh(drawStateMap, meshTransform, mesh, meshAppliedMatPtr); return group; } else { // didn't use group for children, return a ptr directly to the Geode for this mesh // there is no group node but may have a meshTransform node to hold the meshes matrix - if (meshTransform) { - processMesh(drawStateMap,meshTransform,mesh,meshAppliedMatPtr); + if (meshTransform) + { + processMesh(drawStateMap, meshTransform, mesh, meshAppliedMatPtr); return meshTransform; - } else { // no group or meshTransform nodes - create a new Geode and return that - return processMesh(drawStateMap,NULL,mesh,meshAppliedMatPtr); + } + else + { // no group or meshTransform nodes - create a new Geode and return that + return processMesh(drawStateMap, NULL, mesh, meshAppliedMatPtr); } } diff --git a/src/osgPlugins/3ds/lib3ds/lib3ds_file.c b/src/osgPlugins/3ds/lib3ds/lib3ds_file.c index d9cbb0b71..3a0a66fef 100644 --- a/src/osgPlugins/3ds/lib3ds/lib3ds_file.c +++ b/src/osgPlugins/3ds/lib3ds/lib3ds_file.c @@ -549,35 +549,38 @@ kfdata_read(Lib3dsFile *file, Lib3dsIo *io) { { Lib3dsNode **nodes = (Lib3dsNode **)malloc(num_nodes * sizeof(Lib3dsNode*)); - unsigned i; - Lib3dsNode *p, *q, *parent; + if (nodes) + { + unsigned i; + Lib3dsNode *p, *q, *parent; - p = file->nodes; - for (i = 0; i < num_nodes; ++i) { - nodes[i] = p; - p = p->next; - } - qsort(nodes, num_nodes, sizeof(Lib3dsNode*), compare_node_id); - - p = last; - while (p) { - q = (Lib3dsNode *)p->user_ptr; - if (p->user_id != 65535) { - parent = *(Lib3dsNode**)bsearch(&p->user_id, nodes, num_nodes, sizeof(Lib3dsNode*), compare_node_id2); - if (parent) { - q->next = p->next; - p->next = parent->childs; - p->parent = parent; - parent->childs = p; - } else { - /* TODO: warning */ - } + p = file->nodes; + for (i = 0; i < num_nodes; ++i) { + nodes[i] = p; + p = p->next; } - p->user_id = 0; - p->user_ptr = NULL; - p = q; + qsort(nodes, num_nodes, sizeof(Lib3dsNode*), compare_node_id); + + p = last; + while (p) { + q = (Lib3dsNode *)p->user_ptr; + if (p->user_id != 65535) { + parent = *(Lib3dsNode**)bsearch(&p->user_id, nodes, num_nodes, sizeof(Lib3dsNode*), compare_node_id2); + if (parent) { + q->next = p->next; + p->next = parent->childs; + p->parent = parent; + parent->childs = p; + } else { + /* TODO: warning */ + } + } + p->user_id = 0; + p->user_ptr = NULL; + p = q; + } + free(nodes); } - free(nodes); } lib3ds_chunk_read_end(&c, io); diff --git a/src/osgPlugins/3ds/lib3ds/lib3ds_mesh.c b/src/osgPlugins/3ds/lib3ds/lib3ds_mesh.c index 99f340003..e4c9775a6 100644 --- a/src/osgPlugins/3ds/lib3ds/lib3ds_mesh.c +++ b/src/osgPlugins/3ds/lib3ds/lib3ds_mesh.c @@ -170,7 +170,17 @@ lib3ds_mesh_calculate_vertex_normals(Lib3dsMesh *mesh, float (*normals)[3]) { } fl = (Lib3dsFaces**)calloc(sizeof(Lib3dsFaces*), mesh->nvertices); + if (!fl) + { + return; + } + fa = (Lib3dsFaces*)malloc(sizeof(Lib3dsFaces) * 3 * mesh->nfaces); + if (!fa) + { + free(fl); + return; + } for (i = 0; i < mesh->nfaces; ++i) { for (j = 0; j < 3; ++j) { diff --git a/src/osgPlugins/bsp/Q3BSPReader.cpp b/src/osgPlugins/bsp/Q3BSPReader.cpp index 9e90b2abc..fd8bddde6 100644 --- a/src/osgPlugins/bsp/Q3BSPReader.cpp +++ b/src/osgPlugins/bsp/Q3BSPReader.cpp @@ -36,8 +36,6 @@ Q3BSPReader::Q3BSPReader() bool Q3BSPReader::readFile(const std::string& file, const osgDB::ReaderWriter::Options* options) { - std::string ext = osgDB::getLowerCaseFileExtension(file); - Q3BSPLoad load_data; load_data.Load(file,8); @@ -513,7 +511,7 @@ bool Q3BSPReader::loadLightMaps( - // A continuación, añado el blanco + // A continuacin, aado el blanco osg::Image* image=new osg::Image; unsigned char *data=new unsigned char[3]; for(int whiteidx=0;whiteidx<3;whiteidx++) diff --git a/src/osgPlugins/bsp/VBSPReader.cpp b/src/osgPlugins/bsp/VBSPReader.cpp index 90fdfa022..172013581 100644 --- a/src/osgPlugins/bsp/VBSPReader.cpp +++ b/src/osgPlugins/bsp/VBSPReader.cpp @@ -653,8 +653,6 @@ ref_ptr VBSPReader::readMaterialFile(std::string materialName) bool found = false; ref_ptr stateSet; std::string shaderName; - std::string texName; - std::string tex2Name; ref_ptr texture; ref_ptr texture2; ref_ptr combiner0; @@ -992,7 +990,6 @@ void VBSPReader::createScene() Quat yaw, pitch, roll; ref_ptr propXform; std::string propModel; - std::string propFile; ref_ptr propNode; // Load the materials and create a StateSet for each one diff --git a/src/osgPlugins/dae/daeRMaterials.cpp b/src/osgPlugins/dae/daeRMaterials.cpp index 158ca35ef..d4c2703b2 100644 --- a/src/osgPlugins/dae/daeRMaterials.cpp +++ b/src/osgPlugins/dae/daeRMaterials.cpp @@ -589,8 +589,6 @@ bool daeReader::processColorOrTextureType(const osg::StateSet* ss, } bool retVal = false; - std::string texCoordSet; - //osg::StateAttribute *sa = NULL; //TODO: Make all channels process type of value if (channel == osg::Material::EMISSION ) @@ -1017,6 +1015,11 @@ osg::Texture2D* daeReader::processTexture( domFx_surface_common *surface = NULL; domImage *dImg = NULL; + if(tex->getTexture() == NULL) + { + return NULL; + } + std::string target = std::string("./") + std::string(tex->getTexture()); OSG_INFO<<"processTexture("<getTexcoord(); + if(tex->getTexcoord() != NULL) + { + _texCoordSetMap[TextureToCoordSetMap::key_type(ss, tuu)] = tex->getTexcoord(); + } return t2D; } diff --git a/src/osgPlugins/dae/daeRSceneObjects.cpp b/src/osgPlugins/dae/daeRSceneObjects.cpp index 9874ed315..9096345a4 100644 --- a/src/osgPlugins/dae/daeRSceneObjects.cpp +++ b/src/osgPlugins/dae/daeRSceneObjects.cpp @@ -361,7 +361,7 @@ osg::Node* daeReader::processLight( domLight *dlight ) lightmodel->setAmbientIntensity(osg::Vec4(0.0f,0.0f,0.0f,1.0f)); _rootStateSet->setAttributeAndModes(lightmodel, osg::StateAttribute::ON); - osg::LightSource* lightsource = new osg::LightSource(); + osg::ref_ptr lightsource = new osg::LightSource(); lightsource->setLight(light); std::string name = dlight->getId() ? dlight->getId() : ""; if (dlight->getName()) @@ -520,7 +520,7 @@ osg::Node* daeReader::processLight( domLight *dlight ) light->setDirection(osg::Vec3(0, 0, -1)); } - return lightsource; + return lightsource.release(); } // diff --git a/src/osgPlugins/dot/BaseDotVisitor.cpp b/src/osgPlugins/dot/BaseDotVisitor.cpp index 3aec31ac2..0a4804495 100644 --- a/src/osgPlugins/dot/BaseDotVisitor.cpp +++ b/src/osgPlugins/dot/BaseDotVisitor.cpp @@ -24,8 +24,11 @@ using namespace osg; namespace osgDot { - BaseDotVisitor::BaseDotVisitor() - { +BaseDotVisitor::BaseDotVisitor(): + osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) +{ + // setNodeMaskOverride(0xffffff); + _rankdir = "rankdir = LR;"; // Set the locale used by the _nodes and _edges streams to the // classic or "C" locale. This is needed because most of the @@ -33,156 +36,145 @@ namespace osgDot { // by id numbers containing commas or periods. _nodes.imbue(std::locale("C")); _edges.imbue(std::locale("C")); - } +} - BaseDotVisitor::~BaseDotVisitor() { - } +BaseDotVisitor::~BaseDotVisitor() +{ +} - void BaseDotVisitor::setOptions(const osgDB::Options* options) +void BaseDotVisitor::setOptions(const osgDB::Options* options) +{ + _options = const_cast(options); + OSG_INFO<<"BaseDotVisitor::setOptions("<getOptionString().empty())) { - _options = const_cast(options); - OSG_INFO<<"BaseDotVisitor::setOptions("<getOptionString().empty())) + + std::string optionString = _options->getOptionString(); + + OSG_INFO<<" BaseDotVisitor::optionString ("<getOptionString(); - - OSG_INFO<<" BaseDotVisitor::optionString ("<getStateSet(); - if ( s ) { - int id3; - if ( getOrCreateId( s, id3 ) ) { - handle( *s, id3 ); - } - handle( *drawable, *s, id2, id3 ); - } - } - handle( node, *drawable, id, id2 ); - } - + if ( getOrCreateId( &drawable, id ) ) + { + handle( drawable, id ); + handleNodeAndTraverse( drawable, id ); } +} - } - - void BaseDotVisitor::apply(Group& node) { +void BaseDotVisitor::apply(Group& node) +{ int id; - if ( getOrCreateId( &node, id ) ) { - handle( node, id ); - handleNodeAndTraverse( node, id ); + if ( getOrCreateId( &node, id ) ) + { + handle( node, id ); + handleNodeAndTraverse( node, id ); - unsigned int i; - for ( i = 0; i < node.getNumChildren(); i++ ) { - osg::Node* child = node.getChild( i ); - //handleNodeAndTraverse( *child ); - int id2; - if (getOrCreateId( child, id2 )) + unsigned int i; + for ( i = 0; i < node.getNumChildren(); i++ ) { + osg::Node* child = node.getChild( i ); + //handleNodeAndTraverse( *child ); + int id2; + getOrCreateId( child, id2 ); handle( node, *child, id, id2 ); } - } } +} - } +void BaseDotVisitor::handle(osg::Node&, int) {} - void BaseDotVisitor::handle(osg::Node&, int) {} +void BaseDotVisitor::handle(osg::Group&, int) {} - void BaseDotVisitor::handle(osg::Geode&, int) {} +void BaseDotVisitor::handle(osg::Group&, osg::Node&, int, int) {} - void BaseDotVisitor::handle(osg::Group&, int) {} - - void BaseDotVisitor::handle(osg::Group&, osg::Node&, int, int) {} - - void BaseDotVisitor::handleNodeAndTraverse(osg::Node& node, int id) { +void BaseDotVisitor::handleNodeAndTraverse(osg::Node& node, int id) +{ osg::StateSet* ss = node.getStateSet(); - if ( ss ) { - int id2; - if ( getOrCreateId( ss, id2 ) ) { - handle( *ss, id2 ); - } - handle( node, *ss, id, id2 ); + if ( ss ) + { + int id2; + if ( getOrCreateId( ss, id2 ) ) + { + handle( *ss, id2 ); + } + handle( node, *ss, id, id2 ); } traverse(node); - } +} - void BaseDotVisitor::handle(osg::StateSet&, int) {} +void BaseDotVisitor::handle(osg::StateSet&, int) {} - void BaseDotVisitor::handle(osg::Node&, osg::StateSet&, int, int) {} +void BaseDotVisitor::handle(osg::Node&, osg::StateSet&, int, int) {} - void BaseDotVisitor::handle(osg::Drawable&, int) {} +void BaseDotVisitor::handle(osg::Drawable&, int) {} - void BaseDotVisitor::handle(osg::Drawable&, osg::StateSet&, int, int) {} +void BaseDotVisitor::handle(osg::Drawable&, osg::StateSet&, int, int) {} - void BaseDotVisitor::handle(osg::Geode&, osg::Drawable&, int, int) {} - - bool BaseDotVisitor::getOrCreateId( osg::Object* object, int &id ) { - assert( object ); +bool BaseDotVisitor::getOrCreateId( osg::Object* object, int &id ) +{ ObjectMap::iterator it = _objectMap.find( object ); - if ( it != _objectMap.end() ) { - id = it->second; - return false; + if ( it != _objectMap.end() ) + { + id = it->second; + return false; } id = _objectMap.size(); _objectMap[ object ] = id; return true; - } +} } // namespace osgDot diff --git a/src/osgPlugins/dot/BaseDotVisitor.h b/src/osgPlugins/dot/BaseDotVisitor.h index 87b06662a..d0e2b2737 100644 --- a/src/osgPlugins/dot/BaseDotVisitor.h +++ b/src/osgPlugins/dot/BaseDotVisitor.h @@ -30,54 +30,52 @@ namespace osgDot { - class BaseDotVisitor : public osg::NodeVisitor { - public: - typedef std::map< osg::Object*, int > ObjectMap; +class BaseDotVisitor : public osg::NodeVisitor +{ + public: + typedef std::map< osg::Object*, int > ObjectMap; - public: - BaseDotVisitor(); + public: + BaseDotVisitor(); - virtual ~BaseDotVisitor(); + virtual ~BaseDotVisitor(); - void setOptions(const osgDB::Options* options); + void setOptions(const osgDB::Options* options); - bool run( osg::Node& root, std::ostream* ostream ); + bool run( osg::Node& root, std::ostream* ostream ); - virtual void apply(osg::Node& node); + virtual void apply(osg::Node& node); - virtual void apply(osg::Geode& node); + virtual void apply(osg::Drawable& node); - virtual void apply(osg::Group& node); + virtual void apply(osg::Group& node); + protected: - protected: + void handleNodeAndTraverse(osg::Node& node, int id); - void handleNodeAndTraverse(osg::Node& node, int id); + virtual void handle(osg::StateSet& stateset, int id); + virtual void handle(osg::Drawable& drawable, int id); + virtual void handle(osg::Node& node, int id); + virtual void handle(osg::Group& node, int id); - virtual void handle(osg::Node& node, int id); - virtual void handle(osg::Geode& node, int id); - virtual void handle(osg::Group& node, int id); - virtual void handle(osg::StateSet& stateset, int id); - virtual void handle(osg::Drawable& drawable, int id); + virtual void handle(osg::Node& node, osg::StateSet& stateset, int parentID, int childID); + virtual void handle(osg::Drawable& drawable, osg::StateSet& stateset, int parentID, int childID ); + virtual void handle(osg::Group& parent, osg::Node& child, int parentID, int childID); - virtual void handle(osg::Node& node, osg::StateSet& stateset, int parentID, int childID); - virtual void handle(osg::Group& parent, osg::Node& child, int parentID, int childID); - virtual void handle(osg::Geode& geode, osg::Drawable& drawable, int parentID, int childID); - virtual void handle(osg::Drawable& drawable, osg::StateSet& stateset, int parentID, int childID ); + osg::ref_ptr _options; - osg::ref_ptr _options; + std::string _rankdir; - std::string _rankdir; + std::stringstream _nodes; + std::stringstream _edges; - std::stringstream _nodes; - std::stringstream _edges; + private: + bool getOrCreateId( osg::Object* object, int& id ); - private: - bool getOrCreateId( osg::Object* object, int& id ); + ObjectMap _objectMap; - ObjectMap _objectMap; - - }; +}; } // namespace osgDot diff --git a/src/osgPlugins/dot/ReaderWriterDOT.cpp b/src/osgPlugins/dot/ReaderWriterDOT.cpp index 575ee481e..c03079738 100644 --- a/src/osgPlugins/dot/ReaderWriterDOT.cpp +++ b/src/osgPlugins/dot/ReaderWriterDOT.cpp @@ -17,6 +17,7 @@ class ReaderWriterDOT : public osgDB::ReaderWriter { public: + virtual const char* className() const { return "DOT Writer"; } virtual bool acceptsExtension(const std::string& extension) const { return osgDB::equalCaseInsensitive(extension,"dot"); } diff --git a/src/osgPlugins/dot/SimpleDotVisitor.cpp b/src/osgPlugins/dot/SimpleDotVisitor.cpp index 60fad98d0..075a6445a 100644 --- a/src/osgPlugins/dot/SimpleDotVisitor.cpp +++ b/src/osgPlugins/dot/SimpleDotVisitor.cpp @@ -15,79 +15,80 @@ namespace osgDot { - SimpleDotVisitor::SimpleDotVisitor() { - } +SimpleDotVisitor::SimpleDotVisitor() +{ +} - SimpleDotVisitor::~SimpleDotVisitor() { - } +SimpleDotVisitor::~SimpleDotVisitor() +{ +} - void SimpleDotVisitor::handle(osg::Node& node, int id) { - std::stringstream label; - label << " Node"; - if ( !node.getName().empty() ) { label << "| " << node.getName(); } - drawNode( id, "record", "solid", label.str(), "black", "white" ); - } - void SimpleDotVisitor::handle(osg::Geode& node, int id) { - std::stringstream label; - label << " " << node.className(); - if ( !node.getName().empty() ) { label << "| " << node.getName(); } - drawNode( id, "record", "solid", label.str(), "brown", "white" ); - } - - void SimpleDotVisitor::handle(osg::Group& node, int id) { - std::stringstream label; - label << " " << node.className(); - if ( !node.getName().empty() ) { label << "| " << node.getName(); } - drawNode( id, "record", "solid", label.str(), "black", "white" ); - } - - void SimpleDotVisitor::handle(osg::Group&, osg::Node&, int parentID, int childID ) { - drawEdge( parentID, childID, "setlinewidth(2)" ); - } - - void SimpleDotVisitor::handle(osg::StateSet& stateset, int id) { +void SimpleDotVisitor::handle(osg::StateSet& stateset, int id) +{ std::stringstream label; label << " " << stateset.className(); - if ( !stateset.getName().empty() ) { label << "| " << stateset.getName(); } - drawNode( id, "Mrecord", "solid", label.str(), "green", "white" ); - } + if ( !stateset.getName().empty() ) { label << " | " << stateset.getName(); } + drawNode( id, "Mrecord", "solid, filled", label.str(), "green", "black" ); +} - void SimpleDotVisitor::handle(osg::Node&, osg::StateSet&, int parentID, int childID ) { - drawEdge( parentID, childID, "dashed" ); - } - - void SimpleDotVisitor::handle(osg::Drawable& drawable, int id) { +void SimpleDotVisitor::handle(osg::Drawable& drawable, int id) +{ std::stringstream label; label << " " << drawable.className(); - if ( !drawable.getName().empty() ) { label << "| " << drawable.getName(); } - drawNode( id, "record", "solid", label.str(), "blue", "white" ); - } + if ( !drawable.getName().empty() ) { label << " | " << drawable.getName(); } + drawNode( id, "record", "solid, filled", label.str(), "lightblue", "black" ); +} - void SimpleDotVisitor::handle(osg::Geode&, osg::Drawable&, int parentID, int childID ) { - drawEdge( parentID, childID, "dashed" ); - } +void SimpleDotVisitor::handle(osg::Node& node, int id) +{ + std::stringstream label; + label << " "< " << node.className(); + if ( !node.getName().empty() ) { label << " | " << node.getName(); } + drawNode( id, "record", "solid, filled", label.str(), "yellow", "black" ); +} - void SimpleDotVisitor::drawNode( int id, const std::string& shape, const std::string& style, const std::string& label, const std::string& color, const std::string& fillColor ) { +void SimpleDotVisitor::handle(osg::Node&, osg::StateSet&, int parentID, int childID ) +{ + drawEdge( parentID, childID, "" ); +} + +void SimpleDotVisitor::handle(osg::Drawable&, osg::StateSet&, int parentID, int childID ) +{ + drawEdge( parentID, childID, "" ); +} + +void SimpleDotVisitor::handle(osg::Group&, osg::Node&, int parentID, int childID ) +{ + drawEdge( parentID, childID, "" ); +} + +void SimpleDotVisitor::drawNode( int id, const std::string& shape, const std::string& style, const std::string& label, const std::string& color, const std::string& fillColor ) +{ _nodes << id << - "[shape=\"" << shape << - "\" ,label=\"" << label << - "\" ,style=\"" << style << - "\" ,color=\"" << color << - "\" ,fillColor=\"" << fillColor << - "\"]" << std::endl; - } + "[shape=\"" << shape << + "\" ,label=\"" << label << + "\" ,style=\"" << style << + "\" ,color=\"" << color << + "\" ,fillColor=\"" << fillColor << + "\"]" << std::endl; +} - void SimpleDotVisitor::drawEdge( int sourceId, int sinkId, const std::string& style ) { +void SimpleDotVisitor::drawEdge( int sourceId, int sinkId, const std::string& style ) +{ _edges - << sourceId << ":top -> " - << sinkId << ":top [style=\"" - << style << "\"];" - << std::endl; - } + << sourceId << ":top -> " + << sinkId << ":top [style=\"" + << style << "\"];" + << std::endl; +} } // namespace osgDot diff --git a/src/osgPlugins/dot/SimpleDotVisitor.h b/src/osgPlugins/dot/SimpleDotVisitor.h index e5e986ebc..94ad8ec69 100644 --- a/src/osgPlugins/dot/SimpleDotVisitor.h +++ b/src/osgPlugins/dot/SimpleDotVisitor.h @@ -23,30 +23,29 @@ namespace osgDot { - class SimpleDotVisitor : public BaseDotVisitor { - public: - SimpleDotVisitor(); +class SimpleDotVisitor : public BaseDotVisitor +{ + public: + SimpleDotVisitor(); - virtual ~SimpleDotVisitor(); + virtual ~SimpleDotVisitor(); - protected: - virtual void handle(osg::Node& node, int id); - virtual void handle(osg::Geode& geode, int id); - virtual void handle(osg::Group& node, int id); + protected: - virtual void handle(osg::StateSet& stateset, int id); - virtual void handle(osg::Drawable& drawable, int id); + virtual void handle(osg::StateSet& stateset, int id); + virtual void handle(osg::Drawable& drawable, int id); + virtual void handle(osg::Node& node, int id); + virtual void handle(osg::Group& node, int id); - virtual void handle(osg::Node& node, osg::StateSet& stateset, int parentID, int childID ); - virtual void handle(osg::Geode& geometry, osg::Drawable& drawable, int parentID, int childID ); - virtual void handle(osg::Group& parent, osg::Node& child, int parentID, int childID ); - virtual void handle(osg::Drawable& drawable, osg::StateSet& stateset, int parentID, int childID ); + virtual void handle(osg::Node& node, osg::StateSet& stateset, int parentID, int childID ); + virtual void handle(osg::Drawable& drawable, osg::StateSet& stateset, int parentID, int childID ); + virtual void handle(osg::Group& parent, osg::Node& child, int parentID, int childID ); - virtual void drawNode( int id, const std::string& shape, const std::string& style, const std::string& label, const std::string& color, const std::string& fillColor ); + virtual void drawNode( int id, const std::string& shape, const std::string& style, const std::string& label, const std::string& color, const std::string& fillColor ); - virtual void drawEdge( int sourceId, int sinkId, const std::string& style ); + virtual void drawEdge( int sourceId, int sinkId, const std::string& style ); - }; +}; } // namespace osgDot diff --git a/src/osgPlugins/dxf/dxfReader.cpp b/src/osgPlugins/dxf/dxfReader.cpp index 9a8c9ceb6..bce713b72 100644 --- a/src/osgPlugins/dxf/dxfReader.cpp +++ b/src/osgPlugins/dxf/dxfReader.cpp @@ -85,7 +85,7 @@ bool readerText::success(bool inSuccess, string type) bool readerText::getTrimmedLine(std::ifstream& f) { - static string line = ""; + std::string line; if (getline(f, line, _delim)) { ++_lineCount; _str.clear(); diff --git a/src/osgPlugins/exr/CMakeLists.txt b/src/osgPlugins/exr/CMakeLists.txt index 56ef8e0e4..e2ed9bb65 100644 --- a/src/osgPlugins/exr/CMakeLists.txt +++ b/src/osgPlugins/exr/CMakeLists.txt @@ -1,8 +1,9 @@ +INCLUDE_DIRECTORIES( ${ILMBASE_INCLUDE_DIR}/OpenEXR ) INCLUDE_DIRECTORIES( ${OPENEXR_INCLUDE_DIR}/OpenEXR ) SET(TARGET_SRC ReaderWriterEXR.cpp ) -SET(TARGET_LIBRARIES_VARS ${OPENEXR_LIBRARIES_VARS} ZLIB_LIBRARIES) +SET(TARGET_LIBRARIES_VARS ${OPENEXR_LIBRARIES_VARS} ${ILMBASE_LIBRARIES_VARS} ZLIB_LIBRARIES) IF(CMAKE_COMPILER_IS_GNUCXX) # Remove -Wshadow flag as it barfs on ffmoeg headers diff --git a/src/osgPlugins/freetype/FreeTypeFont.cpp b/src/osgPlugins/freetype/FreeTypeFont.cpp index c647e2cf9..d39f984c2 100644 --- a/src/osgPlugins/freetype/FreeTypeFont.cpp +++ b/src/osgPlugins/freetype/FreeTypeFont.cpp @@ -278,19 +278,6 @@ void FreeTypeFont::setFontResolution(const osgText::FontResolution& fontSize) int width = fontSize.first; int height = fontSize.second; - int maxAxis = std::max(width, height); - int margin = _facade->getGlyphImageMargin() + (int)((float)maxAxis * _facade->getGlyphImageMarginRatio()); - - if ((unsigned int)(width+2*margin) > _facade->getTextureWidthHint() || - (unsigned int)(width+2*margin) > _facade->getTextureHeightHint()) - { - OSG_WARN<<"Warning: FreeTypeFont::setSize("<getTextureWidthHint()-2*margin; - height = _facade->getTextureHeightHint()-2*margin; - - OSG_WARN<<" sizes capped ("< glyph = new osgText::Glyph(_facade, charcode); + glyph->setFontResolution(fontRes); + unsigned int dataSize = width*height; unsigned char* data = new unsigned char[dataSize]; @@ -359,14 +348,12 @@ osgText::Glyph* FreeTypeFont::getGlyph(const osgText::FontResolution& fontRes, u for(unsigned char* p=data;psetImage(width,height,1, - OSGTEXT_GLYPH_INTERNALFORMAT, - OSGTEXT_GLYPH_FORMAT, GL_UNSIGNED_BYTE, + GL_ALPHA, + GL_ALPHA, GL_UNSIGNED_BYTE, data, osg::Image::USE_NEW_DELETE, 1); - glyph->setInternalTextureFormat(OSGTEXT_GLYPH_INTERNALFORMAT); - // copy image across to osgText::Glyph image. switch(glyphslot->bitmap.pixel_mode) { diff --git a/src/osgPlugins/gles/GeometryCleaner b/src/osgPlugins/gles/GeometryCleaner index 41310281a..adcef5703 100644 --- a/src/osgPlugins/gles/GeometryCleaner +++ b/src/osgPlugins/gles/GeometryCleaner @@ -39,12 +39,15 @@ public: } else { osg::Vec3Array* positions = dynamic_cast(geometry.getVertexArray()); - SubGeometry cleaned(geometry, - clean(*positions, getTriangles(geometry), 3), - clean(*positions, getLines(geometry), 2), - clean(*positions, getWireframe(geometry), 2), - clean(*positions, getPoints(geometry), 1)); - _clean.push_back(cleaned.geometry()); + if (positions) + { + SubGeometry cleaned(geometry, + clean(*positions, getTriangles(geometry), 3), + clean(*positions, getLines(geometry), 2), + clean(*positions, getWireframe(geometry), 2), + clean(*positions, getPoints(geometry), 1)); + _clean.push_back(cleaned.geometry()); + } } return _clean; diff --git a/src/osgPlugins/glsl/ReaderWriterGLSL.cpp b/src/osgPlugins/glsl/ReaderWriterGLSL.cpp index 60c4842a4..a836a0cf0 100644 --- a/src/osgPlugins/glsl/ReaderWriterGLSL.cpp +++ b/src/osgPlugins/glsl/ReaderWriterGLSL.cpp @@ -24,52 +24,123 @@ class ReaderWriterGLSL : public osgDB::ReaderWriter supportsExtension("tctrl","OpenGL Shader Language format"); supportsExtension("teval","OpenGL Shader Language format"); supportsExtension("compute","OpenGL Shader Language format"); + supportsExtension("cs","OpenGL Shader Language format"); + supportsExtension("gs","OpenGL Shader Language format"); + supportsExtension("vs","OpenGL Shader Language format"); + supportsExtension("fs","OpenGL Shader Language format"); } virtual const char* className() const { return "GLSL Shader Reader"; } - osg::Shader* processIncludes( const osg::Shader* shader, const Options* options ) const + void processIncludes( osg::Shader& shader, const Options* options ) const { - std::string code = shader->getShaderSource(); + std::string code = shader.getShaderSource(); + std::string startOfIncludeMarker("// Start of include code : "); + std::string endOfIncludeMarker("// End of include code : "); + std::string failedLoadMarker("// Failed to load include code : "); + + #if defined(__APPLE__) + std::string endOfLine("\r"); + #elif defined(_WIN32) + std::string endOfLine("\r\n"); + #else + std::string endOfLine("\n"); + #endif + std::string::size_type pos = 0; - - static std::string::size_type includeLen = 8; - - while( ( pos = code.find( "#include", pos ) ) != std::string::npos ) + std::string::size_type pragma_pos = 0; + std::string::size_type include_pos = 0; + while( (pos !=std::string::npos) && (((pragma_pos=code.find( "#pragma", pos )) != std::string::npos) || (include_pos=code.find( "#include", pos )) != std::string::npos)) { - // we found an include - std::string::size_type pos2 = code.find_first_not_of( " ", pos + includeLen ); + pos = (pragma_pos!= std::string::npos) ? pragma_pos : include_pos; - if ( ( pos2 == std::string::npos ) || ( code[ pos2 ] != '\"' ) ) + std::string::size_type start_of_pragma_line = pos; + std::string::size_type end_of_line = code.find_first_of("\n\r", pos ); + + if (pragma_pos!= std::string::npos) { - // error, bail out - return NULL; + // we have #pragma usage so skip to the start of the first non white space + pos = code.find_first_not_of(" \t", pos+7 ); + if (pos==std::string::npos) break; + + + // check for include part of #pragma imclude usage + if (code.compare(pos, 7, "include")!=0) + { + pos = end_of_line; + continue; + } + + // found include entry so skip to next non white space + pos = code.find_first_not_of(" \t", pos+7 ); + if (pos==std::string::npos) break; + } + else + { + // we have #include usage so skip to next non white space + pos = code.find_first_not_of(" \t", pos+8 ); + if (pos==std::string::npos) break; } - // we found an " - std::string::size_type pos3 = code.find( "\"", pos2 + 1 ); - if ( pos3 == std::string::npos ) + std::string::size_type num_characters = (end_of_line==std::string::npos) ? code.size()-pos : end_of_line-pos; + if (num_characters==0) continue; + + // prune trailing white space + while(num_characters>0 && (code[pos+num_characters-1]==' ' || code[pos+num_characters-1]=='\t')) --num_characters; + + if (code[pos]=='\"') { - return NULL; + if (code[pos+num_characters-1]!='\"') + { + num_characters -= 1; + } + else + { + num_characters -= 2; + } + + ++pos; } - const std::string filename = code.substr( pos2 + 1, pos3 - pos2 - 1 ); + std::string filename(code, pos, num_characters); - osg::ref_ptr innerShader = osgDB::readRefShaderFile( shader->getType(), filename, options ); + code.erase(start_of_pragma_line, (end_of_line==std::string::npos) ? code.size()-start_of_pragma_line : end_of_line-start_of_pragma_line); + pos = start_of_pragma_line; - if ( !innerShader.valid() ) + osg::ref_ptr innerShader = osgDB::readRefShaderFile( filename, options ); + + if (innerShader.valid()) { - return NULL; + if (!startOfIncludeMarker.empty()) + { + code.insert(pos, startOfIncludeMarker); pos += startOfIncludeMarker.size(); + code.insert(pos, filename); pos += filename.size(); + code.insert(pos, endOfLine); pos += endOfLine.size(); + } + + code.insert(pos, innerShader->getShaderSource() ); pos += innerShader->getShaderSource().size(); + + if (!endOfIncludeMarker.empty()) + { + code.insert(pos, endOfIncludeMarker); pos += endOfIncludeMarker.size(); + code.insert(pos, filename); pos += filename.size(); + code.insert(pos, endOfLine); pos += endOfLine.size(); + } + } + else + { + if (!failedLoadMarker.empty()) + { + code.insert(pos, failedLoadMarker); pos += failedLoadMarker.size(); + code.insert(pos, filename); pos += filename.size(); + code.insert(pos, endOfLine); pos += endOfLine.size(); + } } - - code.replace( pos, pos3 - pos + 1, innerShader->getShaderSource() ); - - pos += innerShader->getShaderSource().size(); } - return new osg::Shader( shader->getType(), code ); + shader.setShaderSource(code); } virtual ReadResult readObject(std::istream& fin,const Options* options) const @@ -104,8 +175,10 @@ class ReaderWriterGLSL : public osgDB::ReaderWriter if (options->getOptionString().find("compute")!=std::string::npos) shader->setType(osg::Shader::COMPUTE); } + processIncludes( *shader, options ); + // return valid shader - return processIncludes( shader.get(), options ); + return shader.get(); } virtual ReadResult readShader(const std::string& file, const osgDB::ReaderWriter::Options* options) const @@ -116,9 +189,12 @@ class ReaderWriterGLSL : public osgDB::ReaderWriter std::string fileName = osgDB::findDataFile( file, options ); if (fileName.empty()) return ReadResult::FILE_NOT_FOUND; + osg::ref_ptr local_opt = options ? static_cast(options->clone(osg::CopyOp::SHALLOW_COPY)) : new Options; + local_opt->getDatabasePathList().push_front(osgDB::getFilePath(fileName)); + osgDB::ifstream istream(fileName.c_str(), std::ios::in | std::ios::binary); if(!istream) return ReadResult::FILE_NOT_HANDLED; - ReadResult rr = readShader(istream, options); + ReadResult rr = readShader(istream, local_opt.get()); if(rr.validShader()) { osg::Shader* shader = rr.getShader(); @@ -127,11 +203,15 @@ class ReaderWriterGLSL : public osgDB::ReaderWriter { // set type based on filename extension, where possible if (ext == "frag") shader->setType(osg::Shader::FRAGMENT); + if (ext == "fs") shader->setType(osg::Shader::FRAGMENT); if (ext == "vert") shader->setType(osg::Shader::VERTEX); + if (ext == "vs") shader->setType(osg::Shader::VERTEX); if (ext == "geom") shader->setType(osg::Shader::GEOMETRY); + if (ext == "gs") shader->setType(osg::Shader::GEOMETRY); if (ext == "tctrl") shader->setType(osg::Shader::TESSCONTROL); if (ext == "teval") shader->setType(osg::Shader::TESSEVALUATION); if (ext == "compute") shader->setType(osg::Shader::COMPUTE); + if (ext == "cs") shader->setType(osg::Shader::COMPUTE); } } return rr; diff --git a/src/osgPlugins/gz/ReaderWriterGZ.cpp b/src/osgPlugins/gz/ReaderWriterGZ.cpp index 8a917742e..5e8a5bdf3 100644 --- a/src/osgPlugins/gz/ReaderWriterGZ.cpp +++ b/src/osgPlugins/gz/ReaderWriterGZ.cpp @@ -45,7 +45,7 @@ class ReaderWriterGZ : public osgDB::ReaderWriter ~ReaderWriterGZ(); - virtual const char* className() const { return "HTTP Protocol Model Reader"; } + virtual const char* className() const { return "GZ Archive Reader/Writer"; } virtual ReadResult openArchive(const std::string& fileName,ArchiveStatus status, unsigned int , const Options* options) const { @@ -77,6 +77,67 @@ class ReaderWriterGZ : public osgDB::ReaderWriter ReadResult readFile(ObjectType objectType, const std::string& fullFileName, const osgDB::ReaderWriter::Options* options) const; + ///return the reader for fullFileName and a outuncompessed stream fetching this file in the archive + osgDB::ReaderWriter *getStreamAndReader(std::stringstream& outuncompessed, std::istream& fin, const std::string& fullFileName) const { + std::string ext = osgDB::getLowerCaseFileExtension(fullFileName); + osgDB::ReaderWriter* rw = 0; + rw = osgDB::Registry::instance()->getReaderWriterForExtension( ext ); + std::string baseFileName = osgDB::getNameLessExtension( fullFileName ); + std::string baseExt = osgDB::getLowerCaseFileExtension( baseFileName ); + rw = osgDB::Registry::instance()->getReaderWriterForExtension( baseExt ); + OSG_INFO<< className() << "::getStreamAndReader:" << baseExt << " ReaderWriter " << rw <getPluginStringData("STREAM_FILENAME"); + std::string ext = osgDB::getLowerCaseFileExtension(fullFileName); + if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED; + if (osgDB::containsServerAddress(fullFileName)) return ReadResult::FILE_NOT_HANDLED; + std::stringstream decstream; + osgDB::ReaderWriter* rw = getStreamAndReader(decstream, fin, fullFileName); + return readFile(IMAGE, rw, decstream, local_opt); + } + + virtual ReadResult readHeightField(std::istream& fin,const osgDB::ReaderWriter::Options* local_opt=NULL) const { + std::string fullFileName = local_opt->getPluginStringData("STREAM_FILENAME"); + std::string ext = osgDB::getLowerCaseFileExtension(fullFileName); + if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED; + if (osgDB::containsServerAddress(fullFileName)) return ReadResult::FILE_NOT_HANDLED; + std::stringstream decstream; + osgDB::ReaderWriter* rw = getStreamAndReader(decstream, fin, fullFileName); + return readFile(HEIGHTFIELD, rw, decstream, local_opt); + } + + virtual ReadResult readNode(std::istream& fin,const osgDB::ReaderWriter::Options* local_opt=NULL) const { + std::string fullFileName = local_opt->getPluginStringData("STREAM_FILENAME"); + std::string ext = osgDB::getLowerCaseFileExtension(fullFileName); + if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED; + if (osgDB::containsServerAddress(fullFileName)) return ReadResult::FILE_NOT_HANDLED; + std::stringstream decstream; + osgDB::ReaderWriter* rw = getStreamAndReader(decstream, fin, fullFileName); + return readFile(NODE, rw, decstream, local_opt); + } + + virtual ReadResult readObject(std::istream& fin,const osgDB::ReaderWriter::Options* local_opt=NULL) const { + std::string fullFileName = local_opt->getPluginStringData("STREAM_FILENAME"); + std::string ext = osgDB::getLowerCaseFileExtension(fullFileName); + if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED; + if (osgDB::containsServerAddress(fullFileName)) return ReadResult::FILE_NOT_HANDLED; + std::stringstream decstream; + osgDB::ReaderWriter* rw = getStreamAndReader(decstream, fin, fullFileName); + return readFile(OBJECT, rw, decstream, local_opt); + } + virtual ReadResult readArchive(std::istream& fin,const osgDB::ReaderWriter::Options* local_opt=NULL) const { + std::string fullFileName = local_opt->getPluginStringData("STREAM_FILENAME"); + std::string ext = osgDB::getLowerCaseFileExtension(fullFileName); + if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED; + if (osgDB::containsServerAddress(fullFileName)) return ReadResult::FILE_NOT_HANDLED; + std::stringstream decstream; + osgDB::ReaderWriter* rw = getStreamAndReader(decstream, fin, fullFileName); + return readFile(ARCHIVE, rw, decstream, local_opt); + } virtual WriteResult writeObject(const osg::Object& obj, const std::string& fileName, const osgDB::ReaderWriter::Options* options) const @@ -104,8 +165,8 @@ class ReaderWriterGZ : public osgDB::ReaderWriter WriteResult writeFile(ObjectType objectType, const osg::Object* object, const std::string& fullFileName, const osgDB::ReaderWriter::Options* options) const; - bool read(std::istream& fin, std::string& destination) const; - bool write(std::ostream& fout, const std::string& source) const; + bool read(std::istream& fin, std::stringstream& destination) const; + bool write(std::ostream& fout, const std::stringstream& source) const; }; @@ -177,10 +238,8 @@ osgDB::ReaderWriter::ReadResult ReaderWriterGZ::readFile(ObjectType objectType, if (!fin) return ReadResult::ERROR_IN_READING_FILE; - std::string dest; - read(fin, dest); - - std::stringstream strstream(dest); + std::stringstream strstream; + read(fin, strstream); return readFile(objectType, rw, strstream, local_opt.get()); } @@ -229,14 +288,14 @@ osgDB::ReaderWriter::WriteResult ReaderWriterGZ::writeFile(ObjectType objectType osgDB::ofstream fout(fullFileName.c_str(), std::ios::binary|std::ios::out); - write(fout,strstream.str()); + write(fout,strstream); return writeResult; } #define CHUNK 16384 -bool ReaderWriterGZ::read(std::istream& fin, std::string& destination) const +bool ReaderWriterGZ::read(std::istream& fin, std::stringstream& destination) const { int ret; unsigned have; @@ -252,7 +311,7 @@ bool ReaderWriterGZ::read(std::istream& fin, std::string& destination) const strm.next_in = Z_NULL; ret = inflateInit2(&strm, 15 + 32 // autodetected zlib or gzip header - ); + ); if (ret != Z_OK) return false; @@ -285,8 +344,7 @@ bool ReaderWriterGZ::read(std::istream& fin, std::string& destination) const return false; } have = CHUNK - strm.avail_out; - - destination.append((char*)out, have); + destination.write((char*)out,have); } while (strm.avail_out == 0); @@ -298,8 +356,9 @@ bool ReaderWriterGZ::read(std::istream& fin, std::string& destination) const return ret == Z_STREAM_END ? true : false; } -bool ReaderWriterGZ::write(std::ostream& fout, const std::string& source) const +bool ReaderWriterGZ::write(std::ostream& fout, const std::stringstream& sourcestream) const { + std::string source = sourcestream.str(); int ret, flush = Z_FINISH; unsigned have; z_stream strm; @@ -322,7 +381,7 @@ bool ReaderWriterGZ::write(std::ostream& fout, const std::string& source) const 8, // default stategy); if (ret != Z_OK) - return false; + return false; strm.avail_in = source.size(); strm.next_in = (Bytef*)(&(*source.begin())); @@ -357,6 +416,8 @@ bool ReaderWriterGZ::write(std::ostream& fout, const std::string& source) const } + + // now register with Registry to instantiate the above // reader/writer. REGISTER_OSGPLUGIN(GZ, ReaderWriterGZ) diff --git a/src/osgPlugins/ive/Text.cpp b/src/osgPlugins/ive/Text.cpp index ae9da298f..0139695c5 100644 --- a/src/osgPlugins/ive/Text.cpp +++ b/src/osgPlugins/ive/Text.cpp @@ -90,7 +90,7 @@ void Text::write(DataOutputStream* out){ out->writeFloat(getBackdropVerticalOffset()); out->writeVec4(getBackdropColor()); - out->writeUInt(getBackdropImplementation()); + out->writeUInt(4); // old DELAYED_DEPTH_WRITES out->writeUInt(getColorGradientMode()); out->writeVec4(getColorGradientTopLeft()); @@ -213,7 +213,7 @@ void Text::read(DataInputStream* in){ setBackdropOffset(horizontalOffset,verticalOffset); setBackdropColor(in->readVec4()); - setBackdropImplementation((osgText::Text::BackdropImplementation) in->readUInt()); + in->readUInt(); // read old BackdropImplementation value, no longer used setColorGradientMode((osgText::Text::ColorGradientMode) in->readUInt()); osg::Vec4 colorGradientTopLeft,colorGradientBottomLeft,colorGradientBottomRight,colorGradientTopRight; diff --git a/src/osgPlugins/jpeg/ReaderWriterJPEG.cpp b/src/osgPlugins/jpeg/ReaderWriterJPEG.cpp index 115203322..f49a7a18d 100644 --- a/src/osgPlugins/jpeg/ReaderWriterJPEG.cpp +++ b/src/osgPlugins/jpeg/ReaderWriterJPEG.cpp @@ -689,7 +689,7 @@ class ReaderWriterJPEG : public osgDB::ReaderWriter default: { OSG_DEBUG << "ReaderWriterJPEG::write_JPEG_file - Error pixel format non supported" << std::endl; - return WriteResult::ERROR_IN_WRITING_FILE; break; + return WriteResult::ERROR_IN_WRITING_FILE; } } diff --git a/src/osgPlugins/logo/ReaderWriterLOGO.cpp b/src/osgPlugins/logo/ReaderWriterLOGO.cpp index 0af8a20a7..e5ce86a97 100644 --- a/src/osgPlugins/logo/ReaderWriterLOGO.cpp +++ b/src/osgPlugins/logo/ReaderWriterLOGO.cpp @@ -259,7 +259,7 @@ class LOGOReaderWriter : public osgDB::ReaderWriter Logos::RelativePosition pos = Logos::LowerRight; - std::ifstream fin(filePath.c_str()); + std::ifstream fin(fileName.c_str()); if (!fin) return NULL; while(fin) @@ -321,7 +321,7 @@ class LOGOReaderWriter : public osgDB::ReaderWriter if( ld->hasLogos() ) geode->addDrawable( ld ); - geode->setCullingActive(false); + ld->setCullingActive(false); return geode; } }; diff --git a/src/osgPlugins/lua/LuaScriptEngine.cpp b/src/osgPlugins/lua/LuaScriptEngine.cpp index 15be805d1..5488d065d 100644 --- a/src/osgPlugins/lua/LuaScriptEngine.cpp +++ b/src/osgPlugins/lua/LuaScriptEngine.cpp @@ -4074,21 +4074,21 @@ void LuaScriptEngine::addPaths(const osgDB::FilePathList& paths) std::string path = lua_tostring( _lua, -1 ); lua_pop( _lua, 1 ); - OSG_NOTICE<<"LuaScriptEngine::addPaths() original package.path = "<asGeometry(); - if ( g != NULL ) - { - pushStateSet(g->getStateSet()); - - processGeometry(g,m); - - popStateSet(g->getStateSet()); - } + node.getDrawable( i )->accept(*this); } - popStateSet(node.getStateSet()); _nameStack.pop_back(); } diff --git a/src/osgPlugins/obj/OBJWriterNodeVisitor.h b/src/osgPlugins/obj/OBJWriterNodeVisitor.h index be4c8cabd..8dc16a0d5 100644 --- a/src/osgPlugins/obj/OBJWriterNodeVisitor.h +++ b/src/osgPlugins/obj/OBJWriterNodeVisitor.h @@ -65,9 +65,10 @@ class OBJWriterNodeVisitor: public osg::NodeVisitor { } } - virtual void apply(osg::Geode &node); + virtual void apply(osg::Geometry & geometry); + virtual void apply(osg::Geode & node); - virtual void apply(osg::Group &node) + virtual void apply(osg::Group & node) { pushStateSet(node.getStateSet()); _nameStack.push_back( node.getName().empty() ? node.className() : node.getName() ); @@ -78,14 +79,6 @@ class OBJWriterNodeVisitor: public osg::NodeVisitor { traverse( node ); _nameStack.pop_back(); - popStateSet(node.getStateSet()); - } - - void traverse (osg::Node &node) - { - pushStateSet(node.getStateSet()); - - osg::NodeVisitor::traverse( node ); popStateSet(node.getStateSet()); } diff --git a/src/osgPlugins/obj/ReaderWriterOBJ.cpp b/src/osgPlugins/obj/ReaderWriterOBJ.cpp index 5c14abddf..137996ea8 100644 --- a/src/osgPlugins/obj/ReaderWriterOBJ.cpp +++ b/src/osgPlugins/obj/ReaderWriterOBJ.cpp @@ -142,7 +142,8 @@ public: protected: - struct ObjOptionsStruct { + class ObjOptionsStruct { + public: bool rotate; bool noTesselateLargePolygons; bool noTriStripPolygons; @@ -155,6 +156,17 @@ protected: TextureAllocationMap textureUnitAllocation; /// Coordinates precision. int precision; + + ObjOptionsStruct() + { + rotate = true; + noTesselateLargePolygons = false; + noTriStripPolygons = false; + generateFacetNormals = false; + fixBlackMaterials = true; + noReverseFaces = false; + precision = std::numeric_limits::digits10 + 2; + } }; typedef std::map< std::string, osg::ref_ptr > MaterialToStateSetMap; @@ -831,13 +843,6 @@ osg::Node* ReaderWriterOBJ::convertModelToSceneGraph(obj::Model& model, ObjOptio ReaderWriterOBJ::ObjOptionsStruct ReaderWriterOBJ::parseOptions(const osgDB::ReaderWriter::Options* options) const { ObjOptionsStruct localOptions; - localOptions.rotate = true; - localOptions.noTesselateLargePolygons = false; - localOptions.noTriStripPolygons = false; - localOptions.generateFacetNormals = false; - localOptions.fixBlackMaterials = true; - localOptions.noReverseFaces = false; - localOptions.precision = std::numeric_limits::digits10 + 2; if (options!=NULL) { diff --git a/src/osgPlugins/obj/obj.cpp b/src/osgPlugins/obj/obj.cpp index e2038f60a..c041a8437 100644 --- a/src/osgPlugins/obj/obj.cpp +++ b/src/osgPlugins/obj/obj.cpp @@ -231,7 +231,6 @@ bool Model::readMTL(std::istream& fin) bool usingDissolve = false; Material* material = 0;// &(materialMap[""]); - std::string filename; while (fin) { diff --git a/src/osgPlugins/ogr/ReaderWriterOGR.cpp b/src/osgPlugins/ogr/ReaderWriterOGR.cpp index 5fed4aaea..6e27aa652 100644 --- a/src/osgPlugins/ogr/ReaderWriterOGR.cpp +++ b/src/osgPlugins/ogr/ReaderWriterOGR.cpp @@ -262,8 +262,6 @@ public: osg::Geometry* multiPointToDrawable(OGRMultiPoint* mpoint) const { - osg::Geometry* geom = new osg::Geometry; - osg::Geometry* pointGeom = new osg::Geometry(); osg::Vec3Array* vertices = new osg::Vec3Array(); @@ -286,7 +284,7 @@ public: if (pointGeom->getVertexArray()) { - OSG_INFO << "osgOgrFeature::multiPointToDrawable " << geom->getVertexArray()->getNumElements() << " vertexes"<< std::endl; + OSG_INFO << "osgOgrFeature::multiPointToDrawable " << pointGeom->getVertexArray()->getNumElements() << " vertexes"<< std::endl; } return pointGeom; diff --git a/src/osgPlugins/osgjs/Animation.cpp b/src/osgPlugins/osgjs/Animation.cpp index 40af1ed47..a14352d1d 100644 --- a/src/osgPlugins/osgjs/Animation.cpp +++ b/src/osgPlugins/osgjs/Animation.cpp @@ -240,16 +240,6 @@ static void addJSONChannel(osgAnimation::Channel* channel, JSONObject& anim, Wri } } -#ifdef USE_COMPRESSED_CHANNELS - { - osgAnimation::Vec3usLinearChannel* c = dynamic_cast(channel); - if (c) { - if (addJSONChannel("osgAnimation.Vec3LerpChannelCompressed", c, true, anim, writer, parent)) - return; - } - } -#endif - { osgAnimation::QuatSphericalLinearChannel* c = dynamic_cast(channel); if (c) { @@ -258,16 +248,6 @@ static void addJSONChannel(osgAnimation::Channel* channel, JSONObject& anim, Wri } } -#ifdef USE_COMPRESSED_CHANNELS - { - osgAnimation::Vec3usSphericalLinearChannel* c = dynamic_cast(channel); - if (c) { - if (addJSONChannel("osgAnimation.QuatSlerpChannelCompressed", c, true, anim, writer, parent)) - return; - } - } -#endif - { osgAnimation::FloatCubicBezierChannel* c = dynamic_cast(channel); if (c) { diff --git a/src/osgPlugins/osgjs/CMakeLists.txt b/src/osgPlugins/osgjs/CMakeLists.txt index 980f644b9..2c6673119 100644 --- a/src/osgPlugins/osgjs/CMakeLists.txt +++ b/src/osgPlugins/osgjs/CMakeLists.txt @@ -16,10 +16,6 @@ SET(TARGET_H WriteVisitor ) -IF($ENV{SKETCHFAB_BUILD}) - ADD_DEFINITIONS(-DUSE_COMPRESSED_CHANNELS) -ENDIF() - #### end var setup ### SET(TARGET_ADDED_LIBRARIES osgAnimation diff --git a/src/osgPlugins/p3d/ReaderWriterP3D.cpp b/src/osgPlugins/p3d/ReaderWriterP3D.cpp index 0ac468c4b..774a2d1bc 100644 --- a/src/osgPlugins/p3d/ReaderWriterP3D.cpp +++ b/src/osgPlugins/p3d/ReaderWriterP3D.cpp @@ -2195,11 +2195,11 @@ void ReaderWriterP3DXML::parseLayer(osgPresentation::SlideShowConstructor& const if (constructor.getCurrentLayer()) { constructor.getCurrentLayer()->setUserValue("name",name); - OSG_NOTICE<<"Setting current layers name "<setUserValue("name",name); - OSG_NOTICE<<"Setting current slide name "< #include #include +#include #include #include @@ -311,7 +312,8 @@ osg::Node* VertexData::readPlyFile( const char* filename, const bool ignoreColor MESHINFO << filename << ": " << nPlyElems << " elements, file type = " << fileType << ", version = " << version << endl; #endif - char *textureFile = NULL; + + std::string textureFile; for( int i = 0; i < nComments; i++ ) { if( equal_strings( comments[i], "modified by flipply" ) ) @@ -321,38 +323,11 @@ osg::Node* VertexData::readPlyFile( const char* filename, const bool ignoreColor if (strncmp(comments[i], "TextureFile",11)==0) { textureFile = comments[i]+12; - char * path = new char[strlen(const_cast(filename)) + 1 + strlen(comments[i])]; - if (textureFile[0] == '\\' || textureFile[0] == '/' || textureFile[1] == ':') + if (!osgDB::isAbsolutePath(textureFile)) { - // texture filename is absolute - strcpy(path, textureFile); + textureFile = osgDB::concatPaths(osgDB::getFilePath(filename), textureFile); } - else - { - // texture filename is relative - // add directory of ply file - strcpy(path, const_cast(filename)); - char *pp = path + strlen(path); - while (pp >= path) - { - if (*pp == '\\' || *pp == '/') - { - pp++; - *pp = '\0'; - break; - } - pp--; - } - if (pp == path - 1) - { - pp++; - *pp = '\0'; - } - strcat(path, textureFile); - } - textureFile = path; } - } for( int i = 0; i < nPlyElems; ++i ) { @@ -546,7 +521,7 @@ osg::Node* VertexData::readPlyFile( const char* filename, const bool ignoreColor } else if (_texcoord.valid()) { - geom->setTexCoordArray(0, _texcoord); + geom->setTexCoordArray(0, _texcoord.get()); } // If the model has normals, add them to the geometry @@ -563,11 +538,11 @@ osg::Node* VertexData::readPlyFile( const char* filename, const bool ignoreColor // set flage true to activate the vertex buffer object of drawable geom->setUseVertexBufferObjects(true); - osg::Image *image = NULL; - if (textureFile && (image = osgDB::readImageFile(textureFile)) != NULL) + osg::ref_ptr image; + if (!textureFile.empty() && (image = osgDB::readRefImageFile(textureFile)) != NULL) { osg::Texture2D *texture = new osg::Texture2D; - texture->setImage(image); + texture->setImage(image.get()); texture->setResizeNonPowerOfTwoHint(false); osg::TexEnv *texenv = new osg::TexEnv; @@ -576,7 +551,6 @@ osg::Node* VertexData::readPlyFile( const char* filename, const bool ignoreColor osg::StateSet *stateset = geom->getOrCreateStateSet(); stateset->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON); stateset->setTextureAttribute(0, texenv); - delete[] textureFile; } osg::Geode* geode = new osg::Geode; diff --git a/src/osgPlugins/png/ReaderWriterPNG.cpp b/src/osgPlugins/png/ReaderWriterPNG.cpp index 8190a4b4d..fdd2a891b 100644 --- a/src/osgPlugins/png/ReaderWriterPNG.cpp +++ b/src/osgPlugins/png/ReaderWriterPNG.cpp @@ -307,6 +307,18 @@ class ReaderWriterPNG : public osgDB::ReaderWriter pixelFormat = GL_RGBA; int internalFormat = pixelFormat; + if (depth > 8) + { + switch(color) + { + case(GL_LUMINANCE): internalFormat = GL_LUMINANCE16; break; + case(GL_ALPHA): internalFormat = GL_ALPHA16; break; + case(GL_LUMINANCE_ALPHA): internalFormat = GL_LUMINANCE16_ALPHA16; break; + case(GL_RGB): internalFormat = GL_RGB16; break; + case(GL_RGBA): internalFormat = GL_RGBA16; break; + default: break; + } + } png_destroy_read_struct(&png, &info, &endinfo); diff --git a/src/osgPlugins/rgb/ReaderWriterRGB.cpp b/src/osgPlugins/rgb/ReaderWriterRGB.cpp index 63d144955..ffaad7026 100644 --- a/src/osgPlugins/rgb/ReaderWriterRGB.cpp +++ b/src/osgPlugins/rgb/ReaderWriterRGB.cpp @@ -39,7 +39,7 @@ using namespace osg; typedef unsigned int size_pos; -struct rawImageRec : public osg::Referenced +struct rawImageRec { rawImageRec(): imagic(0), @@ -59,7 +59,7 @@ struct rawImageRec : public osg::Referenced { } - virtual ~rawImageRec() + ~rawImageRec() { if (tmp) delete [] tmp; if (tmpR) delete [] tmpR; @@ -131,6 +131,11 @@ struct rawImageRec : public osg::Referenced } }; +struct refImageRec : public rawImageRec, public osg::Referenced +{ +}; + + static void ConvertShort(unsigned short *array, long length) { unsigned long b1, b2; @@ -163,7 +168,7 @@ static void ConvertLong(GLuint *array, long length) -static osg::ref_ptr RawImageOpen(std::istream& fin) +static osg::ref_ptr RawImageOpen(std::istream& fin) { union { @@ -173,7 +178,7 @@ static osg::ref_ptr RawImageOpen(std::istream& fin) int x; - osg::ref_ptr raw = new rawImageRec; + osg::ref_ptr raw = new refImageRec; if (raw == NULL) { OSG_WARN<< "Out of memory!"<< std::endl; @@ -278,27 +283,27 @@ static osg::ref_ptr RawImageOpen(std::istream& fin) } -static void RawImageGetRow(rawImageRec *raw, unsigned char *buf, int y, int z) +static void RawImageGetRow(rawImageRec& raw, unsigned char *buf, int y, int z) { unsigned char *iPtr, *oPtr; unsigned short pixel; int count, done = 0; unsigned short *tempShort; - if ((raw->type & 0xFF00) == 0x0100) + if ((raw.type & 0xFF00) == 0x0100) { - size_pos pos = raw->rowStart[static_cast(y)+static_cast(z)*static_cast(raw->sizeY)]; + size_pos pos = raw.rowStart[static_cast(y)+static_cast(z)*static_cast(raw.sizeY)]; - size_pos amount = raw->rowSize[static_cast(y)+static_cast(z)*static_cast(raw->sizeY)]; + size_pos amount = raw.rowSize[static_cast(y)+static_cast(z)*static_cast(raw.sizeY)]; - raw->file->seekg(pos, std::ios::beg); - raw->file->read((char*)raw->tmp, amount); + raw.file->seekg(pos, std::ios::beg); + raw.file->read((char*)raw.tmp, amount); - iPtr = raw->tmp; + iPtr = raw.tmp; oPtr = buf; while (!done) { - if (raw->bpc == 1) + if (raw.bpc == 1) pixel = *iPtr++; else { @@ -308,15 +313,15 @@ static void RawImageGetRow(rawImageRec *raw, unsigned char *buf, int y, int z) iPtr = reinterpret_cast(tempShort); } - if(raw->bpc != 1) + if(raw.bpc != 1) ConvertShort(&pixel, 1); count = (int)(pixel & 0x7F); // limit the count value to the remiaing row size - if ((static_cast(raw->sizeX)*static_cast(raw->bpc)) <= (oPtr - buf)) + if ((static_cast(raw.sizeX)*static_cast(raw.bpc)) <= (oPtr - buf)) { - count = static_cast(raw->sizeX) - (oPtr - buf) / static_cast(raw->bpc); + count = static_cast(raw.sizeX) - (oPtr - buf) / static_cast(raw.bpc); } if (count<=0) @@ -329,7 +334,7 @@ static void RawImageGetRow(rawImageRec *raw, unsigned char *buf, int y, int z) { while (count--) { - if(raw->bpc == 1) + if(raw.bpc == 1) *oPtr++ = *iPtr++; else{ tempShort = reinterpret_cast(iPtr); @@ -348,7 +353,7 @@ static void RawImageGetRow(rawImageRec *raw, unsigned char *buf, int y, int z) } else { - if (raw->bpc == 1) + if (raw.bpc == 1) { pixel = *iPtr++; } @@ -359,11 +364,11 @@ static void RawImageGetRow(rawImageRec *raw, unsigned char *buf, int y, int z) tempShort++; iPtr = reinterpret_cast(tempShort); } - if(raw->bpc != 1) + if(raw.bpc != 1) ConvertShort(&pixel, 1); while (count--) { - if(raw->bpc == 1) + if(raw.bpc == 1) *oPtr++ = pixel; else { @@ -379,87 +384,87 @@ static void RawImageGetRow(rawImageRec *raw, unsigned char *buf, int y, int z) else { size_pos pos = static_cast(512)+ - (static_cast(y)*static_cast(raw->sizeX)*static_cast(raw->bpc))+ - (static_cast(z)*static_cast(raw->sizeX)*static_cast(raw->sizeY)*static_cast(raw->bpc)); + (static_cast(y)*static_cast(raw.sizeX)*static_cast(raw.bpc))+ + (static_cast(z)*static_cast(raw.sizeX)*static_cast(raw.sizeY)*static_cast(raw.bpc)); - size_pos amount = static_cast(raw->sizeX)*static_cast(raw->bpc); + size_pos amount = static_cast(raw.sizeX)*static_cast(raw.bpc); - raw->file->seekg(pos,std::ios::beg); - raw->file->read((char*)buf, amount); - if(raw->swapFlag && raw->bpc != 1){ - ConvertShort(reinterpret_cast(buf), raw->sizeX); + raw.file->seekg(pos,std::ios::beg); + raw.file->read((char*)buf, amount); + if(raw.swapFlag && raw.bpc != 1){ + ConvertShort(reinterpret_cast(buf), raw.sizeX); } } } -static void RawImageGetData(rawImageRec *raw, unsigned char **data ) +static void RawImageGetData(rawImageRec& raw, unsigned char **data ) { unsigned char *ptr; int i, j; unsigned short *tempShort; // // round the width to a factor 4 - // int width = (int)(floorf((float)raw->sizeX/4.0f)*4.0f); - // if (width!=raw->sizeX) width += 4; + // int width = (int)(floorf((float)raw.sizeX/4.0f)*4.0f); + // if (width!=raw.sizeX) width += 4; // byte aligned. - OSG_INFO<<"raw->sizeX = "<sizeX<sizeY = "<sizeY<sizeZ = "<sizeZ<bpc = "<bpc<getOptionString(); - size_t i = op.find("x"); - std::stringstream ss1(op.substr(0, i)); - std::stringstream ss2(op.substr(i+1, op.size())); - ss1 >> w; - ss2 >> h; - if (w==0 || h==0){ - image = createImage(handle, dimensionData.width, dimensionData.height); + size_t i = op.find("x"); + if (i!=std::string::npos) + { + + std::stringstream ss1(op.substr(0, i)); + std::stringstream ss2(op.substr(i+1, op.size())); + unsigned int w=0, h=0; + ss1 >> w; + ss2 >> h; + if (w!=0 && h!=0) + { + dimensionData.width = w; + dimensionData.height = h; + } } - else{ - image = createImage(handle, w, h); + + i = op.find("rs="); + if (i!=std::string::npos) + { + + std::stringstream ss(op.substr(i+3, op.size())); + double scale; + ss >> scale; + if (scale!=0.0) + { + dimensionData.width = dimensionData.width * scale; + dimensionData.height = dimensionData.height * scale; + } } } - else{ - image = createImage(handle, dimensionData.width, dimensionData.height); - } + + image = createImage(handle, dimensionData.width, dimensionData.height); + g_object_unref(handle); image->setFileName(file); return image; @@ -91,12 +110,15 @@ class ReaderWriterSVG : public osgDB::ReaderWriter // I don't know why, but we check the size... if (width < 128) width = 128; if (height < 128) height = 128; - width = osg::Image::computeNearestPowerOfTwo(width); - height = osg::Image::computeNearestPowerOfTwo(height); + //width = osg::Image::computeNearestPowerOfTwo(width); + //height = osg::Image::computeNearestPowerOfTwo(height); osg::Image *image = new osg::Image(); image->allocateImage(width, height, 1, GL_RGBA, GL_UNSIGNED_BYTE); image->setPixelFormat(GL_BGRA); + // make sure the image data is cleared before we write to it. + memset(image->data(), 0, image->getTotalSizeInBytesIncludingMipmaps()); + cairo_surface_t *cairo_surface = cairo_image_surface_create_for_data(image->data(), CAIRO_FORMAT_ARGB32, width, height, image->getRowSizeInBytes()); cairo_t *cr = cairo_create(cairo_surface); diff --git a/src/osgPlugins/tga/ReaderWriterTGA.cpp b/src/osgPlugins/tga/ReaderWriterTGA.cpp index b1e3ad6a4..861c61b70 100644 --- a/src/osgPlugins/tga/ReaderWriterTGA.cpp +++ b/src/osgPlugins/tga/ReaderWriterTGA.cpp @@ -360,8 +360,14 @@ int *numComponents_ret) { case 1: /* colormap, uncompressed */ { - if (colormapLen == 0 || indexsize == 0) { + if (colormapLen == 0 || indexsize == 0) + { tgaerror = ERR_UNSUPPORTED; /* colormap missing or empty */ + + if (colormap) delete [] colormap; + delete [] buffer; + delete [] linebuf; + return NULL; } unsigned char * formattedMap = new unsigned char[colormapLen * format]; @@ -399,6 +405,7 @@ int *numComponents_ret) break; default: tgaerror = ERR_UNSUPPORTED; + delete [] formattedMap; return NULL; /* unreachable code - (depth < 1 || depth > 4) rejected by "check for reasonable values in case this is not a tga file" near the start of this function*/ } @@ -409,8 +416,7 @@ int *numComponents_ret) dest += lineoffset; } - if (formattedMap) - delete[] formattedMap; + delete [] formattedMap; } break; case 2: /* RGB, uncompressed */ diff --git a/src/osgPlugins/vnc/ReaderWriterVNC.cpp b/src/osgPlugins/vnc/ReaderWriterVNC.cpp index 6da3ccbc3..ce68fd688 100644 --- a/src/osgPlugins/vnc/ReaderWriterVNC.cpp +++ b/src/osgPlugins/vnc/ReaderWriterVNC.cpp @@ -398,17 +398,26 @@ class ReaderWriterVNC : public osgDB::ReaderWriter options->getAuthenticationMap() : osgDB::Registry::instance()->getAuthenticationMap(); - const osgDB::AuthenticationDetails* details = authenticationMap ? - authenticationMap->getAuthenticationDetails(hostname) : - 0; - - // configure authentication if required. - if (details) + if (authenticationMap != NULL) { - OSG_NOTICE<<"Passing in password = "<password<getAuthenticationDetails(hostname); + if (details == NULL) + { + size_t pos = hostname.find(":"); + if (pos != std::string::npos) + { + details = authenticationMap->getAuthenticationDetails(hostname.substr(0, pos)); + } + } - image->_username = details->username; - image->_password = details->password; + // configure authentication if required. + if (details != NULL) + { + OSG_NOTICE << "Passing in password = " << details->password << std::endl; + + image->_username = details->username; + image->_password = details->password; + } } if (options && !options->getOptionString().empty()) diff --git a/src/osgPresentation/KeyEventHandler.cpp b/src/osgPresentation/KeyEventHandler.cpp index ad0373a57..f08fdc003 100644 --- a/src/osgPresentation/KeyEventHandler.cpp +++ b/src/osgPresentation/KeyEventHandler.cpp @@ -146,7 +146,7 @@ void KeyEventHandler::doOperation() } case(osgPresentation::JUMP): { - OSG_NOTICE<<"Requires jump "<dispatchEvent(_keyPos); break; } diff --git a/src/osgPresentation/SlideEventHandler.cpp b/src/osgPresentation/SlideEventHandler.cpp index d88ba4c3f..4c3d22a04 100644 --- a/src/osgPresentation/SlideEventHandler.cpp +++ b/src/osgPresentation/SlideEventHandler.cpp @@ -40,7 +40,7 @@ SlideEventHandler* SlideEventHandler::instance() { return s_seh.get(); } bool JumpData::jump(SlideEventHandler* seh) const { - OSG_NOTICE<<"Requires jump"<s() : 1.0; float t = useTextureRectangle ? image->t() : 1.0; - osg::Geometry* backgroundQuad = osg::createTexturedQuadGeometry(_slideOrigin, + osg::Vec3 backgroundShift(0.0f, _slideWidth*0.0001f, 0.0f); + osg::Geometry* backgroundQuad = osg::createTexturedQuadGeometry(_slideOrigin+backgroundShift, osg::Vec3(_slideWidth,0.0f,0.0f), osg::Vec3(0.0f,0.0f,_slideHeight), s, t); diff --git a/src/osgSim/OverlayNode.cpp b/src/osgSim/OverlayNode.cpp index dbd2e0be2..343d20878 100644 --- a/src/osgSim/OverlayNode.cpp +++ b/src/osgSim/OverlayNode.cpp @@ -19,6 +19,7 @@ #include #include +#include #include #include @@ -1028,7 +1029,7 @@ OverlayNode::OverlayData* OverlayNode::getOverlayData(osgUtil::CullVisitor* cv) std::string vertexShaderFile = osgDB::findDataFile("shaders/overlay_perspective_rtt.vert"); if (!vertexShaderFile.empty()) { - program->addShader(osg::Shader::readShaderFile(osg::Shader::VERTEX, vertexShaderFile)); + program->addShader(osgDB::readRefShaderFile(osg::Shader::VERTEX, vertexShaderFile)); } else { @@ -1119,7 +1120,7 @@ OverlayNode::OverlayData* OverlayNode::getOverlayData(osgUtil::CullVisitor* cv) std::string fragmentShaderFile = osgDB::findDataFile("shaders/overlay_perspective_main.frag"); if (!fragmentShaderFile.empty()) { - overlayData->_mainSubgraphProgram->addShader(osg::Shader::readShaderFile(osg::Shader::FRAGMENT, fragmentShaderFile)); + overlayData->_mainSubgraphProgram->addShader(osgDB::readRefShaderFile(osg::Shader::FRAGMENT, fragmentShaderFile)); } else { diff --git a/src/osgTerrain/GeometryPool.cpp b/src/osgTerrain/GeometryPool.cpp index c7fb3c5f8..45b00fef9 100644 --- a/src/osgTerrain/GeometryPool.cpp +++ b/src/osgTerrain/GeometryPool.cpp @@ -554,7 +554,10 @@ osg::ref_ptr GeometryPool::getOrCreateProgram(LayerTypes& layerTyp _programMap[layerTypes] = program; // add shader that provides the lighting functions - program->addShader(osgDB::readRefShaderFile("shaders/lighting.vert")); + { + #include "shaders/lighting_vert.cpp" + program->addShader(osgDB::readRefShaderFileWithFallback(osg::Shader::VERTEX, "shaders/lighting.vert", lighting_vert)); + } // OSG_NOTICE<<") creating new Program "<getElementBufferObject(); osg::GLBufferObject* ebo_glBufferObject = ebo->getOrCreateGLBufferObject(contextID); - if (ebo_glBufferObject && vbo_glBufferObject->isDirty()) + if (ebo_glBufferObject && ebo_glBufferObject->isDirty()) { // OSG_NOTICE<<"Compile buffer "<compileBuffer(); diff --git a/src/osgTerrain/shaders/lighting_vert.cpp b/src/osgTerrain/shaders/lighting_vert.cpp new file mode 100644 index 000000000..a0ac0f8ac --- /dev/null +++ b/src/osgTerrain/shaders/lighting_vert.cpp @@ -0,0 +1,25 @@ +char lighting_vert[] = "#pragma requires(LIGHTING)\n" + "\n" + "void directionalLight( int lightNum, vec3 normal, inout vec4 color )\n" + "{\n" + " vec3 n = normalize(gl_NormalMatrix * normal);\n" + "\n" + " float NdotL = dot( n, normalize(gl_LightSource[lightNum].position.xyz) );\n" + " NdotL = max( 0.0, NdotL );\n" + "\n" + " float NdotHV = dot( n, gl_LightSource[lightNum].halfVector.xyz );\n" + " NdotHV = max( 0.0, NdotHV );\n" + "#if 1\n" + " color *= gl_LightSource[lightNum].ambient +\n" + " gl_LightSource[lightNum].diffuse * NdotL;\n" + "#else\n" + " color *= gl_FrontLightModelProduct.sceneColor +\n" + " gl_FrontLightProduct[lightNum].ambient +\n" + " gl_FrontLightProduct[lightNum].diffuse * NdotL;\n" + "#endif\n" + "#if 0\n" + " if ( NdotL * NdotHV > 0.0 )\n" + " color += gl_FrontLightProduct[lightNum].specular * pow( NdotHV, gl_FrontMaterial.shininess );\n" + "#endif\n" + "}\n" + "\n"; diff --git a/src/osgTerrain/shaders/terrain_displacement_mapping_vert.cpp b/src/osgTerrain/shaders/terrain_displacement_mapping_vert.cpp index b3b0ce5d9..a052d4dc1 100644 --- a/src/osgTerrain/shaders/terrain_displacement_mapping_vert.cpp +++ b/src/osgTerrain/shaders/terrain_displacement_mapping_vert.cpp @@ -125,5 +125,5 @@ char terrain_displacement_mapping_vert[] = "#version 120\n" " vec3 position = gl_Vertex.xyz + gl_Normal.xyz * height_center;\n" " gl_Position = gl_ModelViewProjectionMatrix * vec4(position,1.0);\n" "\n" - "};\n" + "}\n" "\n"; diff --git a/src/osgText/DefaultFont.cpp b/src/osgText/DefaultFont.cpp index cf0b55cc4..dfc9b5945 100644 --- a/src/osgText/DefaultFont.cpp +++ b/src/osgText/DefaultFont.cpp @@ -24,8 +24,11 @@ using namespace osgText; DefaultFont::DefaultFont() { + _fontSize = FontResolution(8,12); + _minFilterHint = osg::Texture::LINEAR_MIPMAP_LINEAR; - _magFilterHint = osg::Texture::NEAREST; + _magFilterHint = osg::Texture::LINEAR; + constructGlyphs(); } @@ -198,14 +201,12 @@ void DefaultFont::constructGlyphs() for(unsigned char* p=data;psetImage(sourceWidth,sourceHeight,1, - OSGTEXT_GLYPH_INTERNALFORMAT, - OSGTEXT_GLYPH_FORMAT, GL_UNSIGNED_BYTE, + GL_ALPHA, + GL_ALPHA, GL_UNSIGNED_BYTE, data, osg::Image::USE_NEW_DELETE, 1); - glyph->setInternalTextureFormat(OSGTEXT_GLYPH_INTERNALFORMAT); - // now populate data array by converting bitmap into a luminance_alpha map. unsigned char* ptr = rasters[i-32]; unsigned char value_on = 255; @@ -233,6 +234,8 @@ void DefaultFont::constructGlyphs() glyph->setVerticalBearing(osg::Vec2(0.5f,1.0f)); // top middle. glyph->setVerticalAdvance(sourceHeight*coord_scale); + glyph->setFontResolution(fontRes); + addGlyph(fontRes,i,glyph.get()); } } diff --git a/src/osgText/Font.cpp b/src/osgText/Font.cpp index c06392640..599dd6f6e 100644 --- a/src/osgText/Font.cpp +++ b/src/osgText/Font.cpp @@ -32,81 +32,6 @@ using namespace osgText; using namespace std; -#if (!defined(OSG_GLES2_AVAILABLE) && !defined(OSG_GLES3_AVAILABLE)) - #define GLSL_VERSION_STR "330 core" - #define GLYPH_CMP "r" -#else - #define GLSL_VERSION_STR "300 es" - #define GLYPH_CMP "a" -#endif - -static const char* gl3_TextVertexShader = { - "#version " GLSL_VERSION_STR "\n" - "// gl3_TextVertexShader\n" - "#ifdef GL_ES\n" - " precision highp float;\n" - "#endif\n" - "in vec4 osg_Vertex;\n" - "in vec4 osg_Color;\n" - "in vec4 osg_MultiTexCoord0;\n" - "uniform mat4 osg_ModelViewProjectionMatrix;\n" - "out vec2 texCoord;\n" - "out vec4 vertexColor;\n" - "void main(void)\n" - "{\n" - " gl_Position = osg_ModelViewProjectionMatrix * osg_Vertex;\n" - " texCoord = osg_MultiTexCoord0.xy;\n" - " vertexColor = osg_Color; \n" - "}\n" -}; - -static const char* gl3_TextFragmentShader = { - "#version " GLSL_VERSION_STR "\n" - "// gl3_TextFragmentShader\n" - "#ifdef GL_ES\n" - " precision highp float;\n" - "#endif\n" - "uniform sampler2D glyphTexture;\n" - "in vec2 texCoord;\n" - "in vec4 vertexColor;\n" - "out vec4 color;\n" - "void main(void)\n" - "{\n" - " if (texCoord.x>=0.0) color = vertexColor * vec4(1.0, 1.0, 1.0, texture(glyphTexture, texCoord)." GLYPH_CMP ");\n" - " else color = vertexColor;\n" - "}\n" -}; - -static const char* gl2_TextVertexShader = { - "// gl2_TextVertexShader\n" - "#ifdef GL_ES\n" - " precision highp float;\n" - "#endif\n" - "varying vec2 texCoord;\n" - "varying vec4 vertexColor;\n" - "void main(void)\n" - "{\n" - " gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n" - " texCoord = gl_MultiTexCoord0.xy;\n" - " vertexColor = gl_Color; \n" - "}\n" -}; - -static const char* gl2_TextFragmentShader = { - "// gl2_TextFragmentShader\n" - "#ifdef GL_ES\n" - " precision highp float;\n" - "#endif\n" - "uniform sampler2D glyphTexture;\n" - "varying vec2 texCoord;\n" - "varying vec4 vertexColor;\n" - "void main(void)\n" - "{\n" - " if (texCoord.x>=0.0) gl_FragColor = vertexColor * vec4(1.0, 1.0, 1.0, texture2D(glyphTexture, texCoord).a);\n" - " else gl_FragColor = vertexColor;\n" - "}\n" -}; - osg::ref_ptr& Font::getDefaultFont() { static OpenThreads::Mutex s_DefaultFontMutex; @@ -299,67 +224,24 @@ osg::ref_ptr osgText::readRefFontStream(std::istream& stream, const osgDB: Font::Font(FontImplementation* implementation): osg::Object(true), - _margin(1), - _marginRatio(0.02), _textureWidthHint(1024), _textureHeightHint(1024), _minFilterHint(osg::Texture::LINEAR_MIPMAP_LINEAR), _magFilterHint(osg::Texture::LINEAR), + _maxAnisotropy(16), _depth(1), _numCurveSamples(10) { setImplementation(implementation); - _texenv = new osg::TexEnv; - _stateset = new osg::StateSet; - - _stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN); - _stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF); - _stateset->setMode(GL_BLEND, osg::StateAttribute::ON); - -#if defined(OSG_GL_FIXED_FUNCTION_AVAILABLE) - - OSG_INFO<<"Font::Font() Fixed function pipeline"<setTextureMode(0, GL_TEXTURE_2D, osg::StateAttribute::ON); -#endif - - osg::DisplaySettings::ShaderHint shaderHint = osg::DisplaySettings::instance()->getShaderHint(); - if (shaderHint==osg::DisplaySettings::SHADER_GL3 || shaderHint==osg::DisplaySettings::SHADER_GLES3) - { - - OSG_INFO<<"Font::Font() Setting up GL3 compatible shaders"< program = new osg::Program; - program->addShader(new osg::Shader(osg::Shader::VERTEX, gl3_TextVertexShader)); - program->addShader(new osg::Shader(osg::Shader::FRAGMENT, gl3_TextFragmentShader)); - _stateset->setAttributeAndModes(program.get()); - _stateset->addUniform(new osg::Uniform("glyphTexture", 0)); - - } - else if (shaderHint==osg::DisplaySettings::SHADER_GL2 || shaderHint==osg::DisplaySettings::SHADER_GLES2) - { - - - OSG_INFO<<"Font::Font() Setting up GL2 compatible shaders"< program = new osg::Program; - program->addShader(new osg::Shader(osg::Shader::VERTEX, gl2_TextVertexShader)); - program->addShader(new osg::Shader(osg::Shader::FRAGMENT, gl2_TextFragmentShader)); - _stateset->setAttributeAndModes(program.get()); - _stateset->addUniform(new osg::Uniform("glyphTexture", 0)); - - } - char *ptr; - if( (ptr = getenv("OSG_MAX_TEXTURE_SIZE")) != 0) + if ((ptr = getenv("OSG_MAX_TEXTURE_SIZE")) != 0) { unsigned int osg_max_size = atoi(ptr); if (osg_max_size<_textureWidthHint) _textureWidthHint = osg_max_size; if (osg_max_size<_textureHeightHint) _textureHeightHint = osg_max_size; } - } Font::~Font() @@ -390,26 +272,6 @@ std::string Font::getFileName() const return std::string(); } -void Font::setGlyphImageMargin(unsigned int margin) -{ - _margin = margin; -} - -unsigned int Font::getGlyphImageMargin() const -{ - return _margin; -} - -void Font::setGlyphImageMarginRatio(float ratio) -{ - _marginRatio = ratio; -} - -float Font::getGlyphImageMarginRatio() const -{ - return _marginRatio; -} - void Font::setTextureSizeHint(unsigned int width,unsigned int height) { _textureWidthHint = width; @@ -518,9 +380,6 @@ void Font::setThreadSafeRefUnref(bool threadSafe) { osg::Object::setThreadSafeRefUnref(threadSafe); - if (_texenv.valid()) _texenv->setThreadSafeRefUnref(threadSafe); - if (_stateset.valid()) _stateset->setThreadSafeRefUnref(threadSafe); - for(GlyphTextureList::const_iterator itr=_glyphTextureList.begin(); itr!=_glyphTextureList.end(); ++itr) @@ -531,7 +390,12 @@ void Font::setThreadSafeRefUnref(bool threadSafe) void Font::resizeGLObjectBuffers(unsigned int maxSize) { - if (_stateset.valid()) _stateset->resizeGLObjectBuffers(maxSize); + for(StateSets::iterator itr = _statesets.begin(); + itr != _statesets.end(); + ++itr) + { + (*itr)->resizeGLObjectBuffers(maxSize); + } for(GlyphTextureList::const_iterator itr=_glyphTextureList.begin(); itr!=_glyphTextureList.end(); @@ -543,7 +407,12 @@ void Font::resizeGLObjectBuffers(unsigned int maxSize) void Font::releaseGLObjects(osg::State* state) const { - if (_stateset.valid()) _stateset->releaseGLObjects(state); + for(StateSets::const_iterator itr = _statesets.begin(); + itr != _statesets.end(); + ++itr) + { + (*itr)->releaseGLObjects(state); + } for(GlyphTextureList::const_iterator itr=_glyphTextureList.begin(); itr!=_glyphTextureList.end(); @@ -576,6 +445,10 @@ void Font::addGlyph(const FontResolution& fontRes, unsigned int charcode, Glyph* _sizeGlyphMap[fontRes][charcode]=glyph; +} + +void Font::assignGlyphToGlyphTexture(Glyph* glyph, ShaderTechnique shaderTechnique) +{ int posX=0,posY=0; GlyphTexture* glyphTexture = 0; @@ -583,12 +456,12 @@ void Font::addGlyph(const FontResolution& fontRes, unsigned int charcode, Glyph* itr!=_glyphTextureList.end() && !glyphTexture; ++itr) { - if ((*itr)->getSpaceForGlyph(glyph,posX,posY)) glyphTexture = itr->get(); + if ((*itr)->getShaderTechnique()==shaderTechnique && (*itr)->getSpaceForGlyph(glyph,posX,posY)) glyphTexture = itr->get(); } if (glyphTexture) { - //cout << " found space for texture "<setGlyphImageMargin(_margin); - glyphTexture->setGlyphImageMarginRatio(_marginRatio); + glyphTexture->setShaderTechnique(shaderTechnique); glyphTexture->setTextureSize(_textureWidthHint,_textureHeightHint); glyphTexture->setFilter(osg::Texture::MIN_FILTER,_minFilterHint); glyphTexture->setFilter(osg::Texture::MAG_FILTER,_magFilterHint); - glyphTexture->setMaxAnisotropy(8); + glyphTexture->setMaxAnisotropy(_maxAnisotropy); _glyphTextureList.push_back(glyphTexture); @@ -621,5 +493,4 @@ void Font::addGlyph(const FontResolution& fontRes, unsigned int charcode, Glyph* // add the glyph into the texture. glyphTexture->addGlyph(glyph,posX,posY); - } diff --git a/src/osgText/Glyph.cpp b/src/osgText/Glyph.cpp index 3bc346c8f..ed8c7120b 100644 --- a/src/osgText/Glyph.cpp +++ b/src/osgText/Glyph.cpp @@ -28,9 +28,35 @@ using namespace osgText; using namespace std; +// GL_ALPHA and GL_LUMINANCE_ALPHA are deprecated in GL3/GL4 core profile, use GL_RED & GL_RB in this case. +#if defined(OSG_GL3_AVAILABLE) && !defined(OSG_GL2_AVAILABLE) && !defined(OSG_GL1_AVAILABLE) +#define OSGTEXT_GLYPH_ALPHA_FORMAT GL_RED +#define OSGTEXT_GLYPH_ALPHA_INTERNALFORMAT GL_R8 +#define OSGTEXT_GLYPH_SDF_FORMAT GL_RG +#define OSGTEXT_GLYPH_SDF_INTERNALFORMAT GL_RG8 +#else +#define OSGTEXT_GLYPH_ALPHA_FORMAT GL_ALPHA +#define OSGTEXT_GLYPH_ALPHA_INTERNALFORMAT GL_ALPHA +#define OSGTEXT_GLYPH_SDF_FORMAT GL_LUMINANCE_ALPHA +#define OSGTEXT_GLYPH_SDF_INTERNALFORMAT GL_LUMINANCE_ALPHA +#endif + + +#if 0 + #define TEXTURE_IMAGE_NUM_CHANNELS 1 + #define TEXTURE_IMAGE_FORMAT OSGTEXT_GLYPH_FORMAT +#else + #define TEXTURE_IMAGE_NUM_CHANNELS 2 + #define TEXTURE_IMAGE_FORMAT GL_RGBA +#endif + + +////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// GlyphTexture +// GlyphTexture::GlyphTexture(): - _margin(1), - _marginRatio(0.02f), + _shaderTechnique(GREYSCALE), _usedY(0), _partUsedX(0), _partUsedY(0) @@ -51,27 +77,52 @@ int GlyphTexture::compare(const osg::StateAttribute& rhs) const return 0; } +int GlyphTexture::getEffectMargin(const Glyph* glyph) +{ + if (_shaderTechnique==GREYSCALE) return 0; + else return osg::maximum(glyph->getFontResolution().second/6, 2u); +} + +int GlyphTexture::getTexelMargin(const Glyph* glyph) +{ + int width = glyph->s(); + int height = glyph->t(); + int effect_margin = getEffectMargin(glyph); + + int max_dimension = osg::maximum(width, height) + 2 * effect_margin; + int margin = osg::maximum(max_dimension/4, 2) + effect_margin; + + return margin; +} bool GlyphTexture::getSpaceForGlyph(Glyph* glyph, int& posX, int& posY) { - int maxAxis = osg::maximum(glyph->s(), glyph->t()); - int margin = _margin + (int)((float)maxAxis * _marginRatio); + int width = glyph->s(); + int height = glyph->t(); - int width = glyph->s()+2*margin; - int height = glyph->t()+2*margin; + int margin = getTexelMargin(glyph); - // first check box (_partUsedX,_usedY) to (width,height) - if (width <= (getTextureWidth()-_partUsedX) && - height <= (getTextureHeight()-_usedY)) + width += 2*margin; + height += 2*margin; + + int interval = 4; + + int partUsedX = ((_partUsedX % interval) == 0) ? _partUsedX : (((_partUsedX/interval)+1)*interval); + int partUsedY = ((_partUsedY % interval) == 0) ? _partUsedY : (((_partUsedY/interval)+1)*interval); + int usedY = ((_usedY % interval) == 0) ? _usedY : (((_usedY/interval)+1)*interval); + + // first check box (partUsedX, usedY) to (width,height) + if (width <= (getTextureWidth()-partUsedX) && + height <= (getTextureHeight()-usedY)) { // can fit in existing row. // record the position in which the texture will be stored. - posX = _partUsedX+margin; - posY = _usedY+margin; + posX = partUsedX+margin; + posY = usedY+margin; // move used markers on. - _partUsedX += width; + _partUsedX = posX+width; if (_usedY+height>_partUsedY) _partUsedY = _usedY+height; return true; @@ -83,14 +134,14 @@ bool GlyphTexture::getSpaceForGlyph(Glyph* glyph, int& posX, int& posY) { // can fit next row. _partUsedX = 0; - _usedY = _partUsedY; + _usedY = partUsedY; posX = _partUsedX+margin; posY = _usedY+margin; // move used markers on. - _partUsedX += width; - if (_usedY+height>_partUsedY) _partUsedY = _usedY+height; + _partUsedX = posX+width; + _partUsedY = _usedY+height; return true; } @@ -101,23 +152,237 @@ bool GlyphTexture::getSpaceForGlyph(Glyph* glyph, int& posX, int& posY) void GlyphTexture::addGlyph(Glyph* glyph, int posX, int posY) { + OpenThreads::ScopedLock lock(_mutex); if (!_image.valid()) createImage(); _glyphs.push_back(glyph); - // set up the details of where to place glyph's image in the texture. - glyph->setTexture(this); - glyph->setTexturePosition(posX,posY); + osg::ref_ptr info = new Glyph::TextureInfo( + this, + posX, posY, + osg::Vec2( static_cast(posX)/static_cast(getTextureWidth()), static_cast(posY)/static_cast(getTextureHeight()) ), // minTexCoord + osg::Vec2( static_cast(posX+glyph->s())/static_cast(getTextureWidth()), static_cast(posY+glyph->t())/static_cast(getTextureHeight()) ), // maxTexCoord + float(getTexelMargin(glyph))); // margin - glyph->setMinTexCoord( osg::Vec2( static_cast(posX)/static_cast(getTextureWidth()), - static_cast(posY)/static_cast(getTextureHeight()) ) ); - glyph->setMaxTexCoord( osg::Vec2( static_cast(posX+glyph->s())/static_cast(getTextureWidth()), - static_cast(posY+glyph->t())/static_cast(getTextureHeight()) ) ); + glyph->setTextureInfo(_shaderTechnique, info.get()); - _image->copySubImage(glyph->getTexturePositionX(), glyph->getTexturePositionY(), 0, glyph); + copyGlyphImage(glyph, info.get()); +} + +void GlyphTexture::copyGlyphImage(Glyph* glyph, Glyph::TextureInfo* info) +{ _image->dirty(); + + if (_shaderTechnique<=GREYSCALE) + { + // OSG_NOTICE<<"GlyphTexture::copyGlyphImage() greyscale copying. glyphTexture="<get(); - _image->copySubImage(glyph->getTexturePositionX(), glyph->getTexturePositionY(), 0, glyph); - } + _image = new osg::Image; + + GLenum imageFormat = (_shaderTechnique<=GREYSCALE) ? OSGTEXT_GLYPH_ALPHA_FORMAT : OSGTEXT_GLYPH_SDF_FORMAT; + GLenum internalFormat = (_shaderTechnique<=GREYSCALE) ? OSGTEXT_GLYPH_ALPHA_INTERNALFORMAT : OSGTEXT_GLYPH_SDF_INTERNALFORMAT; + + _image->allocateImage(getTextureWidth(), getTextureHeight(), 1, imageFormat, GL_UNSIGNED_BYTE); + _image->setInternalTextureFormat(internalFormat); + + memset(_image->data(), 0, _image->getTotalSizeInBytes()); } return _image.get(); } +////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Glyph +// // all the methods in Font::Glyph have been made non inline because VisualStudio6.0 is STUPID, STUPID, STUPID PILE OF JUNK. Glyph::Glyph(Font* font, unsigned int glyphCode): _font(font), @@ -172,12 +441,7 @@ Glyph::Glyph(Font* font, unsigned int glyphCode): _horizontalBearing(0.0f,0.f), _horizontalAdvance(0.f), _verticalBearing(0.0f,0.f), - _verticalAdvance(0.f), - _texture(0), - _texturePosX(0), - _texturePosY(0), - _minTexCoord(0.0f,0.0f), - _maxTexCoord(0.0f,0.0f) + _verticalAdvance(0.f) { setThreadSafeRefUnref(true); } @@ -198,67 +462,37 @@ const osg::Vec2& Glyph::getVerticalBearing() const { return _verticalBearing; } void Glyph::setVerticalAdvance(float advance) { _verticalAdvance=advance; } float Glyph::getVerticalAdvance() const { return _verticalAdvance; } -void Glyph::setTexture(GlyphTexture* texture) { _texture = texture; } -GlyphTexture* Glyph::getTexture() { return _texture; } -const GlyphTexture* Glyph::getTexture() const { return _texture; } - -void Glyph::setTexturePosition(int posX,int posY) { _texturePosX = posX; _texturePosY = posY; } -int Glyph::getTexturePositionX() const { return _texturePosX; } -int Glyph::getTexturePositionY() const { return _texturePosY; } - -void Glyph::setMinTexCoord(const osg::Vec2& coord) { _minTexCoord=coord; } -const osg::Vec2& Glyph::getMinTexCoord() const { return _minTexCoord; } - -void Glyph::setMaxTexCoord(const osg::Vec2& coord) { _maxTexCoord=coord; } -const osg::Vec2& Glyph::getMaxTexCoord() const { return _maxTexCoord; } - -void Glyph::subload() const +void Glyph::setTextureInfo(ShaderTechnique technique, TextureInfo* info) { - GLenum errorNo = glGetError(); - if (errorNo!=GL_NO_ERROR) + if (technique>=_textureInfoList.size()) { - const GLubyte* msg = osg::gluErrorString(errorNo); - if (msg) { OSG_WARN<<"before Glyph::subload(): detected OpenGL error: "<(data())<<");"<=_textureInfoList.size()) + { + _textureInfoList.resize(technique+1); + } + if (!_textureInfoList[technique]) + { + _font->assignGlyphToGlyphTexture(this, technique); + } + return _textureInfoList[technique].get(); +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Glyph3D +// Glyph3D::Glyph3D(Font* font, unsigned int glyphCode): osg::Referenced(true), _font(font), diff --git a/src/osgText/Text.cpp b/src/osgText/Text.cpp index 53a5d3b1a..6a2d2f96c 100644 --- a/src/osgText/Text.cpp +++ b/src/osgText/Text.cpp @@ -25,13 +25,19 @@ #include +#include +#include + +#define DEBUG_MESSAGE_LEVEL osg::INFO +#define DEBUG_MESSAGE osg::notify(DEBUG_MESSAGE_LEVEL) + using namespace osg; using namespace osgText; Text::Text(): + _shaderTechnique(GREYSCALE), _enableDepthWrites(true), _backdropType(NONE), - _backdropImplementation(DELAYED_DEPTH_WRITES), _backdropHorizontalOffset(0.07f), _backdropVerticalOffset(0.07f), _backdropColor(0.0f, 0.0f, 0.0f, 1.0f), @@ -42,13 +48,24 @@ Text::Text(): _colorGradientTopRight(1.0f, 1.0f, 1.0f, 1.0f) { _supportsVertexBufferObjects = true; + + const std::string& str = osg::DisplaySettings::instance()->getTextShaderTechnique(); + if (!str.empty()) + { + if (str=="ALL_FEATURES" || str=="ALL") _shaderTechnique = ALL_FEATURES; + else if (str=="GREYSCALE") _shaderTechnique = GREYSCALE; + else if (str=="SIGNED_DISTANCE_FIELD" || str=="SDF") _shaderTechnique = SIGNED_DISTANCE_FIELD; + else if (str=="NO_TEXT_SHADER" || str=="NONE") _shaderTechnique = NO_TEXT_SHADER; + } + + assignStateSet(); } Text::Text(const Text& text,const osg::CopyOp& copyop): osgText::TextBase(text,copyop), + _shaderTechnique(text._shaderTechnique), _enableDepthWrites(text._enableDepthWrites), _backdropType(text._backdropType), - _backdropImplementation(text._backdropImplementation), _backdropHorizontalOffset(text._backdropHorizontalOffset), _backdropVerticalOffset(text._backdropVerticalOffset), _backdropColor(text._backdropColor), @@ -65,21 +82,170 @@ Text::~Text() { } -void Text::setFont(osg::ref_ptr font) + +void Text::setShaderTechnique(ShaderTechnique technique) { - if (_font==font) return; + if (_shaderTechnique==technique) return; - osg::StateSet* previousFontStateSet = _font.valid() ? _font->getStateSet() : Font::getDefaultFont()->getStateSet(); - osg::StateSet* newFontStateSet = font.valid() ? font->getStateSet() : Font::getDefaultFont()->getStateSet(); + _shaderTechnique = technique; - if (getStateSet() == previousFontStateSet) - { - setStateSet( newFontStateSet ); - } + assignStateSet(); - TextBase::setFont(font); + computeGlyphRepresentation(); } +osg::StateSet* Text::createStateSet() +{ + Font* activeFont = getActiveFont(); + if (!activeFont) return 0; + + Font::StateSets& statesets = activeFont->getCachedStateSets(); + + std::stringstream ss; + ss<getTextureWidthHint()); + defineList["TEXTURE_DIMENSION"] = osg::StateSet::DefinePair(ss.str(), osg::StateAttribute::ON); + } + + if (_shaderTechnique>GREYSCALE) + { + defineList["SIGNED_DISTNACE_FIELD"] = osg::StateSet::DefinePair("1", osg::StateAttribute::ON); + } + +#if 0 + OSG_NOTICE<<"Text::createStateSet() defines:"<first<<"] = "<second.first<getDefineList()==defineList) + { + // OSG_NOTICE<<"Text::createStateSet() : Matched DefineList, return StateSet "<get()<get(); + } + else + { + } + } + } + + + if (osg::isNotifyEnabled(DEBUG_MESSAGE_LEVEL)) + { + DEBUG_MESSAGE<<"Text::createStateSet() ShaderTechnique "; + switch(_shaderTechnique) + { + case(NO_TEXT_SHADER) : DEBUG_MESSAGE<<"NO_TEXT_SHADER"< stateset = new osg::StateSet; + + stateset->setDefineList(defineList); + + statesets.push_back(stateset.get()); + + stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN); + stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF); + stateset->setMode(GL_BLEND, osg::StateAttribute::ON); + + + #if defined(OSG_GL_FIXED_FUNCTION_AVAILABLE) + osg::DisplaySettings::ShaderHint shaderHint = osg::DisplaySettings::instance()->getShaderHint(); + if (_shaderTechnique==NO_TEXT_SHADER && shaderHint==osg::DisplaySettings::SHADER_NONE) + { + DEBUG_MESSAGE<<"Font::Font() Fixed function pipeline"<setTextureMode(0, GL_TEXTURE_2D, osg::StateAttribute::ON); + return stateset.release(); + } + #endif + + // set up the StateSet to use shaders + stateset->addUniform(new osg::Uniform("glyphTexture", 0)); + + osg::ref_ptr program = new osg::Program; + stateset->setAttributeAndModes(program.get()); + + { + DEBUG_MESSAGE<<"Using shaders/text.vert"<addShader(osgDB::readRefShaderFileWithFallback(osg::Shader::VERTEX, "shaders/text.vert", text_vert)); + } + + { + DEBUG_MESSAGE<<"Using shaders/text.frag"<addShader(osgDB::readRefShaderFileWithFallback(osg::Shader::FRAGMENT, "shaders/text.frag", text_frag)); + } + + return stateset.release(); +} Font* Text::getActiveFont() { @@ -225,22 +391,20 @@ String::iterator Text::computeLastCharacterOnLine(osg::Vec2& cursor, String::ite void Text::addGlyphQuad(Glyph* glyph, const osg::Vec2& minc, const osg::Vec2& maxc, const osg::Vec2& mintc, const osg::Vec2& maxtc) { // set up the coords of the quad - GlyphQuads& glyphquad = _textureGlyphQuadMap[glyph->getTexture()]; + const Glyph::TextureInfo* info = glyph->getOrCreateTextureInfo(_shaderTechnique); + GlyphTexture* glyphTexture = info ? info->texture : 0; + GlyphQuads& glyphquad = _textureGlyphQuadMap[glyphTexture]; glyphquad._glyphs.push_back(glyph); - osg::DrawElements* primitives = 0; - if (glyphquad._primitives.empty()) + osg::DrawElements* primitives = glyphquad._primitives.get(); + if (!primitives) { unsigned int maxIndices = _text.size()*4; if (maxIndices>=16384) primitives = new osg::DrawElementsUInt(GL_TRIANGLES); else primitives = new osg::DrawElementsUShort(GL_TRIANGLES); primitives->setBufferObject(_ebo.get()); - glyphquad._primitives.push_back(primitives); - } - else - { - primitives = glyphquad._primitives[0].get(); + glyphquad._primitives = primitives; } @@ -280,25 +444,18 @@ void Text::computeGlyphRepresentation() if (!_texcoords) { _texcoords = new osg::Vec2Array(osg::Array::BIND_PER_VERTEX); _texcoords->setBufferObject(_vbo.get()); } else _texcoords->clear(); -#if 0 - _textureGlyphQuadMap.clear(); -#else for(TextureGlyphQuadMap::iterator itr = _textureGlyphQuadMap.begin(); itr != _textureGlyphQuadMap.end(); ++itr) { GlyphQuads& glyphquads = itr->second; glyphquads._glyphs.clear(); - for(Primitives::iterator pitr = glyphquads._primitives.begin(); - pitr != glyphquads._primitives.end(); - ++pitr) + if (glyphquads._primitives.valid()) { - (*pitr)->resizeElements(0); - (*pitr)->dirty(); + glyphquads._primitives->resizeElements(0); + glyphquads._primitives->dirty(); } } -#endif - _lineCount = 0; @@ -487,45 +644,53 @@ void Text::computeGlyphRepresentation() local.x() += bearing.x() * wr; local.y() += bearing.y() * hr; - - // Adjust coordinates and texture coordinates to avoid - // clipping the edges of antialiased characters. - osg::Vec2 mintc = glyph->getMinTexCoord(); - osg::Vec2 maxtc = glyph->getMaxTexCoord(); - osg::Vec2 vDiff = maxtc - mintc; - - float fHorizTCMargin = 1.0f / glyph->getTexture()->getTextureWidth(); - float fVertTCMargin = 1.0f / glyph->getTexture()->getTextureHeight(); - float fHorizQuadMargin = vDiff.x() == 0.0f ? 0.0f : width * fHorizTCMargin / vDiff.x(); - float fVertQuadMargin = vDiff.y() == 0.0f ? 0.0f : height * fVertTCMargin / vDiff.y(); - - mintc.x() -= fHorizTCMargin; - mintc.y() -= fVertTCMargin; - maxtc.x() += fHorizTCMargin; - maxtc.y() += fVertTCMargin; - osg::Vec2 minc = local+osg::Vec2(0.0f-fHorizQuadMargin,0.0f-fVertQuadMargin); - osg::Vec2 maxc = local+osg::Vec2(width+fHorizQuadMargin,height+fVertQuadMargin); - - addGlyphQuad(glyph, minc, maxc, mintc, maxtc); - - // move the cursor onto the next character. - // also expand bounding box - switch(_layout) + const Glyph::TextureInfo* info = glyph->getOrCreateTextureInfo(_shaderTechnique); + if (info) { - case LEFT_TO_RIGHT: - cursor.x() += glyph->getHorizontalAdvance() * wr; - _textBB.expandBy(osg::Vec3(minc.x(), minc.y(), 0.0f)); //lower left corner - _textBB.expandBy(osg::Vec3(maxc.x(), maxc.y(), 0.0f)); //upper right corner - break; - case VERTICAL: - cursor.y() -= glyph->getVerticalAdvance() * hr; - _textBB.expandBy(osg::Vec3(minc.x(),maxc.y(),0.0f)); //upper left corner - _textBB.expandBy(osg::Vec3(maxc.x(),minc.y(),0.0f)); //lower right corner - break; - case RIGHT_TO_LEFT: - _textBB.expandBy(osg::Vec3(maxc.x(),minc.y(),0.0f)); //lower right corner - _textBB.expandBy(osg::Vec3(minc.x(),maxc.y(),0.0f)); //upper left corner - break; + // Adjust coordinates and texture coordinates to avoid + // clipping the edges of antialiased characters. + osg::Vec2 mintc = info->minTexCoord; + osg::Vec2 maxtc = info->maxTexCoord; + osg::Vec2 vDiff = maxtc - mintc; + float texelMargin = info->texelMargin; + + float fHorizTCMargin = texelMargin / info->texture->getTextureWidth(); + float fVertTCMargin = texelMargin / info->texture->getTextureHeight(); + float fHorizQuadMargin = vDiff.x() == 0.0f ? 0.0f : width * fHorizTCMargin / vDiff.x(); + float fVertQuadMargin = vDiff.y() == 0.0f ? 0.0f : height * fVertTCMargin / vDiff.y(); + + mintc.x() -= fHorizTCMargin; + mintc.y() -= fVertTCMargin; + maxtc.x() += fHorizTCMargin; + maxtc.y() += fVertTCMargin; + osg::Vec2 minc = local+osg::Vec2(0.0f-fHorizQuadMargin,0.0f-fVertQuadMargin); + osg::Vec2 maxc = local+osg::Vec2(width+fHorizQuadMargin,height+fVertQuadMargin); + + addGlyphQuad(glyph, minc, maxc, mintc, maxtc); + + // move the cursor onto the next character. + // also expand bounding box + switch(_layout) + { + case LEFT_TO_RIGHT: + cursor.x() += glyph->getHorizontalAdvance() * wr; + _textBB.expandBy(osg::Vec3(minc.x(), minc.y(), 0.0f)); //lower left corner + _textBB.expandBy(osg::Vec3(maxc.x(), maxc.y(), 0.0f)); //upper right corner + break; + case VERTICAL: + cursor.y() -= glyph->getVerticalAdvance() * hr; + _textBB.expandBy(osg::Vec3(minc.x(),maxc.y(),0.0f)); //upper left corner + _textBB.expandBy(osg::Vec3(maxc.x(),minc.y(),0.0f)); //lower right corner + break; + case RIGHT_TO_LEFT: + _textBB.expandBy(osg::Vec3(maxc.x(),minc.y(),0.0f)); //lower right corner + _textBB.expandBy(osg::Vec3(minc.x(),maxc.y(),0.0f)); //upper left corner + break; + } + } + else + { + OSG_NOTICE<<"No TextureInfo for "<second; - - osg::DrawElements* src_primitives = glyphquad._primitives[0].get(); - - for(unsigned int i=glyphquad._primitives.size(); i<=backdrop_index; ++i) - { - osg::DrawElementsUShort* dst_primitives = new osg::DrawElementsUShort(GL_TRIANGLES); - dst_primitives->setBufferObject(src_primitives->getBufferObject()); - glyphquad._primitives.push_back(dst_primitives); - } - - osg::DrawElements* dst_primitives = glyphquad._primitives[backdrop_index].get(); - dst_primitives->resizeElements(0); - - unsigned int numCoords = src_primitives->getNumIndices(); - - Coords& src_coords = _coords; - TexCoords& src_texcoords = _texcoords; - - Coords& dst_coords = _coords; - TexCoords& dst_texcoords = _texcoords; - - for(unsigned int i=0;isize(); - (*dst_primitives).addElement(di); - (*dst_coords).push_back(v); - (*dst_texcoords).push_back((*src_texcoords)[si]); - } - } - } -} - // This method adjusts the bounding box to account for the expanded area caused by the backdrop. // This assumes that the bounding box has already been computed for the text without the backdrop. void Text::computeBackdropBoundingBox() @@ -1095,6 +1117,8 @@ void Text::drawImplementation(osg::RenderInfo& renderInfo) const void Text::drawImplementationSinglePass(osg::State& state, const osg::Vec4& colorMultiplier) const { + if (colorMultiplier.a()==0.0f || _color.a()==0.0f) return; + osg::VertexArrayState* vas = state.getCurrentVertexArrayState(); bool usingVertexBufferObjects = state.useVertexBufferObject(_supportsVertexBufferObjects && _useVertexBufferObjects); bool usingVertexArrayObjects = usingVertexBufferObjects && state.useVertexArrayObject(_useVertexArrayObject); @@ -1117,7 +1141,6 @@ void Text::drawImplementationSinglePass(osg::State& state, const osg::Vec4& colo } if (_drawMode & TEXT) -// if (false) { for(TextureGlyphQuadMap::const_iterator titr=_textureGlyphQuadMap.begin(); titr!=_textureGlyphQuadMap.end(); @@ -1128,33 +1151,6 @@ void Text::drawImplementationSinglePass(osg::State& state, const osg::Vec4& colo const GlyphQuads& glyphquad = titr->second; -#if 1 - if(_backdropType != NONE) - { - unsigned int backdrop_index; - unsigned int max_backdrop_index; - if(_backdropType == OUTLINE) - { - backdrop_index = 1; - max_backdrop_index = 8; - } - else - { - backdrop_index = _backdropType+1; - max_backdrop_index = backdrop_index+1; - } - - if (max_backdrop_index>glyphquad._primitives.size()) max_backdrop_index=glyphquad._primitives.size(); - - state.disableColorPointer(); - state.Color(_backdropColor.r(),_backdropColor.g(),_backdropColor.b(),_backdropColor.a()); - - for( ; backdrop_index < max_backdrop_index; backdrop_index++) - { - glyphquad._primitives[backdrop_index]->draw(state, usingVertexBufferObjects); - } - } -#endif if(_colorGradientMode == SOLID) { vas->disableColorArray(state); @@ -1168,7 +1164,7 @@ void Text::drawImplementationSinglePass(osg::State& state, const osg::Vec4& colo } } - glyphquad._primitives[0]->draw(state, usingVertexBufferObjects); + glyphquad._primitives->draw(state, usingVertexBufferObjects); } } } @@ -1216,9 +1212,6 @@ void Text::drawImplementation(osg::State& state, const osg::Vec4& colorMultiplie vas->applyDisablingOfVertexAttributes(state); } -#if 0 - drawImplementationSinglePass(state, colorMultiplier); -#else glDepthMask(GL_FALSE); drawImplementationSinglePass(state, colorMultiplier); @@ -1235,7 +1228,6 @@ void Text::drawImplementation(osg::State& state, const osg::Vec4& colorMultiplie } state.haveAppliedAttribute(osg::StateAttribute::DEPTH); -#endif if (usingVertexBufferObjects && !usingVertexArrayObjects) { @@ -1267,22 +1259,39 @@ void Text::accept(osg::Drawable::ConstAttributeFunctor& af) const void Text::accept(osg::PrimitiveFunctor& pf) const { - pf.setVertexArray(_coords->size(), &(_coords->front())); + if (!_coords || _coords->empty()) return; + + // short term fix/workaround for _coords being transformed by a local matrix before rendering, so we need to replicate this was doing tasks like intersection testing. + osg::ref_ptr vertices = _coords; + if (!_matrix.isIdentity()) + { + vertices = new osg::Vec3Array; + vertices->resize(_coords->size()); + for(Vec3Array::iterator sitr = _coords->begin(), ditr = vertices->begin(); + sitr != _coords->end(); + ++sitr, ++ditr) + { + *ditr = *sitr * _matrix; + } + } + + pf.setVertexArray(vertices->size(), &(vertices->front())); + for(TextureGlyphQuadMap::const_iterator titr=_textureGlyphQuadMap.begin(); titr!=_textureGlyphQuadMap.end(); ++titr) { const GlyphQuads& glyphquad = titr->second; - if (!glyphquad._primitives.empty()) + if (glyphquad._primitives.valid()) { - const osg::DrawElementsUShort* drawElementsUShort = dynamic_cast(glyphquad._primitives[0].get()); + const osg::DrawElementsUShort* drawElementsUShort = dynamic_cast(glyphquad._primitives.get()); if (drawElementsUShort) { pf.drawElements(GL_TRIANGLES, drawElementsUShort->size(), &(drawElementsUShort->front())); } else { - const osg::DrawElementsUInt* drawElementsUInt = dynamic_cast(glyphquad._primitives[0].get()); + const osg::DrawElementsUInt* drawElementsUInt = dynamic_cast(glyphquad._primitives.get()); if (drawElementsUInt) { pf.drawElements(GL_TRIANGLES, drawElementsUInt->size(), &(drawElementsUInt->front())); @@ -1292,6 +1301,21 @@ void Text::accept(osg::PrimitiveFunctor& pf) const } } +bool Text::getCharacterCorners(unsigned int index, osg::Vec3& bottomLeft, osg::Vec3& bottomRight, osg::Vec3& topLeft, osg::Vec3& topRight) const +{ + if (_coords) return false; + + if ((index*4+4)>static_cast(_coords->size())) return false; + + unsigned int base = index*4; + topLeft = (*_coords)[base]; + bottomLeft = (*_coords)[base+1]; + bottomRight = (*_coords)[base+2]; + topRight = (*_coords)[base+3]; + + return true; +} + void Text::resizeGLObjectBuffers(unsigned int maxSize) { TextBase::resizeGLObjectBuffers(maxSize); @@ -1322,22 +1346,19 @@ void Text::setBackdropType(BackdropType type) if (_backdropType==type) return; _backdropType = type; + + assignStateSet(); + computeGlyphRepresentation(); } -void Text::setBackdropImplementation(BackdropImplementation implementation) -{ - if (_backdropImplementation==implementation) return; - - _backdropImplementation = implementation; - computeGlyphRepresentation(); -} - - void Text::setBackdropOffset(float offset) { _backdropHorizontalOffset = offset; _backdropVerticalOffset = offset; + + assignStateSet(); + computeGlyphRepresentation(); } @@ -1345,12 +1366,17 @@ void Text::setBackdropOffset(float horizontal, float vertical) { _backdropHorizontalOffset = horizontal; _backdropVerticalOffset = vertical; + + assignStateSet(); + computeGlyphRepresentation(); } void Text::setBackdropColor(const osg::Vec4& color) { _backdropColor = color; + + assignStateSet(); } void Text::setColorGradientMode(ColorGradientMode mode) @@ -1391,20 +1417,10 @@ Text::GlyphQuads::GlyphQuads(const GlyphQuads&) void Text::GlyphQuads::resizeGLObjectBuffers(unsigned int maxSize) { - for(Primitives::iterator itr = _primitives.begin(); - itr != _primitives.end(); - ++itr) - { - (*itr)->resizeGLObjectBuffers(maxSize); - } + if (_primitives.valid()) _primitives->resizeGLObjectBuffers(maxSize); } void Text::GlyphQuads::releaseGLObjects(osg::State* state) const { - for(Primitives::const_iterator itr = _primitives.begin(); - itr != _primitives.end(); - ++itr) - { - (*itr)->releaseGLObjects(state); - } + if (_primitives.valid()) _primitives->releaseGLObjects(state); } diff --git a/src/osgText/TextBase.cpp b/src/osgText/TextBase.cpp index 5c5e5460e..3d9534903 100644 --- a/src/osgText/TextBase.cpp +++ b/src/osgText/TextBase.cpp @@ -50,7 +50,6 @@ TextBase::TextBase(): _lineCount(0), _glyphNormalized(false) { - setStateSet(Font::getDefaultFont()->getStateSet()); setUseDisplayList(false); setSupportsDisplayList(false); @@ -89,6 +88,11 @@ TextBase::~TextBase() { } +osg::StateSet* TextBase::createStateSet() +{ + return 0; +} + void TextBase::initArraysAndBuffers() { _vbo = new osg::VertexBufferObject; @@ -105,7 +109,7 @@ void TextBase::initArraysAndBuffers() _texcoords->setBufferObject(_vbo.get()); } -osg::VertexArrayState* TextBase::createVertexArrayState(osg::RenderInfo& renderInfo) const +osg::VertexArrayState* TextBase::createVertexArrayStateImplementation(osg::RenderInfo& renderInfo) const { State& state = *renderInfo.getState(); @@ -182,6 +186,10 @@ void TextBase::setColor(const osg::Vec4& color) _color = color; } +void TextBase::assignStateSet() +{ + setStateSet(createStateSet()); +} void TextBase::setFont(osg::ref_ptr font) { @@ -189,6 +197,8 @@ void TextBase::setFont(osg::ref_ptr font) _font = font; + assignStateSet(); + computeGlyphRepresentation(); } @@ -203,6 +213,9 @@ void TextBase::setFontResolution(unsigned int width, unsigned int height) if (_fontSize==size) return; _fontSize = size; + + assignStateSet(); + computeGlyphRepresentation(); } diff --git a/src/osgText/shaders/text_frag.cpp b/src/osgText/shaders/text_frag.cpp new file mode 100644 index 000000000..02c253100 --- /dev/null +++ b/src/osgText/shaders/text_frag.cpp @@ -0,0 +1,257 @@ +char text_frag[] = "$OSG_GLSL_VERSION\n" + "\n" + "#pragma import_defines( BACKDROP_COLOR, SHADOW, OUTLINE, SIGNED_DISTNACE_FIELD, TEXTURE_DIMENSION, GLYPH_DIMENSION)\n" + "\n" + "#ifdef GL_ES\n" + " #extension GL_OES_standard_derivatives : enable\n" + " #ifndef GL_OES_standard_derivatives\n" + " #undef SIGNED_DISTNACE_FIELD\n" + " #endif\n" + "#endif\n" + "\n" + "#if !defined(GL_ES)\n" + " #if __VERSION__>=400\n" + " #define osg_TextureQueryLOD textureQueryLod\n" + " #else\n" + " #extension GL_ARB_texture_query_lod : enable\n" + " #ifdef GL_ARB_texture_query_lod\n" + " #define osg_TextureQueryLOD textureQueryLOD\n" + " #endif\n" + " #endif\n" + "#endif\n" + "\n" + "$OSG_PRECISION_FLOAT\n" + "\n" + "#if __VERSION__>=130\n" + " #define TEXTURE texture\n" + " #define TEXTURELOD textureLod\n" + " out vec4 osg_FragColor;\n" + "#else\n" + " #define TEXTURE texture2D\n" + " #define TEXTURELOD texture2DLod\n" + " #define osg_FragColor gl_FragColor\n" + "#endif\n" + "\n" + "\n" + "#if !defined(GL_ES) && __VERSION__>=130\n" + " #define ALPHA r\n" + " #define SDF g\n" + "#else\n" + " #define ALPHA a\n" + " #define SDF r\n" + "#endif\n" + "\n" + "\n" + "uniform sampler2D glyphTexture;\n" + "\n" + "$OSG_VARYING_IN vec2 texCoord;\n" + "$OSG_VARYING_IN vec4 vertexColor;\n" + "\n" + "#ifndef TEXTURE_DIMENSION\n" + "const float TEXTURE_DIMENSION = 1024.0;\n" + "#endif\n" + "\n" + "#ifndef GLYPH_DIMENSION\n" + "const float GLYPH_DIMENSION = 32.0;\n" + "#endif\n" + "\n" + "#ifdef SIGNED_DISTNACE_FIELD\n" + "\n" + "float distanceFromEdge(vec2 tc)\n" + "{\n" + " float center_alpha = TEXTURELOD(glyphTexture, tc, 0.0).SDF;\n" + " if (center_alpha==0.0) return -1.0;\n" + "\n" + " //float distance_scale = (1.0/4.0)*1.41;\n" + " float distance_scale = (1.0/6.0)*1.41;\n" + " //float distance_scale = (1.0/8.0)*1.41;\n" + "\n" + " return (center_alpha-0.5)*distance_scale;\n" + "}\n" + "\n" + "vec4 distanceFieldColorSample(float edge_distance, float blend_width, float blend_half_width)\n" + "{\n" + "#ifdef OUTLINE\n" + " float outline_width = OUTLINE*0.5;\n" + " if (edge_distance>blend_half_width)\n" + " {\n" + " return vertexColor;\n" + " }\n" + " else if (edge_distance>-blend_half_width)\n" + " {\n" + " return mix(vertexColor, vec4(BACKDROP_COLOR.rgb, BACKDROP_COLOR.a*vertexColor.a), smoothstep(0.0, 1.0, (blend_half_width-edge_distance)/(blend_width)));\n" + " }\n" + " else if (edge_distance>(blend_half_width-outline_width))\n" + " {\n" + " return vec4(BACKDROP_COLOR.rgb, BACKDROP_COLOR.a*vertexColor.a);\n" + " }\n" + " else if (edge_distance>-(outline_width+blend_half_width))\n" + " {\n" + " return vec4(BACKDROP_COLOR.rgb, vertexColor.a * ((blend_half_width+outline_width+edge_distance)/blend_width));\n" + " }\n" + " else\n" + " {\n" + " return vec4(0.0, 0.0, 0.0, 0.0);\n" + " }\n" + "#else\n" + " if (edge_distance>blend_half_width)\n" + " {\n" + " return vertexColor;\n" + " }\n" + " else if (edge_distance>-blend_half_width)\n" + " {\n" + " return vec4(vertexColor.rgb, vertexColor.a * smoothstep(1.0, 0.0, (blend_half_width-edge_distance)/(blend_width)));\n" + " }\n" + " else\n" + " {\n" + " return vec4(0.0, 0.0, 0.0, 0.0);\n" + " }\n" + "#endif\n" + "}\n" + "\n" + "vec4 textColor(vec2 src_texCoord)\n" + "{\n" + " float sample_distance_scale = 0.75;\n" + " vec2 dx = dFdx(src_texCoord)*sample_distance_scale;\n" + " vec2 dy = dFdy(src_texCoord)*sample_distance_scale;\n" + "\n" + "\n" + " float distance_across_pixel = length(dx+dy)*(TEXTURE_DIMENSION/GLYPH_DIMENSION);\n" + "\n" + " // compute the appropriate number of samples required to avoid aliasing.\n" + " int maxNumSamplesAcrossSide = 4;\n" + "\n" + " int numSamplesX = int(TEXTURE_DIMENSION * length(dx));\n" + " int numSamplesY = int(TEXTURE_DIMENSION * length(dy));\n" + " if (numSamplesX<2) numSamplesX = 2;\n" + " if (numSamplesY<2) numSamplesY = 2;\n" + " if (numSamplesX>maxNumSamplesAcrossSide) numSamplesX = maxNumSamplesAcrossSide;\n" + " if (numSamplesY>maxNumSamplesAcrossSide) numSamplesY = maxNumSamplesAcrossSide;\n" + "\n" + "\n" + " vec2 delta_tx = dx/float(numSamplesX-1);\n" + " vec2 delta_ty = dy/float(numSamplesY-1);\n" + "\n" + " float numSamples = float(numSamplesX)*float(numSamplesY);\n" + " float scale = 1.0/numSamples;\n" + " vec4 total_color = vec4(0.0,0.0,0.0,0.0);\n" + "\n" + " float blend_width = 1.5*distance_across_pixel/numSamples;\n" + " float blend_half_width = blend_width*0.5;\n" + "\n" + " // check whether fragment is wholly within or outwith glyph body+outline\n" + " float cd = distanceFromEdge(src_texCoord); // central distance (distance from center to edge)\n" + " if (cd-blend_half_width>distance_across_pixel) return vertexColor; // pixel fully within glyph body\n" + "\n" + " #ifdef OUTLINE\n" + " float outline_width = OUTLINE*0.5;\n" + " if ((-cd-outline_width-blend_half_width)>distance_across_pixel) return vec4(0.0, 0.0, 0.0, 0.0); // pixel fully outside outline+glyph body\n" + " #else\n" + " if (-cd-blend_half_width>distance_across_pixel) return vec4(0.0, 0.0, 0.0, 0.0); // pixel fully outside glyph body\n" + " #endif\n" + "\n" + "\n" + " // use multi-sampling to provide high quality antialised fragments\n" + " vec2 origin = src_texCoord - dx*0.5 - dy*0.5;\n" + " for(;numSamplesY>0; --numSamplesY)\n" + " {\n" + " vec2 pos = origin;\n" + " int numX = numSamplesX;\n" + " for(;numX>0; --numX)\n" + " {\n" + " vec4 c = distanceFieldColorSample(distanceFromEdge(pos), blend_width, blend_half_width);\n" + " total_color = total_color + c * c.a;\n" + " pos += delta_tx;\n" + " }\n" + " origin += delta_ty;\n" + " }\n" + "\n" + " total_color.rgb /= total_color.a;\n" + " total_color.a *= scale;\n" + "\n" + " return total_color;\n" + "}\n" + "\n" + "#else\n" + "\n" + "vec4 textColor(vec2 src_texCoord)\n" + "{\n" + "\n" + "#ifdef OUTLINE\n" + "\n" + " float alpha = TEXTURE(glyphTexture, src_texCoord).ALPHA;\n" + " float delta_tc = 1.6*OUTLINE*GLYPH_DIMENSION/TEXTURE_DIMENSION;\n" + "\n" + " float outline_alpha = alpha;\n" + " vec2 origin = src_texCoord-vec2(delta_tc*0.5, delta_tc*0.5);\n" + "\n" + " float numSamples = 3.0;\n" + " delta_tc = delta_tc/(numSamples-1.0);\n" + "\n" + " float background_alpha = 1.0;\n" + "\n" + " for(float i=0.0; i1.0) outline_alpha = 1.0;\n" + "\n" + " if (outline_alpha==0.0) return vec4(0.0, 0.0, 0.0, 0.0); // outside glyph and outline\n" + "\n" + " vec4 color = mix(BACKDROP_COLOR, vertexColor, smoothstep(0.0, 1.0, alpha));\n" + " color.a = vertexColor.a * smoothstep(0.0, 1.0, outline_alpha);\n" + "\n" + " return color;\n" + "\n" + "#else\n" + "\n" + " float alpha = TEXTURE(glyphTexture, src_texCoord).ALPHA;\n" + " if (alpha==0.0) vec4(0.0, 0.0, 0.0, 0.0);\n" + " return vec4(vertexColor.rgb, vertexColor.a * alpha);\n" + "\n" + "#endif\n" + "}\n" + "\n" + "#endif\n" + "\n" + "\n" + "void main(void)\n" + "{\n" + " if (texCoord.x<0.0 && texCoord.y<0.0)\n" + " {\n" + " osg_FragColor = vertexColor;\n" + " return;\n" + " }\n" + "\n" + "#ifdef SHADOW\n" + " float scale = -1.0*GLYPH_DIMENSION/TEXTURE_DIMENSION;\n" + " vec2 delta_tc = SHADOW*scale;\n" + " vec4 shadow_color = textColor(texCoord+delta_tc);\n" + " shadow_color.rgb = BACKDROP_COLOR.rgb;\n" + "\n" + " vec4 glyph_color = textColor(texCoord);\n" + " vec4 color = mix(shadow_color, glyph_color, glyph_color.a);\n" + "#else\n" + " vec4 color = textColor(texCoord);\n" + "#endif\n" + "\n" + " if (color.a==0.0) discard;\n" + "\n" + " osg_FragColor = color;\n" + "}\n" + "\n"; diff --git a/src/osgText/shaders/text_vert.cpp b/src/osgText/shaders/text_vert.cpp new file mode 100644 index 000000000..72506284f --- /dev/null +++ b/src/osgText/shaders/text_vert.cpp @@ -0,0 +1,13 @@ +char text_vert[] = "$OSG_GLSL_VERSION\n" + "$OSG_PRECISION_FLOAT\n" + "\n" + "$OSG_VARYING_OUT vec2 texCoord;\n" + "$OSG_VARYING_OUT vec4 vertexColor;\n" + "\n" + "void main(void)\n" + "{\n" + " gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n" + " texCoord = gl_MultiTexCoord0.xy;\n" + " vertexColor = gl_Color;\n" + "}\n" + "\n"; diff --git a/src/osgUtil/GLObjectsVisitor.cpp b/src/osgUtil/GLObjectsVisitor.cpp index b194b7990..8784366b8 100644 --- a/src/osgUtil/GLObjectsVisitor.cpp +++ b/src/osgUtil/GLObjectsVisitor.cpp @@ -28,7 +28,7 @@ GLObjectsVisitor::GLObjectsVisitor(Mode mode) setTraversalMode(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN); _mode = mode; - + _checkGLErrors = osg::State::ONCE_PER_ATTRIBUTE; } void GLObjectsVisitor::apply(osg::Node& node) @@ -57,8 +57,15 @@ void GLObjectsVisitor::apply(osg::Drawable& drawable) { if (_drawablesAppliedSet.count(&drawable)!=0) return; + if (_checkGLErrors==osg::State::ONCE_PER_ATTRIBUTE) _renderInfo.getState()->checkGLErrors("start of Drawable::apply(osg::Drawable& drawable)"); + _drawablesAppliedSet.insert(&drawable); + if (drawable.getStateSet()) + { + apply(*(drawable.getStateSet())); + } + if (_mode&SWITCH_OFF_DISPLAY_LISTS) { drawable.setUseDisplayList(false); @@ -82,30 +89,34 @@ void GLObjectsVisitor::apply(osg::Drawable& drawable) if (_mode&COMPILE_DISPLAY_LISTS && _renderInfo.getState() && (drawable.getUseDisplayList() || drawable.getUseVertexBufferObjects())) { + drawable.compileGLObjects(_renderInfo); + + if (_checkGLErrors==osg::State::ONCE_PER_ATTRIBUTE) _renderInfo.getState()->checkGLErrors("after drawable.compileGLObjects() call in Drawable::apply(osg::Drawable& drawable) "); } + if (_mode&RELEASE_DISPLAY_LISTS) { drawable.releaseGLObjects(_renderInfo.getState()); } - - if (drawable.getStateSet()) - { - apply(*(drawable.getStateSet())); - } } void GLObjectsVisitor::apply(osg::StateSet& stateset) { if (_stateSetAppliedSet.count(&stateset)!=0) return; + if (_checkGLErrors==osg::State::ONCE_PER_ATTRIBUTE) _renderInfo.getState()->checkGLErrors("start of GLObjectsVisitor::apply(osg::StateSet& stateset)"); + _stateSetAppliedSet.insert(&stateset); if (_mode & COMPILE_STATE_ATTRIBUTES && _renderInfo.getState()) { + stateset.compileGLObjects(*_renderInfo.getState()); + if (_checkGLErrors==osg::State::ONCE_PER_ATTRIBUTE) _renderInfo.getState()->checkGLErrors("after stateset.compileGLObjects in GLObjectsVisitor::apply(osg::StateSet& stateset)"); + osg::Program* program = dynamic_cast(stateset.getAttribute(osg::StateAttribute::PROGRAM)); if (program) { if( program->isFixedFunction() ) @@ -129,6 +140,8 @@ void GLObjectsVisitor::apply(osg::StateSet& stateset) ++itr) { pcp->apply(*(itr->second.first)); + + if (_checkGLErrors==osg::State::ONCE_PER_ATTRIBUTE) _renderInfo.getState()->checkGLErrors("after pcp->apply(Unfiorm&) in GLObjectsVisitor::apply(osg::StateSet& stateset), unifrom name: ", (itr->second.first->getName()).c_str()); } } } @@ -151,8 +164,29 @@ void GLObjectsVisitor::apply(osg::StateSet& stateset) { stateset.checkValidityOfAssociatedModes(*_renderInfo.getState()); } + + if (_checkGLErrors==osg::State::ONCE_PER_ATTRIBUTE) _renderInfo.getState()->checkGLErrors("after GLObjectsVisitor::apply(osg::StateSet& stateset)"); } +void GLObjectsVisitor::compile(osg::Node& node) +{ + if (_renderInfo.getState()) + { + node.accept(*this); + + if (_lastCompiledProgram.valid()) + { + osg::State* state = _renderInfo.getState(); + osg::GLExtensions* extensions = state->get(); + extensions->glUseProgram(0); + _renderInfo.getState()->setLastAppliedProgramObject(0); + } + + if (_checkGLErrors!=osg::State::NEVER_CHECK_GL_ERRORS) _renderInfo.getState()->checkGLErrors("after GLObjectsVisitor::compile(osg::Node& node)"); + } +} + + ///////////////////////////////////////////////////////////////// // // GLObjectsOperation diff --git a/src/osgUtil/LineSegmentIntersector.cpp b/src/osgUtil/LineSegmentIntersector.cpp index 08faade5e..65b61c8be 100644 --- a/src/osgUtil/LineSegmentIntersector.cpp +++ b/src/osgUtil/LineSegmentIntersector.cpp @@ -69,6 +69,8 @@ struct IntersectFunctor IntersectFunctor(): _primitiveIndex(0), + _length(0.0), + _inverse_length(0.0), _hit(false) { } diff --git a/src/osgUtil/MeshOptimizers.cpp b/src/osgUtil/MeshOptimizers.cpp index 52ff810b7..4eee09a89 100644 --- a/src/osgUtil/MeshOptimizers.cpp +++ b/src/osgUtil/MeshOptimizers.cpp @@ -1183,21 +1183,21 @@ void SharedArrayOptimizer::findDuplicatedUVs(const osg::Geometry& geometry) { _deduplicateUvs.clear(); - // look for all channels that are shared only *within* the geometry + // look for all arrays that are shared only *within* the geometry std::map arrayPointerCounter; for(unsigned int id = 0 ; id < geometry.getNumTexCoordArrays() ; ++ id) { - const osg::Array* channel = geometry.getTexCoordArray(id); - if(channel && channel->getNumElements()) + const osg::Array* array = geometry.getTexCoordArray(id); + if(array && array->getNumElements()) { - if(arrayPointerCounter.find(channel) == arrayPointerCounter.end()) + if(arrayPointerCounter.find(array) == arrayPointerCounter.end()) { - arrayPointerCounter[channel] = 1; + arrayPointerCounter[array] = 1; } else { - arrayPointerCounter[channel] += 1; + arrayPointerCounter[array] += 1; } } } @@ -1206,14 +1206,14 @@ void SharedArrayOptimizer::findDuplicatedUVs(const osg::Geometry& geometry) for(unsigned int id = 0 ; id != geometry.getNumTexCoordArrays() ; ++ id) { - const osg::Array* channel = geometry.getTexCoordArray(id); - // test if array is shared outside the geometry - if(channel && static_cast(channel->referenceCount()) == arrayPointerCounter[channel]) + const osg::Array* array = geometry.getTexCoordArray(id); + // test if array is shared inside the geometry + if(array && arrayPointerCounter[array] > 1) { - std::map::const_iterator reference = references.find(channel); + std::map::const_iterator reference = references.find(array); if(reference == references.end()) { - references[channel] = id; + references[array] = id; } else { diff --git a/src/osgUtil/Optimizer.cpp b/src/osgUtil/Optimizer.cpp index e1602223a..dbdff4ea5 100644 --- a/src/osgUtil/Optimizer.cpp +++ b/src/osgUtil/Optimizer.cpp @@ -1618,7 +1618,7 @@ void Optimizer::CombineLODsVisitor::combineLODs() struct LessGeometry { - bool operator() (const osg::Geometry* lhs,const osg::Geometry* rhs) const + bool operator() (const osg::ref_ptr& lhs,const osg::ref_ptr& rhs) const { if (lhs->getStateSet()getStateSet()) return true; if (rhs->getStateSet()getStateSet()) return false; @@ -1714,7 +1714,7 @@ struct LessGeometry struct LessGeometryPrimitiveType { - bool operator() (const osg::Geometry* lhs,const osg::Geometry* rhs) const + bool operator() (const osg::ref_ptr& lhs,const osg::ref_ptr& rhs) const { for(unsigned int i=0; igetNumPrimitiveSets() && igetNumPrimitiveSets(); @@ -1792,45 +1792,39 @@ bool Optimizer::MergeGeometryVisitor::mergeGroup(osg::Group& group) if (group.getNumChildren()>=2) { - typedef std::vector DuplicateList; - typedef std::vector< osg::ref_ptr > DrawableList; - typedef std::map GeometryDuplicateMap; + typedef std::vector< osg::ref_ptr > DuplicateList; + typedef std::vector< osg::ref_ptr > Nodes; + typedef std::map< osg::ref_ptr ,DuplicateList,LessGeometry> GeometryDuplicateMap; typedef std::vector MergeList; GeometryDuplicateMap geometryDuplicateMap; - DrawableList standardDrawables; + Nodes standardChildren; unsigned int i; for(i=0;iasDrawable(); - if (drawable) + osg::Node* child = group.getChild(i); + osg::Geometry* geom = child->asGeometry(); + if (geom) { - osg::Geometry* geom = drawable->asGeometry(); - if (geom) + if (!geometryContainsSharedArrays(*geom) && + geom->getDataVariance()!=osg::Object::DYNAMIC && + isOperationPermissibleForObject(geom)) { - //geom->computeCorrectBindingsAndArraySizes(); - - if (!geometryContainsSharedArrays(*geom) && - geom->getDataVariance()!=osg::Object::DYNAMIC && - isOperationPermissibleForObject(geom)) - { - geometryDuplicateMap[geom].push_back(geom); - } - else - { - standardDrawables.push_back(drawable); - } + geometryDuplicateMap[geom].push_back(geom); } else { - standardDrawables.push_back(drawable); + standardChildren.push_back(geom); } } + else + { + standardChildren.push_back(child); + } } -#if 1 // first try to group geometries with the same properties // (i.e. array types) to avoid loss of data during merging MergeList mergeListChecked; // List of drawables just before merging, grouped by "compatibility" and vertex limit @@ -1860,7 +1854,7 @@ bool Optimizer::MergeGeometryVisitor::mergeGroup(osg::Group& group) dupItr!=itr->second.end(); ++dupItr) { - osg::Geometry* geomToPush = *dupItr; + osg::Geometry* geomToPush = dupItr->get(); // try to group geomToPush with another geometry MergeList::iterator eachMergeList=mergeListTmp.begin(); @@ -1946,6 +1940,16 @@ bool Optimizer::MergeGeometryVisitor::mergeGroup(osg::Group& group) if (needToDoMerge) { + // to avoid performance issues associated with incrementally removing a large number children, we remove them all and add back the ones we need. + group.removeChildren(0, group.getNumChildren()); + + for(Nodes::iterator itr = standardChildren.begin(); + itr != standardChildren.end(); + ++itr) + { + group.addChild(*itr); + } + // now do the merging of geometries for(MergeList::iterator mitr = mergeList.begin(); mitr != mergeList.end(); @@ -1954,65 +1958,18 @@ bool Optimizer::MergeGeometryVisitor::mergeGroup(osg::Group& group) DuplicateList& duplicateList = *mitr; if (duplicateList.size()>1) { - osg::Geometry* lhs = duplicateList.front(); + osg::ref_ptr lhs = duplicateList.front(); + group.addChild(lhs.get()); + for(DuplicateList::iterator ditr = duplicateList.begin()+1; ditr != duplicateList.end(); ++ditr) { - mergeGeometry(*lhs,**ditr); - - group.removeChild(*ditr); + mergeGeometry(*lhs, **ditr); } } } } - -#else - // don't merge geometry if its above a maximum number of vertices. - for(GeometryDuplicateMap::iterator itr=geometryDuplicateMap.begin(); - itr!=geometryDuplicateMap.end(); - ++itr) - { - if (itr->second.size()>1) - { - std::sort(itr->second.begin(),itr->second.end(),LessGeometryPrimitiveType()); - osg::Geometry* lhs = itr->second[0]; - for(DuplicateList::iterator dupItr=itr->second.begin()+1; - dupItr!=itr->second.end(); - ++dupItr) - { - - osg::Geometry* rhs = *dupItr; - - if (lhs->getVertexArray() && lhs->getVertexArray()->getNumElements()>=_targetMaximumNumberOfVertices) - { - lhs = rhs; - continue; - } - - if (rhs->getVertexArray() && rhs->getVertexArray()->getNumElements()>=_targetMaximumNumberOfVertices) - { - continue; - } - - if (lhs->getVertexArray() && rhs->getVertexArray() && - (lhs->getVertexArray()->getNumElements()+rhs->getVertexArray()->getNumElements())>=_targetMaximumNumberOfVertices) - { - continue; - } - - if (mergeGeometry(*lhs,*rhs)) - { - geode.removeDrawable(rhs); - - static int co = 0; - OSG_INFO<<"merged and removed Geometry "<<++co<reserve(count); typedef const typename Type::value_type* IndexPointer; @@ -34,9 +33,9 @@ osg::PrimitiveSet * drawElementsTemplate(GLenum mode,GLsizei count, const typena for (IndexPointer iptr=indices; iptrpush_back(*(iptr)); + primitives->push_back(*(iptr+2)); + primitives->push_back(*(iptr+1)); } break; } @@ -46,10 +45,10 @@ osg::PrimitiveSet * drawElementsTemplate(GLenum mode,GLsizei count, const typena IndexPointer ilast = &indices[count - 3]; for (IndexPointer iptr = indices; iptrpush_back(*(iptr)); + primitives->push_back(*(iptr+3)); + primitives->push_back(*(iptr+2)); + primitives->push_back(*(iptr+1)); } break; } @@ -59,19 +58,19 @@ osg::PrimitiveSet * drawElementsTemplate(GLenum mode,GLsizei count, const typena IndexPointer ilast = &indices[count]; for (IndexPointer iptr = indices; iptrpush_back(*(iptr+1)); + primitives->push_back(*(iptr)); } break; } case (GL_TRIANGLE_FAN): { - de.push_back(*indices); + primitives->push_back(*indices); IndexPointer iptr = indices + 1; IndexPointer ilast = &indices[count]; - de.resize(count); - std::reverse_copy(iptr, ilast, de.begin() + 1); + primitives->resize(count); + std::reverse_copy(iptr, ilast, primitives->begin() + 1); break; } @@ -83,8 +82,8 @@ osg::PrimitiveSet * drawElementsTemplate(GLenum mode,GLsizei count, const typena { IndexPointer iptr = indices; IndexPointer ilast = &indices[count]; - de.resize(count); - std::reverse_copy(iptr, ilast, de.begin()); + primitives->resize(count); + std::reverse_copy(iptr, ilast, primitives->begin()); break; } @@ -92,7 +91,7 @@ osg::PrimitiveSet * drawElementsTemplate(GLenum mode,GLsizei count, const typena break; } - return &de; + return primitives; } namespace osgUtil { @@ -101,9 +100,8 @@ void ReversePrimitiveFunctor::drawArrays(GLenum mode, GLint first, GLsizei count { if (count==0) return ; - osg::DrawElementsUInt * dePtr = new osg::DrawElementsUInt(mode); - osg::DrawElementsUInt & de = *dePtr; - de.reserve(count); + osg::DrawElementsUInt * primitives = new osg::DrawElementsUInt(mode); + primitives->reserve(count); GLint end = first + count; @@ -113,9 +111,9 @@ void ReversePrimitiveFunctor::drawArrays(GLenum mode, GLint first, GLsizei count { for (GLint i=first; ipush_back(i); + primitives->push_back(i+2); + primitives->push_back(i+1); } break; } @@ -123,10 +121,10 @@ void ReversePrimitiveFunctor::drawArrays(GLenum mode, GLint first, GLsizei count { for (GLint i=first; ipush_back(i); + primitives->push_back(i+3); + primitives->push_back(i+2); + primitives->push_back(i+1); } break; } @@ -135,17 +133,17 @@ void ReversePrimitiveFunctor::drawArrays(GLenum mode, GLint first, GLsizei count { for (GLint i=first; ipush_back(i+1); + primitives->push_back(i); } break; } case (GL_TRIANGLE_FAN): { - de.push_back(first); + primitives->push_back(first); for (GLint i=end-1; i>first; i--) - de.push_back(i); + primitives->push_back(i); break; } @@ -156,7 +154,7 @@ void ReversePrimitiveFunctor::drawArrays(GLenum mode, GLint first, GLsizei count case (GL_LINE_LOOP): { for (GLint i=end-1; i>=first; i--) - de.push_back(i); + primitives->push_back(i); break; } @@ -164,7 +162,7 @@ void ReversePrimitiveFunctor::drawArrays(GLenum mode, GLint first, GLsizei count break; } - _reversedPrimitiveSet = &de; + _reversedPrimitiveSet = primitives; } void ReversePrimitiveFunctor::drawElements(GLenum mode,GLsizei count,const GLubyte* indices) diff --git a/src/osgUtil/SceneView.cpp b/src/osgUtil/SceneView.cpp index b4fd18a89..c788cf8ff 100644 --- a/src/osgUtil/SceneView.cpp +++ b/src/osgUtil/SceneView.cpp @@ -743,7 +743,7 @@ void SceneView::cull() _cullVisitorRight->setClampProjectionMatrixCallback(_cullVisitor->getClampProjectionMatrixCallback()); _cullVisitorRight->setTraversalMask(_cullMaskRight); computeRightEyeViewport(getViewport()); - computeNearFar = cullStage(computeRightEyeProjection(getProjectionMatrix()),computeRightEyeView(getViewMatrix()),_cullVisitorRight.get(),_stateGraphRight.get(),_renderStageRight.get(),_viewportRight.get()); + computeNearFar = cullStage(computeRightEyeProjection(getProjectionMatrix()),computeRightEyeView(getViewMatrix()),_cullVisitorRight.get(),_stateGraphRight.get(),_renderStageRight.get(),_viewportRight.get()) | computeNearFar; if (computeNearFar) { diff --git a/src/osgUtil/Simplifier.cpp b/src/osgUtil/Simplifier.cpp index cb3f2ad61..9d54a2d16 100644 --- a/src/osgUtil/Simplifier.cpp +++ b/src/osgUtil/Simplifier.cpp @@ -267,7 +267,6 @@ public: typedef std::vector< osg::ref_ptr > PointList; typedef std::list< osg::ref_ptr > TriangleList; typedef std::set< osg::ref_ptr > TriangleSet; - typedef std::map< osg::ref_ptr, unsigned int, dereference_less > TriangleMap; struct Point : public osg::Referenced { @@ -813,7 +812,6 @@ public: osg::ref_ptr edge_p1 = edge->_p1; osg::ref_ptr edge_p2 = edge->_p2; - TriangleMap triangleMap; TriangleList triangles_p1; TriangleList triangles_p2; LocalEdgeList oldEdges; diff --git a/src/osgUtil/TangentSpaceGenerator.cpp b/src/osgUtil/TangentSpaceGenerator.cpp index a57988e12..027e8be8a 100644 --- a/src/osgUtil/TangentSpaceGenerator.cpp +++ b/src/osgUtil/TangentSpaceGenerator.cpp @@ -12,8 +12,8 @@ TangentSpaceGenerator::TangentSpaceGenerator() N_(new osg::Vec4Array) { T_->setBinding(osg::Array::BIND_PER_VERTEX); T_->setNormalize(false); - B_->setBinding(osg::Array::BIND_PER_VERTEX); T_->setNormalize(false); - N_->setBinding(osg::Array::BIND_PER_VERTEX); T_->setNormalize(false); + B_->setBinding(osg::Array::BIND_PER_VERTEX); B_->setNormalize(false); + N_->setBinding(osg::Array::BIND_PER_VERTEX); N_->setNormalize(false); } TangentSpaceGenerator::TangentSpaceGenerator(const TangentSpaceGenerator ©, const osg::CopyOp ©op) diff --git a/src/osgUtil/TriStripVisitor.cpp b/src/osgUtil/TriStripVisitor.cpp index 074bfb890..605aa6c8a 100644 --- a/src/osgUtil/TriStripVisitor.cpp +++ b/src/osgUtil/TriStripVisitor.cpp @@ -607,7 +607,7 @@ void TriStripVisitor::mergeTriangleStrips(osg::Geometry::PrimitiveSetList& primi osg::PrimitiveSet* ps = primitives[i].get(); // remove null primitive sets and all primitives that have been merged // (i.e. all TRIANGLE_STRIP DrawElements) - if (!ps || (ps && ps->getMode() == osg::PrimitiveSet::TRIANGLE_STRIP)) + if (ps && ps->getMode() == osg::PrimitiveSet::TRIANGLE_STRIP) { primitives.erase(primitives.begin() + i); } diff --git a/src/osgViewer/GraphicsWindowCarbon.cpp b/src/osgViewer/GraphicsWindowCarbon.cpp index 0fbb6f21c..18169b3f0 100644 --- a/src/osgViewer/GraphicsWindowCarbon.cpp +++ b/src/osgViewer/GraphicsWindowCarbon.cpp @@ -1100,3 +1100,6 @@ public: REGISTER_WINDOWINGSYSTEMINTERFACE(Carbon, CarbonWindowingSystemInterface) } + +#endif + diff --git a/src/osgViewer/GraphicsWindowCocoa.mm b/src/osgViewer/GraphicsWindowCocoa.mm index bbca00de9..14f6fcb5f 100644 --- a/src/osgViewer/GraphicsWindowCocoa.mm +++ b/src/osgViewer/GraphicsWindowCocoa.mm @@ -199,7 +199,7 @@ static NSRect convertToQuartzCoordinates(const NSRect& rect) // the app-delegate, handling quit-requests // ---------------------------------------------------------------------------------------------------------- -@interface CocoaAppDelegate : NSObject +@interface CocoaAppDelegate : NSObject { } diff --git a/src/osgViewer/GraphicsWindowWin32.cpp b/src/osgViewer/GraphicsWindowWin32.cpp index 05ed74b71..c96189518 100644 --- a/src/osgViewer/GraphicsWindowWin32.cpp +++ b/src/osgViewer/GraphicsWindowWin32.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -95,9 +96,9 @@ enum tagPOINTER_INPUT_TYPE { PT_TOUCH = 0x00000002, // Touch PT_PEN = 0x00000003, // Pen PT_MOUSE = 0x00000004, // Mouse -#if(WINVER >= 0x0603) +//#if(WINVER >= 0x0603) PT_TOUCHPAD = 0x00000005, // Touchpad -#endif /* WINVER >= 0x0603 */ +//#endif /* WINVER >= 0x0603 */ }; typedef DWORD POINTER_INPUT_TYPE; @@ -143,6 +144,26 @@ static CloseTouchInputHandleFunc *closeTouchInputHandleFunc = NULL; static GetTouchInputInfoFunc *getTouchInputInfoFunc = NULL; static GetPointerTypeFunc *getPointerTypeFunc = NULL; +// DPI Awareness +// #if(WINVER >= 0x0603) + +#ifndef DPI_ENUMS_DECLARED + +typedef enum PROCESS_DPI_AWARENESS { + PROCESS_DPI_UNAWARE = 0, + PROCESS_SYSTEM_DPI_AWARE = 1, + PROCESS_PER_MONITOR_DPI_AWARE = 2 +} PROCESS_DPI_AWARENESS; + +#endif // DPI_ENUMS_DECLARED + +typedef +BOOL +(WINAPI SetProcessDpiAwarenessFunc( + PROCESS_DPI_AWARENESS dpi_awareness)); + +static SetProcessDpiAwarenessFunc *setProcessDpiAwareness = NULL; +// #endif @@ -764,6 +785,21 @@ Win32WindowingSystem::Win32WindowingSystem() FreeLibrary( hModule); } } + + +// #if(WINVER >= 0x0603) + // For Windows 8.1 and higher + // + // Per monitor DPI aware.This app checks for the DPI when it is created and adjusts the scale factor + // whenever the DPI changes.These applications are not automatically scaled by the system. + HMODULE hModuleShore = LoadLibrary("Shcore"); + if (hModuleShore) { + setProcessDpiAwareness = (SetProcessDpiAwarenessFunc *) GetProcAddress(hModuleShore, "SetProcessDpiAwareness"); + if (setProcessDpiAwareness) { + (*setProcessDpiAwareness)(PROCESS_DPI_AWARENESS::PROCESS_PER_MONITOR_DPI_AWARE); + } + } +// #endif } Win32WindowingSystem::~Win32WindowingSystem() @@ -1314,10 +1350,10 @@ void GraphicsWindowWin32::init() _applyWorkaroundForMultimonitorMultithreadNVidiaWin32Issues = true; #endif - const char* str = getenv("OSG_WIN32_NV_MULTIMON_MULTITHREAD_WORKAROUND"); - if (str) + std::string str; + if (osg::getEnvVar("OSG_WIN32_NV_MULTIMON_MULTITHREAD_WORKAROUND", str)) { - _applyWorkaroundForMultimonitorMultithreadNVidiaWin32Issues = (strcmp(str, "on")==0 || strcmp(str, "ON")==0 || strcmp(str, "On")==0 ); + _applyWorkaroundForMultimonitorMultithreadNVidiaWin32Issues = (str=="on") || (str=="ON") || (str=="On"); } } diff --git a/src/osgViewer/GraphicsWindowX11.cpp b/src/osgViewer/GraphicsWindowX11.cpp index a6eccfef6..f46c32845 100644 --- a/src/osgViewer/GraphicsWindowX11.cpp +++ b/src/osgViewer/GraphicsWindowX11.cpp @@ -390,7 +390,7 @@ bool GraphicsWindowX11::checkAndSendEventFullScreenIfNeeded(Display* display, in Atom netWMStateAtom = XInternAtom(display, "_NET_WM_STATE", True); Atom netWMStateFullscreenAtom = XInternAtom(display, "_NET_WM_STATE_FULLSCREEN", True); - OSG_NOTICE<<"GraphicsWindowX11::checkAndSendEventFullScreenIfNeeded()"<getState()); - sceneView->getSceneData()->accept(glov); + glov.compile(*(sceneView->getSceneData())); } sceneView->getState()->checkGLErrors("After Renderer::compile"); diff --git a/src/osgViewer/Viewer.cpp b/src/osgViewer/Viewer.cpp index 8371f6ef6..0eb63c586 100644 --- a/src/osgViewer/Viewer.cpp +++ b/src/osgViewer/Viewer.cpp @@ -33,6 +33,9 @@ #include #include #include +#include + +#include #include #include @@ -61,6 +64,7 @@ Viewer::Viewer(osg::ArgumentParser& arguments) arguments.getApplicationUsage()->addCommandLineOption("--clear-color ","Set the background color of the viewer in the form \"r,g,b[,a]\"."); arguments.getApplicationUsage()->addCommandLineOption("--screen ","Set the screen to use when multiple screens are present."); arguments.getApplicationUsage()->addCommandLineOption("--window ","Set the position (x,y) and size (w,h) of the viewer window."); + arguments.getApplicationUsage()->addCommandLineOption("--borderless-window ","Set the position (x,y) and size (w,h) of a borderless viewer window."); arguments.getApplicationUsage()->addCommandLineOption("--run-on-demand","Set the run methods frame rate management to only rendering frames when required."); arguments.getApplicationUsage()->addCommandLineOption("--run-continuous","Set the run methods frame rate management to rendering frames continuously."); @@ -134,7 +138,14 @@ Viewer::Viewer(osg::ArgumentParser& arguments) bool ss3d = false; bool wowvx20 = false; bool wowvx42 = false; - if ((wowvx20=arguments.read("--wowvx-20")) || (wowvx42=arguments.read("--wowvx-42")) || arguments.read("--wowvx")) + + if (arguments.read("--borderless-window",x,y,width,height)) + { + osg::ref_ptr sw = new osgViewer::SingleWindow(x, y, width, height, screenNum); + sw->setWindowDecoration(false); + apply(sw.get()); + } + else if ((wowvx20=arguments.read("--wowvx-20")) || (wowvx42=arguments.read("--wowvx-42")) || arguments.read("--wowvx")) { osg::ref_ptr wow = new WoWVxDisplay; @@ -495,28 +506,26 @@ void Viewer::realize() // no windows are already set up so set up a default view - const char* ptr = 0; - if ((ptr = getenv("OSG_CONFIG_FILE")) != 0) + std::string value; + if (osg::getEnvVar("OSG_CONFIG_FILE", value)) { - readConfiguration(ptr); + readConfiguration(value); } else { int screenNum = -1; - if ((ptr = getenv("OSG_SCREEN")) != 0) - { - if (strlen(ptr)!=0) screenNum = atoi(ptr); - else screenNum = -1; - } + osg::getEnvVar("OSG_SCREEN", screenNum); int x = -1, y = -1, width = -1, height = -1; - if ((ptr = getenv("OSG_WINDOW")) != 0) - { - std::istringstream iss(ptr); - iss >> x >> y >> width >> height; - } + osg::getEnvVar("OSG_WINDOW", x, y, width, height); - if (width>0 && height>0) + if (osg::getEnvVar("OSG_BORDERLESS_WINDOW", x, y, width, height)) + { + osg::ref_ptr sw = new osgViewer::SingleWindow(x, y, width, height, screenNum); + sw->setWindowDecoration(false); + apply(sw.get()); + } + else if (width>0 && height>0) { if (screenNum>=0) setUpViewInWindow(x, y, width, height, screenNum); else setUpViewInWindow(x,y,width,height); diff --git a/src/osgViewer/ViewerBase.cpp b/src/osgViewer/ViewerBase.cpp index 508889188..c03f1f0b8 100644 --- a/src/osgViewer/ViewerBase.cpp +++ b/src/osgViewer/ViewerBase.cpp @@ -18,6 +18,7 @@ #include #include +#include #include #include @@ -37,6 +38,7 @@ static osg::ApplicationUsageProxy ViewerBase_e2(osg::ApplicationUsage::ENVIRONME static osg::ApplicationUsageProxy ViewerBase_e3(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_WINDOW x y width height","Set the default window dimensions that windows should open up on."); static osg::ApplicationUsageProxy ViewerBase_e4(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_RUN_FRAME_SCHEME","Frame rate manage scheme that viewer run should use, ON_DEMAND or CONTINUOUS (default)."); static osg::ApplicationUsageProxy ViewerBase_e5(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_RUN_MAX_FRAME_RATE","Set the maximum number of frame as second that viewer run. 0.0 is default and disables an frame rate capping."); +static osg::ApplicationUsageProxy ViewerBase_e6(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_RUN_FRAME_COUNT", "Set the maximum number of frames to run the viewer run method."); using namespace osgViewer; @@ -68,18 +70,14 @@ void ViewerBase::viewerBaseInit() _runFrameScheme = CONTINUOUS; _runMaxFrameRate = 0.0f; - const char* str = getenv("OSG_RUN_FRAME_SCHEME"); - if (str) + std::string str; + if (osg::getEnvVar("OSG_RUN_FRAME_SCHEME", str)) { - if (strcmp(str, "ON_DEMAND")==0) _runFrameScheme = ON_DEMAND; - else if (strcmp(str, "CONTINUOUS")==0) _runFrameScheme = CONTINUOUS; + if (str=="ON_DEMAND") _runFrameScheme = ON_DEMAND; + else if (str=="CONTINUOUS") _runFrameScheme = CONTINUOUS; } - str = getenv("OSG_RUN_MAX_FRAME_RATE"); - if (str) - { - _runMaxFrameRate = osg::asciiToDouble(str); - } + osg::getEnvVar("OSG_RUN_MAX_FRAME_RATE", _runMaxFrameRate); _useConfigureAffinity = true; } @@ -88,7 +86,8 @@ void ViewerBase::configureAffinity() { unsigned int numProcessors = OpenThreads::GetNumberOfProcessors(); - OSG_NOTICE<<"ViewerBase::configureAffinity() numProcessors="<getFrameNumber()getFrameNumber()0.0 ? 1.0/_runMaxFrameRate : 0.0; osg::Timer_t startFrameTick = osg::Timer::instance()->tick(); diff --git a/src/osgViewer/ViewerEventHandlers.cpp b/src/osgViewer/ViewerEventHandlers.cpp index 41e02e1bc..43d7d8b39 100644 --- a/src/osgViewer/ViewerEventHandlers.cpp +++ b/src/osgViewer/ViewerEventHandlers.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -407,15 +408,9 @@ RecordCameraPathHandler::RecordCameraPathHandler(const std::string& filename, fl _animStartTime(0), _lastFrameTime(osg::Timer::instance()->tick()) { - const char* str = getenv("OSG_RECORD_CAMERA_PATH_FPS"); - if (str) - { - _interval = 1.0f / osg::asciiToDouble(str); - } - else - { - _interval = 1.0f / fps; - } + osg::getEnvVar("OSG_RECORD_CAMERA_PATH_FPS", fps); + + _interval = 1.0f / fps; } void RecordCameraPathHandler::getUsage(osg::ApplicationUsage &usage) const diff --git a/src/osgWidget/Label.cpp b/src/osgWidget/Label.cpp index 3731bca8c..6c7e9ebc4 100644 --- a/src/osgWidget/Label.cpp +++ b/src/osgWidget/Label.cpp @@ -134,7 +134,6 @@ void Label::setFontColor(const Color& c) { void Label::setShadow(point_type offset) { _text->setBackdropType(osgText::Text::DROP_SHADOW_BOTTOM_RIGHT); - _text->setBackdropImplementation(osgText::Text::NO_DEPTH_BUFFER); _text->setBackdropOffset(offset); _calculateSize(getTextSize()); diff --git a/src/osgWrappers/deprecated-dotosg/osg/Shader.cpp b/src/osgWrappers/deprecated-dotosg/osg/Shader.cpp index 8ea9d5a49..9c27f720f 100644 --- a/src/osgWrappers/deprecated-dotosg/osg/Shader.cpp +++ b/src/osgWrappers/deprecated-dotosg/osg/Shader.cpp @@ -47,10 +47,7 @@ bool Shader_readLocalData(Object& obj, Input& fr) { osg::ref_ptr s = osgDB::readRefShaderFile(fr[1].getStr(), fr.getOptions()); - if(s.get()) - shader.setShaderSource(s->getShaderSource()); - else - shader.loadShaderSourceFromFile( osgDB::findDataFile(fr[1].getStr()) ); + if(s.get()) shader.setShaderSource(s->getShaderSource()); fr += 2; iteratorAdvanced = true; diff --git a/src/osgWrappers/deprecated-dotosg/osgText/IO_Text.cpp b/src/osgWrappers/deprecated-dotosg/osgText/IO_Text.cpp index e34c1d46e..c2bb99e6a 100644 --- a/src/osgWrappers/deprecated-dotosg/osgText/IO_Text.cpp +++ b/src/osgWrappers/deprecated-dotosg/osgText/IO_Text.cpp @@ -57,27 +57,6 @@ std::string convertBackdropTypeEnumToString(osgText::Text::BackdropType backdrop } } - -osgText::Text::BackdropImplementation convertBackdropImplementationStringToEnum(std::string & str) -{ - if (str=="POLYGON_OFFSET") return osgText::Text::POLYGON_OFFSET; - else if (str=="NO_DEPTH_BUFFER") return osgText::Text::NO_DEPTH_BUFFER; - else if (str=="DEPTH_RANGE") return osgText::Text::DEPTH_RANGE; - else if (str=="STENCIL_BUFFER") return osgText::Text::STENCIL_BUFFER; - else return static_cast(-1); -} -std::string convertBackdropImplementationEnumToString(osgText::Text::BackdropImplementation backdropImplementation) -{ - switch (backdropImplementation) - { - case osgText::Text::POLYGON_OFFSET: return "POLYGON_OFFSET"; - case osgText::Text::NO_DEPTH_BUFFER: return "NO_DEPTH_BUFFER"; - case osgText::Text::DEPTH_RANGE: return "DEPTH_RANGE"; - case osgText::Text::STENCIL_BUFFER: return "STENCIL_BUFFER"; - default : return ""; - } -} - osgText::Text::ColorGradientMode convertColorGradientModeStringToEnum(std::string & str) { if (str=="SOLID") return osgText::Text::SOLID; @@ -155,12 +134,6 @@ bool Text_readLocalData(osg::Object &obj, osgDB::Input &fr) // backdropImplementation if (fr[0].matchWord("backdropImplementation")) { - std::string str = fr[1].getStr(); - osgText::Text::BackdropImplementation backdropImplementation = convertBackdropImplementationStringToEnum(str); - - if (backdropImplementation != static_cast(-1)) - text.setBackdropImplementation(backdropImplementation); - fr += 2; itAdvanced = true; } @@ -254,9 +227,6 @@ bool Text_writeLocalData(const osg::Object &obj, osgDB::Output &fw) osg::Vec4 c = text.getBackdropColor(); fw.indent() << "backdropColor " << c.x() << " " << c.y() << " " << c.z() << " " << c.w() << std::endl; - // backdropImplementation - fw.indent() << "backdropImplementation " << convertBackdropImplementationEnumToString(text.getBackdropImplementation()) << std::endl; - // colorGradientMode fw.indent() << "colorGradientMode " << convertColorGradientModeEnumToString(text.getColorGradientMode()) << std::endl; diff --git a/src/osgWrappers/serializers/osg/ComputeDispatch.cpp b/src/osgWrappers/serializers/osg/ComputeDispatch.cpp new file mode 100644 index 000000000..d77533a5d --- /dev/null +++ b/src/osgWrappers/serializers/osg/ComputeDispatch.cpp @@ -0,0 +1,36 @@ +#include +#include +#include +#include + +// _numGroupsX/Y/Z +static bool checkComputeGroups( const osg::ComputeDispatch& attr ) +{ + GLint numX = 0, numY = 0, numZ = 0; + attr.getComputeGroups( numX, numY, numZ ); + return numX>0 && numY>0 && numZ>0; +} + +static bool readComputeGroups( osgDB::InputStream& is, osg::ComputeDispatch& attr ) +{ + GLint numX = 0, numY = 0, numZ = 0; + is >> numX >> numY >> numZ; + attr.setComputeGroups( numX, numY, numZ ); + return true; +} + +static bool writeComputeGroups( osgDB::OutputStream& os, const osg::ComputeDispatch& attr ) +{ + GLint numX = 0, numY = 0, numZ = 0; + attr.getComputeGroups( numX, numY, numZ ); + os << numX << numY << numZ << std::endl; + return true; +} + +REGISTER_OBJECT_WRAPPER( ComputeDispatch, + new osg::ComputeDispatch, + osg::ComputeDispatch, + "osg::Object osg::Node osg::Drawable osg::ComputeDispatch" ) +{ + ADD_USER_SERIALIZER( ComputeGroups ); // _numGroupsX/Y/Z +} diff --git a/src/osgWrappers/serializers/osg/Program.cpp b/src/osgWrappers/serializers/osg/Program.cpp index d00096d5c..74e0342c3 100644 --- a/src/osgWrappers/serializers/osg/Program.cpp +++ b/src/osgWrappers/serializers/osg/Program.cpp @@ -124,27 +124,56 @@ static bool writeFeedBackMode( osgDB::OutputStream& os, const osg::Program& attr // _numGroupsX/Y/Z static bool checkComputeGroups( const osg::Program& attr ) { - GLint numX = 0, numY = 0, numZ = 0; - attr.getComputeGroups( numX, numY, numZ ); - return numX>0 && numY>0 && numZ>0; + return false; } static bool readComputeGroups( osgDB::InputStream& is, osg::Program& attr ) { GLint numX = 0, numY = 0, numZ = 0; is >> numX >> numY >> numZ; - attr.setComputeGroups( numX, numY, numZ ); return true; } static bool writeComputeGroups( osgDB::OutputStream& os, const osg::Program& attr ) { GLint numX = 0, numY = 0, numZ = 0; - attr.getComputeGroups( numX, numY, numZ ); os << numX << numY << numZ << std::endl; return true; } +static bool checkBindUniformBlock( const osg::Program& node ) +{ + return true; +} + +static bool readBindUniformBlock( osgDB::InputStream& is, osg::Program& p ) +{ + unsigned int size = 0; is >> size >> is.BEGIN_BRACKET; + std::string name; unsigned int index; + for ( unsigned int i=0; i>name; is >>index; + p.addBindUniformBlock(name, index); + } + is >> is.END_BRACKET; + return true; +} + + +static bool writeBindUniformBlock( osgDB::OutputStream& os, const osg::Program& p ) +{ + unsigned int size = p.getUniformBlockBindingList().size(); + os << size << os.BEGIN_BRACKET << std::endl; + for(osg::Program::UniformBlockBindingList::const_iterator bbit = p.getUniformBlockBindingList().begin(); + bbit != p.getUniformBlockBindingList().end(); ++bbit) + { + os << bbit->first; + os << bbit->second; + } + os << os.END_BRACKET << std::endl; + return true; +} + REGISTER_OBJECT_WRAPPER( Program, new osg::Program, osg::Program, @@ -162,9 +191,18 @@ REGISTER_OBJECT_WRAPPER( Program, ADD_USER_SERIALIZER( ComputeGroups ); // _numGroupsX/Y/Z } + { + UPDATE_TO_VERSION_SCOPED( 153 ) + REMOVE_SERIALIZER( ComputeGroups ); + } + { UPDATE_TO_VERSION_SCOPED( 116 ) ADD_USER_SERIALIZER( FeedBackVaryingsName ); ADD_USER_SERIALIZER( FeedBackMode ); } + { + UPDATE_TO_VERSION_SCOPED( 150 ) + ADD_USER_SERIALIZER( BindUniformBlock ); + } } diff --git a/src/osgWrappers/serializers/osg/StateSet.cpp b/src/osgWrappers/serializers/osg/StateSet.cpp index 8a94d1875..1112dbd82 100644 --- a/src/osgWrappers/serializers/osg/StateSet.cpp +++ b/src/osgWrappers/serializers/osg/StateSet.cpp @@ -270,6 +270,50 @@ static bool writeUniformList( osgDB::OutputStream& os, const osg::StateSet& ss ) return true; } +// _defineList +static bool checkDefineList( const osg::StateSet& ss ) +{ + return ss.getDefineList().size()>0; +} + +static bool readDefineList( osgDB::InputStream& is, osg::StateSet& ss ) +{ + unsigned int size = is.readSize(); is >> is.BEGIN_BRACKET; + for ( unsigned int i=0; i> is.PROPERTY("Value"); + int overrideValue = readValue( is ); + + ss.setDefine(defineName, defineValue, overrideValue); + + } + is >> is.END_BRACKET; + return true; +} + +static bool writeDefineList( osgDB::OutputStream& os, const osg::StateSet& ss ) +{ + const osg::StateSet::DefineList& df = ss.getDefineList(); + os.writeSize(df.size()); os << os.BEGIN_BRACKET << std::endl; + for ( osg::StateSet::DefineList::const_iterator itr=df.begin(); + itr!=df.end(); ++itr ) + { + os.writeWrappedString(itr->first); + os.writeWrappedString(itr->second.first); + os << os.PROPERTY("Value"); + writeValue(os, itr->second.second); + os << std::endl; + } + os << os.END_BRACKET << std::endl; + return true; +} + REGISTER_OBJECT_WRAPPER( StateSet, new osg::StateSet, osg::StateSet, @@ -295,4 +339,9 @@ REGISTER_OBJECT_WRAPPER( StateSet, ADD_BOOL_SERIALIZER( NestRenderBins, true ); // _nestRenderBins ADD_OBJECT_SERIALIZER( UpdateCallback, osg::StateSet::Callback, NULL ); // _updateCallback ADD_OBJECT_SERIALIZER( EventCallback, osg::StateSet::Callback, NULL ); // _eventCallback + + { + UPDATE_TO_VERSION_SCOPED( 151 ) + ADD_USER_SERIALIZER( DefineList ); // _defineList + } } diff --git a/src/osgWrappers/serializers/osgAnimation/AnimationManagerBase.cpp b/src/osgWrappers/serializers/osgAnimation/AnimationManagerBase.cpp index 06d2e353b..64d738da7 100644 --- a/src/osgWrappers/serializers/osgAnimation/AnimationManagerBase.cpp +++ b/src/osgWrappers/serializers/osgAnimation/AnimationManagerBase.cpp @@ -5,7 +5,8 @@ #include #include #include - +namespace osgAnimation_AnimationManagerBaseWrapper +{ static bool checkAnimations( const osgAnimation::AnimationManagerBase& manager ) { return manager.getAnimationList().size()>0; @@ -13,7 +14,8 @@ static bool checkAnimations( const osgAnimation::AnimationManagerBase& manager ) static bool readAnimations( osgDB::InputStream& is, osgAnimation::AnimationManagerBase& manager ) { - unsigned int size = is.readSize(); is >> is.BEGIN_BRACKET; + unsigned int size = is.readSize(); + is >> is.BEGIN_BRACKET; for ( unsigned int i=0; i ani = is.readObjectOfType(); @@ -26,16 +28,47 @@ static bool readAnimations( osgDB::InputStream& is, osgAnimation::AnimationManag static bool writeAnimations( osgDB::OutputStream& os, const osgAnimation::AnimationManagerBase& manager ) { const osgAnimation::AnimationList& animations = manager.getAnimationList(); - os.writeSize(animations.size()); os << os.BEGIN_BRACKET << std::endl; + os.writeSize(animations.size()); + os << os.BEGIN_BRACKET << std::endl; for ( osgAnimation::AnimationList::const_iterator itr=animations.begin(); - itr!=animations.end(); ++itr ) + itr!=animations.end(); ++itr ) { os << itr->get(); } os << os.END_BRACKET << std::endl; return true; } +struct osgAnimation_AnimationManagerBasegetnumAnimations : public osgDB::MethodObject +{ + virtual bool run(void* objectPtr, osg::Parameters& inputParameters, osg::Parameters& outputParameters) const + { + osgAnimation::AnimationManagerBase* group = dynamic_cast(reinterpret_cast(objectPtr)); + if (group) outputParameters.push_back(new osg::UIntValueObject("return",group->getNumRegisteredAnimations())); + return true; + } +}; +struct osgAnimation_AnimationManagerBasegetAnimation : public osgDB::MethodObject +{ + virtual bool run(void* objectPtr, osg::Parameters& inputParameters, osg::Parameters& outputParameters) const + { + if (inputParameters.empty()) return false; + osg::Object* indexObject = inputParameters[0].get(); + + unsigned int index = 0; + osg::DoubleValueObject* dvo = dynamic_cast(indexObject); + if (dvo) index = static_cast(dvo->getValue()); + else + { + osg::UIntValueObject* uivo = dynamic_cast(indexObject); + if (uivo) index = uivo->getValue(); + } + osgAnimation::AnimationManagerBase* group = dynamic_cast(reinterpret_cast(objectPtr)); + if (group) outputParameters.push_back(group->getRegisteredAnimation(index)); + + return true; + } +}; REGISTER_OBJECT_WRAPPER( osgAnimation_AnimationManagerBase, /*new osgAnimation::AnimationManagerBase*/NULL, osgAnimation::AnimationManagerBase, @@ -43,7 +76,14 @@ REGISTER_OBJECT_WRAPPER( osgAnimation_AnimationManagerBase, { ADD_USER_SERIALIZER( Animations ); // _animations ADD_BOOL_SERIALIZER( AutomaticLink, true ); // _automaticLink -} + + { + UPDATE_TO_VERSION_SCOPED( 152 ) + ADD_METHOD_OBJECT( "getRegisteredAnimation", osgAnimation_AnimationManagerBasegetAnimation ); + ADD_METHOD_OBJECT( "getNumRegisteredAnimations", osgAnimation_AnimationManagerBasegetnumAnimations ); + } +} +} #undef OBJECT_CAST #define OBJECT_CAST static_cast diff --git a/src/osgWrappers/serializers/osgAnimation/BasicAnimationManager.cpp b/src/osgWrappers/serializers/osgAnimation/BasicAnimationManager.cpp index 22b913a0c..e69869b5a 100644 --- a/src/osgWrappers/serializers/osgAnimation/BasicAnimationManager.cpp +++ b/src/osgWrappers/serializers/osgAnimation/BasicAnimationManager.cpp @@ -5,12 +5,71 @@ #include #include #include +namespace osgAnimation_BasicAnimationManagerWrapper{ +struct BasicAnimationManagerIsplaying : public osgDB::MethodObject +{ + virtual bool run(void* objectPtr, osg::Parameters& inputParameters, osg::Parameters& outputParameters) const + { + if (inputParameters.empty()) return false; + osgAnimation::Animation* child = dynamic_cast(inputParameters[0].get()); + if (!child) return false; + osgAnimation::BasicAnimationManager* group = dynamic_cast(reinterpret_cast(objectPtr)); + if (group) outputParameters.push_back(new osg::BoolValueObject("return", group->isPlaying(child))); + return true; + } +}; +struct BasicAnimationManagerfindAnimation : public osgDB::MethodObject +{ + virtual bool run(void* objectPtr, osg::Parameters& inputParameters, osg::Parameters& outputParameters) const + { + if (inputParameters.empty()) return false; + + osgAnimation::Animation* child = dynamic_cast(inputParameters[0].get()); + if (!child) return false; + osgAnimation::BasicAnimationManager* group = dynamic_cast(reinterpret_cast(objectPtr)); + if (group) outputParameters.push_back(new osg::BoolValueObject("return",group->findAnimation(child))); + return true; + } +}; +struct BasicAnimationManagerPlayanimation : public osgDB::MethodObject +{ + virtual bool run(void* objectPtr, osg::Parameters& inputParameters, osg::Parameters& outputParameters) const + { + if (inputParameters.empty()) return false; + + osgAnimation::Animation* child = dynamic_cast(inputParameters[0].get()); + if (!child) return false; + osgAnimation::BasicAnimationManager* group = dynamic_cast(reinterpret_cast(objectPtr)); + if (group) group->playAnimation(child); + return true; + } +}; +struct BasicAnimationManagerStopanimation : public osgDB::MethodObject +{ + virtual bool run(void* objectPtr, osg::Parameters& inputParameters, osg::Parameters& outputParameters) const + { + if (inputParameters.empty()) return false; + + osgAnimation::Animation* child = dynamic_cast(inputParameters[0].get()); + if (!child) return false; + osgAnimation::BasicAnimationManager* group = dynamic_cast(reinterpret_cast(objectPtr)); + if (group) group->stopAnimation(child); + return true; + } +}; REGISTER_OBJECT_WRAPPER( osgAnimation_BasicAnimationManager, new osgAnimation::BasicAnimationManager, osgAnimation::BasicAnimationManager, "osg::Object osg::NodeCallback osgAnimation::AnimationManagerBase osgAnimation::BasicAnimationManager" ) { + + ADD_METHOD_OBJECT( "isPlaying", BasicAnimationManagerIsplaying ); + ADD_METHOD_OBJECT( "findAnimation", BasicAnimationManagerfindAnimation ); + ADD_METHOD_OBJECT( "playAnimation", BasicAnimationManagerPlayanimation ); + ADD_METHOD_OBJECT( "stopAnimation", BasicAnimationManagerStopanimation ); + +} } #undef OBJECT_CAST diff --git a/src/osgWrappers/serializers/osgAnimation/MorphGeometry.cpp b/src/osgWrappers/serializers/osgAnimation/MorphGeometry.cpp index 8d3d3c58b..d2af644a9 100644 --- a/src/osgWrappers/serializers/osgAnimation/MorphGeometry.cpp +++ b/src/osgWrappers/serializers/osgAnimation/MorphGeometry.cpp @@ -36,10 +36,47 @@ static bool writeMorphTargets( osgDB::OutputStream& os, const osgAnimation::Morp return true; } +#define ADD_ARRAYDATA_FUNCTIONS( ORIGINAL_PROP, PROP ) \ + static bool check##ORIGINAL_PROP( const osgAnimation::MorphGeometry& geom ) \ + { return geom.get##PROP()!=0; } \ + static bool read##ORIGINAL_PROP( osgDB::InputStream& is, osgAnimation::MorphGeometry& geom ) { \ + is >> is.BEGIN_BRACKET; \ + osg::ref_ptr array = is.readArray(); \ + geom.set##PROP(dynamic_cast(array.get())); \ + is >> is.END_BRACKET; \ + return true; \ + } \ + static bool write##ORIGINAL_PROP( osgDB::OutputStream& os, const osgAnimation::MorphGeometry& geom ) { \ + os << os.BEGIN_BRACKET << std::endl; \ + os.writeArray( geom.get##PROP()); \ + os << os.END_BRACKET << std::endl; \ + return true; \ + } +ADD_ARRAYDATA_FUNCTIONS( VertexData, VertexSource ) +ADD_ARRAYDATA_FUNCTIONS( NormalData, NormalSource ) + +struct FinishedObjectReadFillSourceIfRequiredCallback : public osgDB::FinishedObjectReadCallback +{ + virtual void objectRead(osgDB::InputStream&, osg::Object& obj) + { + + osgAnimation::MorphGeometry& geometry = static_cast(obj); + if((!geometry.getVertexSource() ||geometry.getVertexSource()->getNumElements()==0) + && dynamic_cast(geometry.getVertexArray())){ + geometry.setVertexSource((osg::Vec3Array* )geometry.getVertexArray()->clone(osg::CopyOp::DEEP_COPY_ALL)); + } + if((!geometry.getNormalSource() ||geometry.getNormalSource()->getNumElements()==0) + && geometry.getNormalArray()){ + geometry.setNormalSource((osg::Vec3Array* )geometry.getNormalArray()->clone(osg::CopyOp::DEEP_COPY_ALL)); + } +} + +}; + REGISTER_OBJECT_WRAPPER( osgAnimation_MorphGeometry, new osgAnimation::MorphGeometry, osgAnimation::MorphGeometry, - "osg::Object osg::Drawable osg::Geometry osgAnimation::MorphGeometry" ) + "osg::Object osg::Node osg::Drawable osg::Geometry osgAnimation::MorphGeometry" ) { BEGIN_ENUM_SERIALIZER( Method, NORMALIZED ); ADD_ENUM_VALUE( NORMALIZED ); @@ -48,4 +85,14 @@ REGISTER_OBJECT_WRAPPER( osgAnimation_MorphGeometry, ADD_USER_SERIALIZER( MorphTargets ); // _morphTargets ADD_BOOL_SERIALIZER( MorphNormals, true ); // _morphNormals + ADD_USER_SERIALIZER( VertexData ); // VertexSource + ADD_USER_SERIALIZER( NormalData ); // NormalSource + + + { + UPDATE_TO_VERSION_SCOPED( 147 ) + ADD_OBJECT_SERIALIZER( MorphTransformImplementation, osgAnimation::MorphTransform, NULL ); // _geometry + } + + wrapper->addFinishedObjectReadCallback( new FinishedObjectReadFillSourceIfRequiredCallback() ); } diff --git a/src/osgWrappers/serializers/osgAnimation/RigGeometry.cpp b/src/osgWrappers/serializers/osgAnimation/RigGeometry.cpp index 2787ec91c..be47b97b1 100644 --- a/src/osgWrappers/serializers/osgAnimation/RigGeometry.cpp +++ b/src/osgWrappers/serializers/osgAnimation/RigGeometry.cpp @@ -3,6 +3,7 @@ #include #include +namespace wrap_osgAnimationRigGeometry{ static bool checkInfluenceMap( const osgAnimation::RigGeometry& geom ) { return geom.getInfluenceMap()->size()>0; @@ -14,14 +15,13 @@ static bool readInfluenceMap( osgDB::InputStream& is, osgAnimation::RigGeometry& unsigned int size = is.readSize(); is >> is.BEGIN_BRACKET; for ( unsigned int i=0; i> is.PROPERTY("VertexInfluence"); - is.readWrappedString(name); + is.readWrappedString(bonename); viSize = is.readSize(); is >> is.BEGIN_BRACKET; - osgAnimation::VertexInfluence vi; - vi.setName( name ); + vi.setName( bonename ); vi.reserve( viSize ); for ( unsigned int j=0; j> index >> weight; vi.push_back( osgAnimation::VertexIndexWeight(index, weight) ); } - (*map)[name] = vi; + (*map)[bonename] = vi; is >> is.END_BRACKET; } is >> is.END_BRACKET; @@ -78,3 +78,4 @@ REGISTER_OBJECT_WRAPPER( osgAnimation_RigGeometry, ADD_OBJECT_SERIALIZER( RigTransformImplementation, osgAnimation::RigTransform, NULL ); // _geometry } } +} diff --git a/src/osgWrappers/serializers/osgAnimation/RigTransform.cpp b/src/osgWrappers/serializers/osgAnimation/RigTransform.cpp index 82ba7b05d..61d4fbd88 100644 --- a/src/osgWrappers/serializers/osgAnimation/RigTransform.cpp +++ b/src/osgWrappers/serializers/osgAnimation/RigTransform.cpp @@ -1,25 +1,70 @@ #include #include -#include +#include + #include + #include #include #include -namespace wrap_osgAnimationRigTransform{ - REGISTER_OBJECT_WRAPPER( osgAnimation_RigTransform, +namespace wrap_osgAnimationRigTransform +{ + REGISTER_OBJECT_WRAPPER( osgAnimation_RigTransform, NULL, osgAnimation::RigTransform, "osg::Object osgAnimation::RigTransform" ){} } -namespace wrap_osgAnimationRigTransformSoftWare{ - REGISTER_OBJECT_WRAPPER( osgAnimation_RigTransformSoftware, + +namespace wrap_osgAnimationRigTransformSoftWare +{ + REGISTER_OBJECT_WRAPPER( osgAnimation_RigTransformSoftware, new osgAnimation::RigTransformSoftware, osgAnimation::RigTransformSoftware, "osg::Object osgAnimation::RigTransform osgAnimation::RigTransformSoftware" ){} } -namespace wrap_osgAnimationRigTransformHardWare{ - REGISTER_OBJECT_WRAPPER( osgAnimation_RigTransformHardware, + +namespace wrap_osgAnimationRigTransformHardWare +{ + REGISTER_OBJECT_WRAPPER( osgAnimation_RigTransformHardware, new osgAnimation::RigTransformHardware, osgAnimation::RigTransformHardware, - "osg::Object osgAnimation::RigTransform osgAnimation::RigTransformHardware" ){} + "osg::Object osgAnimation::RigTransform osgAnimation::RigTransformHardware" ) + { + { + UPDATE_TO_VERSION_SCOPED(152) + ADD_OBJECT_SERIALIZER(Shader, osg::Shader, NULL); + ADD_UINT_SERIALIZER(FirstVertexAttributeTarget, RIGTRANSHW_DEFAULT_FIRST_VERTATTRIB_TARGETTED); + } + } +} + +namespace wrap_osgAnimationMorphTransform +{ + REGISTER_OBJECT_WRAPPER( osgAnimation_MorphTransform, + NULL, + osgAnimation::MorphTransform, + "osg::Object osgAnimation::MorphTransform" ){} +} + +namespace wrap_osgAnimationMorphTransformSoftWare +{ + REGISTER_OBJECT_WRAPPER( osgAnimation_MorphTransformSoftware, + new osgAnimation::MorphTransformSoftware, + osgAnimation::MorphTransformSoftware, + "osg::Object osgAnimation::MorphTransform osgAnimation::MorphTransformSoftware" ){} +} + +namespace wrap_osgAnimationMorphTransformHardware +{ + REGISTER_OBJECT_WRAPPER( osgAnimation_MorphTransformHardware, + new osgAnimation::MorphTransformHardware, + osgAnimation::MorphTransformHardware, + "osg::Object osgAnimation::MorphTransform osgAnimation::MorphTransformHardware") + { + { + UPDATE_TO_VERSION_SCOPED(152) + ADD_OBJECT_SERIALIZER(Shader, osg::Shader, NULL); + ADD_UINT_SERIALIZER(ReservedTextureUnit, MORPHTRANSHW_DEFAULTMORPHTEXTUREUNIT); + } + } }