mirror of
https://github.com/overte-org/overte.git
synced 2025-08-10 06:53:01 +02:00
Merge remote-tracking branch 'upstream/master' into bindless
This commit is contained in:
commit
0e7ee95c95
58 changed files with 983 additions and 513 deletions
|
@ -18,6 +18,10 @@ if (BUILD_SCRIBE_ONLY)
|
||||||
return()
|
return()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if (NOT DEFINED CLIENT_ONLY)
|
||||||
|
set(CLIENT_ONLY 0)
|
||||||
|
endif()
|
||||||
|
|
||||||
if (NOT DEFINED SERVER_ONLY)
|
if (NOT DEFINED SERVER_ONLY)
|
||||||
set(SERVER_ONLY 0)
|
set(SERVER_ONLY 0)
|
||||||
endif()
|
endif()
|
||||||
|
@ -28,41 +32,49 @@ else()
|
||||||
set(MOBILE 0)
|
set(MOBILE 0)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
set(BUILD_CLIENT_OPTION ON)
|
||||||
|
set(BUILD_SERVER_OPTION ON)
|
||||||
|
set(BUILD_TESTS_OPTION ON)
|
||||||
|
set(BUILD_TOOLS_OPTION ON)
|
||||||
|
set(BUILD_INSTALLER_OPTION ON)
|
||||||
|
set(GLES_OPTION OFF)
|
||||||
|
set(DISABLE_QML_OPTION OFF)
|
||||||
|
|
||||||
if (ANDROID OR UWP)
|
if (ANDROID OR UWP)
|
||||||
option(BUILD_SERVER "Build server components" OFF)
|
set(BUILD_SERVER_OPTION OFF)
|
||||||
option(BUILD_TOOLS "Build tools" OFF)
|
set(BUILD_TOOLS_OPTION OFF)
|
||||||
option(BUILD_INSTALLER "Build installer" OFF)
|
set(BUILD_INSTALLER OFF)
|
||||||
else()
|
endif()
|
||||||
option(BUILD_SERVER "Build server components" ON)
|
|
||||||
option(BUILD_TOOLS "Build tools" ON)
|
if (CLIENT_ONLY)
|
||||||
option(BUILD_INSTALLER "Build installer" ON)
|
set(BUILD_SERVER_OPTION OFF)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (SERVER_ONLY)
|
if (SERVER_ONLY)
|
||||||
option(BUILD_CLIENT "Build client components" OFF)
|
set(BUILD_CLIENT_OPTION OFF)
|
||||||
option(BUILD_TESTS "Build tests" OFF)
|
set(BUILD_TESTS_OPTION OFF)
|
||||||
else()
|
|
||||||
option(BUILD_CLIENT "Build client components" ON)
|
|
||||||
option(BUILD_TESTS "Build tests" ON)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (ANDROID)
|
if (ANDROID)
|
||||||
option(USE_GLES "Use OpenGL ES" ON)
|
set(GLES_OPTION ON)
|
||||||
set(PLATFORM_QT_COMPONENTS AndroidExtras WebView)
|
set(PLATFORM_QT_COMPONENTS AndroidExtras WebView)
|
||||||
else ()
|
else ()
|
||||||
option(USE_GLES "Use OpenGL ES" OFF)
|
|
||||||
set(PLATFORM_QT_COMPONENTS WebEngine WebEngineWidgets)
|
set(PLATFORM_QT_COMPONENTS WebEngine WebEngineWidgets)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
if (USE_GLES AND (NOT ANDROID))
|
if (USE_GLES AND (NOT ANDROID))
|
||||||
option(DISABLE_QML "Disable QML" ON)
|
set(DISABLE_QML_OPTION ON)
|
||||||
else()
|
|
||||||
option(DISABLE_QML "Disable QML" OFF)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
option(BUILD_CLIENT "Build client components" ${BUILD_CLIENT_OPTION})
|
||||||
|
option(BUILD_SERVER "Build server components" ${BUILD_SERVER_OPTION})
|
||||||
|
option(BUILD_TESTS "Build tests" ${BUILD_TESTS_OPTION})
|
||||||
|
option(BUILD_TOOLS "Build tools" ${BUILD_TOOLS_OPTION})
|
||||||
|
option(BUILD_INSTALLER "Build installer" ${BUILD_INSTALLER_OPTION})
|
||||||
|
option(USE_GLES "Use OpenGL ES" ${GLES_OPTION})
|
||||||
|
option(DISABLE_QML "Disable QML" ${DISABLE_QML_OPTION})
|
||||||
option(DISABLE_KTX_CACHE "Disable KTX Cache" OFF)
|
option(DISABLE_KTX_CACHE "Disable KTX Cache" OFF)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
set(PLATFORM_QT_GL OpenGL)
|
set(PLATFORM_QT_GL OpenGL)
|
||||||
|
|
||||||
if (USE_GLES)
|
if (USE_GLES)
|
||||||
|
@ -72,12 +84,10 @@ else()
|
||||||
set(PLATFORM_GL_BACKEND gpu-gl-common gpu-gl)
|
set(PLATFORM_GL_BACKEND gpu-gl-common gpu-gl)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
foreach(PLATFORM_QT_COMPONENT ${PLATFORM_QT_COMPONENTS})
|
foreach(PLATFORM_QT_COMPONENT ${PLATFORM_QT_COMPONENTS})
|
||||||
list(APPEND PLATFORM_QT_LIBRARIES "Qt5::${PLATFORM_QT_COMPONENT}")
|
list(APPEND PLATFORM_QT_LIBRARIES "Qt5::${PLATFORM_QT_COMPONENT}")
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
|
|
||||||
MESSAGE(STATUS "Build server: " ${BUILD_SERVER})
|
MESSAGE(STATUS "Build server: " ${BUILD_SERVER})
|
||||||
MESSAGE(STATUS "Build client: " ${BUILD_CLIENT})
|
MESSAGE(STATUS "Build client: " ${BUILD_CLIENT})
|
||||||
MESSAGE(STATUS "Build tests: " ${BUILD_TESTS})
|
MESSAGE(STATUS "Build tests: " ${BUILD_TESTS})
|
||||||
|
@ -86,13 +96,13 @@ MESSAGE(STATUS "Build installer: " ${BUILD_INSTALLER})
|
||||||
MESSAGE(STATUS "GL ES: " ${USE_GLES})
|
MESSAGE(STATUS "GL ES: " ${USE_GLES})
|
||||||
|
|
||||||
if (DISABLE_QML)
|
if (DISABLE_QML)
|
||||||
MESSAGE(STATUS "QML disabled!")
|
MESSAGE(STATUS "QML disabled!")
|
||||||
add_definitions(-DDISABLE_QML)
|
add_definitions(-DDISABLE_QML)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (DISABLE_KTX_CACHE)
|
if (DISABLE_KTX_CACHE)
|
||||||
MESSAGE(STATUS "KTX cache disabled!")
|
MESSAGE(STATUS "KTX cache disabled!")
|
||||||
add_definitions(-DDISABLE_KTX_CACHE)
|
add_definitions(-DDISABLE_KTX_CACHE)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (UNIX AND DEFINED ENV{HIFI_MEMORY_DEBUGGING})
|
if (UNIX AND DEFINED ENV{HIFI_MEMORY_DEBUGGING})
|
||||||
|
@ -150,10 +160,8 @@ endif()
|
||||||
if (BUILD_CLIENT)
|
if (BUILD_CLIENT)
|
||||||
add_subdirectory(interface)
|
add_subdirectory(interface)
|
||||||
set_target_properties(interface PROPERTIES FOLDER "Apps")
|
set_target_properties(interface PROPERTIES FOLDER "Apps")
|
||||||
if (ANDROID)
|
|
||||||
add_subdirectory(gvr-interface)
|
option(USE_SIXENSE "Build Interface with sixense library/plugin" OFF)
|
||||||
set_target_properties(gvr-interface PROPERTIES FOLDER "Apps")
|
|
||||||
endif()
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (BUILD_CLIENT OR BUILD_SERVER)
|
if (BUILD_CLIENT OR BUILD_SERVER)
|
||||||
|
|
|
@ -17,6 +17,8 @@ To produce an executable installer on Windows, the following are required:
|
||||||
- [Nullsoft Scriptable Install System](http://nsis.sourceforge.net/Download) - 3.0b3
|
- [Nullsoft Scriptable Install System](http://nsis.sourceforge.net/Download) - 3.0b3
|
||||||
- [UAC Plug-in for Nullsoft](http://nsis.sourceforge.net/UAC_plug-in) - 0.2.4c
|
- [UAC Plug-in for Nullsoft](http://nsis.sourceforge.net/UAC_plug-in) - 0.2.4c
|
||||||
- [nsProcess Plug-in for Nullsoft](http://nsis.sourceforge.net/NsProcess_plugin) - 1.6
|
- [nsProcess Plug-in for Nullsoft](http://nsis.sourceforge.net/NsProcess_plugin) - 1.6
|
||||||
|
- [Inetc Plug-in for Nullsoft](http://nsis.sourceforge.net/Inetc_plug-in) - 1.0
|
||||||
|
- [NSISpcre Plug-in for Nullsoft](http://nsis.sourceforge.net/NSISpcre_plug-in) - 1.0
|
||||||
|
|
||||||
Run the `package` target to create an executable installer using the Nullsoft Scriptable Install System.
|
Run the `package` target to create an executable installer using the Nullsoft Scriptable Install System.
|
||||||
|
|
||||||
|
|
|
@ -476,6 +476,7 @@ void EntityScriptServer::clear() {
|
||||||
// do this here (instead of in deleter) to avoid marshalling unload signals back to this thread
|
// do this here (instead of in deleter) to avoid marshalling unload signals back to this thread
|
||||||
_entitiesScriptEngine->unloadAllEntityScripts();
|
_entitiesScriptEngine->unloadAllEntityScripts();
|
||||||
_entitiesScriptEngine->stop();
|
_entitiesScriptEngine->stop();
|
||||||
|
_entitiesScriptEngine->waitTillDoneRunning();
|
||||||
}
|
}
|
||||||
|
|
||||||
_entityViewer.clear();
|
_entityViewer.clear();
|
||||||
|
@ -565,8 +566,15 @@ void EntityScriptServer::handleOctreePacket(QSharedPointer<ReceivedMessage> mess
|
||||||
void EntityScriptServer::aboutToFinish() {
|
void EntityScriptServer::aboutToFinish() {
|
||||||
shutdownScriptEngine();
|
shutdownScriptEngine();
|
||||||
|
|
||||||
|
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
|
||||||
// our entity tree is going to go away so tell that to the EntityScriptingInterface
|
// our entity tree is going to go away so tell that to the EntityScriptingInterface
|
||||||
DependencyManager::get<EntityScriptingInterface>()->setEntityTree(nullptr);
|
entityScriptingInterface->setEntityTree(nullptr);
|
||||||
|
|
||||||
|
// Should always be true as they are singletons.
|
||||||
|
if (entityScriptingInterface->getPacketSender() == &_entityEditSender) {
|
||||||
|
// The packet sender is about to go away.
|
||||||
|
entityScriptingInterface->setPacketSender(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
DependencyManager::get<ResourceManager>()->cleanup();
|
DependencyManager::get<ResourceManager>()->cleanup();
|
||||||
|
|
||||||
|
|
2
cmake/externals/quazip/CMakeLists.txt
vendored
2
cmake/externals/quazip/CMakeLists.txt
vendored
|
@ -4,7 +4,7 @@ cmake_policy(SET CMP0046 OLD)
|
||||||
|
|
||||||
include(ExternalProject)
|
include(ExternalProject)
|
||||||
|
|
||||||
set(QUAZIP_CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> -DCMAKE_PREFIX_PATH=${QT_CMAKE_PREFIX_PATH} -DCMAKE_INSTALL_NAME_DIR:PATH=<INSTALL_DIR>/lib -DZLIB_ROOT=${ZLIB_ROOT} -DCMAKE_POSITION_INDEPENDENT_CODE=ON)
|
set(QUAZIP_CMAKE_ARGS -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> -DCMAKE_PREFIX_PATH=${QT_CMAKE_PREFIX_PATH} -DCMAKE_INSTALL_NAME_DIR:PATH=<INSTALL_DIR>/lib -DZLIB_ROOT=${ZLIB_ROOT} -DCMAKE_POSITION_INDEPENDENT_CODE=ON)
|
||||||
|
|
||||||
if (APPLE)
|
if (APPLE)
|
||||||
else ()
|
else ()
|
||||||
|
|
|
@ -23,7 +23,7 @@ macro(GENERATE_INSTALLERS)
|
||||||
set(CPACK_NSIS_DISPLAY_NAME ${_DISPLAY_NAME})
|
set(CPACK_NSIS_DISPLAY_NAME ${_DISPLAY_NAME})
|
||||||
set(CPACK_NSIS_PACKAGE_NAME ${_DISPLAY_NAME})
|
set(CPACK_NSIS_PACKAGE_NAME ${_DISPLAY_NAME})
|
||||||
if (PR_BUILD)
|
if (PR_BUILD)
|
||||||
set(CPACK_NSIS_COMPRESSOR "/SOLID bzip2")
|
set(CPACK_NSIS_COMPRESSOR "bzip2")
|
||||||
endif ()
|
endif ()
|
||||||
set(CPACK_PACKAGE_INSTALL_DIRECTORY ${_DISPLAY_NAME})
|
set(CPACK_PACKAGE_INSTALL_DIRECTORY ${_DISPLAY_NAME})
|
||||||
|
|
||||||
|
@ -46,9 +46,35 @@ macro(GENERATE_INSTALLERS)
|
||||||
set(UNINSTALLER_HEADER_IMAGE "")
|
set(UNINSTALLER_HEADER_IMAGE "")
|
||||||
fix_path_for_nsis(${_UNINSTALLER_HEADER_BAD_PATH} UNINSTALLER_HEADER_IMAGE)
|
fix_path_for_nsis(${_UNINSTALLER_HEADER_BAD_PATH} UNINSTALLER_HEADER_IMAGE)
|
||||||
|
|
||||||
# grab the latest VC redist (2017) and add it to the installer, our NSIS template
|
# we use external libraries that still need the 120 (VS2013) redistributables
|
||||||
# will call it during the install
|
# so we include them as well until those external libraries are updated
|
||||||
install(CODE "file(DOWNLOAD https://go.microsoft.com/fwlink/?LinkId=746572 \"\${CMAKE_INSTALL_PREFIX}/vcredist_x64.exe\")")
|
# to use the redistributables that match what we build our applications for
|
||||||
|
set(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS
|
||||||
|
"C:/Windows/System32/msvcp120.dll"
|
||||||
|
"C:/Windows/System32/msvcr120.dll"
|
||||||
|
)
|
||||||
|
|
||||||
|
set(CMAKE_INSTALL_UCRT_LIBRARIES TRUE)
|
||||||
|
set(CMAKE_INSTALL_SYSTEM_RUNTIME_DESTINATION ${INTERFACE_INSTALL_DIR})
|
||||||
|
set(CMAKE_INSTALL_SYSTEM_RUNTIME_COMPONENT ${CLIENT_COMPONENT})
|
||||||
|
include(InstallRequiredSystemLibraries)
|
||||||
|
|
||||||
|
if (CLIENT_ONLY OR SERVER_ONLY)
|
||||||
|
set(CPACK_MONOLITHIC_INSTALL 1)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
# setup conditional checks for server component selection depending on
|
||||||
|
# the inclusion of the server component at all
|
||||||
|
if (CLIENT_ONLY)
|
||||||
|
set(SERVER_COMPONENT_CONDITIONAL "0 == 1")
|
||||||
|
set(CLIENT_COMPONENT_CONDITIONAL "1 == 1")
|
||||||
|
elseif (SERVER_ONLY)
|
||||||
|
set(SERVER_COMPONENT_CONDITIONAL "1 == 1")
|
||||||
|
set(CLIENT_COMPONENT_CONDITIONAL "0 == 1")
|
||||||
|
else ()
|
||||||
|
set(SERVER_COMPONENT_CONDITIONAL "\\\${SectionIsSelected} \\\${${SERVER_COMPONENT}}")
|
||||||
|
set(CLIENT_COMPONENT_CONDITIONAL "\\\${SectionIsSelected} \\\${${CLIENT_COMPONENT}}")
|
||||||
|
endif ()
|
||||||
elseif (APPLE)
|
elseif (APPLE)
|
||||||
# produce a drag and drop DMG on OS X
|
# produce a drag and drop DMG on OS X
|
||||||
set(CPACK_GENERATOR "DragNDrop")
|
set(CPACK_GENERATOR "DragNDrop")
|
||||||
|
@ -79,8 +105,13 @@ macro(GENERATE_INSTALLERS)
|
||||||
|
|
||||||
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/LICENSE")
|
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/LICENSE")
|
||||||
|
|
||||||
|
if (BUILD_CLIENT)
|
||||||
cpack_add_component(${CLIENT_COMPONENT} DISPLAY_NAME "High Fidelity Interface")
|
cpack_add_component(${CLIENT_COMPONENT} DISPLAY_NAME "High Fidelity Interface")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
if (BUILD_SERVER)
|
||||||
cpack_add_component(${SERVER_COMPONENT} DISPLAY_NAME "High Fidelity Sandbox")
|
cpack_add_component(${SERVER_COMPONENT} DISPLAY_NAME "High Fidelity Sandbox")
|
||||||
|
endif ()
|
||||||
|
|
||||||
include(CPack)
|
include(CPack)
|
||||||
endmacro()
|
endmacro()
|
||||||
|
|
|
@ -39,7 +39,9 @@ macro(PACKAGE_LIBRARIES_FOR_DEPLOYMENT)
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
TARGET ${TARGET_NAME}
|
TARGET ${TARGET_NAME}
|
||||||
POST_BUILD
|
POST_BUILD
|
||||||
COMMAND CMD /C "SET PATH=%PATH%;${QT_DIR}/bin && ${WINDEPLOYQT_COMMAND} ${EXTRA_DEPLOY_OPTIONS} $<$<OR:$<CONFIG:Release>,$<CONFIG:MinSizeRel>,$<CONFIG:RelWithDebInfo>>:--release> \"$<TARGET_FILE:${TARGET_NAME}>\""
|
COMMAND CMD /C "SET PATH=%PATH%;${QT_DIR}/bin && ${WINDEPLOYQT_COMMAND}\
|
||||||
|
${EXTRA_DEPLOY_OPTIONS} $<$<OR:$<CONFIG:Release>,$<CONFIG:MinSizeRel>,$<CONFIG:RelWithDebInfo>>:--release>\
|
||||||
|
--no-compiler-runtime --no-opengl-sw --no-angle -no-system-d3d-compiler \"$<TARGET_FILE:${TARGET_NAME}>\""
|
||||||
)
|
)
|
||||||
|
|
||||||
set(QTAUDIO_PATH "$<TARGET_FILE_DIR:${TARGET_NAME}>/audio")
|
set(QTAUDIO_PATH "$<TARGET_FILE_DIR:${TARGET_NAME}>/audio")
|
||||||
|
|
|
@ -27,6 +27,11 @@ macro(SET_PACKAGING_PARAMETERS)
|
||||||
message(STATUS "The BRANCH environment variable is: $ENV{BRANCH}")
|
message(STATUS "The BRANCH environment variable is: $ENV{BRANCH}")
|
||||||
message(STATUS "The RELEASE_TYPE variable is: ${RELEASE_TYPE}")
|
message(STATUS "The RELEASE_TYPE variable is: ${RELEASE_TYPE}")
|
||||||
|
|
||||||
|
# setup component categories for installer
|
||||||
|
set(DDE_COMPONENT dde)
|
||||||
|
set(CLIENT_COMPONENT client)
|
||||||
|
set(SERVER_COMPONENT server)
|
||||||
|
|
||||||
if (RELEASE_TYPE STREQUAL "PRODUCTION")
|
if (RELEASE_TYPE STREQUAL "PRODUCTION")
|
||||||
set(DEPLOY_PACKAGE TRUE)
|
set(DEPLOY_PACKAGE TRUE)
|
||||||
set(PRODUCTION_BUILD 1)
|
set(PRODUCTION_BUILD 1)
|
||||||
|
@ -149,13 +154,10 @@ macro(SET_PACKAGING_PARAMETERS)
|
||||||
set(CLIENT_LAUNCH_NOW_REG_KEY "ClientLaunchAfterInstall")
|
set(CLIENT_LAUNCH_NOW_REG_KEY "ClientLaunchAfterInstall")
|
||||||
set(SERVER_LAUNCH_NOW_REG_KEY "ServerLaunchAfterInstall")
|
set(SERVER_LAUNCH_NOW_REG_KEY "ServerLaunchAfterInstall")
|
||||||
set(CUSTOM_INSTALL_REG_KEY "CustomInstall")
|
set(CUSTOM_INSTALL_REG_KEY "CustomInstall")
|
||||||
|
set(CLIENT_ID_REG_KEY "ClientGUID")
|
||||||
|
set(GA_TRACKING_ID $ENV{GA_TRACKING_ID})
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
# setup component categories for installer
|
|
||||||
set(DDE_COMPONENT dde)
|
|
||||||
set(CLIENT_COMPONENT client)
|
|
||||||
set(SERVER_COMPONENT server)
|
|
||||||
|
|
||||||
# print out some results for testing this new build feature
|
# print out some results for testing this new build feature
|
||||||
message(STATUS "The BUILD_GLOBAL_SERVICES variable is: ${BUILD_GLOBAL_SERVICES}")
|
message(STATUS "The BUILD_GLOBAL_SERVICES variable is: ${BUILD_GLOBAL_SERVICES}")
|
||||||
message(STATUS "The USE_STABLE_GLOBAL_SERVICES variable is: ${USE_STABLE_GLOBAL_SERVICES}")
|
message(STATUS "The USE_STABLE_GLOBAL_SERVICES variable is: ${USE_STABLE_GLOBAL_SERVICES}")
|
||||||
|
|
|
@ -41,6 +41,10 @@ set(CONSOLE_STARTUP_REG_KEY "@CONSOLE_STARTUP_REG_KEY@")
|
||||||
set(SERVER_LAUNCH_NOW_REG_KEY "@SERVER_LAUNCH_NOW_REG_KEY@")
|
set(SERVER_LAUNCH_NOW_REG_KEY "@SERVER_LAUNCH_NOW_REG_KEY@")
|
||||||
set(CLIENT_LAUNCH_NOW_REG_KEY "@CLIENT_LAUNCH_NOW_REG_KEY@")
|
set(CLIENT_LAUNCH_NOW_REG_KEY "@CLIENT_LAUNCH_NOW_REG_KEY@")
|
||||||
set(CUSTOM_INSTALL_REG_KEY "@CUSTOM_INSTALL_REG_KEY@")
|
set(CUSTOM_INSTALL_REG_KEY "@CUSTOM_INSTALL_REG_KEY@")
|
||||||
|
set(GA_TRACKING_ID "@GA_TRACKING_ID@")
|
||||||
|
set(CLIENT_ID_REG_KEY "@CLIENT_ID_REG_KEY@")
|
||||||
set(INSTALLER_HEADER_IMAGE "@INSTALLER_HEADER_IMAGE@")
|
set(INSTALLER_HEADER_IMAGE "@INSTALLER_HEADER_IMAGE@")
|
||||||
set(UNINSTALLER_HEADER_IMAGE "@UNINSTALLER_HEADER_IMAGE@")
|
set(UNINSTALLER_HEADER_IMAGE "@UNINSTALLER_HEADER_IMAGE@")
|
||||||
set(ADD_REMOVE_ICON_PATH "@ADD_REMOVE_ICON_PATH@")
|
set(ADD_REMOVE_ICON_PATH "@ADD_REMOVE_ICON_PATH@")
|
||||||
|
set(SERVER_COMPONENT_CONDITIONAL "@SERVER_COMPONENT_CONDITIONAL@")
|
||||||
|
set(CLIENT_COMPONENT_CONDITIONAL "@CLIENT_COMPONENT_CONDITIONAL@")
|
||||||
|
|
|
@ -319,6 +319,78 @@ Function DownloadFile
|
||||||
FunctionEnd
|
FunctionEnd
|
||||||
!endif
|
!endif
|
||||||
|
|
||||||
|
|
||||||
|
!include NSISpcre.nsh
|
||||||
|
!insertmacro REMatches
|
||||||
|
|
||||||
|
Var CampaignName
|
||||||
|
|
||||||
|
!macro GetCampaignName RetVar
|
||||||
|
Call GetCampaignName
|
||||||
|
Pop ${RetVar}
|
||||||
|
!macroend
|
||||||
|
|
||||||
|
Function GetCampaignName
|
||||||
|
Push $0 ; Stash $0
|
||||||
|
|
||||||
|
; Parse filename out of the path
|
||||||
|
${RECaptureMatches} $0 "([^\\]*\\)*(.*)\.exe" $EXEPATH 0
|
||||||
|
${If} $0 == 2
|
||||||
|
Pop $0 ; Discard Path
|
||||||
|
Pop $0 ; Recover filename
|
||||||
|
; Parse campaign out of the filename
|
||||||
|
${RECaptureMatches} $0 "HighFidelity-([^-]*-)Beta-.*" $0 0
|
||||||
|
${If} $0 == 1
|
||||||
|
Pop $0 ; Recover campaign name
|
||||||
|
StrCpy $0 $0 -1 0 ; Remove trailing - and copy to _RetVar
|
||||||
|
${Else}
|
||||||
|
StrCpy $0 ""
|
||||||
|
${EndIf}
|
||||||
|
${Else}
|
||||||
|
StrCpy $0 ""
|
||||||
|
${EndIf}
|
||||||
|
|
||||||
|
Exch $0 ; Restore $0 and push result
|
||||||
|
FunctionEnd
|
||||||
|
|
||||||
|
!macro CreateGUID RetVar
|
||||||
|
System::Call 'ole32::CoCreateGuid(g .s)'
|
||||||
|
Pop ${RetVar}
|
||||||
|
; Strip opening and closing braces
|
||||||
|
StrCpy ${RetVar} ${RetVar} -1 1
|
||||||
|
!macroend
|
||||||
|
|
||||||
|
Var GAClientID
|
||||||
|
|
||||||
|
!macro InitGAClientID
|
||||||
|
; Generate a new GUID on every run for now
|
||||||
|
!insertmacro CreateGUID $GAClientID
|
||||||
|
!macroend
|
||||||
|
|
||||||
|
!macro GoogleAnalytics Category Action Label Value
|
||||||
|
${If} "@GA_TRACKING_ID@" != ""
|
||||||
|
Push $0
|
||||||
|
Push $1
|
||||||
|
|
||||||
|
StrCpy $0 "https://google-analytics.com/collect?v=1&tid=@GA_TRACKING_ID@"
|
||||||
|
StrCpy $0 "$0&cid=$GAClientID&t=event&ec=${Category}&ea=${Action}"
|
||||||
|
|
||||||
|
${If} "${Label}" != ""
|
||||||
|
StrCpy $0 "$0&el=${Label}"
|
||||||
|
${EndIf}
|
||||||
|
${If} "${Value}" != ""
|
||||||
|
StrCpy $0 "$0&ev=${Value}"
|
||||||
|
${EndIf}
|
||||||
|
|
||||||
|
GetTempFileName $1
|
||||||
|
inetc::get /SILENT $0 $1 /END
|
||||||
|
Delete $1
|
||||||
|
|
||||||
|
Pop $1
|
||||||
|
Pop $0
|
||||||
|
${EndIf}
|
||||||
|
!macroend
|
||||||
|
|
||||||
;--------------------------------
|
;--------------------------------
|
||||||
; Installation types
|
; Installation types
|
||||||
|
|
||||||
|
@ -342,28 +414,38 @@ SectionEnd
|
||||||
|
|
||||||
;--------------------------------
|
;--------------------------------
|
||||||
;Pages
|
;Pages
|
||||||
|
!define MUI_CUSTOMFUNCTION_ABORT OnUserAbort
|
||||||
|
|
||||||
|
!define MUI_PAGE_CUSTOMFUNCTION_PRE PageWelcomePre
|
||||||
!insertmacro MUI_PAGE_WELCOME
|
!insertmacro MUI_PAGE_WELCOME
|
||||||
|
|
||||||
|
!define MUI_PAGE_CUSTOMFUNCTION_PRE PageLicensePre
|
||||||
!insertmacro MUI_PAGE_LICENSE "@CPACK_RESOURCE_FILE_LICENSE@"
|
!insertmacro MUI_PAGE_LICENSE "@CPACK_RESOURCE_FILE_LICENSE@"
|
||||||
|
|
||||||
Page custom InstallTypesPage ReadInstallTypes
|
Page custom InstallTypesPage ReadInstallTypes
|
||||||
|
|
||||||
!define MUI_PAGE_CUSTOMFUNCTION_PRE AbortFunction
|
!define MUI_PAGE_CUSTOMFUNCTION_PRE PageDirectoryPre
|
||||||
!insertmacro MUI_PAGE_DIRECTORY
|
!insertmacro MUI_PAGE_DIRECTORY
|
||||||
|
|
||||||
;Start Menu Folder Page Configuration
|
;Start Menu Folder Page Configuration
|
||||||
!define MUI_STARTMENUPAGE_REGISTRY_ROOT "HKLM"
|
!define MUI_STARTMENUPAGE_REGISTRY_ROOT "HKLM"
|
||||||
!define MUI_STARTMENUPAGE_REGISTRY_KEY "Software\@CPACK_PACKAGE_VENDOR@\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@"
|
!define MUI_STARTMENUPAGE_REGISTRY_KEY "Software\@CPACK_PACKAGE_VENDOR@\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@"
|
||||||
!define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "Start Menu Folder"
|
!define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "Start Menu Folder"
|
||||||
|
!define MUI_PAGE_CUSTOMFUNCTION_PRE PageStartMenuPre
|
||||||
!define MUI_PAGE_CUSTOMFUNCTION_PRE AbortFunction
|
|
||||||
!insertmacro MUI_PAGE_STARTMENU Application $STARTMENU_FOLDER
|
!insertmacro MUI_PAGE_STARTMENU Application $STARTMENU_FOLDER
|
||||||
|
|
||||||
!define MUI_PAGE_CUSTOMFUNCTION_PRE AbortFunction
|
!define MUI_PAGE_CUSTOMFUNCTION_PRE PageComponentsPre
|
||||||
@CPACK_NSIS_PAGE_COMPONENTS@
|
@CPACK_NSIS_PAGE_COMPONENTS@
|
||||||
|
|
||||||
|
; the MUI_PAGE_CUSTOMFUNCTION_PRE shouldn't be defined here
|
||||||
|
; which can happen for a component-less (like client only) install
|
||||||
|
!ifdef MUI_PAGE_CUSTOMFUNCTION_PRE
|
||||||
|
!undef MUI_PAGE_CUSTOMFUNCTION_PRE
|
||||||
|
!endif
|
||||||
|
|
||||||
Page custom PostInstallOptionsPage ReadPostInstallOptions
|
Page custom PostInstallOptionsPage ReadPostInstallOptions
|
||||||
|
|
||||||
|
!define MUI_PAGE_CUSTOMFUNCTION_PRE PageInstallFilesPre
|
||||||
!insertmacro MUI_PAGE_INSTFILES
|
!insertmacro MUI_PAGE_INSTFILES
|
||||||
|
|
||||||
!insertmacro MUI_UNPAGE_CONFIRM
|
!insertmacro MUI_UNPAGE_CONFIRM
|
||||||
|
@ -452,8 +534,40 @@ Var CopyFromProductionCheckbox
|
||||||
Var ExpressInstallRadioButton
|
Var ExpressInstallRadioButton
|
||||||
Var CustomInstallRadioButton
|
Var CustomInstallRadioButton
|
||||||
Var InstallTypeDialog
|
Var InstallTypeDialog
|
||||||
Var Express
|
|
||||||
Var CustomInstallTemporaryState
|
Var CustomInstallTemporaryState
|
||||||
|
Var Express
|
||||||
|
|
||||||
|
!macro MaybeSkipPage
|
||||||
|
; Check if Express is set, if so, abort the post install options page
|
||||||
|
${If} $Express == "1"
|
||||||
|
Abort
|
||||||
|
${EndIf}
|
||||||
|
!macroend
|
||||||
|
|
||||||
|
Function OnUserAbort
|
||||||
|
!insertmacro GoogleAnalytics "Installer" "Abort" "User Abort" ""
|
||||||
|
FunctionEnd
|
||||||
|
Function PageWelcomePre
|
||||||
|
!insertmacro GoogleAnalytics "Installer" "Welcome" "" ""
|
||||||
|
FunctionEnd
|
||||||
|
Function PageLicensePre
|
||||||
|
!insertmacro GoogleAnalytics "Installer" "License" "" ""
|
||||||
|
FunctionEnd
|
||||||
|
Function PageDirectoryPre
|
||||||
|
!insertmacro MaybeSkipPage
|
||||||
|
!insertmacro GoogleAnalytics "Installer" "Directory" "" ""
|
||||||
|
FunctionEnd
|
||||||
|
Function PageStartMenuPre
|
||||||
|
!insertmacro MaybeSkipPage
|
||||||
|
!insertmacro GoogleAnalytics "Installer" "StartMenu" "" ""
|
||||||
|
FunctionEnd
|
||||||
|
Function PageComponentsPre
|
||||||
|
!insertmacro MaybeSkipPage
|
||||||
|
!insertmacro GoogleAnalytics "Installer" "Components" "" ""
|
||||||
|
FunctionEnd
|
||||||
|
Function PageInstallFilesPre
|
||||||
|
!insertmacro GoogleAnalytics "Installer" "Install" "" ""
|
||||||
|
FunctionEnd
|
||||||
|
|
||||||
!macro SetInstallOption Checkbox OptionName Default
|
!macro SetInstallOption Checkbox OptionName Default
|
||||||
; reads the value for the given install option to the registry
|
; reads the value for the given install option to the registry
|
||||||
|
@ -472,6 +586,8 @@ Var CustomInstallTemporaryState
|
||||||
!macroend
|
!macroend
|
||||||
|
|
||||||
Function InstallTypesPage
|
Function InstallTypesPage
|
||||||
|
!insertmacro GoogleAnalytics "Installer" "Install Types" "" ""
|
||||||
|
|
||||||
!insertmacro MUI_HEADER_TEXT "Choose Installation Type" "Express or Custom Install"
|
!insertmacro MUI_HEADER_TEXT "Choose Installation Type" "Express or Custom Install"
|
||||||
|
|
||||||
nsDialogs::Create 1018
|
nsDialogs::Create 1018
|
||||||
|
@ -502,9 +618,10 @@ Function InstallTypesPage
|
||||||
|
|
||||||
${If} $CustomInstallTemporaryState == ${BST_UNCHECKED}
|
${If} $CustomInstallTemporaryState == ${BST_UNCHECKED}
|
||||||
${NSD_Check} $ExpressInstallRadioButton
|
${NSD_Check} $ExpressInstallRadioButton
|
||||||
${EndIf}
|
|
||||||
|
|
||||||
Call ChangeExpressLabel
|
Call ChangeExpressLabel
|
||||||
|
${Else}
|
||||||
|
Call ChangeCustomLabel
|
||||||
|
${EndIf}
|
||||||
|
|
||||||
nsDialogs::Show
|
nsDialogs::Show
|
||||||
FunctionEnd
|
FunctionEnd
|
||||||
|
@ -523,14 +640,10 @@ Function ChangeCustomLabel
|
||||||
Pop $R1
|
Pop $R1
|
||||||
FunctionEnd
|
FunctionEnd
|
||||||
|
|
||||||
Function AbortFunction
|
|
||||||
; Check if Express is set, if so, abort the post install options page
|
|
||||||
StrCmp $Express "1" 0 end
|
|
||||||
Abort
|
|
||||||
end:
|
|
||||||
FunctionEnd
|
|
||||||
|
|
||||||
Function PostInstallOptionsPage
|
Function PostInstallOptionsPage
|
||||||
|
!insertmacro MaybeSkipPage
|
||||||
|
!insertmacro GoogleAnalytics "Installer" "Post Install Options" "" ""
|
||||||
|
|
||||||
!insertmacro MUI_HEADER_TEXT "Setup Options" ""
|
!insertmacro MUI_HEADER_TEXT "Setup Options" ""
|
||||||
|
|
||||||
nsDialogs::Create 1018
|
nsDialogs::Create 1018
|
||||||
|
@ -540,15 +653,10 @@ Function PostInstallOptionsPage
|
||||||
Abort
|
Abort
|
||||||
${EndIf}
|
${EndIf}
|
||||||
|
|
||||||
; Check if Express is set, if so, abort the post install options page
|
|
||||||
StrCmp $Express "1" 0 end
|
|
||||||
Abort
|
|
||||||
end:
|
|
||||||
|
|
||||||
StrCpy $CurrentOffset 0
|
StrCpy $CurrentOffset 0
|
||||||
StrCpy $OffsetUnits u
|
StrCpy $OffsetUnits u
|
||||||
|
|
||||||
${If} ${SectionIsSelected} ${@CLIENT_COMPONENT_NAME@}
|
${If} @CLIENT_COMPONENT_CONDITIONAL@
|
||||||
${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Create a desktop shortcut for @INTERFACE_HF_SHORTCUT_NAME@"
|
${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Create a desktop shortcut for @INTERFACE_HF_SHORTCUT_NAME@"
|
||||||
Pop $DesktopClientCheckbox
|
Pop $DesktopClientCheckbox
|
||||||
IntOp $CurrentOffset $CurrentOffset + 15
|
IntOp $CurrentOffset $CurrentOffset + 15
|
||||||
|
@ -557,7 +665,7 @@ Function PostInstallOptionsPage
|
||||||
!insertmacro SetInstallOption $DesktopClientCheckbox @CLIENT_DESKTOP_SHORTCUT_REG_KEY@ ${BST_CHECKED}
|
!insertmacro SetInstallOption $DesktopClientCheckbox @CLIENT_DESKTOP_SHORTCUT_REG_KEY@ ${BST_CHECKED}
|
||||||
${EndIf}
|
${EndIf}
|
||||||
|
|
||||||
${If} ${SectionIsSelected} ${@SERVER_COMPONENT_NAME@}
|
${If} @SERVER_COMPONENT_CONDITIONAL@
|
||||||
${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Create a desktop shortcut for @CONSOLE_HF_SHORTCUT_NAME@"
|
${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Create a desktop shortcut for @CONSOLE_HF_SHORTCUT_NAME@"
|
||||||
Pop $DesktopServerCheckbox
|
Pop $DesktopServerCheckbox
|
||||||
IntOp $CurrentOffset $CurrentOffset + 15
|
IntOp $CurrentOffset $CurrentOffset + 15
|
||||||
|
@ -566,7 +674,7 @@ Function PostInstallOptionsPage
|
||||||
!insertmacro SetInstallOption $DesktopServerCheckbox @CONSOLE_DESKTOP_SHORTCUT_REG_KEY@ ${BST_UNCHECKED}
|
!insertmacro SetInstallOption $DesktopServerCheckbox @CONSOLE_DESKTOP_SHORTCUT_REG_KEY@ ${BST_UNCHECKED}
|
||||||
${EndIf}
|
${EndIf}
|
||||||
|
|
||||||
${If} ${SectionIsSelected} ${@SERVER_COMPONENT_NAME@}
|
${If} @SERVER_COMPONENT_CONDITIONAL@
|
||||||
${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Launch @CONSOLE_HF_SHORTCUT_NAME@ after install"
|
${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Launch @CONSOLE_HF_SHORTCUT_NAME@ after install"
|
||||||
Pop $LaunchServerNowCheckbox
|
Pop $LaunchServerNowCheckbox
|
||||||
|
|
||||||
|
@ -580,7 +688,7 @@ Function PostInstallOptionsPage
|
||||||
IntOp $CurrentOffset $CurrentOffset + 15
|
IntOp $CurrentOffset $CurrentOffset + 15
|
||||||
${EndIf}
|
${EndIf}
|
||||||
|
|
||||||
${If} ${SectionIsSelected} ${@CLIENT_COMPONENT_NAME@}
|
${If} @CLIENT_COMPONENT_CONDITIONAL@
|
||||||
${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Launch @INTERFACE_HF_SHORTCUT_NAME@ after install"
|
${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Launch @INTERFACE_HF_SHORTCUT_NAME@ after install"
|
||||||
Pop $LaunchClientNowCheckbox
|
Pop $LaunchClientNowCheckbox
|
||||||
IntOp $CurrentOffset $CurrentOffset + 30
|
IntOp $CurrentOffset $CurrentOffset + 30
|
||||||
|
@ -593,7 +701,7 @@ Function PostInstallOptionsPage
|
||||||
${EndIf}
|
${EndIf}
|
||||||
${EndIf}
|
${EndIf}
|
||||||
|
|
||||||
${If} ${SectionIsSelected} ${@SERVER_COMPONENT_NAME@}
|
${If} @SERVER_COMPONENT_CONDITIONAL@
|
||||||
${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Launch @CONSOLE_HF_SHORTCUT_NAME@ on startup"
|
${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Launch @CONSOLE_HF_SHORTCUT_NAME@ on startup"
|
||||||
Pop $ServerStartupCheckbox
|
Pop $ServerStartupCheckbox
|
||||||
IntOp $CurrentOffset $CurrentOffset + 15
|
IntOp $CurrentOffset $CurrentOffset + 15
|
||||||
|
@ -602,7 +710,7 @@ Function PostInstallOptionsPage
|
||||||
!insertmacro SetInstallOption $ServerStartupCheckbox @CONSOLE_STARTUP_REG_KEY@ ${BST_CHECKED}
|
!insertmacro SetInstallOption $ServerStartupCheckbox @CONSOLE_STARTUP_REG_KEY@ ${BST_CHECKED}
|
||||||
${EndIf}
|
${EndIf}
|
||||||
|
|
||||||
${If} ${SectionIsSelected} ${@CLIENT_COMPONENT_NAME@}
|
${If} @SERVER_COMPONENT_CONDITIONAL@
|
||||||
${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Perform a clean install (Delete older settings and content)"
|
${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Perform a clean install (Delete older settings and content)"
|
||||||
Pop $CleanInstallCheckbox
|
Pop $CleanInstallCheckbox
|
||||||
IntOp $CurrentOffset $CurrentOffset + 15
|
IntOp $CurrentOffset $CurrentOffset + 15
|
||||||
|
@ -610,11 +718,11 @@ Function PostInstallOptionsPage
|
||||||
|
|
||||||
${If} @PR_BUILD@ == 1
|
${If} @PR_BUILD@ == 1
|
||||||
; a PR build defaults all install options expect LaunchServerNowCheckbox, LaunchClientNowCheckbox and the settings copy to unchecked
|
; a PR build defaults all install options expect LaunchServerNowCheckbox, LaunchClientNowCheckbox and the settings copy to unchecked
|
||||||
${If} ${SectionIsSelected} ${@CLIENT_COMPONENT_NAME@}
|
${If} @CLIENT_COMPONENT_CONDITIONAL@
|
||||||
${NSD_SetState} $DesktopClientCheckbox ${BST_UNCHECKED}
|
${NSD_SetState} $DesktopClientCheckbox ${BST_UNCHECKED}
|
||||||
${EndIf}
|
${EndIf}
|
||||||
|
|
||||||
${If} ${SectionIsSelected} ${@SERVER_COMPONENT_NAME@}
|
${If} @SERVER_COMPONENT_CONDITIONAL@
|
||||||
${NSD_SetState} $DesktopServerCheckbox ${BST_UNCHECKED}
|
${NSD_SetState} $DesktopServerCheckbox ${BST_UNCHECKED}
|
||||||
${NSD_SetState} $ServerStartupCheckbox ${BST_UNCHECKED}
|
${NSD_SetState} $ServerStartupCheckbox ${BST_UNCHECKED}
|
||||||
${EndIf}
|
${EndIf}
|
||||||
|
@ -673,12 +781,12 @@ Function ReadInstallTypes
|
||||||
FunctionEnd
|
FunctionEnd
|
||||||
|
|
||||||
Function ReadPostInstallOptions
|
Function ReadPostInstallOptions
|
||||||
${If} ${SectionIsSelected} ${@CLIENT_COMPONENT_NAME@}
|
${If} @CLIENT_COMPONENT_CONDITIONAL@
|
||||||
; check if the user asked for a desktop shortcut to High Fidelity
|
; check if the user asked for a desktop shortcut to High Fidelity
|
||||||
${NSD_GetState} $DesktopClientCheckbox $DesktopClientState
|
${NSD_GetState} $DesktopClientCheckbox $DesktopClientState
|
||||||
${EndIf}
|
${EndIf}
|
||||||
|
|
||||||
${If} ${SectionIsSelected} ${@SERVER_COMPONENT_NAME@}
|
${If} @SERVER_COMPONENT_CONDITIONAL@
|
||||||
; check if the user asked for a desktop shortcut to Sandbox
|
; check if the user asked for a desktop shortcut to Sandbox
|
||||||
${NSD_GetState} $DesktopServerCheckbox $DesktopServerState
|
${NSD_GetState} $DesktopServerCheckbox $DesktopServerState
|
||||||
|
|
||||||
|
@ -691,24 +799,24 @@ Function ReadPostInstallOptions
|
||||||
${NSD_GetState} $CopyFromProductionCheckbox $CopyFromProductionState
|
${NSD_GetState} $CopyFromProductionCheckbox $CopyFromProductionState
|
||||||
${EndIf}
|
${EndIf}
|
||||||
|
|
||||||
${If} ${SectionIsSelected} ${@SERVER_COMPONENT_NAME@}
|
${If} @SERVER_COMPONENT_CONDITIONAL@
|
||||||
; check if we need to launch the server post-install
|
; check if we need to launch the server post-install
|
||||||
${NSD_GetState} $LaunchServerNowCheckbox $LaunchServerNowState
|
${NSD_GetState} $LaunchServerNowCheckbox $LaunchServerNowState
|
||||||
${EndIf}
|
${EndIf}
|
||||||
|
|
||||||
${If} ${SectionIsSelected} ${@CLIENT_COMPONENT_NAME@}
|
${If} @CLIENT_COMPONENT_CONDITIONAL@
|
||||||
; check if we need to launch the client post-install
|
; check if we need to launch the client post-install
|
||||||
${NSD_GetState} $LaunchClientNowCheckbox $LaunchClientNowState
|
${NSD_GetState} $LaunchClientNowCheckbox $LaunchClientNowState
|
||||||
${EndIf}
|
${EndIf}
|
||||||
|
|
||||||
${If} ${SectionIsSelected} ${@CLIENT_COMPONENT_NAME@}
|
${If} @CLIENT_COMPONENT_CONDITIONAL@
|
||||||
; check if the user asked for a clean install
|
; check if the user asked for a clean install
|
||||||
${NSD_GetState} $CleanInstallCheckbox $CleanInstallState
|
${NSD_GetState} $CleanInstallCheckbox $CleanInstallState
|
||||||
${EndIf}
|
${EndIf}
|
||||||
FunctionEnd
|
FunctionEnd
|
||||||
|
|
||||||
Function HandlePostInstallOptions
|
Function HandlePostInstallOptions
|
||||||
${If} ${SectionIsSelected} ${@CLIENT_COMPONENT_NAME@}
|
${If} @CLIENT_COMPONENT_CONDITIONAL@
|
||||||
; check if the user asked for a desktop shortcut to High Fidelity
|
; check if the user asked for a desktop shortcut to High Fidelity
|
||||||
${If} $DesktopClientState == ${BST_CHECKED}
|
${If} $DesktopClientState == ${BST_CHECKED}
|
||||||
CreateShortCut "$DESKTOP\@INTERFACE_HF_SHORTCUT_NAME@.lnk" "$INSTDIR\@INTERFACE_WIN_EXEC_NAME@"
|
CreateShortCut "$DESKTOP\@INTERFACE_HF_SHORTCUT_NAME@.lnk" "$INSTDIR\@INTERFACE_WIN_EXEC_NAME@"
|
||||||
|
@ -719,7 +827,7 @@ Function HandlePostInstallOptions
|
||||||
|
|
||||||
${EndIf}
|
${EndIf}
|
||||||
|
|
||||||
${If} ${SectionIsSelected} ${@SERVER_COMPONENT_NAME@}
|
${If} @SERVER_COMPONENT_CONDITIONAL@
|
||||||
; check if the user asked for a desktop shortcut to Sandbox
|
; check if the user asked for a desktop shortcut to Sandbox
|
||||||
${If} $DesktopServerState == ${BST_CHECKED}
|
${If} $DesktopServerState == ${BST_CHECKED}
|
||||||
CreateShortCut "$DESKTOP\@CONSOLE_HF_SHORTCUT_NAME@.lnk" "$INSTDIR\@CONSOLE_INSTALL_SUBDIR@\@CONSOLE_WIN_EXEC_NAME@"
|
CreateShortCut "$DESKTOP\@CONSOLE_HF_SHORTCUT_NAME@.lnk" "$INSTDIR\@CONSOLE_INSTALL_SUBDIR@\@CONSOLE_WIN_EXEC_NAME@"
|
||||||
|
@ -748,7 +856,7 @@ Function HandlePostInstallOptions
|
||||||
${EndIf}
|
${EndIf}
|
||||||
${EndIf}
|
${EndIf}
|
||||||
|
|
||||||
${If} ${SectionIsSelected} ${@CLIENT_COMPONENT_NAME@}
|
${If} @CLIENT_COMPONENT_CONDITIONAL@
|
||||||
; check if the user asked for a clean install
|
; check if the user asked for a clean install
|
||||||
${If} $CleanInstallState == ${BST_CHECKED}
|
${If} $CleanInstallState == ${BST_CHECKED}
|
||||||
SetShellVarContext current
|
SetShellVarContext current
|
||||||
|
@ -785,7 +893,8 @@ Function HandlePostInstallOptions
|
||||||
${EndIf}
|
${EndIf}
|
||||||
${EndIf}
|
${EndIf}
|
||||||
|
|
||||||
${If} $LaunchServerNowState == ${BST_CHECKED}
|
${If} @SERVER_COMPONENT_CONDITIONAL@
|
||||||
|
${AndIf} $LaunchServerNowState == ${BST_CHECKED}
|
||||||
!insertmacro WriteInstallOption @SERVER_LAUNCH_NOW_REG_KEY@ YES
|
!insertmacro WriteInstallOption @SERVER_LAUNCH_NOW_REG_KEY@ YES
|
||||||
|
|
||||||
; both launches use the explorer trick in case the user has elevated permissions for the installer
|
; both launches use the explorer trick in case the user has elevated permissions for the installer
|
||||||
|
@ -799,7 +908,7 @@ Function HandlePostInstallOptions
|
||||||
Exec '"$WINDIR\explorer.exe" "$INSTDIR\@CONSOLE_INSTALL_SUBDIR@\@CONSOLE_WIN_EXEC_NAME@"'
|
Exec '"$WINDIR\explorer.exe" "$INSTDIR\@CONSOLE_INSTALL_SUBDIR@\@CONSOLE_WIN_EXEC_NAME@"'
|
||||||
${EndIf}
|
${EndIf}
|
||||||
|
|
||||||
${Else}
|
${ElseIf} @CLIENT_COMPONENT_CONDITIONAL@
|
||||||
!insertmacro WriteInstallOption @SERVER_LAUNCH_NOW_REG_KEY@ NO
|
!insertmacro WriteInstallOption @SERVER_LAUNCH_NOW_REG_KEY@ NO
|
||||||
|
|
||||||
; launch uses the explorer trick in case the user has elevated permissions for the installer
|
; launch uses the explorer trick in case the user has elevated permissions for the installer
|
||||||
|
@ -837,9 +946,6 @@ Section "-Core installation"
|
||||||
Delete "$INSTDIR\ui_resources_200_percent.pak"
|
Delete "$INSTDIR\ui_resources_200_percent.pak"
|
||||||
Delete "$INSTDIR\vccorlib120.dll"
|
Delete "$INSTDIR\vccorlib120.dll"
|
||||||
Delete "$INSTDIR\version"
|
Delete "$INSTDIR\version"
|
||||||
Delete "$INSTDIR\msvcr140.dll"
|
|
||||||
Delete "$INSTDIR\msvcp140.dll"
|
|
||||||
Delete "$INSTDIR\vcruntime140.dll"
|
|
||||||
Delete "$INSTDIR\xinput1_3.dll"
|
Delete "$INSTDIR\xinput1_3.dll"
|
||||||
|
|
||||||
; Delete old desktop shortcuts before they were renamed during Sandbox rename
|
; Delete old desktop shortcuts before they were renamed during Sandbox rename
|
||||||
|
@ -858,11 +964,8 @@ Section "-Core installation"
|
||||||
; Rename the incorrectly cased Raleway font
|
; Rename the incorrectly cased Raleway font
|
||||||
Rename "$INSTDIR\resources\qml\styles-uit\RalewaySemibold.qml" "$INSTDIR\resources\qml\styles-uit\RalewaySemiBold.qml"
|
Rename "$INSTDIR\resources\qml\styles-uit\RalewaySemibold.qml" "$INSTDIR\resources\qml\styles-uit\RalewaySemiBold.qml"
|
||||||
|
|
||||||
ExecWait "$INSTDIR\vcredist_x64.exe /install /q /norestart"
|
|
||||||
|
|
||||||
; Remove the Old Interface directory and vcredist_x64.exe (from installs prior to Server Console)
|
; Remove the Old Interface directory and vcredist_x64.exe (from installs prior to Server Console)
|
||||||
RMDir /r "$INSTDIR\Interface"
|
RMDir /r "$INSTDIR\Interface"
|
||||||
Delete "$INSTDIR\vcredist_x64.exe"
|
|
||||||
|
|
||||||
;Use the entire tree produced by the INSTALL target. Keep the
|
;Use the entire tree produced by the INSTALL target. Keep the
|
||||||
;list of directories here in sync with the RMDir commands below.
|
;list of directories here in sync with the RMDir commands below.
|
||||||
|
@ -931,7 +1034,7 @@ Section "-Core installation"
|
||||||
@CPACK_NSIS_CREATE_ICONS_EXTRA@
|
@CPACK_NSIS_CREATE_ICONS_EXTRA@
|
||||||
|
|
||||||
; Conditional handling for Interface specific options
|
; Conditional handling for Interface specific options
|
||||||
${If} ${SectionIsSelected} ${@CLIENT_COMPONENT_NAME@}
|
${If} @CLIENT_COMPONENT_CONDITIONAL@
|
||||||
CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\@INTERFACE_SHORTCUT_NAME@.lnk" \
|
CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\@INTERFACE_SHORTCUT_NAME@.lnk" \
|
||||||
"$INSTDIR\@INTERFACE_WIN_EXEC_NAME@"
|
"$INSTDIR\@INTERFACE_WIN_EXEC_NAME@"
|
||||||
|
|
||||||
|
@ -946,7 +1049,7 @@ Section "-Core installation"
|
||||||
${EndIf}
|
${EndIf}
|
||||||
|
|
||||||
; Conditional handling for server console shortcut
|
; Conditional handling for server console shortcut
|
||||||
${If} ${SectionIsSelected} ${@SERVER_COMPONENT_NAME@}
|
${If} @SERVER_COMPONENT_CONDITIONAL@
|
||||||
CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\@CONSOLE_SHORTCUT_NAME@.lnk" \
|
CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\@CONSOLE_SHORTCUT_NAME@.lnk" \
|
||||||
"$INSTDIR\@CONSOLE_INSTALL_SUBDIR@\@CONSOLE_WIN_EXEC_NAME@"
|
"$INSTDIR\@CONSOLE_INSTALL_SUBDIR@\@CONSOLE_WIN_EXEC_NAME@"
|
||||||
${EndIf}
|
${EndIf}
|
||||||
|
@ -965,6 +1068,7 @@ Section "-Core installation"
|
||||||
; Handle whichever post install options were set
|
; Handle whichever post install options were set
|
||||||
Call HandlePostInstallOptions
|
Call HandlePostInstallOptions
|
||||||
|
|
||||||
|
!insertmacro GoogleAnalytics "Installer" "Done" "" ""
|
||||||
SectionEnd
|
SectionEnd
|
||||||
|
|
||||||
!include nsProcess.nsh
|
!include nsProcess.nsh
|
||||||
|
@ -992,6 +1096,8 @@ SectionEnd
|
||||||
/SD IDCANCEL IDRETRY Prompt_${UniqueID} IDCANCEL 0
|
/SD IDCANCEL IDRETRY Prompt_${UniqueID} IDCANCEL 0
|
||||||
${EndIf}
|
${EndIf}
|
||||||
|
|
||||||
|
!insertmacro GoogleAnalytics "Installer" "Abort" "${displayName} Running" ""
|
||||||
|
|
||||||
; If the user decided to cancel, stop the current installer/uninstaller
|
; If the user decided to cancel, stop the current installer/uninstaller
|
||||||
Abort
|
Abort
|
||||||
|
|
||||||
|
@ -1087,8 +1193,8 @@ Function .onSelChange
|
||||||
!insertmacro SectionList MaybeSelectionChanged
|
!insertmacro SectionList MaybeSelectionChanged
|
||||||
|
|
||||||
; if neither component is selected, disable the install button
|
; if neither component is selected, disable the install button
|
||||||
${IfNot} ${SectionIsSelected} ${@CLIENT_COMPONENT_NAME@}
|
${IfNot} @CLIENT_COMPONENT_CONDITIONAL@
|
||||||
${AndIfNot} ${SectionIsSelected} ${@SERVER_COMPONENT_NAME@}
|
${AndIfNot} @SERVER_COMPONENT_CONDITIONAL@
|
||||||
GetDlgItem $0 $HWNDPARENT 1
|
GetDlgItem $0 $HWNDPARENT 1
|
||||||
EnableWindow $0 0
|
EnableWindow $0 0
|
||||||
${Else}
|
${Else}
|
||||||
|
@ -1219,6 +1325,11 @@ Function .onInit
|
||||||
Quit
|
Quit
|
||||||
!endif
|
!endif
|
||||||
|
|
||||||
|
!insertmacro InitGAClientID
|
||||||
|
!insertmacro GetCampaignName $CampaignName
|
||||||
|
|
||||||
|
!insertmacro GoogleAnalytics "Installer" "Start" "$CampaignName" ""
|
||||||
|
|
||||||
; make sure none of the installed applications are still running
|
; make sure none of the installed applications are still running
|
||||||
!insertmacro CheckForRunningApplications "installed" "Installer"
|
!insertmacro CheckForRunningApplications "installed" "Installer"
|
||||||
${nsProcess::Unload}
|
${nsProcess::Unload}
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include <QJsonArray>
|
#include <QJsonArray>
|
||||||
#include <QProcess>
|
#include <QProcess>
|
||||||
#include <QSharedMemory>
|
#include <QSharedMemory>
|
||||||
|
#include <QRegularExpression>
|
||||||
#include <QStandardPaths>
|
#include <QStandardPaths>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QUrlQuery>
|
#include <QUrlQuery>
|
||||||
|
@ -727,7 +728,7 @@ void DomainServer::setupNodeListAndAssignments() {
|
||||||
packetReceiver.registerListener(PacketType::OctreeDataPersist, this, "processOctreeDataPersistMessage");
|
packetReceiver.registerListener(PacketType::OctreeDataPersist, this, "processOctreeDataPersistMessage");
|
||||||
|
|
||||||
packetReceiver.registerListener(PacketType::OctreeFileReplacement, this, "handleOctreeFileReplacementRequest");
|
packetReceiver.registerListener(PacketType::OctreeFileReplacement, this, "handleOctreeFileReplacementRequest");
|
||||||
packetReceiver.registerListener(PacketType::OctreeFileReplacementFromUrl, this, "handleOctreeFileReplacementFromURLRequest");
|
packetReceiver.registerListener(PacketType::DomainContentReplacementFromUrl, this, "handleDomainContentReplacementFromURLRequest");
|
||||||
|
|
||||||
// set a custom packetVersionMatch as the verify packet operator for the udt::Socket
|
// set a custom packetVersionMatch as the verify packet operator for the udt::Socket
|
||||||
nodeList->setPacketFilterOperator(&DomainServer::isPacketVerified);
|
nodeList->setPacketFilterOperator(&DomainServer::isPacketVerified);
|
||||||
|
@ -736,7 +737,6 @@ void DomainServer::setupNodeListAndAssignments() {
|
||||||
auto assetClient = DependencyManager::set<AssetClient>();
|
auto assetClient = DependencyManager::set<AssetClient>();
|
||||||
assetClient->moveToThread(&_assetClientThread);
|
assetClient->moveToThread(&_assetClientThread);
|
||||||
_assetClientThread.start();
|
_assetClientThread.start();
|
||||||
|
|
||||||
// add whatever static assignments that have been parsed to the queue
|
// add whatever static assignments that have been parsed to the queue
|
||||||
addStaticAssignmentsToQueue();
|
addStaticAssignmentsToQueue();
|
||||||
}
|
}
|
||||||
|
@ -2136,7 +2136,7 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url
|
||||||
} else if (url.path().startsWith(URI_API_BACKUPS_ID)) {
|
} else if (url.path().startsWith(URI_API_BACKUPS_ID)) {
|
||||||
auto id = url.path().mid(QString(URI_API_BACKUPS_ID).length());
|
auto id = url.path().mid(QString(URI_API_BACKUPS_ID).length());
|
||||||
auto deferred = makePromise("consolidateBackup");
|
auto deferred = makePromise("consolidateBackup");
|
||||||
deferred->then([connectionPtr, JSON_MIME_TYPE](QString error, QVariantMap result) {
|
deferred->then([connectionPtr, JSON_MIME_TYPE, id](QString error, QVariantMap result) {
|
||||||
if (!connectionPtr) {
|
if (!connectionPtr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -2147,7 +2147,14 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url
|
||||||
auto path = result["backupFilePath"].toString();
|
auto path = result["backupFilePath"].toString();
|
||||||
auto file { std::unique_ptr<QFile>(new QFile(path)) };
|
auto file { std::unique_ptr<QFile>(new QFile(path)) };
|
||||||
if (file->open(QIODevice::ReadOnly)) {
|
if (file->open(QIODevice::ReadOnly)) {
|
||||||
connectionPtr->respond(HTTPConnection::StatusCode200, std::move(file));
|
constexpr const char* CONTENT_TYPE_ZIP = "application/zip";
|
||||||
|
|
||||||
|
auto downloadedFilename = id;
|
||||||
|
downloadedFilename.replace(QRegularExpression(".zip$"), ".content.zip");
|
||||||
|
auto contentDisposition = "attachment; filename=\"" + downloadedFilename + "\"";
|
||||||
|
connectionPtr->respond(HTTPConnection::StatusCode200, std::move(file), CONTENT_TYPE_ZIP, {
|
||||||
|
{ "Content-Disposition", contentDisposition.toUtf8() }
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
qCritical(domain_server) << "Unable to load consolidated backup at:" << path << result;
|
qCritical(domain_server) << "Unable to load consolidated backup at:" << path << result;
|
||||||
connectionPtr->respond(HTTPConnection::StatusCode500, "Error opening backup");
|
connectionPtr->respond(HTTPConnection::StatusCode500, "Error opening backup");
|
||||||
|
@ -3429,13 +3436,10 @@ void DomainServer::handleOctreeFileReplacement(QByteArray octreeFile) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DomainServer::handleOctreeFileReplacementFromURLRequest(QSharedPointer<ReceivedMessage> message) {
|
void DomainServer::handleDomainContentReplacementFromURLRequest(QSharedPointer<ReceivedMessage> message) {
|
||||||
qInfo() << "Received request to replace content from a url";
|
qInfo() << "Received request to replace content from a url";
|
||||||
auto node = DependencyManager::get<LimitedNodeList>()->findNodeWithAddr(message->getSenderSockAddr());
|
auto node = DependencyManager::get<LimitedNodeList>()->findNodeWithAddr(message->getSenderSockAddr());
|
||||||
if (node) {
|
if (node && node->getCanReplaceContent()) {
|
||||||
qDebug() << "Found node: " << node->getCanReplaceContent();
|
|
||||||
}
|
|
||||||
if (node->getCanReplaceContent()) {
|
|
||||||
// Convert message data into our URL
|
// Convert message data into our URL
|
||||||
QString url(message->getMessage());
|
QString url(message->getMessage());
|
||||||
QUrl modelsURL = QUrl(url, QUrl::StrictMode);
|
QUrl modelsURL = QUrl(url, QUrl::StrictMode);
|
||||||
|
@ -3448,7 +3452,12 @@ void DomainServer::handleOctreeFileReplacementFromURLRequest(QSharedPointer<Rece
|
||||||
connect(reply, &QNetworkReply::finished, [this, reply, modelsURL]() {
|
connect(reply, &QNetworkReply::finished, [this, reply, modelsURL]() {
|
||||||
QNetworkReply::NetworkError networkError = reply->error();
|
QNetworkReply::NetworkError networkError = reply->error();
|
||||||
if (networkError == QNetworkReply::NoError) {
|
if (networkError == QNetworkReply::NoError) {
|
||||||
|
if (modelsURL.fileName().endsWith(".json.gz")) {
|
||||||
handleOctreeFileReplacement(reply->readAll());
|
handleOctreeFileReplacement(reply->readAll());
|
||||||
|
} else if (modelsURL.fileName().endsWith(".zip")) {
|
||||||
|
auto deferred = makePromise("recoverFromUploadedBackup");
|
||||||
|
_contentManager->recoverFromUploadedBackup(deferred, reply->readAll());
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
qDebug() << "Error downloading JSON from specified file: " << modelsURL;
|
qDebug() << "Error downloading JSON from specified file: " << modelsURL;
|
||||||
}
|
}
|
||||||
|
@ -3456,9 +3465,6 @@ void DomainServer::handleOctreeFileReplacementFromURLRequest(QSharedPointer<Rece
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void DomainServer::handleOctreeFileReplacementRequest(QSharedPointer<ReceivedMessage> message) {
|
void DomainServer::handleOctreeFileReplacementRequest(QSharedPointer<ReceivedMessage> message) {
|
||||||
auto node = DependencyManager::get<NodeList>()->nodeWithUUID(message->getSourceID());
|
auto node = DependencyManager::get<NodeList>()->nodeWithUUID(message->getSourceID());
|
||||||
if (node->getCanReplaceContent()) {
|
if (node->getCanReplaceContent()) {
|
||||||
|
|
|
@ -91,7 +91,7 @@ private slots:
|
||||||
void processICEServerHeartbeatDenialPacket(QSharedPointer<ReceivedMessage> message);
|
void processICEServerHeartbeatDenialPacket(QSharedPointer<ReceivedMessage> message);
|
||||||
void processICEServerHeartbeatACK(QSharedPointer<ReceivedMessage> message);
|
void processICEServerHeartbeatACK(QSharedPointer<ReceivedMessage> message);
|
||||||
|
|
||||||
void handleOctreeFileReplacementFromURLRequest(QSharedPointer<ReceivedMessage> message);
|
void handleDomainContentReplacementFromURLRequest(QSharedPointer<ReceivedMessage> message);
|
||||||
void handleOctreeFileReplacementRequest(QSharedPointer<ReceivedMessage> message);
|
void handleOctreeFileReplacementRequest(QSharedPointer<ReceivedMessage> message);
|
||||||
void handleOctreeFileReplacement(QByteArray octreeFile);
|
void handleOctreeFileReplacement(QByteArray octreeFile);
|
||||||
|
|
||||||
|
|
|
@ -191,7 +191,11 @@ add_dependencies(${TARGET_NAME} resources)
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
# These are external plugins, but we need to do the 'add dependency' here so that their
|
# These are external plugins, but we need to do the 'add dependency' here so that their
|
||||||
# binary directories get added to the fixup path
|
# binary directories get added to the fixup path
|
||||||
|
|
||||||
|
if (USE_SIXENSE)
|
||||||
add_dependency_external_projects(sixense)
|
add_dependency_external_projects(sixense)
|
||||||
|
endif ()
|
||||||
|
|
||||||
add_dependency_external_projects(sdl2)
|
add_dependency_external_projects(sdl2)
|
||||||
add_dependency_external_projects(OpenVR)
|
add_dependency_external_projects(OpenVR)
|
||||||
add_dependency_external_projects(neuron)
|
add_dependency_external_projects(neuron)
|
||||||
|
@ -199,12 +203,6 @@ if (WIN32)
|
||||||
add_dependency_external_projects(steamworks)
|
add_dependency_external_projects(steamworks)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# include OPENSSL
|
|
||||||
include_directories(SYSTEM "${OPENSSL_INCLUDE_DIR}")
|
|
||||||
|
|
||||||
# append OpenSSL to our list of libraries to link
|
|
||||||
target_link_libraries(${TARGET_NAME} ${OPENSSL_LIBRARIES})
|
|
||||||
|
|
||||||
# disable /OPT:REF and /OPT:ICF for the Debug builds
|
# disable /OPT:REF and /OPT:ICF for the Debug builds
|
||||||
# This will prevent the following linker warnings
|
# This will prevent the following linker warnings
|
||||||
# LINK : warning LNK4075: ignoring '/INCREMENTAL' due to '/OPT:ICF' specification
|
# LINK : warning LNK4075: ignoring '/INCREMENTAL' due to '/OPT:ICF' specification
|
||||||
|
@ -228,6 +226,9 @@ link_hifi_libraries(
|
||||||
# include the binary directory of render-utils for shader includes
|
# include the binary directory of render-utils for shader includes
|
||||||
target_include_directories(${TARGET_NAME} PRIVATE "${CMAKE_BINARY_DIR}/libraries/render-utils")
|
target_include_directories(${TARGET_NAME} PRIVATE "${CMAKE_BINARY_DIR}/libraries/render-utils")
|
||||||
|
|
||||||
|
# include OpenSSL
|
||||||
|
target_openssl()
|
||||||
|
|
||||||
target_bullet()
|
target_bullet()
|
||||||
target_opengl()
|
target_opengl()
|
||||||
add_crashpad()
|
add_crashpad()
|
||||||
|
@ -389,3 +390,6 @@ endif()
|
||||||
add_dependency_external_projects(GifCreator)
|
add_dependency_external_projects(GifCreator)
|
||||||
find_package(GifCreator REQUIRED)
|
find_package(GifCreator REQUIRED)
|
||||||
target_include_directories(${TARGET_NAME} PUBLIC ${GIFCREATOR_INCLUDE_DIRS})
|
target_include_directories(${TARGET_NAME} PUBLIC ${GIFCREATOR_INCLUDE_DIRS})
|
||||||
|
|
||||||
|
# tell CMake to exclude ui_console.h for policy CMP0071
|
||||||
|
set_property(SOURCE ui_console.h PROPERTY SKIP_AUTOMOC ON)
|
||||||
|
|
|
@ -351,6 +351,7 @@ static const QString OBJ_EXTENSION = ".obj";
|
||||||
static const QString AVA_JSON_EXTENSION = ".ava.json";
|
static const QString AVA_JSON_EXTENSION = ".ava.json";
|
||||||
static const QString WEB_VIEW_TAG = "noDownload=true";
|
static const QString WEB_VIEW_TAG = "noDownload=true";
|
||||||
static const QString ZIP_EXTENSION = ".zip";
|
static const QString ZIP_EXTENSION = ".zip";
|
||||||
|
static const QString CONTENT_ZIP_EXTENSION = ".content.zip";
|
||||||
|
|
||||||
static const float MIRROR_FULLSCREEN_DISTANCE = 0.389f;
|
static const float MIRROR_FULLSCREEN_DISTANCE = 0.389f;
|
||||||
|
|
||||||
|
@ -378,7 +379,7 @@ static const QString SYSTEM_TABLET = "com.highfidelity.interface.tablet.system";
|
||||||
|
|
||||||
static const QString DOMAIN_SPAWNING_POINT = "/0, -10, 0";
|
static const QString DOMAIN_SPAWNING_POINT = "/0, -10, 0";
|
||||||
|
|
||||||
const QHash<QString, Application::AcceptURLMethod> Application::_acceptedExtensions {
|
const std::vector<std::pair<QString, Application::AcceptURLMethod>> Application::_acceptedExtensions {
|
||||||
{ SVO_EXTENSION, &Application::importSVOFromURL },
|
{ SVO_EXTENSION, &Application::importSVOFromURL },
|
||||||
{ SVO_JSON_EXTENSION, &Application::importSVOFromURL },
|
{ SVO_JSON_EXTENSION, &Application::importSVOFromURL },
|
||||||
{ AVA_JSON_EXTENSION, &Application::askToWearAvatarAttachmentUrl },
|
{ AVA_JSON_EXTENSION, &Application::askToWearAvatarAttachmentUrl },
|
||||||
|
@ -386,6 +387,7 @@ const QHash<QString, Application::AcceptURLMethod> Application::_acceptedExtensi
|
||||||
{ JS_EXTENSION, &Application::askToLoadScript },
|
{ JS_EXTENSION, &Application::askToLoadScript },
|
||||||
{ FST_EXTENSION, &Application::askToSetAvatarUrl },
|
{ FST_EXTENSION, &Application::askToSetAvatarUrl },
|
||||||
{ JSON_GZ_EXTENSION, &Application::askToReplaceDomainContent },
|
{ JSON_GZ_EXTENSION, &Application::askToReplaceDomainContent },
|
||||||
|
{ CONTENT_ZIP_EXTENSION, &Application::askToReplaceDomainContent },
|
||||||
{ ZIP_EXTENSION, &Application::importFromZIP },
|
{ ZIP_EXTENSION, &Application::importFromZIP },
|
||||||
{ JPG_EXTENSION, &Application::importImage },
|
{ JPG_EXTENSION, &Application::importImage },
|
||||||
{ PNG_EXTENSION, &Application::importImage }
|
{ PNG_EXTENSION, &Application::importImage }
|
||||||
|
@ -2704,6 +2706,7 @@ void Application::onDesktopRootContextCreated(QQmlContext* surfaceContext) {
|
||||||
|
|
||||||
surfaceContext->setContextProperty("ApplicationCompositor", &getApplicationCompositor());
|
surfaceContext->setContextProperty("ApplicationCompositor", &getApplicationCompositor());
|
||||||
|
|
||||||
|
surfaceContext->setContextProperty("AvatarInputs", AvatarInputs::getInstance());
|
||||||
surfaceContext->setContextProperty("Selection", DependencyManager::get<SelectionScriptingInterface>().data());
|
surfaceContext->setContextProperty("Selection", DependencyManager::get<SelectionScriptingInterface>().data());
|
||||||
surfaceContext->setContextProperty("ContextOverlay", DependencyManager::get<ContextOverlayInterface>().data());
|
surfaceContext->setContextProperty("ContextOverlay", DependencyManager::get<ContextOverlayInterface>().data());
|
||||||
surfaceContext->setContextProperty("Wallet", DependencyManager::get<WalletScriptingInterface>().data());
|
surfaceContext->setContextProperty("Wallet", DependencyManager::get<WalletScriptingInterface>().data());
|
||||||
|
@ -6173,11 +6176,9 @@ bool Application::canAcceptURL(const QString& urlString) const {
|
||||||
} else if (urlString.startsWith(HIFI_URL_SCHEME)) {
|
} else if (urlString.startsWith(HIFI_URL_SCHEME)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
QHashIterator<QString, AcceptURLMethod> i(_acceptedExtensions);
|
|
||||||
QString lowerPath = url.path().toLower();
|
QString lowerPath = url.path().toLower();
|
||||||
while (i.hasNext()) {
|
for (auto& pair : _acceptedExtensions) {
|
||||||
i.next();
|
if (lowerPath.endsWith(pair.first, Qt::CaseInsensitive)) {
|
||||||
if (lowerPath.endsWith(i.key(), Qt::CaseInsensitive)) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6194,12 +6195,10 @@ bool Application::acceptURL(const QString& urlString, bool defaultUpload) {
|
||||||
}
|
}
|
||||||
|
|
||||||
QUrl url(urlString);
|
QUrl url(urlString);
|
||||||
QHashIterator<QString, AcceptURLMethod> i(_acceptedExtensions);
|
|
||||||
QString lowerPath = url.path().toLower();
|
QString lowerPath = url.path().toLower();
|
||||||
while (i.hasNext()) {
|
for (auto& pair : _acceptedExtensions) {
|
||||||
i.next();
|
if (lowerPath.endsWith(pair.first, Qt::CaseInsensitive)) {
|
||||||
if (lowerPath.endsWith(i.key(), Qt::CaseInsensitive)) {
|
AcceptURLMethod method = pair.second;
|
||||||
AcceptURLMethod method = i.value();
|
|
||||||
return (this->*method)(urlString);
|
return (this->*method)(urlString);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6386,13 +6385,11 @@ void Application::replaceDomainContent(const QString& url) {
|
||||||
QByteArray urlData(url.toUtf8());
|
QByteArray urlData(url.toUtf8());
|
||||||
auto limitedNodeList = DependencyManager::get<NodeList>();
|
auto limitedNodeList = DependencyManager::get<NodeList>();
|
||||||
const auto& domainHandler = limitedNodeList->getDomainHandler();
|
const auto& domainHandler = limitedNodeList->getDomainHandler();
|
||||||
limitedNodeList->eachMatchingNode([](const SharedNodePointer& node) {
|
|
||||||
return node->getType() == NodeType::EntityServer && node->getActiveSocket();
|
auto octreeFilePacket = NLPacket::create(PacketType::DomainContentReplacementFromUrl, urlData.size(), true);
|
||||||
}, [&urlData, limitedNodeList, &domainHandler](const SharedNodePointer& octreeNode) {
|
|
||||||
auto octreeFilePacket = NLPacket::create(PacketType::OctreeFileReplacementFromUrl, urlData.size(), true);
|
|
||||||
octreeFilePacket->write(urlData);
|
octreeFilePacket->write(urlData);
|
||||||
limitedNodeList->sendPacket(std::move(octreeFilePacket), domainHandler.getSockAddr());
|
limitedNodeList->sendPacket(std::move(octreeFilePacket), domainHandler.getSockAddr());
|
||||||
});
|
|
||||||
auto addressManager = DependencyManager::get<AddressManager>();
|
auto addressManager = DependencyManager::get<AddressManager>();
|
||||||
addressManager->handleLookupString(DOMAIN_SPAWNING_POINT);
|
addressManager->handleLookupString(DOMAIN_SPAWNING_POINT);
|
||||||
QString newHomeAddress = addressManager->getHost() + DOMAIN_SPAWNING_POINT;
|
QString newHomeAddress = addressManager->getHost() + DOMAIN_SPAWNING_POINT;
|
||||||
|
@ -7350,10 +7347,35 @@ bool Application::isThrottleRendering() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Application::hasFocus() const {
|
bool Application::hasFocus() const {
|
||||||
if (_displayPlugin) {
|
bool result = (QApplication::activeWindow() != nullptr);
|
||||||
return getActiveDisplayPlugin()->hasFocus();
|
#if defined(Q_OS_WIN)
|
||||||
|
// On Windows, QWidget::activateWindow() - as called in setFocus() - makes the application's taskbar icon flash but doesn't
|
||||||
|
// take user focus away from their current window. So also check whether the application is the user's current foreground
|
||||||
|
// window.
|
||||||
|
result = result && (HWND)QApplication::activeWindow()->winId() == GetForegroundWindow();
|
||||||
|
#endif
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application::setFocus() {
|
||||||
|
// Note: Windows doesn't allow a user focus to be taken away from another application. Instead, it changes the color of and
|
||||||
|
// flashes the taskbar icon.
|
||||||
|
auto window = qApp->getWindow();
|
||||||
|
window->activateWindow();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application::raise() {
|
||||||
|
auto windowState = qApp->getWindow()->windowState();
|
||||||
|
if (windowState & Qt::WindowMinimized) {
|
||||||
|
if (windowState & Qt::WindowMaximized) {
|
||||||
|
qApp->getWindow()->showMaximized();
|
||||||
|
} else if (windowState & Qt::WindowFullScreen) {
|
||||||
|
qApp->getWindow()->showFullScreen();
|
||||||
|
} else {
|
||||||
|
qApp->getWindow()->showNormal();
|
||||||
}
|
}
|
||||||
return (QApplication::activeWindow() != nullptr);
|
}
|
||||||
|
qApp->getWindow()->raise();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::setMaxOctreePacketsPerSecond(int maxOctreePPS) {
|
void Application::setMaxOctreePacketsPerSecond(int maxOctreePPS) {
|
||||||
|
|
|
@ -161,6 +161,8 @@ public:
|
||||||
QRect getRecommendedHUDRect() const;
|
QRect getRecommendedHUDRect() const;
|
||||||
glm::vec2 getDeviceSize() const;
|
glm::vec2 getDeviceSize() const;
|
||||||
bool hasFocus() const;
|
bool hasFocus() const;
|
||||||
|
void setFocus();
|
||||||
|
void raise();
|
||||||
|
|
||||||
void showCursor(const Cursor::Icon& cursor);
|
void showCursor(const Cursor::Icon& cursor);
|
||||||
|
|
||||||
|
@ -603,7 +605,7 @@ private:
|
||||||
GLCanvas* _glWidget{ nullptr };
|
GLCanvas* _glWidget{ nullptr };
|
||||||
|
|
||||||
typedef bool (Application::* AcceptURLMethod)(const QString &);
|
typedef bool (Application::* AcceptURLMethod)(const QString &);
|
||||||
static const QHash<QString, AcceptURLMethod> _acceptedExtensions;
|
static const std::vector<std::pair<QString, Application::AcceptURLMethod>> _acceptedExtensions;
|
||||||
|
|
||||||
glm::uvec2 _renderResolution;
|
glm::uvec2 _renderResolution;
|
||||||
|
|
||||||
|
|
|
@ -74,16 +74,14 @@ QScriptValue WindowScriptingInterface::hasFocus() {
|
||||||
void WindowScriptingInterface::setFocus() {
|
void WindowScriptingInterface::setFocus() {
|
||||||
// It's forbidden to call focus() from another thread.
|
// It's forbidden to call focus() from another thread.
|
||||||
qApp->postLambdaEvent([] {
|
qApp->postLambdaEvent([] {
|
||||||
auto window = qApp->getWindow();
|
qApp->setFocus();
|
||||||
window->activateWindow();
|
|
||||||
window->setFocus();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowScriptingInterface::raiseMainWindow() {
|
void WindowScriptingInterface::raiseMainWindow() {
|
||||||
// It's forbidden to call raise() from another thread.
|
// It's forbidden to call raise() from another thread.
|
||||||
qApp->postLambdaEvent([] {
|
qApp->postLambdaEvent([] {
|
||||||
qApp->getWindow()->raise();
|
qApp->raise();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -62,13 +62,14 @@ public slots:
|
||||||
QScriptValue hasFocus();
|
QScriptValue hasFocus();
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* Make the Interface window have focus.
|
* Make the Interface window have focus. On Windows, if Interface doesn't already have focus, the task bar icon flashes to
|
||||||
|
* indicate that Interface wants attention but focus isn't taken away from the application that the user is using.
|
||||||
* @function Window.setFocus
|
* @function Window.setFocus
|
||||||
*/
|
*/
|
||||||
void setFocus();
|
void setFocus();
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* Raise the Interface window if it is minimized, and give it focus.
|
* Raise the Interface window if it is minimized. If raised, the window gains focus.
|
||||||
* @function Window.raiseMainWindow
|
* @function Window.raiseMainWindow
|
||||||
*/
|
*/
|
||||||
void raiseMainWindow();
|
void raiseMainWindow();
|
||||||
|
|
|
@ -63,6 +63,19 @@ static const float OPAQUE_ALPHA_THRESHOLD = 0.99f;
|
||||||
|
|
||||||
const QString Web3DOverlay::TYPE = "web3d";
|
const QString Web3DOverlay::TYPE = "web3d";
|
||||||
const QString Web3DOverlay::QML = "Web3DOverlay.qml";
|
const QString Web3DOverlay::QML = "Web3DOverlay.qml";
|
||||||
|
|
||||||
|
static auto qmlSurfaceDeleter = [](OffscreenQmlSurface* surface) {
|
||||||
|
AbstractViewStateInterface::instance()->postLambdaEvent([surface] {
|
||||||
|
if (AbstractViewStateInterface::instance()->isAboutToQuit()) {
|
||||||
|
// WebEngineView may run other threads (wasapi), so they must be deleted for a clean shutdown
|
||||||
|
// if the application has already stopped its event loop, delete must be explicit
|
||||||
|
delete surface;
|
||||||
|
} else {
|
||||||
|
surface->deleteLater();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
Web3DOverlay::Web3DOverlay() {
|
Web3DOverlay::Web3DOverlay() {
|
||||||
_touchDevice.setCapabilities(QTouchDevice::Position);
|
_touchDevice.setCapabilities(QTouchDevice::Position);
|
||||||
_touchDevice.setType(QTouchDevice::TouchScreen);
|
_touchDevice.setType(QTouchDevice::TouchScreen);
|
||||||
|
@ -75,7 +88,8 @@ Web3DOverlay::Web3DOverlay() {
|
||||||
connect(this, &Web3DOverlay::resizeWebSurface, this, &Web3DOverlay::onResizeWebSurface);
|
connect(this, &Web3DOverlay::resizeWebSurface, this, &Web3DOverlay::onResizeWebSurface);
|
||||||
|
|
||||||
//need to be intialized before Tablet 1st open
|
//need to be intialized before Tablet 1st open
|
||||||
_webSurface = DependencyManager::get<OffscreenQmlSurfaceCache>()->acquire(_url);
|
_webSurface = DependencyManager::get<OffscreenQmlSurfaceCache>()->acquire(QML);
|
||||||
|
_cachedWebSurface = true;
|
||||||
_webSurface->getSurfaceContext()->setContextProperty("HMD", DependencyManager::get<HMDScriptingInterface>().data());
|
_webSurface->getSurfaceContext()->setContextProperty("HMD", DependencyManager::get<HMDScriptingInterface>().data());
|
||||||
_webSurface->getSurfaceContext()->setContextProperty("Account", AccountServicesScriptingInterface::getInstance()); // DEPRECATED - TO BE REMOVED
|
_webSurface->getSurfaceContext()->setContextProperty("Account", AccountServicesScriptingInterface::getInstance()); // DEPRECATED - TO BE REMOVED
|
||||||
_webSurface->getSurfaceContext()->setContextProperty("GlobalServices", AccountServicesScriptingInterface::getInstance()); // DEPRECATED - TO BE REMOVED
|
_webSurface->getSurfaceContext()->setContextProperty("GlobalServices", AccountServicesScriptingInterface::getInstance()); // DEPRECATED - TO BE REMOVED
|
||||||
|
@ -114,6 +128,7 @@ void Web3DOverlay::destroyWebSurface() {
|
||||||
if (!_webSurface) {
|
if (!_webSurface) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QQuickItem* rootItem = _webSurface->getRootItem();
|
QQuickItem* rootItem = _webSurface->getRootItem();
|
||||||
|
|
||||||
if (rootItem && rootItem->objectName() == "tabletRoot") {
|
if (rootItem && rootItem->objectName() == "tabletRoot") {
|
||||||
|
@ -135,11 +150,16 @@ void Web3DOverlay::destroyWebSurface() {
|
||||||
|
|
||||||
QObject::disconnect(this, &Web3DOverlay::scriptEventReceived, _webSurface.data(), &OffscreenQmlSurface::emitScriptEvent);
|
QObject::disconnect(this, &Web3DOverlay::scriptEventReceived, _webSurface.data(), &OffscreenQmlSurface::emitScriptEvent);
|
||||||
QObject::disconnect(_webSurface.data(), &OffscreenQmlSurface::webEventReceived, this, &Web3DOverlay::webEventReceived);
|
QObject::disconnect(_webSurface.data(), &OffscreenQmlSurface::webEventReceived, this, &Web3DOverlay::webEventReceived);
|
||||||
|
|
||||||
|
// If the web surface was fetched out of the cache, release it back into the cache
|
||||||
|
if (_cachedWebSurface) {
|
||||||
auto offscreenCache = DependencyManager::get<OffscreenQmlSurfaceCache>();
|
auto offscreenCache = DependencyManager::get<OffscreenQmlSurfaceCache>();
|
||||||
// FIXME prevents crash on shutdown, but we shoudln't have to do this check
|
// FIXME prevents crash on shutdown, but we shoudln't have to do this check
|
||||||
if (offscreenCache) {
|
if (offscreenCache) {
|
||||||
offscreenCache->release(QML, _webSurface);
|
offscreenCache->release(QML, _webSurface);
|
||||||
}
|
}
|
||||||
|
_cachedWebSurface = false;
|
||||||
|
}
|
||||||
_webSurface.reset();
|
_webSurface.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,6 +167,8 @@ void Web3DOverlay::buildWebSurface() {
|
||||||
if (_webSurface) {
|
if (_webSurface) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// FIXME the context save here is most likely unecessary since the QML surfaces now render
|
||||||
|
// off the main thread, and all GL context work is done off the main thread (I *think*)
|
||||||
gl::withSavedContext([&] {
|
gl::withSavedContext([&] {
|
||||||
// FIXME, the max FPS could be better managed by being dynamic (based on the number of current surfaces
|
// FIXME, the max FPS could be better managed by being dynamic (based on the number of current surfaces
|
||||||
// and the current rendering load)
|
// and the current rendering load)
|
||||||
|
@ -156,10 +178,13 @@ void Web3DOverlay::buildWebSurface() {
|
||||||
|
|
||||||
if (isWebContent()) {
|
if (isWebContent()) {
|
||||||
_webSurface = DependencyManager::get<OffscreenQmlSurfaceCache>()->acquire(QML);
|
_webSurface = DependencyManager::get<OffscreenQmlSurfaceCache>()->acquire(QML);
|
||||||
|
_cachedWebSurface = true;
|
||||||
_webSurface->getRootItem()->setProperty("url", _url);
|
_webSurface->getRootItem()->setProperty("url", _url);
|
||||||
_webSurface->getRootItem()->setProperty("scriptURL", _scriptURL);
|
_webSurface->getRootItem()->setProperty("scriptURL", _scriptURL);
|
||||||
} else {
|
} else {
|
||||||
_webSurface = DependencyManager::get<OffscreenQmlSurfaceCache>()->acquire(_url);
|
_webSurface = QSharedPointer<OffscreenQmlSurface>(new OffscreenQmlSurface(), qmlSurfaceDeleter);
|
||||||
|
_webSurface->load(_url);
|
||||||
|
_cachedWebSurface = false;
|
||||||
setupQmlSurface();
|
setupQmlSurface();
|
||||||
}
|
}
|
||||||
_webSurface->getSurfaceContext()->setContextProperty("globalPosition", vec3toVariant(getWorldPosition()));
|
_webSurface->getSurfaceContext()->setContextProperty("globalPosition", vec3toVariant(getWorldPosition()));
|
||||||
|
|
|
@ -88,6 +88,7 @@ private:
|
||||||
|
|
||||||
InputMode _inputMode { Touch };
|
InputMode _inputMode { Touch };
|
||||||
QSharedPointer<OffscreenQmlSurface> _webSurface;
|
QSharedPointer<OffscreenQmlSurface> _webSurface;
|
||||||
|
bool _cachedWebSurface{ false };
|
||||||
gpu::TexturePointer _texture;
|
gpu::TexturePointer _texture;
|
||||||
QString _url;
|
QString _url;
|
||||||
QString _scriptURL;
|
QString _scriptURL;
|
||||||
|
|
|
@ -21,10 +21,6 @@ glm::uvec2 NullDisplayPlugin::getRecommendedRenderSize() const {
|
||||||
return glm::uvec2(100, 100);
|
return glm::uvec2(100, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NullDisplayPlugin::hasFocus() const {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void NullDisplayPlugin::submitFrame(const gpu::FramePointer& frame) {
|
void NullDisplayPlugin::submitFrame(const gpu::FramePointer& frame) {
|
||||||
if (frame) {
|
if (frame) {
|
||||||
_gpuContext->consumeFrameUpdates(frame);
|
_gpuContext->consumeFrameUpdates(frame);
|
||||||
|
|
|
@ -16,7 +16,6 @@ public:
|
||||||
grouping getGrouping() const override { return DEVELOPER; }
|
grouping getGrouping() const override { return DEVELOPER; }
|
||||||
|
|
||||||
glm::uvec2 getRecommendedRenderSize() const override;
|
glm::uvec2 getRecommendedRenderSize() const override;
|
||||||
bool hasFocus() const override;
|
|
||||||
void submitFrame(const gpu::FramePointer& newFrame) override;
|
void submitFrame(const gpu::FramePointer& newFrame) override;
|
||||||
QImage getScreenshot(float aspectRatio = 0.0f) const override;
|
QImage getScreenshot(float aspectRatio = 0.0f) const override;
|
||||||
QImage getSecondaryCameraScreenshot() const override;
|
QImage getSecondaryCameraScreenshot() const override;
|
||||||
|
|
|
@ -831,11 +831,6 @@ glm::uvec2 OpenGLDisplayPlugin::getSurfaceSize() const {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OpenGLDisplayPlugin::hasFocus() const {
|
|
||||||
auto window = _container->getPrimaryWidget();
|
|
||||||
return window ? window->hasFocus() : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void OpenGLDisplayPlugin::assertNotPresentThread() const {
|
void OpenGLDisplayPlugin::assertNotPresentThread() const {
|
||||||
Q_ASSERT(QThread::currentThread() != _presentThread);
|
Q_ASSERT(QThread::currentThread() != _presentThread);
|
||||||
}
|
}
|
||||||
|
|
|
@ -98,8 +98,6 @@ protected:
|
||||||
virtual void compositePointer();
|
virtual void compositePointer();
|
||||||
virtual void compositeExtra() {};
|
virtual void compositeExtra() {};
|
||||||
|
|
||||||
virtual bool hasFocus() const override;
|
|
||||||
|
|
||||||
// These functions must only be called on the presentation thread
|
// These functions must only be called on the presentation thread
|
||||||
virtual void customizeContext();
|
virtual void customizeContext();
|
||||||
virtual void uncustomizeContext();
|
virtual void uncustomizeContext();
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include "RenderableMaterialEntityItem.h"
|
#include "RenderableMaterialEntityItem.h"
|
||||||
|
|
||||||
#include "RenderPipelines.h"
|
#include "RenderPipelines.h"
|
||||||
|
#include "GeometryCache.h"
|
||||||
|
|
||||||
using namespace render;
|
using namespace render;
|
||||||
using namespace render::entities;
|
using namespace render::entities;
|
||||||
|
@ -90,138 +91,6 @@ ShapeKey MaterialEntityRenderer::getShapeKey() {
|
||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::vec3 MaterialEntityRenderer::getVertexPos(float phi, float theta) {
|
|
||||||
return glm::vec3(glm::sin(theta) * glm::cos(phi), glm::cos(theta), glm::sin(theta) * glm::sin(phi));
|
|
||||||
}
|
|
||||||
|
|
||||||
glm::vec3 MaterialEntityRenderer::getTangent(float phi, float theta) {
|
|
||||||
return glm::vec3(-glm::cos(theta) * glm::cos(phi), glm::sin(theta), -glm::cos(theta) * glm::sin(phi));
|
|
||||||
}
|
|
||||||
|
|
||||||
void MaterialEntityRenderer::addVertex(std::vector<float>& buffer, const glm::vec3& pos, const glm::vec3& tan, const glm::vec2 uv) {
|
|
||||||
buffer.push_back(pos.x); buffer.push_back(pos.y); buffer.push_back(pos.z);
|
|
||||||
buffer.push_back(tan.x); buffer.push_back(tan.y); buffer.push_back(tan.z);
|
|
||||||
buffer.push_back(uv.x); buffer.push_back(uv.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MaterialEntityRenderer::addTriangleFan(std::vector<float>& buffer, int stack, int step) {
|
|
||||||
float v1 = ((float)stack) / STACKS;
|
|
||||||
float theta1 = v1 * (float)M_PI;
|
|
||||||
glm::vec3 tip = getVertexPos(0, theta1);
|
|
||||||
float v2 = ((float)(stack + step)) / STACKS;
|
|
||||||
float theta2 = v2 * (float)M_PI;
|
|
||||||
for (int i = 0; i < SLICES; i++) {
|
|
||||||
float u1 = ((float)i) / SLICES;
|
|
||||||
float u2 = ((float)(i + step)) / SLICES;
|
|
||||||
float phi1 = u1 * M_PI_TIMES_2;
|
|
||||||
float phi2 = u2 * M_PI_TIMES_2;
|
|
||||||
/* (flipped for negative step)
|
|
||||||
p1
|
|
||||||
/ \
|
|
||||||
/ \
|
|
||||||
/ \
|
|
||||||
p3 ------ p2
|
|
||||||
*/
|
|
||||||
|
|
||||||
glm::vec3 pos2 = getVertexPos(phi2, theta2);
|
|
||||||
glm::vec3 pos3 = getVertexPos(phi1, theta2);
|
|
||||||
|
|
||||||
glm::vec3 tan1 = getTangent(0, theta1);
|
|
||||||
glm::vec3 tan2 = getTangent(phi2, theta2);
|
|
||||||
glm::vec3 tan3 = getTangent(phi1, theta2);
|
|
||||||
|
|
||||||
glm::vec2 uv1 = glm::vec2((u1 + u2) / 2.0f, v1);
|
|
||||||
glm::vec2 uv2 = glm::vec2(u2, v2);
|
|
||||||
glm::vec2 uv3 = glm::vec2(u1, v2);
|
|
||||||
|
|
||||||
addVertex(buffer, tip, tan1, uv1);
|
|
||||||
addVertex(buffer, pos2, tan2, uv2);
|
|
||||||
addVertex(buffer, pos3, tan3, uv3);
|
|
||||||
|
|
||||||
_numVertices += 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int MaterialEntityRenderer::_numVertices = 0;
|
|
||||||
std::shared_ptr<gpu::Stream::Format> MaterialEntityRenderer::_streamFormat = nullptr;
|
|
||||||
std::shared_ptr<gpu::BufferStream> MaterialEntityRenderer::_stream = nullptr;
|
|
||||||
std::shared_ptr<gpu::Buffer> MaterialEntityRenderer::_verticesBuffer = nullptr;
|
|
||||||
|
|
||||||
void MaterialEntityRenderer::generateMesh() {
|
|
||||||
_streamFormat = std::make_shared<gpu::Stream::Format>();
|
|
||||||
_stream = std::make_shared<gpu::BufferStream>();
|
|
||||||
_verticesBuffer = std::make_shared<gpu::Buffer>();
|
|
||||||
|
|
||||||
const int NUM_POS_COORDS = 3;
|
|
||||||
const int NUM_TANGENT_COORDS = 3;
|
|
||||||
const int VERTEX_TANGENT_OFFSET = NUM_POS_COORDS * sizeof(float);
|
|
||||||
const int VERTEX_TEXCOORD_OFFSET = VERTEX_TANGENT_OFFSET + NUM_TANGENT_COORDS * sizeof(float);
|
|
||||||
|
|
||||||
_streamFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0);
|
|
||||||
_streamFormat->setAttribute(gpu::Stream::NORMAL, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0);
|
|
||||||
_streamFormat->setAttribute(gpu::Stream::TANGENT, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), VERTEX_TANGENT_OFFSET);
|
|
||||||
_streamFormat->setAttribute(gpu::Stream::TEXCOORD, 0, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::UV), VERTEX_TEXCOORD_OFFSET);
|
|
||||||
|
|
||||||
_stream->addBuffer(_verticesBuffer, 0, _streamFormat->getChannels().at(0)._stride);
|
|
||||||
|
|
||||||
std::vector<float> vertexBuffer;
|
|
||||||
|
|
||||||
// Top
|
|
||||||
addTriangleFan(vertexBuffer, 0, 1);
|
|
||||||
|
|
||||||
// Middle section
|
|
||||||
for (int j = 1; j < STACKS - 1; j++) {
|
|
||||||
float v1 = ((float)j) / STACKS;
|
|
||||||
float v2 = ((float)(j + 1)) / STACKS;
|
|
||||||
float theta1 = v1 * (float)M_PI;
|
|
||||||
float theta2 = v2 * (float)M_PI;
|
|
||||||
for (int i = 0; i < SLICES; i++) {
|
|
||||||
float u1 = ((float)i) / SLICES;
|
|
||||||
float u2 = ((float)(i + 1)) / SLICES;
|
|
||||||
float phi1 = u1 * M_PI_TIMES_2;
|
|
||||||
float phi2 = u2 * M_PI_TIMES_2;
|
|
||||||
|
|
||||||
/*
|
|
||||||
p2 ---- p3
|
|
||||||
| / |
|
|
||||||
| / |
|
|
||||||
| / |
|
|
||||||
p1 ---- p4
|
|
||||||
*/
|
|
||||||
|
|
||||||
glm::vec3 pos1 = getVertexPos(phi1, theta2);
|
|
||||||
glm::vec3 pos2 = getVertexPos(phi1, theta1);
|
|
||||||
glm::vec3 pos3 = getVertexPos(phi2, theta1);
|
|
||||||
glm::vec3 pos4 = getVertexPos(phi2, theta2);
|
|
||||||
|
|
||||||
glm::vec3 tan1 = getTangent(phi1, theta2);
|
|
||||||
glm::vec3 tan2 = getTangent(phi1, theta1);
|
|
||||||
glm::vec3 tan3 = getTangent(phi2, theta1);
|
|
||||||
glm::vec3 tan4 = getTangent(phi2, theta2);
|
|
||||||
|
|
||||||
glm::vec2 uv1 = glm::vec2(u1, v2);
|
|
||||||
glm::vec2 uv2 = glm::vec2(u1, v1);
|
|
||||||
glm::vec2 uv3 = glm::vec2(u2, v1);
|
|
||||||
glm::vec2 uv4 = glm::vec2(u2, v2);
|
|
||||||
|
|
||||||
addVertex(vertexBuffer, pos1, tan1, uv1);
|
|
||||||
addVertex(vertexBuffer, pos2, tan2, uv2);
|
|
||||||
addVertex(vertexBuffer, pos3, tan3, uv3);
|
|
||||||
|
|
||||||
addVertex(vertexBuffer, pos3, tan3, uv3);
|
|
||||||
addVertex(vertexBuffer, pos4, tan4, uv4);
|
|
||||||
addVertex(vertexBuffer, pos1, tan1, uv1);
|
|
||||||
|
|
||||||
_numVertices += 6;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bottom
|
|
||||||
addTriangleFan(vertexBuffer, STACKS, -1);
|
|
||||||
|
|
||||||
_verticesBuffer->append(vertexBuffer.size() * sizeof(float), (gpu::Byte*) vertexBuffer.data());
|
|
||||||
}
|
|
||||||
|
|
||||||
void MaterialEntityRenderer::doRender(RenderArgs* args) {
|
void MaterialEntityRenderer::doRender(RenderArgs* args) {
|
||||||
PerformanceTimer perfTimer("RenderableMaterialEntityItem::render");
|
PerformanceTimer perfTimer("RenderableMaterialEntityItem::render");
|
||||||
Q_ASSERT(args->_batch);
|
Q_ASSERT(args->_batch);
|
||||||
|
@ -252,14 +121,7 @@ void MaterialEntityRenderer::doRender(RenderArgs* args) {
|
||||||
args->_details._materialSwitches++;
|
args->_details._materialSwitches++;
|
||||||
|
|
||||||
// Draw!
|
// Draw!
|
||||||
if (_numVertices == 0) {
|
DependencyManager::get<GeometryCache>()->renderSphere(batch);
|
||||||
generateMesh();
|
|
||||||
}
|
|
||||||
|
|
||||||
batch.setInputFormat(_streamFormat);
|
args->_details._trianglesRendered += (int)DependencyManager::get<GeometryCache>()->getSphereTriangleCount();
|
||||||
batch.setInputStream(0, *_stream);
|
|
||||||
batch.draw(gpu::TRIANGLES, _numVertices, 0);
|
|
||||||
|
|
||||||
const int NUM_VERTICES_PER_TRIANGLE = 3;
|
|
||||||
args->_details._trianglesRendered += _numVertices / NUM_VERTICES_PER_TRIANGLE;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,20 +40,6 @@ private:
|
||||||
Transform _renderTransform;
|
Transform _renderTransform;
|
||||||
|
|
||||||
std::shared_ptr<NetworkMaterial> _drawMaterial;
|
std::shared_ptr<NetworkMaterial> _drawMaterial;
|
||||||
|
|
||||||
static int _numVertices;
|
|
||||||
static std::shared_ptr<gpu::Stream::Format> _streamFormat;
|
|
||||||
static std::shared_ptr<gpu::BufferStream> _stream;
|
|
||||||
static std::shared_ptr<gpu::Buffer> _verticesBuffer;
|
|
||||||
|
|
||||||
void generateMesh();
|
|
||||||
void addTriangleFan(std::vector<float>& buffer, int stack, int step);
|
|
||||||
static glm::vec3 getVertexPos(float phi, float theta);
|
|
||||||
static glm::vec3 getTangent(float phi, float theta);
|
|
||||||
static void addVertex(std::vector<float>& buffer, const glm::vec3& pos, const glm::vec3& tan, const glm::vec2 uv);
|
|
||||||
const int SLICES = 15;
|
|
||||||
const int STACKS = 9;
|
|
||||||
const float M_PI_TIMES_2 = 2.0f * (float)M_PI;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} }
|
} }
|
||||||
|
|
|
@ -19,6 +19,8 @@
|
||||||
#include "render-utils/simple_vert.h"
|
#include "render-utils/simple_vert.h"
|
||||||
#include "render-utils/simple_frag.h"
|
#include "render-utils/simple_frag.h"
|
||||||
|
|
||||||
|
#include "RenderPipelines.h"
|
||||||
|
|
||||||
//#define SHAPE_ENTITY_USE_FADE_EFFECT
|
//#define SHAPE_ENTITY_USE_FADE_EFFECT
|
||||||
#ifdef SHAPE_ENTITY_USE_FADE_EFFECT
|
#ifdef SHAPE_ENTITY_USE_FADE_EFFECT
|
||||||
#include <FadeEffect.h>
|
#include <FadeEffect.h>
|
||||||
|
@ -109,10 +111,93 @@ bool ShapeEntityRenderer::isTransparent() const {
|
||||||
return Interpolate::calculateFadeRatio(_procedural.getFadeStartTime()) < 1.0f;
|
return Interpolate::calculateFadeRatio(_procedural.getFadeStartTime()) < 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
// return _entity->getLocalRenderAlpha() < 1.0f || Parent::isTransparent();
|
auto mat = _materials.find("0");
|
||||||
|
if (mat != _materials.end()) {
|
||||||
|
if (mat->second.top().material) {
|
||||||
|
auto matKey = mat->second.top().material->getKey();
|
||||||
|
if (matKey.isTranslucent()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return Parent::isTransparent();
|
return Parent::isTransparent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ItemKey ShapeEntityRenderer::getKey() {
|
||||||
|
ItemKey::Builder builder;
|
||||||
|
builder.withTypeShape().withTypeMeta().withTagBits(render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1);
|
||||||
|
|
||||||
|
withReadLock([&] {
|
||||||
|
if (isTransparent()) {
|
||||||
|
builder.withTransparent();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ShapeEntityRenderer::useMaterialPipeline() const {
|
||||||
|
bool proceduralReady = resultWithReadLock<bool>([&] {
|
||||||
|
return _procedural.isReady();
|
||||||
|
});
|
||||||
|
if (proceduralReady) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
graphics::MaterialKey drawMaterialKey;
|
||||||
|
auto mat = _materials.find("0");
|
||||||
|
if (mat != _materials.end() && mat->second.top().material) {
|
||||||
|
drawMaterialKey = mat->second.top().material->getKey();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (drawMaterialKey.isEmissive() || drawMaterialKey.isUnlit() || drawMaterialKey.isMetallic() || drawMaterialKey.isScattering()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the material is using any map, we need to use a material ShapeKey
|
||||||
|
for (int i = 0; i < graphics::Material::MapChannel::NUM_MAP_CHANNELS; i++) {
|
||||||
|
if (drawMaterialKey.isMapChannel(graphics::Material::MapChannel(i))) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ShapeKey ShapeEntityRenderer::getShapeKey() {
|
||||||
|
if (useMaterialPipeline()) {
|
||||||
|
graphics::MaterialKey drawMaterialKey;
|
||||||
|
if (_materials["0"].top().material) {
|
||||||
|
drawMaterialKey = _materials["0"].top().material->getKey();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isTranslucent = drawMaterialKey.isTranslucent();
|
||||||
|
bool hasTangents = drawMaterialKey.isNormalMap();
|
||||||
|
bool hasLightmap = drawMaterialKey.isLightmapMap();
|
||||||
|
bool isUnlit = drawMaterialKey.isUnlit();
|
||||||
|
|
||||||
|
ShapeKey::Builder builder;
|
||||||
|
builder.withMaterial();
|
||||||
|
|
||||||
|
if (isTranslucent) {
|
||||||
|
builder.withTranslucent();
|
||||||
|
}
|
||||||
|
if (hasTangents) {
|
||||||
|
builder.withTangents();
|
||||||
|
}
|
||||||
|
if (hasLightmap) {
|
||||||
|
builder.withLightmap();
|
||||||
|
}
|
||||||
|
if (isUnlit) {
|
||||||
|
builder.withUnlit();
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.build();
|
||||||
|
} else {
|
||||||
|
return Parent::getShapeKey();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ShapeEntityRenderer::doRender(RenderArgs* args) {
|
void ShapeEntityRenderer::doRender(RenderArgs* args) {
|
||||||
PerformanceTimer perfTimer("RenderableShapeEntityItem::render");
|
PerformanceTimer perfTimer("RenderableShapeEntityItem::render");
|
||||||
Q_ASSERT(args->_batch);
|
Q_ASSERT(args->_batch);
|
||||||
|
@ -149,7 +234,7 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) {
|
||||||
} else {
|
} else {
|
||||||
geometryCache->renderShape(batch, geometryShape, outColor);
|
geometryCache->renderShape(batch, geometryShape, outColor);
|
||||||
}
|
}
|
||||||
} else {
|
} else if (!useMaterialPipeline()) {
|
||||||
// FIXME, support instanced multi-shape rendering using multidraw indirect
|
// FIXME, support instanced multi-shape rendering using multidraw indirect
|
||||||
outColor.a *= _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f;
|
outColor.a *= _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f;
|
||||||
auto pipeline = outColor.a < 1.0f ? geometryCache->getTransparentShapePipeline() : geometryCache->getOpaqueShapePipeline();
|
auto pipeline = outColor.a < 1.0f ? geometryCache->getTransparentShapePipeline() : geometryCache->getOpaqueShapePipeline();
|
||||||
|
@ -158,6 +243,11 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) {
|
||||||
} else {
|
} else {
|
||||||
geometryCache->renderSolidShapeInstance(args, batch, geometryShape, outColor, pipeline);
|
geometryCache->renderSolidShapeInstance(args, batch, geometryShape, outColor, pipeline);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
RenderPipelines::bindMaterial(mat, batch, args->_enableTexturing);
|
||||||
|
args->_details._materialSwitches++;
|
||||||
|
|
||||||
|
geometryCache->renderShape(batch, geometryShape);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto triCount = geometryCache->getShapeTriangleCount(geometryShape);
|
const auto triCount = geometryCache->getShapeTriangleCount(geometryShape);
|
||||||
|
|
|
@ -24,6 +24,10 @@ public:
|
||||||
|
|
||||||
virtual scriptable::ScriptableModelBase getScriptableModel() override;
|
virtual scriptable::ScriptableModelBase getScriptableModel() override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
ItemKey getKey() override;
|
||||||
|
ShapeKey getShapeKey() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual bool needsRenderUpdate() const override;
|
virtual bool needsRenderUpdate() const override;
|
||||||
virtual bool needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const override;
|
virtual bool needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const override;
|
||||||
|
@ -32,6 +36,8 @@ private:
|
||||||
virtual void doRender(RenderArgs* args) override;
|
virtual void doRender(RenderArgs* args) override;
|
||||||
virtual bool isTransparent() const override;
|
virtual bool isTransparent() const override;
|
||||||
|
|
||||||
|
bool useMaterialPipeline() const;
|
||||||
|
|
||||||
Procedural _procedural;
|
Procedural _procedural;
|
||||||
QString _lastUserData;
|
QString _lastUserData;
|
||||||
Transform _renderTransform;
|
Transform _renderTransform;
|
||||||
|
|
|
@ -239,7 +239,7 @@ void WebEntityRenderer::doRender(RenderArgs* args) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WebEntityRenderer::hasWebSurface() {
|
bool WebEntityRenderer::hasWebSurface() {
|
||||||
return (bool)_webSurface;
|
return (bool)_webSurface && _webSurface->getRootItem();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WebEntityRenderer::buildWebSurface(const TypedEntityPointer& entity) {
|
bool WebEntityRenderer::buildWebSurface(const TypedEntityPointer& entity) {
|
||||||
|
@ -303,7 +303,7 @@ bool WebEntityRenderer::buildWebSurface(const TypedEntityPointer& entity) {
|
||||||
_fadeStartTime = usecTimestampNow();
|
_fadeStartTime = usecTimestampNow();
|
||||||
_webSurface->resume();
|
_webSurface->resume();
|
||||||
|
|
||||||
return true;
|
return _webSurface->getRootItem();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebEntityRenderer::destroyWebSurface() {
|
void WebEntityRenderer::destroyWebSurface() {
|
||||||
|
|
|
@ -157,7 +157,7 @@ void MaterialEntityItem::setMaterialURL(const QString& materialURLString, bool u
|
||||||
}
|
}
|
||||||
|
|
||||||
if (usingUserData) {
|
if (usingUserData) {
|
||||||
_parsedMaterials = NetworkMaterialResource::parseJSONMaterials(QJsonDocument::fromJson(getUserData().toUtf8()));
|
_parsedMaterials = NetworkMaterialResource::parseJSONMaterials(QJsonDocument::fromJson(getUserData().toUtf8()), materialURLString);
|
||||||
|
|
||||||
// Since our material changed, the current name might not be valid anymore, so we need to update
|
// Since our material changed, the current name might not be valid anymore, so we need to update
|
||||||
setCurrentMaterialName(_currentMaterialName);
|
setCurrentMaterialName(_currentMaterialName);
|
||||||
|
|
|
@ -20,7 +20,7 @@ void NetworkMaterialResource::downloadFinished(const QByteArray& data) {
|
||||||
parsedMaterials.reset();
|
parsedMaterials.reset();
|
||||||
|
|
||||||
if (_url.toString().contains(".json")) {
|
if (_url.toString().contains(".json")) {
|
||||||
parsedMaterials = parseJSONMaterials(QJsonDocument::fromJson(data));
|
parsedMaterials = parseJSONMaterials(QJsonDocument::fromJson(data), _url);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: parse other material types
|
// TODO: parse other material types
|
||||||
|
@ -75,7 +75,7 @@ bool NetworkMaterialResource::parseJSONColor(const QJsonValue& array, glm::vec3&
|
||||||
* @property {number} materialVersion=1 - The version of the material. <em>Currently not used.</em>
|
* @property {number} materialVersion=1 - The version of the material. <em>Currently not used.</em>
|
||||||
* @property {Material|Material[]} materials - The details of the material or materials.
|
* @property {Material|Material[]} materials - The details of the material or materials.
|
||||||
*/
|
*/
|
||||||
NetworkMaterialResource::ParsedMaterials NetworkMaterialResource::parseJSONMaterials(const QJsonDocument& materialJSON) {
|
NetworkMaterialResource::ParsedMaterials NetworkMaterialResource::parseJSONMaterials(const QJsonDocument& materialJSON, const QUrl& baseUrl) {
|
||||||
ParsedMaterials toReturn;
|
ParsedMaterials toReturn;
|
||||||
if (!materialJSON.isNull() && materialJSON.isObject()) {
|
if (!materialJSON.isNull() && materialJSON.isObject()) {
|
||||||
QJsonObject materialJSONObject = materialJSON.object();
|
QJsonObject materialJSONObject = materialJSON.object();
|
||||||
|
@ -91,13 +91,13 @@ NetworkMaterialResource::ParsedMaterials NetworkMaterialResource::parseJSONMater
|
||||||
QJsonArray materials = materialsValue.toArray();
|
QJsonArray materials = materialsValue.toArray();
|
||||||
for (auto material : materials) {
|
for (auto material : materials) {
|
||||||
if (!material.isNull() && material.isObject()) {
|
if (!material.isNull() && material.isObject()) {
|
||||||
auto parsedMaterial = parseJSONMaterial(material.toObject());
|
auto parsedMaterial = parseJSONMaterial(material.toObject(), baseUrl);
|
||||||
toReturn.networkMaterials[parsedMaterial.first] = parsedMaterial.second;
|
toReturn.networkMaterials[parsedMaterial.first] = parsedMaterial.second;
|
||||||
toReturn.names.push_back(parsedMaterial.first);
|
toReturn.names.push_back(parsedMaterial.first);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (materialsValue.isObject()) {
|
} else if (materialsValue.isObject()) {
|
||||||
auto parsedMaterial = parseJSONMaterial(materialsValue.toObject());
|
auto parsedMaterial = parseJSONMaterial(materialsValue.toObject(), baseUrl);
|
||||||
toReturn.networkMaterials[parsedMaterial.first] = parsedMaterial.second;
|
toReturn.networkMaterials[parsedMaterial.first] = parsedMaterial.second;
|
||||||
toReturn.names.push_back(parsedMaterial.first);
|
toReturn.names.push_back(parsedMaterial.first);
|
||||||
}
|
}
|
||||||
|
@ -138,7 +138,7 @@ NetworkMaterialResource::ParsedMaterials NetworkMaterialResource::parseJSONMater
|
||||||
* @property {string} lightMap - URL of light map texture image. <em>Currently not used.</em>
|
* @property {string} lightMap - URL of light map texture image. <em>Currently not used.</em>
|
||||||
*/
|
*/
|
||||||
// Note: See MaterialEntityItem.h for default values used in practice.
|
// Note: See MaterialEntityItem.h for default values used in practice.
|
||||||
std::pair<std::string, std::shared_ptr<NetworkMaterial>> NetworkMaterialResource::parseJSONMaterial(const QJsonObject& materialJSON) {
|
std::pair<std::string, std::shared_ptr<NetworkMaterial>> NetworkMaterialResource::parseJSONMaterial(const QJsonObject& materialJSON, const QUrl& baseUrl) {
|
||||||
std::string name = "";
|
std::string name = "";
|
||||||
std::shared_ptr<NetworkMaterial> material = std::make_shared<NetworkMaterial>();
|
std::shared_ptr<NetworkMaterial> material = std::make_shared<NetworkMaterial>();
|
||||||
for (auto& key : materialJSON.keys()) {
|
for (auto& key : materialJSON.keys()) {
|
||||||
|
@ -199,57 +199,58 @@ std::pair<std::string, std::shared_ptr<NetworkMaterial>> NetworkMaterialResource
|
||||||
} else if (key == "albedoMap") {
|
} else if (key == "albedoMap") {
|
||||||
auto value = materialJSON.value(key);
|
auto value = materialJSON.value(key);
|
||||||
if (value.isString()) {
|
if (value.isString()) {
|
||||||
|
QString urlString = value.toString();
|
||||||
bool useAlphaChannel = false;
|
bool useAlphaChannel = false;
|
||||||
auto opacityMap = materialJSON.find("opacityMap");
|
auto opacityMap = materialJSON.find("opacityMap");
|
||||||
if (opacityMap != materialJSON.end() && opacityMap->isString() && opacityMap->toString() == value.toString()) {
|
if (opacityMap != materialJSON.end() && opacityMap->isString() && opacityMap->toString() == urlString) {
|
||||||
useAlphaChannel = true;
|
useAlphaChannel = true;
|
||||||
}
|
}
|
||||||
material->setAlbedoMap(value.toString(), useAlphaChannel);
|
material->setAlbedoMap(baseUrl.resolved(urlString), useAlphaChannel);
|
||||||
}
|
}
|
||||||
} else if (key == "roughnessMap") {
|
} else if (key == "roughnessMap") {
|
||||||
auto value = materialJSON.value(key);
|
auto value = materialJSON.value(key);
|
||||||
if (value.isString()) {
|
if (value.isString()) {
|
||||||
material->setRoughnessMap(value.toString(), false);
|
material->setRoughnessMap(baseUrl.resolved(value.toString()), false);
|
||||||
}
|
}
|
||||||
} else if (key == "glossMap") {
|
} else if (key == "glossMap") {
|
||||||
auto value = materialJSON.value(key);
|
auto value = materialJSON.value(key);
|
||||||
if (value.isString()) {
|
if (value.isString()) {
|
||||||
material->setRoughnessMap(value.toString(), true);
|
material->setRoughnessMap(baseUrl.resolved(value.toString()), true);
|
||||||
}
|
}
|
||||||
} else if (key == "metallicMap") {
|
} else if (key == "metallicMap") {
|
||||||
auto value = materialJSON.value(key);
|
auto value = materialJSON.value(key);
|
||||||
if (value.isString()) {
|
if (value.isString()) {
|
||||||
material->setMetallicMap(value.toString(), false);
|
material->setMetallicMap(baseUrl.resolved(value.toString()), false);
|
||||||
}
|
}
|
||||||
} else if (key == "specularMap") {
|
} else if (key == "specularMap") {
|
||||||
auto value = materialJSON.value(key);
|
auto value = materialJSON.value(key);
|
||||||
if (value.isString()) {
|
if (value.isString()) {
|
||||||
material->setMetallicMap(value.toString(), true);
|
material->setMetallicMap(baseUrl.resolved(value.toString()), true);
|
||||||
}
|
}
|
||||||
} else if (key == "normalMap") {
|
} else if (key == "normalMap") {
|
||||||
auto value = materialJSON.value(key);
|
auto value = materialJSON.value(key);
|
||||||
if (value.isString()) {
|
if (value.isString()) {
|
||||||
material->setNormalMap(value.toString(), false);
|
material->setNormalMap(baseUrl.resolved(value.toString()), false);
|
||||||
}
|
}
|
||||||
} else if (key == "bumpMap") {
|
} else if (key == "bumpMap") {
|
||||||
auto value = materialJSON.value(key);
|
auto value = materialJSON.value(key);
|
||||||
if (value.isString()) {
|
if (value.isString()) {
|
||||||
material->setNormalMap(value.toString(), true);
|
material->setNormalMap(baseUrl.resolved(value.toString()), true);
|
||||||
}
|
}
|
||||||
} else if (key == "occlusionMap") {
|
} else if (key == "occlusionMap") {
|
||||||
auto value = materialJSON.value(key);
|
auto value = materialJSON.value(key);
|
||||||
if (value.isString()) {
|
if (value.isString()) {
|
||||||
material->setOcclusionMap(value.toString());
|
material->setOcclusionMap(baseUrl.resolved(value.toString()));
|
||||||
}
|
}
|
||||||
} else if (key == "scatteringMap") {
|
} else if (key == "scatteringMap") {
|
||||||
auto value = materialJSON.value(key);
|
auto value = materialJSON.value(key);
|
||||||
if (value.isString()) {
|
if (value.isString()) {
|
||||||
material->setScatteringMap(value.toString());
|
material->setScatteringMap(baseUrl.resolved(value.toString()));
|
||||||
}
|
}
|
||||||
} else if (key == "lightMap") {
|
} else if (key == "lightMap") {
|
||||||
auto value = materialJSON.value(key);
|
auto value = materialJSON.value(key);
|
||||||
if (value.isString()) {
|
if (value.isString()) {
|
||||||
material->setLightmapMap(value.toString());
|
material->setLightmapMap(baseUrl.resolved(value.toString()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,8 +37,8 @@ public:
|
||||||
|
|
||||||
ParsedMaterials parsedMaterials;
|
ParsedMaterials parsedMaterials;
|
||||||
|
|
||||||
static ParsedMaterials parseJSONMaterials(const QJsonDocument& materialJSON);
|
static ParsedMaterials parseJSONMaterials(const QJsonDocument& materialJSON, const QUrl& baseUrl);
|
||||||
static std::pair<std::string, std::shared_ptr<NetworkMaterial>> parseJSONMaterial(const QJsonObject& materialJSON);
|
static std::pair<std::string, std::shared_ptr<NetworkMaterial>> parseJSONMaterial(const QJsonObject& materialJSON, const QUrl& baseUrl);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static bool parseJSONColor(const QJsonValue& array, glm::vec3& color, bool& isSRGB);
|
static bool parseJSONColor(const QJsonValue& array, glm::vec3& color, bool& isSRGB);
|
||||||
|
|
|
@ -556,58 +556,58 @@ graphics::TextureMapPointer NetworkMaterial::fetchTextureMap(const QUrl& url, im
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetworkMaterial::setAlbedoMap(const QString& url, bool useAlphaChannel) {
|
void NetworkMaterial::setAlbedoMap(const QUrl& url, bool useAlphaChannel) {
|
||||||
auto map = fetchTextureMap(QUrl(url), image::TextureUsage::ALBEDO_TEXTURE, MapChannel::ALBEDO_MAP);
|
auto map = fetchTextureMap(url, image::TextureUsage::ALBEDO_TEXTURE, MapChannel::ALBEDO_MAP);
|
||||||
if (map) {
|
if (map) {
|
||||||
map->setUseAlphaChannel(useAlphaChannel);
|
map->setUseAlphaChannel(useAlphaChannel);
|
||||||
setTextureMap(MapChannel::ALBEDO_MAP, map);
|
setTextureMap(MapChannel::ALBEDO_MAP, map);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetworkMaterial::setNormalMap(const QString& url, bool isBumpmap) {
|
void NetworkMaterial::setNormalMap(const QUrl& url, bool isBumpmap) {
|
||||||
auto map = fetchTextureMap(QUrl(url), isBumpmap ? image::TextureUsage::BUMP_TEXTURE : image::TextureUsage::NORMAL_TEXTURE, MapChannel::NORMAL_MAP);
|
auto map = fetchTextureMap(url, isBumpmap ? image::TextureUsage::BUMP_TEXTURE : image::TextureUsage::NORMAL_TEXTURE, MapChannel::NORMAL_MAP);
|
||||||
if (map) {
|
if (map) {
|
||||||
setTextureMap(MapChannel::NORMAL_MAP, map);
|
setTextureMap(MapChannel::NORMAL_MAP, map);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetworkMaterial::setRoughnessMap(const QString& url, bool isGloss) {
|
void NetworkMaterial::setRoughnessMap(const QUrl& url, bool isGloss) {
|
||||||
auto map = fetchTextureMap(QUrl(url), isGloss ? image::TextureUsage::GLOSS_TEXTURE : image::TextureUsage::ROUGHNESS_TEXTURE, MapChannel::ROUGHNESS_MAP);
|
auto map = fetchTextureMap(url, isGloss ? image::TextureUsage::GLOSS_TEXTURE : image::TextureUsage::ROUGHNESS_TEXTURE, MapChannel::ROUGHNESS_MAP);
|
||||||
if (map) {
|
if (map) {
|
||||||
setTextureMap(MapChannel::ROUGHNESS_MAP, map);
|
setTextureMap(MapChannel::ROUGHNESS_MAP, map);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetworkMaterial::setMetallicMap(const QString& url, bool isSpecular) {
|
void NetworkMaterial::setMetallicMap(const QUrl& url, bool isSpecular) {
|
||||||
auto map = fetchTextureMap(QUrl(url), isSpecular ? image::TextureUsage::SPECULAR_TEXTURE : image::TextureUsage::METALLIC_TEXTURE, MapChannel::METALLIC_MAP);
|
auto map = fetchTextureMap(url, isSpecular ? image::TextureUsage::SPECULAR_TEXTURE : image::TextureUsage::METALLIC_TEXTURE, MapChannel::METALLIC_MAP);
|
||||||
if (map) {
|
if (map) {
|
||||||
setTextureMap(MapChannel::METALLIC_MAP, map);
|
setTextureMap(MapChannel::METALLIC_MAP, map);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetworkMaterial::setOcclusionMap(const QString& url) {
|
void NetworkMaterial::setOcclusionMap(const QUrl& url) {
|
||||||
auto map = fetchTextureMap(QUrl(url), image::TextureUsage::OCCLUSION_TEXTURE, MapChannel::OCCLUSION_MAP);
|
auto map = fetchTextureMap(url, image::TextureUsage::OCCLUSION_TEXTURE, MapChannel::OCCLUSION_MAP);
|
||||||
if (map) {
|
if (map) {
|
||||||
setTextureMap(MapChannel::OCCLUSION_MAP, map);
|
setTextureMap(MapChannel::OCCLUSION_MAP, map);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetworkMaterial::setEmissiveMap(const QString& url) {
|
void NetworkMaterial::setEmissiveMap(const QUrl& url) {
|
||||||
auto map = fetchTextureMap(QUrl(url), image::TextureUsage::EMISSIVE_TEXTURE, MapChannel::EMISSIVE_MAP);
|
auto map = fetchTextureMap(url, image::TextureUsage::EMISSIVE_TEXTURE, MapChannel::EMISSIVE_MAP);
|
||||||
if (map) {
|
if (map) {
|
||||||
setTextureMap(MapChannel::EMISSIVE_MAP, map);
|
setTextureMap(MapChannel::EMISSIVE_MAP, map);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetworkMaterial::setScatteringMap(const QString& url) {
|
void NetworkMaterial::setScatteringMap(const QUrl& url) {
|
||||||
auto map = fetchTextureMap(QUrl(url), image::TextureUsage::SCATTERING_TEXTURE, MapChannel::SCATTERING_MAP);
|
auto map = fetchTextureMap(url, image::TextureUsage::SCATTERING_TEXTURE, MapChannel::SCATTERING_MAP);
|
||||||
if (map) {
|
if (map) {
|
||||||
setTextureMap(MapChannel::SCATTERING_MAP, map);
|
setTextureMap(MapChannel::SCATTERING_MAP, map);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetworkMaterial::setLightmapMap(const QString& url) {
|
void NetworkMaterial::setLightmapMap(const QUrl& url) {
|
||||||
auto map = fetchTextureMap(QUrl(url), image::TextureUsage::LIGHTMAP_TEXTURE, MapChannel::LIGHTMAP_MAP);
|
auto map = fetchTextureMap(url, image::TextureUsage::LIGHTMAP_TEXTURE, MapChannel::LIGHTMAP_MAP);
|
||||||
if (map) {
|
if (map) {
|
||||||
//map->setTextureTransform(_lightmapTransform);
|
//map->setTextureTransform(_lightmapTransform);
|
||||||
//map->setLightmapOffsetScale(_lightmapParams.x, _lightmapParams.y);
|
//map->setLightmapOffsetScale(_lightmapParams.x, _lightmapParams.y);
|
||||||
|
|
|
@ -164,14 +164,14 @@ public:
|
||||||
NetworkMaterial(const FBXMaterial& material, const QUrl& textureBaseUrl);
|
NetworkMaterial(const FBXMaterial& material, const QUrl& textureBaseUrl);
|
||||||
NetworkMaterial(const NetworkMaterial& material);
|
NetworkMaterial(const NetworkMaterial& material);
|
||||||
|
|
||||||
void setAlbedoMap(const QString& url, bool useAlphaChannel);
|
void setAlbedoMap(const QUrl& url, bool useAlphaChannel);
|
||||||
void setNormalMap(const QString& url, bool isBumpmap);
|
void setNormalMap(const QUrl& url, bool isBumpmap);
|
||||||
void setRoughnessMap(const QString& url, bool isGloss);
|
void setRoughnessMap(const QUrl& url, bool isGloss);
|
||||||
void setMetallicMap(const QString& url, bool isSpecular);
|
void setMetallicMap(const QUrl& url, bool isSpecular);
|
||||||
void setOcclusionMap(const QString& url);
|
void setOcclusionMap(const QUrl& url);
|
||||||
void setEmissiveMap(const QString& url);
|
void setEmissiveMap(const QUrl& url);
|
||||||
void setScatteringMap(const QString& url);
|
void setScatteringMap(const QUrl& url);
|
||||||
void setLightmapMap(const QString& url);
|
void setLightmapMap(const QUrl& url);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend class Geometry;
|
friend class Geometry;
|
||||||
|
|
|
@ -121,7 +121,7 @@ public:
|
||||||
ReplicatedAvatarIdentity,
|
ReplicatedAvatarIdentity,
|
||||||
ReplicatedKillAvatar,
|
ReplicatedKillAvatar,
|
||||||
ReplicatedBulkAvatarData,
|
ReplicatedBulkAvatarData,
|
||||||
OctreeFileReplacementFromUrl,
|
DomainContentReplacementFromUrl,
|
||||||
ChallengeOwnership,
|
ChallengeOwnership,
|
||||||
EntityScriptCallMethod,
|
EntityScriptCallMethod,
|
||||||
ChallengeOwnershipRequest,
|
ChallengeOwnershipRequest,
|
||||||
|
@ -171,7 +171,7 @@ public:
|
||||||
<< PacketTypeEnum::Value::DomainServerPathResponse << PacketTypeEnum::Value::DomainServerAddedNode
|
<< PacketTypeEnum::Value::DomainServerPathResponse << PacketTypeEnum::Value::DomainServerAddedNode
|
||||||
<< PacketTypeEnum::Value::DomainServerConnectionToken << PacketTypeEnum::Value::DomainSettingsRequest
|
<< PacketTypeEnum::Value::DomainServerConnectionToken << PacketTypeEnum::Value::DomainSettingsRequest
|
||||||
<< PacketTypeEnum::Value::OctreeDataFileRequest << PacketTypeEnum::Value::OctreeDataFileReply
|
<< PacketTypeEnum::Value::OctreeDataFileRequest << PacketTypeEnum::Value::OctreeDataFileReply
|
||||||
<< PacketTypeEnum::Value::OctreeDataPersist << PacketTypeEnum::Value::OctreeFileReplacementFromUrl
|
<< PacketTypeEnum::Value::OctreeDataPersist << PacketTypeEnum::Value::DomainContentReplacementFromUrl
|
||||||
<< PacketTypeEnum::Value::DomainSettings << PacketTypeEnum::Value::ICEServerPeerInformation
|
<< PacketTypeEnum::Value::DomainSettings << PacketTypeEnum::Value::ICEServerPeerInformation
|
||||||
<< PacketTypeEnum::Value::ICEServerQuery << PacketTypeEnum::Value::ICEServerHeartbeat
|
<< PacketTypeEnum::Value::ICEServerQuery << PacketTypeEnum::Value::ICEServerHeartbeat
|
||||||
<< PacketTypeEnum::Value::ICEServerHeartbeatACK << PacketTypeEnum::Value::ICEPing
|
<< PacketTypeEnum::Value::ICEServerHeartbeatACK << PacketTypeEnum::Value::ICEPing
|
||||||
|
|
|
@ -140,9 +140,6 @@ public:
|
||||||
virtual void setContext(const gpu::ContextPointer& context) final { _gpuContext = context; }
|
virtual void setContext(const gpu::ContextPointer& context) final { _gpuContext = context; }
|
||||||
virtual void submitFrame(const gpu::FramePointer& newFrame) = 0;
|
virtual void submitFrame(const gpu::FramePointer& newFrame) = 0;
|
||||||
|
|
||||||
// Does the rendering surface have current focus?
|
|
||||||
virtual bool hasFocus() const = 0;
|
|
||||||
|
|
||||||
// The size of the rendering target (may be larger than the device size due to distortion)
|
// The size of the rendering target (may be larger than the device size due to distortion)
|
||||||
virtual glm::uvec2 getRecommendedRenderSize() const = 0;
|
virtual glm::uvec2 getRecommendedRenderSize() const = 0;
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,9 @@ include_hifi_library_headers(audio)
|
||||||
include_hifi_library_headers(networking)
|
include_hifi_library_headers(networking)
|
||||||
include_hifi_library_headers(octree)
|
include_hifi_library_headers(octree)
|
||||||
|
|
||||||
|
# tell CMake to exclude qrc_fonts.cpp for policy CMP0071
|
||||||
|
set_property(SOURCE qrc_fonts.cpp PROPERTY SKIP_AUTOMOC ON)
|
||||||
|
|
||||||
if (NOT ANDROID)
|
if (NOT ANDROID)
|
||||||
target_nsight()
|
target_nsight()
|
||||||
endif ()
|
endif ()
|
||||||
|
|
|
@ -100,6 +100,8 @@ static const int VERTICES_PER_TRIANGLE = 3;
|
||||||
|
|
||||||
static const gpu::Element POSITION_ELEMENT { gpu::VEC3, gpu::FLOAT, gpu::XYZ };
|
static const gpu::Element POSITION_ELEMENT { gpu::VEC3, gpu::FLOAT, gpu::XYZ };
|
||||||
static const gpu::Element NORMAL_ELEMENT { gpu::VEC3, gpu::FLOAT, gpu::XYZ };
|
static const gpu::Element NORMAL_ELEMENT { gpu::VEC3, gpu::FLOAT, gpu::XYZ };
|
||||||
|
static const gpu::Element TEXCOORD0_ELEMENT { gpu::VEC2, gpu::FLOAT, gpu::UV };
|
||||||
|
static const gpu::Element TANGENT_ELEMENT { gpu::VEC3, gpu::FLOAT, gpu::XYZ };
|
||||||
static const gpu::Element COLOR_ELEMENT { gpu::VEC4, gpu::NUINT8, gpu::RGBA };
|
static const gpu::Element COLOR_ELEMENT { gpu::VEC4, gpu::NUINT8, gpu::RGBA };
|
||||||
static const gpu::Element TEXCOORD4_ELEMENT { gpu::VEC4, gpu::FLOAT, gpu::XYZW };
|
static const gpu::Element TEXCOORD4_ELEMENT { gpu::VEC4, gpu::FLOAT, gpu::XYZW };
|
||||||
|
|
||||||
|
@ -107,8 +109,10 @@ static gpu::Stream::FormatPointer SOLID_STREAM_FORMAT;
|
||||||
static gpu::Stream::FormatPointer INSTANCED_SOLID_STREAM_FORMAT;
|
static gpu::Stream::FormatPointer INSTANCED_SOLID_STREAM_FORMAT;
|
||||||
static gpu::Stream::FormatPointer INSTANCED_SOLID_FADE_STREAM_FORMAT;
|
static gpu::Stream::FormatPointer INSTANCED_SOLID_FADE_STREAM_FORMAT;
|
||||||
|
|
||||||
static const uint SHAPE_VERTEX_STRIDE = sizeof(glm::vec3) * 2; // vertices and normals
|
static const uint SHAPE_VERTEX_STRIDE = sizeof(GeometryCache::ShapeVertex); // position, normal, texcoords, tangent
|
||||||
static const uint SHAPE_NORMALS_OFFSET = sizeof(glm::vec3);
|
static const uint SHAPE_NORMALS_OFFSET = offsetof(GeometryCache::ShapeVertex, normal);
|
||||||
|
static const uint SHAPE_TEXCOORD0_OFFSET = offsetof(GeometryCache::ShapeVertex, uv);
|
||||||
|
static const uint SHAPE_TANGENT_OFFSET = offsetof(GeometryCache::ShapeVertex, tangent);
|
||||||
|
|
||||||
void GeometryCache::computeSimpleHullPointListForShape(const int entityShape, const glm::vec3 &entityExtents, QVector<glm::vec3> &outPointList) {
|
void GeometryCache::computeSimpleHullPointListForShape(const int entityShape, const glm::vec3 &entityExtents, QVector<glm::vec3> &outPointList) {
|
||||||
|
|
||||||
|
@ -167,16 +171,20 @@ std::vector<vec3> polygon() {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GeometryCache::ShapeData::setupVertices(gpu::BufferPointer& vertexBuffer, const geometry::VertexVector& vertices) {
|
void GeometryCache::ShapeData::setupVertices(gpu::BufferPointer& vertexBuffer, const std::vector<ShapeVertex>& vertices) {
|
||||||
gpu::Buffer::Size offset = vertexBuffer->getSize();
|
gpu::Buffer::Size offset = vertexBuffer->getSize();
|
||||||
vertexBuffer->append(vertices);
|
vertexBuffer->append(vertices);
|
||||||
|
|
||||||
gpu::Buffer::Size viewSize = vertices.size() * sizeof(glm::vec3);
|
gpu::Buffer::Size viewSize = vertices.size() * sizeof(ShapeVertex);
|
||||||
|
|
||||||
_positionView = gpu::BufferView(vertexBuffer, offset,
|
_positionView = gpu::BufferView(vertexBuffer, offset,
|
||||||
viewSize, SHAPE_VERTEX_STRIDE, POSITION_ELEMENT);
|
viewSize, SHAPE_VERTEX_STRIDE, POSITION_ELEMENT);
|
||||||
_normalView = gpu::BufferView(vertexBuffer, offset + SHAPE_NORMALS_OFFSET,
|
_normalView = gpu::BufferView(vertexBuffer, offset + SHAPE_NORMALS_OFFSET,
|
||||||
viewSize, SHAPE_VERTEX_STRIDE, NORMAL_ELEMENT);
|
viewSize, SHAPE_VERTEX_STRIDE, NORMAL_ELEMENT);
|
||||||
|
_texCoordView = gpu::BufferView(vertexBuffer, offset + SHAPE_TEXCOORD0_OFFSET,
|
||||||
|
viewSize, SHAPE_VERTEX_STRIDE, TEXCOORD0_ELEMENT);
|
||||||
|
_tangentView = gpu::BufferView(vertexBuffer, offset + SHAPE_TANGENT_OFFSET,
|
||||||
|
viewSize, SHAPE_VERTEX_STRIDE, TANGENT_ELEMENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GeometryCache::ShapeData::setupIndices(gpu::BufferPointer& indexBuffer, const geometry::IndexVector& indices, const geometry::IndexVector& wireIndices) {
|
void GeometryCache::ShapeData::setupIndices(gpu::BufferPointer& indexBuffer, const geometry::IndexVector& indices, const geometry::IndexVector& wireIndices) {
|
||||||
|
@ -202,6 +210,8 @@ void GeometryCache::ShapeData::setupIndices(gpu::BufferPointer& indexBuffer, con
|
||||||
void GeometryCache::ShapeData::setupBatch(gpu::Batch& batch) const {
|
void GeometryCache::ShapeData::setupBatch(gpu::Batch& batch) const {
|
||||||
batch.setInputBuffer(gpu::Stream::POSITION, _positionView);
|
batch.setInputBuffer(gpu::Stream::POSITION, _positionView);
|
||||||
batch.setInputBuffer(gpu::Stream::NORMAL, _normalView);
|
batch.setInputBuffer(gpu::Stream::NORMAL, _normalView);
|
||||||
|
batch.setInputBuffer(gpu::Stream::TEXCOORD, _texCoordView);
|
||||||
|
batch.setInputBuffer(gpu::Stream::TANGENT, _tangentView);
|
||||||
batch.setIndexBuffer(_indicesView);
|
batch.setIndexBuffer(_indicesView);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -268,14 +278,14 @@ static IndexPair indexToken(geometry::Index a, geometry::Index b) {
|
||||||
template <size_t N>
|
template <size_t N>
|
||||||
void setupFlatShape(GeometryCache::ShapeData& shapeData, const geometry::Solid<N>& shape, gpu::BufferPointer& vertexBuffer, gpu::BufferPointer& indexBuffer) {
|
void setupFlatShape(GeometryCache::ShapeData& shapeData, const geometry::Solid<N>& shape, gpu::BufferPointer& vertexBuffer, gpu::BufferPointer& indexBuffer) {
|
||||||
using namespace geometry;
|
using namespace geometry;
|
||||||
VertexVector vertices;
|
std::vector<GeometryCache::ShapeVertex> vertices;
|
||||||
IndexVector solidIndices, wireIndices;
|
IndexVector solidIndices, wireIndices;
|
||||||
IndexPairs wireSeenIndices;
|
IndexPairs wireSeenIndices;
|
||||||
|
|
||||||
size_t faceCount = shape.faces.size();
|
size_t faceCount = shape.faces.size();
|
||||||
size_t faceIndexCount = triangulatedFaceIndexCount<N>();
|
size_t faceIndexCount = triangulatedFaceIndexCount<N>();
|
||||||
|
|
||||||
vertices.reserve(N * faceCount * 2);
|
vertices.reserve(N * faceCount);
|
||||||
solidIndices.reserve(faceIndexCount * faceCount);
|
solidIndices.reserve(faceIndexCount * faceCount);
|
||||||
|
|
||||||
Index baseVertex = 0;
|
Index baseVertex = 0;
|
||||||
|
@ -284,11 +294,35 @@ void setupFlatShape(GeometryCache::ShapeData& shapeData, const geometry::Solid<N
|
||||||
// Compute the face normal
|
// Compute the face normal
|
||||||
vec3 faceNormal = shape.getFaceNormal(f);
|
vec3 faceNormal = shape.getFaceNormal(f);
|
||||||
|
|
||||||
|
// Find two points on this face with the same Y tex coords, and find the vector going from the one with the smaller X tex coord to the one with the larger X tex coord
|
||||||
|
vec3 faceTangent = vec3(0.0f);
|
||||||
|
Index i1 = 0;
|
||||||
|
Index i2 = i1 + 1;
|
||||||
|
while (i1 < N) {
|
||||||
|
if (shape.texCoords[f * N + i1].y == shape.texCoords[f * N + i2].y) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i2 == N - 1) {
|
||||||
|
i1++;
|
||||||
|
i2 = i1 + 1;
|
||||||
|
} else {
|
||||||
|
i2++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i1 < N && i2 < N) {
|
||||||
|
vec3 p1 = shape.vertices[face[i1]];
|
||||||
|
vec3 p2 = shape.vertices[face[i2]];
|
||||||
|
faceTangent = glm::normalize(p1 - p2);
|
||||||
|
if (shape.texCoords[f * N + i1].x < shape.texCoords[f * N + i2].x) {
|
||||||
|
faceTangent *= -1.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Create the vertices for the face
|
// Create the vertices for the face
|
||||||
for (Index i = 0; i < N; i++) {
|
for (Index i = 0; i < N; i++) {
|
||||||
Index originalIndex = face[i];
|
Index originalIndex = face[i];
|
||||||
vertices.push_back(shape.vertices[originalIndex]);
|
vertices.emplace_back(shape.vertices[originalIndex], faceNormal, shape.texCoords[f * N + i], faceTangent);
|
||||||
vertices.push_back(faceNormal);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the wire indices for unseen edges
|
// Create the wire indices for unseen edges
|
||||||
|
@ -316,21 +350,95 @@ void setupFlatShape(GeometryCache::ShapeData& shapeData, const geometry::Solid<N
|
||||||
shapeData.setupIndices(indexBuffer, solidIndices, wireIndices);
|
shapeData.setupIndices(indexBuffer, solidIndices, wireIndices);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vec2 calculateSphereTexCoord(const vec3& vertex) {
|
||||||
|
float u = 1.0f - (std::atan2(-vertex.z, -vertex.x) / ((float)M_PI) + 1.0f) * 0.5f;
|
||||||
|
if (vertex.y == 1.0f || vertex.y == -1.0f) {
|
||||||
|
// Remember points at the top so we don't treat them as being along the seam
|
||||||
|
u = NAN;
|
||||||
|
}
|
||||||
|
float v = 0.5f - std::asin(vertex.y) / (float)M_PI;
|
||||||
|
return vec2(u, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
const float M_PI_TIMES_2 = 2.0f * (float)M_PI;
|
||||||
|
|
||||||
|
vec3 calculateSphereTangent(float u) {
|
||||||
|
float phi = u * M_PI_TIMES_2;
|
||||||
|
return -glm::normalize(glm::vec3(glm::sin(phi), 0.0f, glm::cos(phi)));
|
||||||
|
}
|
||||||
|
|
||||||
template <size_t N>
|
template <size_t N>
|
||||||
void setupSmoothShape(GeometryCache::ShapeData& shapeData, const geometry::Solid<N>& shape, gpu::BufferPointer& vertexBuffer, gpu::BufferPointer& indexBuffer) {
|
void setupSmoothShape(GeometryCache::ShapeData& shapeData, const geometry::Solid<N>& shape, gpu::BufferPointer& vertexBuffer, gpu::BufferPointer& indexBuffer) {
|
||||||
using namespace geometry;
|
using namespace geometry;
|
||||||
|
|
||||||
VertexVector vertices;
|
std::vector<GeometryCache::ShapeVertex> vertices;
|
||||||
vertices.reserve(shape.vertices.size() * 2);
|
vertices.reserve(shape.vertices.size());
|
||||||
for (const auto& vertex : shape.vertices) {
|
for (const auto& vertex : shape.vertices) {
|
||||||
vertices.push_back(vertex);
|
// We'll fill in the correct tangents later, once we correct the UVs
|
||||||
vertices.push_back(vertex);
|
vertices.emplace_back(vertex, vertex, calculateSphereTexCoord(vertex), vec3(0.0f));
|
||||||
|
}
|
||||||
|
|
||||||
|
// We need to fix up the sphere's UVs because it's actually a tesselated icosahedron. See http://mft-dev.dk/uv-mapping-sphere/
|
||||||
|
size_t faceCount = shape.faces.size();
|
||||||
|
for (size_t f = 0; f < faceCount; f++) {
|
||||||
|
// Fix zipper
|
||||||
|
{
|
||||||
|
float& u1 = vertices[shape.faces[f][0]].uv.x;
|
||||||
|
float& u2 = vertices[shape.faces[f][1]].uv.x;
|
||||||
|
float& u3 = vertices[shape.faces[f][2]].uv.x;
|
||||||
|
|
||||||
|
if (glm::isnan(u1)) {
|
||||||
|
u1 = (u2 + u3) / 2.0f;
|
||||||
|
}
|
||||||
|
if (glm::isnan(u2)) {
|
||||||
|
u2 = (u1 + u3) / 2.0f;
|
||||||
|
}
|
||||||
|
if (glm::isnan(u3)) {
|
||||||
|
u3 = (u1 + u2) / 2.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
const float U_THRESHOLD = 0.25f;
|
||||||
|
float max = glm::max(u1, glm::max(u2, u3));
|
||||||
|
float min = glm::min(u1, glm::min(u2, u3));
|
||||||
|
|
||||||
|
if (max - min > U_THRESHOLD) {
|
||||||
|
if (u1 < U_THRESHOLD) {
|
||||||
|
u1 += 1.0f;
|
||||||
|
}
|
||||||
|
if (u2 < U_THRESHOLD) {
|
||||||
|
u2 += 1.0f;
|
||||||
|
}
|
||||||
|
if (u3 < U_THRESHOLD) {
|
||||||
|
u3 += 1.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fix swirling at poles
|
||||||
|
for (Index i = 0; i < N; i++) {
|
||||||
|
Index originalIndex = shape.faces[f][i];
|
||||||
|
if (shape.vertices[originalIndex].y == 1.0f || shape.vertices[originalIndex].y == -1.0f) {
|
||||||
|
float uSum = 0.0f;
|
||||||
|
for (Index i2 = 1; i2 <= N - 1; i2++) {
|
||||||
|
float u = vertices[shape.faces[f][(i + i2) % N]].uv.x;
|
||||||
|
uSum += u;
|
||||||
|
}
|
||||||
|
uSum /= (float)(N - 1);
|
||||||
|
vertices[originalIndex].uv.x = uSum;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill in tangents
|
||||||
|
for (Index i = 0; i < N; i++) {
|
||||||
|
vec3 tangent = calculateSphereTangent(vertices[shape.faces[f][i]].uv.x);
|
||||||
|
vertices[shape.faces[f][i]].tangent = tangent;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IndexVector solidIndices, wireIndices;
|
IndexVector solidIndices, wireIndices;
|
||||||
IndexPairs wireSeenIndices;
|
IndexPairs wireSeenIndices;
|
||||||
|
|
||||||
size_t faceCount = shape.faces.size();
|
|
||||||
size_t faceIndexCount = triangulatedFaceIndexCount<N>();
|
size_t faceIndexCount = triangulatedFaceIndexCount<N>();
|
||||||
|
|
||||||
solidIndices.reserve(faceIndexCount * faceCount);
|
solidIndices.reserve(faceIndexCount * faceCount);
|
||||||
|
@ -365,25 +473,22 @@ void setupSmoothShape(GeometryCache::ShapeData& shapeData, const geometry::Solid
|
||||||
template <uint32_t N>
|
template <uint32_t N>
|
||||||
void extrudePolygon(GeometryCache::ShapeData& shapeData, gpu::BufferPointer& vertexBuffer, gpu::BufferPointer& indexBuffer, bool isConical = false) {
|
void extrudePolygon(GeometryCache::ShapeData& shapeData, gpu::BufferPointer& vertexBuffer, gpu::BufferPointer& indexBuffer, bool isConical = false) {
|
||||||
using namespace geometry;
|
using namespace geometry;
|
||||||
VertexVector vertices;
|
std::vector<GeometryCache::ShapeVertex> vertices;
|
||||||
IndexVector solidIndices, wireIndices;
|
IndexVector solidIndices, wireIndices;
|
||||||
|
|
||||||
// Top (if not conical) and bottom faces
|
// Top (if not conical) and bottom faces
|
||||||
std::vector<vec3> shape = polygon<N>();
|
std::vector<vec3> shape = polygon<N>();
|
||||||
if (isConical) {
|
if (isConical) {
|
||||||
for (uint32_t i = 0; i < N; i++) {
|
for (uint32_t i = 0; i < N; i++) {
|
||||||
vertices.push_back(vec3(0.0f, 0.5f, 0.0f));
|
vertices.emplace_back(vec3(0.0f, 0.5f, 0.0f), vec3(0.0f, 1.0f, 0.0f), vec2((float)i / (float)N, 1.0f), vec3(0.0f));
|
||||||
vertices.push_back(vec3(0.0f, 1.0f, 0.0f));
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (const vec3& v : shape) {
|
for (const vec3& v : shape) {
|
||||||
vertices.push_back(vec3(v.x, 0.5f, v.z));
|
vertices.emplace_back(vec3(v.x, 0.5f, v.z), vec3(0.0f, 1.0f, 0.0f), vec2(v.x, v.z) + vec2(0.5f), vec3(1.0f, 0.0f, 0.0f));
|
||||||
vertices.push_back(vec3(0.0f, 1.0f, 0.0f));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (const vec3& v : shape) {
|
for (const vec3& v : shape) {
|
||||||
vertices.push_back(vec3(v.x, -0.5f, v.z));
|
vertices.emplace_back(vec3(v.x, -0.5f, v.z), vec3(0.0f, -1.0f, 0.0f), vec2(-v.x, v.z) + vec2(0.5f), vec3(-1.0f, 0.0f, 0.0f));
|
||||||
vertices.push_back(vec3(0.0f, -1.0f, 0.0f));
|
|
||||||
}
|
}
|
||||||
Index baseVertex = 0;
|
Index baseVertex = 0;
|
||||||
for (uint32_t i = 2; i < N; i++) {
|
for (uint32_t i = 2; i < N; i++) {
|
||||||
|
@ -412,15 +517,16 @@ void extrudePolygon(GeometryCache::ShapeData& shapeData, gpu::BufferPointer& ver
|
||||||
vec3 topRight = (isConical ? vec3(0.0f, 0.5f, 0.0f) : vec3(right.x, 0.5f, right.z));
|
vec3 topRight = (isConical ? vec3(0.0f, 0.5f, 0.0f) : vec3(right.x, 0.5f, right.z));
|
||||||
vec3 bottomLeft = vec3(left.x, -0.5f, left.z);
|
vec3 bottomLeft = vec3(left.x, -0.5f, left.z);
|
||||||
vec3 bottomRight = vec3(right.x, -0.5f, right.z);
|
vec3 bottomRight = vec3(right.x, -0.5f, right.z);
|
||||||
|
vec3 tangent = glm::normalize(bottomLeft - bottomRight);
|
||||||
|
|
||||||
vertices.push_back(topLeft);
|
// Our tex coords go in the opposite direction as our vertices
|
||||||
vertices.push_back(normal);
|
float u = 1.0f - (float)i / (float)N;
|
||||||
vertices.push_back(bottomLeft);
|
float u2 = 1.0f - (float)(i + 1) / (float)N;
|
||||||
vertices.push_back(normal);
|
|
||||||
vertices.push_back(topRight);
|
vertices.emplace_back(topLeft, normal, vec2(u, 0.0f), tangent);
|
||||||
vertices.push_back(normal);
|
vertices.emplace_back(bottomLeft, normal, vec2(u, 1.0f), tangent);
|
||||||
vertices.push_back(bottomRight);
|
vertices.emplace_back(topRight, normal, vec2(u2, 0.0f), tangent);
|
||||||
vertices.push_back(normal);
|
vertices.emplace_back(bottomRight, normal, vec2(u2, 1.0f), tangent);
|
||||||
|
|
||||||
solidIndices.push_back(baseVertex + 0);
|
solidIndices.push_back(baseVertex + 0);
|
||||||
solidIndices.push_back(baseVertex + 2);
|
solidIndices.push_back(baseVertex + 2);
|
||||||
|
@ -439,41 +545,6 @@ void extrudePolygon(GeometryCache::ShapeData& shapeData, gpu::BufferPointer& ver
|
||||||
shapeData.setupIndices(indexBuffer, solidIndices, wireIndices);
|
shapeData.setupIndices(indexBuffer, solidIndices, wireIndices);
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawCircle(GeometryCache::ShapeData& shapeData, gpu::BufferPointer& vertexBuffer, gpu::BufferPointer& indexBuffer) {
|
|
||||||
// Draw a circle with radius 1/4th the size of the bounding box
|
|
||||||
using namespace geometry;
|
|
||||||
|
|
||||||
VertexVector vertices;
|
|
||||||
IndexVector solidIndices, wireIndices;
|
|
||||||
const int NUM_CIRCLE_VERTICES = 64;
|
|
||||||
|
|
||||||
std::vector<vec3> shape = polygon<NUM_CIRCLE_VERTICES>();
|
|
||||||
for (const vec3& v : shape) {
|
|
||||||
vertices.push_back(vec3(v.x, 0.0f, v.z));
|
|
||||||
vertices.push_back(vec3(0.0f, 0.0f, 0.0f));
|
|
||||||
}
|
|
||||||
|
|
||||||
Index baseVertex = 0;
|
|
||||||
for (uint32_t i = 2; i < NUM_CIRCLE_VERTICES; i++) {
|
|
||||||
solidIndices.push_back(baseVertex + 0);
|
|
||||||
solidIndices.push_back(baseVertex + i);
|
|
||||||
solidIndices.push_back(baseVertex + i - 1);
|
|
||||||
solidIndices.push_back(baseVertex + NUM_CIRCLE_VERTICES);
|
|
||||||
solidIndices.push_back(baseVertex + i + NUM_CIRCLE_VERTICES - 1);
|
|
||||||
solidIndices.push_back(baseVertex + i + NUM_CIRCLE_VERTICES);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (uint32_t i = 1; i <= NUM_CIRCLE_VERTICES; i++) {
|
|
||||||
wireIndices.push_back(baseVertex + (i % NUM_CIRCLE_VERTICES));
|
|
||||||
wireIndices.push_back(baseVertex + i - 1);
|
|
||||||
wireIndices.push_back(baseVertex + (i % NUM_CIRCLE_VERTICES) + NUM_CIRCLE_VERTICES);
|
|
||||||
wireIndices.push_back(baseVertex + (i - 1) + NUM_CIRCLE_VERTICES);
|
|
||||||
}
|
|
||||||
|
|
||||||
shapeData.setupVertices(vertexBuffer, vertices);
|
|
||||||
shapeData.setupIndices(indexBuffer, solidIndices, wireIndices);
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME solids need per-face vertices, but smooth shaded
|
// FIXME solids need per-face vertices, but smooth shaded
|
||||||
// components do not. Find a way to support using draw elements
|
// components do not. Find a way to support using draw elements
|
||||||
// or draw arrays as appropriate
|
// or draw arrays as appropriate
|
||||||
|
@ -506,9 +577,9 @@ void GeometryCache::buildShapes() {
|
||||||
// Line
|
// Line
|
||||||
{
|
{
|
||||||
ShapeData& shapeData = _shapes[Line];
|
ShapeData& shapeData = _shapes[Line];
|
||||||
shapeData.setupVertices(_shapeVertices, VertexVector {
|
shapeData.setupVertices(_shapeVertices, std::vector<ShapeVertex> {
|
||||||
vec3(-0.5f, 0.0f, 0.0f), vec3(-0.5f, 0.0f, 0.0f),
|
ShapeVertex(vec3(-0.5f, 0.0f, 0.0f), vec3(-0.5f, 0.0f, 0.0f), vec2(0.0f, 0.0f), vec3(0.0f, 0.0f, 0.0f)),
|
||||||
vec3(0.5f, 0.0f, 0.0f), vec3(0.5f, 0.0f, 0.0f)
|
ShapeVertex(vec3(0.5f, 0.0f, 0.0f), vec3(0.5f, 0.0f, 0.0f), vec2(0.0f, 0.0f), vec3(0.0f, 0.0f, 0.0f))
|
||||||
});
|
});
|
||||||
IndexVector wireIndices;
|
IndexVector wireIndices;
|
||||||
// Only two indices
|
// Only two indices
|
||||||
|
@ -572,6 +643,8 @@ gpu::Stream::FormatPointer& getSolidStreamFormat() {
|
||||||
SOLID_STREAM_FORMAT = std::make_shared<gpu::Stream::Format>(); // 1 for everyone
|
SOLID_STREAM_FORMAT = std::make_shared<gpu::Stream::Format>(); // 1 for everyone
|
||||||
SOLID_STREAM_FORMAT->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, POSITION_ELEMENT);
|
SOLID_STREAM_FORMAT->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, POSITION_ELEMENT);
|
||||||
SOLID_STREAM_FORMAT->setAttribute(gpu::Stream::NORMAL, gpu::Stream::NORMAL, NORMAL_ELEMENT);
|
SOLID_STREAM_FORMAT->setAttribute(gpu::Stream::NORMAL, gpu::Stream::NORMAL, NORMAL_ELEMENT);
|
||||||
|
SOLID_STREAM_FORMAT->setAttribute(gpu::Stream::TEXCOORD0, gpu::Stream::TEXCOORD0, TEXCOORD0_ELEMENT);
|
||||||
|
SOLID_STREAM_FORMAT->setAttribute(gpu::Stream::TANGENT, gpu::Stream::TANGENT, TANGENT_ELEMENT);
|
||||||
}
|
}
|
||||||
return SOLID_STREAM_FORMAT;
|
return SOLID_STREAM_FORMAT;
|
||||||
}
|
}
|
||||||
|
@ -581,6 +654,8 @@ gpu::Stream::FormatPointer& getInstancedSolidStreamFormat() {
|
||||||
INSTANCED_SOLID_STREAM_FORMAT = std::make_shared<gpu::Stream::Format>(); // 1 for everyone
|
INSTANCED_SOLID_STREAM_FORMAT = std::make_shared<gpu::Stream::Format>(); // 1 for everyone
|
||||||
INSTANCED_SOLID_STREAM_FORMAT->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, POSITION_ELEMENT);
|
INSTANCED_SOLID_STREAM_FORMAT->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, POSITION_ELEMENT);
|
||||||
INSTANCED_SOLID_STREAM_FORMAT->setAttribute(gpu::Stream::NORMAL, gpu::Stream::NORMAL, NORMAL_ELEMENT);
|
INSTANCED_SOLID_STREAM_FORMAT->setAttribute(gpu::Stream::NORMAL, gpu::Stream::NORMAL, NORMAL_ELEMENT);
|
||||||
|
INSTANCED_SOLID_STREAM_FORMAT->setAttribute(gpu::Stream::TEXCOORD0, gpu::Stream::TEXCOORD0, TEXCOORD0_ELEMENT);
|
||||||
|
INSTANCED_SOLID_STREAM_FORMAT->setAttribute(gpu::Stream::TANGENT, gpu::Stream::TANGENT, TANGENT_ELEMENT);
|
||||||
INSTANCED_SOLID_STREAM_FORMAT->setAttribute(gpu::Stream::COLOR, gpu::Stream::COLOR, COLOR_ELEMENT, 0, gpu::Stream::PER_INSTANCE);
|
INSTANCED_SOLID_STREAM_FORMAT->setAttribute(gpu::Stream::COLOR, gpu::Stream::COLOR, COLOR_ELEMENT, 0, gpu::Stream::PER_INSTANCE);
|
||||||
}
|
}
|
||||||
return INSTANCED_SOLID_STREAM_FORMAT;
|
return INSTANCED_SOLID_STREAM_FORMAT;
|
||||||
|
@ -591,6 +666,8 @@ gpu::Stream::FormatPointer& getInstancedSolidFadeStreamFormat() {
|
||||||
INSTANCED_SOLID_FADE_STREAM_FORMAT = std::make_shared<gpu::Stream::Format>(); // 1 for everyone
|
INSTANCED_SOLID_FADE_STREAM_FORMAT = std::make_shared<gpu::Stream::Format>(); // 1 for everyone
|
||||||
INSTANCED_SOLID_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, POSITION_ELEMENT);
|
INSTANCED_SOLID_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, POSITION_ELEMENT);
|
||||||
INSTANCED_SOLID_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::NORMAL, gpu::Stream::NORMAL, NORMAL_ELEMENT);
|
INSTANCED_SOLID_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::NORMAL, gpu::Stream::NORMAL, NORMAL_ELEMENT);
|
||||||
|
INSTANCED_SOLID_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::TEXCOORD0, gpu::Stream::TEXCOORD0, TEXCOORD0_ELEMENT);
|
||||||
|
INSTANCED_SOLID_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::TANGENT, gpu::Stream::TANGENT, TANGENT_ELEMENT);
|
||||||
INSTANCED_SOLID_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::COLOR, gpu::Stream::COLOR, COLOR_ELEMENT, 0, gpu::Stream::PER_INSTANCE);
|
INSTANCED_SOLID_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::COLOR, gpu::Stream::COLOR, COLOR_ELEMENT, 0, gpu::Stream::PER_INSTANCE);
|
||||||
INSTANCED_SOLID_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::TEXCOORD2, gpu::Stream::TEXCOORD2, TEXCOORD4_ELEMENT, 0, gpu::Stream::PER_INSTANCE);
|
INSTANCED_SOLID_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::TEXCOORD2, gpu::Stream::TEXCOORD2, TEXCOORD4_ELEMENT, 0, gpu::Stream::PER_INSTANCE);
|
||||||
INSTANCED_SOLID_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::TEXCOORD3, gpu::Stream::TEXCOORD3, TEXCOORD4_ELEMENT, 0, gpu::Stream::PER_INSTANCE);
|
INSTANCED_SOLID_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::TEXCOORD3, gpu::Stream::TEXCOORD3, TEXCOORD4_ELEMENT, 0, gpu::Stream::PER_INSTANCE);
|
||||||
|
@ -893,6 +970,7 @@ void GeometryCache::updateVertices(int id, const QVector<glm::vec2>& points, con
|
||||||
|
|
||||||
details.streamFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::XYZ), 0);
|
details.streamFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::XYZ), 0);
|
||||||
details.streamFormat->setAttribute(gpu::Stream::NORMAL, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), VERTEX_NORMAL_OFFSET);
|
details.streamFormat->setAttribute(gpu::Stream::NORMAL, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), VERTEX_NORMAL_OFFSET);
|
||||||
|
// TODO: circle3D overlays use this to define their vertices, so they need tex coords
|
||||||
details.streamFormat->setAttribute(gpu::Stream::COLOR, 1, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA));
|
details.streamFormat->setAttribute(gpu::Stream::COLOR, 1, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA));
|
||||||
|
|
||||||
details.stream->addBuffer(details.verticesBuffer, 0, details.streamFormat->getChannels().at(0)._stride);
|
details.stream->addBuffer(details.verticesBuffer, 0, details.streamFormat->getChannels().at(0)._stride);
|
||||||
|
|
|
@ -354,13 +354,24 @@ public:
|
||||||
/// Set a batch to the simple pipeline, returning the previous pipeline
|
/// Set a batch to the simple pipeline, returning the previous pipeline
|
||||||
void useSimpleDrawPipeline(gpu::Batch& batch, bool noBlend = false);
|
void useSimpleDrawPipeline(gpu::Batch& batch, bool noBlend = false);
|
||||||
|
|
||||||
|
struct ShapeVertex {
|
||||||
|
ShapeVertex(const vec3& pos, const vec3& normal, const vec2& uv, const vec3& tangent) : pos(pos), normal(normal), uv(uv), tangent(tangent) {}
|
||||||
|
|
||||||
|
vec3 pos;
|
||||||
|
vec3 normal;
|
||||||
|
vec2 uv;
|
||||||
|
vec3 tangent;
|
||||||
|
};
|
||||||
|
|
||||||
struct ShapeData {
|
struct ShapeData {
|
||||||
gpu::BufferView _positionView;
|
gpu::BufferView _positionView;
|
||||||
gpu::BufferView _normalView;
|
gpu::BufferView _normalView;
|
||||||
|
gpu::BufferView _texCoordView;
|
||||||
|
gpu::BufferView _tangentView;
|
||||||
gpu::BufferView _indicesView;
|
gpu::BufferView _indicesView;
|
||||||
gpu::BufferView _wireIndicesView;
|
gpu::BufferView _wireIndicesView;
|
||||||
|
|
||||||
void setupVertices(gpu::BufferPointer& vertexBuffer, const geometry::VertexVector& vertices);
|
void setupVertices(gpu::BufferPointer& vertexBuffer, const std::vector<ShapeVertex>& vertices);
|
||||||
void setupIndices(gpu::BufferPointer& indexBuffer, const geometry::IndexVector& indices, const geometry::IndexVector& wireIndices);
|
void setupIndices(gpu::BufferPointer& indexBuffer, const geometry::IndexVector& indices, const geometry::IndexVector& wireIndices);
|
||||||
void setupBatch(gpu::Batch& batch) const;
|
void setupBatch(gpu::Batch& batch) const;
|
||||||
void draw(gpu::Batch& batch) const;
|
void draw(gpu::Batch& batch) const;
|
||||||
|
|
|
@ -218,25 +218,25 @@ vec3 fetchLightmapMap(vec2 uv) {
|
||||||
}
|
}
|
||||||
<@endfunc@>
|
<@endfunc@>
|
||||||
|
|
||||||
<@func tangentToViewSpace(fetchedNormal, interpolatedNormal, interpolatedTangent, normal)@>
|
<@func evalMaterialNormal(fetchedNormal, interpolatedNormal, interpolatedTangent, normal)@>
|
||||||
{
|
{
|
||||||
vec3 normalizedNormal = normalize(<$interpolatedNormal$>.xyz);
|
vec3 normalizedNormal = normalize(<$interpolatedNormal$>.xyz);
|
||||||
vec3 normalizedTangent = normalize(<$interpolatedTangent$>.xyz);
|
vec3 normalizedTangent = normalize(<$interpolatedTangent$>.xyz);
|
||||||
vec3 normalizedBitangent = normalize(cross(normalizedNormal, normalizedTangent));
|
vec3 normalizedBitangent = cross(normalizedNormal, normalizedTangent);
|
||||||
vec3 localNormal = <$fetchedNormal$>;
|
vec3 localNormal = <$fetchedNormal$>;
|
||||||
<$normal$> = vec3(normalizedTangent * localNormal.x + normalizedNormal * localNormal.y + normalizedBitangent * localNormal.z);
|
<$normal$> = vec3(normalizedBitangent * localNormal.x + normalizedNormal * localNormal.y + normalizedTangent * localNormal.z);
|
||||||
}
|
}
|
||||||
<@endfunc@>
|
<@endfunc@>
|
||||||
|
|
||||||
<@func tangentToViewSpaceLOD(fragPos, fetchedNormal, interpolatedNormal, interpolatedTangent, normal)@>
|
<@func evalMaterialNormalLOD(fragPos, fetchedNormal, interpolatedNormal, interpolatedTangent, normal)@>
|
||||||
{
|
{
|
||||||
vec3 normalizedNormal = normalize(<$interpolatedNormal$>.xyz);
|
vec3 normalizedNormal = normalize(<$interpolatedNormal$>.xyz);
|
||||||
vec3 normalizedTangent = normalize(<$interpolatedTangent$>.xyz);
|
vec3 normalizedTangent = normalize(<$interpolatedTangent$>.xyz);
|
||||||
vec3 normalizedBitangent = normalize(cross(normalizedNormal, normalizedTangent));
|
vec3 normalizedBitangent = cross(normalizedNormal, normalizedTangent);
|
||||||
// attenuate the normal map divergence from the mesh normal based on distance
|
// attenuate the normal map divergence from the mesh normal based on distance
|
||||||
// THe attenuation range [20,100] meters from the eye is arbitrary for now
|
// The attenuation range [20,100] meters from the eye is arbitrary for now
|
||||||
vec3 localNormal = mix(<$fetchedNormal$>, vec3(0.0, 1.0, 0.0), smoothstep(20.0, 100.0, (-<$fragPos$>).z));
|
vec3 localNormal = mix(<$fetchedNormal$>, vec3(0.0, 1.0, 0.0), smoothstep(20.0, 100.0, (-<$fragPos$>).z));
|
||||||
<$normal$> = vec3(normalizedTangent * localNormal.x + normalizedNormal * localNormal.y + normalizedBitangent * localNormal.z);
|
<$normal$> = vec3(normalizedBitangent * localNormal.x + normalizedNormal * localNormal.y + normalizedTangent * localNormal.z);
|
||||||
}
|
}
|
||||||
<@endfunc@>
|
<@endfunc@>
|
||||||
|
|
||||||
|
|
|
@ -47,6 +47,8 @@ template <> void payloadRender(const MeshPartPayload::Pointer& payload, RenderAr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const graphics::MaterialPointer MeshPartPayload::DEFAULT_MATERIAL = std::make_shared<graphics::Material>();
|
||||||
|
|
||||||
MeshPartPayload::MeshPartPayload(const std::shared_ptr<const graphics::Mesh>& mesh, int partIndex, graphics::MaterialPointer material) {
|
MeshPartPayload::MeshPartPayload(const std::shared_ptr<const graphics::Mesh>& mesh, int partIndex, graphics::MaterialPointer material) {
|
||||||
updateMeshPart(mesh, partIndex);
|
updateMeshPart(mesh, partIndex);
|
||||||
addMaterial(graphics::MaterialLayer(material, 0));
|
addMaterial(graphics::MaterialLayer(material, 0));
|
||||||
|
@ -99,7 +101,7 @@ void MeshPartPayload::updateKey(bool isVisible, bool isLayered, bool canCastShad
|
||||||
builder.withSubMetaCulled();
|
builder.withSubMetaCulled();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_drawMaterials.top().material) {
|
if (topMaterialExists()) {
|
||||||
auto matKey = _drawMaterials.top().material->getKey();
|
auto matKey = _drawMaterials.top().material->getKey();
|
||||||
if (matKey.isTranslucent()) {
|
if (matKey.isTranslucent()) {
|
||||||
builder.withTransparent();
|
builder.withTransparent();
|
||||||
|
@ -119,7 +121,7 @@ Item::Bound MeshPartPayload::getBound() const {
|
||||||
|
|
||||||
ShapeKey MeshPartPayload::getShapeKey() const {
|
ShapeKey MeshPartPayload::getShapeKey() const {
|
||||||
graphics::MaterialKey drawMaterialKey;
|
graphics::MaterialKey drawMaterialKey;
|
||||||
if (_drawMaterials.top().material) {
|
if (topMaterialExists()) {
|
||||||
drawMaterialKey = _drawMaterials.top().material->getKey();
|
drawMaterialKey = _drawMaterials.top().material->getKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,7 +173,7 @@ void MeshPartPayload::render(RenderArgs* args) {
|
||||||
bindMesh(batch);
|
bindMesh(batch);
|
||||||
|
|
||||||
// apply material properties
|
// apply material properties
|
||||||
RenderPipelines::bindMaterial(_drawMaterials.top().material, batch, args->_enableTexturing);
|
RenderPipelines::bindMaterial(!_drawMaterials.empty() ? _drawMaterials.top().material : DEFAULT_MATERIAL, batch, args->_enableTexturing);
|
||||||
args->_details._materialSwitches++;
|
args->_details._materialSwitches++;
|
||||||
|
|
||||||
// Draw!
|
// Draw!
|
||||||
|
@ -356,7 +358,7 @@ void ModelMeshPartPayload::updateKey(bool isVisible, bool isLayered, bool canCas
|
||||||
builder.withDeformed();
|
builder.withDeformed();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_drawMaterials.top().material) {
|
if (topMaterialExists()) {
|
||||||
auto matKey = _drawMaterials.top().material->getKey();
|
auto matKey = _drawMaterials.top().material->getKey();
|
||||||
if (matKey.isTranslucent()) {
|
if (matKey.isTranslucent()) {
|
||||||
builder.withTransparent();
|
builder.withTransparent();
|
||||||
|
@ -387,7 +389,7 @@ void ModelMeshPartPayload::setShapeKey(bool invalidateShapeKey, bool isWireframe
|
||||||
}
|
}
|
||||||
|
|
||||||
graphics::MaterialKey drawMaterialKey;
|
graphics::MaterialKey drawMaterialKey;
|
||||||
if (_drawMaterials.top().material) {
|
if (topMaterialExists()) {
|
||||||
drawMaterialKey = _drawMaterials.top().material->getKey();
|
drawMaterialKey = _drawMaterials.top().material->getKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -469,7 +471,7 @@ void ModelMeshPartPayload::render(RenderArgs* args) {
|
||||||
bindMesh(batch);
|
bindMesh(batch);
|
||||||
|
|
||||||
// apply material properties
|
// apply material properties
|
||||||
RenderPipelines::bindMaterial(_drawMaterials.top().material, batch, args->_enableTexturing);
|
RenderPipelines::bindMaterial(!_drawMaterials.empty() ? _drawMaterials.top().material : DEFAULT_MATERIAL, batch, args->_enableTexturing);
|
||||||
args->_details._materialSwitches++;
|
args->_details._materialSwitches++;
|
||||||
|
|
||||||
// Draw!
|
// Draw!
|
||||||
|
|
|
@ -65,15 +65,18 @@ public:
|
||||||
graphics::Mesh::Part _drawPart;
|
graphics::Mesh::Part _drawPart;
|
||||||
|
|
||||||
size_t getVerticesCount() const { return _drawMesh ? _drawMesh->getNumVertices() : 0; }
|
size_t getVerticesCount() const { return _drawMesh ? _drawMesh->getNumVertices() : 0; }
|
||||||
size_t getMaterialTextureSize() { return _drawMaterials.top().material ? _drawMaterials.top().material->getTextureSize() : 0; }
|
size_t getMaterialTextureSize() { return topMaterialExists() ? _drawMaterials.top().material->getTextureSize() : 0; }
|
||||||
int getMaterialTextureCount() { return _drawMaterials.top().material ? _drawMaterials.top().material->getTextureCount() : 0; }
|
int getMaterialTextureCount() { return topMaterialExists() ? _drawMaterials.top().material->getTextureCount() : 0; }
|
||||||
bool hasTextureInfo() const { return _drawMaterials.top().material ? _drawMaterials.top().material->hasTextureInfo() : false; }
|
bool hasTextureInfo() const { return topMaterialExists() ? _drawMaterials.top().material->hasTextureInfo() : false; }
|
||||||
|
|
||||||
void addMaterial(graphics::MaterialLayer material);
|
void addMaterial(graphics::MaterialLayer material);
|
||||||
void removeMaterial(graphics::MaterialPointer material);
|
void removeMaterial(graphics::MaterialPointer material);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
static const graphics::MaterialPointer DEFAULT_MATERIAL;
|
||||||
render::ItemKey _itemKey{ render::ItemKey::Builder::opaqueShape().build() };
|
render::ItemKey _itemKey{ render::ItemKey::Builder::opaqueShape().build() };
|
||||||
|
|
||||||
|
bool topMaterialExists() const { return !_drawMaterials.empty() && _drawMaterials.top().material; }
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace render {
|
namespace render {
|
||||||
|
|
|
@ -1604,7 +1604,8 @@ void Model::createVisibleRenderItemSet() {
|
||||||
int numParts = (int)mesh->getNumParts();
|
int numParts = (int)mesh->getNumParts();
|
||||||
for (int partIndex = 0; partIndex < numParts; partIndex++) {
|
for (int partIndex = 0; partIndex < numParts; partIndex++) {
|
||||||
_modelMeshRenderItems << std::make_shared<ModelMeshPartPayload>(shared_from_this(), i, partIndex, shapeID, transform, offset);
|
_modelMeshRenderItems << std::make_shared<ModelMeshPartPayload>(shared_from_this(), i, partIndex, shapeID, transform, offset);
|
||||||
_modelMeshMaterialNames.push_back(getGeometry()->getShapeMaterial(shapeID)->getName());
|
auto material = getGeometry()->getShapeMaterial(shapeID);
|
||||||
|
_modelMeshMaterialNames.push_back(material ? material->getName() : "");
|
||||||
_modelMeshRenderItemShapes.emplace_back(ShapeInfo{ (int)i });
|
_modelMeshRenderItemShapes.emplace_back(ShapeInfo{ (int)i });
|
||||||
shapeID++;
|
shapeID++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,7 +58,7 @@ void main(void) {
|
||||||
|
|
||||||
vec3 fragPosition = _position.xyz;
|
vec3 fragPosition = _position.xyz;
|
||||||
vec3 fragNormal;
|
vec3 fragNormal;
|
||||||
<$tangentToViewSpace(normalTex, _normal, _tangent, fragNormal)$>
|
<$evalMaterialNormal(normalTex, _normal, _tangent, fragNormal)$>
|
||||||
|
|
||||||
TransformCamera cam = getTransformCamera();
|
TransformCamera cam = getTransformCamera();
|
||||||
|
|
||||||
|
|
|
@ -33,11 +33,11 @@ void main(void) {
|
||||||
<$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedo, roughness, normalTexel, metallicTex)$>
|
<$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedo, roughness, normalTexel, metallicTex)$>
|
||||||
<$fetchMaterialTexturesCoord1(matKey, _texCoord1, _SCRIBE_NULL, lightmapVal)$>
|
<$fetchMaterialTexturesCoord1(matKey, _texCoord1, _SCRIBE_NULL, lightmapVal)$>
|
||||||
|
|
||||||
vec3 viewNormal;
|
vec3 fragNormal;
|
||||||
<$tangentToViewSpaceLOD(_position, normalTexel, _normal, _tangent, viewNormal)$>
|
<$evalMaterialNormalLOD(_position, normalTexel, _normal, _tangent, fragNormal)$>
|
||||||
|
|
||||||
packDeferredFragmentLightmap(
|
packDeferredFragmentLightmap(
|
||||||
normalize(viewNormal.xyz),
|
normalize(fragNormal.xyz),
|
||||||
evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedo.a),
|
evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedo.a),
|
||||||
getMaterialAlbedo(mat) * albedo.rgb * _color,
|
getMaterialAlbedo(mat) * albedo.rgb * _color,
|
||||||
getMaterialRoughness(mat) * roughness,
|
getMaterialRoughness(mat) * roughness,
|
||||||
|
|
|
@ -43,11 +43,11 @@ void main(void) {
|
||||||
<$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedo, roughness, normalTexel, metallicTex)$>
|
<$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedo, roughness, normalTexel, metallicTex)$>
|
||||||
<$fetchMaterialTexturesCoord1(matKey, _texCoord1, _SCRIBE_NULL, lightmapVal)$>
|
<$fetchMaterialTexturesCoord1(matKey, _texCoord1, _SCRIBE_NULL, lightmapVal)$>
|
||||||
|
|
||||||
vec3 viewNormal;
|
vec3 fragNormal;
|
||||||
<$tangentToViewSpaceLOD(_position, normalTexel, _normal, _tangent, viewNormal)$>
|
<$evalMaterialNormalLOD(_position, normalTexel, _normal, _tangent, fragNormal)$>
|
||||||
|
|
||||||
packDeferredFragmentLightmap(
|
packDeferredFragmentLightmap(
|
||||||
normalize(viewNormal.xyz),
|
normalize(fragNormal.xyz),
|
||||||
evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedo.a),
|
evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedo.a),
|
||||||
getMaterialAlbedo(mat) * albedo.rgb * _color,
|
getMaterialAlbedo(mat) * albedo.rgb * _color,
|
||||||
getMaterialRoughness(mat) * roughness,
|
getMaterialRoughness(mat) * roughness,
|
||||||
|
|
|
@ -46,8 +46,8 @@ void main(void) {
|
||||||
vec3 emissive = getMaterialEmissive(mat);
|
vec3 emissive = getMaterialEmissive(mat);
|
||||||
<$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>;
|
<$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>;
|
||||||
|
|
||||||
vec3 viewNormal;
|
vec3 fragNormal;
|
||||||
<$tangentToViewSpaceLOD(_position, normalTex, _normal, _tangent, viewNormal)$>
|
<$evalMaterialNormalLOD(_position, normalTex, _normal, _tangent, fragNormal)$>
|
||||||
|
|
||||||
float metallic = getMaterialMetallic(mat);
|
float metallic = getMaterialMetallic(mat);
|
||||||
<$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>;
|
<$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>;
|
||||||
|
@ -56,7 +56,7 @@ void main(void) {
|
||||||
<$evalMaterialScattering(scatteringTex, scattering, matKey, scattering)$>;
|
<$evalMaterialScattering(scatteringTex, scattering, matKey, scattering)$>;
|
||||||
|
|
||||||
packDeferredFragment(
|
packDeferredFragment(
|
||||||
normalize(viewNormal.xyz),
|
normalize(fragNormal.xyz),
|
||||||
opacity,
|
opacity,
|
||||||
albedo,
|
albedo,
|
||||||
roughness,
|
roughness,
|
||||||
|
|
|
@ -56,8 +56,8 @@ void main(void) {
|
||||||
vec3 emissive = getMaterialEmissive(mat);
|
vec3 emissive = getMaterialEmissive(mat);
|
||||||
<$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>;
|
<$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>;
|
||||||
|
|
||||||
vec3 viewNormal;
|
vec3 fragNormal;
|
||||||
<$tangentToViewSpaceLOD(_position, normalTex, _normal, _tangent, viewNormal)$>
|
<$evalMaterialNormalLOD(_position, normalTex, _normal, _tangent, fragNormal)$>
|
||||||
|
|
||||||
float metallic = getMaterialMetallic(mat);
|
float metallic = getMaterialMetallic(mat);
|
||||||
<$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>;
|
<$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>;
|
||||||
|
@ -65,7 +65,7 @@ void main(void) {
|
||||||
float scattering = getMaterialScattering(mat);
|
float scattering = getMaterialScattering(mat);
|
||||||
|
|
||||||
packDeferredFragment(
|
packDeferredFragment(
|
||||||
normalize(viewNormal.xyz),
|
normalize(fragNormal.xyz),
|
||||||
opacity,
|
opacity,
|
||||||
albedo,
|
albedo,
|
||||||
roughness,
|
roughness,
|
||||||
|
|
|
@ -61,7 +61,7 @@ void main(void) {
|
||||||
|
|
||||||
vec3 fragPosition = _position.xyz;
|
vec3 fragPosition = _position.xyz;
|
||||||
vec3 fragNormal;
|
vec3 fragNormal;
|
||||||
<$tangentToViewSpaceLOD(_position, normalTex, _normal, _tangent, fragNormal)$>
|
<$evalMaterialNormalLOD(_position, normalTex, _normal, _tangent, fragNormal)$>
|
||||||
|
|
||||||
TransformCamera cam = getTransformCamera();
|
TransformCamera cam = getTransformCamera();
|
||||||
vec3 fragEyeVector = vec3(cam._viewInverse * vec4(-fragPosition, 0.0));
|
vec3 fragEyeVector = vec3(cam._viewInverse * vec4(-fragPosition, 0.0));
|
||||||
|
|
|
@ -71,7 +71,7 @@ void main(void) {
|
||||||
vec3 fragPosition = _position.xyz;
|
vec3 fragPosition = _position.xyz;
|
||||||
// Lighting is done in world space
|
// Lighting is done in world space
|
||||||
vec3 fragNormal;
|
vec3 fragNormal;
|
||||||
<$tangentToViewSpaceLOD(_position, normalTex, _normal, _tangent, fragNormal)$>
|
<$evalMaterialNormalLOD(_position, normalTex, _normal, _tangent, fragNormal)$>
|
||||||
|
|
||||||
TransformCamera cam = getTransformCamera();
|
TransformCamera cam = getTransformCamera();
|
||||||
vec3 fragEyeVector = vec3(cam._viewInverse * vec4(-fragPosition, 0.0));
|
vec3 fragEyeVector = vec3(cam._viewInverse * vec4(-fragPosition, 0.0));
|
||||||
|
|
|
@ -8,8 +8,11 @@
|
||||||
|
|
||||||
#include "Shapes.h"
|
#include "Shapes.h"
|
||||||
|
|
||||||
|
#include "qmath.h"
|
||||||
|
|
||||||
namespace geometry {
|
namespace geometry {
|
||||||
|
|
||||||
|
using glm::vec2;
|
||||||
using glm::vec3;
|
using glm::vec3;
|
||||||
|
|
||||||
// The golden ratio
|
// The golden ratio
|
||||||
|
@ -19,8 +22,8 @@ Solid<3> tesselate(const Solid<3>& solid_, int count) {
|
||||||
Solid<3> solid = solid_;
|
Solid<3> solid = solid_;
|
||||||
float length = glm::length(solid.vertices[0]);
|
float length = glm::length(solid.vertices[0]);
|
||||||
for (int i = 0; i < count; ++i) {
|
for (int i = 0; i < count; ++i) {
|
||||||
Solid<3> result { solid.vertices, {} };
|
Solid<3> result { solid.vertices, {}, {} };
|
||||||
result.vertices.reserve(solid.vertices.size() + solid.faces.size() * 3);
|
result.vertices.reserve(solid.vertices.size() + solid.faces.size() * 6);
|
||||||
for (size_t f = 0; f < solid.faces.size(); ++f) {
|
for (size_t f = 0; f < solid.faces.size(); ++f) {
|
||||||
Index baseVertex = (Index)result.vertices.size();
|
Index baseVertex = (Index)result.vertices.size();
|
||||||
const Face<3>& oldFace = solid.faces[f];
|
const Face<3>& oldFace = solid.faces[f];
|
||||||
|
@ -30,13 +33,26 @@ Solid<3> tesselate(const Solid<3>& solid_, int count) {
|
||||||
vec3 ab = glm::normalize(a + b) * length;
|
vec3 ab = glm::normalize(a + b) * length;
|
||||||
vec3 bc = glm::normalize(b + c) * length;
|
vec3 bc = glm::normalize(b + c) * length;
|
||||||
vec3 ca = glm::normalize(c + a) * length;
|
vec3 ca = glm::normalize(c + a) * length;
|
||||||
|
|
||||||
|
result.vertices.push_back(a);
|
||||||
|
result.vertices.push_back(ab);
|
||||||
|
result.vertices.push_back(ca);
|
||||||
|
result.faces.push_back(Face<3>{ { baseVertex, baseVertex + 1, baseVertex + 2 } });
|
||||||
|
|
||||||
|
result.vertices.push_back(ab);
|
||||||
|
result.vertices.push_back(b);
|
||||||
|
result.vertices.push_back(bc);
|
||||||
|
result.faces.push_back(Face<3>{ { baseVertex + 3, baseVertex + 4, baseVertex + 5 } });
|
||||||
|
|
||||||
|
result.vertices.push_back(bc);
|
||||||
|
result.vertices.push_back(c);
|
||||||
|
result.vertices.push_back(ca);
|
||||||
|
result.faces.push_back(Face<3>{ { baseVertex + 6, baseVertex + 7, baseVertex + 8 } });
|
||||||
|
|
||||||
result.vertices.push_back(ab);
|
result.vertices.push_back(ab);
|
||||||
result.vertices.push_back(bc);
|
result.vertices.push_back(bc);
|
||||||
result.vertices.push_back(ca);
|
result.vertices.push_back(ca);
|
||||||
result.faces.push_back(Face<3>{ { oldFace[0], baseVertex, baseVertex + 2 } });
|
result.faces.push_back(Face<3>{ { baseVertex + 9, baseVertex + 10, baseVertex + 11 } });
|
||||||
result.faces.push_back(Face<3>{ { baseVertex, oldFace[1], baseVertex + 1 } });
|
|
||||||
result.faces.push_back(Face<3>{ { baseVertex + 1, oldFace[2], baseVertex + 2 } });
|
|
||||||
result.faces.push_back(Face<3>{ { baseVertex, baseVertex + 1, baseVertex + 2 } });
|
|
||||||
}
|
}
|
||||||
solid = result;
|
solid = result;
|
||||||
}
|
}
|
||||||
|
@ -50,6 +66,10 @@ const Solid<3>& tetrahedron() {
|
||||||
static const auto D = vec3(-1, -1, 1);
|
static const auto D = vec3(-1, -1, 1);
|
||||||
static const Solid<3> TETRAHEDRON = Solid<3>{
|
static const Solid<3> TETRAHEDRON = Solid<3>{
|
||||||
{ A, B, C, D },
|
{ A, B, C, D },
|
||||||
|
{ vec2(0.75f, 0.5f), vec2(0.5f, 0.0f), vec2(0.25f, 0.5f),
|
||||||
|
vec2(0.5f, 1.0f), vec2(1.0f, 1.0f), vec2(0.75f, 0.5f),
|
||||||
|
vec2(0.25f, 0.5f), vec2(0.5f, 1.0f), vec2(0.75f, 0.5f),
|
||||||
|
vec2(0.25f, 0.5f), vec2(0.0f, 1.0f), vec2(0.5f, 1.0f) },
|
||||||
FaceVector<3>{
|
FaceVector<3>{
|
||||||
Face<3> { { 0, 1, 2 } },
|
Face<3> { { 0, 1, 2 } },
|
||||||
Face<3> { { 3, 1, 0 } },
|
Face<3> { { 3, 1, 0 } },
|
||||||
|
@ -65,8 +85,15 @@ const Solid<4>& cube() {
|
||||||
static const auto B = vec3(-1, 1, 1);
|
static const auto B = vec3(-1, 1, 1);
|
||||||
static const auto C = vec3(-1, 1, -1);
|
static const auto C = vec3(-1, 1, -1);
|
||||||
static const auto D = vec3(1, 1, -1);
|
static const auto D = vec3(1, 1, -1);
|
||||||
|
static const float THIRD = 1.0f / 3.0f;
|
||||||
static const Solid<4> CUBE = Solid<4>{
|
static const Solid<4> CUBE = Solid<4>{
|
||||||
{ A, B, C, D, -A, -B, -C, -D },
|
{ A, B, C, D, -A, -B, -C, -D },
|
||||||
|
{ vec2(0.5f, 0.0f), vec2(0.25f, 0.0f), vec2(0.25f, THIRD), vec2(0.5f, THIRD),
|
||||||
|
vec2(0.5f, THIRD), vec2(0.25f, THIRD), vec2(0.25f, 2.0f * THIRD), vec2(0.5f, 2.0f * THIRD),
|
||||||
|
vec2(0.25f, THIRD), vec2(0.0f, THIRD), vec2(0.0f, 2.0f * THIRD), vec2(0.25f, 2.0f * THIRD),
|
||||||
|
vec2(1.0f, THIRD), vec2(0.75f, THIRD), vec2(0.75f, 2.0f * THIRD), vec2(1.0f, 2.0f * THIRD),
|
||||||
|
vec2(0.75f, THIRD), vec2(0.5f, THIRD), vec2(0.5f, 2.0f * THIRD), vec2(0.75f, 2.0f * THIRD),
|
||||||
|
vec2(0.25f, 1.0f), vec2(0.5f, 1.0f), vec2(0.5f, 2.0f * THIRD), vec2(0.25f, 2.0f * THIRD) },
|
||||||
FaceVector<4>{
|
FaceVector<4>{
|
||||||
Face<4> { { 3, 2, 1, 0 } },
|
Face<4> { { 3, 2, 1, 0 } },
|
||||||
Face<4> { { 0, 1, 7, 6 } },
|
Face<4> { { 0, 1, 7, 6 } },
|
||||||
|
@ -86,8 +113,18 @@ const Solid<3>& octahedron() {
|
||||||
static const auto D = vec3(0, 0, -1);
|
static const auto D = vec3(0, 0, -1);
|
||||||
static const auto E = vec3(1, 0, 0);
|
static const auto E = vec3(1, 0, 0);
|
||||||
static const auto F = vec3(-1, 0, 0);
|
static const auto F = vec3(-1, 0, 0);
|
||||||
|
static const float THIRD = 1.0f / 3.0f;
|
||||||
|
static const float SEVENTH = 1.0f / 7.0f;
|
||||||
static const Solid<3> OCTAHEDRON = Solid<3>{
|
static const Solid<3> OCTAHEDRON = Solid<3>{
|
||||||
{ A, B, C, D, E, F},
|
{ A, B, C, D, E, F},
|
||||||
|
{ vec2(2.0f * SEVENTH, THIRD), vec2(SEVENTH, 2.0f * THIRD), vec2(3.0f * SEVENTH, 2.0f * THIRD),
|
||||||
|
vec2(2.0f * SEVENTH, THIRD), vec2(3.0f * SEVENTH, 2.0f * THIRD), vec2(4.0f * SEVENTH, THIRD),
|
||||||
|
vec2(5.0f * SEVENTH, 0.0f), vec2(4.0f * SEVENTH, THIRD), vec2(6.0f * SEVENTH, THIRD),
|
||||||
|
vec2(2.0f * SEVENTH, THIRD), vec2(0.0f, THIRD), vec2(1.0f * SEVENTH, 2.0f * THIRD),
|
||||||
|
vec2(2.0f * SEVENTH, 1.0f), vec2(3.0f * SEVENTH, 2.0f * THIRD), vec2(1.0f * SEVENTH, 2.0f * THIRD),
|
||||||
|
vec2(5.0f * SEVENTH, 2.0f * THIRD), vec2(4.0f * SEVENTH, THIRD), vec2(3.0f * SEVENTH, 2.0f * THIRD),
|
||||||
|
vec2(5.0f * SEVENTH, 2.0f * THIRD), vec2(6.0f * SEVENTH, THIRD), vec2(4.0f * SEVENTH, THIRD),
|
||||||
|
vec2(5.0f * SEVENTH, 2.0f * THIRD), vec2(1.0f, 2.0f * THIRD), vec2(6.0f * SEVENTH, THIRD) },
|
||||||
FaceVector<3> {
|
FaceVector<3> {
|
||||||
Face<3> { { 0, 2, 4, } },
|
Face<3> { { 0, 2, 4, } },
|
||||||
Face<3> { { 0, 4, 3, } },
|
Face<3> { { 0, 4, 3, } },
|
||||||
|
@ -116,11 +153,52 @@ const Solid<5>& dodecahedron() {
|
||||||
static const vec3 I = vec3(0, -IP, P);
|
static const vec3 I = vec3(0, -IP, P);
|
||||||
static const vec3 J = vec3(P, 0, IP);
|
static const vec3 J = vec3(P, 0, IP);
|
||||||
|
|
||||||
|
|
||||||
|
/* _
|
||||||
|
/ \ |
|
||||||
|
/ \ y2
|
||||||
|
/ \ |
|
||||||
|
/ \ _
|
||||||
|
\ / |
|
||||||
|
\ / y1
|
||||||
|
\ / |
|
||||||
|
___________ _
|
||||||
|
|x3|- - x1 - -||x3|
|
||||||
|
|- - - - x2- - - -|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// x1, x2, and x3 are the solutions to the following system of equations:
|
||||||
|
// 1 = 3 * x1 + 3 * x2 + x3
|
||||||
|
// x1 + 2 * x3 = (golden ratio) * x1
|
||||||
|
// x2 = x1 + 2 * x3
|
||||||
|
static const float x1 = 4.0f / (17.0f + 7.0f * sqrtf(5.0f));
|
||||||
|
static const float x2 = (1.0f / 11.0f) * (5.0f * sqrtf(5.0f) - 9.0f);
|
||||||
|
static const float x2_2 = x2 / 2.0f;
|
||||||
|
static const float x3 = (1.0f / 11.0f) * (6.0f * sqrtf(5.0f) - 13.0f);
|
||||||
|
// y1 and y2 are the solutions to the following system of equations (x is the sidelength, but is different than x1 because the scale in the y direction is different):
|
||||||
|
// 1 = 3 * y1 + 2 * y2
|
||||||
|
// y1 = sin(108 deg) * x
|
||||||
|
// y1 + y2 = x * sqrtf(5 + 2 * sqrtf(5)) / 2
|
||||||
|
static const float y1 = sqrtf(2.0f * (5.0f + sqrtf(5.0f))) / (sqrtf(2.0f * (5.0f + sqrtf(5.0f))) + 4.0f * sqrtf(5.0f + 2.0f * sqrtf(5.0f)));
|
||||||
|
static const float y2 = -(sqrtf(2.0f * (5.0f + sqrtf(5.0f))) - 2.0f * sqrtf(5.0f + 2.0f * sqrtf(5.0f))) / (sqrtf(2.0f * (5.0f + sqrtf(5.0f))) + 4.0f * sqrtf(5.0f + 2.0f * sqrtf(5.0f)));
|
||||||
|
|
||||||
static const Solid<5> DODECAHEDRON = Solid<5>{
|
static const Solid<5> DODECAHEDRON = Solid<5>{
|
||||||
{
|
{
|
||||||
A, B, C, D, E, F, G, H, I, J,
|
A, B, C, D, E, F, G, H, I, J,
|
||||||
-A, -B, -C, -D, -E, -F, -G, -H, -I, -J,
|
-A, -B, -C, -D, -E, -F, -G, -H, -I, -J,
|
||||||
},
|
},
|
||||||
|
{ vec2(x1 + x2_2, 0.0f), vec2(x2_2, 0.0f), vec2(x2_2 - x3, y1), vec2(x3 + x1, y1 + y2), vec2(x3 + x1 + x2_2, y1),
|
||||||
|
vec2(1.0f - (x2 - x3 + x2_2), 0.0f), vec2(1.0f - (x2 + x1 + x3), y2), vec2(1.0f - (x2 + x1), y1 + y2), vec2(1.0f - x2, y1 + y2), vec2(1.0f - (x2 - x3), y2),
|
||||||
|
vec2(1.0f - x2_2, y1), vec2(1.0f - x2, y1 + y2), vec2(1.0f - (x3 + x1), y1 + y2 + y1), vec2(1.0f - x3, y1 + y2 + y1), vec2(1.0f, y1 + y2),
|
||||||
|
vec2(x3, y1 + y2), vec2(0.0f, y1 + y2 + y1), vec2(x2_2, y1 + y2 + y1 + y2), vec2(x2, y1 + y2 + y1), vec2(x1 + x3, y1 + y2),
|
||||||
|
vec2(x3 + x1, y1 + y2), vec2(x2, y1 + y2 + y1), vec2(x2 + x1, y1 + y2 + y1), vec2(x3 + x1 + x2, y1 + y2), vec2(x3 + x1 + x2_2, y1),
|
||||||
|
vec2(x3 + x1 + x2_2, y1), vec2(x3 + x1 + x2, y1 + y2), vec2(x3 + x1 + x2 + x2_2, y1), vec2(x1 + x2 + x2_2, 0.0f), vec2(x3 + x1 + x2_2 + x3, 0.0f),
|
||||||
|
vec2(1.0f - (x3 + x1 + x2_2), 1.0f - y1), vec2(1.0f - (x3 + x1 + x2), 1.0f - (y1 + y2)), vec2(1.0f - (x3 + x1 + x2 + x2_2), 1.0f - y1), vec2(1.0f - (x1 + x2 + x2_2), 1.0f), vec2(1.0f - (x3 + x1 + x2_2 + x3), 1.0f),
|
||||||
|
vec2(x2 + x1 + x3, 1.0f - y2), vec2(x2 + x1, 1.0f - (y1 + y2)), vec2(x2, 1.0f - (y1 + y2)), vec2(x2 - x3, 1.0f - y2), vec2(x2 - x3 + x2_2, 1.0f),
|
||||||
|
vec2(x2 + x1 + x2, y1 + y2 + y1), vec2(x3 + x1 + x2 + x1, y1 + y2), vec2(x3 + x1 + x2, y1 + y2), vec2(x2 + x1, y1 + y2 + y1), vec2(x2 + x1 + x2_2, y1 + y2 + y1 + y2),
|
||||||
|
vec2(1.0f - (x3 + x1 + x2), y1 + y2 + y1), vec2(1.0f - (x2 + x1), y1 + y2), vec2(1.0f - (x2 + x1 + x2_2), y1), vec2(1.0f - (x2 + x1 + x2), y1 + y2), vec2(1.0f - (x3 + x1 + x2 + x1), y1 + y2 + y1),
|
||||||
|
vec2(1.0f - (x3 + x1 + x2_2), y1 + y2 + y1 + y2), vec2(1.0f - (x3 + x1), y1 + y2 + y1), vec2(1.0f - x2, y1 + y2), vec2(1.0f - (x2 + x1), y2 + y1), vec2(1.0f - (x3 + x1 + x2), y1 + y2 + y1),
|
||||||
|
vec2(1.0f - (x1 + x2_2), 1.0f), vec2(1.0f - x2_2, 1.0f), vec2(1.0f - (x2_2 - x3), 1.0f - y1), vec2(1.0f - (x1 + x3), 1.0f - (y1 + y2)), vec2(1.0f - (x3 + x1 + x2_2), 1.0f - y1) },
|
||||||
FaceVector<5> {
|
FaceVector<5> {
|
||||||
Face<5> { { 0, 1, 2, 3, 4 } },
|
Face<5> { { 0, 1, 2, 3, 4 } },
|
||||||
Face<5> { { 0, 5, 18, 6, 1 } },
|
Face<5> { { 0, 5, 18, 6, 1 } },
|
||||||
|
@ -148,12 +226,33 @@ const Solid<3>& icosahedron() {
|
||||||
static const auto D = vec3(P, 0, N);
|
static const auto D = vec3(P, 0, N);
|
||||||
static const auto E = vec3(P, 0, -N);
|
static const auto E = vec3(P, 0, -N);
|
||||||
static const auto F = vec3(0, N, -P);
|
static const auto F = vec3(0, N, -P);
|
||||||
|
static const float THIRD = 1.0f / 3.0f;
|
||||||
|
static const float ELEVENTH = 1.0f / 11.0f;
|
||||||
static const Solid<3> ICOSAHEDRON = Solid<3> {
|
static const Solid<3> ICOSAHEDRON = Solid<3> {
|
||||||
{
|
{
|
||||||
A, B, C, D, E, F,
|
A, B, C, D, E, F,
|
||||||
-A, -B, -C, -D, -E, -F,
|
-A, -B, -C, -D, -E, -F,
|
||||||
},
|
},
|
||||||
|
{ vec2(3.0f * ELEVENTH, 0.0f), vec2(2.0f * ELEVENTH, THIRD), vec2(4.0f * ELEVENTH, THIRD),
|
||||||
|
vec2(2.0f * ELEVENTH, THIRD), vec2(3.0f * ELEVENTH, 2.0f * THIRD), vec2(4.0f * ELEVENTH, THIRD),
|
||||||
|
vec2(3.0f * ELEVENTH, 2.0f * THIRD), vec2(5.0f * ELEVENTH, 2.0f * THIRD), vec2(4.0f * ELEVENTH, THIRD),
|
||||||
|
vec2(5.0f * ELEVENTH, 2.0f * THIRD), vec2(6.0f * ELEVENTH, THIRD), vec2(4.0f * ELEVENTH, THIRD),
|
||||||
|
vec2(6.0f * ELEVENTH, THIRD), vec2(5.0f * ELEVENTH, 0.0f), vec2(4.0f * ELEVENTH, THIRD),
|
||||||
|
vec2(1.0f * ELEVENTH, 0.0f), vec2(0.0f, THIRD), vec2(2.0f * ELEVENTH, THIRD),
|
||||||
|
vec2(1.0f * ELEVENTH, 2.0f * THIRD), vec2(2.0f * ELEVENTH, THIRD), vec2(0.0f, THIRD),
|
||||||
|
vec2(2.0f * ELEVENTH, THIRD), vec2(1.0f * ELEVENTH, 2.0f * THIRD), vec2(3.0f * ELEVENTH, 2.0f * THIRD),
|
||||||
|
vec2(2.0f * ELEVENTH, 1.0f), vec2(3.0f * ELEVENTH, 2.0f * THIRD), vec2(1.0f * ELEVENTH, 2.0f * THIRD),
|
||||||
|
vec2(3.0f * ELEVENTH, 2.0f * THIRD), vec2(4.0f * ELEVENTH, 1.0f), vec2(5.0f * ELEVENTH, 2.0f * THIRD),
|
||||||
|
vec2(7.0f * ELEVENTH, 2.0f * THIRD), vec2(5.0f * ELEVENTH, 2.0f * THIRD), vec2(6.0f * ELEVENTH, 1.0f),
|
||||||
|
vec2(5.0f * ELEVENTH, 2.0f * THIRD), vec2(7.0f * ELEVENTH, 2.0f * THIRD), vec2(6.0f * ELEVENTH, THIRD),
|
||||||
|
vec2(8.0f * ELEVENTH, THIRD), vec2(6.0f * ELEVENTH, THIRD), vec2(7.0f * ELEVENTH, 2.0f * THIRD),
|
||||||
|
vec2(6.0f * ELEVENTH, THIRD), vec2(8.0f * ELEVENTH, THIRD), vec2(7.0f * ELEVENTH, 0.0f),
|
||||||
|
vec2(10.0f * ELEVENTH, THIRD), vec2(9.0f * ELEVENTH, 0.0f), vec2(8.0f * ELEVENTH, THIRD),
|
||||||
|
vec2(7.0f * ELEVENTH, 2.0f * THIRD), vec2(8.0f * ELEVENTH, 1.0f), vec2(9.0f * ELEVENTH, 2.0f * THIRD),
|
||||||
|
vec2(8.0f * ELEVENTH, THIRD), vec2(7.0f * ELEVENTH, 2.0f * THIRD), vec2(9.0f * ELEVENTH, 2.0f * THIRD),
|
||||||
|
vec2(10.0f * ELEVENTH, THIRD), vec2(8.0f * ELEVENTH, THIRD), vec2(9.0f * ELEVENTH, 2.0f * THIRD),
|
||||||
|
vec2(1.0f, 2.0f * THIRD), vec2(10.0f * ELEVENTH, THIRD), vec2(9.0f * ELEVENTH, 2.0f * THIRD),
|
||||||
|
vec2(10.0f * ELEVENTH, 1.0f), vec2(1.0f, 2.0f * THIRD), vec2(9.0f * ELEVENTH, 2.0f * THIRD) },
|
||||||
FaceVector<3> {
|
FaceVector<3> {
|
||||||
Face<3> { { 1, 2, 0 } },
|
Face<3> { { 1, 2, 0 } },
|
||||||
Face<3> { { 2, 3, 0 } },
|
Face<3> { { 2, 3, 0 } },
|
||||||
|
|
|
@ -22,6 +22,7 @@ namespace geometry {
|
||||||
using Index = uint32_t;
|
using Index = uint32_t;
|
||||||
using Vec = glm::vec3;
|
using Vec = glm::vec3;
|
||||||
using VertexVector = std::vector<Vec>;
|
using VertexVector = std::vector<Vec>;
|
||||||
|
using TexCoordVector = std::vector<glm::vec2>;
|
||||||
using IndexVector = std::vector<Index>;
|
using IndexVector = std::vector<Index>;
|
||||||
|
|
||||||
template <size_t N>
|
template <size_t N>
|
||||||
|
@ -33,6 +34,7 @@ namespace geometry {
|
||||||
template <size_t N>
|
template <size_t N>
|
||||||
struct Solid {
|
struct Solid {
|
||||||
VertexVector vertices;
|
VertexVector vertices;
|
||||||
|
TexCoordVector texCoords;
|
||||||
FaceVector<N> faces;
|
FaceVector<N> faces;
|
||||||
|
|
||||||
Solid<N>& fitDimension(float newMaxDimension) {
|
Solid<N>& fitDimension(float newMaxDimension) {
|
||||||
|
|
|
@ -20,8 +20,12 @@ if (NOT SERVER_ONLY AND NOT ANDROID)
|
||||||
add_subdirectory(${DIR})
|
add_subdirectory(${DIR})
|
||||||
set(DIR "oculusLegacy")
|
set(DIR "oculusLegacy")
|
||||||
add_subdirectory(${DIR})
|
add_subdirectory(${DIR})
|
||||||
|
|
||||||
|
if (USE_SIXENSE)
|
||||||
set(DIR "hifiSixense")
|
set(DIR "hifiSixense")
|
||||||
add_subdirectory(${DIR})
|
add_subdirectory(${DIR})
|
||||||
|
endif()
|
||||||
|
|
||||||
set(DIR "hifiSpacemouse")
|
set(DIR "hifiSpacemouse")
|
||||||
add_subdirectory(${DIR})
|
add_subdirectory(${DIR})
|
||||||
set(DIR "hifiNeuron")
|
set(DIR "hifiNeuron")
|
||||||
|
|
|
@ -12,5 +12,7 @@ link_hifi_libraries(audio plugins)
|
||||||
add_dependency_external_projects(hifiAudioCodec)
|
add_dependency_external_projects(hifiAudioCodec)
|
||||||
target_include_directories(${TARGET_NAME} PRIVATE ${HIFIAUDIOCODEC_INCLUDE_DIRS})
|
target_include_directories(${TARGET_NAME} PRIVATE ${HIFIAUDIOCODEC_INCLUDE_DIRS})
|
||||||
target_link_libraries(${TARGET_NAME} ${HIFIAUDIOCODEC_LIBRARIES})
|
target_link_libraries(${TARGET_NAME} ${HIFIAUDIOCODEC_LIBRARIES})
|
||||||
install_beside_console()
|
|
||||||
|
|
||||||
|
if (BUILD_SERVER)
|
||||||
|
install_beside_console()
|
||||||
|
endif ()
|
||||||
|
|
|
@ -19,7 +19,7 @@ if (WIN32 AND (NOT USE_GLES))
|
||||||
set(TARGET_NAME oculus)
|
set(TARGET_NAME oculus)
|
||||||
setup_hifi_plugin(Multimedia)
|
setup_hifi_plugin(Multimedia)
|
||||||
link_hifi_libraries(
|
link_hifi_libraries(
|
||||||
shared task gl gpu gpu-gl controllers ui qml
|
shared task gl gpu ${PLATFORM_GL_BACKEND} controllers ui qml
|
||||||
plugins ui-plugins display-plugins input-plugins
|
plugins ui-plugins display-plugins input-plugins
|
||||||
audio-client networking render-utils
|
audio-client networking render-utils
|
||||||
${PLATFORM_GL_BACKEND}
|
${PLATFORM_GL_BACKEND}
|
||||||
|
|
|
@ -9,5 +9,7 @@
|
||||||
set(TARGET_NAME pcmCodec)
|
set(TARGET_NAME pcmCodec)
|
||||||
setup_hifi_client_server_plugin()
|
setup_hifi_client_server_plugin()
|
||||||
link_hifi_libraries(shared plugins)
|
link_hifi_libraries(shared plugins)
|
||||||
install_beside_console()
|
|
||||||
|
|
||||||
|
if (BUILD_SERVER)
|
||||||
|
install_beside_console()
|
||||||
|
endif ()
|
||||||
|
|
102
scripts/developer/tests/webOverlayTool.js
Normal file
102
scripts/developer/tests/webOverlayTool.js
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
// webSpawnTool.js
|
||||||
|
//
|
||||||
|
// Stress tests the rendering of web surfaces over time
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
SPAWNER = function (properties) {
|
||||||
|
properties = properties || {};
|
||||||
|
var RADIUS = properties.radius || 5.0; // Spawn within this radius (square)
|
||||||
|
var SPAWN_COUNT = properties.count || 10000; // number of entities to spawn
|
||||||
|
var SPAWN_LIMIT = properties.spawnLimit || 1;
|
||||||
|
var SPAWN_INTERVAL = properties.spawnInterval || properties.interval || 2;
|
||||||
|
var SPAWN_LIFETIME = properties.lifetime || 10; // Entity timeout (when/if we crash, we need the entities to delete themselves)
|
||||||
|
|
||||||
|
function randomPositionXZ(center, radius) {
|
||||||
|
return {
|
||||||
|
x: center.x + (Math.random() * radius * 2.0) - radius,
|
||||||
|
y: center.y,
|
||||||
|
z: center.z + (Math.random() * radius * 2.0) - radius
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function makeObject(properties) {
|
||||||
|
|
||||||
|
var overlay = Overlays.addOverlay("web3d", {
|
||||||
|
name: "Web",
|
||||||
|
url: "https://www.reddit.com/r/random",
|
||||||
|
localPosition: randomPositionXZ( { x: 0, y: 0, z: -1 }, 1),
|
||||||
|
localRotation: Quat.angleAxis(180, Vec3.Y_AXIS),
|
||||||
|
dimensions: {x: .8, y: .45, z: 0.1},
|
||||||
|
color: { red: 255, green: 255, blue: 255 },
|
||||||
|
alpha: 1.0,
|
||||||
|
showKeyboardFocusHighlight: false,
|
||||||
|
visible: true
|
||||||
|
});
|
||||||
|
|
||||||
|
var now = Date.now();
|
||||||
|
|
||||||
|
return {
|
||||||
|
destroy: function () {
|
||||||
|
Overlays.deleteOverlay(overlay)
|
||||||
|
},
|
||||||
|
getAge: function () {
|
||||||
|
return (Date.now() - now) / 1000.0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var items = [];
|
||||||
|
var toCreate = 0;
|
||||||
|
var spawned = 0;
|
||||||
|
var spawnTimer = 0.0;
|
||||||
|
var keepAliveTimer = 0.0;
|
||||||
|
|
||||||
|
function clear () {
|
||||||
|
}
|
||||||
|
|
||||||
|
function create() {
|
||||||
|
toCreate = SPAWN_COUNT;
|
||||||
|
Script.update.connect(spawn);
|
||||||
|
}
|
||||||
|
|
||||||
|
function spawn(dt) {
|
||||||
|
if (toCreate <= 0) {
|
||||||
|
Script.update.disconnect(spawn);
|
||||||
|
print("Finished spawning");
|
||||||
|
}
|
||||||
|
else if ((spawnTimer -= dt) < 0.0){
|
||||||
|
spawnTimer = SPAWN_INTERVAL;
|
||||||
|
|
||||||
|
var n = Math.min(toCreate, SPAWN_LIMIT);
|
||||||
|
print("Spawning " + n + " items (" + (spawned += n) + ")");
|
||||||
|
|
||||||
|
toCreate -= n;
|
||||||
|
for (; n > 0; --n) {
|
||||||
|
items.push(makeObject());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function despawn() {
|
||||||
|
print("despawning");
|
||||||
|
items.forEach(function (item) {
|
||||||
|
item.destroy();
|
||||||
|
});
|
||||||
|
item = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
function init () {
|
||||||
|
Script.update.disconnect(init);
|
||||||
|
Script.scriptEnding.connect(despawn);
|
||||||
|
clear();
|
||||||
|
create();
|
||||||
|
}
|
||||||
|
|
||||||
|
Script.update.connect(init);
|
||||||
|
};
|
||||||
|
|
||||||
|
SPAWNER();
|
|
@ -14,7 +14,7 @@ set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "Tests/manual-tests/")
|
||||||
# link in the shared libraries
|
# link in the shared libraries
|
||||||
link_hifi_libraries(
|
link_hifi_libraries(
|
||||||
shared task networking animation
|
shared task networking animation
|
||||||
ktx image octree gl gpu gpu-gl
|
ktx image octree gl gpu ${PLATFORM_GL_BACKEND}
|
||||||
render render-utils
|
render render-utils
|
||||||
graphics fbx model-networking graphics-scripting
|
graphics fbx model-networking graphics-scripting
|
||||||
entities entities-renderer audio avatars script-engine
|
entities entities-renderer audio avatars script-engine
|
||||||
|
|
|
@ -18,4 +18,6 @@ elseif (APPLE)
|
||||||
set_target_properties(${TARGET_NAME} PROPERTIES INSTALL_RPATH "@executable_path/../Frameworks")
|
set_target_properties(${TARGET_NAME} PROPERTIES INSTALL_RPATH "@executable_path/../Frameworks")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
install_beside_console()
|
if (BUILD_SERVER)
|
||||||
|
install_beside_console()
|
||||||
|
endif ()
|
||||||
|
|
|
@ -40,6 +40,8 @@ Oven::Oven() {
|
||||||
}
|
}
|
||||||
|
|
||||||
Oven::~Oven() {
|
Oven::~Oven() {
|
||||||
|
DependencyManager::get<ResourceManager>()->cleanup();
|
||||||
|
|
||||||
// quit all worker threads and wait on them
|
// quit all worker threads and wait on them
|
||||||
for (auto& thread : _workerThreads) {
|
for (auto& thread : _workerThreads) {
|
||||||
thread->quit();
|
thread->quit();
|
||||||
|
|
Loading…
Reference in a new issue