diff --git a/BUILD.md b/BUILD.md index a5ee32262f..ad365fcde2 100644 --- a/BUILD.md +++ b/BUILD.md @@ -5,6 +5,7 @@ * [OpenSSL](https://www.openssl.org/related/binaries.html) ~> 1.0.1m * IMPORTANT: Using the recommended version of OpenSSL is critical to avoid security vulnerabilities. * [VHACD](https://github.com/virneo/v-hacd)(clone this repository)(Optional) +* [zlib](http://www.zlib.net/) ####CMake External Project Dependencies diff --git a/BUILD_OSX.md b/BUILD_OSX.md index 60fbb7cf92..9d1357d672 100644 --- a/BUILD_OSX.md +++ b/BUILD_OSX.md @@ -1,7 +1,7 @@ Please read the [general build guide](BUILD.md) for information on dependencies required for all platforms. Only OS X specific instructions are found in this file. ###Homebrew -[Homebrew](http://brew.sh/) is an excellent package manager for OS X. It makes install of all hifi dependencies very simple. +[Homebrew](http://brew.sh/) is an excellent package manager for OS X. It makes install of all High Fidelity dependencies very simple. brew tap highfidelity/homebrew-formulas brew install cmake openssl diff --git a/BUILD_WIN.md b/BUILD_WIN.md index e905a83ace..b6ec31b713 100644 --- a/BUILD_WIN.md +++ b/BUILD_WIN.md @@ -75,6 +75,16 @@ To prevent these problems, install OpenSSL yourself. Download the following bina Install OpenSSL into the Windows system directory, to make sure that Qt uses the version that you've just installed, and not some other version. +####zlib + +Install zlib from + + [Zlib for Windows](http://gnuwin32.sourceforge.net/packages/zlib.htm) + +and fix a header file, as described here: + + [zlib zconf.h bug](http://sourceforge.net/p/gnuwin32/bugs/169/) + ###Build High Fidelity using Visual Studio Follow the same build steps from the CMake section of [BUILD.md](BUILD.md), but pass a different generator to CMake. diff --git a/CMakeLists.txt b/CMakeLists.txt index 4a5f3a5916..38bcb42e26 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -186,13 +186,10 @@ option(GET_POLYVOX "Get polyvox library automatically as external project" 1) option(GET_OPENVR "Get OpenVR library automatically as external project" 1) option(GET_BOOSTCONFIG "Get Boost-config library automatically as external project" 1) option(GET_OGLPLUS "Get OGLplus library automatically as external project" 1) +option(GET_GLEW "Get GLEW library automatically as external project" 1) option(USE_NSIGHT "Attempt to find the nSight libraries" 1) -if (WIN32) - option(GET_GLEW "Get GLEW library automatically as external project" 1) -endif () - option(GET_SDL2 "Get SDL2 library automatically as external project" 0) if (WIN32) diff --git a/cmake/externals/glew/CMakeLists.txt b/cmake/externals/glew/CMakeLists.txt index f943fd2129..5f59cc2377 100644 --- a/cmake/externals/glew/CMakeLists.txt +++ b/cmake/externals/glew/CMakeLists.txt @@ -1,34 +1,34 @@ -if (WIN32) - set(EXTERNAL_NAME glew) +set(EXTERNAL_NAME glew) - include(ExternalProject) - ExternalProject_Add( - ${EXTERNAL_NAME} - URL http://hifi-public.s3.amazonaws.com/dependencies/glew-1.10.0-win32.zip - URL_MD5 37514e4e595a3b3dc587eee8f7e8ec2f - CONFIGURE_COMMAND "" - BUILD_COMMAND "" - INSTALL_COMMAND "" - LOG_DOWNLOAD 1 - ) +if (ANDROID) + set(ANDROID_CMAKE_ARGS "-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}" "-DANDROID_NATIVE_API_LEVEL=19") +endif () - # Hide this external target (for ide users) - set_target_properties(${EXTERNAL_NAME} PROPERTIES FOLDER "hidden/externals") +include(ExternalProject) +ExternalProject_Add( + ${EXTERNAL_NAME} + URL http://hifi-public.s3.amazonaws.com/dependencies/glew_simple.zip + URL_MD5 0507dc08337a82a5e7ecbc5417f92cc1 + CONFIGURE_COMMAND CMAKE_ARGS ${ANDROID_CMAKE_ARGS} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_INSTALL_PREFIX:PATH= + LOG_DOWNLOAD 1 + LOG_CONFIGURE 1 + LOG_BUILD 1 +) - ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR) +# Hide this external target (for ide users) +set_target_properties(${EXTERNAL_NAME} PROPERTIES FOLDER "hidden/externals") - string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) - set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/include CACHE PATH "List of glew include directories") +ExternalProject_Get_Property(${EXTERNAL_NAME} INSTALL_DIR) - if ("${CMAKE_SIZEOF_VOID_P}" EQUAL "8") - set(_LIB_DIR ${SOURCE_DIR}/lib/Release/x64) - set(${EXTERNAL_NAME_UPPER}_DLL_PATH ${SOURCE_DIR}/bin/Release/x64 CACHE FILEPATH "Location of GLEW DLL") - else() - set(_LIB_DIR ${SOURCE_DIR}/lib/Release/Win32) - set(${EXTERNAL_NAME_UPPER}_DLL_PATH ${SOURCE_DIR}/bin/Release/Win32 CACHE FILEPATH "Location of GLEW DLL") - endif() +string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) +set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${INSTALL_DIR}/include CACHE PATH "List of glew include directories") - set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${_LIB_DIR}/glew32.lib CACHE FILEPATH "Location of GLEW release library") - set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG "" CACHE FILEPATH "Location of GLEW debug library") +if (UNIX) + set(LIB_PREFIX "lib") + set(LIB_EXT "a") +elseif (WIN32) + set(LIB_EXT "lib") +endif () -endif () \ No newline at end of file +set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${INSTALL_DIR}/lib/${LIB_PREFIX}glew_d.${LIB_EXT} CACHE FILEPATH "Path to glew debug library") +set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/lib/${LIB_PREFIX}glew.${LIB_EXT} CACHE FILEPATH "Path to glew release library") \ No newline at end of file diff --git a/cmake/externals/zlib/CMakeLists.txt b/cmake/externals/zlib/CMakeLists.txt new file mode 100644 index 0000000000..69dbca714d --- /dev/null +++ b/cmake/externals/zlib/CMakeLists.txt @@ -0,0 +1,28 @@ + +if (WIN32) + set(EXTERNAL_NAME zlib) + string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) + + include(ExternalProject) + ExternalProject_Add( + ${EXTERNAL_NAME} + URL http://zlib.net/zlib128.zip + URL_MD5 126f8676442ffbd97884eb4d6f32afb4 + INSTALL_COMMAND "" + LOG_DOWNLOAD 1 + ) + + # Hide this external target (for ide users) + set_target_properties(${EXTERNAL_NAME} PROPERTIES FOLDER "hidden/externals") + + ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR) + + set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/include CACHE PATH "List of zlib include directories") + + ExternalProject_Get_Property(${EXTERNAL_NAME} BINARY_DIR) + + set(${EXTERNAL_NAME_UPPER}_DLL_PATH ${BINARY_DIR}/Release CACHE FILEPATH "Location of GLEW DLL") + set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${BINARY_DIR}/Release/zlib.lib CACHE FILEPATH "Location of ZLib release library") + set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG "" CACHE FILEPATH "Location of ZLib debug library") + +endif () \ No newline at end of file diff --git a/cmake/macros/SetupHifiLibrary.cmake b/cmake/macros/SetupHifiLibrary.cmake index 6d1de8f24d..e38e224084 100644 --- a/cmake/macros/SetupHifiLibrary.cmake +++ b/cmake/macros/SetupHifiLibrary.cmake @@ -12,7 +12,7 @@ macro(SETUP_HIFI_LIBRARY) project(${TARGET_NAME}) # grab the implemenation and header files - file(GLOB_RECURSE LIB_SRCS "src/*.h" "src/*.cpp") + file(GLOB_RECURSE LIB_SRCS "src/*.h" "src/*.cpp" "src/*.c") list(APPEND ${TARGET_NAME}_SRCS ${LIB_SRCS}) # create a library and set the property so it can be referenced later diff --git a/cmake/macros/SetupHifiOpenGL.cmake b/cmake/macros/SetupHifiOpenGL.cmake index c62e43c27e..2b1858fd4b 100644 --- a/cmake/macros/SetupHifiOpenGL.cmake +++ b/cmake/macros/SetupHifiOpenGL.cmake @@ -10,11 +10,6 @@ macro(SETUP_HIFI_OPENGL) elseif (WIN32) - add_dependency_external_projects(glew) - find_package(GLEW REQUIRED) - target_include_directories(${TARGET_NAME} PUBLIC ${GLEW_INCLUDE_DIRS}) - target_link_libraries(${TARGET_NAME} ${GLEW_LIBRARIES} opengl32.lib) - if (USE_NSIGHT) # try to find the Nsight package and add it to the build if we find it find_package(NSIGHT) diff --git a/cmake/modules/Find3DConnexionClient.cmake b/cmake/modules/Find3DConnexionClient.cmake new file mode 100644 index 0000000000..e927ad1954 --- /dev/null +++ b/cmake/modules/Find3DConnexionClient.cmake @@ -0,0 +1,38 @@ +# +# Find3DConnexionClient.cmake +# +# Once done this will define + +# 3DCONNEXIONCLIENT_FOUND - system found 3DConnexion +# 3DCONNEXIONCLIENT_INCLUDE_DIRS - the 3DConnexion include directory +# 3DCONNEXIONCLIENT_LIBRARY - Link this to use 3DConnexion +# +# Created on 10/06/2015 by Marcel Verhagen +# Copyright 2015 High Fidelity, Inc. +# +# Distributed under the Apache License, Version 2.0. +# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +# + +include("${MACRO_DIR}/HifiLibrarySearchHints.cmake") +hifi_library_search_hints("connexionclient") + +if (APPLE) + find_library(3DCONNEXIONCLIENT_LIBRARIES NAMES 3DConnexionClient HINTS 3DCONNEXIONCLIENT_SEARCH_DIRS) + if(EXISTS ${3DConnexionClient}) + set(3DCONNEXIONCLIENT_FOUND true) + set(3DCONNEXIONCLIENT_INCLUDE_DIRS ${3DConnexionClient}) + set(3DCONNEXIONCLIENT_LIBRARY ${3DConnexionClient}) + message(STATUS "Found 3DConnexion at " ${3DConnexionClient}) + mark_as_advanced(3DCONNEXIONCLIENT_INCLUDE_DIR 3DCONNEXIONCLIENT_LIBRARY) + else () + message(STATUS "Could NOT find 3DConnexionClient") + endif() +elseif (WIN32) + find_path(3DCONNEXIONCLIENT_INCLUDE_DIRS I3dMouseParams.h PATH_SUFFIXES include HINTS ${3DCONNEXIONCLIENT_SEARCH_DIRS}) + + include(FindPackageHandleStandardArgs) + find_package_handle_standard_args(3DConnexionClient DEFAULT_MSG 3DCONNEXIONCLIENT_INCLUDE_DIRS) + + mark_as_advanced(3DCONNEXIONCLIENT_INCLUDE_DIRS 3DCONNEXIONCLIENT_SEARCH_DIRS) +endif() \ No newline at end of file diff --git a/cmake/modules/FindGLEW.cmake b/cmake/modules/FindGLEW.cmake index b1789fb614..4f22271e3e 100644 --- a/cmake/modules/FindGLEW.cmake +++ b/cmake/modules/FindGLEW.cmake @@ -1,7 +1,7 @@ # # FindGLEW.cmake # -# Try to find GLEW library and include path. +# Try to find GLEW library and include path. Note that this only handles static GLEW. # Once done this will define # # GLEW_FOUND @@ -18,39 +18,18 @@ # See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html # -if (WIN32) - include("${MACRO_DIR}/HifiLibrarySearchHints.cmake") - hifi_library_search_hints("glew") - - find_path(GLEW_INCLUDE_DIRS GL/glew.h PATH_SUFFIXES include HINTS ${GLEW_SEARCH_DIRS}) - - find_library(GLEW_LIBRARY_RELEASE glew32 PATH_SUFFIXES "lib/Release/Win32" "lib" HINTS ${GLEW_SEARCH_DIRS}) - find_library(GLEW_LIBRARY_DEBUG glew32d PATH_SUFFIXES "lib/Debug/Win32" "lib" HINTS ${GLEW_SEARCH_DIRS}) - - find_path(GLEW_DLL_PATH glew32.dll PATH_SUFFIXES "bin/Release/Win32" HINTS ${GLEW_SEARCH_DIRS}) - - include(SelectLibraryConfigurations) - select_library_configurations(GLEW) - - set(GLEW_LIBRARIES ${GLEW_LIBRARY}) +include("${MACRO_DIR}/HifiLibrarySearchHints.cmake") +hifi_library_search_hints("glew") - include(FindPackageHandleStandardArgs) - find_package_handle_standard_args(GLEW DEFAULT_MSG GLEW_INCLUDE_DIRS GLEW_LIBRARIES GLEW_DLL_PATH) - - add_paths_to_fixup_libs(${GLEW_DLL_PATH}) -elseif (APPLE) -else () - find_path(GLEW_INCLUDE_DIR GL/glew.h) - find_library(GLEW_LIBRARY NAMES GLEW glew32 glew glew32s PATH_SUFFIXES lib64) +find_path(GLEW_INCLUDE_DIRS GL/glew.h PATH_SUFFIXES include HINTS ${GLEW_SEARCH_DIRS}) - set(GLEW_INCLUDE_DIRS ${GLEW_INCLUDE_DIR}) - set(GLEW_LIBRARIES ${GLEW_LIBRARY}) +find_library(GLEW_LIBRARY_RELEASE glew32 PATH_SUFFIXES "lib/Release/Win32" "lib" HINTS ${GLEW_SEARCH_DIRS}) +find_library(GLEW_LIBRARY_DEBUG glew32d PATH_SUFFIXES "lib/Debug/Win32" "lib" HINTS ${GLEW_SEARCH_DIRS}) - include(FindPackageHandleStandardArgs) - find_package_handle_standard_args(GLEW - REQUIRED_VARS GLEW_INCLUDE_DIR GLEW_LIBRARY) +include(SelectLibraryConfigurations) +select_library_configurations(GLEW) - mark_as_advanced(GLEW_INCLUDE_DIR GLEW_LIBRARY) - -endif () +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(GLEW DEFAULT_MSG GLEW_INCLUDE_DIRS GLEW_LIBRARIES) +message(STATUS "Found GLEW - Assuming that GLEW is static and defining GLEW_STATIC") \ No newline at end of file diff --git a/cmake/modules/FindconnexionClient.cmake b/cmake/modules/FindconnexionClient.cmake deleted file mode 100644 index 1d6d7d4514..0000000000 --- a/cmake/modules/FindconnexionClient.cmake +++ /dev/null @@ -1,38 +0,0 @@ -# -# FindconnexionClient.cmake -# -# Once done this will define -# -# 3DCONNEXIONCLIENT_INCLUDE_DIRS -# -# Created on 10/06/2015 by Marcel Verhagen -# Copyright 2015 High Fidelity, Inc. -# -# Distributed under the Apache License, Version 2.0. -# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -# - -# setup hints for 3DCONNEXIONCLIENT search -include("${MACRO_DIR}/HifiLibrarySearchHints.cmake") -hifi_library_search_hints("connexionclient") - -if (APPLE) - find_library(3DconnexionClient 3DconnexionClient) - if(EXISTS ${3DconnexionClient}) - set(CONNEXIONCLIENT_FOUND true) - set(CONNEXIONCLIENT_INCLUDE_DIR ${3DconnexionClient}) - set(CONNEXIONCLIENT_LIBRARY ${3DconnexionClient}) - set_target_properties(${TARGET_NAME} PROPERTIES LINK_FLAGS "-weak_framework 3DconnexionClient") - message(STATUS "Found 3Dconnexion") - mark_as_advanced(CONNEXIONCLIENT_INCLUDE_DIR CONNEXIONCLIENT_LIBRARY) - endif() -endif() - -if (WIN32) - find_path(CONNEXIONCLIENT_INCLUDE_DIRS I3dMouseParams.h PATH_SUFFIXES Inc HINTS ${CONNEXIONCLIENT_SEARCH_DIRS}) - - include(FindPackageHandleStandardArgs) - find_package_handle_standard_args(connexionClient DEFAULT_MSG CONNEXIONCLIENT_INCLUDE_DIRS) - - mark_as_advanced(CONNEXIONCLIENT_INCLUDE_DIRS CONNEXIONCLIENT_SEARCH_DIRS) -endif() diff --git a/domain-server/resources/describe-settings.json b/domain-server/resources/describe-settings.json index ff2f4cf683..696a87d2b8 100644 --- a/domain-server/resources/describe-settings.json +++ b/domain-server/resources/describe-settings.json @@ -389,6 +389,10 @@ { "value": "json", "label": "Entity server persists data as JSON" + }, + { + "value": "json.gz", + "label": "Entity server persists data as gzipped JSON" } ], "advanced": true diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index c13de0449e..4e5b563fc6 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -579,7 +579,6 @@ const NodeSet STATICALLY_ASSIGNED_NODES = NodeSet() << NodeType::AudioMixer void DomainServer::processConnectRequestPacket(QSharedPointer packet) { NodeType_t nodeType; HifiSockAddr publicSockAddr, localSockAddr; - if (packet->getPayloadSize() == 0) { return; @@ -625,31 +624,62 @@ void DomainServer::processConnectRequestPacket(QSharedPointer packet) return; } } - } QList nodeInterestList; QString username; QByteArray usernameSignature; - - packetStream >> nodeInterestList >> username >> usernameSignature; - + auto limitedNodeList = DependencyManager::get(); - + + packetStream >> nodeInterestList; + + if (packet->bytesLeftToRead() > 0) { + // try to verify username + packetStream >> username; + } + + bool isRestrictingAccess = + _settingsManager.valueOrDefaultValueForKeyPath(RESTRICTED_ACCESS_SETTINGS_KEYPATH).toBool(); + + // we always let in a user who is sending a packet from our local socket or from the localhost address + bool isLocalUser = (senderSockAddr.getAddress() == DependencyManager::get()->getLocalSockAddr().getAddress() || senderSockAddr.getAddress() == QHostAddress::LocalHost); + + if (isRestrictingAccess && !isLocalUser) { + if (!username.isEmpty()) { + // if there's a username, try to unpack username signature + packetStream >> usernameSignature; + + if (usernameSignature.isEmpty()) { + // if user didn't include usernameSignature in connect request, send a connectionToken packet + QUuid& connectionToken = _connectionTokenHash[username.toLower()]; + + if (connectionToken.isNull()) { + connectionToken = QUuid::createUuid(); + } + + static auto connectionTokenPacket = NLPacket::create(PacketType::DomainServerConnectionToken, NUM_BYTES_RFC4122_UUID); + connectionTokenPacket->reset(); + connectionTokenPacket->write(connectionToken.toRfc4122()); + limitedNodeList->sendUnreliablePacket(*connectionTokenPacket, packet->getSenderSockAddr()); + return; + } + } + } + QString reason; if (!isAssignment && !shouldAllowConnectionFromNode(username, usernameSignature, senderSockAddr, reason)) { // this is an agent and we've decided we won't let them connect - send them a packet to deny connection - QByteArray utfString = reason.toUtf8(); quint16 payloadSize = utfString.size(); auto connectionDeniedPacket = NLPacket::create(PacketType::DomainConnectionDenied, payloadSize + sizeof(payloadSize)); - connectionDeniedPacket->writePrimitive(payloadSize); - connectionDeniedPacket->write(utfString); - + if (payloadSize > 0) { + connectionDeniedPacket->writePrimitive(payloadSize); + connectionDeniedPacket->write(utfString); + } // tell client it has been refused. limitedNodeList->sendPacket(std::move(connectionDeniedPacket), senderSockAddr); - return; } @@ -736,6 +766,7 @@ void DomainServer::processConnectRequestPacket(QSharedPointer packet) } } + void DomainServer::processListRequestPacket(QSharedPointer packet, SharedNodePointer sendingNode) { NodeType_t throwawayNodeType; @@ -766,52 +797,61 @@ unsigned int DomainServer::countConnectedUsers() { } -bool DomainServer::verifyUsersKey(const QString& username, - const QByteArray& usernameSignature, - QString& reasonReturn) { +bool DomainServer::verifyUserSignature(const QString& username, + const QByteArray& usernameSignature, + QString& reasonReturn) { + // it's possible this user can be allowed to connect, but we need to check their username signature - QByteArray publicKeyArray = _userPublicKeys.value(username); - if (!publicKeyArray.isEmpty()) { + + const QUuid& connectionToken = _connectionTokenHash.value(username.toLower()); + + if (!publicKeyArray.isEmpty() && !connectionToken.isNull()) { // if we do have a public key for the user, check for a signature match const unsigned char* publicKeyData = reinterpret_cast(publicKeyArray.constData()); // first load up the public key into an RSA struct RSA* rsaPublicKey = d2i_RSA_PUBKEY(NULL, &publicKeyData, publicKeyArray.size()); - + + QByteArray lowercaseUsername = username.toLower().toUtf8(); + QByteArray usernameWithToken = QCryptographicHash::hash(lowercaseUsername.append(connectionToken.toRfc4122()), + QCryptographicHash::Sha256); + if (rsaPublicKey) { QByteArray decryptedArray(RSA_size(rsaPublicKey), 0); - int decryptResult = - RSA_public_decrypt(usernameSignature.size(), - reinterpret_cast(usernameSignature.constData()), - reinterpret_cast(decryptedArray.data()), - rsaPublicKey, RSA_PKCS1_PADDING); + int decryptResult = RSA_verify(NID_sha256, + reinterpret_cast(usernameWithToken.constData()), + usernameWithToken.size(), + reinterpret_cast(usernameSignature.constData()), + usernameSignature.size(), + rsaPublicKey); + + if (decryptResult == 1) { + qDebug() << "Username signature matches for" << username << "- allowing connection."; - if (decryptResult != -1) { - if (username.toLower() == decryptedArray) { - qDebug() << "Username signature matches for" << username << "- allowing connection."; + // free up the public key and remove connection token before we return + RSA_free(rsaPublicKey); + _connectionTokenHash.remove(username); - // free up the public key before we return - RSA_free(rsaPublicKey); - - return true; - } else { - qDebug() << "Username signature did not match for" << username << "- denying connection."; - reasonReturn = "Username signature did not match."; - } + return true; + } else { - qDebug() << "Couldn't decrypt user signature for" << username << "- denying connection."; - reasonReturn = "Couldn't decrypt user signature."; + qDebug() << "Error decrypting username signature for " << username << "- denying connection."; + reasonReturn = "Error decrypting username signature."; + // free up the public key, we don't need it anymore + RSA_free(rsaPublicKey); } - // free up the public key, we don't need it anymore - RSA_free(rsaPublicKey); } else { + // we can't let this user in since we couldn't convert their public key to an RSA key we could use qDebug() << "Couldn't convert data to RSA key for" << username << "- denying connection."; reasonReturn = "Couldn't convert data to RSA key."; } + } else { + qDebug() << "Insufficient data to decrypt username signature - denying connection."; + reasonReturn = "Insufficient data"; } requestUserPublicKey(username); // no joy. maybe next time? @@ -823,41 +863,40 @@ bool DomainServer::shouldAllowConnectionFromNode(const QString& username, const QByteArray& usernameSignature, const HifiSockAddr& senderSockAddr, QString& reasonReturn) { - + + //TODO: improve flow so these bools aren't declared twice bool isRestrictingAccess = _settingsManager.valueOrDefaultValueForKeyPath(RESTRICTED_ACCESS_SETTINGS_KEYPATH).toBool(); + bool isLocalUser = (senderSockAddr.getAddress() == DependencyManager::get()->getLocalSockAddr().getAddress() || senderSockAddr.getAddress() == QHostAddress::LocalHost); - // we always let in a user who is sending a packet from our local socket or from the localhost address - if (senderSockAddr.getAddress() == DependencyManager::get()->getLocalSockAddr().getAddress() - || senderSockAddr.getAddress() == QHostAddress::LocalHost) { - return true; - } - - if (isRestrictingAccess) { - + if (isRestrictingAccess && !isLocalUser) { QStringList allowedUsers = _settingsManager.valueOrDefaultValueForKeyPath(ALLOWED_USERS_SETTINGS_KEYPATH).toStringList(); - + if (allowedUsers.contains(username, Qt::CaseInsensitive)) { - if (!verifyUsersKey(username, usernameSignature, reasonReturn)) { + if (username.isEmpty()) { + qDebug() << "Connect request denied - no username provided."; + reasonReturn = "No username provided"; + return false; + } + if (!verifyUserSignature(username, usernameSignature, reasonReturn)) { return false; } } else { qDebug() << "Connect request denied for user" << username << "not in allowed users list."; reasonReturn = "User not on whitelist."; - + return false; } } - + // either we aren't restricting users, or this user is in the allowed list - // if this user is in the editors list, exempt them from the max-capacity check const QVariant* allowedEditorsVariant = valueForKeyPath(_settingsManager.getSettingsMap(), ALLOWED_EDITORS_SETTINGS_KEYPATH); QStringList allowedEditors = allowedEditorsVariant ? allowedEditorsVariant->toStringList() : QStringList(); if (allowedEditors.contains(username)) { - if (verifyUsersKey(username, usernameSignature, reasonReturn)) { + if (verifyUserSignature(username, usernameSignature, reasonReturn)) { return true; } } diff --git a/domain-server/src/DomainServer.h b/domain-server/src/DomainServer.h index 7786fb34ac..7495e080de 100644 --- a/domain-server/src/DomainServer.h +++ b/domain-server/src/DomainServer.h @@ -90,7 +90,7 @@ private: void pingPunchForConnectingPeer(const SharedNetworkPeer& peer); unsigned int countConnectedUsers(); - bool verifyUsersKey (const QString& username, const QByteArray& usernameSignature, QString& reasonReturn); + bool verifyUserSignature (const QString& username, const QByteArray& usernameSignature, QString& reasonReturn); bool shouldAllowConnectionFromNode(const QString& username, const QByteArray& usernameSignature, const HifiSockAddr& senderSockAddr, QString& reasonReturn); @@ -149,6 +149,8 @@ private: QSet _webAuthenticationStateSet; QHash _cookieSessionHash; + + QHash _connectionTokenHash; QHash _userPublicKeys; diff --git a/examples/gridTest.js b/examples/gridTest.js new file mode 100644 index 0000000000..2baa4650e3 --- /dev/null +++ b/examples/gridTest.js @@ -0,0 +1,78 @@ +// +// Created by Philip Rosedale on July 28, 2015 +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +// Creates a rectangular grid of objects, starting at the origin and proceeding along the X/Z plane. +// Useful for testing the rendering, LOD, and octree storage aspects of the system. +// +// Note that when creating things quickly, the entity server will ignore data if we send updates too quickly. +// like Internet MTU, these rates are set by th domain operator, so in this script there is a RATE_PER_SECOND +// variable letting you set this speed. If entities are missing from the grid after a relog, this number +// being too high may be the reason. + +var SIZE = 10.0; +var SEPARATION = 20.0; +var ROWS_X = 30; +var ROWS_Z = 30; +var TYPE = "Sphere"; // Right now this can be "Box" or "Model" or "Sphere" +var MODEL_URL = "https://hifi-public.s3.amazonaws.com/models/props/LowPolyIsland/CypressTreeGroup.fbx"; +var MODEL_DIMENSION = { x: 33, y: 16, z: 49 }; +var RATE_PER_SECOND = 1000; // The entity server will drop data if we create things too fast. +var SCRIPT_INTERVAL = 100; +var LIFETIME = 600; // By default, these entities will live in the server for 10 minutes + +var addRandom = false; + +var x = 0; +var z = 0; +var totalCreated = 0; + +Script.setInterval(function () { + if (!Entities.serversExist() || !Entities.canRez()) { + return; + } + + var numToCreate = RATE_PER_SECOND * (SCRIPT_INTERVAL / 1000.0); + for (var i = 0; i < numToCreate; i++) { + var position = { x: SIZE + (x * SEPARATION), y: SIZE, z: SIZE + (z * SEPARATION) }; + if (TYPE == "Model") { + Entities.addEntity({ + type: TYPE, + name: "gridTest", + modelURL: MODEL_URL, + position: position, + dimensions: MODEL_DIMENSION, + ignoreCollisions: true, + collisionsWillMove: false, + lifetime: LIFETIME + }); + } else { + Entities.addEntity({ + type: TYPE, + name: "gridTest", + position: position, + dimensions: { x: SIZE, y: SIZE, z: SIZE }, + color: { red: x / ROWS_X * 255, green: 50, blue: z / ROWS_Z * 255 }, + ignoreCollisions: true, + collisionsWillMove: false, + lifetime: LIFETIME + }); + } + + totalCreated++; + + x++; + if (x == ROWS_X) { + x = 0; + z++; + print("Created: " + totalCreated); + } + if (z == ROWS_Z) { + Script.stop(); + } + } +}, SCRIPT_INTERVAL); + diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index f1bcbf4c47..6f05dd9c2c 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -2,7 +2,7 @@ set(TARGET_NAME interface) project(${TARGET_NAME}) # set a default root dir for each of our optional externals if it was not passed -set(OPTIONAL_EXTERNALS "Faceshift" "Sixense" "LeapMotion" "RtMidi" "SDL2" "RSSDK" "connexionClient") +set(OPTIONAL_EXTERNALS "Faceshift" "Sixense" "LeapMotion" "RtMidi" "SDL2" "RSSDK" "3DConnexionClient") foreach(EXTERNAL ${OPTIONAL_EXTERNALS}) string(TOUPPER ${EXTERNAL} ${EXTERNAL}_UPPERCASE) if (NOT ${${EXTERNAL}_UPPERCASE}_ROOT_DIR) diff --git a/interface/external/connexionclient/Inc/I3dMouseParams.h b/interface/external/3dconnexionclient/include/I3dMouseParams.h similarity index 100% rename from interface/external/connexionclient/Inc/I3dMouseParams.h rename to interface/external/3dconnexionclient/include/I3dMouseParams.h diff --git a/interface/external/3dconnexionclient/readme.txt b/interface/external/3dconnexionclient/readme.txt new file mode 100644 index 0000000000..a8014b386d --- /dev/null +++ b/interface/external/3dconnexionclient/readme.txt @@ -0,0 +1,3 @@ +The Mac version does not require any files. The 3D Connexion driver should be installed from http://www.3dconnexion.eu/service/drivers.html + +For Windows the provided header file is required: include/I3dMouseParams.h \ No newline at end of file diff --git a/interface/external/connexionclient/readme.txt b/interface/external/connexionclient/readme.txt deleted file mode 100644 index dd67a29449..0000000000 --- a/interface/external/connexionclient/readme.txt +++ /dev/null @@ -1,4 +0,0 @@ -The mac version does not require any files here. 3D connexion should be installed from -http://www.3dconnexion.eu/service/drivers.html - -For windows a header file is required Inc/I3dMouseParams.h diff --git a/interface/resources/images/normalFittingScale.dds b/interface/resources/images/normalFittingScale.dds new file mode 100644 index 0000000000..8207ee0981 Binary files /dev/null and b/interface/resources/images/normalFittingScale.dds differ diff --git a/interface/resources/meshes/defaultAvatar_full.fst b/interface/resources/meshes/defaultAvatar_full.fst new file mode 100644 index 0000000000..eba175e771 --- /dev/null +++ b/interface/resources/meshes/defaultAvatar_full.fst @@ -0,0 +1,64 @@ +name = defaultAvatar_full +type = body+head +scale = 1 +filename = defaultAvatar_full/defaultAvatar_full.fbx +texdir = defaultAvatar_full/textures +joint = jointNeck = Head +joint = jointLeftHand = LeftHand +joint = jointRoot = Hips +joint = jointHead = HeadTop_End +joint = jointRightHand = RightHand +joint = jointLean = Spine +freeJoint = LeftArm +freeJoint = LeftForeArm +freeJoint = RightArm +freeJoint = RightForeArm +jointIndex = LeftHand = 35 +jointIndex = Reye = 3 +jointIndex = Hips = 10 +jointIndex = LeftHandIndex1 = 36 +jointIndex = LeftHandIndex2 = 37 +jointIndex = LeftHandIndex3 = 38 +jointIndex = LeftHandIndex4 = 39 +jointIndex = LeftShoulder = 32 +jointIndex = RightLeg = 12 +jointIndex = Grp_blendshapes = 0 +jointIndex = Leye = 4 +jointIndex = headphone = 8 +jointIndex = RightForeArm = 26 +jointIndex = Spine = 21 +jointIndex = LeftFoot = 18 +jointIndex = RightToeBase = 14 +jointIndex = face = 1 +jointIndex = LeftToe_End = 20 +jointIndex = Spine1 = 22 +jointIndex = body = 9 +jointIndex = Spine2 = 23 +jointIndex = RightUpLeg = 11 +jointIndex = top1 = 7 +jointIndex = Neck = 40 +jointIndex = HeadTop_End = 42 +jointIndex = RightShoulder = 24 +jointIndex = RightArm = 25 +jointIndex = Head = 41 +jointIndex = LeftLeg = 17 +jointIndex = LeftForeArm = 34 +jointIndex = hair = 6 +jointIndex = RightHand = 27 +jointIndex = LeftToeBase = 19 +jointIndex = LeftUpLeg = 16 +jointIndex = mouth = 2 +jointIndex = RightFoot = 13 +jointIndex = LeftArm = 33 +jointIndex = shield = 5 +jointIndex = RightHandIndex1 = 28 +jointIndex = RightHandIndex2 = 29 +jointIndex = RightToe_End = 15 +jointIndex = RightHandIndex3 = 30 +jointIndex = RightHandIndex4 = 31 +ry = 0 +rz = 0 +tx = 0 +ty = 0 +tz = 0 +rx = 0 diff --git a/interface/resources/meshes/defaultAvatar_full/defaultAvatar_full.fbx b/interface/resources/meshes/defaultAvatar_full/defaultAvatar_full.fbx new file mode 100644 index 0000000000..71bc127c41 Binary files /dev/null and b/interface/resources/meshes/defaultAvatar_full/defaultAvatar_full.fbx differ diff --git a/interface/resources/meshes/defaultAvatar_full/textures/visor.png b/interface/resources/meshes/defaultAvatar_full/textures/visor.png new file mode 100644 index 0000000000..e4e6292b2c Binary files /dev/null and b/interface/resources/meshes/defaultAvatar_full/textures/visor.png differ diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index acdfd8cfc9..503acc2ce3 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -115,7 +115,7 @@ #include "devices/MIDIManager.h" #include "devices/OculusManager.h" #include "devices/TV3DManager.h" -#include "devices/3Dconnexion.h" +#include "devices/3DConnexionClient.h" #include "scripting/AccountScriptingInterface.h" #include "scripting/AudioDeviceScriptingInterface.h" @@ -641,7 +641,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : applicationUpdater->checkForUpdate(); // the 3Dconnexion device wants to be initiliazed after a window is displayed. - ConnexionClient::init(); + ConnexionClient::getInstance().init(); auto& packetReceiver = nodeList->getPacketReceiver(); packetReceiver.registerListener(PacketType::DomainConnectionDenied, this, "handleDomainConnectionDeniedPacket"); @@ -754,7 +754,7 @@ Application::~Application() { Leapmotion::destroy(); RealSense::destroy(); - ConnexionClient::destroy(); + ConnexionClient::getInstance().destroy(); qInstallMessageHandler(NULL); // NOTE: Do this as late as possible so we continue to get our log messages } @@ -893,14 +893,15 @@ void Application::paintGL() { { float ratio = ((float)QApplication::desktop()->windowHandle()->devicePixelRatio() * getRenderResolutionScale()); - auto mirrorViewport = glm::ivec4(0, 0, _mirrorViewRect.width() * ratio, _mirrorViewRect.height() * ratio); - auto mirrorViewportDest = mirrorViewport; + // Flip the src and destination rect horizontally to do the mirror + auto mirrorRect = glm::ivec4(0, 0, _mirrorViewRect.width() * ratio, _mirrorViewRect.height() * ratio); + auto mirrorRectDest = glm::ivec4(mirrorRect.z, mirrorRect.y, mirrorRect.x, mirrorRect.w); auto selfieFbo = DependencyManager::get()->getSelfieFramebuffer(); gpu::Batch batch; batch.setFramebuffer(selfieFbo); batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, glm::vec4(0.0f, 0.0f, 0.0f, 0.0f)); - batch.blit(primaryFbo, mirrorViewport, selfieFbo, mirrorViewportDest); + batch.blit(primaryFbo, mirrorRect, selfieFbo, mirrorRectDest); batch.setFramebuffer(nullptr); renderArgs._context->render(batch); } @@ -991,8 +992,14 @@ void Application::paintGL() { auto geometryCache = DependencyManager::get(); auto primaryFbo = DependencyManager::get()->getPrimaryFramebufferDepthColor(); gpu::Batch batch; - batch.blit(primaryFbo, glm::ivec4(0, 0, _renderResolution.x, _renderResolution.y), - nullptr, glm::ivec4(0, 0, _glWidget->getDeviceSize().width(), _glWidget->getDeviceSize().height())); + + if (renderArgs._renderMode == RenderArgs::MIRROR_RENDER_MODE) { + batch.blit(primaryFbo, glm::ivec4(0, 0, _renderResolution.x, _renderResolution.y), + nullptr, glm::ivec4(_glWidget->getDeviceSize().width(), 0, 0, _glWidget->getDeviceSize().height())); + } else { + batch.blit(primaryFbo, glm::ivec4(0, 0, _renderResolution.x, _renderResolution.y), + nullptr, glm::ivec4(0, 0, _glWidget->getDeviceSize().width(), _glWidget->getDeviceSize().height())); + } batch.setFramebuffer(nullptr); @@ -2013,6 +2020,7 @@ void Application::setActiveFaceTracker() { #ifdef HAVE_DDE bool isUsingDDE = Menu::getInstance()->isOptionChecked(MenuOption::UseCamera); Menu::getInstance()->getActionForOption(MenuOption::BinaryEyelidControl)->setVisible(isUsingDDE); + Menu::getInstance()->getActionForOption(MenuOption::CoupleEyelids)->setVisible(isUsingDDE); Menu::getInstance()->getActionForOption(MenuOption::UseAudioForMouth)->setVisible(isUsingDDE); Menu::getInstance()->getActionForOption(MenuOption::VelocityFilter)->setVisible(isUsingDDE); Menu::getInstance()->getActionForOption(MenuOption::CalibrateCamera)->setVisible(isUsingDDE); diff --git a/interface/src/GLCanvas.cpp b/interface/src/GLCanvas.cpp index 705a98b855..57c6ae40a7 100644 --- a/interface/src/GLCanvas.cpp +++ b/interface/src/GLCanvas.cpp @@ -19,7 +19,22 @@ const int MSECS_PER_FRAME_WHEN_THROTTLED = 66; -GLCanvas::GLCanvas() : QGLWidget(QGL::NoDepthBuffer | QGL::NoStencilBuffer), +static QGLFormat& getDesiredGLFormat() { + // Specify an OpenGL 3.3 format using the Core profile. + // That is, no old-school fixed pipeline functionality + static QGLFormat glFormat; + static std::once_flag once; + std::call_once(once, [] { + glFormat.setVersion(4, 1); + glFormat.setProfile(QGLFormat::CoreProfile); // Requires >=Qt-4.8.0 + glFormat.setSampleBuffers(false); + glFormat.setDepth(false); + glFormat.setStencil(false); + }); + return glFormat; +} + +GLCanvas::GLCanvas() : QGLWidget(getDesiredGLFormat()), _throttleRendering(false), _idleRenderInterval(MSECS_PER_FRAME_WHEN_THROTTLED) { diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 1cbe127857..6fcc46478e 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -29,7 +29,7 @@ #include "devices/Faceshift.h" #include "devices/RealSense.h" #include "devices/SixenseManager.h" -#include "devices/3Dconnexion.h" +#include "devices/3DConnexionClient.h" #include "MainWindow.h" #include "scripting/MenuScriptingInterface.h" #if defined(Q_OS_MAC) || defined(Q_OS_WIN) @@ -421,6 +421,8 @@ Menu::Menu() { faceTrackingMenu->addSeparator(); QAction* binaryEyelidControl = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::BinaryEyelidControl, 0, true); binaryEyelidControl->setVisible(true); // DDE face tracking is on by default + QAction* coupleEyelids = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::CoupleEyelids, 0, true); + coupleEyelids->setVisible(true); // DDE face tracking is on by default QAction* useAudioForMouth = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::UseAudioForMouth, 0, true); useAudioForMouth->setVisible(true); // DDE face tracking is on by default QAction* ddeFiltering = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::VelocityFilter, 0, true); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 62a1ae3b0f..bd6c982d70 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -165,6 +165,7 @@ namespace MenuOption { const QString ControlWithSpeech = "Control With Speech"; const QString CopyAddress = "Copy Address to Clipboard"; const QString CopyPath = "Copy Path to Clipboard"; + const QString CoupleEyelids = "Couple Eyelids"; const QString DebugAmbientOcclusion = "Debug Ambient Occlusion"; const QString DecreaseAvatarSize = "Decrease Avatar Size"; const QString DeleteBookmark = "Delete Bookmark..."; diff --git a/interface/src/audio/AudioScope.cpp b/interface/src/audio/AudioScope.cpp index 8f9d072b8e..d0567c55d7 100644 --- a/interface/src/audio/AudioScope.cpp +++ b/interface/src/audio/AudioScope.cpp @@ -137,7 +137,7 @@ void AudioScope::render(RenderArgs* renderArgs, int width, int height) { batch.setProjectionTransform(legacyProjection); batch.setModelTransform(Transform()); batch.setViewTransform(Transform()); - batch._glLineWidth(1.0f); // default + geometryCache->renderQuad(batch, x, y, w, h, backgroundColor, _audioScopeBackground); geometryCache->renderGrid(batch, x, y, w, h, gridRows, gridCols, gridColor, _audioScopeGrid); renderLineStrip(batch, _inputID, inputColor, x, y, _samplesPerScope, _scopeInputOffset, _scopeInput); diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index e29e5e4408..b25eaa4030 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -936,8 +936,14 @@ void Avatar::setFaceModelURL(const QUrl& faceModelURL) { void Avatar::setSkeletonModelURL(const QUrl& skeletonModelURL) { AvatarData::setSkeletonModelURL(skeletonModelURL); + const QUrl DEFAULT_FULL_MODEL_URL = QUrl::fromLocalFile(PathUtils::resourcesPath() + "meshes/defaultAvatar_full.fst"); const QUrl DEFAULT_SKELETON_MODEL_URL = QUrl::fromLocalFile(PathUtils::resourcesPath() + "meshes/defaultAvatar_body.fst"); - _skeletonModel.setURL(_skeletonModelURL, DEFAULT_SKELETON_MODEL_URL, true, !isMyAvatar()); + if (isMyAvatar()) { + _skeletonModel.setURL(_skeletonModelURL, + getUseFullAvatar() ? DEFAULT_FULL_MODEL_URL : DEFAULT_SKELETON_MODEL_URL, true, !isMyAvatar()); + } else { + _skeletonModel.setURL(_skeletonModelURL, DEFAULT_SKELETON_MODEL_URL, true, !isMyAvatar()); + } } void Avatar::setAttachmentData(const QVector& attachmentData) { diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index 6035c44389..a51da387d0 100644 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -150,6 +150,7 @@ public: Q_INVOKABLE glm::vec3 getAngularVelocity() const { return _angularVelocity; } Q_INVOKABLE glm::vec3 getAngularAcceleration() const { return _angularAcceleration; } + virtual bool getUseFullAvatar() const { return false; } /// Scales a world space position vector relative to the avatar position and scale /// \param vector position to be scaled. Will store the result @@ -169,9 +170,6 @@ public: void setMotionState(AvatarMotionState* motionState) { _motionState = motionState; } AvatarMotionState* getMotionState() { return _motionState; } - signals: - void collisionWithAvatar(const QUuid& myUUID, const QUuid& theirUUID, const CollisionInfo& collision); - protected: SkeletonModel _skeletonModel; glm::vec3 _skeletonOffset; diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index bfa2e437a1..06a29e5d82 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -397,7 +397,7 @@ void Head::renderLookatVectors(RenderArgs* renderArgs, glm::vec3 leftEyePosition auto& batch = *renderArgs->_batch; auto transform = Transform{}; batch.setModelTransform(transform); - batch._glLineWidth(2.0f); + // FIXME: THe line width of 2.0f is not supported anymore, we ll need a workaround auto deferredLighting = DependencyManager::get(); deferredLighting->bindSimpleProgram(batch); diff --git a/interface/src/avatar/ModelReferential.cpp b/interface/src/avatar/ModelReferential.cpp index 53eae21ff7..46290b17b5 100644 --- a/interface/src/avatar/ModelReferential.cpp +++ b/interface/src/avatar/ModelReferential.cpp @@ -107,7 +107,7 @@ JointReferential::JointReferential(Referential* referential, EntityTree* tree, A EntityItemPointer item = _tree->findEntityByID(_entityID); const Model* model = getModel(item); - if (!isValid() || model == NULL || _jointIndex >= (uint32_t)(model->getJointStateCount())) { + if (isValid() && model != NULL && _jointIndex < (uint32_t)(model->getJointStateCount())) { _lastRefDimension = item->getDimensions(); model->getJointRotationInWorldFrame(_jointIndex, _refRotation); model->getJointPositionInWorldFrame(_jointIndex, _refPosition); diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 0c01ce0249..7d486dcf50 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include @@ -48,9 +47,6 @@ #include "Util.h" #include "InterfaceLogging.h" -#include "gpu/GLBackend.h" - - using namespace std; const glm::vec3 DEFAULT_UP_DIRECTION(0.0f, 1.0f, 0.0f); @@ -104,7 +100,6 @@ MyAvatar::MyAvatar(RigPointer rig) : _rig(rig), _prevShouldDrawHead(true) { - ShapeCollider::initDispatchTable(); for (int i = 0; i < MAX_DRIVE_KEYS; i++) { _driveKeys[i] = 0.0f; } @@ -625,6 +620,12 @@ float loadSetting(QSettings& settings, const char* name, float defaultValue) { return value; } +void MyAvatar::setEnableRigAnimations(bool isEnabled) { + Settings settings; + settings.setValue("enableRig", isEnabled); + _rig->setEnableRig(isEnabled); +} + void MyAvatar::loadData() { Settings settings; settings.beginGroup("Avatar"); diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 129a05f93b..13223b66b9 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -72,6 +72,7 @@ public: Q_INVOKABLE AnimationDetails getAnimationDetailsByRole(const QString& role); Q_INVOKABLE AnimationDetails getAnimationDetails(const QString& url); void clearJointAnimationPriorities(); + Q_INVOKABLE void setEnableRigAnimations(bool isEnabled); // get/set avatar data void saveData(); @@ -115,7 +116,7 @@ public: Q_INVOKABLE void useHeadAndBodyURLs(const QUrl& headURL, const QUrl& bodyURL, const QString& headName = QString(), const QString& bodyName = QString()); - Q_INVOKABLE bool getUseFullAvatar() const { return _useFullAvatar; } + Q_INVOKABLE virtual bool getUseFullAvatar() const { return _useFullAvatar; } Q_INVOKABLE const QUrl& getFullAvatarURLFromPreferences() const { return _fullAvatarURLFromPreferences; } Q_INVOKABLE const QUrl& getHeadURLFromPreferences() const { return _headURLFromPreferences; } Q_INVOKABLE const QUrl& getBodyURLFromPreferences() const { return _skeletonURLFromPreferences; } diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 1b3298c75d..83de16ab4f 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -42,7 +42,23 @@ SkeletonModel::~SkeletonModel() { void SkeletonModel::initJointStates(QVector states) { const FBXGeometry& geometry = _geometry->getFBXGeometry(); glm::mat4 parentTransform = glm::scale(_scale) * glm::translate(_offset) * geometry.offset; - _boundingRadius = _rig->initJointStates(states, parentTransform); + + int rootJointIndex = geometry.rootJointIndex; + int leftHandJointIndex = geometry.leftHandJointIndex; + int leftElbowJointIndex = leftHandJointIndex >= 0 ? geometry.joints.at(leftHandJointIndex).parentIndex : -1; + int leftShoulderJointIndex = leftElbowJointIndex >= 0 ? geometry.joints.at(leftElbowJointIndex).parentIndex : -1; + int rightHandJointIndex = geometry.rightHandJointIndex; + int rightElbowJointIndex = rightHandJointIndex >= 0 ? geometry.joints.at(rightHandJointIndex).parentIndex : -1; + int rightShoulderJointIndex = rightElbowJointIndex >= 0 ? geometry.joints.at(rightElbowJointIndex).parentIndex : -1; + + _boundingRadius = _rig->initJointStates(states, parentTransform, + rootJointIndex, + leftHandJointIndex, + leftElbowJointIndex, + leftShoulderJointIndex, + rightHandJointIndex, + rightElbowJointIndex, + rightShoulderJointIndex); // Determine the default eye position for avatar scale = 1.0 int headJointIndex = _geometry->getFBXGeometry().headJointIndex; @@ -81,10 +97,11 @@ void SkeletonModel::initJointStates(QVector states) { } const float PALM_PRIORITY = DEFAULT_PRIORITY; -const float LEAN_PRIORITY = DEFAULT_PRIORITY; void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) { - _rig->computeMotionAnimationState(deltaTime, _owningAvatar->getPosition(), _owningAvatar->getVelocity(), _owningAvatar->getOrientation()); + if (_owningAvatar->isMyAvatar()) { + _rig->computeMotionAnimationState(deltaTime, _owningAvatar->getPosition(), _owningAvatar->getVelocity(), _owningAvatar->getOrientation()); + } Model::updateRig(deltaTime, parentTransform); if (_owningAvatar->isMyAvatar()) { const FBXGeometry& geometry = _geometry->getFBXGeometry(); @@ -227,7 +244,7 @@ void SkeletonModel::applyPalmData(int jointIndex, PalmData& palm) { palmRotation = rotationBetween(palmRotation * glm::vec3(-sign, 0.0f, 0.0f), fingerDirection) * palmRotation; if (Menu::getInstance()->isOptionChecked(MenuOption::AlternateIK)) { - setHandPosition(jointIndex, palmPosition, palmRotation); + _rig->setHandPosition(jointIndex, palmPosition, palmRotation, extractUniformScale(_scale), PALM_PRIORITY); } else if (Menu::getInstance()->isOptionChecked(MenuOption::AlignForearmsWithWrists)) { float forearmLength = geometry.joints.at(jointIndex).distanceToParent * extractUniformScale(_scale); glm::vec3 forearm = palmRotation * glm::vec3(sign * forearmLength, 0.0f, 0.0f); @@ -248,7 +265,8 @@ void SkeletonModel::renderJointConstraints(gpu::Batch& batch, int jointIndex) { const FBXGeometry& geometry = _geometry->getFBXGeometry(); const float BASE_DIRECTION_SIZE = 0.3f; float directionSize = BASE_DIRECTION_SIZE * extractUniformScale(_scale); - batch._glLineWidth(3.0f); + // FIXME: THe line width of 3.0f is not supported anymore, we ll need a workaround + do { const FBXJoint& joint = geometry.joints.at(jointIndex); const JointState& jointState = _rig->getJointState(jointIndex); @@ -332,69 +350,6 @@ void SkeletonModel::renderOrientationDirections(gpu::Batch& batch, int jointInde geometryCache->renderLine(batch, position, pFront, blue, jointLineIDs._front); } - - -void SkeletonModel::setHandPosition(int jointIndex, const glm::vec3& position, const glm::quat& rotation) { - // this algorithm is from sample code from sixense - const FBXGeometry& geometry = _geometry->getFBXGeometry(); - int elbowJointIndex = geometry.joints.at(jointIndex).parentIndex; - if (elbowJointIndex == -1) { - return; - } - int shoulderJointIndex = geometry.joints.at(elbowJointIndex).parentIndex; - glm::vec3 shoulderPosition; - if (!getJointPosition(shoulderJointIndex, shoulderPosition)) { - return; - } - // precomputed lengths - float scale = extractUniformScale(_scale); - float upperArmLength = geometry.joints.at(elbowJointIndex).distanceToParent * scale; - float lowerArmLength = geometry.joints.at(jointIndex).distanceToParent * scale; - - // first set wrist position - glm::vec3 wristPosition = position; - - glm::vec3 shoulderToWrist = wristPosition - shoulderPosition; - float distanceToWrist = glm::length(shoulderToWrist); - - // prevent gimbal lock - if (distanceToWrist > upperArmLength + lowerArmLength - EPSILON) { - distanceToWrist = upperArmLength + lowerArmLength - EPSILON; - shoulderToWrist = glm::normalize(shoulderToWrist) * distanceToWrist; - wristPosition = shoulderPosition + shoulderToWrist; - } - - // cosine of angle from upper arm to hand vector - float cosA = (upperArmLength * upperArmLength + distanceToWrist * distanceToWrist - lowerArmLength * lowerArmLength) / - (2 * upperArmLength * distanceToWrist); - float mid = upperArmLength * cosA; - float height = sqrt(upperArmLength * upperArmLength + mid * mid - 2 * upperArmLength * mid * cosA); - - // direction of the elbow - glm::vec3 handNormal = glm::cross(rotation * glm::vec3(0.0f, 1.0f, 0.0f), shoulderToWrist); // elbow rotating with wrist - glm::vec3 relaxedNormal = glm::cross(glm::vec3(0.0f, 1.0f, 0.0f), shoulderToWrist); // elbow pointing straight down - const float NORMAL_WEIGHT = 0.5f; - glm::vec3 finalNormal = glm::mix(relaxedNormal, handNormal, NORMAL_WEIGHT); - - bool rightHand = (jointIndex == geometry.rightHandJointIndex); - if (rightHand ? (finalNormal.y > 0.0f) : (finalNormal.y < 0.0f)) { - finalNormal.y = 0.0f; // dont allow elbows to point inward (y is vertical axis) - } - - glm::vec3 tangent = glm::normalize(glm::cross(shoulderToWrist, finalNormal)); - - // ik solution - glm::vec3 elbowPosition = shoulderPosition + glm::normalize(shoulderToWrist) * mid - tangent * height; - glm::vec3 forwardVector(rightHand ? -1.0f : 1.0f, 0.0f, 0.0f); - glm::quat shoulderRotation = rotationBetween(forwardVector, elbowPosition - shoulderPosition); - - _rig->setJointRotationInBindFrame(shoulderJointIndex, shoulderRotation, PALM_PRIORITY); - _rig->setJointRotationInBindFrame(elbowJointIndex, - rotationBetween(shoulderRotation * forwardVector, wristPosition - elbowPosition) * - shoulderRotation, PALM_PRIORITY); - _rig->setJointRotationInBindFrame(jointIndex, rotation, PALM_PRIORITY); -} - bool SkeletonModel::getLeftHandPosition(glm::vec3& position) const { return getJointPositionInWorldFrame(getLeftHandJointIndex(), position); } diff --git a/interface/src/avatar/SkeletonModel.h b/interface/src/avatar/SkeletonModel.h index ecc5c80118..a13d3c4e75 100644 --- a/interface/src/avatar/SkeletonModel.h +++ b/interface/src/avatar/SkeletonModel.h @@ -131,11 +131,6 @@ private: QHash _jointOrientationLines; int _triangleFanID; - /// \param jointIndex index of joint in model - /// \param position position of joint in model-frame - /// \param rotation rotation of joint in model-frame - void setHandPosition(int jointIndex, const glm::vec3& position, const glm::quat& rotation); - bool getEyeModelPositions(glm::vec3& firstEyePosition, glm::vec3& secondEyePosition) const; Avatar* _owningAvatar; diff --git a/interface/src/devices/3Dconnexion.cpp b/interface/src/devices/3DConnexionClient.cpp similarity index 87% rename from interface/src/devices/3Dconnexion.cpp rename to interface/src/devices/3DConnexionClient.cpp index ef66e6660b..7459f7da2a 100755 --- a/interface/src/devices/3Dconnexion.cpp +++ b/interface/src/devices/3DConnexionClient.cpp @@ -1,6 +1,6 @@ // -// 3DConnexion.cpp -// hifi +// 3DConnexionClient.cpp +// interface/src/devices // // Created by MarcelEdward Verhagen on 09-06-15. // Copyright 2015 High Fidelity, Inc. @@ -9,7 +9,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "3Dconnexion.h" +#include "3DConnexionClient.h" #include "UserActivityLogger.h" const float MAX_AXIS = 75.0f; // max forward = 2x speed @@ -28,7 +28,6 @@ ConnexionData::ConnexionData() { } void ConnexionData::handleAxisEvent() { - //qCWarning(interfaceapp) << "pos state x = " << cc_position.x << " y = " << cc_position.y << " z = " << cc_position.z << " Rotation x = " << cc_rotation.x << " y = " << cc_rotation.y << " z = " << cc_rotation.z; _axisStateMap[makeInput(ROTATION_AXIS_Y_POS).getChannel()] = (cc_rotation.y > 0.0f) ? cc_rotation.y / MAX_AXIS : 0.0f; _axisStateMap[makeInput(ROTATION_AXIS_Y_NEG).getChannel()] = (cc_rotation.y < 0.0f) ? -cc_rotation.y / MAX_AXIS : 0.0f; _axisStateMap[makeInput(POSITION_AXIS_X_POS).getChannel()] = (cc_position.x > 0.0f) ? cc_position.x / MAX_AXIS : 0.0f; @@ -148,7 +147,7 @@ UserInputMapper::Input ConnexionData::makeInput(ConnexionData::PositionChannel a void ConnexionData::update() { // the update is done in the ConnexionClient class. - // for windows in the nativeEventFilter the inputmapper is connected or registed or removed when an 3Dconnnexion device is attached or deteched + // for windows in the nativeEventFilter the inputmapper is connected or registed or removed when an 3Dconnnexion device is attached or detached // for osx the api will call DeviceAddedHandler or DeviceRemoveHandler when a 3Dconnexion device is attached or detached } @@ -157,40 +156,32 @@ ConnexionClient& ConnexionClient::getInstance() { return sharedInstance; } -#ifdef HAVE_CONNEXIONCLIENT +#ifdef HAVE_3DCONNEXIONCLIENT -#ifdef _WIN32 +#ifdef Q_OS_WIN -static ConnexionClient* gMouseInput = 0; - -void ConnexionClient::toggleConnexion(bool shouldEnable) -{ +void ConnexionClient::toggleConnexion(bool shouldEnable) { ConnexionData& connexiondata = ConnexionData::getInstance(); if (shouldEnable && connexiondata.getDeviceID() == 0) { - ConnexionClient::init(); + init(); } if (!shouldEnable && connexiondata.getDeviceID() != 0) { - ConnexionClient::destroy(); + destroy(); } - } void ConnexionClient::init() { if (Menu::getInstance()->isOptionChecked(MenuOption::Connexion)) { - ConnexionClient& cclient = ConnexionClient::getInstance(); - cclient.fLast3dmouseInputTime = 0; + fLast3dmouseInputTime = 0; - cclient.InitializeRawInput(GetActiveWindow()); + InitializeRawInput(GetActiveWindow()); - gMouseInput = &cclient; - - QAbstractEventDispatcher::instance()->installNativeEventFilter(&cclient); + QAbstractEventDispatcher::instance()->installNativeEventFilter(this); } } void ConnexionClient::destroy() { - ConnexionClient& cclient = ConnexionClient::getInstance(); - QAbstractEventDispatcher::instance()->removeNativeEventFilter(&cclient); + QAbstractEventDispatcher::instance()->removeNativeEventFilter(this); ConnexionData& connexiondata = ConnexionData::getInstance(); int deviceid = connexiondata.getDeviceID(); connexiondata.setDeviceID(0); @@ -225,15 +216,15 @@ enum ConnexionPid { // e3dmouse_virtual_key enum V3dk { - V3DK_INVALID = 0 - , V3DK_MENU = 1, V3DK_FIT - , V3DK_TOP, V3DK_LEFT, V3DK_RIGHT, V3DK_FRONT, V3DK_BOTTOM, V3DK_BACK - , V3DK_CW, V3DK_CCW - , V3DK_ISO1, V3DK_ISO2 - , V3DK_1, V3DK_2, V3DK_3, V3DK_4, V3DK_5, V3DK_6, V3DK_7, V3DK_8, V3DK_9, V3DK_10 - , V3DK_ESC, V3DK_ALT, V3DK_SHIFT, V3DK_CTRL - , V3DK_ROTATE, V3DK_PANZOOM, V3DK_DOMINANT - , V3DK_PLUS, V3DK_MINUS + V3DK_INVALID = 0, + V3DK_MENU = 1, V3DK_FIT, + V3DK_TOP, V3DK_LEFT, V3DK_RIGHT, V3DK_FRONT, V3DK_BOTTOM, V3DK_BACK, + V3DK_CW, V3DK_CCW, + V3DK_ISO1, V3DK_ISO2, + V3DK_1, V3DK_2, V3DK_3, V3DK_4, V3DK_5, V3DK_6, V3DK_7, V3DK_8, V3DK_9, V3DK_10, + V3DK_ESC, V3DK_ALT, V3DK_SHIFT, V3DK_CTRL, + V3DK_ROTATE, V3DK_PANZOOM, V3DK_DOMINANT, + V3DK_PLUS, V3DK_MINUS }; struct tag_VirtualKeys { @@ -244,33 +235,33 @@ struct tag_VirtualKeys { // e3dmouse_virtual_key static const V3dk SpaceExplorerKeys[] = { - V3DK_INVALID // there is no button 0 - , V3DK_1, V3DK_2 - , V3DK_TOP, V3DK_LEFT, V3DK_RIGHT, V3DK_FRONT - , V3DK_ESC, V3DK_ALT, V3DK_SHIFT, V3DK_CTRL - , V3DK_FIT, V3DK_MENU - , V3DK_PLUS, V3DK_MINUS - , V3DK_ROTATE + V3DK_INVALID, // there is no button 0 + V3DK_1, V3DK_2, + V3DK_TOP, V3DK_LEFT, V3DK_RIGHT, V3DK_FRONT, + V3DK_ESC, V3DK_ALT, V3DK_SHIFT, V3DK_CTRL, + V3DK_FIT, V3DK_MENU, + V3DK_PLUS, V3DK_MINUS, + V3DK_ROTATE }; //e3dmouse_virtual_key static const V3dk SpacePilotKeys[] = { - V3DK_INVALID - , V3DK_1, V3DK_2, V3DK_3, V3DK_4, V3DK_5, V3DK_6 - , V3DK_TOP, V3DK_LEFT, V3DK_RIGHT, V3DK_FRONT - , V3DK_ESC, V3DK_ALT, V3DK_SHIFT, V3DK_CTRL - , V3DK_FIT, V3DK_MENU - , V3DK_PLUS, V3DK_MINUS - , V3DK_DOMINANT, V3DK_ROTATE + V3DK_INVALID, + V3DK_1, V3DK_2, V3DK_3, V3DK_4, V3DK_5, V3DK_6, + V3DK_TOP, V3DK_LEFT, V3DK_RIGHT, V3DK_FRONT, + V3DK_ESC, V3DK_ALT, V3DK_SHIFT, V3DK_CTRL, + V3DK_FIT, V3DK_MENU, + V3DK_PLUS, V3DK_MINUS, + V3DK_DOMINANT, V3DK_ROTATE, }; static const struct tag_VirtualKeys _3dmouseVirtualKeys[] = { - CONNEXIONPID_SPACEPILOT - , sizeof(SpacePilotKeys) / sizeof(SpacePilotKeys[0]) - , const_cast(SpacePilotKeys), - CONNEXIONPID_SPACEEXPLORER - , sizeof(SpaceExplorerKeys) / sizeof(SpaceExplorerKeys[0]) - , const_cast(SpaceExplorerKeys) + CONNEXIONPID_SPACEPILOT, + sizeof(SpacePilotKeys) / sizeof(SpacePilotKeys[0]), + const_cast(SpacePilotKeys), + CONNEXIONPID_SPACEEXPLORER, + sizeof(SpaceExplorerKeys) / sizeof(SpaceExplorerKeys[0]), + const_cast(SpaceExplorerKeys) }; // Converts a hid device keycode (button identifier) of a pre-2009 3Dconnexion USB device to the standard 3d mouse virtual key definition. @@ -282,10 +273,8 @@ static const struct tag_VirtualKeys _3dmouseVirtualKeys[] = { // to the standard 3d mouse virtual key definition. unsigned short HidToVirtualKey(unsigned long pid, unsigned short hidKeyCode) { unsigned short virtualkey = hidKeyCode; - for (size_t i = 0; iremoveDevice(deviceid); } - if (!ConnexionClient::Is3dmouseAttached()) { + if (!Is3dmouseAttached()) { return false; } @@ -318,8 +307,8 @@ bool ConnexionClient::RawInputEventFilter(void* msg, long* result) { if (message->message == WM_INPUT) { HRAWINPUT hRawInput = reinterpret_cast(message->lParam); - gMouseInput->OnRawInput(RIM_INPUT, hRawInput); - if (result != 0) { + OnRawInput(RIM_INPUT, hRawInput); + if (result != 0) { result = 0; } return true; @@ -327,15 +316,6 @@ bool ConnexionClient::RawInputEventFilter(void* msg, long* result) { return false; } -ConnexionClient::ConnexionClient() { - -} - -ConnexionClient::~ConnexionClient() { - ConnexionClient& cclient = ConnexionClient::getInstance(); - QAbstractEventDispatcher::instance()->removeNativeEventFilter(&cclient); -} - // Access the mouse parameters structure I3dMouseParam& ConnexionClient::MouseParams() { return f3dMouseParams; @@ -680,8 +660,6 @@ void ConnexionClient::OnRawInput(UINT nInputCode, HRAWINPUT hRawInput) { bool ConnexionClient::TranslateRawInputData(UINT nInputCode, PRAWINPUT pRawInput) { bool bIsForeground = (nInputCode == RIM_INPUT); - //qDebug("Rawinput.header.dwType=0x%x\n", pRawInput->header.dwType); - // We are not interested in keyboard or mouse data received via raw input if (pRawInput->header.dwType != RIM_TYPEHID) { return false; @@ -689,9 +667,9 @@ bool ConnexionClient::TranslateRawInputData(UINT nInputCode, PRAWINPUT pRawInput if (TRACE_RIDI_DEVICENAME == 1) { UINT dwSize = 0; - if (::GetRawInputDeviceInfo(pRawInput->header.hDevice, RIDI_DEVICENAME, NULL, &dwSize) == 0) { + if (::GetRawInputDeviceInfo(pRawInput->header.hDevice, RIDI_DEVICENAME, NULL, &dwSize) == 0) { std::vector szDeviceName(dwSize + 1); - if (::GetRawInputDeviceInfo(pRawInput->header.hDevice, RIDI_DEVICENAME, &szDeviceName[0], &dwSize) >0) { + if (::GetRawInputDeviceInfo(pRawInput->header.hDevice, RIDI_DEVICENAME, &szDeviceName[0], &dwSize) > 0) { qDebug("Device Name = %s\nDevice handle = 0x%x\n", &szDeviceName[0], pRawInput->header.hDevice); } } @@ -703,7 +681,7 @@ bool ConnexionClient::TranslateRawInputData(UINT nInputCode, PRAWINPUT pRawInput if (::GetRawInputDeviceInfo(pRawInput->header.hDevice, RIDI_DEVICEINFO, &sRidDeviceInfo, &cbSize) == cbSize) { if (TRACE_RIDI_DEVICEINFO == 1) { - switch (sRidDeviceInfo.dwType) { + switch (sRidDeviceInfo.dwType) { case RIM_TYPEMOUSE: qDebug("\tsRidDeviceInfo.dwType=RIM_TYPEMOUSE\n"); break; @@ -806,16 +784,15 @@ bool ConnexionClient::TranslateRawInputData(UINT nInputCode, PRAWINPUT pRawInput return false; } -MouseParameters::MouseParameters() : fNavigation(NAVIGATION_OBJECT_MODE) - , fPivot(PIVOT_AUTO) - , fPivotVisibility(PIVOT_SHOW) - , fIsLockHorizon(true) - , fIsPanZoom(true) - , fIsRotate(true) - , fSpeed(SPEED_LOW) { -} - -MouseParameters::~MouseParameters() { +MouseParameters::MouseParameters() : + fNavigation(NAVIGATION_OBJECT_MODE), + fPivot(PIVOT_AUTO), + fPivotVisibility(PIVOT_SHOW), + fIsLockHorizon(true), + fIsPanZoom(true), + fIsRotate(true), + fSpeed(SPEED_LOW) +{ } bool MouseParameters::IsPanZoom() const { @@ -831,15 +808,15 @@ MouseParameters::Speed MouseParameters::GetSpeed() const { } void MouseParameters::SetPanZoom(bool isPanZoom) { - fIsPanZoom=isPanZoom; + fIsPanZoom = isPanZoom; } void MouseParameters::SetRotate(bool isRotate) { - fIsRotate=isRotate; + fIsRotate = isRotate; } void MouseParameters::SetSpeed(Speed speed) { - fSpeed=speed; + fSpeed = speed; } MouseParameters::Navigation MouseParameters::GetNavigationMode() const { @@ -878,13 +855,6 @@ void MouseParameters::SetPivotVisibility(PivotVisibility visibility) { #else -#define WITH_SEPARATE_THREAD false // set to true or false - -// Make the linker happy for the framework check (see link below for more info) -// http://developer.apple.com/documentation/MacOSX/Conceptual/BPFrameworks/Concepts/WeakLinking.html - -extern int16_t SetConnexionHandlers(ConnexionMessageHandlerProc messageHandler, ConnexionAddedHandlerProc addedHandler, ConnexionRemovedHandlerProc removedHandler, bool useSeparateThread) __attribute__((weak_import)); - int fConnexionClientID; static ConnexionDeviceState lastState; @@ -893,20 +863,18 @@ static void DeviceAddedHandler(unsigned int connection); static void DeviceRemovedHandler(unsigned int connection); static void MessageHandler(unsigned int connection, unsigned int messageType, void *messageArgument); -void ConnexionClient::toggleConnexion(bool shouldEnable) -{ - if (shouldEnable && !ConnexionClient::Is3dmouseAttached()) { - ConnexionClient::init(); +void ConnexionClient::toggleConnexion(bool shouldEnable) { + if (shouldEnable && !Is3dmouseAttached()) { + init(); } - if (!shouldEnable && ConnexionClient::Is3dmouseAttached()) { - ConnexionClient::destroy(); + if (!shouldEnable && Is3dmouseAttached()) { + destroy(); } - } void ConnexionClient::init() { // Make sure the framework is installed - if (SetConnexionHandlers != NULL && Menu::getInstance()->isOptionChecked(MenuOption::Connexion)) { + if (Menu::getInstance()->isOptionChecked(MenuOption::Connexion)) { // Install message handler and register our client InstallConnexionHandlers(MessageHandler, DeviceAddedHandler, DeviceRemovedHandler); // Either use this to take over in our application only... does not work @@ -923,7 +891,7 @@ void ConnexionClient::init() { // use default switches ConnexionClientControl(fConnexionClientID, kConnexionCtlSetSwitches, kConnexionSwitchesDisabled, NULL); - if (ConnexionClient::Is3dmouseAttached() && connexiondata.getDeviceID() == 0) { + if (Is3dmouseAttached() && connexiondata.getDeviceID() == 0) { connexiondata.registerToUserInputMapper(*Application::getUserInputMapper()); connexiondata.assignDefaultInputMapping(*Application::getUserInputMapper()); UserActivityLogger::getInstance().connectedDevice("controller", "3Dconnexion"); @@ -1010,4 +978,4 @@ void MessageHandler(unsigned int connection, unsigned int messageType, void *mes #endif // __APPLE__ -#endif // HAVE_CONNEXIONCLIENT +#endif // HAVE_3DCONNEXIONCLIENT diff --git a/interface/src/devices/3Dconnexion.h b/interface/src/devices/3DConnexionClient.h similarity index 86% rename from interface/src/devices/3Dconnexion.h rename to interface/src/devices/3DConnexionClient.h index 28b4924e44..f0e9f10785 100755 --- a/interface/src/devices/3Dconnexion.h +++ b/interface/src/devices/3DConnexionClient.h @@ -1,5 +1,5 @@ -// 3DConnexion.h -// hifi +// 3DConnexionClient.h +// interface/src/devices // // Created by Marcel Verhagen on 09-06-15. // Copyright 2015 High Fidelity, Inc. @@ -8,8 +8,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#ifndef hifi_ConnexionClient_h -#define hifi_ConnexionClient_h +#ifndef hifi_3DConnexionClient_h +#define hifi_3DConnexionClient_h #include #include @@ -18,22 +18,22 @@ #include "ui/UserInputMapper.h" -#ifndef HAVE_CONNEXIONCLIENT +#ifndef HAVE_3DCONNEXIONCLIENT class ConnexionClient : public QObject { Q_OBJECT public: static ConnexionClient& getInstance(); - static void init() {}; - static void destroy() {}; - static bool Is3dmouseAttached() { return false; }; + void init() {}; + void destroy() {}; + bool Is3dmouseAttached() { return false; }; public slots: void toggleConnexion(bool shouldEnable) {}; }; -#endif // NOT_HAVE_CONNEXIONCLIENT +#endif // NOT_HAVE_3DCONNEXIONCLIENT -#ifdef HAVE_CONNEXIONCLIENT +#ifdef HAVE_3DCONNEXIONCLIENT // the windows connexion rawinput -#ifdef _WIN32 +#ifdef Q_OS_WIN #include "I3dMouseParams.h" #include @@ -45,7 +45,6 @@ public slots: class MouseParameters : public I3dMouseParam { public: MouseParameters(); - ~MouseParameters(); // I3dmouseSensor interface bool IsPanZoom() const; @@ -86,16 +85,14 @@ private: class ConnexionClient : public QObject, public QAbstractNativeEventFilter { Q_OBJECT public: - ConnexionClient(); - ~ConnexionClient(); + ConnexionClient() {}; - static ConnexionClient& getInstance(); - - ConnexionClient* client; - static void init(); - static void destroy(); - - static bool Is3dmouseAttached(); + static ConnexionClient& getInstance(); + void init(); + void destroy(); + bool Is3dmouseAttached(); + + ConnexionClient* client; I3dMouseParam& MouseParams(); const I3dMouseParam& MouseParams() const; @@ -107,7 +104,7 @@ public: virtual bool nativeEventFilter(const QByteArray& eventType, void* message, long* result) Q_DECL_OVERRIDE { MSG* msg = static_cast< MSG * >(message); - return ConnexionClient::RawInputEventFilter(message, result); + return RawInputEventFilter(message, result); } public slots: @@ -121,7 +118,7 @@ signals: private: bool InitializeRawInput(HWND hwndTarget); - static bool RawInputEventFilter(void* msg, long* result); + bool RawInputEventFilter(void* msg, long* result); void OnRawInput(UINT nInputCode, HRAWINPUT hRawInput); UINT GetRawInputBuffer(PRAWINPUT pData, PUINT pcbSize, UINT cbSizeHeader); @@ -166,16 +163,16 @@ class ConnexionClient : public QObject { Q_OBJECT public: static ConnexionClient& getInstance(); - static bool Is3dmouseAttached(); - static void init(); - static void destroy(); + void init(); + void destroy(); + bool Is3dmouseAttached(); public slots: void toggleConnexion(bool shouldEnable); }; #endif // __APPLE__ -#endif // HAVE_CONNEXIONCLIENT +#endif // HAVE_3DCONNEXIONCLIENT // connnects to the userinputmapper @@ -241,4 +238,4 @@ protected: AxisStateMap _axisStateMap; }; -#endif // defined(hifi_ConnexionClient_h) \ No newline at end of file +#endif // defined(hifi_3DConnexionClient_h) \ No newline at end of file diff --git a/interface/src/devices/DdeFaceTracker.cpp b/interface/src/devices/DdeFaceTracker.cpp index c9170bd413..396539c3cf 100644 --- a/interface/src/devices/DdeFaceTracker.cpp +++ b/interface/src/devices/DdeFaceTracker.cpp @@ -564,6 +564,13 @@ void DdeFaceTracker::decodePacket(const QByteArray& buffer) { eyeCoefficients[1] = _filteredEyeBlinks[1]; } + // Couple eyelid values if configured - use the most "open" value for both + if (Menu::getInstance()->isOptionChecked(MenuOption::CoupleEyelids)) { + float eyeCoefficient = std::min(eyeCoefficients[0], eyeCoefficients[1]); + eyeCoefficients[0] = eyeCoefficient; + eyeCoefficients[1] = eyeCoefficient; + } + // Use EyeBlink values to control both EyeBlink and EyeOpen if (eyeCoefficients[0] > 0) { _coefficients[_leftBlinkIndex] = eyeCoefficients[0]; diff --git a/interface/src/scripting/ControllerScriptingInterface.cpp b/interface/src/scripting/ControllerScriptingInterface.cpp index 7a3f4a99b5..feceecc3fd 100644 --- a/interface/src/scripting/ControllerScriptingInterface.cpp +++ b/interface/src/scripting/ControllerScriptingInterface.cpp @@ -24,7 +24,8 @@ ControllerScriptingInterface::ControllerScriptingInterface() : _mouseCaptured(false), _touchCaptured(false), - _wheelCaptured(false) + _wheelCaptured(false), + _actionsCaptured(false) { } diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index acc24ba2be..80f5ce2b69 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include @@ -32,7 +31,6 @@ #include "ui/AvatarInputs.h" const vec4 CONNECTION_STATUS_BORDER_COLOR{ 1.0f, 0.0f, 0.0f, 0.8f }; -const float CONNECTION_STATUS_BORDER_LINE_WIDTH = 4.0f; static const float ORTHO_NEAR_CLIP = -1000.0f; static const float ORTHO_FAR_CLIP = 1000.0f; @@ -137,8 +135,7 @@ void ApplicationOverlay::renderAudioScope(RenderArgs* renderArgs) { batch.setProjectionTransform(legacyProjection); batch.setModelTransform(Transform()); batch.setViewTransform(Transform()); - batch._glLineWidth(1.0f); // default - + // Render the audio scope DependencyManager::get()->render(renderArgs, width, height); } @@ -157,8 +154,7 @@ void ApplicationOverlay::renderOverlays(RenderArgs* renderArgs) { batch.setProjectionTransform(legacyProjection); batch.setModelTransform(Transform()); batch.setViewTransform(Transform()); - batch._glLineWidth(1.0f); // default - + // Render all of the Script based "HUD" aka 2D overlays. // note: we call them HUD, as opposed to 2D, only because there are some cases of 3D HUD overlays, like the // cameral controls for the edit.js @@ -195,6 +191,7 @@ void ApplicationOverlay::renderRearView(RenderArgs* renderArgs) { glm::vec2 texCoordMinCorner(0.0f, 0.0f); glm::vec2 texCoordMaxCorner(viewport.width() * renderRatio / float(selfieTexture->getWidth()), viewport.height() * renderRatio / float(selfieTexture->getHeight())); + geometryCache->useSimpleDrawPipeline(batch, true); batch.setResourceTexture(0, selfieTexture); geometryCache->renderQuad(batch, bottomLeft, topRight, texCoordMinCorner, texCoordMaxCorner, glm::vec4(1.0f, 1.0f, 1.0f, 1.0f)); @@ -247,7 +244,7 @@ void ApplicationOverlay::renderDomainConnectionStatusBorder(RenderArgs* renderAr batch.setModelTransform(Transform()); batch.setViewTransform(Transform()); batch.setResourceTexture(0, DependencyManager::get()->getWhiteTexture()); - batch._glLineWidth(CONNECTION_STATUS_BORDER_LINE_WIDTH); + // FIXME: THe line width of CONNECTION_STATUS_BORDER_LINE_WIDTH is not supported anymore, we ll need a workaround // TODO animate the disconnect border for some excitement while not connected? //double usecs = usecTimestampNow(); diff --git a/interface/src/ui/overlays/BillboardOverlay.cpp b/interface/src/ui/overlays/BillboardOverlay.cpp index 3bd1f56ba3..58790c4722 100644 --- a/interface/src/ui/overlays/BillboardOverlay.cpp +++ b/interface/src/ui/overlays/BillboardOverlay.cpp @@ -105,7 +105,7 @@ void BillboardOverlay::render(RenderArgs* args) { batch->setModelTransform(transform); batch->setResourceTexture(0, _texture->getGPUTexture()); - DependencyManager::get()->bindSimpleProgram(*batch, true, true, false, true); + DependencyManager::get()->bindSimpleProgram(*batch, true, false, false, true); DependencyManager::get()->renderQuad( *batch, topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight, glm::vec4(color.red / MAX_COLOR, color.green / MAX_COLOR, color.blue / MAX_COLOR, alpha) diff --git a/interface/src/ui/overlays/Circle3DOverlay.cpp b/interface/src/ui/overlays/Circle3DOverlay.cpp index 4e80ac5b63..588a5077b4 100644 --- a/interface/src/ui/overlays/Circle3DOverlay.cpp +++ b/interface/src/ui/overlays/Circle3DOverlay.cpp @@ -101,8 +101,9 @@ void Circle3DOverlay::render(RenderArgs* args) { Q_ASSERT(args->_batch); auto& batch = *args->_batch; - batch._glLineWidth(_lineWidth); - + + // FIXME: THe line width of _lineWidth is not supported anymore, we ll need a workaround + auto transform = _transform; transform.postScale(glm::vec3(getDimensions(), 1.0f)); batch.setModelTransform(transform); diff --git a/interface/src/ui/overlays/Grid3DOverlay.cpp b/interface/src/ui/overlays/Grid3DOverlay.cpp index 074ad3d17f..bfb0d1d9df 100644 --- a/interface/src/ui/overlays/Grid3DOverlay.cpp +++ b/interface/src/ui/overlays/Grid3DOverlay.cpp @@ -60,7 +60,6 @@ void Grid3DOverlay::render(RenderArgs* args) { // Minor grid { - batch->_glLineWidth(1.0f); auto position = glm::vec3(_minorGridWidth * (floorf(rotated.x / spacing) - MINOR_GRID_DIVISIONS / 2), spacing * (floorf(rotated.y / spacing) - MINOR_GRID_DIVISIONS / 2), getPosition().z); @@ -76,7 +75,6 @@ void Grid3DOverlay::render(RenderArgs* args) { // Major grid { - batch->_glLineWidth(4.0f); spacing *= _majorGridEvery; auto position = glm::vec3(spacing * (floorf(rotated.x / spacing) - MAJOR_GRID_DIVISIONS / 2), spacing * (floorf(rotated.y / spacing) - MAJOR_GRID_DIVISIONS / 2), @@ -86,6 +84,8 @@ void Grid3DOverlay::render(RenderArgs* args) { transform.setTranslation(position); transform.setScale(scale); + // FIXME: THe line width of 4.0f is not supported anymore, we ll need a workaround + batch->setModelTransform(transform); DependencyManager::get()->renderGrid(*batch, MAJOR_GRID_DIVISIONS, MAJOR_GRID_DIVISIONS, gridColor); diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index bce219b4b4..c4acdbb482 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -15,7 +15,6 @@ #include #include -#include #include #include "Application.h" @@ -119,7 +118,6 @@ void Overlays::renderHUD(RenderArgs* renderArgs) { batch.setProjectionTransform(legacyProjection); batch.setModelTransform(Transform()); batch.setViewTransform(Transform()); - batch._glLineWidth(1.0f); // default thisOverlay->render(renderArgs); } diff --git a/interface/src/ui/overlays/TextOverlay.cpp b/interface/src/ui/overlays/TextOverlay.cpp index e9fda2def8..6926e9b241 100644 --- a/interface/src/ui/overlays/TextOverlay.cpp +++ b/interface/src/ui/overlays/TextOverlay.cpp @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include diff --git a/libraries/animation/src/AnimationHandle.cpp b/libraries/animation/src/AnimationHandle.cpp index 605fb25f1c..ebf0e29b97 100644 --- a/libraries/animation/src/AnimationHandle.cpp +++ b/libraries/animation/src/AnimationHandle.cpp @@ -49,7 +49,7 @@ void AnimationHandle::setMaskedJoints(const QStringList& maskedJoints) { _jointMappings.clear(); } -void AnimationHandle::setRunning(bool running) { +void AnimationHandle::setRunning(bool running, bool doRestoreJoints) { if (running && isRunning()) { // if we're already running, this is the same as a restart setFrameIndex(getFirstFrame()); @@ -62,7 +62,9 @@ void AnimationHandle::setRunning(bool running) { } } else { _rig->removeRunningAnimation(getAnimationHandlePointer()); - restoreJoints(); + if (doRestoreJoints) { + restoreJoints(); + } replaceMatchingPriorities(0.0f); } emit runningChanged(isRunning()); @@ -71,7 +73,9 @@ void AnimationHandle::setRunning(bool running) { AnimationHandle::AnimationHandle(RigPointer rig) : QObject(rig.get()), _rig(rig), - _priority(1.0f) + _priority(1.0f), + _fade(0.0f), + _fadePerSecond(0.0f) { } diff --git a/libraries/animation/src/AnimationHandle.h b/libraries/animation/src/AnimationHandle.h index 42e564944e..65f7423aa5 100644 --- a/libraries/animation/src/AnimationHandle.h +++ b/libraries/animation/src/AnimationHandle.h @@ -64,6 +64,10 @@ public: void setPriority(float priority); float getPriority() const { return _priority; } void setMix(float mix) { _mix = mix; } + void setFade(float fade) { _fade = fade; } + float getFade() const { return _fade; } + void setFadePerSecond(float fadePerSecond) { _fadePerSecond = fadePerSecond; } + float getFadePerSecond() const { return _fadePerSecond; } void setMaskedJoints(const QStringList& maskedJoints); const QStringList& getMaskedJoints() const { return _maskedJoints; } @@ -87,7 +91,7 @@ public: void setLastFrame(float lastFrame) { _animationLoop.setLastFrame(lastFrame); } float getLastFrame() const { return _animationLoop.getLastFrame(); } - void setRunning(bool running); + void setRunning(bool running, bool restoreJoints = true); bool isRunning() const { return _animationLoop.isRunning(); } void setFrameIndex(float frameIndex) { _animationLoop.setFrameIndex(frameIndex); } @@ -111,7 +115,7 @@ signals: public slots: void start() { setRunning(true); } - void stop() { setRunning(false); } + void stop() { setRunning(false); _fadePerSecond = _fade = 0.0f; } private: @@ -120,7 +124,9 @@ private: QString _role; QUrl _url; float _priority; - float _mix; + float _mix; // How much of this animation to blend against what is already there. 1.0 sets to just this animation. + float _fade; // How far are we into full strength. 0.0 uses none of this animation, 1.0 (the max) is as much as possible. + float _fadePerSecond; // How fast should _fade change? +1.0 means _fade is increasing to 1.0 in 1 second. Negative is fading out. QStringList _maskedJoints; QVector _jointMappings; diff --git a/libraries/animation/src/AvatarRig.cpp b/libraries/animation/src/AvatarRig.cpp index 919ea43e7d..97fbb82944 100644 --- a/libraries/animation/src/AvatarRig.cpp +++ b/libraries/animation/src/AvatarRig.cpp @@ -20,15 +20,81 @@ void AvatarRig::updateJointState(int index, glm::mat4 parentTransform) { const FBXJoint& joint = state.getFBXJoint(); // compute model transforms - int parentIndex = joint.parentIndex; - if (parentIndex == -1) { + if (index == _rootJointIndex) { + // we always zero-out the translation part of an avatar's root join-transform. state.computeTransform(parentTransform); clearJointTransformTranslation(index); } else { // guard against out-of-bounds access to _jointStates - if (joint.parentIndex >= 0 && joint.parentIndex < _jointStates.size()) { + int parentIndex = joint.parentIndex; + if (parentIndex >= 0 && parentIndex < _jointStates.size()) { const JointState& parentState = _jointStates.at(parentIndex); state.computeTransform(parentState.getTransform(), parentState.getTransformChanged()); } } } + +void AvatarRig::setHandPosition(int jointIndex, + const glm::vec3& position, const glm::quat& rotation, + float scale, float priority) { + bool rightHand = (jointIndex == _rightHandJointIndex); + + int elbowJointIndex = rightHand ? _rightElbowJointIndex : _leftElbowJointIndex; + int shoulderJointIndex = rightHand ? _rightShoulderJointIndex : _leftShoulderJointIndex; + + // this algorithm is from sample code from sixense + if (elbowJointIndex == -1 || shoulderJointIndex == -1) { + return; + } + + glm::vec3 shoulderPosition; + if (!getJointPosition(shoulderJointIndex, shoulderPosition)) { + return; + } + + // precomputed lengths + float upperArmLength = _jointStates[elbowJointIndex].getFBXJoint().distanceToParent * scale; + float lowerArmLength = _jointStates[jointIndex].getFBXJoint().distanceToParent * scale; + + // first set wrist position + glm::vec3 wristPosition = position; + + glm::vec3 shoulderToWrist = wristPosition - shoulderPosition; + float distanceToWrist = glm::length(shoulderToWrist); + + // prevent gimbal lock + if (distanceToWrist > upperArmLength + lowerArmLength - EPSILON) { + distanceToWrist = upperArmLength + lowerArmLength - EPSILON; + shoulderToWrist = glm::normalize(shoulderToWrist) * distanceToWrist; + wristPosition = shoulderPosition + shoulderToWrist; + } + + // cosine of angle from upper arm to hand vector + float cosA = (upperArmLength * upperArmLength + distanceToWrist * distanceToWrist - lowerArmLength * lowerArmLength) / + (2 * upperArmLength * distanceToWrist); + float mid = upperArmLength * cosA; + float height = sqrt(upperArmLength * upperArmLength + mid * mid - 2 * upperArmLength * mid * cosA); + + // direction of the elbow + glm::vec3 handNormal = glm::cross(rotation * glm::vec3(0.0f, 1.0f, 0.0f), shoulderToWrist); // elbow rotating with wrist + glm::vec3 relaxedNormal = glm::cross(glm::vec3(0.0f, 1.0f, 0.0f), shoulderToWrist); // elbow pointing straight down + const float NORMAL_WEIGHT = 0.5f; + glm::vec3 finalNormal = glm::mix(relaxedNormal, handNormal, NORMAL_WEIGHT); + + if (rightHand ? (finalNormal.y > 0.0f) : (finalNormal.y < 0.0f)) { + finalNormal.y = 0.0f; // dont allow elbows to point inward (y is vertical axis) + } + + glm::vec3 tangent = glm::normalize(glm::cross(shoulderToWrist, finalNormal)); + + // ik solution + glm::vec3 elbowPosition = shoulderPosition + glm::normalize(shoulderToWrist) * mid - tangent * height; + glm::vec3 forwardVector(rightHand ? -1.0f : 1.0f, 0.0f, 0.0f); + glm::quat shoulderRotation = rotationBetween(forwardVector, elbowPosition - shoulderPosition); + + setJointRotationInBindFrame(shoulderJointIndex, shoulderRotation, priority); + setJointRotationInBindFrame(elbowJointIndex, + rotationBetween(shoulderRotation * forwardVector, wristPosition - elbowPosition) * + shoulderRotation, priority); + setJointRotationInBindFrame(jointIndex, rotation, priority); +} diff --git a/libraries/animation/src/AvatarRig.h b/libraries/animation/src/AvatarRig.h index 4a111a535b..5e2153e226 100644 --- a/libraries/animation/src/AvatarRig.h +++ b/libraries/animation/src/AvatarRig.h @@ -22,6 +22,8 @@ class AvatarRig : public Rig { public: ~AvatarRig() {} virtual void updateJointState(int index, glm::mat4 parentTransform); + virtual void setHandPosition(int jointIndex, const glm::vec3& position, const glm::quat& rotation, + float scale, float priority); }; #endif // hifi_AvatarRig_h diff --git a/libraries/animation/src/EntityRig.h b/libraries/animation/src/EntityRig.h index e8e15a5a28..9b519a7bfe 100644 --- a/libraries/animation/src/EntityRig.h +++ b/libraries/animation/src/EntityRig.h @@ -22,6 +22,8 @@ class EntityRig : public Rig { public: ~EntityRig() {} virtual void updateJointState(int index, glm::mat4 parentTransform); + virtual void setHandPosition(int jointIndex, const glm::vec3& position, const glm::quat& rotation, + float scale, float priority) {} }; #endif // hifi_EntityRig_h diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 8406b61d12..2d1856e41b 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -58,15 +58,19 @@ void Rig::removeAnimationHandle(const AnimationHandlePointer& handle) { void Rig::startAnimation(const QString& url, float fps, float priority, bool loop, bool hold, float firstFrame, float lastFrame, const QStringList& maskedJoints) { - //qCDebug(animation) << "startAnimation" << url << fps << priority << loop << hold << firstFrame << lastFrame << maskedJoints; + // This is different than startAnimationByRole, in which we use the existing values if the animation already exists. + // Here we reuse the animation handle if possible, but in any case, we set the values to those given (or defaulted). + AnimationHandlePointer handle = nullptr; foreach (const AnimationHandlePointer& candidate, _animationHandles) { if (candidate->getURL() == url) { - candidate->start(); - return; + handle = candidate; } } - AnimationHandlePointer handle = createAnimationHandle(); - handle->setURL(url); + if (!handle) { + handle = createAnimationHandle(); + handle->setURL(url); + } + handle->setFade(1.0f); // If you want to fade, use the startAnimationByRole system. handle->setFPS(fps); handle->setPriority(priority); handle->setLoop(loop); @@ -77,8 +81,8 @@ void Rig::startAnimation(const QString& url, float fps, float priority, handle->start(); } -void Rig::addAnimationByRole(const QString& role, const QString& url, float fps, float priority, - bool loop, bool hold, float firstFrame, float lastFrame, const QStringList& maskedJoints, bool startAutomatically) { +AnimationHandlePointer Rig::addAnimationByRole(const QString& role, const QString& url, float fps, float priority, + bool loop, bool hold, float firstFrame, float lastFrame, const QStringList& maskedJoints, bool startAutomatically) { // check for a configured animation for the role //qCDebug(animation) << "addAnimationByRole" << role << url << fps << priority << loop << hold << firstFrame << lastFrame << maskedJoints << startAutomatically; foreach (const AnimationHandlePointer& candidate, _animationHandles) { @@ -86,12 +90,38 @@ void Rig::addAnimationByRole(const QString& role, const QString& url, float fps, if (startAutomatically) { candidate->start(); } - return; + return candidate; } } AnimationHandlePointer handle = createAnimationHandle(); + QString standard = ""; + if (url.isEmpty()) { // Default animations for fight club + const QString& base = "https://hifi-public.s3.amazonaws.com/ozan/"; + if (role == "walk") { + standard = base + "support/FightClubBotTest1/Animations/standard_walk.fbx"; + lastFrame = 60; + } else if (role == "leftTurn") { + standard = base + "support/FightClubBotTest1/Animations/left_turn_noHipRotation.fbx"; + lastFrame = 29; + } else if (role == "rightTurn") { + standard = base + "support/FightClubBotTest1/Animations/right_turn_noHipRotation.fbx"; + lastFrame = 31; + } else if (role == "leftStrafe") { + standard = base + "animations/fightclub_bot_anims/side_step_left_inPlace.fbx"; + lastFrame = 31; + } else if (role == "rightStrafe") { + standard = base + "animations/fightclub_bot_anims/side_step_right_inPlace.fbx"; + lastFrame = 31; + } else if (role == "idle") { + standard = base + "support/FightClubBotTest1/Animations/standard_idle.fbx"; + fps = 25.0f; + } + if (!standard.isEmpty()) { + loop = true; + } + } handle->setRole(role); - handle->setURL(url); + handle->setURL(url.isEmpty() ? standard : url); handle->setFPS(fps); handle->setPriority(priority); handle->setLoop(loop); @@ -102,16 +132,18 @@ void Rig::addAnimationByRole(const QString& role, const QString& url, float fps, if (startAutomatically) { handle->start(); } + return handle; } void Rig::startAnimationByRole(const QString& role, const QString& url, float fps, float priority, bool loop, bool hold, float firstFrame, float lastFrame, const QStringList& maskedJoints) { - addAnimationByRole(role, url, fps, priority, loop, hold, firstFrame, lastFrame, maskedJoints, true); + AnimationHandlePointer handle = addAnimationByRole(role, url, fps, priority, loop, hold, firstFrame, lastFrame, maskedJoints, true); + handle->setFadePerSecond(1.0f); // For now. Could be individualized later. } void Rig::stopAnimationByRole(const QString& role) { foreach (const AnimationHandlePointer& handle, getRunningAnimations()) { if (handle->getRole() == role) { - handle->stop(); + handle->setFadePerSecond(-1.0f); // For now. Could be individualized later. } } } @@ -119,7 +151,8 @@ void Rig::stopAnimationByRole(const QString& role) { void Rig::stopAnimation(const QString& url) { foreach (const AnimationHandlePointer& handle, getRunningAnimations()) { if (handle->getURL() == url) { - handle->stop(); + handle->setFade(0.0f); // right away. Will be remove during updateAnimations, without locking + handle->setFadePerSecond(-1.0f); // so that the updateAnimation code notices } } } @@ -135,6 +168,14 @@ void Rig::addRunningAnimation(AnimationHandlePointer animationHandle) { bool Rig::isRunningAnimation(AnimationHandlePointer animationHandle) { return _runningAnimations.contains(animationHandle); } +bool Rig::isRunningRole(const QString& role) { //obviously, there are more efficient ways to do this + for (auto animation : _runningAnimations) { + if ((animation->getRole() == role) && (animation->getFadePerSecond() >= 0.0f)) { // Don't count those being faded out + return true; + } + } + return false; +} void Rig::deleteAnimations() { for (auto animation : _animationHandles) { @@ -143,8 +184,24 @@ void Rig::deleteAnimations() { _animationHandles.clear(); } -float Rig::initJointStates(QVector states, glm::mat4 parentTransform) { +float Rig::initJointStates(QVector states, glm::mat4 parentTransform, + int rootJointIndex, + int leftHandJointIndex, + int leftElbowJointIndex, + int leftShoulderJointIndex, + int rightHandJointIndex, + int rightElbowJointIndex, + int rightShoulderJointIndex) { _jointStates = states; + + _rootJointIndex = rootJointIndex; + _leftHandJointIndex = leftHandJointIndex; + _leftElbowJointIndex = leftElbowJointIndex; + _leftShoulderJointIndex = leftShoulderJointIndex; + _rightHandJointIndex = rightHandJointIndex; + _rightElbowJointIndex = rightElbowJointIndex; + _rightShoulderJointIndex = rightShoulderJointIndex; + initJointTransforms(parentTransform); int numStates = _jointStates.size(); @@ -356,47 +413,85 @@ glm::mat4 Rig::getJointVisibleTransform(int jointIndex) const { } void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPosition, const glm::vec3& worldVelocity, const glm::quat& worldRotation) { - if (_enableRig) { - glm::vec3 front = worldRotation * IDENTITY_FRONT; - float forwardSpeed = glm::dot(worldVelocity, front); - float rotationalSpeed = glm::angle(front, _lastFront) / deltaTime; - bool isWalking = std::abs(forwardSpeed) > 0.01f; - bool isTurning = std::abs(rotationalSpeed) > 0.5f; - - // Crude, until we have blending: - isTurning = isTurning && !isWalking; // Only one of walk/turn, walk wins. - isTurning = false; // FIXME - bool isIdle = !isWalking && !isTurning; - auto singleRole = [](bool walking, bool turning, bool idling) { - return walking ? "walk" : (turning ? "turn" : (idling ? "idle" : "")); - }; - QString toStop = singleRole(_isWalking && !isWalking, _isTurning && !isTurning, _isIdle && !isIdle); - if (!toStop.isEmpty()) { - //qCDebug(animation) << "isTurning" << isTurning << "fronts" << front << _lastFront << glm::angle(front, _lastFront) << rotationalSpeed; - stopAnimationByRole(toStop); - } - QString newRole = singleRole(isWalking && !_isWalking, isTurning && !_isTurning, isIdle && !_isIdle); - if (!newRole.isEmpty()) { - startAnimationByRole(newRole); - qCDebug(animation) << deltaTime << ":" << worldVelocity << "." << front << "=> " << forwardSpeed << newRole; - } - - _lastPosition = worldPosition; - _lastFront = front; - _isWalking = isWalking; - _isTurning = isTurning; - _isIdle = isIdle; + if (!_enableRig) { + return; } + bool isMoving = false; + glm::vec3 front = worldRotation * IDENTITY_FRONT; + float forwardSpeed = glm::dot(worldVelocity, front); + float rightLateralSpeed = glm::dot(worldVelocity, worldRotation * IDENTITY_RIGHT); + float rightTurningSpeed = glm::orientedAngle(front, _lastFront, IDENTITY_UP) / deltaTime; + auto updateRole = [&](const QString& role, bool isOn) { + isMoving = isMoving || isOn; + if (isOn) { + if (!isRunningRole(role)) { + qCDebug(animation) << "Rig STARTING" << role; + startAnimationByRole(role); + } + } else { + if (isRunningRole(role)) { + qCDebug(animation) << "Rig stopping" << role; + stopAnimationByRole(role); + } + } + }; + updateRole("walk", std::abs(forwardSpeed) > 0.01f); + bool isTurning = std::abs(rightTurningSpeed) > 0.5f; + updateRole("rightTurn", isTurning && (rightTurningSpeed > 0)); + updateRole("leftTurn", isTurning && (rightTurningSpeed < 0)); + bool isStrafing = std::abs(rightLateralSpeed) > 0.01f; + updateRole("rightStrafe", isStrafing && (rightLateralSpeed > 0.0f)); + updateRole("leftStrafe", isStrafing && (rightLateralSpeed < 0.0f)); + updateRole("idle", !isMoving); // Must be last, as it makes isMoving bogus. + _lastFront = front; + _lastPosition = worldPosition; } void Rig::updateAnimations(float deltaTime, glm::mat4 parentTransform) { - int nAnimationsSoFar = 0; + + // First normalize the fades so that they sum to 1.0. + // update the fade data in each animation (not normalized as they are an independent propert of animation) foreach (const AnimationHandlePointer& handle, _runningAnimations) { - handle->setMix(1.0f / ++nAnimationsSoFar); - handle->setPriority(1.0); + float fadePerSecond = handle->getFadePerSecond(); + float fade = handle->getFade(); + if (fadePerSecond != 0.0f) { + fade += fadePerSecond * deltaTime; + if ((0.0f >= fade) || (fade >= 1.0f)) { + fade = glm::clamp(fade, 0.0f, 1.0f); + handle->setFadePerSecond(0.0f); + } + handle->setFade(fade); + if (fade <= 0.0f) { // stop any finished animations now + handle->setRunning(false, false); // but do not restore joints as it causes a flicker + } + } + } + // sum the remaining fade data + float fadeTotal = 0.0f; + foreach (const AnimationHandlePointer& handle, _runningAnimations) { + fadeTotal += handle->getFade(); + } + float fadeSumSoFar = 0.0f; + foreach (const AnimationHandlePointer& handle, _runningAnimations) { + handle->setPriority(1.0f); + // if no fadeTotal, everyone's (typically just one running) is starting at zero. In that case, blend equally. + float normalizedFade = (fadeTotal != 0.0f) ? (handle->getFade() / fadeTotal) : (1.0f / _runningAnimations.count()); + assert(normalizedFade != 0.0f); + // simulate() will blend each animation result into the result so far, based on the pairwise mix at at each step. + // i.e., slerp the 'mix' distance from the result so far towards this iteration's animation result. + // The formula here for mix is based on the idea that, at each step: + // fadeSum is to normalizedFade, as (1 - mix) is to mix + // i.e., fadeSumSoFar/normalizedFade = (1 - mix)/mix + // Then we solve for mix. + // Sanity check: For the first animation, fadeSum = 0, and the mix will always be 1. + // Sanity check: For equal blending, the formula is equivalent to mix = 1 / nAnimationsSoFar++ + float mix = 1.0f / ((fadeSumSoFar / normalizedFade) + 1.0f); + assert((0.0f <= mix) && (mix <= 1.0f)); + fadeSumSoFar += normalizedFade; + handle->setMix(mix); handle->simulate(deltaTime); } - + for (int i = 0; i < _jointStates.size(); i++) { updateJointState(i, parentTransform); } diff --git a/libraries/animation/src/Rig.h b/libraries/animation/src/Rig.h index 52db16826a..113d097f96 100644 --- a/libraries/animation/src/Rig.h +++ b/libraries/animation/src/Rig.h @@ -42,7 +42,6 @@ class AnimationHandle; typedef std::shared_ptr AnimationHandlePointer; -// typedef QWeakPointer WeakAnimationHandlePointer; class Rig; typedef std::shared_ptr RigPointer; @@ -76,6 +75,7 @@ public: bool removeRunningAnimation(AnimationHandlePointer animationHandle); void addRunningAnimation(AnimationHandlePointer animationHandle); bool isRunningAnimation(AnimationHandlePointer animationHandle); + bool isRunningRole(const QString& role); // There can be multiple animations per role, so this is more general than isRunningAnimation. const QList& getRunningAnimations() const { return _runningAnimations; } void deleteAnimations(); const QList& getAnimationHandles() const { return _animationHandles; } @@ -86,11 +86,18 @@ public: float priority = 1.0f, bool loop = false, bool hold = false, float firstFrame = 0.0f, float lastFrame = FLT_MAX, const QStringList& maskedJoints = QStringList()); void stopAnimationByRole(const QString& role); - void addAnimationByRole(const QString& role, const QString& url = QString(), float fps = 30.0f, - float priority = 1.0f, bool loop = false, bool hold = false, float firstFrame = 0.0f, - float lastFrame = FLT_MAX, const QStringList& maskedJoints = QStringList(), bool startAutomatically = false); + AnimationHandlePointer addAnimationByRole(const QString& role, const QString& url = QString(), float fps = 30.0f, + float priority = 1.0f, bool loop = false, bool hold = false, float firstFrame = 0.0f, + float lastFrame = FLT_MAX, const QStringList& maskedJoints = QStringList(), bool startAutomatically = false); - float initJointStates(QVector states, glm::mat4 parentTransform); + float initJointStates(QVector states, glm::mat4 parentTransform, + int rootJointIndex, + int leftHandJointIndex, + int leftElbowJointIndex, + int leftShoulderJointIndex, + int rightHandJointIndex, + int rightElbowJointIndex, + int rightShoulderJointIndex); bool jointStatesEmpty() { return _jointStates.isEmpty(); }; int getJointStateCount() const { return _jointStates.size(); } int indexOfJoint(const QString& jointName) ; @@ -149,6 +156,9 @@ public: void updateFromHeadParameters(const HeadParameters& params); + virtual void setHandPosition(int jointIndex, const glm::vec3& position, const glm::quat& rotation, + float scale, float priority) = 0; + protected: void updateLeanJoint(int index, float leanSideways, float leanForward, float torsoTwist); @@ -156,16 +166,22 @@ public: void updateEyeJoint(int index, const glm::quat& worldHeadOrientation, const glm::vec3& lookAt, const glm::vec3& saccade); QVector _jointStates; + int _rootJointIndex = -1; + + int _leftHandJointIndex = -1; + int _leftElbowJointIndex = -1; + int _leftShoulderJointIndex = -1; + + int _rightHandJointIndex = -1; + int _rightElbowJointIndex = -1; + int _rightShoulderJointIndex = -1; QList _animationHandles; QList _runningAnimations; bool _enableRig; - bool _isWalking; - bool _isTurning; - bool _isIdle; glm::vec3 _lastFront; glm::vec3 _lastPosition; - }; +}; #endif /* defined(__hifi__Rig__) */ diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index a020be0f7a..565e30b5bd 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -46,7 +46,6 @@ typedef unsigned long long quint64; #include #include -#include #include #include #include @@ -257,10 +256,6 @@ public: const HeadData* getHeadData() const { return _headData; } const HandData* getHandData() const { return _handData; } - virtual bool findSphereCollisions(const glm::vec3& particleCenter, float particleRadius, CollisionList& collisions) { - return false; - } - bool hasIdentityChangedAfterParsing(NLPacket& packet); QByteArray identityByteArray(); diff --git a/libraries/entities-renderer/CMakeLists.txt b/libraries/entities-renderer/CMakeLists.txt index e9adf2b750..c4dddb8971 100644 --- a/libraries/entities-renderer/CMakeLists.txt +++ b/libraries/entities-renderer/CMakeLists.txt @@ -3,7 +3,7 @@ set(TARGET_NAME entities-renderer) AUTOSCRIBE_SHADER_LIB(gpu model render) # use setup_hifi_library macro to setup our project and link appropriate Qt modules -setup_hifi_library(Widgets OpenGL Network Script) +setup_hifi_library(Widgets Network Script) add_dependency_external_projects(glm) find_package(GLM REQUIRED) diff --git a/libraries/entities-renderer/src/RenderableLineEntityItem.cpp b/libraries/entities-renderer/src/RenderableLineEntityItem.cpp index 08bb5d83ce..4b556a8339 100644 --- a/libraries/entities-renderer/src/RenderableLineEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableLineEntityItem.cpp @@ -46,13 +46,11 @@ void RenderableLineEntityItem::render(RenderArgs* args) { transform.setTranslation(getPosition()); transform.setRotation(getRotation()); batch.setModelTransform(transform); - - batch._glLineWidth(getLineWidth()); + if (getLinePoints().size() > 1) { DependencyManager::get()->bindSimpleProgram(batch); DependencyManager::get()->renderVertices(batch, gpu::LINE_STRIP, _lineVerticesID); } - batch._glLineWidth(1.0f); - + RenderableDebugableEntityItem::render(this, args); }; diff --git a/libraries/entities-renderer/src/textured_particle.slf b/libraries/entities-renderer/src/textured_particle.slf index 543aa643aa..58a3103323 100644 --- a/libraries/entities-renderer/src/textured_particle.slf +++ b/libraries/entities-renderer/src/textured_particle.slf @@ -11,10 +11,12 @@ uniform sampler2D colorMap; -varying vec4 varColor; -varying vec2 varTexCoord; +in vec4 _color; +in vec2 _texCoord0; + +out vec4 outFragColor; void main(void) { - vec4 color = texture2D(colorMap, varTexCoord); - gl_FragColor = color * varColor; + vec4 color = texture(colorMap, _texCoord0); + outFragColor = color * _color; } diff --git a/libraries/entities-renderer/src/textured_particle.slv b/libraries/entities-renderer/src/textured_particle.slv index 7564feb1ce..c741af559d 100644 --- a/libraries/entities-renderer/src/textured_particle.slv +++ b/libraries/entities-renderer/src/textured_particle.slv @@ -10,19 +10,21 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +<@include gpu/Inputs.slh@> + <@include gpu/Transform.slh@> <$declareStandardTransform()$> -varying vec4 varColor; -varying vec2 varTexCoord; +out vec4 _color; +out vec2 _texCoord0; void main(void) { // pass along the color & uvs to fragment shader - varColor = gl_Color; - varTexCoord = gl_MultiTexCoord0.xy; + _color = inColor; + _texCoord0 = inTexCoord0.xy; TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); - <$transformModelToClipPos(cam, obj, gl_Vertex, gl_Position)$> + <$transformModelToClipPos(cam, obj, inPosition, gl_Position)$> } diff --git a/libraries/entities-renderer/src/untextured_particle.slf b/libraries/entities-renderer/src/untextured_particle.slf index bb3ed77e3f..11f25bb693 100644 --- a/libraries/entities-renderer/src/untextured_particle.slf +++ b/libraries/entities-renderer/src/untextured_particle.slf @@ -9,8 +9,10 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -varying vec4 varColor; +in vec4 _color; + +out vec4 outFragColor; void main(void) { - gl_FragColor = varColor; + outFragColor = _color; } diff --git a/libraries/entities-renderer/src/untextured_particle.slv b/libraries/entities-renderer/src/untextured_particle.slv index 2975dab046..3d1d99c0dc 100644 --- a/libraries/entities-renderer/src/untextured_particle.slv +++ b/libraries/entities-renderer/src/untextured_particle.slv @@ -8,17 +8,19 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +<@include gpu/Inputs.slh@> + <@include gpu/Transform.slh@> <$declareStandardTransform()$> -varying vec4 varColor; +out vec4 _color; void main(void) { // pass along the diffuse color - varColor = gl_Color; + _color = inColor; TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); - <$transformModelToClipPos(cam, obj, gl_Vertex, gl_Position)$> + <$transformModelToClipPos(cam, obj, inPosition, gl_Position)$> } \ No newline at end of file diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index b698a5c511..57f8883cea 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -18,7 +18,6 @@ #include #include // for Animation, AnimationCache, and AnimationPointer classes -#include #include // for EncodeBitstreamParams class #include // for OctreeElement::AppendState #include diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index ebe4ac6014..4e7228e573 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -71,7 +71,8 @@ CONSTRUCT_PROPERTY(exponent, 0.0f), CONSTRUCT_PROPERTY(cutoff, ENTITY_ITEM_DEFAULT_CUTOFF), CONSTRUCT_PROPERTY(locked, ENTITY_ITEM_DEFAULT_LOCKED), CONSTRUCT_PROPERTY(textures, ""), -CONSTRUCT_PROPERTY(animationSettings, ""), +CONSTRUCT_PROPERTY(animationSettings, "{\"firstFrame\":0,\"fps\":30,\"frameIndex\":0,\"hold\":false," + "\"lastFrame\":100000,\"loop\":false,\"running\":false,\"startAutomatically\":false}"), CONSTRUCT_PROPERTY(userData, ENTITY_ITEM_DEFAULT_USER_DATA), CONSTRUCT_PROPERTY(simulationOwner, SimulationOwner()), CONSTRUCT_PROPERTY(text, TextEntityItem::DEFAULT_TEXT), diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index c232437757..d3710c6ccc 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -16,7 +16,6 @@ #include -#include #include #include #include diff --git a/libraries/entities/src/TextEntityItem.cpp b/libraries/entities/src/TextEntityItem.cpp index a851d025fc..3ab15ba6cb 100644 --- a/libraries/entities/src/TextEntityItem.cpp +++ b/libraries/entities/src/TextEntityItem.cpp @@ -15,7 +15,7 @@ #include #include -#include +#include #include "EntityTree.h" #include "EntityTreeElement.h" @@ -128,46 +128,13 @@ void TextEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBits } - bool TextEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, void** intersectedObject, bool precisionPicking) const { - - RayIntersectionInfo rayInfo; - rayInfo._rayStart = origin; - rayInfo._rayDirection = direction; - rayInfo._rayLength = std::numeric_limits::max(); - - PlaneShape plane; - - const glm::vec3 UNROTATED_NORMAL(0.0f, 0.0f, -1.0f); - glm::vec3 normal = getRotation() * UNROTATED_NORMAL; - plane.setNormal(normal); - plane.setPoint(getPosition()); // the position is definitely a point on our plane - - bool intersects = plane.findRayIntersection(rayInfo); - - if (intersects) { - glm::vec3 hitAt = origin + (direction * rayInfo._hitDistance); - // now we know the point the ray hit our plane - - glm::mat4 rotation = glm::mat4_cast(getRotation()); - glm::mat4 translation = glm::translate(getPosition()); - glm::mat4 entityToWorldMatrix = translation * rotation; - glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix); - - glm::vec3 dimensions = getDimensions(); - glm::vec3 registrationPoint = getRegistrationPoint(); - glm::vec3 corner = -(dimensions * registrationPoint); - AABox entityFrameBox(corner, dimensions); - - glm::vec3 entityFrameHitAt = glm::vec3(worldToEntityMatrix * glm::vec4(hitAt, 1.0f)); - - intersects = entityFrameBox.contains(entityFrameHitAt); - } - - if (intersects) { - distance = rayInfo._hitDistance; - } - return intersects; + glm::vec3 dimensions = getDimensions(); + glm::vec2 xyDimensions(dimensions.x, dimensions.y); + glm::quat rotation = getRotation(); + glm::vec3 position = getPosition() + rotation * + (dimensions * (getRegistrationPoint() - ENTITY_ITEM_DEFAULT_REGISTRATION_POINT)); + return findRayRectangleIntersection(origin, direction, rotation, position, xyDimensions, distance); } diff --git a/libraries/entities/src/WebEntityItem.cpp b/libraries/entities/src/WebEntityItem.cpp index 2cb233bbee..c3dc757199 100644 --- a/libraries/entities/src/WebEntityItem.cpp +++ b/libraries/entities/src/WebEntityItem.cpp @@ -13,7 +13,7 @@ #include #include -#include +#include #include "EntityTree.h" #include "EntityTreeElement.h" @@ -98,50 +98,17 @@ void WebEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBitst APPEND_ENTITY_PROPERTY(PROP_SOURCE_URL, _sourceUrl); } - bool WebEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, void** intersectedObject, bool precisionPicking) const { - - RayIntersectionInfo rayInfo; - rayInfo._rayStart = origin; - rayInfo._rayDirection = direction; - rayInfo._rayLength = std::numeric_limits::max(); - - PlaneShape plane; - - const glm::vec3 UNROTATED_NORMAL(0.0f, 0.0f, -1.0f); - glm::vec3 normal = getRotation() * UNROTATED_NORMAL; - plane.setNormal(normal); - plane.setPoint(getPosition()); // the position is definitely a point on our plane - - bool intersects = plane.findRayIntersection(rayInfo); - - if (intersects) { - glm::vec3 hitAt = origin + (direction * rayInfo._hitDistance); - // now we know the point the ray hit our plane - - glm::mat4 rotation = glm::mat4_cast(getRotation()); - glm::mat4 translation = glm::translate(getPosition()); - glm::mat4 entityToWorldMatrix = translation * rotation; - glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix); - - glm::vec3 dimensions = getDimensions(); - glm::vec3 registrationPoint = getRegistrationPoint(); - glm::vec3 corner = -(dimensions * registrationPoint); - AABox entityFrameBox(corner, dimensions); - - glm::vec3 entityFrameHitAt = glm::vec3(worldToEntityMatrix * glm::vec4(hitAt, 1.0f)); - - intersects = entityFrameBox.contains(entityFrameHitAt); - } - - if (intersects) { - distance = rayInfo._hitDistance; - } - return intersects; + glm::vec3 dimensions = getDimensions(); + glm::vec2 xyDimensions(dimensions.x, dimensions.y); + glm::quat rotation = getRotation(); + glm::vec3 position = getPosition() + rotation * + (dimensions * (getRegistrationPoint() - ENTITY_ITEM_DEFAULT_REGISTRATION_POINT)); + return findRayRectangleIntersection(origin, direction, rotation, position, xyDimensions, distance); } - + void WebEntityItem::setSourceUrl(const QString& value) { if (_sourceUrl != value) { _sourceUrl = value; diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 63855af513..5e7647263a 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -28,7 +28,6 @@ #include #include #include -#include #include #include @@ -977,6 +976,8 @@ ExtractedMesh extractMesh(const FBXNode& object, unsigned int& meshIndex) { data.extracted.mesh.meshIndex = meshIndex++; QVector materials; QVector textures; + bool isMaterialPerPolygon = false; + foreach (const FBXNode& child, object.children) { if (child.name == "Vertices") { data.vertices = createVec3Vector(getDoubleVector(child)); @@ -1106,8 +1107,16 @@ ExtractedMesh extractMesh(const FBXNode& object, unsigned int& meshIndex) { foreach (const FBXNode& subdata, child.children) { if (subdata.name == "Materials") { materials = getIntVector(subdata); + } else if (subdata.name == "MappingInformationType") { + if (subdata.properties.at(0) == "ByPolygon") { + isMaterialPerPolygon = true; + } else { + isMaterialPerPolygon = false; + } } } + + } else if (child.name == "LayerElementTexture") { foreach (const FBXNode& subdata, child.children) { if (subdata.name == "TextureId") { @@ -1117,6 +1126,12 @@ ExtractedMesh extractMesh(const FBXNode& object, unsigned int& meshIndex) { } } + + bool isMultiMaterial = false; + if (isMaterialPerPolygon) { + isMultiMaterial = true; + } + // convert the polygons to quads and triangles int polygonIndex = 0; QHash, int> materialTextureParts; @@ -2105,6 +2120,9 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, if (type.contains("diffuse")) { diffuseTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1)); + } else if (type.contains("transparentcolor")) { // it should be TransparentColor... + // THis is how Maya assign a texture that affect diffuse color AND transparency ? + diffuseTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1)); } else if (type.contains("bump") || type.contains("normal")) { bumpTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1)); diff --git a/libraries/fbx/src/OBJReader.cpp b/libraries/fbx/src/OBJReader.cpp index 3d7cf6582e..b7ae948490 100644 --- a/libraries/fbx/src/OBJReader.cpp +++ b/libraries/fbx/src/OBJReader.cpp @@ -23,7 +23,6 @@ #include #include "FBXReader.h" #include "OBJReader.h" -#include "Shape.h" #include "ModelFormatLogging.h" diff --git a/libraries/gpu/CMakeLists.txt b/libraries/gpu/CMakeLists.txt index 89939535b0..7a88580f7f 100644 --- a/libraries/gpu/CMakeLists.txt +++ b/libraries/gpu/CMakeLists.txt @@ -7,17 +7,18 @@ setup_hifi_library() link_hifi_libraries(shared) +add_dependency_external_projects(glew) +find_package(GLEW REQUIRED) +add_definitions(-DGLEW_STATIC) +target_include_directories(${TARGET_NAME} PUBLIC ${GLEW_INCLUDE_DIRS}) +target_link_libraries(${TARGET_NAME} ${GLEW_LIBRARY}) + if (APPLE) # link in required OS X frameworks and include the right GL headers find_library(OpenGL OpenGL) - target_link_libraries(${TARGET_NAME} ${OpenGL}) elseif (WIN32) - add_dependency_external_projects(glew) - find_package(GLEW REQUIRED) - target_include_directories(${TARGET_NAME} PUBLIC ${GLEW_INCLUDE_DIRS}) - - target_link_libraries(${TARGET_NAME} ${GLEW_LIBRARIES} opengl32.lib) + target_link_libraries(${TARGET_NAME} ${GLEW_LIBRARY} opengl32.lib) if (USE_NSIGHT) # try to find the Nsight package and add it to the build if we find it @@ -32,8 +33,6 @@ elseif (WIN32) elseif (ANDROID) target_link_libraries(${TARGET_NAME} "-lGLESv3" "-lEGL") else () - find_package(GLEW REQUIRED) - target_include_directories(${TARGET_NAME} PUBLIC ${GLEW_INCLUDE_DIRS}) find_package(OpenGL REQUIRED) @@ -41,6 +40,5 @@ else () include_directories(SYSTEM "${OPENGL_INCLUDE_DIR}") endif () - target_link_libraries(${TARGET_NAME} "${GLEW_LIBRARIES}" "${OPENGL_LIBRARY}") - + target_link_libraries(${TARGET_NAME} "${OPENGL_LIBRARY}") endif (APPLE) diff --git a/libraries/gpu/src/gpu/Batch.h b/libraries/gpu/src/gpu/Batch.h index 5135d1ac4f..d48ffef209 100644 --- a/libraries/gpu/src/gpu/Batch.h +++ b/libraries/gpu/src/gpu/Batch.h @@ -106,7 +106,10 @@ public: void clearStencilFramebuffer(int stencil, bool enableScissor = false); // not a command, just a shortcut for clearFramebuffer, it touches only stencil target void clearDepthStencilFramebuffer(float depth, int stencil, bool enableScissor = false); // not a command, just a shortcut for clearFramebuffer, it touches depth and stencil target - void blit(const FramebufferPointer& src, const Vec4i& srcViewport, const FramebufferPointer& dst, const Vec4i& dstViewport); + // Blit src framebuffer to destination + // the srcRect and dstRect are the rect region in source and destination framebuffers expressed in pixel space + // with xy and zw the bounding corners of the rect region. + void blit(const FramebufferPointer& src, const Vec4i& srcRect, const FramebufferPointer& dst, const Vec4i& dstRect); // Query Section void beginQuery(const QueryPointer& query); @@ -134,7 +137,6 @@ public: void _glUniformMatrix4fv(int location, int count, unsigned char transpose, const float* value); void _glColor4f(float red, float green, float blue, float alpha); - void _glLineWidth(float width); enum Command { COMMAND_draw = 0, @@ -183,7 +185,6 @@ public: COMMAND_glUniformMatrix4fv, COMMAND_glColor4f, - COMMAND_glLineWidth, NUM_COMMANDS, }; diff --git a/libraries/gpu/src/gpu/Config.slh b/libraries/gpu/src/gpu/Config.slh index f24b54e5d5..3da92df7c1 100644 --- a/libraries/gpu/src/gpu/Config.slh +++ b/libraries/gpu/src/gpu/Config.slh @@ -13,17 +13,11 @@ <@if GLPROFILE == PC_GL @> <@def GPU_FEATURE_PROFILE GPU_CORE@> - <@def GPU_TRANSFORM_PROFILE GPU_CORE@> - <@def VERSION_HEADER #version 430 compatibility@> + <@def VERSION_HEADER #version 410 core@> <@elif GLPROFILE == MAC_GL @> - <@def GPU_FEATURE_PROFILE GPU_LEGACY@> - <@def GPU_TRANSFORM_PROFILE GPU_LEGACY@> - <@def VERSION_HEADER #version 120 -#extension GL_EXT_gpu_shader4 : enable@> + <@def GPU_FEATURE_PROFILE GPU_CORE@> + <@def VERSION_HEADER #version 410 core@> <@else@> <@def GPU_FEATURE_PROFILE GPU_CORE@> - <@def GPU_TRANSFORM_PROFILE GPU_CORE@> - <@def VERSION_HEADER #version 430 compatibility@> -<@endif@> - + <@def VERSION_HEADER #version 410 core@> <@endif@> diff --git a/libraries/gpu/src/gpu/DrawColoredTexture.slf b/libraries/gpu/src/gpu/DrawColoredTexture.slf index b60c7d9575..2a7f6aae36 100755 --- a/libraries/gpu/src/gpu/DrawColoredTexture.slf +++ b/libraries/gpu/src/gpu/DrawColoredTexture.slf @@ -11,12 +11,13 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // - + uniform sampler2D colorMap; uniform vec4 color; -varying vec2 varTexcoord; +in vec2 varTexCoord0; +out vec4 outFragColor; void main(void) { - gl_FragColor = texture2D(colorMap, varTexcoord) * color; + outFragColor = texture(colorMap, varTexCoord0) * color; } diff --git a/libraries/gpu/src/gpu/DrawTexcoordRectTransformUnitQuad.slv b/libraries/gpu/src/gpu/DrawTexcoordRectTransformUnitQuad.slv index 284f68dd93..c9cc9e9dfa 100755 --- a/libraries/gpu/src/gpu/DrawTexcoordRectTransformUnitQuad.slv +++ b/libraries/gpu/src/gpu/DrawTexcoordRectTransformUnitQuad.slv @@ -13,27 +13,27 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -<@include gpu/Transform.slh@> - +<@include gpu/Transform.slh@> + <$declareStandardTransform()$> uniform vec4 texcoordRect; -varying vec2 varTexcoord; +out vec2 varTexCoord0; void main(void) { - const vec4 UNIT_QUAD[4] = vec4[4]( - vec4(-1.0, -1.0, 0.0, 1.0), - vec4(1.0, -1.0, 0.0, 1.0), - vec4(-1.0, 1.0, 0.0, 1.0), + const vec4 UNIT_QUAD[4] = vec4[4]( + vec4(-1.0, -1.0, 0.0, 1.0), + vec4(1.0, -1.0, 0.0, 1.0), + vec4(-1.0, 1.0, 0.0, 1.0), vec4(1.0, 1.0, 0.0, 1.0) ); vec4 pos = UNIT_QUAD[gl_VertexID]; - - // standard transform - TransformCamera cam = getTransformCamera(); - TransformObject obj = getTransformObject(); - <$transformModelToClipPos(cam, obj, pos, gl_Position)$> - - varTexcoord = ((pos.xy + 1) * 0.5) * texcoordRect.zw + texcoordRect.xy; + + // standard transform + TransformCamera cam = getTransformCamera(); + TransformObject obj = getTransformObject(); + <$transformModelToClipPos(cam, obj, pos, gl_Position)$> + + varTexCoord0 = ((pos.xy + 1) * 0.5) * texcoordRect.zw + texcoordRect.xy; } diff --git a/libraries/gpu/src/gpu/DrawTexture.slf b/libraries/gpu/src/gpu/DrawTexture.slf index e456c49649..64389f02b3 100755 --- a/libraries/gpu/src/gpu/DrawTexture.slf +++ b/libraries/gpu/src/gpu/DrawTexture.slf @@ -11,11 +11,12 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // - + uniform sampler2D colorMap; -varying vec2 varTexcoord; +in vec2 varTexCoord0; +out vec4 outFragColor; void main(void) { - gl_FragColor = texture2D(colorMap, varTexcoord); + outFragColor = texture(colorMap, varTexCoord0); } diff --git a/libraries/gpu/src/gpu/DrawTextureOpaque.slf b/libraries/gpu/src/gpu/DrawTextureOpaque.slf index 1ce3a34c02..14d2072ff3 100755 --- a/libraries/gpu/src/gpu/DrawTextureOpaque.slf +++ b/libraries/gpu/src/gpu/DrawTextureOpaque.slf @@ -12,11 +12,12 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // - + uniform sampler2D colorMap; -varying vec2 varTexcoord; +in vec2 varTexCoord0; +out vec4 outFragColor; void main(void) { - gl_FragColor = vec4(texture2D(colorMap, varTexcoord).xyz, 1.0); + outFragColor = vec4(texture(colorMap, varTexCoord0).xyz, 1.0); } diff --git a/libraries/gpu/src/gpu/DrawTransformUnitQuad.slv b/libraries/gpu/src/gpu/DrawTransformUnitQuad.slv index 2d1e4584a7..f55abf1089 100755 --- a/libraries/gpu/src/gpu/DrawTransformUnitQuad.slv +++ b/libraries/gpu/src/gpu/DrawTransformUnitQuad.slv @@ -12,25 +12,25 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -<@include gpu/Transform.slh@> - +<@include gpu/Transform.slh@> + <$declareStandardTransform()$> -varying vec2 varTexcoord; +out vec2 varTexCoord0; void main(void) { - const vec4 UNIT_QUAD[4] = vec4[4]( - vec4(-1.0, -1.0, 0.0, 1.0), - vec4(1.0, -1.0, 0.0, 1.0), - vec4(-1.0, 1.0, 0.0, 1.0), + const vec4 UNIT_QUAD[4] = vec4[4]( + vec4(-1.0, -1.0, 0.0, 1.0), + vec4(1.0, -1.0, 0.0, 1.0), + vec4(-1.0, 1.0, 0.0, 1.0), vec4(1.0, 1.0, 0.0, 1.0) ); vec4 pos = UNIT_QUAD[gl_VertexID]; - - // standard transform - TransformCamera cam = getTransformCamera(); - TransformObject obj = getTransformObject(); - <$transformModelToClipPos(cam, obj, pos, gl_Position)$> - - varTexcoord = (pos.xy + 1) * 0.5; + + // standard transform + TransformCamera cam = getTransformCamera(); + TransformObject obj = getTransformObject(); + <$transformModelToClipPos(cam, obj, pos, gl_Position)$> + + varTexCoord0 = (pos.xy + 1) * 0.5; } diff --git a/libraries/gpu/src/gpu/DrawViewportQuadTransformTexcoord.slv b/libraries/gpu/src/gpu/DrawViewportQuadTransformTexcoord.slv index e91b8a7644..1f9bc13700 100755 --- a/libraries/gpu/src/gpu/DrawViewportQuadTransformTexcoord.slv +++ b/libraries/gpu/src/gpu/DrawViewportQuadTransformTexcoord.slv @@ -16,7 +16,7 @@ <$declareStandardTransform()$> -varying vec2 varTexcoord; +out vec2 varTexCoord0; void main(void) { const vec4 UNIT_QUAD[4] = vec4[4]( @@ -34,5 +34,5 @@ void main(void) { <$transformModelToWorldPos(obj, tc, tc)$> gl_Position = pos; - varTexcoord = tc.xy; + varTexCoord0 = tc.xy; } diff --git a/libraries/gpu/src/gpu/Format.h b/libraries/gpu/src/gpu/Format.h index b710a44f39..8cd16e0be4 100644 --- a/libraries/gpu/src/gpu/Format.h +++ b/libraries/gpu/src/gpu/Format.h @@ -88,7 +88,26 @@ static const int TYPE_SIZE[NUM_TYPES] = { 1, 1 }; +// Array answering the question Does this type is integer or not +static const bool TYPE_IS_INTEGER[NUM_TYPES] = { + false, + true, + true, + false, + true, + true, + true, + true, + false, + true, + true, + false, + true, + true, + true, + true +}; // Dimension of an Element enum Dimension { @@ -168,6 +187,7 @@ public: Type getType() const { return (Type)_type; } bool isNormalized() const { return (getType() >= NFLOAT); } + bool isInteger() const { return TYPE_IS_INTEGER[getType()]; } uint32 getSize() const { return DIMENSION_COUNT[_dimension] * TYPE_SIZE[_type]; } diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index c74a94e03e..f0029d15a3 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -60,7 +60,6 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] = (&::gpu::GLBackend::do_glUniformMatrix4fv), (&::gpu::GLBackend::do_glColor4f), - (&::gpu::GLBackend::do_glLineWidth), }; void GLBackend::init() { @@ -74,14 +73,16 @@ void GLBackend::init() { qCDebug(gpulogging) << "GL Renderer: " << QString((const char*) glGetString(GL_RENDERER)); -#ifdef WIN32 + glewExperimental = true; GLenum err = glewInit(); + glGetError(); if (GLEW_OK != err) { /* Problem: glewInit failed, something is seriously wrong. */ qCDebug(gpulogging, "Error: %s\n", glewGetErrorString(err)); } qCDebug(gpulogging, "Status: Using GLEW %s\n", glewGetString(GLEW_VERSION)); +#if defined(Q_OS_WIN) if (wglewGetExtension("WGL_EXT_swap_control")) { int swapInterval = wglGetSwapIntervalEXT(); qCDebug(gpulogging, "V-Sync is %s\n", (swapInterval > 0 ? "ON" : "OFF")); @@ -89,13 +90,6 @@ void GLBackend::init() { #endif #if defined(Q_OS_LINUX) - GLenum err = glewInit(); - if (GLEW_OK != err) { - /* Problem: glewInit failed, something is seriously wrong. */ - qCDebug(gpulogging, "Error: %s\n", glewGetErrorString(err)); - } - qCDebug(gpulogging, "Status: Using GLEW %s\n", glewGetString(GLEW_VERSION)); - // TODO: Write the correct code for Linux... /* if (wglewGetExtension("WGL_EXT_swap_control")) { int swapInterval = wglGetSwapIntervalEXT(); @@ -200,7 +194,6 @@ void GLBackend::do_draw(Batch& batch, uint32 paramOffset) { GLenum mode = _primitiveToGLmode[primitiveType]; uint32 numVertices = batch._params[paramOffset + 1]._uint; uint32 startVertex = batch._params[paramOffset + 0]._uint; - glDrawArrays(mode, startVertex, numVertices); (void) CHECK_GL_ERROR(); } @@ -494,22 +487,11 @@ void Batch::_glColor4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) DO_IT_NOW(_glColor4f, 4); } void GLBackend::do_glColor4f(Batch& batch, uint32 paramOffset) { - glColor4f( + // TODO Replace this with a proper sticky Input attribute buffer with frequency 0 + glVertexAttrib4f( gpu::Stream::COLOR, batch._params[paramOffset + 3]._float, batch._params[paramOffset + 2]._float, batch._params[paramOffset + 1]._float, batch._params[paramOffset + 0]._float); (void) CHECK_GL_ERROR(); } - -void Batch::_glLineWidth(GLfloat width) { - ADD_COMMAND_GL(glLineWidth); - - _params.push_back(width); - - DO_IT_NOW(_glLineWidth, 1); -} -void GLBackend::do_glLineWidth(Batch& batch, uint32 paramOffset) { - glLineWidth(batch._params[paramOffset]._float); - (void) CHECK_GL_ERROR(); -} diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index c0bae76d78..f3e3b1cc7c 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -93,13 +93,6 @@ public: GLint _transformCameraSlot = -1; GLint _transformObjectSlot = -1; -#if (GPU_TRANSFORM_PROFILE == GPU_CORE) -#else - GLint _transformObject_model = -1; - GLint _transformCamera_viewInverse = -1; - GLint _transformCamera_viewport = -1; -#endif - GLShader(); ~GLShader(); }; @@ -327,8 +320,6 @@ protected: bool _invalidProj; bool _invalidViewport; - GLenum _lastMode; - TransformStageState() : _transformObjectBuffer(0), _transformCameraBuffer(0), @@ -339,14 +330,13 @@ protected: _invalidModel(true), _invalidView(true), _invalidProj(false), - _invalidViewport(false), - _lastMode(GL_TEXTURE) {} + _invalidViewport(false) {} } _transform; // Uniform Stage void do_setUniformBuffer(Batch& batch, uint32 paramOffset); - void releaseUniformBuffer(int slot); + void releaseUniformBuffer(uint32_t slot); void resetUniformStage(); struct UniformStageState { Buffers _buffers; @@ -359,7 +349,7 @@ protected: // Resource Stage void do_setResourceTexture(Batch& batch, uint32 paramOffset); - void releaseResourceTexture(int slot); + void releaseResourceTexture(uint32_t slot); void resetResourceStage(); struct ResourceStageState { Textures _textures; @@ -392,13 +382,6 @@ protected: GLuint _program; bool _invalidProgram; -#if (GPU_TRANSFORM_PROFILE == GPU_CORE) -#else - GLint _program_transformObject_model = -1; - GLint _program_transformCamera_viewInverse = -1; - GLint _program_transformCamera_viewport = -1; -#endif - State::Data _stateCache; State::Signature _stateSignatureCache; @@ -462,7 +445,6 @@ protected: void do_glUniformMatrix4fv(Batch& batch, uint32 paramOffset); void do_glColor4f(Batch& batch, uint32 paramOffset); - void do_glLineWidth(Batch& batch, uint32 paramOffset); typedef void (GLBackend::*CommandCall)(Batch&, uint32); static CommandCall _commandCalls[Batch::NUM_COMMANDS]; diff --git a/libraries/gpu/src/gpu/GLBackendInput.cpp b/libraries/gpu/src/gpu/GLBackendInput.cpp index 9014024914..efbead5da2 100755 --- a/libraries/gpu/src/gpu/GLBackendInput.cpp +++ b/libraries/gpu/src/gpu/GLBackendInput.cpp @@ -57,66 +57,41 @@ void GLBackend::do_setInputBuffer(Batch& batch, uint32 paramOffset) { } } -#define NOT_SUPPORT_VAO -#if defined(SUPPORT_VAO) +#if (GPU_INPUT_PROFILE == GPU_CORE_41) +#define NO_SUPPORT_VERTEX_ATTRIB_FORMAT #else +#define SUPPORT_VERTEX_ATTRIB_FORMAT +#endif -#define SUPPORT_LEGACY_OPENGL -#if defined(SUPPORT_LEGACY_OPENGL) -static const int NUM_CLASSIC_ATTRIBS = Stream::TANGENT; -static const GLenum attributeSlotToClassicAttribName[NUM_CLASSIC_ATTRIBS] = { - GL_VERTEX_ARRAY, - GL_NORMAL_ARRAY, - GL_COLOR_ARRAY, - GL_TEXTURE_COORD_ARRAY -}; -#endif -#endif void GLBackend::initInput() { -#if defined(SUPPORT_VAO) if(!_input._defaultVAO) { glGenVertexArrays(1, &_input._defaultVAO); } glBindVertexArray(_input._defaultVAO); (void) CHECK_GL_ERROR(); -#endif } void GLBackend::killInput() { -#if defined(SUPPORT_VAO) glBindVertexArray(0); if(_input._defaultVAO) { glDeleteVertexArrays(1, &_input._defaultVAO); } (void) CHECK_GL_ERROR(); -#endif } void GLBackend::syncInputStateCache() { -#if defined(SUPPORT_VAO) - for (int i = 0; i < NUM_CLASSIC_ATTRIBS; i++) { - _input._attributeActivation[i] = glIsEnabled(attributeSlotToClassicAttribName[i]); - } - //_input._defaultVAO - glBindVertexArray(_input._defaultVAO); -#else - size_t i = 0; -#if defined(SUPPORT_LEGACY_OPENGL) - for (; i < NUM_CLASSIC_ATTRIBS; i++) { - _input._attributeActivation[i] = glIsEnabled(attributeSlotToClassicAttribName[i]); - } -#endif - for (; i < _input._attributeActivation.size(); i++) { + for (uint32_t i = 0; i < _input._attributeActivation.size(); i++) { GLint active = 0; glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &active); _input._attributeActivation[i] = active; } -#endif + //_input._defaultVAO + glBindVertexArray(_input._defaultVAO); } void GLBackend::updateInput() { -#if defined(SUPPORT_VAO) +#if defined(SUPPORT_VERTEX_ATTRIB_FORMAT) if (_input._invalidFormat) { InputStageState::ActivationCache newActivation; @@ -193,21 +168,11 @@ void GLBackend::updateInput() { for (unsigned int i = 0; i < newActivation.size(); i++) { bool newState = newActivation[i]; if (newState != _input._attributeActivation[i]) { -#if defined(SUPPORT_LEGACY_OPENGL) - if (i < NUM_CLASSIC_ATTRIBS) { - if (newState) { - glEnableClientState(attributeSlotToClassicAttribName[i]); - } else { - glDisableClientState(attributeSlotToClassicAttribName[i]); - } - } else -#endif - { - if (newState) { - glEnableVertexAttribArray(i); - } else { - glDisableVertexAttribArray(i); - } + + if (newState) { + glEnableVertexAttribArray(i); + } else { + glDisableVertexAttribArray(i); } (void) CHECK_GL_ERROR(); @@ -249,30 +214,13 @@ void GLBackend::updateInput() { GLenum type = _elementTypeToGLType[attrib._element.getType()]; GLuint stride = strides[bufferNum]; GLuint pointer = attrib._offset + offsets[bufferNum]; -#if defined(SUPPORT_LEGACY_OPENGL) - const bool useClientState = slot < NUM_CLASSIC_ATTRIBS; - if (useClientState) { - switch (slot) { - case Stream::POSITION: - glVertexPointer(count, type, stride, reinterpret_cast(pointer)); - break; - case Stream::NORMAL: - glNormalPointer(type, stride, reinterpret_cast(pointer)); - break; - case Stream::COLOR: - glColorPointer(count, type, stride, reinterpret_cast(pointer)); - break; - case Stream::TEXCOORD: - glTexCoordPointer(count, type, stride, reinterpret_cast(pointer)); - break; - }; - } else -#endif - { - GLboolean isNormalized = attrib._element.isNormalized(); - glVertexAttribPointer(slot, count, type, isNormalized, stride, + GLboolean isNormalized = attrib._element.isNormalized(); + + glVertexAttribPointer(slot, count, type, isNormalized, stride, reinterpret_cast(pointer)); - } + + // TODO: Support properly the IAttrib version + (void) CHECK_GL_ERROR(); } } @@ -293,35 +241,20 @@ void GLBackend::resetInputStage() { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); (void) CHECK_GL_ERROR(); - -#if defined(SUPPORT_VAO) - // TODO -#else glBindBuffer(GL_ARRAY_BUFFER, 0); - size_t i = 0; -#if defined(SUPPORT_LEGACY_OPENGL) - for (; i < NUM_CLASSIC_ATTRIBS; i++) { - glDisableClientState(attributeSlotToClassicAttribName[i]); - } - glVertexPointer(4, GL_FLOAT, 0, 0); - glNormalPointer(GL_FLOAT, 0, 0); - glColorPointer(4, GL_FLOAT, 0, 0); - glTexCoordPointer(4, GL_FLOAT, 0, 0); -#endif - for (; i < _input._attributeActivation.size(); i++) { + for (uint32_t i = 0; i < _input._attributeActivation.size(); i++) { glDisableVertexAttribArray(i); glVertexAttribPointer(i, 4, GL_FLOAT, GL_FALSE, 0, 0); } -#endif // Reset vertex buffer and format _input._format.reset(); _input._invalidFormat = false; _input._attributeActivation.reset(); - for (int i = 0; i < _input._buffers.size(); i++) { + for (uint32_t i = 0; i < _input._buffers.size(); i++) { _input._buffers[i].reset(); _input._bufferOffsets[i] = 0; _input._bufferStrides[i] = 0; diff --git a/libraries/gpu/src/gpu/GLBackendPipeline.cpp b/libraries/gpu/src/gpu/GLBackendPipeline.cpp index 090dd4ad31..8dd5242c3a 100755 --- a/libraries/gpu/src/gpu/GLBackendPipeline.cpp +++ b/libraries/gpu/src/gpu/GLBackendPipeline.cpp @@ -71,13 +71,6 @@ void GLBackend::do_setPipeline(Batch& batch, uint32 paramOffset) { _pipeline._program = 0; _pipeline._invalidProgram = true; -#if (GPU_TRANSFORM_PROFILE == GPU_CORE) -#else - _pipeline._program_transformObject_model = -1; - _pipeline._program_transformCamera_viewInverse = -1; - _pipeline._program_transformCamera_viewport = -1; -#endif - _pipeline._state = nullptr; _pipeline._invalidState = true; } else { @@ -90,13 +83,6 @@ void GLBackend::do_setPipeline(Batch& batch, uint32 paramOffset) { if (_pipeline._program != pipelineObject->_program->_program) { _pipeline._program = pipelineObject->_program->_program; _pipeline._invalidProgram = true; - -#if (GPU_TRANSFORM_PROFILE == GPU_CORE) -#else - _pipeline._program_transformObject_model = pipelineObject->_program->_transformObject_model; - _pipeline._program_transformCamera_viewInverse = pipelineObject->_program->_transformCamera_viewInverse; - _pipeline._program_transformCamera_viewport = pipelineObject->_program->_transformCamera_viewport; -#endif } // Now for the state @@ -144,24 +130,6 @@ void GLBackend::updatePipeline() { } _pipeline._invalidState = false; } - -#if (GPU_TRANSFORM_PROFILE == GPU_CORE) -#else - // If shader program needs the model we need to provide it - if (_pipeline._program_transformObject_model >= 0) { - glUniformMatrix4fv(_pipeline._program_transformObject_model, 1, false, (const GLfloat*) &_transform._transformObject._model); - } - - // If shader program needs the inverseView we need to provide it - if (_pipeline._program_transformCamera_viewInverse >= 0) { - glUniformMatrix4fv(_pipeline._program_transformCamera_viewInverse, 1, false, (const GLfloat*) &_transform._transformCamera._viewInverse); - } - - // If shader program needs the viewport we need to provide it - if (_pipeline._program_transformCamera_viewport >= 0) { - glUniform4fv(_pipeline._program_transformCamera_viewport, 1, (const GLfloat*) &_transform._transformCamera._viewport); - } -#endif } void GLBackend::resetPipelineStage() { @@ -179,13 +147,12 @@ void GLBackend::resetPipelineStage() { } -void GLBackend::releaseUniformBuffer(int slot) { +void GLBackend::releaseUniformBuffer(uint32_t slot) { #if (GPU_FEATURE_PROFILE == GPU_CORE) auto& buf = _uniform._buffers[slot]; if (buf) { auto* object = Backend::getGPUObject(*buf); if (object) { - GLuint bo = object->_buffer; glBindBufferBase(GL_UNIFORM_BUFFER, slot, 0); // RELEASE (void) CHECK_GL_ERROR(); @@ -196,7 +163,7 @@ void GLBackend::releaseUniformBuffer(int slot) { } void GLBackend::resetUniformStage() { - for (int i = 0; i < _uniform._buffers.size(); i++) { + for (uint32_t i = 0; i < _uniform._buffers.size(); i++) { releaseUniformBuffer(i); } } @@ -249,12 +216,11 @@ void GLBackend::do_setUniformBuffer(Batch& batch, uint32 paramOffset) { #endif } -void GLBackend::releaseResourceTexture(int slot) { +void GLBackend::releaseResourceTexture(uint32_t slot) { auto& tex = _resource._textures[slot]; if (tex) { auto* object = Backend::getGPUObject(*tex); if (object) { - GLuint to = object->_texture; GLuint target = object->_target; glActiveTexture(GL_TEXTURE0 + slot); glBindTexture(target, 0); // RELEASE @@ -266,7 +232,7 @@ void GLBackend::releaseResourceTexture(int slot) { } void GLBackend::resetResourceStage() { - for (int i = 0; i < _resource._textures.size(); i++) { + for (uint32_t i = 0; i < _resource._textures.size(); i++) { releaseResourceTexture(i); } } diff --git a/libraries/gpu/src/gpu/GLBackendShader.cpp b/libraries/gpu/src/gpu/GLBackendShader.cpp index 9c0cf7628d..5f90313423 100755 --- a/libraries/gpu/src/gpu/GLBackendShader.cpp +++ b/libraries/gpu/src/gpu/GLBackendShader.cpp @@ -35,71 +35,44 @@ void makeBindings(GLBackend::GLShader* shader) { GLint loc = -1; //Check for gpu specific attribute slotBindings - loc = glGetAttribLocation(glprogram, "position"); - if (loc >= 0) { - glBindAttribLocation(glprogram, gpu::Stream::POSITION, "position"); + loc = glGetAttribLocation(glprogram, "inPosition"); + if (loc >= 0 && loc != gpu::Stream::POSITION) { + glBindAttribLocation(glprogram, gpu::Stream::POSITION, "inPosition"); } - loc = glGetAttribLocation(glprogram, "attribPosition"); - if (loc >= 0) { - glBindAttribLocation(glprogram, gpu::Stream::POSITION, "attribPosition"); + loc = glGetAttribLocation(glprogram, "inNormal"); + if (loc >= 0 && loc != gpu::Stream::NORMAL) { + glBindAttribLocation(glprogram, gpu::Stream::NORMAL, "inNormal"); } - //Check for gpu specific attribute slotBindings - loc = glGetAttribLocation(glprogram, "gl_Vertex"); - if (loc >= 0) { - glBindAttribLocation(glprogram, gpu::Stream::POSITION, "gl_Vertex"); + loc = glGetAttribLocation(glprogram, "inColor"); + if (loc >= 0 && loc != gpu::Stream::COLOR) { + glBindAttribLocation(glprogram, gpu::Stream::COLOR, "inColor"); } - loc = glGetAttribLocation(glprogram, "normal"); - if (loc >= 0) { - glBindAttribLocation(glprogram, gpu::Stream::NORMAL, "normal"); - } - loc = glGetAttribLocation(glprogram, "attribNormal"); - if (loc >= 0) { - glBindAttribLocation(glprogram, gpu::Stream::NORMAL, "attribNormal"); + loc = glGetAttribLocation(glprogram, "inTexCoord0"); + if (loc >= 0 && loc != gpu::Stream::TEXCOORD) { + glBindAttribLocation(glprogram, gpu::Stream::TEXCOORD, "inTexCoord0"); } - loc = glGetAttribLocation(glprogram, "color"); - if (loc >= 0) { - glBindAttribLocation(glprogram, gpu::Stream::COLOR, "color"); - } - loc = glGetAttribLocation(glprogram, "attribColor"); - if (loc >= 0) { - glBindAttribLocation(glprogram, gpu::Stream::COLOR, "attribColor"); + loc = glGetAttribLocation(glprogram, "inTangent"); + if (loc >= 0 && loc != gpu::Stream::TANGENT) { + glBindAttribLocation(glprogram, gpu::Stream::TANGENT, "inTangent"); } - loc = glGetAttribLocation(glprogram, "texcoord"); - if (loc >= 0) { - glBindAttribLocation(glprogram, gpu::Stream::TEXCOORD, "texcoord"); - } - loc = glGetAttribLocation(glprogram, "attribTexcoord"); - if (loc >= 0) { - glBindAttribLocation(glprogram, gpu::Stream::TEXCOORD, "attribTexcoord"); - } - - loc = glGetAttribLocation(glprogram, "tangent"); - if (loc >= 0) { - glBindAttribLocation(glprogram, gpu::Stream::TANGENT, "tangent"); + loc = glGetAttribLocation(glprogram, "inTexCoord1"); + if (loc >= 0 && loc != gpu::Stream::TEXCOORD1) { + glBindAttribLocation(glprogram, gpu::Stream::TEXCOORD1, "inTexCoord1"); } - loc = glGetAttribLocation(glprogram, "texcoord1"); - if (loc >= 0) { - glBindAttribLocation(glprogram, gpu::Stream::TEXCOORD1, "texcoord1"); - } - loc = glGetAttribLocation(glprogram, "attribTexcoord1"); - if (loc >= 0) { - glBindAttribLocation(glprogram, gpu::Stream::TEXCOORD1, "texcoord1"); + loc = glGetAttribLocation(glprogram, "inSkinClusterIndex"); + if (loc >= 0 && loc != gpu::Stream::SKIN_CLUSTER_INDEX) { + glBindAttribLocation(glprogram, gpu::Stream::SKIN_CLUSTER_INDEX, "inSkinClusterIndex"); } - loc = glGetAttribLocation(glprogram, "clusterIndices"); - if (loc >= 0) { - glBindAttribLocation(glprogram, gpu::Stream::SKIN_CLUSTER_INDEX, "clusterIndices"); - } - - loc = glGetAttribLocation(glprogram, "clusterWeights"); - if (loc >= 0) { - glBindAttribLocation(glprogram, gpu::Stream::SKIN_CLUSTER_WEIGHT, "clusterWeights"); + loc = glGetAttribLocation(glprogram, "inSkinClusterWeight"); + if (loc >= 0 && loc != gpu::Stream::SKIN_CLUSTER_WEIGHT) { + glBindAttribLocation(glprogram, gpu::Stream::SKIN_CLUSTER_WEIGHT, "inSkinClusterWeight"); } // Link again to take into account the assigned attrib location @@ -114,7 +87,6 @@ void makeBindings(GLBackend::GLShader* shader) { // now assign the ubo binding, then DON't relink! //Check for gpu specific uniform slotBindings -#if (GPU_TRANSFORM_PROFILE == GPU_CORE) loc = glGetUniformBlockIndex(glprogram, "transformObjectBuffer"); if (loc >= 0) { glUniformBlockBinding(glprogram, loc, gpu::TRANSFORM_OBJECT_SLOT); @@ -126,22 +98,6 @@ void makeBindings(GLBackend::GLShader* shader) { glUniformBlockBinding(glprogram, loc, gpu::TRANSFORM_CAMERA_SLOT); shader->_transformCameraSlot = gpu::TRANSFORM_CAMERA_SLOT; } -#else - loc = glGetUniformLocation(glprogram, "transformObject_model"); - if (loc >= 0) { - shader->_transformObject_model = loc; - } - - loc = glGetUniformLocation(glprogram, "transformCamera_viewInverse"); - if (loc >= 0) { - shader->_transformCamera_viewInverse = loc; - } - - loc = glGetUniformLocation(glprogram, "transformCamera_viewport"); - if (loc >= 0) { - shader->_transformCamera_viewport = loc; - } -#endif } GLBackend::GLShader* compileShader(const Shader& shader) { @@ -191,8 +147,8 @@ GLBackend::GLShader* compileShader(const Shader& shader) { char* temp = new char[infoLength] ; glGetShaderInfoLog(glshader, infoLength, NULL, temp); - qCDebug(gpulogging) << "GLShader::compileShader - failed to compile the gl shader object:"; - qCDebug(gpulogging) << temp; + qCWarning(gpulogging) << "GLShader::compileShader - failed to compile the gl shader object:"; + qCWarning(gpulogging) << temp; /* filestream.open("debugshader.glsl.info.txt"); @@ -635,8 +591,6 @@ bool isUnusedSlot(GLint binding) { int makeUniformBlockSlots(GLuint glprogram, const Shader::BindingSet& slotBindings, Shader::SlotSet& buffers) { GLint buffersCount = 0; -#if (GPU_FEATURE_PROFILE == GPU_CORE) - glGetProgramiv(glprogram, GL_ACTIVE_UNIFORM_BLOCKS, &buffersCount); // fast exit @@ -689,7 +643,6 @@ int makeUniformBlockSlots(GLuint glprogram, const Shader::BindingSet& slotBindin Element element(SCALAR, gpu::UINT32, gpu::UNIFORM_BUFFER); buffers.insert(Shader::Slot(name, binding, element, Resource::BUFFER)); } -#endif return buffersCount; } @@ -750,11 +703,7 @@ bool GLBackend::makeProgram(Shader& shader, const Shader::BindingSet& slotBindin Shader::SlotSet uniforms; Shader::SlotSet textures; Shader::SlotSet samplers; -#if (GPU_FEATURE_PROFILE == GPU_CORE) makeUniformSlots(object->_program, slotBindings, uniforms, textures, samplers); -#else - makeUniformSlots(object->_program, slotBindings, uniforms, textures, samplers, buffers); -#endif Shader::SlotSet inputs; makeInputSlots(object->_program, slotBindings, inputs); diff --git a/libraries/gpu/src/gpu/GLBackendState.cpp b/libraries/gpu/src/gpu/GLBackendState.cpp index 22c61b2365..c5cc987fd1 100644 --- a/libraries/gpu/src/gpu/GLBackendState.cpp +++ b/libraries/gpu/src/gpu/GLBackendState.cpp @@ -484,10 +484,14 @@ void GLBackend::syncPipelineStateCache() { glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); // Point size is always on - glHint(GL_POINT_SMOOTH_HINT, GL_NICEST); + // FIXME CORE + //glHint(GL_POINT_SMOOTH_HINT, GL_NICEST); glEnable(GL_PROGRAM_POINT_SIZE_EXT); glEnable(GL_VERTEX_PROGRAM_POINT_SIZE); + // Default line width accross the board + glLineWidth(1.0f); + getCurrentGLState(state); State::Signature signature = State::evalSignature(state); @@ -583,10 +587,8 @@ void GLBackend::do_setStateMultisampleEnable(bool enable) { void GLBackend::do_setStateAntialiasedLineEnable(bool enable) { if (_pipeline._stateCache.antialisedLineEnable != enable) { if (enable) { - glEnable(GL_POINT_SMOOTH); glEnable(GL_LINE_SMOOTH); } else { - glDisable(GL_POINT_SMOOTH); glDisable(GL_LINE_SMOOTH); } (void) CHECK_GL_ERROR(); diff --git a/libraries/gpu/src/gpu/GLBackendTransform.cpp b/libraries/gpu/src/gpu/GLBackendTransform.cpp index e05e0fc1c0..5099e3ed2a 100755 --- a/libraries/gpu/src/gpu/GLBackendTransform.cpp +++ b/libraries/gpu/src/gpu/GLBackendTransform.cpp @@ -41,7 +41,6 @@ void GLBackend::do_setViewportTransform(Batch& batch, uint32 paramOffset) { } void GLBackend::initTransform() { - #if (GPU_TRANSFORM_PROFILE == GPU_CORE) glGenBuffers(1, &_transform._transformObjectBuffer); glGenBuffers(1, &_transform._transformCameraBuffer); @@ -51,18 +50,12 @@ void GLBackend::initTransform() { glBindBuffer(GL_UNIFORM_BUFFER, _transform._transformCameraBuffer); glBufferData(GL_UNIFORM_BUFFER, sizeof(_transform._transformCamera), (const void*) &_transform._transformCamera, GL_DYNAMIC_DRAW); - glBindBuffer(GL_UNIFORM_BUFFER, 0); -#else -#endif } void GLBackend::killTransform() { - #if (GPU_TRANSFORM_PROFILE == GPU_CORE) glDeleteBuffers(1, &_transform._transformObjectBuffer); glDeleteBuffers(1, &_transform._transformCameraBuffer); -#else -#endif } void GLBackend::syncTransformStateCache() { @@ -73,14 +66,7 @@ void GLBackend::syncTransformStateCache() { glGetIntegerv(GL_VIEWPORT, (GLint*) &_transform._viewport); - GLint currentMode; - glGetIntegerv(GL_MATRIX_MODE, ¤tMode); - _transform._lastMode = currentMode; - - glGetFloatv(GL_PROJECTION_MATRIX, (float*) &_transform._projection); - Mat4 modelView; - glGetFloatv(GL_MODELVIEW_MATRIX, (float*) &modelView); auto modelViewInv = glm::inverse(modelView); _transform._view.evalFromRawMatrix(modelViewInv); _transform._model.setIdentity(); @@ -113,7 +99,8 @@ void GLBackend::updateTransform() { _transform._transformCamera._projectionViewUntranslated = _transform._transformCamera._projection * viewUntranslated; } - #if (GPU_TRANSFORM_PROFILE == GPU_CORE) + // TODO: WE need a ring buffer to do effcient dynamic updates here + // FOr now let's just do that bind and update sequence if (_transform._invalidView || _transform._invalidProj || _transform._invalidViewport) { glBindBufferBase(GL_UNIFORM_BUFFER, TRANSFORM_CAMERA_SLOT, 0); glBindBuffer(GL_ARRAY_BUFFER, _transform._transformCameraBuffer); @@ -133,52 +120,6 @@ void GLBackend::updateTransform() { glBindBufferBase(GL_UNIFORM_BUFFER, TRANSFORM_OBJECT_SLOT, _transform._transformObjectBuffer); glBindBufferBase(GL_UNIFORM_BUFFER, TRANSFORM_CAMERA_SLOT, _transform._transformCameraBuffer); CHECK_GL_ERROR(); -#endif - - -#if (GPU_TRANSFORM_PROFILE == GPU_LEGACY) - // Do it again for fixed pipeline until we can get rid of it - GLint originalMatrixMode; - glGetIntegerv(GL_MATRIX_MODE, &originalMatrixMode); - - if (_transform._invalidProj) { - if (_transform._lastMode != GL_PROJECTION) { - glMatrixMode(GL_PROJECTION); - _transform._lastMode = GL_PROJECTION; - } - glLoadMatrixf(reinterpret_cast< const GLfloat* >(&_transform._projection)); - - (void) CHECK_GL_ERROR(); - } - - - if (_transform._invalidModel || _transform._invalidView) { - if (_transform._lastMode != GL_MODELVIEW) { - glMatrixMode(GL_MODELVIEW); - _transform._lastMode = GL_MODELVIEW; - } - if (!_transform._model.isIdentity()) { - Transform::Mat4 modelView; - if (!_transform._view.isIdentity()) { - Transform mvx; - Transform::inverseMult(mvx, _transform._view, _transform._model); - mvx.getMatrix(modelView); - } else { - _transform._model.getMatrix(modelView); - } - glLoadMatrixf(reinterpret_cast< const GLfloat* >(&modelView)); - } else if (!_transform._view.isIdentity()) { - Transform::Mat4 modelView; - _transform._view.getInverseMatrix(modelView); - glLoadMatrixf(reinterpret_cast< const GLfloat* >(&modelView)); - } else { - glLoadIdentity(); - } - (void) CHECK_GL_ERROR(); - } - - glMatrixMode(originalMatrixMode); -#endif // Flags are clean _transform._invalidView = _transform._invalidProj = _transform._invalidModel = _transform._invalidViewport = false; diff --git a/libraries/gpu/src/gpu/GPUConfig.h b/libraries/gpu/src/gpu/GPUConfig.h index 5590c4cc8d..0aa7ce4020 100644 --- a/libraries/gpu/src/gpu/GPUConfig.h +++ b/libraries/gpu/src/gpu/GPUConfig.h @@ -18,18 +18,18 @@ #define GPU_LEGACY 0 #if defined(__APPLE__) -#include -#include -#define GPU_FEATURE_PROFILE GPU_LEGACY -#define GPU_TRANSFORM_PROFILE GPU_LEGACY +#include + +#define GPU_FEATURE_PROFILE GPU_CORE +#define GPU_INPUT_PROFILE GPU_CORE_41 #elif defined(WIN32) #include #include #define GPU_FEATURE_PROFILE GPU_CORE -#define GPU_TRANSFORM_PROFILE GPU_CORE +#define GPU_INPUT_PROFILE GPU_CORE_41 #elif defined(ANDROID) @@ -38,7 +38,7 @@ #include #define GPU_FEATURE_PROFILE GPU_CORE -#define GPU_TRANSFORM_PROFILE GPU_CORE +#define GPU_INPUT_PROFILE GPU_CORE_41 #endif diff --git a/libraries/gpu/src/gpu/Inputs.slh b/libraries/gpu/src/gpu/Inputs.slh new file mode 100644 index 0000000000..8f90b6ebee --- /dev/null +++ b/libraries/gpu/src/gpu/Inputs.slh @@ -0,0 +1,21 @@ + +<@if not GPU_INPUTS_SLH@> +<@def GPU_INPUTS_SLH@> +in vec4 inPosition; +in vec4 inNormal; +in vec4 inColor; +in vec4 inTexCoord0; +in vec4 inTangent; +in vec4 inSkinClusterIndex; +in vec4 inSkinClusterWeight; +in vec4 inTexCoord1; +<@endif@> diff --git a/libraries/gpu/src/gpu/Resource.cpp b/libraries/gpu/src/gpu/Resource.cpp index 5498e24189..4cdbe8203a 100644 --- a/libraries/gpu/src/gpu/Resource.cpp +++ b/libraries/gpu/src/gpu/Resource.cpp @@ -14,7 +14,7 @@ using namespace gpu; -const Element Element::COLOR_RGBA_32 = Element(VEC4, UINT8, RGBA); +const Element Element::COLOR_RGBA_32 = Element(VEC4, NUINT8, RGBA); const Element Element::VEC3F_XYZ = Element(VEC3, FLOAT, XYZ); const Element Element::INDEX_UINT16 = Element(SCALAR, UINT16, INDEX); const Element Element::PART_DRAWCALL = Element(VEC4, UINT32, PART); diff --git a/libraries/gpu/src/gpu/State.h b/libraries/gpu/src/gpu/State.h index 39cad1445f..5e53284f36 100755 --- a/libraries/gpu/src/gpu/State.h +++ b/libraries/gpu/src/gpu/State.h @@ -260,7 +260,7 @@ public: depthClampEnable(false), scissorEnable(false), multisampleEnable(false), - antialisedLineEnable(false), + antialisedLineEnable(true), alphaToCoverageEnable(false) {} }; diff --git a/libraries/gpu/src/gpu/Stream.h b/libraries/gpu/src/gpu/Stream.h index 27cb0ca539..46ea1574ed 100644 --- a/libraries/gpu/src/gpu/Stream.h +++ b/libraries/gpu/src/gpu/Stream.h @@ -27,13 +27,17 @@ public: // Possible input slots identifiers enum InputSlot { POSITION = 0, - NORMAL, - COLOR, - TEXCOORD, - TANGENT, - SKIN_CLUSTER_INDEX, - SKIN_CLUSTER_WEIGHT, - TEXCOORD1, + NORMAL = 1, + COLOR = 2, + TEXCOORD0 = 3, + TEXCOORD = TEXCOORD0, + TANGENT = 4, + SKIN_CLUSTER_INDEX = 5, + SKIN_CLUSTER_WEIGHT = 6, + TEXCOORD1 = 7, + INSTANCE_XFM = 8, + INSTANCE_SCALE = 9, + INSTANCE_TRANSLATE = 10, NUM_INPUT_SLOTS, }; diff --git a/libraries/gpu/src/gpu/Transform.slh b/libraries/gpu/src/gpu/Transform.slh index a3299ae599..49c2455c8a 100644 --- a/libraries/gpu/src/gpu/Transform.slh +++ b/libraries/gpu/src/gpu/Transform.slh @@ -25,7 +25,6 @@ struct TransformCamera { vec4 _viewport; }; -<@if GPU_TRANSFORM_PROFILE == GPU_CORE@> uniform transformObjectBuffer { TransformObject _object; }; @@ -39,83 +38,22 @@ uniform transformCameraBuffer { TransformCamera getTransformCamera() { return _camera; } - -<@else@> -//uniform vec4 transformObjectBuffer[8]; - -TransformObject getTransformObject() { - TransformObject object; - /* object._model[0] = transformObjectBuffer[0]; - object._model[1] = transformObjectBuffer[1]; - object._model[2] = transformObjectBuffer[2]; - object._model[3] = transformObjectBuffer[3]; - - object._modelInverse[0] = transformObjectBuffer[4]; - object._modelInverse[1] = transformObjectBuffer[5]; - object._modelInverse[2] = transformObjectBuffer[6]; - object._modelInverse[3] = transformObjectBuffer[7]; -*/ - return object; -} - -//uniform vec4 transformCameraBuffer[17]; -TransformCamera getTransformCamera() { - TransformCamera camera; -/* camera._view[0] = transformCameraBuffer[0]; - camera._view[1] = transformCameraBuffer[1]; - camera._view[2] = transformCameraBuffer[2]; - camera._view[3] = transformCameraBuffer[3]; - - camera._viewInverse[0] = transformCameraBuffer[4]; - camera._viewInverse[1] = transformCameraBuffer[5]; - camera._viewInverse[2] = transformCameraBuffer[6]; - camera._viewInverse[3] = transformCameraBuffer[7]; - - camera._projectionViewUntranslated[0] = transformCameraBuffer[8]; - camera._projectionViewUntranslated[1] = transformCameraBuffer[9]; - camera._projectionViewUntranslated[2] = transformCameraBuffer[10]; - camera._projectionViewUntranslated[3] = transformCameraBuffer[11]; - - camera._projection[0] = transformCameraBuffer[12]; - camera._projection[1] = transformCameraBuffer[13]; - camera._projection[2] = transformCameraBuffer[14]; - camera._projection[3] = transformCameraBuffer[15]; - - camera._viewport = transformCameraBuffer[16]; -*/ - return camera; -} - -uniform mat4 transformObject_model; -uniform mat4 transformCamera_viewInverse; -uniform vec4 transformCamera_viewport; - -<@endif@> <@endfunc@> <@func transformCameraViewport(cameraTransform, viewport)@> -<@if GPU_TRANSFORM_PROFILE == GPU_CORE@> <$viewport$> = <$cameraTransform$>._viewport; -<@else@> - <$viewport$> = transformCamera_viewport; -<@endif@> <@endfunc@> <@func transformModelToClipPos(cameraTransform, objectTransform, modelPos, clipPos)@> -<@if GPU_TRANSFORM_PROFILE == GPU_CORE@> { // transformModelToClipPos vec4 _eyepos = (<$objectTransform$>._model * <$modelPos$>) + vec4(-<$modelPos$>.w * <$cameraTransform$>._viewInverse[3].xyz, 0.0); <$clipPos$> = <$cameraTransform$>._projectionViewUntranslated * _eyepos; } -<@else@> - <$clipPos$> = gl_ModelViewProjectionMatrix * <$modelPos$>; -<@endif@> <@endfunc@> <@func $transformModelToEyeAndClipPos(cameraTransform, objectTransform, modelPos, eyePos, clipPos)@> -<@if GPU_TRANSFORM_PROFILE == GPU_CORE@> { // transformModelToClipPos @@ -125,24 +63,15 @@ uniform vec4 transformCamera_viewport; <$clipPos$> = <$cameraTransform$>._projectionViewUntranslated * _eyepos; // <$eyePos$> = (<$cameraTransform$>._projectionInverse * <$clipPos$>); } -<@else@> - <$eyePos$> = gl_ModelViewMatrix * <$modelPos$>; - <$clipPos$> = gl_ModelViewProjectionMatrix * <$modelPos$>; -<@endif@> <@endfunc@> <@func transformModelToWorldPos(objectTransform, modelPos, worldPos)@> -<@if GPU_TRANSFORM_PROFILE == GPU_CORE@> { // transformModelToWorldPos <$worldPos$> = (<$objectTransform$>._model * <$modelPos$>); } -<@else@> - <$worldPos$> = (transformObject_model * <$modelPos$>); -<@endif@> <@endfunc@> <@func transformModelToEyeDir(cameraTransform, objectTransform, modelDir, eyeDir)@> -<@if GPU_TRANSFORM_PROFILE == GPU_CORE@> { // transformModelToEyeDir vec3 mr0 = vec3(<$objectTransform$>._modelInverse[0].x, <$objectTransform$>._modelInverse[1].x, <$objectTransform$>._modelInverse[2].x); vec3 mr1 = vec3(<$objectTransform$>._modelInverse[0].y, <$objectTransform$>._modelInverse[1].y, <$objectTransform$>._modelInverse[2].y); @@ -154,29 +83,18 @@ uniform vec4 transformCamera_viewport; <$eyeDir$> = vec3(dot(mvc0, <$modelDir$>), dot(mvc1, <$modelDir$>), dot(mvc2, <$modelDir$>)); } -<@else@> - <$eyeDir$> = gl_NormalMatrix * <$modelDir$>; -<@endif@> <@endfunc@> <@func transformEyeToWorldDir(cameraTransform, eyeDir, worldDir)@> -<@if GPU_TRANSFORM_PROFILE == GPU_CORE@> { // transformEyeToWorldDir <$worldDir$> = vec3(<$cameraTransform$>._viewInverse * vec4(<$eyeDir$>.xyz, 0.0)); } -<@else@> - <$worldDir$> = vec3(transformCamera_viewInverse * vec4(<$eyeDir$>.xyz, 0.0)); -<@endif@> <@endfunc@> <@func transformClipToEyeDir(cameraTransform, clipPos, eyeDir)@> -<@if GPU_TRANSFORM_PROFILE == GPU_CORE@> { // transformClipToEyeDir <$eyeDir$> = vec3(<$cameraTransform$>._projectionInverse * vec4(<$clipPos$>.xyz, 1.0)); } -<@else@> - <$eyeDir$> = vec3(gl_ProjectionMatrixInverse * vec4(<$clipPos$>.xyz, 1.0)); -<@endif@> <@endfunc@> <@endif@> diff --git a/libraries/model/CMakeLists.txt b/libraries/model/CMakeLists.txt index 7ede1c5746..563f347952 100755 --- a/libraries/model/CMakeLists.txt +++ b/libraries/model/CMakeLists.txt @@ -1,6 +1,6 @@ set(TARGET_NAME model) -AUTOSCRIBE_SHADER_LIB(gpu) +AUTOSCRIBE_SHADER_LIB(gpu model) # use setup_hifi_library macro to setup our project and link appropriate Qt modules setup_hifi_library() diff --git a/libraries/model/src/model/Atmosphere.slh b/libraries/model/src/model/Atmosphere.slh index cc1b7017b0..0af5fa27f3 100755 --- a/libraries/model/src/model/Atmosphere.slh +++ b/libraries/model/src/model/Atmosphere.slh @@ -6,53 +6,53 @@ // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -!> +!> <@if not MODEL_ATMOSPHERE_SLH@> -<@def MODEL_ATMOSPHERE_SLH@> - - - +<@def MODEL_ATMOSPHERE_SLH@> + + + struct Atmosphere { vec4 _invWaveLength; vec4 _radiuses; vec4 _scales; vec4 _scatterings; vec4 _control; -}; - -const int numSamples = 2; +}; + +const int numSamples = 2; vec3 getAtmosphereInvWaveLength(Atmosphere a) { return a._invWaveLength.xyz; } // 1 / pow(wavelength, 4) for the red, green, and blue channels @@ -68,88 +68,88 @@ float getAtmosphereKrESun(Atmosphere a) { return a._scatterings.x; } // Kr * ESu float getAtmosphereKmESun(Atmosphere a) { return a._scatterings.y; } // Km * ESun float getAtmosphereKr4PI(Atmosphere a) { return a._scatterings.z; } // Kr * 4 * PI float getAtmosphereKm4PI(Atmosphere a) { return a._scatterings.w; } // Km * 4 * PI - + float getAtmosphereNumSamples(Atmosphere a) { return a._control.x; } // numSamples vec2 getAtmosphereGAndG2(Atmosphere a) { return a._control.yz; } // g and g2 -float atmosphereScale(float scaleDepth, float fCos) -{ - float x = 1.0 - fCos; - return scaleDepth * exp(-0.00287 + x*(0.459 + x*(3.83 + x*(-6.80 + x*5.25)))); -} - -vec4 evalAtmosphereContribution(Atmosphere atmospheric, vec3 position, vec3 cameraPos, vec3 lightPos) { - float fInnerRadius = getAtmosphereInnerRadius(atmospheric); - float fSamples = getAtmosphereNumSamples(atmospheric); - - vec3 v3InvWavelength = getAtmosphereInvWaveLength(atmospheric); - vec4 scatteringCoefs = getAtmosphereScattering(atmospheric); - float fKrESun = scatteringCoefs.x; - float fKmESun = scatteringCoefs.y; - float fKr4PI = scatteringCoefs.z; - float fKm4PI = scatteringCoefs.w; - - vec2 gAndg2 = getAtmosphereGAndG2(atmospheric); - float g = gAndg2.x; - float g2 = gAndg2.y; - - float fScale = getAtmosphereScale(atmospheric); - float fScaleDepth = getAtmosphereScaleDepth(atmospheric); - float fScaleOverScaleDepth = getAtmosphereScaleOverScaleDepth(atmospheric); - - // Get the ray from the camera to the vertex, and its length (which is the far point of the ray passing through the atmosphere) - vec3 v3Pos = position; - vec3 v3Ray = v3Pos - cameraPos; - float fFar = length(v3Ray); - v3Ray /= fFar; - - // Calculate the ray's starting position, then calculate its scattering offset - vec3 v3Start = cameraPos; - float fHeight = length(v3Start); - float fDepthStart = exp(fScaleOverScaleDepth * (fInnerRadius - fHeight)); - float fStartAngle = dot(v3Ray, v3Start) / fHeight; - float fStartOffset = fDepthStart * atmosphereScale(fScaleDepth, fStartAngle); - - // Initialize the scattering loop variables - //gl_FrontColor = vec4(0.0, 0.0, 0.0, 0.0); - float fSampleLength = fFar / fSamples; - float fScaledLength = fSampleLength * fScale; - - vec3 v3SampleRay = v3Ray * fSampleLength; - vec3 v3SamplePoint = v3Start + v3SampleRay * 0.5; - - // Now loop through the sample rays - vec3 v3FrontColor = vec3(0.0, 0.0, 0.0); - // int nSamples = numSamples; - int nSamples = int(fSamples); - for(int i=0; i uniform atmosphereBuffer { @@ -171,75 +171,75 @@ Atmosphere getAtmosphere() { return atmosphere; } <@endif@> - - - + + + <@endif@> diff --git a/libraries/model/src/model/Material.slh b/libraries/model/src/model/Material.slh index 6b8eea18a6..61b433b432 100644 --- a/libraries/model/src/model/Material.slh +++ b/libraries/model/src/model/Material.slh @@ -18,32 +18,17 @@ struct Material { vec4 _spare; }; +uniform materialBuffer { + Material _mat; +}; + +Material getMaterial() { + return _mat; +} + float getMaterialOpacity(Material m) { return m._diffuse.a; } vec3 getMaterialDiffuse(Material m) { return m._diffuse.rgb; } vec3 getMaterialSpecular(Material m) { return m._specular.rgb; } float getMaterialShininess(Material m) { return m._specular.a; } - - -<@if GPU_FEATURE_PROFILE == GPU_CORE@> -uniform materialBuffer { - Material _mat; -}; -Material getMaterial() { - return _mat; -} -<@else@> -uniform vec4 materialBuffer[4]; -Material getMaterial() { - Material mat; - mat._diffuse = materialBuffer[0]; - mat._specular = materialBuffer[1]; - mat._emissive = materialBuffer[2]; - mat._spare = materialBuffer[3]; - return mat; -} -<@endif@> - - - <@endif@> diff --git a/libraries/model/src/model/Skybox.slf b/libraries/model/src/model/Skybox.slf index abb30bf09c..47444b21bd 100755 --- a/libraries/model/src/model/Skybox.slf +++ b/libraries/model/src/model/Skybox.slf @@ -2,6 +2,7 @@ <$VERSION_HEADER$> // Generated on <$_SCRIBE_DATE$> // skybox.frag +// fragment shader // // Created by Sam Gateau on 5/5/2015. // Copyright 2015 High Fidelity, Inc. @@ -12,14 +13,22 @@ uniform samplerCube cubeMap; -varying vec3 normal; -varying vec2 texcoord; -varying vec3 color; +struct Skybox { + vec4 _color; +}; +uniform skyboxBuffer { + Skybox _skybox; +}; + +in vec3 _normal; + +out vec4 _fragColor; void main(void) { - vec3 coord = normalize(normal); - vec4 texel = textureCube(cubeMap, coord); - vec3 pixel = pow(texel.xyz * color, vec3(1.0/2.2)); // manual Gamma correction - gl_FragData[0] = vec4(pixel, 0.0); + vec3 coord = normalize(_normal); + vec3 texel = texture(cubeMap, coord).rgb; + vec3 color = texel * _skybox._color.rgb; + vec3 pixel = pow(color, vec3(1.0/2.2)); // manual Gamma correction + _fragColor = vec4(pixel, 0.0); } diff --git a/libraries/model/src/model/Skybox.slv b/libraries/model/src/model/Skybox.slv index 0ca64ffbf7..d1b9a20a66 100755 --- a/libraries/model/src/model/Skybox.slv +++ b/libraries/model/src/model/Skybox.slv @@ -11,48 +11,24 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // + +<@include gpu/Inputs.slh@> + <@include gpu/Transform.slh@> <$declareStandardTransform()$> -struct Skybox { - vec4 _color; -}; - -<@if GPU_FEATURE_PROFILE == GPU_CORE @> -uniform skyboxBuffer { - Skybox _skybox; -}; -Skybox getSkybox() { - return _skybox; -} -<@else@> -uniform vec4 skyboxBuffer[1]; -Skybox getSkybox() { - Skybox _skybox; - _skybox._color = skyboxBuffer[0]; - return _skybox; -} -<@endif@> - -varying vec3 normal; -varying vec2 texcoord; -varying vec3 color; - -void main(void) { - texcoord = gl_Vertex.xy; - - Skybox skybox = getSkybox(); - color = skybox._color.xyz; +out vec3 _normal; +void main(void) { // standard transform TransformCamera cam = getTransformCamera(); - vec3 clipDir = vec3(texcoord.xy, 0.0); + vec3 clipDir = vec3(inPosition.xy, 0.0); vec3 eyeDir; - <$transformClipToEyeDir(cam, clipDir, eyeDir)$>; - <$transformEyeToWorldDir(cam, eyeDir, normal)$>; - - // Position is supposed to cmoe in clip space - gl_Position = vec4(texcoord.xy, 0.0, 1.0); -} + <$transformClipToEyeDir(cam, clipDir, eyeDir)$> + <$transformEyeToWorldDir(cam, eyeDir, _normal)$> + + // Position is supposed to come in clip space + gl_Position = vec4(inPosition.xy, 0.0, 1.0); +} \ No newline at end of file diff --git a/libraries/networking/src/DataServerAccountInfo.cpp b/libraries/networking/src/DataServerAccountInfo.cpp index a85aa588a8..0628e21574 100644 --- a/libraries/networking/src/DataServerAccountInfo.cpp +++ b/libraries/networking/src/DataServerAccountInfo.cpp @@ -10,11 +10,13 @@ // #include +#include #include #include #include +#include "UUID.h" #include "NetworkLogging.h" #include "DataServerAccountInfo.h" @@ -30,8 +32,7 @@ DataServerAccountInfo::DataServerAccountInfo() : _walletID(), _balance(0), _hasBalance(false), - _privateKey(), - _usernameSignature() + _privateKey() { } @@ -73,9 +74,6 @@ void DataServerAccountInfo::setAccessTokenFromJSON(const QJsonObject& jsonObject void DataServerAccountInfo::setUsername(const QString& username) { if (_username != username) { _username = username; - - // clear our username signature so it has to be re-created - _usernameSignature = QByteArray(); qCDebug(networking) << "Username changed to" << username; } @@ -128,8 +126,8 @@ void DataServerAccountInfo::setProfileInfoFromJSON(const QJsonObject& jsonObject setWalletID(QUuid(user["wallet_id"].toString())); } -const QByteArray& DataServerAccountInfo::getUsernameSignature() { - if (_usernameSignature.isEmpty()) { +QByteArray DataServerAccountInfo::getUsernameSignature(const QUuid& connectionToken) { + if (!_privateKey.isEmpty()) { const char* privateKeyData = _privateKey.constData(); RSA* rsaPrivateKey = d2i_RSAPrivateKey(NULL, @@ -137,36 +135,41 @@ const QByteArray& DataServerAccountInfo::getUsernameSignature() { _privateKey.size()); if (rsaPrivateKey) { QByteArray lowercaseUsername = _username.toLower().toUtf8(); - _usernameSignature.resize(RSA_size(rsaPrivateKey)); + QByteArray usernameWithToken = QCryptographicHash::hash(lowercaseUsername.append(connectionToken.toRfc4122()), + QCryptographicHash::Sha256); - int encryptReturn = RSA_private_encrypt(lowercaseUsername.size(), - reinterpret_cast(lowercaseUsername.constData()), - reinterpret_cast(_usernameSignature.data()), - rsaPrivateKey, RSA_PKCS1_PADDING); + QByteArray usernameSignature(RSA_size(rsaPrivateKey), 0); + unsigned int usernameSignatureSize = 0; - if (encryptReturn == -1) { - qCDebug(networking) << "Error encrypting username signature."; - qCDebug(networking) << "Will re-attempt on next domain-server check in."; - _usernameSignature = QByteArray(); - } + int encryptReturn = RSA_sign(NID_sha256, + reinterpret_cast(usernameWithToken.constData()), + usernameWithToken.size(), + reinterpret_cast(usernameSignature.data()), + &usernameSignatureSize, + rsaPrivateKey); // free the private key RSA struct now that we are done with it RSA_free(rsaPrivateKey); + + if (encryptReturn == -1) { + qCDebug(networking) << "Error encrypting username signature."; + qCDebug(networking) << "Will re-attempt on next domain-server check in."; + } else { + qDebug(networking) << "Returning username" << _username << "signed with connection UUID" << uuidStringWithoutCurlyBraces(connectionToken); + return usernameSignature; + } + } else { qCDebug(networking) << "Could not create RSA struct from QByteArray private key."; qCDebug(networking) << "Will re-attempt on next domain-server check in."; } } - } - - return _usernameSignature; + return QByteArray(); } void DataServerAccountInfo::setPrivateKey(const QByteArray& privateKey) { _privateKey = privateKey; - // clear our username signature so it has to be re-created - _usernameSignature = QByteArray(); } QDataStream& operator<<(QDataStream &out, const DataServerAccountInfo& info) { diff --git a/libraries/networking/src/DataServerAccountInfo.h b/libraries/networking/src/DataServerAccountInfo.h index d7f9d5167a..9b80de5422 100644 --- a/libraries/networking/src/DataServerAccountInfo.h +++ b/libraries/networking/src/DataServerAccountInfo.h @@ -43,7 +43,7 @@ public: const QUuid& getWalletID() const { return _walletID; } void setWalletID(const QUuid& walletID); - const QByteArray& getUsernameSignature(); + QByteArray getUsernameSignature(const QUuid& connectionToken); bool hasPrivateKey() const { return !_privateKey.isEmpty(); } void setPrivateKey(const QByteArray& privateKey); @@ -73,7 +73,7 @@ private: qint64 _balance; bool _hasBalance; QByteArray _privateKey; - QByteArray _usernameSignature; + }; #endif // hifi_DataServerAccountInfo_h diff --git a/libraries/networking/src/DomainHandler.cpp b/libraries/networking/src/DomainHandler.cpp index afb362053e..8f4b9cc61f 100644 --- a/libraries/networking/src/DomainHandler.cpp +++ b/libraries/networking/src/DomainHandler.cpp @@ -29,6 +29,7 @@ DomainHandler::DomainHandler(QObject* parent) : _uuid(), _sockAddr(HifiSockAddr(QHostAddress::Null, DEFAULT_DOMAIN_SERVER_PORT)), _assignmentUUID(), + _connectionToken(), _iceDomainID(), _iceClientID(), _iceServerSockAddr(), @@ -43,7 +44,8 @@ DomainHandler::DomainHandler(QObject* parent) : void DomainHandler::clearConnectionInfo() { _uuid = QUuid(); - + _connectionToken = QUuid(); + _icePeer.reset(); if (requiresICE()) { diff --git a/libraries/networking/src/DomainHandler.h b/libraries/networking/src/DomainHandler.h index 6079035f8b..7bb0582914 100644 --- a/libraries/networking/src/DomainHandler.h +++ b/libraries/networking/src/DomainHandler.h @@ -50,9 +50,12 @@ public: unsigned short getPort() const { return _sockAddr.getPort(); } void setPort(quint16 port) { _sockAddr.setPort(port); } + const QUuid& getConnectionToken() const { return _connectionToken; } + void setConnectionToken(const QUuid& connectionToken) { _connectionToken = connectionToken; } + const QUuid& getAssignmentUUID() const { return _assignmentUUID; } void setAssignmentUUID(const QUuid& assignmentUUID) { _assignmentUUID = assignmentUUID; } - + const QUuid& getICEDomainID() const { return _iceDomainID; } const QUuid& getICEClientID() const { return _iceClientID; } @@ -114,6 +117,7 @@ private: QString _hostname; HifiSockAddr _sockAddr; QUuid _assignmentUUID; + QUuid _connectionToken; QUuid _iceDomainID; QUuid _iceClientID; HifiSockAddr _iceServerSockAddr; diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index dfa3ef86a5..44b9c0b829 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -94,7 +94,7 @@ NodeList::NodeList(char newOwnerType, unsigned short socketListenPort, unsigned packetReceiver.registerListener(PacketType::PingReply, this, "processPingReplyPacket"); packetReceiver.registerListener(PacketType::ICEPing, this, "processICEPingPacket"); packetReceiver.registerListener(PacketType::DomainServerAddedNode, this, "processDomainServerAddedNode"); - + packetReceiver.registerListener(PacketType::DomainServerConnectionToken, this, "processDomainServerConnectionTokenPacket"); packetReceiver.registerListener(PacketType::ICEServerPeerInformation, &_domainHandler, "processICEResponsePacket"); packetReceiver.registerListener(PacketType::DomainServerRequireDTLS, &_domainHandler, "processDTLSRequirementPacket"); packetReceiver.registerListener(PacketType::ICEPingReply, &_domainHandler, "processICEPingReplyPacket"); @@ -274,17 +274,23 @@ void NodeList::sendDomainServerCheckIn() { // pack our data to send to the domain-server packetStream << _ownerType << _publicSockAddr << _localSockAddr << _nodeTypesOfInterest.toList(); - + // if this is a connect request, and we can present a username signature, send it along - if (!_domainHandler.isConnected()) { + if (!_domainHandler.isConnected() ) { + DataServerAccountInfo& accountInfo = AccountManager::getInstance().getAccountInfo(); packetStream << accountInfo.getUsername(); - - const QByteArray& usernameSignature = AccountManager::getInstance().getAccountInfo().getUsernameSignature(); - - if (!usernameSignature.isEmpty()) { - qCDebug(networking) << "Including username signature in domain connect request."; - packetStream << usernameSignature; + + // get connection token from the domain-server + const QUuid& connectionToken = _domainHandler.getConnectionToken(); + + if (!connectionToken.isNull()) { + + const QByteArray& usernameSignature = AccountManager::getInstance().getAccountInfo().getUsernameSignature(connectionToken); + + if (!usernameSignature.isEmpty()) { + packetStream << usernameSignature; + } } } @@ -361,6 +367,7 @@ void NodeList::sendDSPathQuery(const QString& newPath) { } } + void NodeList::processDomainServerPathResponse(QSharedPointer packet) { // This is a response to a path query we theoretically made. // In the future we may want to check that this was actually from our DS and for a query we actually made. @@ -450,6 +457,17 @@ void NodeList::pingPunchForDomainServer() { } } + +void NodeList::processDomainServerConnectionTokenPacket(QSharedPointer packet) { + if (_domainHandler.getSockAddr().isNull()) { + // refuse to process this packet if we aren't currently connected to the DS + return; + } + // read in the connection token from the packet, then send domain-server checkin + _domainHandler.setConnectionToken(QUuid::fromRfc4122(packet->read(NUM_BYTES_RFC4122_UUID))); + sendDomainServerCheckIn(); +} + void NodeList::processDomainServerList(QSharedPointer packet) { if (_domainHandler.getSockAddr().isNull()) { // refuse to process this packet if we aren't currently connected to the DS diff --git a/libraries/networking/src/NodeList.h b/libraries/networking/src/NodeList.h index e3f8feeeda..3aae3e3dfc 100644 --- a/libraries/networking/src/NodeList.h +++ b/libraries/networking/src/NodeList.h @@ -76,6 +76,8 @@ public slots: void processDomainServerAddedNode(QSharedPointer packet); void processDomainServerPathResponse(QSharedPointer packet); + void processDomainServerConnectionTokenPacket(QSharedPointer packet); + void processPingPacket(QSharedPointer packet, SharedNodePointer sendingNode); void processPingReplyPacket(QSharedPointer packet, SharedNodePointer sendingNode); diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp index 0591ac30fe..f3f222f310 100644 --- a/libraries/networking/src/udt/PacketHeaders.cpp +++ b/libraries/networking/src/udt/PacketHeaders.cpp @@ -26,7 +26,7 @@ const QSet SEQUENCE_NUMBERED_PACKETS = QSet NON_SOURCED_PACKETS = QSet() << StunResponse << CreateAssignment << RequestAssignment - << DomainServerRequireDTLS << DomainConnectRequest + << DomainServerRequireDTLS << DomainConnectRequest << DomainServerConnectionToken << DomainList << DomainConnectionDenied << DomainServerPathQuery << DomainServerPathResponse << DomainServerAddedNode @@ -119,6 +119,7 @@ QString nameForPacketType(PacketType::Value packetType) { PACKET_TYPE_NAME_LOOKUP(ICEPingReply); PACKET_TYPE_NAME_LOOKUP(EntityAdd); PACKET_TYPE_NAME_LOOKUP(EntityEdit); + PACKET_TYPE_NAME_LOOKUP(DomainServerConnectionToken); default: return QString("Type: ") + QString::number((int)packetType); } diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index 3f3f165e87..46f834db74 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -73,7 +73,8 @@ namespace PacketType { EntityQuery, EntityAdd, EntityErase, - EntityEdit + EntityEdit, + DomainServerConnectionToken }; }; diff --git a/libraries/octree/src/Octree.cpp b/libraries/octree/src/Octree.cpp index 203ff2b072..999cb23407 100644 --- a/libraries/octree/src/Octree.cpp +++ b/libraries/octree/src/Octree.cpp @@ -38,8 +38,8 @@ #include #include #include -#include #include +#include #include "CoverageMap.h" #include "OctreeConstants.h" @@ -49,7 +49,7 @@ #include "OctreeLogging.h" -QVector PERSIST_EXTENSIONS = {"svo", "json"}; +QVector PERSIST_EXTENSIONS = {"svo", "json", "json.gz"}; float boundaryDistanceForRenderLevel(unsigned int renderLevel, float voxelSizeScale) { return voxelSizeScale / powf(2, renderLevel); @@ -791,13 +791,6 @@ public: bool found; }; -class ShapeArgs { -public: - const Shape* shape; - CollisionList& collisions; - bool found; -}; - class ContentArgs { public: AACube cube; @@ -1809,29 +1802,52 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* element, } bool Octree::readFromFile(const char* fileName) { - bool fileOk = false; - QString qFileName = findMostRecentFileExtension(fileName, PERSIST_EXTENSIONS); - QFile file(qFileName); - fileOk = file.open(QIODevice::ReadOnly); - if(fileOk) { - QDataStream fileInputStream(&file); - QFileInfo fileInfo(qFileName); - unsigned long fileLength = fileInfo.size(); - - emit importSize(1.0f, 1.0f, 1.0f); - emit importProgress(0); - - qCDebug(octree) << "Loading file" << qFileName << "..."; - - fileOk = readFromStream(fileLength, fileInputStream); - - emit importProgress(100); - file.close(); + if (qFileName.endsWith(".json.gz")) { + return readJSONFromGzippedFile(qFileName); } - return fileOk; + QFile file(qFileName); + + if (!file.open(QIODevice::ReadOnly)) { + qCritical() << "unable to open for reading: " << fileName; + return false; + } + + QDataStream fileInputStream(&file); + QFileInfo fileInfo(qFileName); + unsigned long fileLength = fileInfo.size(); + + emit importSize(1.0f, 1.0f, 1.0f); + emit importProgress(0); + + qCDebug(octree) << "Loading file" << qFileName << "..."; + + bool success = readFromStream(fileLength, fileInputStream); + + emit importProgress(100); + file.close(); + + return success; +} + +bool Octree::readJSONFromGzippedFile(QString qFileName) { + QFile file(qFileName); + if (!file.open(QIODevice::ReadOnly)) { + qCritical() << "Cannot open gzipped json file for reading: " << qFileName; + return false; + } + QByteArray compressedJsonData = file.readAll(); + QByteArray jsonData; + + if (!gunzip(compressedJsonData, jsonData)) { + qCritical() << "json File not in gzip format: " << qFileName; + return false; + } + + QDataStream jsonStream(jsonData); + return readJSONFromStream(-1, jsonStream); } bool Octree::readFromURL(const QString& urlString) { @@ -1867,18 +1883,17 @@ bool Octree::readFromURL(const QString& urlString) { bool Octree::readFromStream(unsigned long streamLength, QDataStream& inputStream) { - - // decide if this is SVO or JSON + // decide if this is binary SVO or JSON-formatted SVO QIODevice *device = inputStream.device(); char firstChar; device->getChar(&firstChar); device->ungetChar(firstChar); if (firstChar == (char) PacketType::EntityData) { - qCDebug(octree) << "Reading from SVO Stream length:" << streamLength; + qCDebug(octree) << "Reading from binary SVO Stream length:" << streamLength; return readSVOFromStream(streamLength, inputStream); } else { - qCDebug(octree) << "Reading from JSON Stream length:" << streamLength; + qCDebug(octree) << "Reading from JSON SVO Stream length:" << streamLength; return readJSONFromStream(streamLength, inputStream); } } @@ -2013,12 +2028,28 @@ bool Octree::readSVOFromStream(unsigned long streamLength, QDataStream& inputStr return fileOk; } -bool Octree::readJSONFromStream(unsigned long streamLength, QDataStream& inputStream) { - char* rawData = new char[streamLength + 1]; // allocate enough room to null terminate - inputStream.readRawData(rawData, streamLength); - rawData[streamLength] = 0; // make sure we null terminate this string +const int READ_JSON_BUFFER_SIZE = 2048; - QJsonDocument asDocument = QJsonDocument::fromJson(rawData); +bool Octree::readJSONFromStream(unsigned long streamLength, QDataStream& inputStream) { + // if the data is gzipped we may not have a useful bytesAvailable() result, so just keep reading until + // we get an eof. Leave streamLength parameter for consistency. + + QByteArray jsonBuffer; + char* rawData = new char[READ_JSON_BUFFER_SIZE]; + while (true) { + int got = inputStream.readRawData(rawData, READ_JSON_BUFFER_SIZE - 1); + if (got < 0) { + qCritical() << "error while reading from json stream"; + delete[] rawData; + return false; + } + if (got == 0) { + break; + } + jsonBuffer += QByteArray(rawData, got); + } + + QJsonDocument asDocument = QJsonDocument::fromJson(jsonBuffer); QVariant asVariant = asDocument.toVariant(); QVariantMap asMap = asVariant.toMap(); readFromMap(asMap); @@ -2036,13 +2067,14 @@ void Octree::writeToFile(const char* fileName, OctreeElement* element, QString p writeToSVOFile(fileName, element); } else if (persistAsFileType == "json") { writeToJSONFile(cFileName, element); + } else if (persistAsFileType == "json.gz") { + writeToJSONFile(cFileName, element, true); } else { qCDebug(octree) << "unable to write octree to file of type" << persistAsFileType; } } -void Octree::writeToJSONFile(const char* fileName, OctreeElement* element) { - QFile persistFile(fileName); +void Octree::writeToJSONFile(const char* fileName, OctreeElement* element, bool doGzip) { QVariantMap entityDescription; qCDebug(octree, "Saving JSON SVO to file %s...", fileName); @@ -2061,10 +2093,27 @@ void Octree::writeToJSONFile(const char* fileName, OctreeElement* element) { // store the entity data bool entityDescriptionSuccess = writeToMap(entityDescription, top, true); + if (!entityDescriptionSuccess) { + qCritical("Failed to convert Entities to QVariantMap while saving to json."); + return; + } // convert the QVariantMap to JSON - if (entityDescriptionSuccess && persistFile.open(QIODevice::WriteOnly)) { - persistFile.write(QJsonDocument::fromVariant(entityDescription).toJson()); + QByteArray jsonData = QJsonDocument::fromVariant(entityDescription).toJson(); + QByteArray jsonDataForFile; + + if (doGzip) { + if (!gzip(jsonData, jsonDataForFile, -1)) { + qCritical("unable to gzip data while saving to json."); + return; + } + } else { + jsonDataForFile = jsonData; + } + + QFile persistFile(fileName); + if (persistFile.open(QIODevice::WriteOnly)) { + persistFile.write(jsonDataForFile); } else { qCritical("Could not write to JSON description of entities."); } diff --git a/libraries/octree/src/Octree.h b/libraries/octree/src/Octree.h index e00434be80..244359e394 100644 --- a/libraries/octree/src/Octree.h +++ b/libraries/octree/src/Octree.h @@ -330,7 +330,7 @@ public: // Octree exporters void writeToFile(const char* filename, OctreeElement* element = NULL, QString persistAsFileType = "svo"); - void writeToJSONFile(const char* filename, OctreeElement* element = NULL); + void writeToJSONFile(const char* filename, OctreeElement* element = NULL, bool doGzip = false); void writeToSVOFile(const char* filename, OctreeElement* element = NULL); virtual bool writeToMap(QVariantMap& entityDescription, OctreeElement* element, bool skipDefaultValues) = 0; @@ -340,6 +340,7 @@ public: bool readFromStream(unsigned long streamLength, QDataStream& inputStream); bool readSVOFromStream(unsigned long streamLength, QDataStream& inputStream); bool readJSONFromStream(unsigned long streamLength, QDataStream& inputStream); + bool readJSONFromGzippedFile(QString qFileName); virtual bool readFromMap(QVariantMap& entityDescription) = 0; unsigned long getOctreeElementsCount(); diff --git a/libraries/octree/src/OctreeElement.cpp b/libraries/octree/src/OctreeElement.cpp index e11a11fc8e..85ea0caef0 100644 --- a/libraries/octree/src/OctreeElement.cpp +++ b/libraries/octree/src/OctreeElement.cpp @@ -19,7 +19,6 @@ #include #include #include -#include #include "AACube.h" #include "OctalCode.h" @@ -637,53 +636,8 @@ OctreeElement* OctreeElement::getOrCreateChildElementAt(float x, float y, float if (s > halfOurScale) { return this; } - // otherwise, we need to find which of our children we should recurse - glm::vec3 ourCenter = _cube.calcCenter(); - int childIndex = CHILD_UNKNOWN; - // left half - if (x > ourCenter.x) { - if (y > ourCenter.y) { - // top left - if (z > ourCenter.z) { - // top left far - childIndex = CHILD_TOP_LEFT_FAR; - } else { - // top left near - childIndex = CHILD_TOP_LEFT_NEAR; - } - } else { - // bottom left - if (z > ourCenter.z) { - // bottom left far - childIndex = CHILD_BOTTOM_LEFT_FAR; - } else { - // bottom left near - childIndex = CHILD_BOTTOM_LEFT_NEAR; - } - } - } else { - // right half - if (y > ourCenter.y) { - // top right - if (z > ourCenter.z) { - // top right far - childIndex = CHILD_TOP_RIGHT_FAR; - } else { - // top right near - childIndex = CHILD_TOP_RIGHT_NEAR; - } - } else { - // bottom right - if (z > ourCenter.z) { - // bottom right far - childIndex = CHILD_BOTTOM_RIGHT_FAR; - } else { - // bottom right near - childIndex = CHILD_BOTTOM_RIGHT_NEAR; - } - } - } + int childIndex = getMyChildContainingPoint(glm::vec3(x, y, z)); // Now, check if we have a child at that location child = getChildAtIndex(childIndex); diff --git a/libraries/octree/src/OctreeElement.h b/libraries/octree/src/OctreeElement.h index 830655242f..d2f3f7d3aa 100644 --- a/libraries/octree/src/OctreeElement.h +++ b/libraries/octree/src/OctreeElement.h @@ -24,7 +24,6 @@ #include "ViewFrustum.h" #include "OctreeConstants.h" -class CollisionList; class EncodeBitstreamParams; class Octree; class OctreeElement; diff --git a/libraries/render-utils/CMakeLists.txt b/libraries/render-utils/CMakeLists.txt index 9d3b4a441f..357b9284fd 100644 --- a/libraries/render-utils/CMakeLists.txt +++ b/libraries/render-utils/CMakeLists.txt @@ -8,8 +8,6 @@ qt5_add_resources(QT_RESOURCES_FILE "${CMAKE_CURRENT_SOURCE_DIR}/res/fonts/fonts # use setup_hifi_library macro to setup our project and link appropriate Qt modules setup_hifi_library(Widgets OpenGL Network Qml Quick Script) -setup_hifi_opengl() - add_dependency_external_projects(glm) find_package(GLM REQUIRED) target_include_directories(${TARGET_NAME} PUBLIC ${GLM_INCLUDE_DIRS}) diff --git a/libraries/render-utils/src/DeferredBuffer.slh b/libraries/render-utils/src/DeferredBuffer.slh index 885fa96543..b9112def10 100755 --- a/libraries/render-utils/src/DeferredBuffer.slh +++ b/libraries/render-utils/src/DeferredBuffer.slh @@ -50,10 +50,10 @@ struct DeferredFragment { DeferredFragment unpackDeferredFragment(vec2 texcoord) { DeferredFragment frag; - frag.depthVal = texture2D(depthMap, texcoord).r; - frag.normalVal = texture2D(normalMap, texcoord); - frag.diffuseVal = texture2D(diffuseMap, texcoord); - frag.specularVal = texture2D(specularMap, texcoord); + frag.depthVal = texture(depthMap, texcoord).r; + frag.normalVal = texture(normalMap, texcoord); + frag.diffuseVal = texture(diffuseMap, texcoord); + frag.specularVal = texture(specularMap, texcoord); // compute the view space position using the depth float z = near / (frag.depthVal * depthScale - 1.0); diff --git a/libraries/render-utils/src/DeferredBufferWrite.slh b/libraries/render-utils/src/DeferredBufferWrite.slh index a3edfbdbbb..b9b0198ba5 100755 --- a/libraries/render-utils/src/DeferredBufferWrite.slh +++ b/libraries/render-utils/src/DeferredBufferWrite.slh @@ -11,12 +11,33 @@ <@if not DEFERRED_BUFFER_WRITE_SLH@> <@def DEFERRED_BUFFER_WRITE_SLH@> +layout(location = 0) out vec4 _fragColor0; +layout(location = 1) out vec4 _fragColor1; +layout(location = 2) out vec4 _fragColor2; + // the glow intensity uniform float glowIntensity; // the alpha threshold uniform float alphaThreshold; +uniform sampler2D normalFittingMap; + +vec3 bestFitNormal(vec3 normal) { + vec3 absNorm = abs(normal); + float maxNAbs = max(absNorm.z, max(absNorm.x, absNorm.y)); + + vec2 texcoord = (absNorm.z < maxNAbs ? + (absNorm.y < maxNAbs ? absNorm.yz : absNorm.xz) : + absNorm.xy); + texcoord = (texcoord.x < texcoord.y ? texcoord.yx : texcoord.xy); + texcoord.y /= texcoord.x; + vec3 cN = normal / maxNAbs; + float fittingScale = texture(normalFittingMap, texcoord).a; + cN *= fittingScale; + return (cN * 0.5 + 0.5); +} + float evalOpaqueFinalAlpha(float alpha, float mapAlpha) { return mix(alpha * glowIntensity, 1.0 - alpha * glowIntensity, step(mapAlpha, alphaThreshold)); } @@ -28,9 +49,9 @@ void packDeferredFragment(vec3 normal, float alpha, vec3 diffuse, vec3 specular, if (alpha != glowIntensity) { discard; } - gl_FragData[0] = vec4(diffuse.rgb, alpha); - gl_FragData[1] = vec4(normal, 0.0) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0); - gl_FragData[2] = vec4(specular, shininess / 128.0); + _fragColor0 = vec4(diffuse.rgb, alpha); + _fragColor1 = vec4(bestFitNormal(normal), 1.0); + _fragColor2 = vec4(specular, shininess / 128.0); } void packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 diffuse, vec3 specular, float shininess, vec3 emissive) { @@ -38,10 +59,10 @@ void packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 diffuse, vec3 s discard; } - gl_FragData[0] = vec4(diffuse.rgb, alpha); - //gl_FragData[1] = vec4(normal, 0.0) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0); - gl_FragData[1] = vec4(normal, 0.0) * 0.5 + vec4(0.5, 0.5, 0.5, 0.5); - gl_FragData[2] = vec4(emissive, shininess / 128.0); + _fragColor0 = vec4(diffuse.rgb, alpha); + //_fragColor1 = vec4(normal, 0.0) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0); + _fragColor1 = vec4(bestFitNormal(normal), 0.5); + _fragColor2 = vec4(emissive, shininess / 128.0); } void packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 diffuse, vec3 specular, float shininess) { @@ -49,9 +70,9 @@ void packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 diffuse, vec discard; } - gl_FragData[0] = vec4(diffuse.rgb, alpha); - // gl_FragData[1] = vec4(normal, 0.0) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0); - // gl_FragData[2] = vec4(specular, shininess / 128.0); + _fragColor0 = vec4(diffuse.rgb, alpha); + // _fragColor1 = vec4(normal, 0.0) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0); + // _fragColor2 = vec4(specular, shininess / 128.0); } <@endif@> diff --git a/libraries/render-utils/src/DeferredGlobalLight.slh b/libraries/render-utils/src/DeferredGlobalLight.slh index 2f312e42d8..fe8e74361a 100755 --- a/libraries/render-utils/src/DeferredGlobalLight.slh +++ b/libraries/render-utils/src/DeferredGlobalLight.slh @@ -16,12 +16,9 @@ uniform samplerCube skyboxMap; vec4 evalSkyboxLight(vec3 direction, float lod) { - -<@if GPU_TRANSFORM_PROFILE == GPU_CORE@> - vec4 skytexel = textureCubeLod(skyboxMap, direction, lod * textureQueryLevels(skyboxMap)); -<@else@> - vec4 skytexel = textureCube(skyboxMap, direction); -<@endif@> + // FIXME + //vec4 skytexel = textureLod(skyboxMap, direction, lod * textureQueryLevels(skyboxMap)); + vec4 skytexel = texture(skyboxMap, direction); return skytexel; } diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 3fc0a4c46a..08ab6e0cf6 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -86,6 +86,7 @@ void DeferredLightingEffect::init(AbstractViewStateInterface* viewState) { _emissiveShader = gpu::ShaderPointer(gpu::Shader::createProgram(VS, PSEmissive)); gpu::Shader::BindingSet slotBindings; + slotBindings.insert(gpu::Shader::Binding(std::string("normalFittingMap"), DeferredLightingEffect::NORMAL_FITTING_MAP_SLOT)); gpu::Shader::makeProgram(*_simpleShader, slotBindings); gpu::Shader::makeProgram(*_emissiveShader, slotBindings); @@ -151,6 +152,8 @@ void DeferredLightingEffect::bindSimpleProgram(gpu::Batch& batch, bool textured, // If it is not textured, bind white texture and keep using textured pipeline batch.setResourceTexture(0, DependencyManager::get()->getWhiteTexture()); } + + batch.setResourceTexture(NORMAL_FITTING_MAP_SLOT, DependencyManager::get()->getNormalFittingTexture()); } void DeferredLightingEffect::renderSolidSphere(gpu::Batch& batch, float radius, int slices, int stacks, const glm::vec4& color) { @@ -406,9 +409,7 @@ void DeferredLightingEffect::render(RenderArgs* args) { Transform viewMat; args->_viewFrustum->evalProjectionMatrix(projMat); args->_viewFrustum->evalViewTransform(viewMat); - if (args->_renderMode == RenderArgs::MIRROR_RENDER_MODE) { - viewMat.postScale(glm::vec3(-1.0f, 1.0f, 1.0f)); - } + batch.setProjectionTransform(projMat); batch.setViewTransform(viewMat); diff --git a/libraries/render-utils/src/DeferredLightingEffect.h b/libraries/render-utils/src/DeferredLightingEffect.h index ba4fbd6d69..62497851d7 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.h +++ b/libraries/render-utils/src/DeferredLightingEffect.h @@ -30,7 +30,8 @@ class DeferredLightingEffect : public Dependency { SINGLETON_DEPENDENCY public: - + static const int NORMAL_FITTING_MAP_SLOT = 10; + void init(AbstractViewStateInterface* viewState); /// Sets up the state necessary to render static untextured geometry with the simple program. diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index c793c9dc82..31b030f75a 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -20,7 +20,6 @@ #include #include -#include #include #include "TextureCache.h" @@ -277,7 +276,7 @@ void GeometryCache::renderSphere(gpu::Batch& batch, float radius, int slices, in streamFormat = std::make_shared(); // 1 for everyone streamFormat->setAttribute(gpu::Stream::POSITION, VERTICES_SLOT, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0); streamFormat->setAttribute(gpu::Stream::NORMAL, NORMALS_SLOT, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ)); - streamFormat->setAttribute(gpu::Stream::COLOR, COLOR_SLOT, gpu::Element(gpu::VEC4, gpu::UINT8, gpu::RGBA)); + streamFormat->setAttribute(gpu::Stream::COLOR, COLOR_SLOT, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA)); positionElement = streamFormat->getAttributes().at(gpu::Stream::POSITION)._element; normalElement = streamFormat->getAttributes().at(gpu::Stream::NORMAL)._element; colorElement = streamFormat->getAttributes().at(gpu::Stream::COLOR)._element; @@ -363,7 +362,7 @@ void GeometryCache::renderGrid(gpu::Batch& batch, int xDivisions, int yDivisions auto streamFormat = std::make_shared(); // 1 for everyone streamFormat->setAttribute(gpu::Stream::POSITION, VERTICES_SLOT, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::XYZ), 0); - streamFormat->setAttribute(gpu::Stream::COLOR, COLOR_SLOT, gpu::Element(gpu::VEC4, gpu::UINT8, gpu::RGBA)); + streamFormat->setAttribute(gpu::Stream::COLOR, COLOR_SLOT, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA)); gpu::BufferView verticesView(verticesBuffer, 0, verticesBuffer->getSize(), streamFormat->getAttributes().at(gpu::Stream::POSITION)._element); gpu::BufferView colorView(colorBuffer, streamFormat->getAttributes().at(gpu::Stream::COLOR)._element); @@ -470,7 +469,7 @@ void GeometryCache::renderGrid(gpu::Batch& batch, int x, int y, int width, int h auto streamFormat = std::make_shared(); // 1 for everyone streamFormat->setAttribute(gpu::Stream::POSITION, VERTICES_SLOT, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::XYZ), 0); - streamFormat->setAttribute(gpu::Stream::COLOR, COLOR_SLOT, gpu::Element(gpu::VEC4, gpu::UINT8, gpu::RGBA)); + streamFormat->setAttribute(gpu::Stream::COLOR, COLOR_SLOT, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA)); gpu::BufferView verticesView(verticesBuffer, 0, verticesBuffer->getSize(), streamFormat->getAttributes().at(gpu::Stream::POSITION)._element); gpu::BufferView colorView(colorBuffer, streamFormat->getAttributes().at(gpu::Stream::COLOR)._element); @@ -507,7 +506,7 @@ void GeometryCache::updateVertices(int id, const QVector& points, con details.stream = stream; details.streamFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::XYZ), 0); - details.streamFormat->setAttribute(gpu::Stream::COLOR, 1, gpu::Element(gpu::VEC4, gpu::UINT8, 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.colorBuffer, 0, details.streamFormat->getChannels().at(1)._stride); @@ -568,7 +567,7 @@ void GeometryCache::updateVertices(int id, const QVector& points, con details.stream = stream; details.streamFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0); - details.streamFormat->setAttribute(gpu::Stream::COLOR, 1, gpu::Element(gpu::VEC4, gpu::UINT8, 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.colorBuffer, 0, details.streamFormat->getChannels().at(1)._stride); @@ -632,7 +631,7 @@ void GeometryCache::updateVertices(int id, const QVector& points, con details.streamFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0); details.streamFormat->setAttribute(gpu::Stream::TEXCOORD, 0, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::UV), 3 * sizeof(float)); - details.streamFormat->setAttribute(gpu::Stream::COLOR, 1, gpu::Element(gpu::VEC4, gpu::UINT8, 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.colorBuffer, 0, details.streamFormat->getChannels().at(1)._stride); @@ -786,7 +785,7 @@ void GeometryCache::renderSolidCube(gpu::Batch& batch, float size, const glm::ve streamFormat = std::make_shared(); // 1 for everyone streamFormat->setAttribute(gpu::Stream::POSITION, VERTICES_SLOT, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0); streamFormat->setAttribute(gpu::Stream::NORMAL, NORMALS_SLOT, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ)); - streamFormat->setAttribute(gpu::Stream::COLOR, COLOR_SLOT, gpu::Element(gpu::VEC4, gpu::UINT8, gpu::RGBA)); + streamFormat->setAttribute(gpu::Stream::COLOR, COLOR_SLOT, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA)); positionElement = streamFormat->getAttributes().at(gpu::Stream::POSITION)._element; normalElement = streamFormat->getAttributes().at(gpu::Stream::NORMAL)._element; colorElement = streamFormat->getAttributes().at(gpu::Stream::COLOR)._element; @@ -873,7 +872,7 @@ void GeometryCache::renderWireCube(gpu::Batch& batch, float size, const glm::vec if (!streamFormat) { streamFormat = std::make_shared(); // 1 for everyone streamFormat->setAttribute(gpu::Stream::POSITION, VERTICES_SLOT, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0); - streamFormat->setAttribute(gpu::Stream::COLOR, COLOR_SLOT, gpu::Element(gpu::VEC4, gpu::UINT8, gpu::RGBA)); + streamFormat->setAttribute(gpu::Stream::COLOR, COLOR_SLOT, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA)); positionElement = streamFormat->getAttributes().at(gpu::Stream::POSITION)._element; colorElement = streamFormat->getAttributes().at(gpu::Stream::COLOR)._element; } @@ -929,7 +928,7 @@ void GeometryCache::renderBevelCornersRect(gpu::Batch& batch, int x, int y, int details.stream = stream; details.streamFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::XYZ)); - details.streamFormat->setAttribute(gpu::Stream::COLOR, 1, gpu::Element(gpu::VEC4, gpu::UINT8, 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.colorBuffer, 0, details.streamFormat->getChannels().at(1)._stride); @@ -1031,7 +1030,7 @@ void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec2& minCorner, co details.stream = stream; details.streamFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::XYZ), 0); - details.streamFormat->setAttribute(gpu::Stream::COLOR, 1, gpu::Element(gpu::VEC4, gpu::UINT8, 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.colorBuffer, 0, details.streamFormat->getChannels().at(1)._stride); @@ -1126,7 +1125,7 @@ void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec2& minCorner, co details.streamFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::XYZ), 0); details.streamFormat->setAttribute(gpu::Stream::TEXCOORD, 0, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::UV), VERTEX_TEXCOORD_OFFSET); - details.streamFormat->setAttribute(gpu::Stream::COLOR, 1, gpu::Element(gpu::VEC4, gpu::UINT8, 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.colorBuffer, 0, details.streamFormat->getChannels().at(1)._stride); @@ -1200,7 +1199,7 @@ void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec3& minCorner, co details.stream = stream; details.streamFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0); - details.streamFormat->setAttribute(gpu::Stream::COLOR, 1, gpu::Element(gpu::VEC4, gpu::UINT8, 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.colorBuffer, 0, details.streamFormat->getChannels().at(1)._stride); @@ -1293,7 +1292,7 @@ void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec3& topLeft, cons details.streamFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0); details.streamFormat->setAttribute(gpu::Stream::TEXCOORD, 0, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::UV), VERTEX_TEXCOORD_OFFSET); - details.streamFormat->setAttribute(gpu::Stream::COLOR, 1, gpu::Element(gpu::VEC4, gpu::UINT8, 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.colorBuffer, 0, details.streamFormat->getChannels().at(1)._stride); @@ -1373,7 +1372,7 @@ void GeometryCache::renderDashedLine(gpu::Batch& batch, const glm::vec3& start, details.stream = stream; details.streamFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0); - details.streamFormat->setAttribute(gpu::Stream::COLOR, 1, gpu::Element(gpu::VEC4, gpu::UINT8, 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.colorBuffer, 0, details.streamFormat->getChannels().at(1)._stride); @@ -1531,7 +1530,7 @@ void GeometryCache::renderLine(gpu::Batch& batch, const glm::vec3& p1, const glm details.stream = stream; details.streamFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0); - details.streamFormat->setAttribute(gpu::Stream::COLOR, 1, gpu::Element(gpu::VEC4, gpu::UINT8, 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.colorBuffer, 0, details.streamFormat->getChannels().at(1)._stride); @@ -1615,7 +1614,7 @@ void GeometryCache::renderLine(gpu::Batch& batch, const glm::vec2& p1, const glm details.stream = stream; details.streamFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0); - details.streamFormat->setAttribute(gpu::Stream::COLOR, 1, gpu::Element(gpu::VEC4, gpu::UINT8, 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.colorBuffer, 0, details.streamFormat->getChannels().at(1)._stride); @@ -2240,10 +2239,17 @@ bool NetworkMeshPart::isTranslucent() const { return diffuseTexture && diffuseTexture->isTranslucent(); } + +bool NetworkMesh::isPartTranslucent(const FBXMesh& fbxMesh, int partIndex) const { + assert(partIndex >= 0); + assert(partIndex < parts.size()); + return (parts.at(partIndex).isTranslucent() || fbxMesh.parts.at(partIndex).opacity != 1.0f); +} + int NetworkMesh::getTranslucentPartCount(const FBXMesh& fbxMesh) const { int count = 0; for (int i = 0; i < parts.size(); i++) { - if (parts.at(i).isTranslucent() || fbxMesh.parts.at(i).opacity != 1.0f) { + if (isPartTranslucent(fbxMesh, i)) { count++; } } diff --git a/libraries/render-utils/src/GeometryCache.h b/libraries/render-utils/src/GeometryCache.h index 812d12b846..f70eae6380 100644 --- a/libraries/render-utils/src/GeometryCache.h +++ b/libraries/render-utils/src/GeometryCache.h @@ -398,6 +398,7 @@ public: QVector parts; int getTranslucentPartCount(const FBXMesh& fbxMesh) const; + bool isPartTranslucent(const FBXMesh& fbxMesh, int partIndex) const; }; #endif // hifi_GeometryCache_h diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 51f737505f..8839a5b463 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -16,12 +16,9 @@ #include #include -#include #include #include #include -#include -#include #include #include #include @@ -108,6 +105,8 @@ void Model::RenderPipelineLib::addRenderPipeline(Model::RenderKey key, slotBindings.insert(gpu::Shader::Binding(std::string("specularMap"), 2)); slotBindings.insert(gpu::Shader::Binding(std::string("emissiveMap"), 3)); slotBindings.insert(gpu::Shader::Binding(std::string("lightBuffer"), 4)); + slotBindings.insert(gpu::Shader::Binding(std::string("normalFittingMap"), DeferredLightingEffect::NORMAL_FITTING_MAP_SLOT)); + gpu::ShaderPointer program = gpu::ShaderPointer(gpu::Shader::createProgram(vertexShader, pixelShader)); gpu::Shader::makeProgram(*program, slotBindings); @@ -159,8 +158,6 @@ void Model::RenderPipelineLib::addRenderPipeline(Model::RenderKey key, RenderKey mirrorKey(key.getRaw() | RenderKey::IS_MIRROR); auto mirrorState = std::make_shared(state->getValues()); - mirrorState->setFrontFaceClockwise(true); - // create a new RenderPipeline with the same shader side and the mirrorState auto mirrorPipeline = gpu::PipelinePointer(gpu::Pipeline::create(program, mirrorState)); insert(value_type(mirrorKey.getRaw(), RenderPipeline(mirrorPipeline, locations))); @@ -185,6 +182,8 @@ void Model::RenderPipelineLib::initLocations(gpu::ShaderPointer& program, Model: locations.emissiveParams = program->getUniforms().findLocation("emissiveParams"); locations.glowIntensity = program->getUniforms().findLocation("glowIntensity"); + locations.normalFittingMapUnit = program->getTextures().findLocation("normalFittingMap"); + locations.specularTextureUnit = program->getTextures().findLocation("specularMap"); locations.emissiveTextureUnit = program->getTextures().findLocation("emissiveMap"); @@ -193,11 +192,8 @@ void Model::RenderPipelineLib::initLocations(gpu::ShaderPointer& program, Model: locations.clusterMatrices = program->getUniforms().findLocation("clusterMatrices"); - locations.clusterIndices = program->getInputs().findLocation("clusterIndices");; - locations.clusterWeights = program->getInputs().findLocation("clusterWeights");; - - - + locations.clusterIndices = program->getInputs().findLocation("inSkinClusterIndex"); + locations.clusterWeights = program->getInputs().findLocation("inSkinClusterWeight"); } AbstractViewStateInterface* Model::_viewState = NULL; @@ -476,7 +472,23 @@ bool Model::updateGeometry() { void Model::initJointStates(QVector states) { const FBXGeometry& geometry = _geometry->getFBXGeometry(); glm::mat4 parentTransform = glm::scale(_scale) * glm::translate(_offset) * geometry.offset; - _boundingRadius = _rig->initJointStates(states, parentTransform); + + int rootJointIndex = geometry.rootJointIndex; + int leftHandJointIndex = geometry.leftHandJointIndex; + int leftElbowJointIndex = leftHandJointIndex >= 0 ? geometry.joints.at(leftHandJointIndex).parentIndex : -1; + int leftShoulderJointIndex = leftElbowJointIndex >= 0 ? geometry.joints.at(leftElbowJointIndex).parentIndex : -1; + int rightHandJointIndex = geometry.rightHandJointIndex; + int rightElbowJointIndex = rightHandJointIndex >= 0 ? geometry.joints.at(rightHandJointIndex).parentIndex : -1; + int rightShoulderJointIndex = rightElbowJointIndex >= 0 ? geometry.joints.at(rightElbowJointIndex).parentIndex : -1; + + _boundingRadius = _rig->initJointStates(states, parentTransform, + rootJointIndex, + leftHandJointIndex, + leftElbowJointIndex, + leftShoulderJointIndex, + rightHandJointIndex, + rightElbowJointIndex, + rightShoulderJointIndex); } bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const glm::vec3& direction, float& distance, @@ -1812,11 +1824,10 @@ void Model::segregateMeshGroups() { translucentMesh = hasTangents = hasSpecular = hasLightmap = isSkinned = false; } - // Debug... + // Create the render payloads int totalParts = mesh.parts.size(); for (int partIndex = 0; partIndex < totalParts; partIndex++) { - // this is a good place to create our renderPayloads - if (translucentMesh) { + if (networkMesh.isPartTranslucent(mesh, partIndex)) { _transparentRenderItems << std::make_shared(true, this, i, partIndex); } else { _opaqueRenderItems << std::make_shared(false, this, i, partIndex); @@ -1856,6 +1867,10 @@ void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, f const float DEFAULT_GLOW_INTENSITY = 1.0f; // FIXME - glow is removed batch._glUniform1f(locations->glowIntensity, DEFAULT_GLOW_INTENSITY); } + + if ((locations->normalFittingMapUnit > -1)) { + batch.setResourceTexture(locations->normalFittingMapUnit, DependencyManager::get()->getNormalFittingTexture()); + } } bool Model::initWhenReady(render::ScenePointer scene) { diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 09504c7501..9fdb2f3691 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -350,6 +350,7 @@ private: int emissiveTextureUnit; int emissiveParams; int glowIntensity; + int normalFittingMapUnit; int materialBufferUnit; int clusterMatrices; int clusterIndices; diff --git a/libraries/render-utils/src/PhysicsEntity.h b/libraries/render-utils/src/PhysicsEntity.h index 3b527c7827..f36473af26 100644 --- a/libraries/render-utils/src/PhysicsEntity.h +++ b/libraries/render-utils/src/PhysicsEntity.h @@ -18,9 +18,6 @@ #include #include -#include -#include - class PhysicsEntity { public: diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 07a8b63e6f..2db56fe68a 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -166,9 +166,7 @@ void DrawOpaqueDeferred::run(const SceneContextPointer& sceneContext, const Rend Transform viewMat; args->_viewFrustum->evalProjectionMatrix(projMat); args->_viewFrustum->evalViewTransform(viewMat); - if (args->_renderMode == RenderArgs::MIRROR_RENDER_MODE) { - viewMat.preScale(glm::vec3(-1.0f, 1.0f, 1.0f)); - } + batch.setProjectionTransform(projMat); batch.setViewTransform(viewMat); @@ -197,9 +195,7 @@ void DrawTransparentDeferred::run(const SceneContextPointer& sceneContext, const Transform viewMat; args->_viewFrustum->evalProjectionMatrix(projMat); args->_viewFrustum->evalViewTransform(viewMat); - if (args->_renderMode == RenderArgs::MIRROR_RENDER_MODE) { - viewMat.postScale(glm::vec3(-1.0f, 1.0f, 1.0f)); - } + batch.setProjectionTransform(projMat); batch.setViewTransform(viewMat); @@ -259,9 +255,7 @@ void DrawOverlay3D::run(const SceneContextPointer& sceneContext, const RenderCon Transform viewMat; args->_viewFrustum->evalProjectionMatrix(projMat); args->_viewFrustum->evalViewTransform(viewMat); - if (args->_renderMode == RenderArgs::MIRROR_RENDER_MODE) { - viewMat.postScale(glm::vec3(-1.0f, 1.0f, 1.0f)); - } + batch.setProjectionTransform(projMat); batch.setViewTransform(viewMat); batch.setViewportTransform(args->_viewport); diff --git a/libraries/render-utils/src/Shadow.slh b/libraries/render-utils/src/Shadow.slh index 2e75e2764c..decb434177 100755 --- a/libraries/render-utils/src/Shadow.slh +++ b/libraries/render-utils/src/Shadow.slh @@ -14,13 +14,25 @@ // the shadow texture uniform sampler2DShadow shadowMap; +struct EyePlanes { + vec4 _S[1]; + vec4 _T[1]; + vec4 _R[1]; + vec4 _Q[1]; +}; + +uniform eyePlanes { + EyePlanes _eyePlanes; +}; + +EyePlanes getEyePlanes() { + return _eyePlanes; +} + + // Fetching it float fetchShadow(vec3 texcoord) { -<@if GPU_FEATURE_PROFILE == GPU_CORE @> return texture(shadowMap, texcoord); -<@else@> - return shadow2D(shadowMap, texcoord).r; -<@endif@> } // the distances to the cascade sections @@ -44,17 +56,22 @@ vec2 samples[8] = vec2[8]( vec4 evalShadowTexcoord(vec4 position) { // compute the corresponding texture coordinates - vec3 shadowTexcoord = vec3(dot(gl_EyePlaneS[0], position), dot(gl_EyePlaneT[0], position), dot(gl_EyePlaneR[0], position)); + EyePlanes eyePlanes = getEyePlanes(); + vec3 shadowTexcoord = vec3(dot(eyePlanes._S[0], position), dot(eyePlanes._T[0], position), dot(eyePlanes._R[0], position)); return vec4(shadowTexcoord, 0.0); } vec4 evalCascadedShadowTexcoord(vec4 position) { + EyePlanes eyePlanes = getEyePlanes(); + // compute the index of the cascade to use and the corresponding texture coordinates int shadowIndex = int(dot(step(vec3(position.z), shadowDistances), vec3(1.0, 1.0, 1.0))); - vec3 shadowTexcoord = vec3(dot(gl_EyePlaneS[shadowIndex], position), dot(gl_EyePlaneT[shadowIndex], position), - dot(gl_EyePlaneR[shadowIndex], position)); + vec3 shadowTexcoord = vec3( + dot(eyePlanes._S[shadowIndex], position), + dot(eyePlanes._T[shadowIndex], position), + dot(eyePlanes._R[shadowIndex], position)); - return vec4(shadowTexcoord, shadowIndex); + return vec4(shadowTexcoord, shadowIndex); } float evalShadowAttenuationPCF(vec4 shadowTexcoord) { @@ -76,7 +93,7 @@ float evalShadowAttenuationPCF(vec4 shadowTexcoord) { )); } - return shadowAttenuation; + return shadowAttenuation; } float evalShadowAttenuationBasic(vec4 shadowTexcoord) { @@ -87,11 +104,11 @@ float evalShadowAttenuationBasic(vec4 shadowTexcoord) { fetchShadow(shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[2], 0.0)) + fetchShadow(shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[3], 0.0)) )); - return shadowAttenuation; + return shadowAttenuation; } float evalShadowAttenuation(vec4 shadowTexcoord) { - return evalShadowAttenuationBasic(shadowTexcoord); + return evalShadowAttenuationBasic(shadowTexcoord); } diff --git a/libraries/render-utils/src/SkyFromAtmosphere.slf b/libraries/render-utils/src/SkyFromAtmosphere.slf index 1e1718677c..c2a3635f07 100755 --- a/libraries/render-utils/src/SkyFromAtmosphere.slf +++ b/libraries/render-utils/src/SkyFromAtmosphere.slf @@ -33,16 +33,16 @@ // Copyright (c) 2004 Sean O'Neil // -uniform vec3 v3CameraPos; // The camera's current position -uniform vec3 v3InvWavelength; // 1 / pow(wavelength, 4) for the red, green, and blue channels -uniform float fInnerRadius; // The inner (planetary) radius -uniform float fKrESun; // Kr * ESun -uniform float fKmESun; // Km * ESun -uniform float fKr4PI; // Kr * 4 * PI -uniform float fKm4PI; // Km * 4 * PI -uniform float fScale; // 1 / (fOuterRadius - fInnerRadius) -uniform float fScaleDepth; // The scale depth (i.e. the altitude at which the atmosphere's average density is found) -uniform float fScaleOverScaleDepth; // fScale / fScaleDepth +uniform vec3 v3CameraPos; // The camera's current position +uniform vec3 v3InvWavelength; // 1 / pow(wavelength, 4) for the red, green, and blue channels +uniform float fInnerRadius; // The inner (planetary) radius +uniform float fKrESun; // Kr * ESun +uniform float fKmESun; // Km * ESun +uniform float fKr4PI; // Kr * 4 * PI +uniform float fKm4PI; // Km * 4 * PI +uniform float fScale; // 1 / (fOuterRadius - fInnerRadius) +uniform float fScaleDepth; // The scale depth (i.e. the altitude at which the atmosphere's average density is found) +uniform float fScaleOverScaleDepth; // fScale / fScaleDepth const int nSamples = 2; const float fSamples = 2.0; @@ -51,7 +51,8 @@ uniform vec3 v3LightPos; uniform float g; uniform float g2; -varying vec3 position; +in vec3 position; +out vec4 outFragColor; float scale(float fCos) @@ -97,7 +98,7 @@ void main (void) v3SamplePoint += v3SampleRay; } - // Finally, scale the Mie and Rayleigh colors and set up the varying variables for the pixel shader + // Finally, scale the Mie and Rayleigh colors and set up the in variables for the pixel shader vec3 secondaryFrontColor = v3FrontColor * fKmESun; vec3 frontColor = v3FrontColor * (v3InvWavelength * fKrESun); vec3 v3Direction = v3CameraPos - v3Pos; @@ -106,6 +107,6 @@ void main (void) float fMiePhase = 1.5 * ((1.0 - g2) / (2.0 + g2)) * (1.0 + fCos*fCos) / pow(1.0 + g2 - 2.0*g*fCos, 1.5); vec3 finalColor = frontColor.rgb + fMiePhase * secondaryFrontColor.rgb; - gl_FragColor.a = finalColor.b; - gl_FragColor.rgb = pow(finalColor.rgb, vec3(1.0/2.2)); + outFragColor.a = finalColor.b; + outFragColor.rgb = pow(finalColor.rgb, vec3(1.0/2.2)); } diff --git a/libraries/render-utils/src/SkyFromAtmosphere.slv b/libraries/render-utils/src/SkyFromAtmosphere.slv index 29c907b94c..c78f3b0a15 100755 --- a/libraries/render-utils/src/SkyFromAtmosphere.slv +++ b/libraries/render-utils/src/SkyFromAtmosphere.slv @@ -33,32 +33,33 @@ // Copyright (c) 2004 Sean O'Neil // +<@include gpu/Inputs.slh@> <@include gpu/Transform.slh@> <$declareStandardTransform()$> -uniform vec3 v3CameraPos; // The camera's current position -uniform vec3 v3LightPos; // The direction vector to the light source -uniform vec3 v3InvWavelength; // 1 / pow(wavelength, 4) for the red, green, and blue channels -uniform float fOuterRadius; // The outer (atmosphere) radius -uniform float fInnerRadius; // The inner (planetary) radius -uniform float fKrESun; // Kr * ESun -uniform float fKmESun; // Km * ESun -uniform float fKr4PI; // Kr * 4 * PI -uniform float fKm4PI; // Km * 4 * PI -uniform float fScale; // 1 / (fOuterRadius - fInnerRadius) -uniform float fScaleDepth; // The scale depth (i.e. the altitude at which the atmosphere's average density is found) -uniform float fScaleOverScaleDepth; // fScale / fScaleDepth +uniform vec3 v3CameraPos; // The camera's current position +uniform vec3 v3LightPos; // The direction vector to the light source +uniform vec3 v3InvWavelength; // 1 / pow(wavelength, 4) for the red, green, and blue channels +uniform float fOuterRadius; // The outer (atmosphere) radius +uniform float fInnerRadius; // The inner (planetary) radius +uniform float fKrESun; // Kr * ESun +uniform float fKmESun; // Km * ESun +uniform float fKr4PI; // Kr * 4 * PI +uniform float fKm4PI; // Km * 4 * PI +uniform float fScale; // 1 / (fOuterRadius - fInnerRadius) +uniform float fScaleDepth; // The scale depth (i.e. the altitude at which the atmosphere's average density is found) +uniform float fScaleOverScaleDepth; // fScale / fScaleDepth const int nSamples = 2; const float fSamples = 2.0; -varying vec3 position; +out vec3 position; void main(void) { - // Get the ray from the camera to the vertex, and its length (which is the far point of the ray passing through the atmosphere) - position = gl_Vertex.xyz * fOuterRadius; + // Get the ray from the camera to the vertex, and its length (which is the far point of the ray passing through the atmosphere) + position = inPosition.xyz * fOuterRadius; // standard transform TransformCamera cam = getTransformCamera(); diff --git a/libraries/render-utils/src/SkyFromSpace.slf b/libraries/render-utils/src/SkyFromSpace.slf index 2373511932..e3569a2914 100755 --- a/libraries/render-utils/src/SkyFromSpace.slf +++ b/libraries/render-utils/src/SkyFromSpace.slf @@ -1,4 +1,5 @@ -#version 120 +<@include gpu/Config.slh@> +<$VERSION_HEADER$> // // For licensing information, see http://http.developer.nvidia.com/GPUGems/gpugems_app01.html: @@ -32,20 +33,20 @@ // Copyright (c) 2004 Sean O'Neil // -uniform vec3 v3CameraPos; // The camera's current position -uniform vec3 v3LightPos; // The direction vector to the light source -uniform vec3 v3InvWavelength; // 1 / pow(wavelength, 4) for the red, green, and blue channels -uniform float fCameraHeight2; // fCameraHeight^2 -uniform float fOuterRadius; // The outer (atmosphere) radius -uniform float fOuterRadius2; // fOuterRadius^2 -uniform float fInnerRadius; // The inner (planetary) radius -uniform float fKrESun; // Kr * ESun -uniform float fKmESun; // Km * ESun -uniform float fKr4PI; // Kr * 4 * PI -uniform float fKm4PI; // Km * 4 * PI -uniform float fScale; // 1 / (fOuterRadius - fInnerRadius) -uniform float fScaleDepth; // The scale depth (i.e. the altitude at which the atmosphere's average density is found) -uniform float fScaleOverScaleDepth; // fScale / fScaleDepth +uniform vec3 v3CameraPos; // The camera's current position +uniform vec3 v3LightPos; // The direction vector to the light source +uniform vec3 v3InvWavelength; // 1 / pow(wavelength, 4) for the red, green, and blue channels +uniform float fCameraHeight2; // fCameraHeight^2 +uniform float fOuterRadius; // The outer (atmosphere) radius +uniform float fOuterRadius2; // fOuterRadius^2 +uniform float fInnerRadius; // The inner (planetary) radius +uniform float fKrESun; // Kr * ESun +uniform float fKmESun; // Km * ESun +uniform float fKr4PI; // Kr * 4 * PI +uniform float fKm4PI; // Km * 4 * PI +uniform float fScale; // 1 / (fOuterRadius - fInnerRadius) +uniform float fScaleDepth; // The scale depth (i.e. the altitude at which the atmosphere's average density is found) +uniform float fScaleOverScaleDepth; // fScale / fScaleDepth uniform float g; uniform float g2; @@ -53,63 +54,65 @@ uniform float g2; const int nSamples = 2; const float fSamples = 2.0; -varying vec3 position; +in vec3 position; + +out vec4 outFragColor; float scale(float fCos) { - float x = 1.0 - fCos; - return fScaleDepth * exp(-0.00287 + x*(0.459 + x*(3.83 + x*(-6.80 + x*5.25)))); + float x = 1.0 - fCos; + return fScaleDepth * exp(-0.00287 + x*(0.459 + x*(3.83 + x*(-6.80 + x*5.25)))); } void main (void) { // Get the ray from the camera to the vertex and its length (which is the far point of the ray passing through the atmosphere) - vec3 v3Pos = position; - vec3 v3Ray = v3Pos - v3CameraPos; - float fFar = length(v3Ray); - v3Ray /= fFar; + vec3 v3Pos = position; + vec3 v3Ray = v3Pos - v3CameraPos; + float fFar = length(v3Ray); + v3Ray /= fFar; - // Calculate the closest intersection of the ray with the outer atmosphere (which is the near point of the ray passing through the atmosphere) - float B = 2.0 * dot(v3CameraPos, v3Ray); - float C = fCameraHeight2 - fOuterRadius2; - float fDet = max(0.0, B*B - 4.0 * C); - float fNear = 0.5 * (-B - sqrt(fDet)); + // Calculate the closest intersection of the ray with the outer atmosphere (which is the near point of the ray passing through the atmosphere) + float B = 2.0 * dot(v3CameraPos, v3Ray); + float C = fCameraHeight2 - fOuterRadius2; + float fDet = max(0.0, B*B - 4.0 * C); + float fNear = 0.5 * (-B - sqrt(fDet)); - // Calculate the ray's starting position, then calculate its scattering offset - vec3 v3Start = v3CameraPos + v3Ray * fNear; - fFar -= fNear; - float fStartAngle = dot(v3Ray, v3Start) / fOuterRadius; - float fStartDepth = exp(-1.0 / fScaleDepth); - float fStartOffset = fStartDepth * scale(fStartAngle); + // Calculate the ray's starting position, then calculate its scattering offset + vec3 v3Start = v3CameraPos + v3Ray * fNear; + fFar -= fNear; + float fStartAngle = dot(v3Ray, v3Start) / fOuterRadius; + float fStartDepth = exp(-1.0 / fScaleDepth); + float fStartOffset = fStartDepth * scale(fStartAngle); - // Initialize the scattering loop variables - //gl_FrontColor = vec4(0.0, 0.0, 0.0, 0.0); - float fSampleLength = fFar / fSamples; - float fScaledLength = fSampleLength * fScale; - vec3 v3SampleRay = v3Ray * fSampleLength; - vec3 v3SamplePoint = v3Start + v3SampleRay * 0.5; + // Initialize the scattering loop variables + //gl_FrontColor = vec4(0.0, 0.0, 0.0, 0.0); + float fSampleLength = fFar / fSamples; + float fScaledLength = fSampleLength * fScale; + vec3 v3SampleRay = v3Ray * fSampleLength; + vec3 v3SamplePoint = v3Start + v3SampleRay * 0.5; - // Now loop through the sample rays - vec3 v3FrontColor = vec3(0.0, 0.0, 0.0); - for(int i=0; i <@include gpu/Transform.slh@> <$declareStandardTransform()$> -uniform float fOuterRadius; // The outer (atmosphere) radius +uniform float fOuterRadius; // The outer (atmosphere) radius -varying vec3 position; +out vec3 position; void main(void) { - position = gl_Vertex.xyz * fOuterRadius; + position = inPosition.xyz * fOuterRadius; // standard transform TransformCamera cam = getTransformCamera(); diff --git a/libraries/render-utils/src/TextureCache.cpp b/libraries/render-utils/src/TextureCache.cpp index d6a9bf5b36..deeec58f49 100644 --- a/libraries/render-utils/src/TextureCache.cpp +++ b/libraries/render-utils/src/TextureCache.cpp @@ -21,6 +21,7 @@ #include #include #include +#include "PathUtils.h" #include @@ -129,6 +130,14 @@ const gpu::TexturePointer& TextureCache::getBlackTexture() { return _blackTexture; } + +const gpu::TexturePointer& TextureCache::getNormalFittingTexture() { + if (!_normalFittingTexture) { + _normalFittingTexture = getImageTexture(PathUtils::resourcesPath() + "images/normalFittingScale.dds"); + } + return _normalFittingTexture; +} + /// Extra data for creating textures. class TextureExtra { public: @@ -170,6 +179,7 @@ gpu::TexturePointer TextureCache::getImageTexture(const QString& path) { return texture; } + QSharedPointer TextureCache::createResource(const QUrl& url, const QSharedPointer& fallback, bool delayLoad, const void* extra) { const TextureExtra* textureExtra = static_cast(extra); diff --git a/libraries/render-utils/src/TextureCache.h b/libraries/render-utils/src/TextureCache.h index 8f60382e9b..eeb17f07b9 100644 --- a/libraries/render-utils/src/TextureCache.h +++ b/libraries/render-utils/src/TextureCache.h @@ -54,6 +54,9 @@ public: /// Returns the a black texture (useful for a default). const gpu::TexturePointer& getBlackTexture(); + // Returns a map used to compress the normals through a fitting scale algorithm + const gpu::TexturePointer& getNormalFittingTexture(); + /// Returns a texture version of an image file static gpu::TexturePointer getImageTexture(const QString& path); @@ -76,6 +79,7 @@ private: gpu::TexturePointer _grayTexture; gpu::TexturePointer _blueTexture; gpu::TexturePointer _blackTexture; + gpu::TexturePointer _normalFittingTexture; QHash > _dilatableNetworkTextures; }; diff --git a/libraries/render-utils/src/ambient_occlusion.slf b/libraries/render-utils/src/ambient_occlusion.slf index f45fd9b6a0..649fb16c56 100644 --- a/libraries/render-utils/src/ambient_occlusion.slf +++ b/libraries/render-utils/src/ambient_occlusion.slf @@ -21,7 +21,7 @@ // Based on NVidia HBAO implementation in D3D11 // http://www.nvidia.co.uk/object/siggraph-2008-HBAO.html -varying vec2 varTexcoord; +in vec2 varTexcoord; uniform sampler2D depthTexture; uniform sampler2D normalTexture; @@ -47,12 +47,15 @@ const float AOStrength = 1.9; const float R = 0.3; const float R2 = 0.3*0.3; const float NegInvR2 = - 1.0 / (0.3*0.3); -const float TanBias = tan(30.0 * PI / 180.0); +// can't use tan to initialize a const value +const float TanBias = 0.57735027; // tan(30.0 * PI / 180.0); const float MaxRadiusPixels = 50.0; const int NumDirections = 6; const int NumSamples = 4; +out vec4 outFragColor; + float ViewSpaceZFromDepth(float d){ // [0,1] -> [-1,1] clip space d = d * 2.0 - 1.0; @@ -67,14 +70,14 @@ vec3 UVToViewSpace(vec2 uv, float z){ } vec3 GetViewPos(vec2 uv){ - float z = ViewSpaceZFromDepth(texture2D(depthTexture, uv).r); + float z = ViewSpaceZFromDepth(texture(depthTexture, uv).r); return UVToViewSpace(uv, z); } vec3 GetViewPosPoint(ivec2 uv){ vec2 coord = vec2(gl_FragCoord.xy) + uv; //float z = texelFetch(texture0, coord, 0).r; - float z = texture2D(depthTexture, uv).r; + float z = texture(depthTexture, uv).r; return UVToViewSpace(uv, z); } @@ -241,5 +244,5 @@ void main(void){ ao = 1.0 - ao / numDirections * AOStrength; } - gl_FragColor = vec4(vec3(ao), 1.0); + outFragColor = vec4(vec3(ao), 1.0); } \ No newline at end of file diff --git a/libraries/render-utils/src/ambient_occlusion.slv b/libraries/render-utils/src/ambient_occlusion.slv index 81f196dd46..46da3f5fd5 100644 --- a/libraries/render-utils/src/ambient_occlusion.slv +++ b/libraries/render-utils/src/ambient_occlusion.slv @@ -12,13 +12,15 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +<@include gpu/Inputs.slh@> + <@include gpu/Transform.slh@> <$declareStandardTransform()$> -varying vec2 varTexcoord; +out vec2 varTexcoord; void main(void) { - varTexcoord = gl_MultiTexCoord0.xy; - gl_Position = gl_Vertex; + varTexcoord = inTexCoord0.xy; + gl_Position = inPosition; } diff --git a/libraries/render-utils/src/deferred_light.slv b/libraries/render-utils/src/deferred_light.slv index 1427dd0f52..d0e3a754d3 100644 --- a/libraries/render-utils/src/deferred_light.slv +++ b/libraries/render-utils/src/deferred_light.slv @@ -12,7 +12,11 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +<@include gpu/Inputs.slh@> + +out vec2 _texCoord0; + void main(void) { - gl_TexCoord[0] = gl_MultiTexCoord0; - gl_Position = gl_Vertex; + _texCoord0 = inTexCoord0.st; + gl_Position = inPosition; } diff --git a/libraries/render-utils/src/deferred_light_limited.slv b/libraries/render-utils/src/deferred_light_limited.slv index d57b987b68..e9f3e1bdb3 100644 --- a/libraries/render-utils/src/deferred_light_limited.slv +++ b/libraries/render-utils/src/deferred_light_limited.slv @@ -14,17 +14,21 @@ <@include gpu/Transform.slh@> +<@include gpu/Inputs.slh@> + <$declareStandardTransform()$> uniform mat4 texcoordMat; +out vec4 _texCoord0; + void main(void) { // standard transform TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); - <$transformModelToClipPos(cam, obj, gl_Vertex, gl_Position)$>; + <$transformModelToClipPos(cam, obj, inPosition, gl_Position)$>; vec4 projected = gl_Position / gl_Position.w; - gl_TexCoord[0] = vec4(dot(projected, texcoordMat[0]) * gl_Position.w, + _texCoord0 = vec4(dot(projected, texcoordMat[0]) * gl_Position.w, dot(projected, texcoordMat[1]) * gl_Position.w, 0.0, gl_Position.w); } diff --git a/libraries/render-utils/src/deferred_light_spot.slv b/libraries/render-utils/src/deferred_light_spot.slv index d3ef18fd53..8365899fde 100755 --- a/libraries/render-utils/src/deferred_light_spot.slv +++ b/libraries/render-utils/src/deferred_light_spot.slv @@ -12,6 +12,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +<@include gpu/Inputs.slh@> + <@include gpu/Transform.slh@> <$declareStandardTransform()$> @@ -19,8 +21,10 @@ uniform mat4 texcoordMat; uniform vec4 coneParam; +out vec4 _texCoord0; + void main(void) { - vec4 coneVertex = gl_Vertex; + vec4 coneVertex = inPosition; if (coneParam.w != 0.0) { if(coneVertex.z >= 0.0) { // Evaluate the true position of the spot volume @@ -42,6 +46,6 @@ void main(void) { <$transformModelToClipPos(cam, obj, coneVertex, gl_Position)$>; vec4 projected = gl_Position / gl_Position.w; - gl_TexCoord[0] = vec4(dot(projected, texcoordMat[0]) * gl_Position.w, + _texCoord0 = vec4(dot(projected, texcoordMat[0]) * gl_Position.w, dot(projected, texcoordMat[1]) * gl_Position.w, 0.0, gl_Position.w); } diff --git a/libraries/render-utils/src/directional_ambient_light.slf b/libraries/render-utils/src/directional_ambient_light.slf index 114c5615b8..10de6a1101 100755 --- a/libraries/render-utils/src/directional_ambient_light.slf +++ b/libraries/render-utils/src/directional_ambient_light.slf @@ -17,8 +17,11 @@ <@include DeferredGlobalLight.slh@> +in vec2 _texCoord0; +out vec4 _fragColor; + void main(void) { - DeferredFragment frag = unpackDeferredFragment(gl_TexCoord[0].st); + DeferredFragment frag = unpackDeferredFragment(_texCoord0); // Light mapped or not ? @@ -29,7 +32,7 @@ void main(void) { frag.diffuse, frag.specularVal.xyz); - gl_FragColor = vec4(color, 1.0); + _fragColor = vec4(color, 1.0); } else { vec3 color = evalAmbienSphereGlobalColor(1.0, frag.position.xyz, @@ -38,6 +41,6 @@ void main(void) { frag.specular, frag.gloss); - gl_FragColor = vec4(color, frag.normalVal.a); + _fragColor = vec4(color, frag.normalVal.a); } } diff --git a/libraries/render-utils/src/directional_ambient_light_cascaded_shadow_map.slf b/libraries/render-utils/src/directional_ambient_light_cascaded_shadow_map.slf index d52363a26b..ff8e6aa91c 100755 --- a/libraries/render-utils/src/directional_ambient_light_cascaded_shadow_map.slf +++ b/libraries/render-utils/src/directional_ambient_light_cascaded_shadow_map.slf @@ -20,8 +20,11 @@ // Everything about shadow <@include Shadow.slh@> +in vec2 _texCoord0; +out vec4 _fragColor; + void main(void) { - DeferredFragment frag = unpackDeferredFragment(gl_TexCoord[0].st); + DeferredFragment frag = unpackDeferredFragment(_texCoord0); // Eval shadow Texcoord and then Attenuation vec4 shadowTexcoord = evalCascadedShadowTexcoord(frag.position); @@ -29,7 +32,7 @@ void main(void) { // Light mapped or not ? if ((frag.normalVal.a >= 0.45) && (frag.normalVal.a <= 0.55)) { - gl_FragColor = vec4(evalLightmappedColor( + _fragColor = vec4(evalLightmappedColor( shadowAttenuation, frag.normal, frag.diffuse, @@ -43,6 +46,6 @@ void main(void) { frag.specular, frag.gloss); - gl_FragColor = vec4(color, frag.normalVal.a); + _fragColor = vec4(color, frag.normalVal.a); } } diff --git a/libraries/render-utils/src/directional_ambient_light_shadow_map.slf b/libraries/render-utils/src/directional_ambient_light_shadow_map.slf index 7f098eac2e..d446d4edb2 100755 --- a/libraries/render-utils/src/directional_ambient_light_shadow_map.slf +++ b/libraries/render-utils/src/directional_ambient_light_shadow_map.slf @@ -20,9 +20,11 @@ // Everything about shadow <@include Shadow.slh@> +in vec2 _texCoord0; +out vec4 _fragColor; void main(void) { - DeferredFragment frag = unpackDeferredFragment(gl_TexCoord[0].st); + DeferredFragment frag = unpackDeferredFragment(_texCoord0); // Eval shadow Texcoord and then Attenuation vec4 shadowTexcoord = evalShadowTexcoord(frag.position); @@ -30,7 +32,7 @@ void main(void) { // Light mapped or not ? if ((frag.normalVal.a >= 0.45) && (frag.normalVal.a <= 0.55)) { - gl_FragColor = vec4(evalLightmappedColor( + _fragColor = vec4(evalLightmappedColor( shadowAttenuation, frag.normal, frag.diffuse, @@ -44,6 +46,6 @@ void main(void) { frag.specular, frag.gloss); - gl_FragColor = vec4(color, frag.normalVal.a); + _fragColor = vec4(color, frag.normalVal.a); } } diff --git a/libraries/render-utils/src/directional_light.slf b/libraries/render-utils/src/directional_light.slf index 0299b2a229..2e0334406e 100644 --- a/libraries/render-utils/src/directional_light.slf +++ b/libraries/render-utils/src/directional_light.slf @@ -17,12 +17,15 @@ <@include DeferredGlobalLight.slh@> +in vec2 _texCoord0; +out vec4 _fragColor; + void main(void) { - DeferredFragment frag = unpackDeferredFragment(gl_TexCoord[0].st); + DeferredFragment frag = unpackDeferredFragment(_texCoord0); // Light mapped or not ? if ((frag.normalVal.a >= 0.45) && (frag.normalVal.a <= 0.55)) { - gl_FragColor = vec4( evalLightmappedColor( + _fragColor = vec4( evalLightmappedColor( 1.0, frag.normal, frag.diffuse, @@ -36,6 +39,6 @@ void main(void) { frag.specular, frag.gloss); - gl_FragColor = vec4(color, frag.normalVal.a); + _fragColor = vec4(color, frag.normalVal.a); } } diff --git a/libraries/render-utils/src/directional_light_cascaded_shadow_map.slf b/libraries/render-utils/src/directional_light_cascaded_shadow_map.slf index 71464fb916..bfc42db9bc 100644 --- a/libraries/render-utils/src/directional_light_cascaded_shadow_map.slf +++ b/libraries/render-utils/src/directional_light_cascaded_shadow_map.slf @@ -20,8 +20,11 @@ // Everything about shadow <@include Shadow.slh@> +in vec2 _texCoord0; +out vec4 _fragColor; + void main(void) { - DeferredFragment frag = unpackDeferredFragment(gl_TexCoord[0].st); + DeferredFragment frag = unpackDeferredFragment(_texCoord0); // Eval shadow Texcoord and then Attenuation vec4 shadowTexcoord = evalCascadedShadowTexcoord(frag.position); @@ -29,7 +32,7 @@ void main(void) { // Light mapped or not ? if ((frag.normalVal.a >= 0.45) && (frag.normalVal.a <= 0.55)) { - gl_FragColor = vec4(evalLightmappedColor( + _fragColor = vec4(evalLightmappedColor( shadowAttenuation, frag.normal, frag.diffuse, @@ -43,6 +46,6 @@ void main(void) { frag.specular, frag.gloss); - gl_FragColor = vec4(color, frag.normalVal.a); + _fragColor = vec4(color, frag.normalVal.a); } } diff --git a/libraries/render-utils/src/directional_light_shadow_map.slf b/libraries/render-utils/src/directional_light_shadow_map.slf index 2c53a02348..951aeab122 100644 --- a/libraries/render-utils/src/directional_light_shadow_map.slf +++ b/libraries/render-utils/src/directional_light_shadow_map.slf @@ -20,9 +20,11 @@ // Everything about shadow <@include Shadow.slh@> +in vec2 _texCoord0; +out vec4 _fragColor; void main(void) { - DeferredFragment frag = unpackDeferredFragment(gl_TexCoord[0].st); + DeferredFragment frag = unpackDeferredFragment(_texCoord0); // Eval shadow Texcoord and then Attenuation vec4 shadowTexcoord = evalShadowTexcoord(frag.position); @@ -30,7 +32,7 @@ void main(void) { // Light mapped or not ? if ((frag.normalVal.a >= 0.45) && (frag.normalVal.a <= 0.55)) { - gl_FragColor = vec4(evalLightmappedColor( + _fragColor = vec4(evalLightmappedColor( shadowAttenuation, frag.normal, frag.diffuse, @@ -44,6 +46,6 @@ void main(void) { frag.specular, frag.gloss); - gl_FragColor = vec4(color, frag.normalVal.a); + _fragColor = vec4(color, frag.normalVal.a); } } diff --git a/libraries/render-utils/src/directional_skybox_light.slf b/libraries/render-utils/src/directional_skybox_light.slf index 38e3f9eb72..cd95369395 100755 --- a/libraries/render-utils/src/directional_skybox_light.slf +++ b/libraries/render-utils/src/directional_skybox_light.slf @@ -17,8 +17,11 @@ <@include DeferredGlobalLight.slh@> +in vec2 _texCoord0; +out vec4 _fragColor; + void main(void) { - DeferredFragment frag = unpackDeferredFragment(gl_TexCoord[0].st); + DeferredFragment frag = unpackDeferredFragment(_texCoord0); // Light mapped or not ? @@ -29,7 +32,7 @@ void main(void) { frag.diffuse, frag.specularVal.xyz); - gl_FragColor = vec4(color, 1.0); + _fragColor = vec4(color, 1.0); } else { vec3 color = evalSkyboxGlobalColor(1.0, frag.position.xyz, @@ -38,6 +41,6 @@ void main(void) { frag.specular, frag.gloss); - gl_FragColor = vec4(color, frag.normalVal.a); + _fragColor = vec4(color, frag.normalVal.a); } } diff --git a/libraries/render-utils/src/directional_skybox_light_cascaded_shadow_map.slf b/libraries/render-utils/src/directional_skybox_light_cascaded_shadow_map.slf index d7d843855f..171d3fa996 100755 --- a/libraries/render-utils/src/directional_skybox_light_cascaded_shadow_map.slf +++ b/libraries/render-utils/src/directional_skybox_light_cascaded_shadow_map.slf @@ -20,8 +20,11 @@ // Everything about shadow <@include Shadow.slh@> +in vec2 _texCoord0; +out vec4 _fragColor; + void main(void) { - DeferredFragment frag = unpackDeferredFragment(gl_TexCoord[0].st); + DeferredFragment frag = unpackDeferredFragment(_texCoord0); // Eval shadow Texcoord and then Attenuation vec4 shadowTexcoord = evalCascadedShadowTexcoord(frag.position); @@ -29,7 +32,7 @@ void main(void) { // Light mapped or not ? if ((frag.normalVal.a >= 0.45) && (frag.normalVal.a <= 0.55)) { - gl_FragColor = vec4(evalLightmappedColor( + _fragColor = vec4(evalLightmappedColor( shadowAttenuation, frag.normal, frag.diffuse, @@ -43,6 +46,6 @@ void main(void) { frag.specular, frag.gloss); - gl_FragColor = vec4(color, frag.normalVal.a); + _fragColor = vec4(color, frag.normalVal.a); } } diff --git a/libraries/render-utils/src/directional_skybox_light_shadow_map.slf b/libraries/render-utils/src/directional_skybox_light_shadow_map.slf index 8c19cb959f..aa4206bce9 100755 --- a/libraries/render-utils/src/directional_skybox_light_shadow_map.slf +++ b/libraries/render-utils/src/directional_skybox_light_shadow_map.slf @@ -20,9 +20,11 @@ // Everything about shadow <@include Shadow.slh@> +in vec2 _texCoord0; +out vec4 _fragColor; void main(void) { - DeferredFragment frag = unpackDeferredFragment(gl_TexCoord[0].st); + DeferredFragment frag = unpackDeferredFragment(_texCoord0); // Eval shadow Texcoord and then Attenuation vec4 shadowTexcoord = evalShadowTexcoord(frag.position); @@ -30,7 +32,7 @@ void main(void) { // Light mapped or not ? if ((frag.normalVal.a >= 0.45) && (frag.normalVal.a <= 0.55)) { - gl_FragColor = vec4(evalLightmappedColor( + _fragColor = vec4(evalLightmappedColor( shadowAttenuation, frag.normal, frag.diffuse, @@ -44,6 +46,6 @@ void main(void) { frag.specular, frag.gloss); - gl_FragColor = vec4(color, frag.normalVal.a); + _fragColor = vec4(color, frag.normalVal.a); } } diff --git a/libraries/render-utils/src/gaussian_blur.slf b/libraries/render-utils/src/gaussian_blur.slf index 63ba14a07c..01c1bc8807 100644 --- a/libraries/render-utils/src/gaussian_blur.slf +++ b/libraries/render-utils/src/gaussian_blur.slf @@ -15,28 +15,29 @@ <@include DeferredBufferWrite.slh@> // the interpolated normal -//varying vec4 interpolatedNormal; +//in vec4 interpolatedNormal; -varying vec2 varTexcoord; -varying vec2 varBlurTexcoords[14]; +in vec2 varTexcoord; +in vec2 varBlurTexcoords[14]; uniform sampler2D occlusionTexture; +out vec4 outFragColor; void main(void) { - gl_FragColor = vec4(0.0); - gl_FragColor += texture2D(occlusionTexture, varBlurTexcoords[0])*0.0044299121055113265; - gl_FragColor += texture2D(occlusionTexture, varBlurTexcoords[1])*0.00895781211794; - gl_FragColor += texture2D(occlusionTexture, varBlurTexcoords[2])*0.0215963866053; - gl_FragColor += texture2D(occlusionTexture, varBlurTexcoords[3])*0.0443683338718; - gl_FragColor += texture2D(occlusionTexture, varBlurTexcoords[4])*0.0776744219933; - gl_FragColor += texture2D(occlusionTexture, varBlurTexcoords[5])*0.115876621105; - gl_FragColor += texture2D(occlusionTexture, varBlurTexcoords[6])*0.147308056121; - gl_FragColor += texture2D(occlusionTexture, varTexcoord)*0.159576912161; - gl_FragColor += texture2D(occlusionTexture, varBlurTexcoords[7])*0.147308056121; - gl_FragColor += texture2D(occlusionTexture, varBlurTexcoords[8])*0.115876621105; - gl_FragColor += texture2D(occlusionTexture, varBlurTexcoords[9])*0.0776744219933; - gl_FragColor += texture2D(occlusionTexture, varBlurTexcoords[10])*0.0443683338718; - gl_FragColor += texture2D(occlusionTexture, varBlurTexcoords[11])*0.0215963866053; - gl_FragColor += texture2D(occlusionTexture, varBlurTexcoords[12])*0.00895781211794; - gl_FragColor += texture2D(occlusionTexture, varBlurTexcoords[13])*0.0044299121055113265; + outFragColor = vec4(0.0); + outFragColor += texture(occlusionTexture, varBlurTexcoords[0])*0.0044299121055113265; + outFragColor += texture(occlusionTexture, varBlurTexcoords[1])*0.00895781211794; + outFragColor += texture(occlusionTexture, varBlurTexcoords[2])*0.0215963866053; + outFragColor += texture(occlusionTexture, varBlurTexcoords[3])*0.0443683338718; + outFragColor += texture(occlusionTexture, varBlurTexcoords[4])*0.0776744219933; + outFragColor += texture(occlusionTexture, varBlurTexcoords[5])*0.115876621105; + outFragColor += texture(occlusionTexture, varBlurTexcoords[6])*0.147308056121; + outFragColor += texture(occlusionTexture, varTexcoord)*0.159576912161; + outFragColor += texture(occlusionTexture, varBlurTexcoords[7])*0.147308056121; + outFragColor += texture(occlusionTexture, varBlurTexcoords[8])*0.115876621105; + outFragColor += texture(occlusionTexture, varBlurTexcoords[9])*0.0776744219933; + outFragColor += texture(occlusionTexture, varBlurTexcoords[10])*0.0443683338718; + outFragColor += texture(occlusionTexture, varBlurTexcoords[11])*0.0215963866053; + outFragColor += texture(occlusionTexture, varBlurTexcoords[12])*0.00895781211794; + outFragColor += texture(occlusionTexture, varBlurTexcoords[13])*0.0044299121055113265; } diff --git a/libraries/render-utils/src/gaussian_blur_horizontal.slv b/libraries/render-utils/src/gaussian_blur_horizontal.slv index c3f326daac..7f8fb1c87f 100644 --- a/libraries/render-utils/src/gaussian_blur_horizontal.slv +++ b/libraries/render-utils/src/gaussian_blur_horizontal.slv @@ -12,16 +12,18 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +<@include gpu/Inputs.slh@> + <@include gpu/Transform.slh@> <$declareStandardTransform()$> -varying vec2 varTexcoord; -varying vec2 varBlurTexcoords[14]; +out vec2 varTexcoord; +out vec2 varBlurTexcoords[14]; void main(void) { - varTexcoord = gl_MultiTexCoord0.xy; - gl_Position = gl_Vertex; + varTexcoord = inTexCoord0.xy; + gl_Position = inPosition; varBlurTexcoords[0] = varTexcoord + vec2(-0.028, 0.0); varBlurTexcoords[1] = varTexcoord + vec2(-0.024, 0.0); diff --git a/libraries/render-utils/src/gaussian_blur_vertical.slv b/libraries/render-utils/src/gaussian_blur_vertical.slv index fc35a96bf0..4a4d65dcf9 100644 --- a/libraries/render-utils/src/gaussian_blur_vertical.slv +++ b/libraries/render-utils/src/gaussian_blur_vertical.slv @@ -12,16 +12,18 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +<@include gpu/Inputs.slh@> + <@include gpu/Transform.slh@> <$declareStandardTransform()$> -varying vec2 varTexcoord; -varying vec2 varBlurTexcoords[14]; +out vec2 varTexcoord; +out vec2 varBlurTexcoords[14]; void main(void) { - varTexcoord = gl_MultiTexCoord0.xy; - gl_Position = gl_Vertex; + varTexcoord = inTexCoord0.xy; + gl_Position = inPosition; varBlurTexcoords[0] = varTexcoord + vec2(0.0, -0.028); varBlurTexcoords[1] = varTexcoord + vec2(0.0, -0.024); diff --git a/libraries/render-utils/src/hit_effect.slf b/libraries/render-utils/src/hit_effect.slf index 6c0dcd7a70..ed11aea0b9 100644 --- a/libraries/render-utils/src/hit_effect.slf +++ b/libraries/render-utils/src/hit_effect.slf @@ -14,11 +14,12 @@ <@include DeferredBufferWrite.slh@> -varying vec2 varQuadPosition; +in vec2 varQuadPosition; +out vec4 outFragColor; void main(void) { vec2 center = vec2(0.0, 0.0); float distFromCenter = distance( vec2(0.0, 0.0), varQuadPosition); float alpha = mix(0.0, 0.5, pow(distFromCenter,5.)); - gl_FragColor = vec4(1.0, 0.0, 0.0, alpha); + outFragColor = vec4(1.0, 0.0, 0.0, alpha); } \ No newline at end of file diff --git a/libraries/render-utils/src/hit_effect.slv b/libraries/render-utils/src/hit_effect.slv index d1efdebc18..b9b0638f9e 100644 --- a/libraries/render-utils/src/hit_effect.slv +++ b/libraries/render-utils/src/hit_effect.slv @@ -12,13 +12,15 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +<@include gpu/Inputs.slh@> + <@include gpu/Transform.slh@> <$declareStandardTransform()$> -varying vec2 varQuadPosition; +out vec2 varQuadPosition; void main(void) { - varQuadPosition = gl_Vertex.xy; - gl_Position = gl_Vertex; + varQuadPosition = inPosition.xy; + gl_Position = inPosition; } \ No newline at end of file diff --git a/libraries/render-utils/src/model.slf b/libraries/render-utils/src/model.slf index 7648cac429..f455030f6f 100755 --- a/libraries/render-utils/src/model.slf +++ b/libraries/render-utils/src/model.slf @@ -18,22 +18,22 @@ // the diffuse texture uniform sampler2D diffuseMap; -// the interpolated normal -varying vec4 interpolatedNormal; - -varying vec3 color; +in vec4 _position; +in vec3 _normal; +in vec3 _color; +in vec2 _texCoord0; void main(void) { // Fetch diffuse map - vec4 diffuse = texture2D(diffuseMap, gl_TexCoord[0].st); + vec4 diffuse = texture(diffuseMap, _texCoord0); Material mat = getMaterial(); packDeferredFragment( - normalize(interpolatedNormal.xyz), + normalize(_normal.xyz), evalOpaqueFinalAlpha(getMaterialOpacity(mat), diffuse.a), - getMaterialDiffuse(mat) * diffuse.rgb * color, + getMaterialDiffuse(mat) * diffuse.rgb * _color, getMaterialSpecular(mat), getMaterialShininess(mat)); } diff --git a/libraries/render-utils/src/model.slv b/libraries/render-utils/src/model.slv index 2d22c0df51..4319e9f9e0 100755 --- a/libraries/render-utils/src/model.slv +++ b/libraries/render-utils/src/model.slv @@ -11,6 +11,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +<@include gpu/Inputs.slh@> + <@include gpu/Transform.slh@> <$declareStandardTransform()$> @@ -19,27 +21,22 @@ const int MAX_TEXCOORDS = 2; uniform mat4 texcoordMatrices[MAX_TEXCOORDS]; -// interpolated eye position -varying vec4 interpolatedPosition; - -// the interpolated normal -varying vec4 interpolatedNormal; - -varying vec3 color; +out vec4 _position; +out vec3 _normal; +out vec3 _color; +out vec2 _texCoord0; void main(void) { // pass along the diffuse color - color = gl_Color.xyz; + _color = inColor.xyz; // and the texture coordinates - gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.0, 1.0); + _texCoord0 = (texcoordMatrices[0] * vec4(inTexCoord0.st, 0.0, 1.0)).st; // standard transform TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); - <$transformModelToEyeAndClipPos(cam, obj, gl_Vertex, interpolatedPosition, gl_Position)$> - <$transformModelToEyeDir(cam, obj, gl_Normal, interpolatedNormal.xyz)$> - - interpolatedNormal = vec4(normalize(interpolatedNormal.xyz), 0.0); + <$transformModelToEyeAndClipPos(cam, obj, inPosition, _position, gl_Position)$> + <$transformModelToEyeDir(cam, obj, inNormal.xyz, _normal)$> } diff --git a/libraries/render-utils/src/model_lightmap.slf b/libraries/render-utils/src/model_lightmap.slf index 00d74ed997..ab92d2bf4c 100755 --- a/libraries/render-utils/src/model_lightmap.slf +++ b/libraries/render-utils/src/model_lightmap.slf @@ -23,25 +23,22 @@ uniform sampler2D diffuseMap; uniform sampler2D emissiveMap; uniform vec2 emissiveParams; -// the interpolated normal -varying vec4 interpolatedNormal; - -varying vec3 color; - -// the interpolated texcoord1 -varying vec2 interpolatedTexcoord1; +in vec4 _position; +in vec2 _texCoord0; +in vec2 _texCoord1; +in vec3 _normal; +in vec3 _color; void main(void) { - // set the diffuse, normal, specular data - vec4 diffuse = texture2D(diffuseMap, gl_TexCoord[0].st); - vec4 emissive = texture2D(emissiveMap, interpolatedTexcoord1.st); + vec4 diffuse = texture(diffuseMap, _texCoord0); + vec4 emissive = texture(emissiveMap, _texCoord1); Material mat = getMaterial(); packDeferredFragmentLightmap( - normalize(interpolatedNormal.xyz), + normalize(_normal), evalOpaqueFinalAlpha(getMaterialOpacity(mat), diffuse.a), - getMaterialDiffuse(mat) * diffuse.rgb * color, + getMaterialDiffuse(mat) * diffuse.rgb * _color, getMaterialSpecular(mat), getMaterialShininess(mat), (vec3(emissiveParams.x) + emissiveParams.y * emissive.rgb)); diff --git a/libraries/render-utils/src/model_lightmap.slv b/libraries/render-utils/src/model_lightmap.slv index 54d9bd21e1..7742896228 100755 --- a/libraries/render-utils/src/model_lightmap.slv +++ b/libraries/render-utils/src/model_lightmap.slv @@ -12,6 +12,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +<@include gpu/Inputs.slh@> + <@include gpu/Transform.slh@> <$declareStandardTransform()$> @@ -20,32 +22,23 @@ const int MAX_TEXCOORDS = 2; uniform mat4 texcoordMatrices[MAX_TEXCOORDS]; -attribute vec2 texcoord1; - -// the interpolated normal -varying vec4 interpolatedNormal; - -// the interpolated texcoord1 -varying vec2 interpolatedTexcoord1; - -varying vec3 color; - +out vec4 _position; +out vec2 _texCoord0; +out vec2 _texCoord1; +out vec3 _normal; +out vec3 _color; void main(void) { - // pass along the diffuse color - color = gl_Color.xyz; - + _color = inColor.xyz; + // and the texture coordinates - gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.0, 1.0); - // interpolatedTexcoord1 = vec2(texcoordMatrices[1] * vec4(gl_MultiTexCoord0.xy, 0.0, 1.0)).xy; - interpolatedTexcoord1 = vec2(texcoordMatrices[1] * vec4(texcoord1.xy, 0.0, 1.0)).xy; + _texCoord0 = (texcoordMatrices[0] * vec4(inTexCoord0.st, 0.0, 1.0)).st; + _texCoord1 = (texcoordMatrices[1] * vec4(inTexCoord1.st, 0.0, 1.0)).st; // standard transform TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); - <$transformModelToClipPos(cam, obj, gl_Vertex, gl_Position)$> - <$transformModelToEyeDir(cam, obj, gl_Normal, interpolatedNormal.xyz)$> - - interpolatedNormal = vec4(normalize(interpolatedNormal.xyz), 0.0); + <$transformModelToEyeAndClipPos(cam, obj, inPosition, _position, gl_Position)$> + <$transformModelToEyeDir(cam, obj, inNormal.xyz, _normal)$> } diff --git a/libraries/render-utils/src/model_lightmap_normal_map.slf b/libraries/render-utils/src/model_lightmap_normal_map.slf index 7120fd61de..78c802be51 100755 --- a/libraries/render-utils/src/model_lightmap_normal_map.slf +++ b/libraries/render-utils/src/model_lightmap_normal_map.slf @@ -26,35 +26,32 @@ uniform sampler2D normalMap; uniform sampler2D emissiveMap; uniform vec2 emissiveParams; -// the interpolated normal -varying vec4 interpolatedNormal; - -// the interpolated tangent -varying vec4 interpolatedTangent; - -varying vec2 interpolatedTexcoord1; - -varying vec3 color; +in vec4 _position; +in vec2 _texCoord0; +in vec2 _texCoord1; +in vec3 _normal; +in vec3 _tangent; +in vec3 _color; void main(void) { // compute the view normal from the various bits - vec3 normalizedNormal = normalize(vec3(interpolatedNormal)); - vec3 normalizedTangent = normalize(vec3(interpolatedTangent)); + vec3 normalizedNormal = normalize(_normal); + vec3 normalizedTangent = normalize(_tangent); vec3 normalizedBitangent = normalize(cross(normalizedNormal, normalizedTangent)); - vec3 localNormal = vec3(texture2D(normalMap, gl_TexCoord[0].st)) - vec3(0.5, 0.5, 0.5); + vec3 localNormal = vec3(texture(normalMap, _texCoord0)) - vec3(0.5, 0.5, 0.5); vec4 viewNormal = vec4(normalizedTangent * localNormal.x + normalizedBitangent * localNormal.y + normalizedNormal * localNormal.z, 0.0); // set the diffuse, normal, specular data - vec4 diffuse = texture2D(diffuseMap, gl_TexCoord[0].st); - vec4 emissive = texture2D(emissiveMap, interpolatedTexcoord1.st); + vec4 diffuse = texture(diffuseMap, _texCoord0); + vec4 emissive = texture(emissiveMap, _texCoord1); Material mat = getMaterial(); packDeferredFragmentLightmap( normalize(viewNormal.xyz), evalOpaqueFinalAlpha(getMaterialOpacity(mat), diffuse.a), - getMaterialDiffuse(mat) * diffuse.rgb * color, + getMaterialDiffuse(mat) * diffuse.rgb * _color, getMaterialSpecular(mat), getMaterialShininess(mat), (vec3(emissiveParams.x) + emissiveParams.y * emissive.rgb)); diff --git a/libraries/render-utils/src/model_lightmap_normal_map.slv b/libraries/render-utils/src/model_lightmap_normal_map.slv index bfa8bc2cc2..f63030301f 100755 --- a/libraries/render-utils/src/model_lightmap_normal_map.slv +++ b/libraries/render-utils/src/model_lightmap_normal_map.slv @@ -12,6 +12,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +<@include gpu/Inputs.slh@> + <@include gpu/Transform.slh@> <$declareStandardTransform()$> @@ -20,41 +22,24 @@ const int MAX_TEXCOORDS = 2; uniform mat4 texcoordMatrices[MAX_TEXCOORDS]; -// the tangent vector -attribute vec3 tangent; - -attribute vec2 texcoord1; - -// the interpolated normal -varying vec4 interpolatedNormal; - -// the interpolated tangent -varying vec4 interpolatedTangent; - -// the interpolated texcoord1 -varying vec2 interpolatedTexcoord1; - -varying vec3 color; +out vec4 _position; +out vec2 _texCoord0; +out vec2 _texCoord1; +out vec3 _normal; +out vec3 _tangent; +out vec3 _color; void main(void) { - // transform and store the normal and tangent for interpolation - //interpolatedNormal = gl_ModelViewMatrix * vec4(gl_Normal, 0.0); - //interpolatedTangent = gl_ModelViewMatrix * vec4(tangent, 0.0); - - // pass along the diffuse color - color = gl_Color.xyz; - + _color = inColor.xyz; + // and the texture coordinates - gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.0, 1.0); - interpolatedTexcoord1 = vec2(texcoordMatrices[1] * vec4(texcoord1.xy, 0.0, 1.0)).xy; - + _texCoord0 = (texcoordMatrices[0] * vec4(inTexCoord0.st, 0.0, 1.0)).st; + _texCoord1 = (texcoordMatrices[1] * vec4(inTexCoord1.st, 0.0, 1.0)).st; + // standard transform TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); - <$transformModelToClipPos(cam, obj, gl_Vertex, gl_Position)$> - <$transformModelToEyeDir(cam, obj, gl_Normal, interpolatedNormal.xyz)$> - <$transformModelToEyeDir(cam, obj, tangent, interpolatedTangent.xyz)$> - - interpolatedNormal = vec4(normalize(interpolatedNormal.xyz), 0.0); - interpolatedTangent = vec4(normalize(interpolatedTangent.xyz), 0.0); + <$transformModelToEyeAndClipPos(cam, obj, inPosition, _position, gl_Position)$> + <$transformModelToEyeDir(cam, obj, inNormal.xyz, _normal)$> + <$transformModelToEyeDir(cam, obj, inTangent.xyz, _tangent)$> } diff --git a/libraries/render-utils/src/model_lightmap_normal_specular_map.slf b/libraries/render-utils/src/model_lightmap_normal_specular_map.slf index 2c57c14803..1b7416baa5 100755 --- a/libraries/render-utils/src/model_lightmap_normal_specular_map.slf +++ b/libraries/render-utils/src/model_lightmap_normal_specular_map.slf @@ -29,37 +29,33 @@ uniform sampler2D normalMap; // the specular map texture uniform sampler2D specularMap; -// the interpolated normal -varying vec4 interpolatedNormal; - -// the interpolated tangent -varying vec4 interpolatedTangent; - -varying vec2 interpolatedTexcoord1; - -varying vec3 color; - +in vec4 _position; +in vec2 _texCoord0; +in vec2 _texCoord1; +in vec3 _normal; +in vec3 _tangent; +in vec3 _color; void main(void) { // compute the view normal from the various bits - vec3 normalizedNormal = normalize(vec3(interpolatedNormal)); - vec3 normalizedTangent = normalize(vec3(interpolatedTangent)); + vec3 normalizedNormal = normalize(_normal); + vec3 normalizedTangent = normalize(_tangent); vec3 normalizedBitangent = normalize(cross(normalizedNormal, normalizedTangent)); - vec3 localNormal = vec3(texture2D(normalMap, gl_TexCoord[0].st)) - vec3(0.5, 0.5, 0.5); + vec3 localNormal = vec3(texture(normalMap, _texCoord0)) - vec3(0.5, 0.5, 0.5); vec4 viewNormal = vec4(normalizedTangent * localNormal.x + normalizedBitangent * localNormal.y + normalizedNormal * localNormal.z, 0.0); // set the diffuse, normal, specular data - vec4 diffuse = texture2D(diffuseMap, gl_TexCoord[0].st); - vec3 specular = texture2D(specularMap, gl_TexCoord[0].st).rgb; - vec4 emissive = texture2D(emissiveMap, interpolatedTexcoord1.st); + vec4 diffuse = texture(diffuseMap, _texCoord0); + vec3 specular = texture(specularMap, _texCoord0).rgb; + vec4 emissive = texture(emissiveMap, _texCoord1); Material mat = getMaterial(); packDeferredFragmentLightmap( normalize(viewNormal.xyz), evalOpaqueFinalAlpha(getMaterialOpacity(mat), diffuse.a), - getMaterialDiffuse(mat) * diffuse.rgb * color, + getMaterialDiffuse(mat) * diffuse.rgb * _color, specular, // no use of getMaterialSpecular(mat) getMaterialShininess(mat), (vec3(emissiveParams.x) + emissiveParams.y * emissive.rgb)); diff --git a/libraries/render-utils/src/model_lightmap_specular_map.slf b/libraries/render-utils/src/model_lightmap_specular_map.slf index daabfe2d07..efdfcd6be9 100755 --- a/libraries/render-utils/src/model_lightmap_specular_map.slf +++ b/libraries/render-utils/src/model_lightmap_specular_map.slf @@ -26,25 +26,24 @@ uniform vec2 emissiveParams; // the specular texture uniform sampler2D specularMap; -// the interpolated normal -varying vec4 interpolatedNormal; - -varying vec2 interpolatedTexcoord1; - -varying vec3 color; +in vec4 _position; +in vec2 _texCoord0; +in vec2 _texCoord1; +in vec3 _normal; +in vec3 _color; void main(void) { // set the diffuse, normal, specular data - vec4 diffuse = texture2D(diffuseMap, gl_TexCoord[0].st); - vec3 specular = texture2D(specularMap, gl_TexCoord[0].st).rgb; - vec4 emissive = texture2D(emissiveMap, interpolatedTexcoord1.st); + vec4 diffuse = texture(diffuseMap, _texCoord0); + vec3 specular = texture(specularMap, _texCoord0).rgb; + vec4 emissive = texture(emissiveMap, _texCoord1); Material mat = getMaterial(); packDeferredFragmentLightmap( - normalize(interpolatedNormal.xyz), + normalize(_normal), evalOpaqueFinalAlpha(getMaterialOpacity(mat), diffuse.a), - getMaterialDiffuse(mat) * diffuse.rgb * color, + getMaterialDiffuse(mat) * diffuse.rgb * _color, specular, // no use of getMaterialSpecular(mat) getMaterialShininess(mat), (vec3(emissiveParams.x) + emissiveParams.y * emissive.rgb)); diff --git a/libraries/render-utils/src/model_normal_map.slf b/libraries/render-utils/src/model_normal_map.slf index 5a4bc0e1bb..5479cec8eb 100755 --- a/libraries/render-utils/src/model_normal_map.slf +++ b/libraries/render-utils/src/model_normal_map.slf @@ -22,31 +22,29 @@ uniform sampler2D diffuseMap; // the normal map texture uniform sampler2D normalMap; -// the interpolated normal -varying vec4 interpolatedNormal; - -// the interpolated tangent -varying vec4 interpolatedTangent; - -varying vec3 color; +in vec4 _position; +in vec2 _texCoord0; +in vec3 _normal; +in vec3 _tangent; +in vec3 _color; void main(void) { // compute the view normal from the various bits - vec3 normalizedNormal = normalize(vec3(interpolatedNormal)); - vec3 normalizedTangent = normalize(vec3(interpolatedTangent)); + vec3 normalizedNormal = normalize(_normal.xyz); + vec3 normalizedTangent = normalize(_tangent.xyz); vec3 normalizedBitangent = normalize(cross(normalizedNormal, normalizedTangent)); - vec3 localNormal = normalize(vec3(texture2D(normalMap, gl_TexCoord[0].st)) - vec3(0.5, 0.5, 0.5)); + vec3 localNormal = normalize(vec3(texture(normalMap, _texCoord0.st)) - vec3(0.5, 0.5, 0.5)); vec4 viewNormal = vec4(normalizedTangent * localNormal.x + normalizedBitangent * localNormal.y + normalizedNormal * localNormal.z, 0.0); - vec4 diffuse = texture2D(diffuseMap, gl_TexCoord[0].st); + vec4 diffuse = texture(diffuseMap, _texCoord0.st); Material mat = getMaterial(); packDeferredFragment( normalize(viewNormal.xyz), evalOpaqueFinalAlpha(getMaterialOpacity(mat), diffuse.a), - getMaterialDiffuse(mat) * diffuse.rgb * color, + getMaterialDiffuse(mat) * diffuse.rgb * _color, getMaterialSpecular(mat), getMaterialShininess(mat)); } diff --git a/libraries/render-utils/src/model_normal_map.slv b/libraries/render-utils/src/model_normal_map.slv index 58eb03e564..752f367a48 100755 --- a/libraries/render-utils/src/model_normal_map.slv +++ b/libraries/render-utils/src/model_normal_map.slv @@ -2,7 +2,7 @@ <$VERSION_HEADER$> // Generated on <$_SCRIBE_DATE$> // -// model.vert +// model_normal_map.vert // vertex shader // // Created by Andrzej Kapolka on 10/14/13. @@ -12,6 +12,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +<@include gpu/Inputs.slh@> + <@include gpu/Transform.slh@> <$declareStandardTransform()$> @@ -20,38 +22,23 @@ const int MAX_TEXCOORDS = 2; uniform mat4 texcoordMatrices[MAX_TEXCOORDS]; -// the tangent vector -attribute vec3 tangent; - -// interpolated eye position -varying vec4 interpolatedPosition; - -// the interpolated normal -varying vec4 interpolatedNormal; - -// the interpolated tangent -varying vec4 interpolatedTangent; - -varying vec3 color; +out vec4 _position; +out vec2 _texCoord0; +out vec3 _normal; +out vec3 _tangent; +out vec3 _color; void main(void) { - // transform and store the normal and tangent for interpolation - //interpolatedNormal = gl_ModelViewMatrix * vec4(gl_Normal, 0.0); - //interpolatedTangent = gl_ModelViewMatrix * vec4(tangent, 0.0); - // pass along the diffuse color - color = gl_Color.xyz; - + _color = inColor.rgb; + // and the texture coordinates - gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.0, 1.0); - + _texCoord0 = (texcoordMatrices[0] * vec4(inTexCoord0.xy, 0.0, 1.0)).st; + // standard transform TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); - <$transformModelToEyeAndClipPos(cam, obj, gl_Vertex, interpolatedPosition, gl_Position)$> - <$transformModelToEyeDir(cam, obj, gl_Normal, interpolatedNormal.xyz)$> - <$transformModelToEyeDir(cam, obj, tangent, interpolatedTangent.xyz)$> - - interpolatedNormal = vec4(normalize(interpolatedNormal.xyz), 0.0); - interpolatedTangent = vec4(normalize(interpolatedTangent.xyz), 0.0); + <$transformModelToEyeAndClipPos(cam, obj, inPosition, _position, gl_Position)$> + <$transformModelToEyeDir(cam, obj, inNormal.xyz, _normal)$> + <$transformModelToEyeDir(cam, obj, inTangent.xyz, _tangent)$> } diff --git a/libraries/render-utils/src/model_normal_specular_map.slf b/libraries/render-utils/src/model_normal_specular_map.slf index 0fc021a31d..2ebcdaae44 100755 --- a/libraries/render-utils/src/model_normal_specular_map.slf +++ b/libraries/render-utils/src/model_normal_specular_map.slf @@ -25,33 +25,31 @@ uniform sampler2D normalMap; // the specular map texture uniform sampler2D specularMap; -// the interpolated normal -varying vec4 interpolatedNormal; - -// the interpolated tangent -varying vec4 interpolatedTangent; - -varying vec3 color; +in vec4 _position; +in vec2 _texCoord0; +in vec3 _normal; +in vec3 _tangent; +in vec3 _color; void main(void) { // compute the view normal from the various bits - vec3 normalizedNormal = normalize(vec3(interpolatedNormal)); - vec3 normalizedTangent = normalize(vec3(interpolatedTangent)); + vec3 normalizedNormal = normalize(_normal); + vec3 normalizedTangent = normalize(_tangent); vec3 normalizedBitangent = normalize(cross(normalizedNormal, normalizedTangent)); - vec3 localNormal = normalize(vec3(texture2D(normalMap, gl_TexCoord[0].st)) - vec3(0.5, 0.5, 0.5)); + vec3 localNormal = normalize(vec3(texture(normalMap, _texCoord0)) - vec3(0.5, 0.5, 0.5)); vec4 viewNormal = vec4(normalizedTangent * localNormal.x + normalizedBitangent * localNormal.y + normalizedNormal * localNormal.z, 0.0); // set the diffuse, normal, specular data - vec4 diffuse = texture2D(diffuseMap, gl_TexCoord[0].st); - vec3 specular = texture2D(specularMap, gl_TexCoord[0].st).rgb; + vec4 diffuse = texture(diffuseMap, _texCoord0); + vec3 specular = texture(specularMap, _texCoord0).rgb; Material mat = getMaterial(); packDeferredFragment( normalize(viewNormal.xyz), evalOpaqueFinalAlpha(getMaterialOpacity(mat), diffuse.a), - getMaterialDiffuse(mat) * diffuse.rgb * color, + getMaterialDiffuse(mat) * diffuse.rgb * _color, specular, //getMaterialSpecular(mat), getMaterialShininess(mat)); } diff --git a/libraries/render-utils/src/model_shadow.slf b/libraries/render-utils/src/model_shadow.slf index e8bdb01f30..d691104bdd 100755 --- a/libraries/render-utils/src/model_shadow.slf +++ b/libraries/render-utils/src/model_shadow.slf @@ -12,7 +12,9 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +out vec4 _fragColor; + void main(void) { // fixed color for now (we may eventually want to use texture alpha) - gl_FragColor = vec4(1.0, 1.0, 1.0, 0.0); + _fragColor = vec4(1.0, 1.0, 1.0, 0.0); } diff --git a/libraries/render-utils/src/model_shadow.slv b/libraries/render-utils/src/model_shadow.slv index 88e597557e..b18c123d82 100755 --- a/libraries/render-utils/src/model_shadow.slv +++ b/libraries/render-utils/src/model_shadow.slv @@ -1,5 +1,5 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> +<@include gpu/Config.slh@> +<$VERSION_HEADER$> // Generated on <$_SCRIBE_DATE$> // // model_shadow.vert @@ -11,12 +11,16 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -<@include gpu/Transform.slh@> -<$declareStandardTransform()$> + +<@include gpu/Inputs.slh@> + +<@include gpu/Transform.slh@> + +<$declareStandardTransform()$> void main(void) { - // standard transform - TransformCamera cam = getTransformCamera(); - TransformObject obj = getTransformObject(); - <$transformModelToClipPos(cam, obj, gl_Vertex, gl_Position)$> + // standard transform + TransformCamera cam = getTransformCamera(); + TransformObject obj = getTransformObject(); + <$transformModelToClipPos(cam, obj, inPosition, gl_Position)$> } diff --git a/libraries/render-utils/src/model_specular_map.slf b/libraries/render-utils/src/model_specular_map.slf index 46f565de6c..e7f639194d 100755 --- a/libraries/render-utils/src/model_specular_map.slf +++ b/libraries/render-utils/src/model_specular_map.slf @@ -22,22 +22,23 @@ uniform sampler2D diffuseMap; // the specular texture uniform sampler2D specularMap; -// the interpolated normal -varying vec4 interpolatedNormal; +in vec4 _position; +in vec2 _texCoord0; +in vec3 _normal; +in vec3 _color; -varying vec3 color; void main(void) { // set the diffuse, normal, specular data - vec4 diffuse = texture2D(diffuseMap, gl_TexCoord[0].st); - vec3 specular = texture2D(specularMap, gl_TexCoord[0].st).rgb; + vec4 diffuse = texture(diffuseMap, _texCoord0); + vec3 specular = texture(specularMap, _texCoord0).rgb; Material mat = getMaterial(); packDeferredFragment( - normalize(interpolatedNormal.xyz), + normalize(_normal), evalOpaqueFinalAlpha(getMaterialOpacity(mat), diffuse.a), - getMaterialDiffuse(mat) * diffuse.rgb * color, + getMaterialDiffuse(mat) * diffuse.rgb * _color, specular, //getMaterialSpecular(mat), getMaterialShininess(mat)); } diff --git a/libraries/render-utils/src/model_translucent.slf b/libraries/render-utils/src/model_translucent.slf index 179b7b9e28..12e841399b 100755 --- a/libraries/render-utils/src/model_translucent.slf +++ b/libraries/render-utils/src/model_translucent.slf @@ -11,34 +11,6 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // - - -<@include model/Material.slh@> - -// the diffuse texture -uniform sampler2D diffuseMap; - -varying vec4 interpolatedNormal; - -varying vec3 color; - -void main(void) { - - // Fetch diffuse map - vec4 diffuse = texture2D(diffuseMap, gl_TexCoord[0].st); - - Material mat = getMaterial(); - - packDeferredFragmentTranslucent( - normalize(interpolatedNormal.xyz), - getMaterialOpacity(mat) * diffuse.a, - getMaterialDiffuse(mat) * diffuse.rgb * color, - getMaterialSpecular(mat), - getMaterialShininess(mat)); - - // set the diffuse data - // gl_FragData[0] = gl_Color * texture2D(diffuseMap, gl_TexCoord[0].st); -}*/!> <@include model/Material.slh@> // Everything about global lighting @@ -99,34 +71,31 @@ vec4 evalGlobalColor(float shadowAttenuation, vec3 position, vec3 normal, vec3 d // the diffuse texture uniform sampler2D diffuseMap; -// the interpolated view position -varying vec4 interpolatedPosition; +in vec4 _position; +in vec2 _texCoord0; +in vec3 _normal; +in vec3 _color; -// the interpolated normal -varying vec4 interpolatedNormal; - -varying vec3 color; +out vec4 _fragColor; void main(void) { - vec3 fragPosition = interpolatedPosition.xyz; + vec3 fragPosition = _position.xyz; // Fetch diffuse map - vec4 diffuse = texture2D(diffuseMap, gl_TexCoord[0].st); + vec4 diffuse = texture(diffuseMap, _texCoord0); Material mat = getMaterial(); - vec3 fragNormal = normalize(interpolatedNormal.xyz); + vec3 fragNormal = normalize(_normal); float fragOpacity = getMaterialOpacity(mat) * diffuse.a; - vec3 fragDiffuse = getMaterialDiffuse(mat) * diffuse.rgb * color; + vec3 fragDiffuse = getMaterialDiffuse(mat) * diffuse.rgb * _color; vec3 fragSpecular = getMaterialSpecular(mat); float fragGloss = getMaterialShininess(mat); - vec4 fragColor = evalGlobalColor(1.0, + _fragColor = evalGlobalColor(1.0, fragPosition, fragNormal, fragDiffuse, fragSpecular, fragGloss, fragOpacity); - - gl_FragColor = fragColor; } diff --git a/libraries/render-utils/src/occlusion_blend.slf b/libraries/render-utils/src/occlusion_blend.slf index cdab624b95..58873d9884 100644 --- a/libraries/render-utils/src/occlusion_blend.slf +++ b/libraries/render-utils/src/occlusion_blend.slf @@ -14,13 +14,14 @@ <@include DeferredBufferWrite.slh@> -varying vec2 varTexcoord; +in vec2 varTexcoord; +out vec4 outFragColor; uniform sampler2D blurredOcclusionTexture; void main(void) { - vec4 occlusionColor = texture2D(blurredOcclusionTexture, varTexcoord); + vec4 occlusionColor = texture(blurredOcclusionTexture, varTexcoord); - gl_FragColor = vec4(vec3(0.0), occlusionColor.r); + outFragColor = vec4(vec3(0.0), occlusionColor.r); } diff --git a/libraries/render-utils/src/overlay3D.slf b/libraries/render-utils/src/overlay3D.slf index 69ea8c0e76..7b8a8d85f4 100644 --- a/libraries/render-utils/src/overlay3D.slf +++ b/libraries/render-utils/src/overlay3D.slf @@ -13,17 +13,18 @@ uniform sampler2D diffuseMap; -varying vec2 varTexcoord; +in vec2 varTexcoord; -varying vec3 varEyeNormal; +in vec3 varEyeNormal; -varying vec4 varColor; +in vec4 varColor; +out vec4 outFragColor; void main(void) { - vec4 diffuse = texture2D(diffuseMap, varTexcoord.st); + vec4 diffuse = texture(diffuseMap, varTexcoord.st); if (diffuse.a < 0.5) { discard; } - gl_FragColor = vec4(varColor * diffuse); + outFragColor = vec4(varColor * diffuse); } diff --git a/libraries/render-utils/src/overlay3D.slv b/libraries/render-utils/src/overlay3D.slv index cdb11c1d08..a57f02d854 100644 --- a/libraries/render-utils/src/overlay3D.slv +++ b/libraries/render-utils/src/overlay3D.slv @@ -10,31 +10,31 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +<@include gpu/Inputs.slh@> + <@include gpu/Transform.slh@> <$declareStandardTransform()$> -//attribute vec2 texcoord; - -varying vec2 varTexcoord; +out vec2 varTexcoord; // interpolated eye position -varying vec4 varEyePosition; +out vec4 varEyePosition; // the interpolated normal -varying vec3 varEyeNormal; +out vec3 varEyeNormal; -varying vec4 varColor; +out vec4 varColor; void main(void) { - varTexcoord = gl_MultiTexCoord0.xy; + varTexcoord = inTexCoord0.xy; // pass along the color - varColor = gl_Color; + varColor = inColor; // standard transform TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); - <$transformModelToEyeAndClipPos(cam, obj, gl_Vertex, varEyePosition, gl_Position)$> - <$transformModelToEyeDir(cam, obj, gl_Normal, varEyeNormal.xyz)$> + <$transformModelToEyeAndClipPos(cam, obj, inPosition, varEyePosition, gl_Position)$> + <$transformModelToEyeDir(cam, obj, inNormal.xyz, varEyeNormal.xyz)$> } diff --git a/libraries/render-utils/src/point_light.slf b/libraries/render-utils/src/point_light.slf index 78d3d1e458..528e6e9d96 100644 --- a/libraries/render-utils/src/point_light.slf +++ b/libraries/render-utils/src/point_light.slf @@ -2,7 +2,7 @@ <$VERSION_HEADER$> // Generated on <$_SCRIBE_DATE$> // -// spot_light.frag +// point_light.frag // fragment shader // // Created by Andrzej Kapolka on 9/18/14. @@ -24,9 +24,12 @@ // The view Matrix uniform mat4 invViewMat; +in vec4 _texCoord0; +out vec4 _fragColor; + void main(void) { // Grab the fragment data from the uv - vec2 texCoord = gl_TexCoord[0].st / gl_TexCoord[0].q; + vec2 texCoord = _texCoord0.st / _texCoord0.q; DeferredFragment frag = unpackDeferredFragment(texCoord); // Kill if in front of the light volume @@ -62,14 +65,14 @@ void main(void) { // Final Lighting color vec3 fragColor = shading.w * (frag.diffuse + shading.xyz); - gl_FragColor = vec4(fragColor * radialAttenuation * getLightColor(light) * getLightIntensity(light), 0.0); + _fragColor = vec4(fragColor * radialAttenuation * getLightColor(light) * getLightIntensity(light), 0.0); if (getLightShowContour(light) > 0.0) { // Show edge float edge = abs(2.0 * ((getLightRadius(light) - fragLightDistance) / (0.1)) - 1.0); if (edge < 1) { float edgeCoord = exp2(-8.0*edge*edge); - gl_FragColor = vec4(edgeCoord * edgeCoord * getLightShowContour(light) * getLightColor(light), 0.0); + _fragColor = vec4(edgeCoord * edgeCoord * getLightShowContour(light) * getLightColor(light), 0.0); } } } diff --git a/libraries/render-utils/src/sdf_text3D.slf b/libraries/render-utils/src/sdf_text3D.slf index 425d6f9b08..69fec0042b 100644 --- a/libraries/render-utils/src/sdf_text3D.slf +++ b/libraries/render-utils/src/sdf_text3D.slf @@ -15,7 +15,14 @@ uniform bool Outline; uniform vec4 Color; // the interpolated normal -varying vec4 interpolatedNormal; +in vec3 _normal; +in vec2 _texCoord0; + +layout(location = 0) out vec4 _fragColor0; +layout(location = 1) out vec4 _fragColor1; +layout(location = 2) out vec4 _fragColor2; + +const float DEFAULT_SHININESS = 10; const float gamma = 2.2; const float smoothing = 256.0; @@ -24,7 +31,7 @@ const float outlineExpansion = 0.2; void main() { // retrieve signed distance - float sdf = texture2D(Font, gl_TexCoord[0].xy).g; + float sdf = texture(Font, _texCoord0).g; if (Outline) { if (sdf > interiorCutoff) { sdf = 1.0 - sdf; @@ -34,7 +41,7 @@ void main() { } // perform adaptive anti-aliasing of the edges // The larger we're rendering, the less anti-aliasing we need - float s = smoothing * length(fwidth(gl_TexCoord[0].xy)); + float s = smoothing * length(fwidth(_texCoord0)); float w = clamp( s, 0.0, 0.5); float a = smoothstep(0.5 - w, 0.5 + w, sdf); @@ -46,7 +53,7 @@ void main() { } // final color - gl_FragData[0] = vec4(Color.rgb, Color.a * a); - gl_FragData[1] = vec4(normalize(interpolatedNormal.xyz), 0.0) * 0.5 + vec4(0.5, 0.5, 0.5, 0.5); - gl_FragData[2] = vec4(Color.rgb, gl_FrontMaterial.shininess / 128.0); + _fragColor0 = vec4(Color.rgb, Color.a * a); + _fragColor1 = vec4(normalize(_normal.xyz), 0.0) * 0.5 + vec4(0.5, 0.5, 0.5, 0.5); + _fragColor2 = vec4(Color.rgb, DEFAULT_SHININESS / 128.0); } \ No newline at end of file diff --git a/libraries/render-utils/src/sdf_text3D.slv b/libraries/render-utils/src/sdf_text3D.slv index 6838650e75..d8b7587789 100644 --- a/libraries/render-utils/src/sdf_text3D.slv +++ b/libraries/render-utils/src/sdf_text3D.slv @@ -9,21 +9,23 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // + +<@include gpu/Inputs.slh@> + <@include gpu/Transform.slh@> <$declareStandardTransform()$> // the interpolated normal -varying vec4 interpolatedNormal; +out vec3 _normal; +out vec2 _texCoord0; void main() { - gl_TexCoord[0] = gl_MultiTexCoord0; + _texCoord0 = inTexCoord0.xy; // standard transform TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); - <$transformModelToClipPos(cam, obj, gl_Vertex, gl_Position)$> - <$transformModelToEyeDir(cam, obj, gl_Normal, interpolatedNormal.xyz)$> - - interpolatedNormal = vec4(normalize(interpolatedNormal.xyz), 0.0); + <$transformModelToClipPos(cam, obj, inPosition, gl_Position)$> + <$transformModelToEyeDir(cam, obj, inNormal.xyz, _normal.xyz)$> } \ No newline at end of file diff --git a/libraries/render-utils/src/simple.slf b/libraries/render-utils/src/simple.slf index 84f1752c37..31d33a73e4 100644 --- a/libraries/render-utils/src/simple.slf +++ b/libraries/render-utils/src/simple.slf @@ -13,14 +13,17 @@ // <@include DeferredBufferWrite.slh@> +<@include model/Material.slh@> // the interpolated normal -varying vec4 interpolatedNormal; +in vec3 _normal; +in vec3 _color; void main(void) { + Material material = getMaterial(); packDeferredFragment( - normalize(interpolatedNormal.xyz), + normalize(_normal.xyz), glowIntensity, - gl_Color.rgb, - DEFAULT_SPECULAR, DEFAULT_SHININESS); + _color.rgb, + DEFAULT_SPECULAR, DEFAULT_SHININESS); } diff --git a/libraries/render-utils/src/simple.slv b/libraries/render-utils/src/simple.slv index 380734e70c..99f404eaec 100644 --- a/libraries/render-utils/src/simple.slv +++ b/libraries/render-utils/src/simple.slv @@ -12,24 +12,25 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +<@include gpu/Inputs.slh@> + <@include gpu/Transform.slh@> <$declareStandardTransform()$> // the interpolated normal -varying vec4 interpolatedNormal; + +out vec3 _normal; +out vec3 _color; +out vec2 _texCoord0; void main(void) { - gl_TexCoord[0] = gl_MultiTexCoord0; - - // pass along the diffuse color - gl_FrontColor = gl_Color; - + _color = inColor.rgb; + _texCoord0 = inTexCoord0.st; + // standard transform TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); - <$transformModelToClipPos(cam, obj, gl_Vertex, gl_Position)$> - <$transformModelToEyeDir(cam, obj, gl_Normal, interpolatedNormal.xyz)$> - - interpolatedNormal = vec4(normalize(interpolatedNormal.xyz), 0.0); + <$transformModelToClipPos(cam, obj, inPosition, gl_Position)$> + <$transformModelToEyeDir(cam, obj, inNormal.xyz, _normal)$> } \ No newline at end of file diff --git a/libraries/render-utils/src/simple_textured.slf b/libraries/render-utils/src/simple_textured.slf index 68d235050d..d567b043f4 100644 --- a/libraries/render-utils/src/simple_textured.slf +++ b/libraries/render-utils/src/simple_textured.slf @@ -13,19 +13,23 @@ // <@include DeferredBufferWrite.slh@> +<@include model/Material.slh@> // the diffuse texture uniform sampler2D originalTexture; // the interpolated normal -varying vec4 interpolatedNormal; +in vec3 _normal; +in vec3 _color; +in vec2 _texCoord0; void main(void) { - vec4 texel = texture2D(originalTexture, gl_TexCoord[0].st); + Material material = getMaterial(); + vec4 texel = texture(originalTexture, _texCoord0); packDeferredFragment( - normalize(interpolatedNormal.xyz), - glowIntensity * texel.a, - gl_Color.rgb * texel.rgb, - DEFAULT_SPECULAR, DEFAULT_SHININESS); + normalize(_normal.xyz), + glowIntensity * texel.a, + _color.rgb * texel.rgb, + DEFAULT_SPECULAR, DEFAULT_SHININESS); } \ No newline at end of file diff --git a/libraries/render-utils/src/simple_textured_emisive.slf b/libraries/render-utils/src/simple_textured_emisive.slf index d2c7d403c3..96119e98f0 100644 --- a/libraries/render-utils/src/simple_textured_emisive.slf +++ b/libraries/render-utils/src/simple_textured_emisive.slf @@ -18,15 +18,17 @@ uniform sampler2D originalTexture; // the interpolated normal -varying vec4 interpolatedNormal; +in vec3 _normal; +in vec3 _color; +in vec2 _texCoord0; void main(void) { - vec4 texel = texture2D(originalTexture, gl_TexCoord[0].st); + vec4 texel = texture(originalTexture, _texCoord0.st); packDeferredFragmentLightmap( - normalize(interpolatedNormal.xyz), + normalize(_normal), glowIntensity * texel.a, - gl_Color.rgb, + _color.rgb, DEFAULT_SPECULAR, DEFAULT_SHININESS, texel.rgb); } \ No newline at end of file diff --git a/libraries/render-utils/src/skin_model.slv b/libraries/render-utils/src/skin_model.slv index a13c73c73c..53e68727fb 100755 --- a/libraries/render-utils/src/skin_model.slv +++ b/libraries/render-utils/src/skin_model.slv @@ -12,7 +12,10 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +<@include gpu/Inputs.slh@> + <@include gpu/Transform.slh@> + <$declareStandardTransform()$> const int MAX_TEXCOORDS = 2; @@ -22,38 +25,31 @@ const int INDICES_PER_VERTEX = 4; uniform mat4 clusterMatrices[MAX_CLUSTERS]; uniform mat4 texcoordMatrices[MAX_TEXCOORDS]; -attribute vec4 clusterIndices; -attribute vec4 clusterWeights; - -// interpolated eye position -varying vec4 interpolatedPosition; - -// the interpolated normal -varying vec4 interpolatedNormal; - -varying vec3 color; +out vec4 _position; +out vec2 _texCoord0; +out vec3 _normal; +out vec3 _color; void main(void) { vec4 position = vec4(0.0, 0.0, 0.0, 0.0); - interpolatedNormal = vec4(0.0, 0.0, 0.0, 0.0); + vec4 interpolatedNormal = vec4(0.0, 0.0, 0.0, 0.0); for (int i = 0; i < INDICES_PER_VERTEX; i++) { - mat4 clusterMatrix = clusterMatrices[int(clusterIndices[i])]; - float clusterWeight = clusterWeights[i]; - position += clusterMatrix * gl_Vertex * clusterWeight; - interpolatedNormal += clusterMatrix * vec4(gl_Normal, 0.0) * clusterWeight; + mat4 clusterMatrix = clusterMatrices[int(inSkinClusterIndex[i])]; + float clusterWeight = inSkinClusterWeight[i]; + position += clusterMatrix * inPosition * clusterWeight; + interpolatedNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight; } // pass along the diffuse color - color = gl_Color.xyz; + _color = inColor.rgb; // and the texture coordinates - gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.0, 1.0); + _texCoord0 = (texcoordMatrices[0] * vec4(inTexCoord0.st, 0.0, 1.0)).st; // standard transform TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); - <$transformModelToEyeAndClipPos(cam, obj, position, interpolatedPosition, gl_Position)$> + <$transformModelToEyeAndClipPos(cam, obj, position, _position, gl_Position)$> <$transformModelToEyeDir(cam, obj, interpolatedNormal.xyz, interpolatedNormal.xyz)$> - - interpolatedNormal = vec4(normalize(interpolatedNormal.xyz), 0.0); + _normal = interpolatedNormal.xyz; } diff --git a/libraries/render-utils/src/skin_model_normal_map.slv b/libraries/render-utils/src/skin_model_normal_map.slv index 3f815ba47e..4c558939d8 100755 --- a/libraries/render-utils/src/skin_model_normal_map.slv +++ b/libraries/render-utils/src/skin_model_normal_map.slv @@ -12,7 +12,10 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +<@include gpu/Inputs.slh@> + <@include gpu/Transform.slh@> + <$declareStandardTransform()$> const int MAX_TEXCOORDS = 2; @@ -22,40 +25,29 @@ const int INDICES_PER_VERTEX = 4; uniform mat4 clusterMatrices[MAX_CLUSTERS]; uniform mat4 texcoordMatrices[MAX_TEXCOORDS]; -// the tangent vector -attribute vec3 tangent; - -attribute vec4 clusterIndices; -attribute vec4 clusterWeights; - -// interpolated eye position -varying vec4 interpolatedPosition; - -// the interpolated normal -varying vec4 interpolatedNormal; - -// the interpolated tangent -varying vec4 interpolatedTangent; - -varying vec3 color; +out vec4 _position; +out vec2 _texCoord0; +out vec3 _normal; +out vec3 _tangent; +out vec3 _color; void main(void) { vec4 position = vec4(0.0, 0.0, 0.0, 0.0); - interpolatedNormal = vec4(0.0, 0.0, 0.0, 0.0); - interpolatedTangent = vec4(0.0, 0.0, 0.0, 0.0); + vec4 interpolatedNormal = vec4(0.0, 0.0, 0.0, 0.0); + vec4 interpolatedTangent = vec4(0.0, 0.0, 0.0, 0.0); for (int i = 0; i < INDICES_PER_VERTEX; i++) { - mat4 clusterMatrix = clusterMatrices[int(clusterIndices[i])]; - float clusterWeight = clusterWeights[i]; - position += clusterMatrix * gl_Vertex * clusterWeight; - interpolatedNormal += clusterMatrix * vec4(gl_Normal, 0.0) * clusterWeight; - interpolatedTangent += clusterMatrix * vec4(tangent, 0.0) * clusterWeight; + mat4 clusterMatrix = clusterMatrices[int(inSkinClusterIndex[i])]; + float clusterWeight = inSkinClusterWeight[i]; + position += clusterMatrix * inPosition * clusterWeight; + interpolatedNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight; + interpolatedTangent += clusterMatrix * vec4(inTangent.xyz, 0.0) * clusterWeight; } // pass along the diffuse color - color = gl_Color.xyz; + _color = inColor.rgb; // and the texture coordinates - gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.0, 1.0); + _texCoord0 = (texcoordMatrices[0] * vec4(inTexCoord0.st, 0.0, 1.0)).st; interpolatedNormal = vec4(normalize(interpolatedNormal.xyz), 0.0); interpolatedTangent = vec4(normalize(interpolatedTangent.xyz), 0.0); @@ -63,10 +55,10 @@ void main(void) { // standard transform TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); - <$transformModelToEyeAndClipPos(cam, obj, position, interpolatedPosition, gl_Position)$> + <$transformModelToEyeAndClipPos(cam, obj, position, _position, gl_Position)$> <$transformModelToEyeDir(cam, obj, interpolatedNormal.xyz, interpolatedNormal.xyz)$> <$transformModelToEyeDir(cam, obj, interpolatedTangent.xyz, interpolatedTangent.xyz)$> - interpolatedNormal = vec4(normalize(interpolatedNormal.xyz), 0.0); - interpolatedTangent = vec4(normalize(interpolatedTangent.xyz), 0.0); + _normal = interpolatedNormal.xyz; + _tangent = interpolatedTangent.xyz; } diff --git a/libraries/render-utils/src/skin_model_shadow.slv b/libraries/render-utils/src/skin_model_shadow.slv index 03b912a981..6cb4da25f4 100755 --- a/libraries/render-utils/src/skin_model_shadow.slv +++ b/libraries/render-utils/src/skin_model_shadow.slv @@ -1,5 +1,5 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> +<@include gpu/Config.slh@> +<$VERSION_HEADER$> // Generated on <$_SCRIBE_DATE$> // // skin_model_shadow.vert @@ -12,27 +12,25 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +<@include gpu/Inputs.slh@> <@include gpu/Transform.slh@> -<$declareStandardTransform()$> +<$declareStandardTransform()$> const int MAX_CLUSTERS = 128; const int INDICES_PER_VERTEX = 4; uniform mat4 clusterMatrices[MAX_CLUSTERS]; -attribute vec4 clusterIndices; -attribute vec4 clusterWeights; - void main(void) { vec4 position = vec4(0.0, 0.0, 0.0, 0.0); for (int i = 0; i < INDICES_PER_VERTEX; i++) { - mat4 clusterMatrix = clusterMatrices[int(clusterIndices[i])]; - float clusterWeight = clusterWeights[i]; - position += clusterMatrix * gl_Vertex * clusterWeight; + mat4 clusterMatrix = clusterMatrices[int(inSkinClusterIndex[i])]; + float clusterWeight = inSkinClusterWeight[i]; + position += clusterMatrix * inPosition * clusterWeight; } - // standard transform - TransformCamera cam = getTransformCamera(); - TransformObject obj = getTransformObject(); + // standard transform + TransformCamera cam = getTransformCamera(); + TransformObject obj = getTransformObject(); <$transformModelToClipPos(cam, obj, position, gl_Position)$> } diff --git a/libraries/render-utils/src/spot_light.slf b/libraries/render-utils/src/spot_light.slf index cfb2a6da4b..6510ee612c 100644 --- a/libraries/render-utils/src/spot_light.slf +++ b/libraries/render-utils/src/spot_light.slf @@ -24,9 +24,12 @@ // The view Matrix uniform mat4 invViewMat; +in vec4 _texCoord0; +out vec4 _fragColor; + void main(void) { // Grab the fragment data from the uv - vec2 texCoord = gl_TexCoord[0].st / gl_TexCoord[0].q; + vec2 texCoord = _texCoord0.st / _texCoord0.q; DeferredFragment frag = unpackDeferredFragment(texCoord); // Kill if in front of the light volume @@ -70,7 +73,7 @@ void main(void) { // Final Lighting color vec3 fragColor = shading.w * (frag.diffuse + shading.xyz); - gl_FragColor = vec4(fragColor * angularAttenuation * radialAttenuation * getLightColor(light) * getLightIntensity(light), 0.0); + _fragColor = vec4(fragColor * angularAttenuation * radialAttenuation * getLightColor(light) * getLightIntensity(light), 0.0); if (getLightShowContour(light) > 0.0) { // Show edges @@ -80,7 +83,7 @@ void main(void) { float edge = abs(2.0 * (edgeDist / (0.1)) - 1.0); if (edge < 1) { float edgeCoord = exp2(-8.0*edge*edge); - gl_FragColor = vec4(edgeCoord * edgeCoord * getLightColor(light), 0.0); + _fragColor = vec4(edgeCoord * edgeCoord * getLightColor(light), 0.0); } } } diff --git a/libraries/render-utils/src/standardDrawTexture.slf b/libraries/render-utils/src/standardDrawTexture.slf index 4fbeb6eb7f..95ac82557c 100644 --- a/libraries/render-utils/src/standardDrawTexture.slf +++ b/libraries/render-utils/src/standardDrawTexture.slf @@ -14,11 +14,14 @@ // the texture uniform sampler2D colorMap; -varying vec2 varTexcoord; -varying vec4 varColor; +in vec3 varPosition; +in vec3 varNormal; +in vec2 varTexCoord0; +in vec4 varColor; +out vec4 outFragColor; void main(void) { - vec4 color = texture2D(colorMap, varTexcoord); - gl_FragColor = color * varColor; + vec4 color = texture(colorMap, varTexCoord0); + outFragColor = color * varColor; } diff --git a/libraries/render-utils/src/standardTransformPNTC.slv b/libraries/render-utils/src/standardTransformPNTC.slv index 93abea267c..340dfd9c8e 100644 --- a/libraries/render-utils/src/standardTransformPNTC.slv +++ b/libraries/render-utils/src/standardTransformPNTC.slv @@ -12,24 +12,25 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +<@include gpu/Inputs.slh@> + <@include gpu/Transform.slh@> <$declareStandardTransform()$> -varying vec3 varPosition; -varying vec3 varNormal; -varying vec2 varTexcoord; -varying vec4 varColor; +out vec3 varPosition; +out vec3 varNormal; +out vec2 varTexCoord0; +out vec4 varColor; void main(void) { - varTexcoord = gl_MultiTexCoord0.xy; - varColor = gl_Color; + varTexCoord0 = inTexCoord0.st; + varColor = inColor; // standard transform TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); - <$transformModelToClipPos(cam, obj, gl_Vertex, gl_Position)$> - <$transformModelToEyeDir(cam, obj, gl_Normal, varNormal)$> - varNormal = normalize(varNormal); - varPosition = gl_Vertex.xyz; + <$transformModelToClipPos(cam, obj, inPosition, gl_Position)$> + <$transformModelToEyeDir(cam, obj, inNormal.xyz, varNormal)$> + varPosition = inPosition.xyz; } \ No newline at end of file diff --git a/libraries/render-utils/src/stars.slf b/libraries/render-utils/src/stars.slf index 7e1c96bc5b..14191f2a6a 100644 --- a/libraries/render-utils/src/stars.slf +++ b/libraries/render-utils/src/stars.slf @@ -10,8 +10,25 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -varying vec4 varColor; +in vec4 varColor; +in float varSize; + +out vec4 outFragColor; + +const float EDGE_SIZE = 0.25; +const float ALPHA_BOUNDARY = 1.0 - EDGE_SIZE; void main(void) { - gl_FragColor = varColor; //vec4(varColor, 1.0); + vec2 coord = gl_PointCoord * vec2(2.0) - vec2(1.0); + coord = coord * coord; + + float l = coord.x + coord.y; + if (l > 1.0) { + discard; + } + + outFragColor = varColor; + if (l >= ALPHA_BOUNDARY) { + outFragColor.a = smoothstep(1.0, ALPHA_BOUNDARY, l); + } } diff --git a/libraries/render-utils/src/stars.slv b/libraries/render-utils/src/stars.slv index 98241321fa..b9ad736d5e 100644 --- a/libraries/render-utils/src/stars.slv +++ b/libraries/render-utils/src/stars.slv @@ -12,21 +12,26 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +<@include gpu/Inputs.slh@> + <@include gpu/Transform.slh@> <$declareStandardTransform()$> -varying vec3 varPosition; -varying vec4 varColor; +// TODO we need to get the viewport resolution and FOV passed to us so we can modify the point size +// and effectively producing a points that take up a constant angular size regardless of the display resolution +// or projection matrix +out vec4 varColor; +out float varSize; void main(void) { - varColor = gl_Color.rgba; + varColor = inColor.rgba; // standard transform TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); - <$transformModelToClipPos(cam, obj, gl_Vertex, gl_Position)$> - varPosition = gl_Vertex.xyz; - gl_PointSize = gl_Color.a; + <$transformModelToClipPos(cam, obj, inPosition, gl_Position)$> + varSize = inColor.a; + gl_PointSize = varSize; } \ No newline at end of file diff --git a/libraries/render-utils/src/starsGrid.slf b/libraries/render-utils/src/starsGrid.slf index 12dfd0317c..c52ccb54d9 100644 --- a/libraries/render-utils/src/starsGrid.slf +++ b/libraries/render-utils/src/starsGrid.slf @@ -7,9 +7,9 @@ // // Created by Bradley Austin Davis on 2015/06/19 -varying vec2 varTexcoord; -varying vec3 varNomral; -varying vec3 varPosition; +in vec2 varTexcoord; +in vec3 varNomral; +in vec3 varPosition; uniform float iGlobalTime; @@ -20,6 +20,7 @@ const float latitudeDist = PI / 2.0 / float(latitudeCount); const int meridianCount = 4; const float merdianDist = PI / float(meridianCount); +out vec4 outFragColor; float clampLine(float val, float target) { return clamp((1.0 - abs((val - target)) - 0.998) * 500.0, 0.0, 1.0); @@ -58,6 +59,6 @@ void mainVR( out vec4 fragColor, in vec2 fragCoord, in vec3 fragRayOri, in vec3 } void main(void) { - mainVR(gl_FragColor, gl_FragCoord.xy, vec3(0.0), normalize(varPosition)); + mainVR(outFragColor, gl_FragCoord.xy, vec3(0.0), normalize(varPosition)); } diff --git a/libraries/render-utils/src/text/Font.cpp b/libraries/render-utils/src/text/Font.cpp index 3cedcdcbc1..0157d873d3 100644 --- a/libraries/render-utils/src/text/Font.cpp +++ b/libraries/render-utils/src/text/Font.cpp @@ -31,10 +31,10 @@ struct QuadBuilder { texMin + glm::vec2(0.0f, texSize.y)); vertices[1] = TextureVertex(min + glm::vec2(size.x, 0.0f), texMin + texSize); - vertices[2] = TextureVertex(min + size, - texMin + glm::vec2(texSize.x, 0.0f)); - vertices[3] = TextureVertex(min + glm::vec2(0.0f, size.y), + vertices[2] = TextureVertex(min + glm::vec2(0.0f, size.y), texMin); + vertices[3] = TextureVertex(min + size, + texMin + glm::vec2(texSize.x, 0.0f)); } QuadBuilder(const Glyph& glyph, const glm::vec2& offset) : QuadBuilder(offset + glm::vec2(glyph.offset.x, glyph.offset.y - glyph.size.y), glyph.size, @@ -303,12 +303,23 @@ void Font::rebuildVertices(float x, float y, const QString& str, const glm::vec2 // NOTE: Random guy on the internet's recommended triangle slices // Triangle tri1 = { v0, v1, v2 }; // Triangle tri2 = { v2, v3, v0 }; + + // The problem here being that the 4 vertices are { ll, lr, ul, ur }, a Z pattern + // Additionally, you want to ensure that the shared side vertices are used sequentially + // to improve cache locality + // + // 2 -- 3 + // | | + // | | + // 0 -- 1 + // + // { 0, 1, 2 } -> { 2, 1, 3 } quint16 indices[NUMBER_OF_INDICES_PER_QUAD]; indices[0] = verticesOffset + 0; indices[1] = verticesOffset + 1; - indices[2] = verticesOffset + 3; - indices[3] = verticesOffset + 1; - indices[4] = verticesOffset + 2; + indices[2] = verticesOffset + 2; + indices[3] = verticesOffset + 2; + indices[4] = verticesOffset + 1; indices[5] = verticesOffset + 3; _indicesBuffer->append(sizeof(indices), (const gpu::Byte*)indices); _numIndices += NUMBER_OF_INDICES_PER_QUAD; diff --git a/libraries/render/src/render/DrawStatus.cpp b/libraries/render/src/render/DrawStatus.cpp index cf3616a83a..0c1b92b559 100644 --- a/libraries/render/src/render/DrawStatus.cpp +++ b/libraries/render/src/render/DrawStatus.cpp @@ -132,9 +132,7 @@ void DrawStatus::run(const SceneContextPointer& sceneContext, const RenderContex Transform viewMat; args->_viewFrustum->evalProjectionMatrix(projMat); args->_viewFrustum->evalViewTransform(viewMat); - if (args->_renderMode == RenderArgs::MIRROR_RENDER_MODE) { - viewMat.postScale(glm::vec3(-1.0f, 1.0f, 1.0f)); - } + batch.setProjectionTransform(projMat); batch.setViewTransform(viewMat); batch.setModelTransform(Transform()); diff --git a/libraries/render/src/render/DrawTask.cpp b/libraries/render/src/render/DrawTask.cpp index 36ff302952..ff2cf6ff41 100755 --- a/libraries/render/src/render/DrawTask.cpp +++ b/libraries/render/src/render/DrawTask.cpp @@ -264,9 +264,7 @@ void DrawBackground::run(const SceneContextPointer& sceneContext, const RenderCo Transform viewMat; args->_viewFrustum->evalProjectionMatrix(projMat); args->_viewFrustum->evalViewTransform(viewMat); - if (args->_renderMode == RenderArgs::MIRROR_RENDER_MODE) { - viewMat.postScale(glm::vec3(-1.0f, 1.0f, 1.0f)); - } + batch.setProjectionTransform(projMat); batch.setViewTransform(viewMat); diff --git a/libraries/render/src/render/drawItemBounds.slf b/libraries/render/src/render/drawItemBounds.slf index b5d1a297bf..a4ade87b1c 100644 --- a/libraries/render/src/render/drawItemBounds.slf +++ b/libraries/render/src/render/drawItemBounds.slf @@ -11,9 +11,10 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -varying vec4 varColor; +in vec4 varColor; +out vec4 outFragColor; void main(void) { - gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0); + outFragColor = vec4(1.0, 1.0, 1.0, 1.0); } diff --git a/libraries/render/src/render/drawItemStatus.slf b/libraries/render/src/render/drawItemStatus.slf index dcf5d3ee25..4cc45db2ec 100644 --- a/libraries/render/src/render/drawItemStatus.slf +++ b/libraries/render/src/render/drawItemStatus.slf @@ -11,9 +11,10 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -varying vec4 varColor; +in vec4 varColor; +out vec4 outFragColor; void main(void) { - gl_FragColor = varColor; + outFragColor = varColor; } diff --git a/libraries/render/src/render/drawItemStatus.slv b/libraries/render/src/render/drawItemStatus.slv index 106a5684bb..b90daef76a 100644 --- a/libraries/render/src/render/drawItemStatus.slv +++ b/libraries/render/src/render/drawItemStatus.slv @@ -16,7 +16,7 @@ <$declareStandardTransform()$> -varying vec4 varColor; +out vec4 varColor; uniform vec3 inBoundPos; uniform vec3 inBoundDim; diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index afbf3eaf38..861034a6dc 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include @@ -370,8 +369,6 @@ void ScriptEngine::init() { // constants globalObject().setProperty("TREE_SCALE", newVariant(QVariant(TREE_SCALE))); - globalObject().setProperty("COLLISION_GROUP_ENVIRONMENT", newVariant(QVariant(COLLISION_GROUP_ENVIRONMENT))); - globalObject().setProperty("COLLISION_GROUP_AVATARS", newVariant(QVariant(COLLISION_GROUP_AVATARS))); } QScriptValue ScriptEngine::registerGlobalObject(const QString& name, QObject* object) { diff --git a/libraries/shared/CMakeLists.txt b/libraries/shared/CMakeLists.txt index 8deda7f4b1..00a80619bc 100644 --- a/libraries/shared/CMakeLists.txt +++ b/libraries/shared/CMakeLists.txt @@ -4,7 +4,17 @@ set(TARGET_NAME shared) # TODO: there isn't really a good reason to have Script linked here - let's get what is requiring it out (RegisteredMetaTypes.cpp) setup_hifi_library(Gui Network Script Widgets) +find_package(ZLIB REQUIRED) +target_link_libraries(${TARGET_NAME} ${ZLIB_LIBRARIES}) + add_dependency_external_projects(glm) find_package(GLM REQUIRED) -target_include_directories(${TARGET_NAME} PUBLIC ${GLM_INCLUDE_DIRS}) +target_include_directories(${TARGET_NAME} PUBLIC ${GLM_INCLUDE_DIRS} ${ZLIB_INCLUDE_DIRS}) +if (WIN32) + # Birarda will fix this when he finds it. + get_filename_component(ZLIB_LIB_DIR "${ZLIB_LIBRARIES}" DIRECTORY) + get_filename_component(ZLIB_DIR "${ZLIB_LIB_DIR}" DIRECTORY) + set(ZLIB_BIN_DIR "${ZLIB_DIR}/bin") + add_paths_to_fixup_libs(${ZLIB_BIN_DIR}) +endif () diff --git a/libraries/shared/src/AACubeShape.cpp b/libraries/shared/src/AACubeShape.cpp deleted file mode 100644 index 5c40b3bb64..0000000000 --- a/libraries/shared/src/AACubeShape.cpp +++ /dev/null @@ -1,76 +0,0 @@ -// -// AACubeShape.cpp -// libraries/shared/src -// -// Created by Andrew Meadows on 2014.08.22 -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include -#include - -#include "AACubeShape.h" -#include "NumericalConstants.h" // for SQUARE_ROOT_OF_3 - -glm::vec3 faceNormals[3] = { glm::vec3(1.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f) }; - -bool AACubeShape::findRayIntersection(RayIntersectionInfo& intersection) const { - // A = ray point - // B = cube center - glm::vec3 BA = _translation - intersection._rayStart; - - // check for ray intersection with cube's bounding sphere - // a = distance along line to closest approach to B - float a = glm::dot(intersection._rayDirection, BA); - // b2 = squared distance from cube center to point of closest approach - float b2 = glm::length2(a * intersection._rayDirection - BA); - // r = bounding radius of cube - float halfSide = 0.5f * _scale; - const float r = SQUARE_ROOT_OF_3 * halfSide; - if (b2 > r * r) { - // line doesn't hit cube's bounding sphere - return false; - } - - // check for tuncated/short ray - // maxLength = maximum possible distance between rayStart and center of cube - const float maxLength = glm::min(intersection._rayLength, intersection._hitDistance) + r; - if (a * a + b2 > maxLength * maxLength) { - // ray is not long enough to reach cube's bounding sphere - // NOTE: we don't fall in here when ray's length if FLT_MAX because maxLength^2 will be inf or nan - return false; - } - - // the trivial checks have been exhausted, so must trace to each face - bool hit = false; - for (int i = 0; i < 3; ++i) { - for (float sign = -1.0f; sign < 2.0f; sign += 2.0f) { - glm::vec3 faceNormal = sign * faceNormals[i]; - float rayDotPlane = glm::dot(intersection._rayDirection, faceNormal); - if (glm::abs(rayDotPlane) > EPSILON) { - float distanceToFace = (halfSide + glm::dot(BA, faceNormal)) / rayDotPlane; - if (distanceToFace >= 0.0f) { - glm::vec3 point = distanceToFace * intersection._rayDirection - BA; - int j = (i + 1) % 3; - int k = (i + 2) % 3; - glm::vec3 secondNormal = faceNormals[j]; - glm::vec3 thirdNormal = faceNormals[k]; - if (glm::abs(glm::dot(point, secondNormal)) > halfSide || - glm::abs(glm::dot(point, thirdNormal)) > halfSide) { - continue; - } - if (distanceToFace < intersection._hitDistance && distanceToFace < intersection._rayLength) { - intersection._hitDistance = distanceToFace; - intersection._hitNormal = faceNormal; - intersection._hitShape = const_cast(this); - hit = true; - } - } - } - } - } - return hit; -} diff --git a/libraries/shared/src/AACubeShape.h b/libraries/shared/src/AACubeShape.h deleted file mode 100644 index da7ba9d53f..0000000000 --- a/libraries/shared/src/AACubeShape.h +++ /dev/null @@ -1,50 +0,0 @@ -// -// AACubeShape.h -// libraries/shared/src -// -// Created by Andrew Meadows on 2014.08.22 -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_AACubeShape_h -#define hifi_AACubeShape_h - -#include -#include "Shape.h" - -class AACubeShape : public Shape { -public: - AACubeShape() : Shape(AACUBE_SHAPE), _scale(1.0f) { } - AACubeShape(float scale) : Shape(AACUBE_SHAPE), _scale(scale) { } - AACubeShape(float scale, const glm::vec3& position) : Shape(AACUBE_SHAPE, position), _scale(scale) { } - - virtual ~AACubeShape() { } - - float getScale() const { return _scale; } - void setScale(float scale) { _scale = scale; } - - bool findRayIntersection(RayIntersectionInfo& intersection) const; - - float getVolume() const { return _scale * _scale * _scale; } - virtual QDebug& dumpToDebug(QDebug& debugConext) const; - -protected: - float _scale; -}; - -inline QDebug& AACubeShape::dumpToDebug(QDebug& debugConext) const { - debugConext << "AACubeShape[ (" - << "type: " << getType() - << "position: " - << getTranslation().x << ", " << getTranslation().y << ", " << getTranslation().z - << "scale: " - << getScale() - << "]"; - - return debugConext; -} - -#endif // hifi_AACubeShape_h diff --git a/libraries/shared/src/CapsuleShape.cpp b/libraries/shared/src/CapsuleShape.cpp deleted file mode 100644 index ec71ebadbb..0000000000 --- a/libraries/shared/src/CapsuleShape.cpp +++ /dev/null @@ -1,218 +0,0 @@ -// -// CapsuleShape.cpp -// libraries/shared/src -// -// Created by Andrew Meadows on 02/20/2014. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include -#include - -#include "CapsuleShape.h" -#include "GeometryUtil.h" -#include "NumericalConstants.h" - -CapsuleShape::CapsuleShape() : Shape(CAPSULE_SHAPE), _radius(0.0f), _halfHeight(0.0f) {} - -CapsuleShape::CapsuleShape(float radius, float halfHeight) : Shape(CAPSULE_SHAPE), - _radius(radius), _halfHeight(halfHeight) { - updateBoundingRadius(); -} - -CapsuleShape::CapsuleShape(float radius, float halfHeight, const glm::vec3& position, const glm::quat& rotation) : - Shape(CAPSULE_SHAPE, position, rotation), _radius(radius), _halfHeight(halfHeight) { - updateBoundingRadius(); -} - -CapsuleShape::CapsuleShape(float radius, const glm::vec3& startPoint, const glm::vec3& endPoint) : - Shape(CAPSULE_SHAPE), _radius(radius), _halfHeight(0.0f) { - setEndPoints(startPoint, endPoint); -} - -/// \param[out] startPoint is the center of start cap -void CapsuleShape::getStartPoint(glm::vec3& startPoint) const { - startPoint = _translation - _rotation * glm::vec3(0.0f, _halfHeight, 0.0f); -} - -/// \param[out] endPoint is the center of the end cap -void CapsuleShape::getEndPoint(glm::vec3& endPoint) const { - endPoint = _translation + _rotation * glm::vec3(0.0f, _halfHeight, 0.0f); -} - -void CapsuleShape::computeNormalizedAxis(glm::vec3& axis) const { - // default axis of a capsule is along the yAxis - axis = _rotation * DEFAULT_CAPSULE_AXIS; -} - -void CapsuleShape::setRadius(float radius) { - _radius = radius; - updateBoundingRadius(); -} - -void CapsuleShape::setHalfHeight(float halfHeight) { - _halfHeight = halfHeight; - updateBoundingRadius(); -} - -void CapsuleShape::setRadiusAndHalfHeight(float radius, float halfHeight) { - _radius = radius; - _halfHeight = halfHeight; - updateBoundingRadius(); -} - -void CapsuleShape::setEndPoints(const glm::vec3& startPoint, const glm::vec3& endPoint) { - glm::vec3 axis = endPoint - startPoint; - _translation = 0.5f * (endPoint + startPoint); - float height = glm::length(axis); - if (height > EPSILON) { - _halfHeight = 0.5f * height; - axis /= height; - _rotation = computeNewRotation(axis); - } - updateBoundingRadius(); -} - -// helper -bool findRayIntersectionWithCap(const glm::vec3& sphereCenter, float sphereRadius, - const glm::vec3& capsuleCenter, RayIntersectionInfo& intersection) { - float r2 = sphereRadius * sphereRadius; - - // compute closest approach (CA) - float a = glm::dot(sphereCenter - intersection._rayStart, intersection._rayDirection); // a = distance from ray-start to CA - float b2 = glm::distance2(sphereCenter, intersection._rayStart + a * intersection._rayDirection); // b2 = squared distance from sphere-center to CA - if (b2 > r2) { - // ray does not hit sphere - return false; - } - float c = sqrtf(r2 - b2); // c = distance from CA to sphere surface along intersection._rayDirection - float d2 = glm::distance2(intersection._rayStart, sphereCenter); // d2 = squared distance from sphere-center to ray-start - float distance = FLT_MAX; - if (a < 0.0f) { - // ray points away from sphere-center - if (d2 > r2) { - // ray starts outside sphere - return false; - } - // ray starts inside sphere - distance = c + a; - } else if (d2 > r2) { - // ray starts outside sphere - distance = a - c; - } else { - // ray starts inside sphere - distance = a + c; - } - if (distance > 0.0f && distance < intersection._rayLength && distance < intersection._hitDistance) { - glm::vec3 sphereCenterToHitPoint = intersection._rayStart + distance * intersection._rayDirection - sphereCenter; - if (glm::dot(sphereCenterToHitPoint, sphereCenter - capsuleCenter) >= 0.0f) { - intersection._hitDistance = distance; - intersection._hitNormal = glm::normalize(sphereCenterToHitPoint); - return true; - } - } - return false; -} - -bool CapsuleShape::findRayIntersectionWithCaps(const glm::vec3& capsuleCenter, RayIntersectionInfo& intersection) const { - glm::vec3 capCenter; - getStartPoint(capCenter); - bool hit = findRayIntersectionWithCap(capCenter, _radius, capsuleCenter, intersection); - getEndPoint(capCenter); - hit = findRayIntersectionWithCap(capCenter, _radius, capsuleCenter, intersection) || hit; - if (hit) { - intersection._hitShape = const_cast(this); - } - return hit; -} - -bool CapsuleShape::findRayIntersection(RayIntersectionInfo& intersection) const { - // ray is U, capsule is V - glm::vec3 axisV; - computeNormalizedAxis(axisV); - glm::vec3 centerV = getTranslation(); - - // first handle parallel case - float uDotV = glm::dot(axisV, intersection._rayDirection); - glm::vec3 UV = intersection._rayStart - centerV; - if (glm::abs(1.0f - glm::abs(uDotV)) < EPSILON) { - // line and cylinder are parallel - float distanceV = glm::dot(UV, intersection._rayDirection); - if (glm::length2(UV - distanceV * intersection._rayDirection) <= _radius * _radius) { - // ray is inside cylinder's radius and might intersect caps - return findRayIntersectionWithCaps(centerV, intersection); - } - return false; - } - - // Given a line with point 'U' and normalized direction 'u' and - // a cylinder with axial point 'V', radius 'r', and normalized direction 'v' - // the intersection of the two is on the line at distance 't' from 'U'. - // - // Determining the values of t reduces to solving a quadratic equation: At^2 + Bt + C = 0 - // - // where: - // - // UV = U-V - // w = u-(u.v)v - // Q = UV-(UV.v)v - // - // A = w^2 - // B = 2(w.Q) - // C = Q^2 - r^2 - - glm::vec3 w = intersection._rayDirection - uDotV * axisV; - glm::vec3 Q = UV - glm::dot(UV, axisV) * axisV; - - // we save a few multiplies by storing 2*A rather than just A - float A2 = 2.0f * glm::dot(w, w); - float B = 2.0f * glm::dot(w, Q); - - // since C is only ever used once (in the determinant) we compute it inline - float determinant = B * B - 2.0f * A2 * (glm::dot(Q, Q) - _radius * _radius); - if (determinant < 0.0f) { - return false; - } - float hitLow = (-B - sqrtf(determinant)) / A2; - float hitHigh = -(hitLow + 2.0f * B / A2); - - if (hitLow > hitHigh) { - // re-arrange so hitLow is always the smaller value - float temp = hitHigh; - hitHigh = hitLow; - hitLow = temp; - } - if (hitLow < 0.0f) { - if (hitHigh < 0.0f) { - // capsule is completely behind rayStart - return false; - } - hitLow = hitHigh; - } - - glm::vec3 p = intersection._rayStart + hitLow * intersection._rayDirection; - float d = glm::dot(p - centerV, axisV); - if (glm::abs(d) <= getHalfHeight()) { - // we definitely hit the cylinder wall - intersection._hitDistance = hitLow; - intersection._hitNormal = glm::normalize(p - centerV - d * axisV); - intersection._hitShape = const_cast(this); - return true; - } - - // ray still might hit the caps - return findRayIntersectionWithCaps(centerV, intersection); -} - -// static -glm::quat CapsuleShape::computeNewRotation(const glm::vec3& newAxis) { - float angle = glm::angle(newAxis, DEFAULT_CAPSULE_AXIS); - if (angle > EPSILON) { - glm::vec3 rotationAxis = glm::normalize(glm::cross(DEFAULT_CAPSULE_AXIS, newAxis)); - return glm::angleAxis(angle, rotationAxis); - } - return glm::quat(); -} diff --git a/libraries/shared/src/CapsuleShape.h b/libraries/shared/src/CapsuleShape.h deleted file mode 100644 index 32c09696d7..0000000000 --- a/libraries/shared/src/CapsuleShape.h +++ /dev/null @@ -1,62 +0,0 @@ -// -// CapsuleShape.h -// libraries/shared/src -// -// Created by Andrew Meadows on 02/20/2014. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_CapsuleShape_h -#define hifi_CapsuleShape_h - -#include "NumericalConstants.h" -#include "Shape.h" - -// default axis of CapsuleShape is Y-axis -const glm::vec3 DEFAULT_CAPSULE_AXIS(0.0f, 1.0f, 0.0f); - - -class CapsuleShape : public Shape { -public: - CapsuleShape(); - CapsuleShape(float radius, float halfHeight); - CapsuleShape(float radius, float halfHeight, const glm::vec3& position, const glm::quat& rotation); - CapsuleShape(float radius, const glm::vec3& startPoint, const glm::vec3& endPoint); - - virtual ~CapsuleShape() {} - - float getRadius() const { return _radius; } - virtual float getHalfHeight() const { return _halfHeight; } - - /// \param[out] startPoint is the center of start cap - virtual void getStartPoint(glm::vec3& startPoint) const; - - /// \param[out] endPoint is the center of the end cap - virtual void getEndPoint(glm::vec3& endPoint) const; - - virtual void computeNormalizedAxis(glm::vec3& axis) const; - - void setRadius(float radius); - virtual void setHalfHeight(float height); - virtual void setRadiusAndHalfHeight(float radius, float height); - - /// Sets the endpoints and updates center, rotation, and halfHeight to agree. - virtual void setEndPoints(const glm::vec3& startPoint, const glm::vec3& endPoint); - - bool findRayIntersection(RayIntersectionInfo& intersection) const; - - virtual float getVolume() const { return (PI * _radius * _radius) * (1.3333333333f * _radius + getHalfHeight()); } - -protected: - bool findRayIntersectionWithCaps(const glm::vec3& capsuleCenter, RayIntersectionInfo& intersection) const; - virtual void updateBoundingRadius() { _boundingRadius = _radius + getHalfHeight(); } - static glm::quat computeNewRotation(const glm::vec3& newAxis); - - float _radius; - float _halfHeight; -}; - -#endif // hifi_CapsuleShape_h diff --git a/libraries/shared/src/CollisionInfo.cpp b/libraries/shared/src/CollisionInfo.cpp deleted file mode 100644 index 7f145efb20..0000000000 --- a/libraries/shared/src/CollisionInfo.cpp +++ /dev/null @@ -1,110 +0,0 @@ -// -// CollisionInfo.cpp -// libraries/shared/src -// -// Created by Andrew Meadows on 02/14/2014. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include "CollisionInfo.h" -#include "NumericalConstants.h" -#include "Shape.h" - -CollisionInfo::CollisionInfo() : - _data(NULL), - _intData(0), - _shapeA(NULL), - _shapeB(NULL), - _damping(0.0f), - _elasticity(1.0f), - _contactPoint(0.0f), - _penetration(0.0f), - _addedVelocity(0.0f) { -} - -quint64 CollisionInfo::getShapePairKey() const { - if (_shapeB == NULL || _shapeA == NULL) { - // zero is an invalid key - return 0; - } - quint32 idA = _shapeA->getID(); - quint32 idB = _shapeB->getID(); - return idA < idB ? ((quint64)idA << 32) + (quint64)idB : ((quint64)idB << 32) + (quint64)idA; -} - -CollisionList::CollisionList(int maxSize) : - _maxSize(maxSize), - _size(0) { - _collisions.resize(_maxSize); -} - -void CollisionInfo::apply() { - assert(_shapeA); - // NOTE: Shape::computeEffectiveMass() has side effects: computes and caches partial Lagrangian coefficients - Shape* shapeA = const_cast(_shapeA); - float massA = shapeA->computeEffectiveMass(_penetration, _contactPoint); - float massB = MAX_SHAPE_MASS; - float totalMass = massA + massB; - if (_shapeB) { - Shape* shapeB = const_cast(_shapeB); - massB = shapeB->computeEffectiveMass(-_penetration, _contactPoint - _penetration); - totalMass = massA + massB; - if (totalMass < EPSILON) { - massA = massB = 1.0f; - totalMass = 2.0f; - } - // remember that _penetration points from A into B - shapeB->accumulateDelta(massA / totalMass, _penetration); - } - // NOTE: Shape::accumulateDelta() uses the coefficients from previous call to Shape::computeEffectiveMass() - // remember that _penetration points from A into B - shapeA->accumulateDelta(massB / totalMass, -_penetration); -} - -CollisionInfo* CollisionList::getNewCollision() { - // return pointer to existing CollisionInfo, or NULL of list is full - return (_size < _maxSize) ? &(_collisions[_size++]) : NULL; -} - -void CollisionList::deleteLastCollision() { - if (_size > 0) { - --_size; - } -} - -CollisionInfo* CollisionList::getCollision(int index) { - return (index > -1 && index < _size) ? &(_collisions[index]) : NULL; -} - -CollisionInfo* CollisionList::getLastCollision() { - return (_size > 0) ? &(_collisions[_size - 1]) : NULL; -} - -void CollisionList::clear() { - // we rely on the external context to properly set or clear the data members of CollisionInfos - /* - for (int i = 0; i < _size; ++i) { - // we only clear the important stuff - CollisionInfo& collision = _collisions[i]; - //collision._data = NULL; - //collision._intData = 0; - //collision._floatDAta = 0.0f; - //collision._vecData = glm::vec3(0.0f); - //collision._shapeA = NULL; - //collision._shapeB = NULL; - //collision._damping; - //collision._elasticity; - //collision._contactPoint; - //collision._penetration; - //collision._addedVelocity; - } - */ - _size = 0; -} - -CollisionInfo* CollisionList::operator[](int index) { - return (index > -1 && index < _size) ? &(_collisions[index]) : NULL; -} diff --git a/libraries/shared/src/CollisionInfo.h b/libraries/shared/src/CollisionInfo.h deleted file mode 100644 index e6daf949b3..0000000000 --- a/libraries/shared/src/CollisionInfo.h +++ /dev/null @@ -1,101 +0,0 @@ -// -// CollisionInfo.h -// libraries/shared/src -// -// Created by Andrew Meadows on 02/14/2014. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_CollisionInfo_h -#define hifi_CollisionInfo_h - -#include -#include - -#include -#include - -class Shape; - -const quint32 COLLISION_GROUP_ENVIRONMENT = 1U << 0; -const quint32 COLLISION_GROUP_AVATARS = 1U << 1; -const quint32 COLLISION_GROUP_VOXELS = 1U << 2; -const quint32 VALID_COLLISION_GROUPS = 0x0f; - -// CollisionInfo contains details about the collision between two things: BodyA and BodyB. -// The assumption is that the context that analyzes the collision knows about BodyA but -// does not necessarily know about BodyB. Hence the data storred in the CollisionInfo -// is expected to be relative to BodyA (for example the penetration points from A into B). - -class CollisionInfo { -public: - CollisionInfo(); - ~CollisionInfo() {} - - // TODO: Andrew to get rid of these data members - void* _data; - int _intData; - float _floatData; - glm::vec3 _vecData; - - /// accumulates position changes for the shapes in this collision to resolve penetration - void apply(); - - Shape* getShapeA() const { return const_cast(_shapeA); } - Shape* getShapeB() const { return const_cast(_shapeB); } - - /// \return unique key for shape pair - quint64 getShapePairKey() const; - - const Shape* _shapeA; // pointer to shapeA in this collision - const Shape* _shapeB; // pointer to shapeB in this collision - - void* _extraData; // pointer to extraData for this collision, opaque to the collision info, useful for external data - - float _damping; // range [0,1] of friction coeficient - float _elasticity; // range [0,1] of energy conservation - glm::vec3 _contactPoint; // world-frame point on BodyA that is deepest into BodyB - glm::vec3 _penetration; // depth that BodyA penetrates into BodyB - glm::vec3 _addedVelocity; // velocity of BodyB -}; - -// CollisionList is intended to be a recycled container. Fill the CollisionInfo's, -// use them, and then clear them for the next frame or context. - -class CollisionList { -public: - CollisionList(int maxSize); - - /// \return pointer to next collision. NULL if list is full. - CollisionInfo* getNewCollision(); - - /// \forget about collision at the end - void deleteLastCollision(); - - /// \return pointer to collision by index. NULL if index out of bounds. - CollisionInfo* getCollision(int index); - - /// \return pointer to last collision on the list. NULL if list is empty - CollisionInfo* getLastCollision(); - - /// \return true if list is full - bool isFull() const { return _size == _maxSize; } - - /// \return number of valid collisions - int size() const { return _size; } - - /// Clear valid collisions. - void clear(); - - CollisionInfo* operator[](int index); - -private: - int _maxSize; // the container cannot get larger than this - int _size; // the current number of valid collisions in the list - QVector _collisions; -}; - -#endif // hifi_CollisionInfo_h diff --git a/libraries/shared/src/GLHelpers.cpp b/libraries/shared/src/GLHelpers.cpp index f2371e49bb..f67f9e9120 100644 --- a/libraries/shared/src/GLHelpers.cpp +++ b/libraries/shared/src/GLHelpers.cpp @@ -10,7 +10,6 @@ QSurfaceFormat getDefaultOpenGlSurfaceFormat() { #ifdef DEBUG format.setOption(QSurfaceFormat::DebugContext); #endif - // FIXME move to core as soon as possible - format.setProfile(QSurfaceFormat::OpenGLContextProfile::CompatibilityProfile); + format.setProfile(QSurfaceFormat::OpenGLContextProfile::CoreProfile); return format; } diff --git a/libraries/shared/src/GeometryUtil.cpp b/libraries/shared/src/GeometryUtil.cpp index afb5890d05..b612fe0696 100644 --- a/libraries/shared/src/GeometryUtil.cpp +++ b/libraries/shared/src/GeometryUtil.cpp @@ -11,11 +11,10 @@ #include #include +#include #include "GeometryUtil.h" #include "NumericalConstants.h" -#include "PlaneShape.h" -#include "RayIntersectionInfo.h" glm::vec3 computeVectorFromPointToSegment(const glm::vec3& point, const glm::vec3& start, const glm::vec3& end) { // compute the projection of the point vector onto the segment vector @@ -496,31 +495,45 @@ void PolygonClip::copyCleanArray(int& lengthA, glm::vec2* vertexArrayA, int& len bool findRayRectangleIntersection(const glm::vec3& origin, const glm::vec3& direction, const glm::quat& rotation, const glm::vec3& position, const glm::vec2& dimensions, float& distance) { - RayIntersectionInfo rayInfo; - rayInfo._rayStart = origin; - rayInfo._rayDirection = direction; - rayInfo._rayLength = std::numeric_limits::max(); - - PlaneShape plane; - const glm::vec3 UNROTATED_NORMAL(0.0f, 0.0f, -1.0f); glm::vec3 normal = rotation * UNROTATED_NORMAL; - plane.setNormal(normal); - plane.setPoint(position); // the position is definitely a point on our plane - bool intersects = plane.findRayIntersection(rayInfo); + bool maybeIntersects = false; + float denominator = glm::dot(normal, direction); + glm::vec3 offset = origin - position; + float normDotOffset = glm::dot(offset, normal); + float d = 0.0f; + if (fabsf(denominator) < EPSILON) { + // line is perpendicular to plane + if (fabsf(normDotOffset) < EPSILON) { + // ray starts on the plane + maybeIntersects = true; - if (intersects) { - distance = rayInfo._hitDistance; - - glm::vec3 hitPosition = origin + (distance * direction); - glm::vec3 localHitPosition = glm::inverse(rotation) * (hitPosition - position); - - glm::vec2 halfDimensions = 0.5f * dimensions; - - intersects = -halfDimensions.x <= localHitPosition.x && localHitPosition.x <= halfDimensions.x - && -halfDimensions.y <= localHitPosition.y && localHitPosition.y <= halfDimensions.y; + // compute distance to closest approach + d = - glm::dot(offset, direction); // distance to closest approach of center of rectangle + if (d < 0.0f) { + // ray points away from center of rectangle, so ray's start is the closest approach + d = 0.0f; + } + } + } else { + d = - normDotOffset / denominator; + if (d > 0.0f) { + // ray points toward plane + maybeIntersects = true; + } } - return intersects; + if (maybeIntersects) { + glm::vec3 hitPosition = origin + (d * direction); + glm::vec3 localHitPosition = glm::inverse(rotation) * (hitPosition - position); + glm::vec2 halfDimensions = 0.5f * dimensions; + if (fabsf(localHitPosition.x) < halfDimensions.x && fabsf(localHitPosition.y) < halfDimensions.y) { + // only update distance on intersection + distance = d; + return true; + } + } + + return false; } diff --git a/libraries/shared/src/Gzip.cpp b/libraries/shared/src/Gzip.cpp new file mode 100644 index 0000000000..a77f459fc9 --- /dev/null +++ b/libraries/shared/src/Gzip.cpp @@ -0,0 +1,153 @@ +// +// Gzip.cpp +// libraries/shared/src +// +// Created by Seth Alves on 2015-08-03. +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include +#include "Gzip.h" + +const int GZIP_WINDOWS_BIT = 31; +const int GZIP_CHUNK_SIZE = 4096; +const int DEFAULT_MEM_LEVEL = 8; + +bool gunzip(QByteArray source, QByteArray &destination) { + destination.clear(); + if (source.length() == 0) { + return true; + } + + z_stream strm; + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + strm.avail_in = 0; + strm.next_in = Z_NULL; + + int status = inflateInit2(&strm, GZIP_WINDOWS_BIT); + + if (status != Z_OK) { + return false; + } + + char *sourceData = source.data(); + int sourceDataLength = source.length(); + + for (;;) { + int chunkSize = qMin(GZIP_CHUNK_SIZE, sourceDataLength); + if (chunkSize <= 0) { + break; + } + + strm.next_in = (unsigned char*)sourceData; + strm.avail_in = chunkSize; + sourceData += chunkSize; + sourceDataLength -= chunkSize; + + for (;;) { + char out[GZIP_CHUNK_SIZE]; + + strm.next_out = (unsigned char*)out; + strm.avail_out = GZIP_CHUNK_SIZE; + + status = inflate(&strm, Z_NO_FLUSH); + + switch (status) { + case Z_NEED_DICT: + status = Z_DATA_ERROR; + case Z_DATA_ERROR: + case Z_MEM_ERROR: + case Z_STREAM_ERROR: + inflateEnd(&strm); + return false; + } + + int available = (GZIP_CHUNK_SIZE - strm.avail_out); + if (available > 0) { + destination.append((char*)out, available); + } + + if (strm.avail_out != 0) { + break; + } + } + + if (status == Z_STREAM_END) { + break; + } + } + + inflateEnd(&strm); + return status == Z_STREAM_END; +} + +bool gzip(QByteArray source, QByteArray &destination, int compressionLevel) { + destination.clear(); + if (source.length() == 0) { + return true; + } + + int flushOrFinish = 0; + z_stream strm; + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + strm.next_in = Z_NULL; + strm.avail_in = 0; + + int status = deflateInit2(&strm, + qMax(Z_DEFAULT_COMPRESSION, qMin(9, compressionLevel)), + Z_DEFLATED, + GZIP_WINDOWS_BIT, + DEFAULT_MEM_LEVEL, + Z_DEFAULT_STRATEGY); + if (status != Z_OK) { + return false; + } + char *sourceData = source.data(); + int sourceDataLength = source.length(); + + for (;;) { + int chunkSize = qMin(GZIP_CHUNK_SIZE, sourceDataLength); + strm.next_in = (unsigned char*)sourceData; + strm.avail_in = chunkSize; + sourceData += chunkSize; + sourceDataLength -= chunkSize; + + if (sourceDataLength <= 0) { + flushOrFinish = Z_FINISH; + } else { + flushOrFinish = Z_NO_FLUSH; + } + + for (;;) { + char out[GZIP_CHUNK_SIZE]; + strm.next_out = (unsigned char*)out; + strm.avail_out = GZIP_CHUNK_SIZE; + status = deflate(&strm, flushOrFinish); + if (status == Z_STREAM_ERROR) { + deflateEnd(&strm); + return false; + } + int available = (GZIP_CHUNK_SIZE - strm.avail_out); + if (available > 0) { + destination.append((char*)out, available); + } + if (strm.avail_out != 0) { + break; + } + } + + if (flushOrFinish == Z_FINISH) { + break; + } + } + + deflateEnd(&strm); + return status == Z_STREAM_END; +} diff --git a/libraries/shared/src/Gzip.h b/libraries/shared/src/Gzip.h new file mode 100644 index 0000000000..e3ed6bbbea --- /dev/null +++ b/libraries/shared/src/Gzip.h @@ -0,0 +1,27 @@ +// +// Gzip.h +// libraries/shared/src +// +// Created by Seth Alves on 2015-08-03. +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef GZIP_H +#define GZIP_H + +#include + +// The compression level must be Z_DEFAULT_COMPRESSION (-1), or between 0 and +// 9: 1 gives best speed, 9 gives best compression, 0 gives no +// compression at all (the input data is simply copied a block at a +// time). Z_DEFAULT_COMPRESSION requests a default compromise between +// speed and compression (currently equivalent to level 6). + +bool gzip(QByteArray source, QByteArray &destination, int compressionLevel = -1); // -1 is Z_DEFAULT_COMPRESSION + +bool gunzip(QByteArray source, QByteArray &destination); + +#endif diff --git a/libraries/shared/src/ListShape.cpp b/libraries/shared/src/ListShape.cpp deleted file mode 100644 index 255330c713..0000000000 --- a/libraries/shared/src/ListShape.cpp +++ /dev/null @@ -1,90 +0,0 @@ -// -// ListShape.cpp -// libraries/shared/src -// -// Created by Andrew Meadows on 02/20/2014. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include "ListShape.h" - -// ListShapeEntry - -void ListShapeEntry::updateTransform(const glm::vec3& rootPosition, const glm::quat& rootRotation) { - _shape->setTranslation(rootPosition + rootRotation * _localPosition); - _shape->setRotation(_localRotation * rootRotation); -} - -// ListShape - -ListShape::~ListShape() { - clear(); -} - -void ListShape::setTranslation(const glm::vec3& position) { - _subShapeTransformsAreDirty = true; - Shape::setTranslation(position); -} - -void ListShape::setRotation(const glm::quat& rotation) { - _subShapeTransformsAreDirty = true; - Shape::setRotation(rotation); -} - -const Shape* ListShape::getSubShape(int index) const { - if (index < 0 || index > _subShapeEntries.size()) { - return NULL; - } - return _subShapeEntries[index]._shape; -} - -void ListShape::updateSubTransforms() { - if (_subShapeTransformsAreDirty) { - for (int i = 0; i < _subShapeEntries.size(); ++i) { - _subShapeEntries[i].updateTransform(_translation, _rotation); - } - _subShapeTransformsAreDirty = false; - } -} - -void ListShape::addShape(Shape* shape, const glm::vec3& localPosition, const glm::quat& localRotation) { - if (shape) { - ListShapeEntry entry; - entry._shape = shape; - entry._localPosition = localPosition; - entry._localRotation = localRotation; - _subShapeEntries.push_back(entry); - } -} - -void ListShape::setShapes(QVector& shapes) { - clear(); - _subShapeEntries.swap(shapes); - // TODO: audit our new list of entries and delete any that have null pointers - computeBoundingRadius(); -} - -void ListShape::clear() { - // the ListShape owns its subShapes, so they need to be deleted - for (int i = 0; i < _subShapeEntries.size(); ++i) { - delete _subShapeEntries[i]._shape; - } - _subShapeEntries.clear(); - setBoundingRadius(0.0f); -} - -void ListShape::computeBoundingRadius() { - float maxRadius = 0.0f; - for (int i = 0; i < _subShapeEntries.size(); ++i) { - ListShapeEntry& entry = _subShapeEntries[i]; - float radius = glm::length(entry._localPosition) + entry._shape->getBoundingRadius(); - if (radius > maxRadius) { - maxRadius = radius; - } - } - setBoundingRadius(maxRadius); -} - diff --git a/libraries/shared/src/ListShape.h b/libraries/shared/src/ListShape.h deleted file mode 100644 index 6352ef3f07..0000000000 --- a/libraries/shared/src/ListShape.h +++ /dev/null @@ -1,72 +0,0 @@ -// -// ListShape.h -// libraries/shared/src -// -// Created by Andrew Meadows on 02/20/2014. -// Copyright 2014 High Fidelity, Inc. -// -// ListShape: A collection of shapes, each with a local transform. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_ListShape_h -#define hifi_ListShape_h - -#include - -#include -#include -#include - -#include "Shape.h" - - -class ListShapeEntry { -public: - void updateTransform(const glm::vec3& position, const glm::quat& rotation); - - Shape* _shape; - glm::vec3 _localPosition; - glm::quat _localRotation; -}; - -class ListShape : public Shape { -public: - - ListShape() : Shape(LIST_SHAPE), _subShapeEntries(), _subShapeTransformsAreDirty(false) {} - - ListShape(const glm::vec3& position, const glm::quat& rotation) : - Shape(LIST_SHAPE, position, rotation), _subShapeEntries(), _subShapeTransformsAreDirty(false) {} - - ~ListShape(); - - void setTranslation(const glm::vec3& position); - void setRotation(const glm::quat& rotation); - - const Shape* getSubShape(int index) const; - - void updateSubTransforms(); - - int size() const { return _subShapeEntries.size(); } - - void addShape(Shape* shape, const glm::vec3& localPosition, const glm::quat& localRotation); - - void setShapes(QVector& shapes); - - // TODO: either implement this or remove ListShape altogether - bool findRayIntersection(RayIntersectionInfo& intersection) const { return false; } - -protected: - void clear(); - void computeBoundingRadius(); - - QVector _subShapeEntries; - bool _subShapeTransformsAreDirty; - -private: - ListShape(const ListShape& otherList); // don't implement this -}; - -#endif // hifi_ListShape_h diff --git a/libraries/shared/src/PlaneShape.cpp b/libraries/shared/src/PlaneShape.cpp deleted file mode 100644 index cad04afa42..0000000000 --- a/libraries/shared/src/PlaneShape.cpp +++ /dev/null @@ -1,78 +0,0 @@ -// -// PlaneShape.cpp -// libraries/shared/src -// -// Created by Andrzej Kapolka on 4/10/2014. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include "GLMHelpers.h" -#include "NumericalConstants.h" -#include "PlaneShape.h" - -const glm::vec3 UNROTATED_NORMAL(0.0f, 1.0f, 0.0f); - -PlaneShape::PlaneShape(const glm::vec4& coefficients) : - Shape(PLANE_SHAPE) { - - glm::vec3 normal = glm::vec3(coefficients); - _translation = -normal * coefficients.w; - - float angle = acosf(glm::dot(normal, UNROTATED_NORMAL)); - if (angle > EPSILON) { - if (angle > PI - EPSILON) { - _rotation = glm::angleAxis(PI, glm::vec3(1.0f, 0.0f, 0.0f)); - } else { - _rotation = glm::angleAxis(angle, glm::normalize(glm::cross(UNROTATED_NORMAL, normal))); - } - } -} - -glm::vec3 PlaneShape::getNormal() const { - return _rotation * UNROTATED_NORMAL; -} - -void PlaneShape::setNormal(const glm::vec3& direction) { - glm::vec3 oldTranslation = _translation; - _rotation = rotationBetween(UNROTATED_NORMAL, direction); - glm::vec3 normal = getNormal(); - _translation = glm::dot(oldTranslation, normal) * normal; -} - -void PlaneShape::setPoint(const glm::vec3& point) { - glm::vec3 normal = getNormal(); - _translation = glm::dot(point, normal) * normal; -} - -glm::vec4 PlaneShape::getCoefficients() const { - glm::vec3 normal = _rotation * UNROTATED_NORMAL; - return glm::vec4(normal.x, normal.y, normal.z, -glm::dot(normal, _translation)); -} - -bool PlaneShape::findRayIntersection(RayIntersectionInfo& intersection) const { - glm::vec3 n = getNormal(); - float denominator = glm::dot(n, intersection._rayDirection); - if (fabsf(denominator) < EPSILON) { - // line is parallel to plane - if (glm::dot(_translation - intersection._rayStart, n) < EPSILON) { - // ray starts on the plane - intersection._hitDistance = 0.0f; - intersection._hitNormal = n; - intersection._hitShape = const_cast(this); - return true; - } - } else { - float d = glm::dot(_translation - intersection._rayStart, n) / denominator; - if (d > 0.0f && d < intersection._rayLength && d < intersection._hitDistance) { - // ray points toward plane - intersection._hitDistance = d; - intersection._hitNormal = n; - intersection._hitShape = const_cast(this); - return true; - } - } - return false; -} diff --git a/libraries/shared/src/PlaneShape.h b/libraries/shared/src/PlaneShape.h deleted file mode 100644 index 8d6de326af..0000000000 --- a/libraries/shared/src/PlaneShape.h +++ /dev/null @@ -1,30 +0,0 @@ -// -// PlaneShape.h -// libraries/shared/src -// -// Created by Andrzej Kapolka on 4/9/2014. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_PlaneShape_h -#define hifi_PlaneShape_h - -#include "Shape.h" - -class PlaneShape : public Shape { -public: - PlaneShape(const glm::vec4& coefficients = glm::vec4(0.0f, 1.0f, 0.0f, 0.0f)); - - glm::vec3 getNormal() const; - glm::vec4 getCoefficients() const; - - void setNormal(const glm::vec3& normal); - void setPoint(const glm::vec3& point); - - bool findRayIntersection(RayIntersectionInfo& intersection) const; -}; - -#endif // hifi_PlaneShape_h diff --git a/libraries/shared/src/RayIntersectionInfo.h b/libraries/shared/src/RayIntersectionInfo.h deleted file mode 100644 index 06ec0aceaa..0000000000 --- a/libraries/shared/src/RayIntersectionInfo.h +++ /dev/null @@ -1,37 +0,0 @@ -// -// RayIntersectionInfo.h -// libraries/physcis/src -// -// Created by Andrew Meadows 2014.09.09 -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_RayIntersectionInfo_h -#define hifi_RayIntersectionInfo_h - -#include - -class Shape; - -class RayIntersectionInfo { -public: - RayIntersectionInfo() : _rayStart(0.0f), _rayDirection(1.0f, 0.0f, 0.0f), _rayLength(FLT_MAX), - _hitDistance(FLT_MAX), _hitNormal(1.0f, 0.0f, 0.0f), _hitShape(NULL) { } - - glm::vec3 getIntersectionPoint() const { return _rayStart + _hitDistance * _rayDirection; } - - // input - glm::vec3 _rayStart; - glm::vec3 _rayDirection; - float _rayLength; - - // output - float _hitDistance; - glm::vec3 _hitNormal; - Shape* _hitShape; -}; - -#endif // hifi_RayIntersectionInfo_h diff --git a/libraries/shared/src/Shape.h b/libraries/shared/src/Shape.h deleted file mode 100644 index 048b8d7257..0000000000 --- a/libraries/shared/src/Shape.h +++ /dev/null @@ -1,144 +0,0 @@ -// -// Shape.h -// libraries/shared/src -// -// Created by Andrew Meadows on 2014. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_Shape_h -#define hifi_Shape_h - -#include -#include -#include -#include -#include - -#include "RayIntersectionInfo.h" - -class PhysicsEntity; - -const float MAX_SHAPE_MASS = 1.0e18f; // something less than sqrt(FLT_MAX) - -// DANGER: until ShapeCollider goes away the order of these values matter. Specifically, -// UNKNOWN_SHAPE must be equal to the number of shapes that ShapeCollider actually supports. -const quint8 SPHERE_SHAPE = 0; -const quint8 CAPSULE_SHAPE = 1; -const quint8 PLANE_SHAPE = 2; -const quint8 AACUBE_SHAPE = 3; -const quint8 LIST_SHAPE = 4; -const quint8 UNKNOWN_SHAPE = 5; -const quint8 INVALID_SHAPE = 5; - -// new shapes to be supported by Bullet -const quint8 BOX_SHAPE = 7; -const quint8 CYLINDER_SHAPE = 8; - -class Shape { -public: - - typedef quint8 Type; - - static quint32 getNextID() { static quint32 nextID = 0; return ++nextID; } - - Shape() : _type(UNKNOWN_SHAPE), _owningEntity(NULL), _boundingRadius(0.0f), - _translation(0.0f), _rotation(), _mass(MAX_SHAPE_MASS) { - _id = getNextID(); - } - virtual ~Shape() { } - - Type getType() const { return _type; } - quint32 getID() const { return _id; } - - void setEntity(PhysicsEntity* entity) { _owningEntity = entity; } - PhysicsEntity* getEntity() const { return _owningEntity; } - - float getBoundingRadius() const { return _boundingRadius; } - - virtual const glm::quat& getRotation() const { return _rotation; } - virtual void setRotation(const glm::quat& rotation) { _rotation = rotation; } - - virtual void setTranslation(const glm::vec3& translation) { _translation = translation; } - virtual const glm::vec3& getTranslation() const { return _translation; } - - virtual void setMass(float mass) { _mass = mass; } - virtual float getMass() const { return _mass; } - - virtual bool findRayIntersection(RayIntersectionInfo& intersection) const = 0; - - /// \param penetration of collision - /// \param contactPoint of collision - /// \return the effective mass for the collision - /// For most shapes has side effects: computes and caches the partial Lagrangian coefficients which will be - /// used in the next accumulateDelta() call. - virtual float computeEffectiveMass(const glm::vec3& penetration, const glm::vec3& contactPoint) { return _mass; } - - /// \param relativeMassFactor the final ingredient for partial Lagrangian coefficients from computeEffectiveMass() - /// \param penetration the delta movement - virtual void accumulateDelta(float relativeMassFactor, const glm::vec3& penetration) {} - - virtual void applyAccumulatedDelta() {} - - /// \return volume of shape in cubic meters - virtual float getVolume() const { return 1.0; } - - virtual QDebug& dumpToDebug(QDebug& debugConext) const; - -protected: - // these ctors are protected (used by derived classes only) - Shape(Type type) : _type(type), _owningEntity(NULL), - _boundingRadius(0.0f), _translation(0.0f), - _rotation(), _mass(MAX_SHAPE_MASS) { - _id = getNextID(); - } - - Shape(Type type, const glm::vec3& position) : - _type(type), _owningEntity(NULL), - _boundingRadius(0.0f), _translation(position), - _rotation(), _mass(MAX_SHAPE_MASS) { - _id = getNextID(); - } - - Shape(Type type, const glm::vec3& position, const glm::quat& rotation) : _type(type), _owningEntity(NULL), - _boundingRadius(0.0f), _translation(position), - _rotation(rotation), _mass(MAX_SHAPE_MASS) { - _id = getNextID(); - } - - void setBoundingRadius(float radius) { _boundingRadius = radius; } - - Type _type; - quint32 _id; - PhysicsEntity* _owningEntity; - float _boundingRadius; - glm::vec3 _translation; - glm::quat _rotation; - float _mass; -}; - -inline QDebug& Shape::dumpToDebug(QDebug& debugConext) const { - debugConext << "Shape[ (" - << "type: " << getType() - << "position: " - << getTranslation().x << ", " << getTranslation().y << ", " << getTranslation().z - << "radius: " - << getBoundingRadius() - << "]"; - - return debugConext; -} - -inline QDebug operator<<(QDebug debug, const Shape& shape) { - return shape.dumpToDebug(debug); -} - -inline QDebug operator<<(QDebug debug, const Shape* shape) { - return shape->dumpToDebug(debug); -} - - -#endif // hifi_Shape_h diff --git a/libraries/shared/src/ShapeCollider.cpp b/libraries/shared/src/ShapeCollider.cpp deleted file mode 100644 index fa86d8c0fb..0000000000 --- a/libraries/shared/src/ShapeCollider.cpp +++ /dev/null @@ -1,1211 +0,0 @@ -// -// ShapeCollider.cpp -// libraries/shared/src -// -// Created by Andrew Meadows on 02/20/2014. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include - -#include "AACubeShape.h" -#include "CapsuleShape.h" -#include "GeometryUtil.h" -#include "ListShape.h" -#include "NumericalConstants.h" -#include "PlaneShape.h" -#include "ShapeCollider.h" -#include "SphereShape.h" -#include "StreamUtils.h" - - -// NOTE: -// -// * Large ListShape's are inefficient keep the lists short. -// * Collisions between lists of lists work in theory but are not recommended. - -const quint8 NUM_SHAPE_TYPES = UNKNOWN_SHAPE; -const quint8 NUM_DISPATCH_CELLS = NUM_SHAPE_TYPES * NUM_SHAPE_TYPES; - -Shape::Type getDispatchKey(Shape::Type typeA, Shape::Type typeB) { - return typeA + NUM_SHAPE_TYPES * typeB; -} - -// dummy dispatch for any non-implemented pairings -bool notImplemented(const Shape* shapeA, const Shape* shapeB, CollisionList& collisions) { - return false; -} - -// NOTE: hardcode the number of dispatchTable entries (NUM_SHAPE_TYPES ^2) -bool (*dispatchTable[NUM_DISPATCH_CELLS])(const Shape*, const Shape*, CollisionList&); - -namespace ShapeCollider { - -// NOTE: the dispatch table must be initialized before the ShapeCollider is used. -void initDispatchTable() { - for (Shape::Type i = 0; i < NUM_DISPATCH_CELLS; ++i) { - dispatchTable[i] = ¬Implemented; - } - - dispatchTable[getDispatchKey(SPHERE_SHAPE, SPHERE_SHAPE)] = &sphereVsSphere; - dispatchTable[getDispatchKey(SPHERE_SHAPE, CAPSULE_SHAPE)] = &sphereVsCapsule; - dispatchTable[getDispatchKey(SPHERE_SHAPE, PLANE_SHAPE)] = &sphereVsPlane; - dispatchTable[getDispatchKey(SPHERE_SHAPE, AACUBE_SHAPE)] = &sphereVsAACube; - dispatchTable[getDispatchKey(SPHERE_SHAPE, LIST_SHAPE)] = &shapeVsList; - - dispatchTable[getDispatchKey(CAPSULE_SHAPE, SPHERE_SHAPE)] = &capsuleVsSphere; - dispatchTable[getDispatchKey(CAPSULE_SHAPE, CAPSULE_SHAPE)] = &capsuleVsCapsule; - dispatchTable[getDispatchKey(CAPSULE_SHAPE, PLANE_SHAPE)] = &capsuleVsPlane; - dispatchTable[getDispatchKey(CAPSULE_SHAPE, AACUBE_SHAPE)] = &capsuleVsAACube; - dispatchTable[getDispatchKey(CAPSULE_SHAPE, LIST_SHAPE)] = &shapeVsList; - - dispatchTable[getDispatchKey(PLANE_SHAPE, SPHERE_SHAPE)] = &planeVsSphere; - dispatchTable[getDispatchKey(PLANE_SHAPE, CAPSULE_SHAPE)] = &planeVsCapsule; - dispatchTable[getDispatchKey(PLANE_SHAPE, PLANE_SHAPE)] = &planeVsPlane; - dispatchTable[getDispatchKey(PLANE_SHAPE, AACUBE_SHAPE)] = ¬Implemented; - dispatchTable[getDispatchKey(PLANE_SHAPE, LIST_SHAPE)] = &shapeVsList; - - dispatchTable[getDispatchKey(AACUBE_SHAPE, SPHERE_SHAPE)] = &aaCubeVsSphere; - dispatchTable[getDispatchKey(AACUBE_SHAPE, CAPSULE_SHAPE)] = &aaCubeVsCapsule; - dispatchTable[getDispatchKey(AACUBE_SHAPE, PLANE_SHAPE)] = ¬Implemented; - dispatchTable[getDispatchKey(AACUBE_SHAPE, AACUBE_SHAPE)] = &aaCubeVsAACube; - dispatchTable[getDispatchKey(AACUBE_SHAPE, LIST_SHAPE)] = &shapeVsList; - - dispatchTable[getDispatchKey(LIST_SHAPE, SPHERE_SHAPE)] = &listVsShape; - dispatchTable[getDispatchKey(LIST_SHAPE, CAPSULE_SHAPE)] = &listVsShape; - dispatchTable[getDispatchKey(LIST_SHAPE, PLANE_SHAPE)] = &listVsShape; - dispatchTable[getDispatchKey(LIST_SHAPE, AACUBE_SHAPE)] = &listVsShape; - dispatchTable[getDispatchKey(LIST_SHAPE, LIST_SHAPE)] = &listVsList; - - // all of the UNKNOWN_SHAPE pairings are notImplemented -} - -bool collideShapes(const Shape* shapeA, const Shape* shapeB, CollisionList& collisions) { - return (*dispatchTable[shapeA->getType() + NUM_SHAPE_TYPES * shapeB->getType()])(shapeA, shapeB, collisions); -} - -static CollisionList tempCollisions(32); - -bool collideShapeWithShapes(const Shape* shapeA, const QVector& shapes, int startIndex, CollisionList& collisions) { - bool collided = false; - if (shapeA) { - int numShapes = shapes.size(); - for (int i = startIndex; i < numShapes; ++i) { - const Shape* shapeB = shapes.at(i); - if (!shapeB) { - continue; - } - if (collideShapes(shapeA, shapeB, collisions)) { - collided = true; - if (collisions.isFull()) { - break; - } - } - } - } - return collided; -} - -bool collideShapesWithShapes(const QVector& shapesA, const QVector& shapesB, CollisionList& collisions) { - bool collided = false; - int numShapesA = shapesA.size(); - for (int i = 0; i < numShapesA; ++i) { - Shape* shapeA = shapesA.at(i); - if (!shapeA) { - continue; - } - if (collideShapeWithShapes(shapeA, shapesB, 0, collisions)) { - collided = true; - if (collisions.isFull()) { - break; - } - } - } - return collided; -} - -bool collideShapeWithAACubeLegacy(const Shape* shapeA, const glm::vec3& cubeCenter, float cubeSide, CollisionList& collisions) { - Shape::Type typeA = shapeA->getType(); - if (typeA == SPHERE_SHAPE) { - return sphereVsAACubeLegacy(static_cast(shapeA), cubeCenter, cubeSide, collisions); - } else if (typeA == CAPSULE_SHAPE) { - return capsuleVsAACubeLegacy(static_cast(shapeA), cubeCenter, cubeSide, collisions); - } else if (typeA == LIST_SHAPE) { - const ListShape* listA = static_cast(shapeA); - bool touching = false; - for (int i = 0; i < listA->size() && !collisions.isFull(); ++i) { - const Shape* subShape = listA->getSubShape(i); - int subType = subShape->getType(); - if (subType == SPHERE_SHAPE) { - touching = sphereVsAACubeLegacy(static_cast(subShape), cubeCenter, cubeSide, collisions) || touching; - } else if (subType == CAPSULE_SHAPE) { - touching = capsuleVsAACubeLegacy(static_cast(subShape), cubeCenter, cubeSide, collisions) || touching; - } - } - return touching; - } - return false; -} - -bool sphereVsSphere(const Shape* shapeA, const Shape* shapeB, CollisionList& collisions) { - const SphereShape* sphereA = static_cast(shapeA); - const SphereShape* sphereB = static_cast(shapeB); - glm::vec3 BA = sphereB->getTranslation() - sphereA->getTranslation(); - float distanceSquared = glm::dot(BA, BA); - float totalRadius = sphereA->getRadius() + sphereB->getRadius(); - if (distanceSquared < totalRadius * totalRadius) { - // normalize BA - float distance = sqrtf(distanceSquared); - if (distance < EPSILON) { - // the spheres are on top of each other, so we pick an arbitrary penetration direction - BA = glm::vec3(0.0f, 1.0f, 0.0f); - distance = totalRadius; - } else { - BA /= distance; - } - // penetration points from A into B - CollisionInfo* collision = collisions.getNewCollision(); - if (collision) { - collision->_penetration = BA * (totalRadius - distance); - // contactPoint is on surface of A - collision->_contactPoint = sphereA->getTranslation() + sphereA->getRadius() * BA; - collision->_shapeA = shapeA; - collision->_shapeB = shapeB; - return true; - } - } - return false; -} - -bool sphereVsCapsule(const Shape* shapeA, const Shape* shapeB, CollisionList& collisions) { - const SphereShape* sphereA = static_cast(shapeA); - const CapsuleShape* capsuleB = static_cast(shapeB); - // find sphereA's closest approach to axis of capsuleB - glm::vec3 BA = capsuleB->getTranslation() - sphereA->getTranslation(); - glm::vec3 capsuleAxis; - capsuleB->computeNormalizedAxis(capsuleAxis); - float axialDistance = - glm::dot(BA, capsuleAxis); - float absAxialDistance = fabsf(axialDistance); - float totalRadius = sphereA->getRadius() + capsuleB->getRadius(); - if (absAxialDistance < totalRadius + capsuleB->getHalfHeight()) { - glm::vec3 radialAxis = BA + axialDistance * capsuleAxis; // points from A to axis of B - float radialDistance2 = glm::length2(radialAxis); - float totalRadius2 = totalRadius * totalRadius; - if (radialDistance2 > totalRadius2) { - // sphere is too far from capsule axis - return false; - } - if (absAxialDistance > capsuleB->getHalfHeight()) { - // sphere hits capsule on a cap --> recompute radialAxis to point from spherA to cap center - float sign = (axialDistance > 0.0f) ? 1.0f : -1.0f; - radialAxis = BA + (sign * capsuleB->getHalfHeight()) * capsuleAxis; - radialDistance2 = glm::length2(radialAxis); - if (radialDistance2 > totalRadius2) { - return false; - } - } - if (radialDistance2 > EPSILON * EPSILON) { - CollisionInfo* collision = collisions.getNewCollision(); - if (!collision) { - // collisions list is full - return false; - } - // normalize the radialAxis - float radialDistance = sqrtf(radialDistance2); - radialAxis /= radialDistance; - // penetration points from A into B - collision->_penetration = (totalRadius - radialDistance) * radialAxis; // points from A into B - // contactPoint is on surface of sphereA - collision->_contactPoint = sphereA->getTranslation() + sphereA->getRadius() * radialAxis; - collision->_shapeA = shapeA; - collision->_shapeB = shapeB; - } else { - // A is on B's axis, so the penetration is undefined... - if (absAxialDistance > capsuleB->getHalfHeight()) { - // ...for the cylinder case (for now we pretend the collision doesn't exist) - return false; - } - CollisionInfo* collision = collisions.getNewCollision(); - if (!collision) { - // collisions list is full - return false; - } - // ... but still defined for the cap case - if (axialDistance < 0.0f) { - // we're hitting the start cap, so we negate the capsuleAxis - capsuleAxis *= -1; - } - // penetration points from A into B - float sign = (axialDistance > 0.0f) ? -1.0f : 1.0f; - collision->_penetration = (sign * (totalRadius + capsuleB->getHalfHeight() - absAxialDistance)) * capsuleAxis; - // contactPoint is on surface of sphereA - collision->_contactPoint = sphereA->getTranslation() + (sign * sphereA->getRadius()) * capsuleAxis; - collision->_shapeA = shapeA; - collision->_shapeB = shapeB; - } - return true; - } - return false; -} - -bool sphereVsPlane(const Shape* shapeA, const Shape* shapeB, CollisionList& collisions) { - const SphereShape* sphereA = static_cast(shapeA); - const PlaneShape* planeB = static_cast(shapeB); - glm::vec3 penetration; - if (findSpherePlanePenetration(sphereA->getTranslation(), sphereA->getRadius(), planeB->getCoefficients(), penetration)) { - CollisionInfo* collision = collisions.getNewCollision(); - if (!collision) { - return false; // collision list is full - } - collision->_penetration = penetration; - collision->_contactPoint = sphereA->getTranslation() + sphereA->getRadius() * glm::normalize(penetration); - collision->_shapeA = shapeA; - collision->_shapeB = shapeB; - return true; - } - return false; -} - -bool capsuleVsSphere(const Shape* shapeA, const Shape* shapeB, CollisionList& collisions) { - return sphereVsCapsule(shapeB, shapeA, collisions); -} - -/// \param lineP point on line -/// \param lineDir normalized direction of line -/// \param cylinderP point on cylinder axis -/// \param cylinderDir normalized direction of cylinder axis -/// \param cylinderRadius radius of cylinder -/// \param hitLow[out] distance from point on line to first intersection with cylinder -/// \param hitHigh[out] distance from point on line to second intersection with cylinder -/// \return true if line hits cylinder -bool lineCylinder(const glm::vec3& lineP, const glm::vec3& lineDir, - const glm::vec3& cylinderP, const glm::vec3& cylinderDir, float cylinderRadius, - float& hitLow, float& hitHigh) { - - // first handle parallel case - float uDotV = glm::dot(lineDir, cylinderDir); - if (fabsf(1.0f - fabsf(uDotV)) < EPSILON) { - // line and cylinder are parallel - if (glm::distance2(lineP, cylinderP) <= cylinderRadius * cylinderRadius) { - // line is inside cylinder, which we consider a hit - hitLow = 0.0f; - hitHigh = 0.0f; - return true; - } - return false; - } - - // Given a line with point 'p' and normalized direction 'u' and - // a cylinder with axial point 's', radius 'r', and normalized direction 'v' - // the intersection of the two is on the line at distance 't' from 'p'. - // - // Determining the values of t reduces to solving a quadratic equation: At^2 + Bt + C = 0 - // - // where: - // - // P = p-s - // w = u-(u.v)v - // Q = P-(P.v)v - // - // A = w^2 - // B = 2(w.Q) - // C = Q^2 - r^2 - - glm::vec3 P = lineP - cylinderP; - glm::vec3 w = lineDir - uDotV * cylinderDir; - glm::vec3 Q = P - glm::dot(P, cylinderDir) * cylinderDir; - - // we save a few multiplies by storing 2*A rather than just A - float A2 = 2.0f * glm::dot(w, w); - float B = 2.0f * glm::dot(w, Q); - - // since C is only ever used once (in the determinant) we compute it inline - float determinant = B * B - 2.0f * A2 * (glm::dot(Q, Q) - cylinderRadius * cylinderRadius); - if (determinant < 0.0f) { - return false; - } - hitLow = (-B - sqrtf(determinant)) / A2; - hitHigh = -(hitLow + 2.0f * B / A2); - - if (hitLow > hitHigh) { - // re-arrange so hitLow is always the smaller value - float temp = hitHigh; - hitHigh = hitLow; - hitLow = temp; - } - return true; -} - -bool capsuleVsCapsule(const Shape* shapeA, const Shape* shapeB, CollisionList& collisions) { - const CapsuleShape* capsuleA = static_cast(shapeA); - const CapsuleShape* capsuleB = static_cast(shapeB); - glm::vec3 axisA; - capsuleA->computeNormalizedAxis(axisA); - glm::vec3 axisB; - capsuleB->computeNormalizedAxis(axisB); - glm::vec3 centerA = capsuleA->getTranslation(); - glm::vec3 centerB = capsuleB->getTranslation(); - - // NOTE: The formula for closest approach between two lines is: - // d = [(B - A) . (a - (a.b)b)] / (1 - (a.b)^2) - - float aDotB = glm::dot(axisA, axisB); - float denominator = 1.0f - aDotB * aDotB; - float totalRadius = capsuleA->getRadius() + capsuleB->getRadius(); - if (denominator > EPSILON) { - // perform line-cylinder intesection test between axis of cylinderA and cylinderB with exanded radius - float hitLow = 0.0f; - float hitHigh = 0.0f; - if (!lineCylinder(centerA, axisA, centerB, axisB, totalRadius, hitLow, hitHigh)) { - return false; - } - - float halfHeightA = capsuleA->getHalfHeight(); - if (hitLow > halfHeightA || hitHigh < -halfHeightA) { - // the intersections are off the ends of capsuleA - return false; - } - - // compute nearest approach on axisA of axisB - float distanceA = glm::dot((centerB - centerA), (axisA - (aDotB) * axisB)) / denominator; - // clamp to intersection zone - if (distanceA > hitLow) { - if (distanceA > hitHigh) { - distanceA = hitHigh; - } - } else { - distanceA = hitLow; - } - // clamp to capsule segment - distanceA = glm::clamp(distanceA, -halfHeightA, halfHeightA); - - // find the closest point on capsuleB to sphere on capsuleA - float distanceB = glm::dot(centerA + distanceA * axisA - centerB, axisB); - float halfHeightB = capsuleB->getHalfHeight(); - if (fabsf(distanceB) > halfHeightB) { - // we must clamp distanceB... - distanceB = glm::clamp(distanceB, -halfHeightB, halfHeightB); - // ...and therefore must recompute distanceA - distanceA = glm::clamp(glm::dot(centerB + distanceB * axisB - centerA, axisA), -halfHeightA, halfHeightA); - } - - // collide like two spheres (do most of the math relative to B) - glm::vec3 BA = (centerB + distanceB * axisB) - (centerA + distanceA * axisA); - float distanceSquared = glm::dot(BA, BA); - if (distanceSquared < totalRadius * totalRadius) { - CollisionInfo* collision = collisions.getNewCollision(); - if (!collision) { - // collisions list is full - return false; - } - // normalize BA - float distance = sqrtf(distanceSquared); - if (distance < EPSILON) { - // the contact spheres are on top of each other, so we need to pick a penetration direction... - // try vector between the capsule centers... - BA = centerB - centerA; - distanceSquared = glm::length2(BA); - if (distanceSquared > EPSILON * EPSILON) { - distance = sqrtf(distanceSquared); - BA /= distance; - } else - { - // the capsule centers are on top of each other! - // give up on a valid penetration direction and just use the yAxis - BA = glm::vec3(0.0f, 1.0f, 0.0f); - distance = glm::max(capsuleB->getRadius(), capsuleA->getRadius()); - } - } else { - BA /= distance; - } - // penetration points from A into B - collision->_penetration = BA * (totalRadius - distance); - // contactPoint is on surface of A - collision->_contactPoint = centerA + distanceA * axisA + capsuleA->getRadius() * BA; - collision->_shapeA = shapeA; - collision->_shapeB = shapeB; - return true; - } - } else { - // capsules are approximiately parallel but might still collide - glm::vec3 BA = centerB - centerA; - float axialDistance = glm::dot(BA, axisB); - if (fabsf(axialDistance) > totalRadius + capsuleA->getHalfHeight() + capsuleB->getHalfHeight()) { - return false; - } - BA = BA - axialDistance * axisB; // BA now points from centerA to axisB (perp to axis) - float distanceSquared = glm::length2(BA); - if (distanceSquared < totalRadius * totalRadius) { - CollisionInfo* collision = collisions.getNewCollision(); - if (!collision) { - // collisions list is full - return false; - } - // We have all the info we need to compute the penetration vector... - // normalize BA - float distance = sqrtf(distanceSquared); - if (distance < EPSILON) { - // the spheres are on top of each other, so we pick an arbitrary penetration direction - BA = glm::vec3(0.0f, 1.0f, 0.0f); - } else { - BA /= distance; - } - // penetration points from A into B - collision->_penetration = BA * (totalRadius - distance); - - // However we need some more world-frame info to compute the contactPoint, - // which is on the surface of capsuleA... - // - // Find the overlapping secion of the capsules --> they collide as if there were - // two spheres at the midpoint of this overlapping section. - // So we project all endpoints to axisB, find the interior pair, - // and put A's proxy sphere on axisA at the midpoint of this section. - - // sort the projections as much as possible during calculation - float points[5]; - points[0] = -capsuleB->getHalfHeight(); - points[1] = axialDistance - capsuleA->getHalfHeight(); - points[2] = axialDistance + capsuleA->getHalfHeight(); - points[3] = capsuleB->getHalfHeight(); - - // Since there are only three comparisons to do we unroll the sort algorithm... - // and use a fifth slot as temp during swap. - if (points[1] > points[2]) { - points[4] = points[1]; - points[1] = points[2]; - points[2] = points[4]; - } - if (points[2] > points[3]) { - points[4] = points[2]; - points[2] = points[3]; - points[3] = points[4]; - } - if (points[0] > points[1]) { - points[4] = points[0]; - points[0] = points[1]; - points[1] = points[4]; - } - - // average the internal pair, and then do the math from centerB - collision->_contactPoint = centerB + (0.5f * (points[1] + points[2])) * axisB - + (capsuleA->getRadius() - distance) * BA; - collision->_shapeA = shapeA; - collision->_shapeB = shapeB; - return true; - } - } - return false; -} - -bool capsuleVsPlane(const Shape* shapeA, const Shape* shapeB, CollisionList& collisions) { - const CapsuleShape* capsuleA = static_cast(shapeA); - const PlaneShape* planeB = static_cast(shapeB); - glm::vec3 start, end, penetration; - capsuleA->getStartPoint(start); - capsuleA->getEndPoint(end); - glm::vec4 plane = planeB->getCoefficients(); - if (findCapsulePlanePenetration(start, end, capsuleA->getRadius(), plane, penetration)) { - CollisionInfo* collision = collisions.getNewCollision(); - if (!collision) { - return false; // collision list is full - } - collision->_penetration = penetration; - glm::vec3 deepestEnd = (glm::dot(start, glm::vec3(plane)) < glm::dot(end, glm::vec3(plane))) ? start : end; - collision->_contactPoint = deepestEnd + capsuleA->getRadius() * glm::normalize(penetration); - collision->_shapeA = shapeA; - collision->_shapeB = shapeB; - return true; - } - return false; -} - -bool planeVsSphere(const Shape* shapeA, const Shape* shapeB, CollisionList& collisions) { - return sphereVsPlane(shapeB, shapeA, collisions); -} - -bool planeVsCapsule(const Shape* shapeA, const Shape* shapeB, CollisionList& collisions) { - return capsuleVsPlane(shapeB, shapeA, collisions); -} - -bool planeVsPlane(const Shape* shapeA, const Shape* shapeB, CollisionList& collisions) { - // technically, planes always collide unless they're parallel and not coincident; however, that's - // not going to give us any useful information - return false; -} - -// helper function -bool sphereVsAACubeLegacy(const glm::vec3& sphereCenter, float sphereRadius, const glm::vec3& cubeCenter, - float cubeSide, CollisionList& collisions) { - // sphere is A - // cube is B - // BA = B - A = from center of A to center of B - float halfCubeSide = 0.5f * cubeSide; - glm::vec3 BA = cubeCenter - sphereCenter; - float distance = glm::length(BA); - if (distance > EPSILON) { - float maxBA = glm::max(glm::max(glm::abs(BA.x), glm::abs(BA.y)), glm::abs(BA.z)); - if (maxBA > halfCubeSide + sphereRadius) { - // sphere misses cube entirely - return false; - } - CollisionInfo* collision = collisions.getNewCollision(); - if (!collision) { - return false; - } - if (maxBA > halfCubeSide) { - // sphere hits cube but its center is outside cube - - // compute contact anti-pole on cube (in cube frame) - glm::vec3 cubeContact = glm::abs(BA); - if (cubeContact.x > halfCubeSide) { - cubeContact.x = halfCubeSide; - } - if (cubeContact.y > halfCubeSide) { - cubeContact.y = halfCubeSide; - } - if (cubeContact.z > halfCubeSide) { - cubeContact.z = halfCubeSide; - } - glm::vec3 signs = glm::sign(BA); - cubeContact.x *= signs.x; - cubeContact.y *= signs.y; - cubeContact.z *= signs.z; - - // compute penetration direction - glm::vec3 direction = BA - cubeContact; - float lengthDirection = glm::length(direction); - if (lengthDirection < EPSILON) { - // sphereCenter is touching cube surface, so we can't use the difference between those two - // points to compute the penetration direction. Instead we use the unitary components of - // cubeContact. - direction = cubeContact / halfCubeSide; - glm::modf(BA, direction); - lengthDirection = glm::length(direction); - } else if (lengthDirection > sphereRadius) { - collisions.deleteLastCollision(); - return false; - } - direction /= lengthDirection; - - // compute collision details - collision->_contactPoint = sphereCenter + sphereRadius * direction; - collision->_penetration = sphereRadius * direction - (BA - cubeContact); - } else { - // sphere center is inside cube - // --> push out nearest face - glm::vec3 direction; - BA /= maxBA; - glm::modf(BA, direction); - float lengthDirection = glm::length(direction); - direction /= lengthDirection; - - // compute collision details - collision->_floatData = cubeSide; - collision->_vecData = cubeCenter; - collision->_penetration = (halfCubeSide * lengthDirection + sphereRadius - maxBA * glm::dot(BA, direction)) * direction; - collision->_contactPoint = sphereCenter + sphereRadius * direction; - } - collision->_floatData = cubeSide; - collision->_vecData = cubeCenter; - collision->_shapeA = NULL; - collision->_shapeB = NULL; - return true; - } else if (sphereRadius + halfCubeSide > distance) { - // NOTE: for cocentric approximation we collide sphere and cube as two spheres which means - // this algorithm will probably be wrong when both sphere and cube are very small (both ~EPSILON) - CollisionInfo* collision = collisions.getNewCollision(); - if (collision) { - // the penetration and contactPoint are undefined, so we pick a penetration direction (-yAxis) - collision->_penetration = (sphereRadius + halfCubeSide) * glm::vec3(0.0f, -1.0f, 0.0f); - // contactPoint is on surface of A - collision->_contactPoint = sphereCenter + collision->_penetration; - - collision->_floatData = cubeSide; - collision->_vecData = cubeCenter; - collision->_shapeA = NULL; - collision->_shapeB = NULL; - return true; - } - } - return false; -} - -// helper function -CollisionInfo* sphereVsAACubeHelper(const glm::vec3& sphereCenter, float sphereRadius, const glm::vec3& cubeCenter, - float cubeSide, CollisionList& collisions) { - // sphere is A - // cube is B - // BA = B - A = from center of A to center of B - float halfCubeSide = 0.5f * cubeSide; - glm::vec3 BA = cubeCenter - sphereCenter; - float distance = glm::length(BA); - if (distance > EPSILON) { - float maxBA = glm::max(glm::max(glm::abs(BA.x), glm::abs(BA.y)), glm::abs(BA.z)); - if (maxBA > halfCubeSide + sphereRadius) { - // sphere misses cube entirely - return NULL; - } - CollisionInfo* collision = collisions.getNewCollision(); - if (!collision) { - return NULL; - } - if (maxBA > halfCubeSide) { - // sphere hits cube but its center is outside cube - - // compute contact anti-pole on cube (in cube frame) - glm::vec3 cubeContact = glm::abs(BA); - if (cubeContact.x > halfCubeSide) { - cubeContact.x = halfCubeSide; - } - if (cubeContact.y > halfCubeSide) { - cubeContact.y = halfCubeSide; - } - if (cubeContact.z > halfCubeSide) { - cubeContact.z = halfCubeSide; - } - glm::vec3 signs = glm::sign(BA); - cubeContact.x *= signs.x; - cubeContact.y *= signs.y; - cubeContact.z *= signs.z; - - // compute penetration direction - glm::vec3 direction = BA - cubeContact; - float lengthDirection = glm::length(direction); - if (lengthDirection < EPSILON) { - // sphereCenter is touching cube surface, so we can't use the difference between those two - // points to compute the penetration direction. Instead we use the unitary components of - // cubeContact. - glm::modf(cubeContact / halfCubeSide, direction); - lengthDirection = glm::length(direction); - } else if (lengthDirection > sphereRadius) { - collisions.deleteLastCollision(); - return NULL; - } - direction /= lengthDirection; - - // compute collision details - collision->_contactPoint = sphereCenter + sphereRadius * direction; - collision->_penetration = sphereRadius * direction - (BA - cubeContact); - } else { - // sphere center is inside cube - // --> push out nearest face - glm::vec3 direction; - BA /= maxBA; - glm::modf(BA, direction); - float lengthDirection = glm::length(direction); - direction /= lengthDirection; - - // compute collision details - collision->_floatData = cubeSide; - collision->_vecData = cubeCenter; - collision->_penetration = (halfCubeSide * lengthDirection + sphereRadius - maxBA * glm::dot(BA, direction)) * direction; - collision->_contactPoint = sphereCenter + sphereRadius * direction; - } - collision->_shapeA = NULL; - collision->_shapeB = NULL; - return collision; - } else if (sphereRadius + halfCubeSide > distance) { - // NOTE: for cocentric approximation we collide sphere and cube as two spheres which means - // this algorithm will probably be wrong when both sphere and cube are very small (both ~EPSILON) - CollisionInfo* collision = collisions.getNewCollision(); - if (collision) { - // the penetration and contactPoint are undefined, so we pick a penetration direction (-yAxis) - collision->_penetration = (sphereRadius + halfCubeSide) * glm::vec3(0.0f, -1.0f, 0.0f); - // contactPoint is on surface of A - collision->_contactPoint = sphereCenter + collision->_penetration; - collision->_shapeA = NULL; - collision->_shapeB = NULL; - return collision; - } - } - return NULL; -} - -bool sphereVsAACube(const Shape* shapeA, const Shape* shapeB, CollisionList& collisions) { - // BA = B - A = from center of A to center of B - const SphereShape* sphereA = static_cast(shapeA); - const AACubeShape* cubeB = static_cast(shapeB); - - CollisionInfo* collision = sphereVsAACubeHelper( sphereA->getTranslation(), sphereA->getRadius(), - cubeB->getTranslation(), cubeB->getScale(), collisions); - if (collision) { - collision->_shapeA = shapeA; - collision->_shapeB = shapeB; - return true; - } - return false; -} - -glm::vec3 cubeNormals[3] = { glm::vec3(1.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f) }; - -// the wallIndices is a sequence of pairs that represent the OTHER directions for each cube face, -// hence the first pair is (1, 2) because the OTHER faces for xFace are (yFace, zFace) = (1, 2) -int wallIndices[] = { 1, 2, 0, 2, 0, 1 }; - -bool capsuleVsAACubeFace(const CapsuleShape* capsuleA, const AACubeShape* cubeB, int faceIndex, const glm::vec3& faceNormal, CollisionList& collisions) { - // we only fall in here when the capsuleAxis is nearly parallel to the face of a cube - glm::vec3 capsuleAxis; - capsuleA->computeNormalizedAxis(capsuleAxis); - glm::vec3 cubeCenter = cubeB->getTranslation(); - - // Revisualize the capsule as a line segment between two points. We'd like to collide the - // capsule as two spheres located at the endpoints or where the line segment hits the boundary - // of the face. - - // We raytrace forward into the four planes that neigbhor the face to find the boundary - // points of the line segment. - glm::vec3 capsuleStart; - capsuleA->getStartPoint(capsuleStart); - - // translate into cube-relative frame - capsuleStart -= cubeCenter; - float capsuleLength = 2.0f * capsuleA->getHalfHeight(); - float halfCubeSide = 0.5f * cubeB->getScale(); - float capsuleRadius = capsuleA->getRadius(); - - // preload distances with values that work for when the capsuleAxis runs parallel to neighbor face - float distances[] = {FLT_MAX, -FLT_MAX, FLT_MAX, -FLT_MAX, 0.0f}; - - // Loop over the directions that are NOT parallel to face (there are two of them). - // For each direction we'll raytrace against the positive and negative planes to find where - // the axis passes through. - for (int i = 0; i < 2; ++i) { - int wallIndex = wallIndices[2 * faceIndex + i]; - glm::vec3 wallNormal = cubeNormals[wallIndex]; - // each direction has two walls: positive and negative - float axisDotWall = glm::dot(capsuleAxis, wallNormal); - if (fabsf(axisDotWall) > EPSILON) { - // formula for distance to intersection between line (P,p) and plane (V,n) is: (V-P)*n / p*n - distances[2 * i] = (halfCubeSide - glm::dot(capsuleStart, wallNormal)) / axisDotWall; - distances[2 * i + 1] = -(halfCubeSide + glm::dot(capsuleStart, wallNormal)) / axisDotWall; - } - } - - // sort the distances from large to small - int j = 3; - while (j > 0) { - for (int i = 0; i <= j; ++i) { - if (distances[i] < distances[i+1]) { - // swap (using distances[4] as temp space) - distances[4] = distances[i]; - distances[i] = distances[i+1]; - distances[i+1] = distances[4]; - } - } - --j; - } - - // the capsule overlaps when the max of the mins is less than the min of the maxes - distances[0] = glm::min(capsuleLength, distances[1]); // maxDistance - distances[1] = glm::max(0.0f, distances[2]); // minDistance - bool hit = false; - if (distances[1] < distances[0]) { - // if we collide at all it will be at two points - for (int i = 0; i < 2; ++i) { - glm::vec3 sphereCenter = cubeCenter + capsuleStart + distances[i] * capsuleAxis; - // collide like a sphere at point0 with capsuleRadius - CollisionInfo* collision = sphereVsAACubeHelper(sphereCenter, capsuleRadius, - cubeCenter, 2.0f * halfCubeSide, collisions); - if (collision) { - // we hit! so store back pointers to the shapes - collision->_shapeA = capsuleA; - collision->_shapeB = cubeB; - hit = true; - } - } - return hit; - } else if (distances[1] < capsuleLength + capsuleRadius ) { - // we might collide at the end cap - glm::vec3 sphereCenter = cubeCenter + capsuleStart + capsuleLength * capsuleAxis; - // collide like a sphere at point0 with capsuleRadius - CollisionInfo* collision = sphereVsAACubeHelper(sphereCenter, capsuleRadius, - cubeCenter, 2.0f * halfCubeSide, collisions); - if (collision) { - // we hit! so store back pointers to the shapes - collision->_shapeA = capsuleA; - collision->_shapeB = cubeB; - hit = true; - } - } else if (distances[0] > -capsuleLength) { - // we might collide at the start cap - glm::vec3 sphereCenter = cubeCenter + capsuleStart; - // collide like a sphere at point0 with capsuleRadius - CollisionInfo* collision = sphereVsAACubeHelper(sphereCenter, capsuleRadius, - cubeCenter, 2.0f * halfCubeSide, collisions); - if (collision) { - // we hit! so store back pointers to the shapes - collision->_shapeA = capsuleA; - collision->_shapeB = cubeB; - hit = true; - } - } - return hit; -} - -bool capsuleVsAACube(const Shape* shapeA, const Shape* shapeB, CollisionList& collisions) { - const CapsuleShape* capsuleA = static_cast(shapeA); - const AACubeShape* cubeB = static_cast(shapeB); - - // find nearest approach of capsule's line segment to cube's center - glm::vec3 capsuleAxis; - capsuleA->computeNormalizedAxis(capsuleAxis); - float halfHeight = capsuleA->getHalfHeight(); - glm::vec3 cubeCenter = cubeB->getTranslation(); - glm::vec3 capsuleCenter = capsuleA->getTranslation(); - glm::vec3 BA = cubeCenter - capsuleCenter; - float axialOffset = glm::dot(capsuleAxis, BA); - if (fabsf(axialOffset) > halfHeight) { - axialOffset = (axialOffset < 0.0f) ? -halfHeight : halfHeight; - } - glm::vec3 nearestApproach = capsuleCenter + axialOffset * capsuleAxis; - - // transform nearestApproach into cube-relative frame - nearestApproach -= cubeCenter; - - // determine the face of nearest approach - glm::vec3 signs = glm::sign(nearestApproach); - int faceIndex = 0; - glm::vec3 faceNormal(signs.x, 0.0f, 0.0f); - float maxApproach = fabsf(nearestApproach.x); - if (maxApproach < fabsf(nearestApproach.y)) { - maxApproach = fabsf(nearestApproach.y); - faceIndex = 1; - faceNormal = glm::vec3(0.0f, signs.y, 0.0f); - } - if (maxApproach < fabsf(nearestApproach.z)) { - maxApproach = fabsf(nearestApproach.z); - faceIndex = 2; - faceNormal = glm::vec3(0.0f, 0.0f, signs.z); - } - - if (fabsf(glm::dot(faceNormal, capsuleAxis)) < EPSILON) { - if (glm::dot(nearestApproach, faceNormal) > cubeB->getScale() + capsuleA->getRadius()) { - return false; - } - // we expect this case to be rare but complicated enough that we split it out - // into its own helper function - return capsuleVsAACubeFace(capsuleA, cubeB, faceIndex, faceNormal, collisions); - } - - // Revisualize the capsule as a startPoint and an axis that points toward the cube face. - // We raytrace forward into the four planes that neigbhor the face to find the furthest - // point along the capsule's axis that might hit face. - glm::vec3 capsuleStart; - if (glm::dot(capsuleAxis, faceNormal) < 0.0f) { - capsuleA->getStartPoint(capsuleStart); - } else { - // NOTE: we want dot(capsuleAxis, faceNormal) to be negative which simplifies some - // logic below, so we pretend the end is the start thereby reversing its axis. - capsuleA->getEndPoint(capsuleStart); - capsuleAxis *= -1.0f; - } - // translate into cube-relative frame - capsuleStart -= cubeCenter; - float capsuleLength = 2.0f * halfHeight; - float halfCubeSide = 0.5f * cubeB->getScale(); - float capsuleRadius = capsuleA->getRadius(); - - // Loop over the directions that are NOT parallel to face (there are two of them). - // For each direction we'll raytrace along capsuleAxis to find where the axis passes - // through the furthest face and then we'll clamp to remain on the capsule's line segment - float shortestDistance = capsuleLength; - - for (int i = 0; i < 2; ++i) { - int wallIndex = wallIndices[2 * faceIndex + i]; - // each direction has two walls: positive and negative - for (float wallSign = -1.0f; wallSign < 2.0f; wallSign += 2.0f) { - glm::vec3 wallNormal = wallSign * cubeNormals[wallIndex]; - float axisDotWall = glm::dot(capsuleAxis, wallNormal); - if (axisDotWall > EPSILON) { - // formula for distance to intersection between line (P,p) and plane (V,n) is: (V-P)*n / p*n - float newDistance = (halfCubeSide - glm::dot(capsuleStart, wallNormal)) / axisDotWall; - if (newDistance < 0.0f) { - // The wall is behind the capsule, but there is still a possibility that it collides - // against the edge so we recast against the diagonal plane beteween the two faces. - // NOTE: it is impossible for the startPoint to be in front of the diagonal plane, - // therefore we know we'll get a valid distance. - glm::vec3 thirdNormal = glm::cross(faceNormal, wallNormal); - glm::vec3 diagonalNormal = glm::normalize(glm::cross(glm::cross(capsuleAxis, thirdNormal), thirdNormal)); - newDistance = glm::dot(halfCubeSide * (faceNormal + wallNormal) - capsuleStart, diagonalNormal) / - glm::dot(capsuleAxis, diagonalNormal); - } else if (newDistance < capsuleLength) { - // The wall truncates the capsule axis, but we must check the case where the capsule - // collides with an edge/corner rather than the face. The good news is that this gives us - // an opportunity to check for an early exit case. - float heightOfImpact = glm::dot(capsuleStart + newDistance * capsuleAxis, faceNormal); - if (heightOfImpact > halfCubeSide + SQUARE_ROOT_OF_2 * capsuleRadius) { - // it is impossible for the capsule to hit the face - return false; - } else { - // recast against the diagonal plane between the two faces - glm::vec3 thirdNormal = glm::cross(faceNormal, wallNormal); - glm::vec3 diagonalNormal = glm::normalize(glm::cross(glm::cross(capsuleAxis, thirdNormal), thirdNormal)); - newDistance = glm::dot(halfCubeSide * (faceNormal + wallNormal) - capsuleStart, diagonalNormal) / - glm::dot(capsuleAxis, diagonalNormal); - } - } - if (newDistance < shortestDistance) { - shortestDistance = newDistance; - } - // there can only be one hit per direction - break; - } - } - } - - // chose the point that produces the deepest penetration against face - // and translate back into real frame - glm::vec3 sphereCenter = cubeCenter + capsuleStart + shortestDistance * capsuleAxis; - - // collide like a sphere at point0 with capsuleRadius - CollisionInfo* collision = sphereVsAACubeHelper(sphereCenter, capsuleRadius, - cubeCenter, 2.0f * halfCubeSide, collisions); - if (collision) { - // we hit! so store back pointers to the shapes - collision->_shapeA = shapeA; - collision->_shapeB = shapeB; - return true; - } - return false; -} - -bool aaCubeVsSphere(const Shape* shapeA, const Shape* shapeB, CollisionList& collisions) { - return sphereVsAACube(shapeB, shapeA, collisions); -} - -bool aaCubeVsCapsule(const Shape* shapeA, const Shape* shapeB, CollisionList& collisions) { - return capsuleVsAACube(shapeB, shapeA, collisions); -} - -// helper function -CollisionInfo* aaCubeVsAACubeHelper(const glm::vec3& cubeCenterA, float cubeSideA, const glm::vec3& cubeCenterB, - float cubeSideB, CollisionList& collisions) { - // cube is A - // cube is B - // BA = B - A = from center of A to center of B - float halfCubeSideA = 0.5f * cubeSideA; - float halfCubeSideB = 0.5f * cubeSideB; - glm::vec3 BA = cubeCenterB - cubeCenterA; - - float distance = glm::length(BA); - - if (distance > EPSILON) { - float maxBA = glm::max(glm::max(glm::abs(BA.x), glm::abs(BA.y)), glm::abs(BA.z)); - if (maxBA > halfCubeSideB + halfCubeSideA) { - // cube misses cube entirely - return NULL; - } - CollisionInfo* collision = collisions.getNewCollision(); - if (!collision) { - return NULL; // no more room for collisions - } - if (maxBA > halfCubeSideB) { - // cube hits cube but its center is outside cube - // compute contact anti-pole on cube (in cube frame) - glm::vec3 cubeContact = glm::abs(BA); - if (cubeContact.x > halfCubeSideB) { - cubeContact.x = halfCubeSideB; - } - if (cubeContact.y > halfCubeSideB) { - cubeContact.y = halfCubeSideB; - } - if (cubeContact.z > halfCubeSideB) { - cubeContact.z = halfCubeSideB; - } - glm::vec3 signs = glm::sign(BA); - cubeContact.x *= signs.x; - cubeContact.y *= signs.y; - cubeContact.z *= signs.z; - - // compute penetration direction - glm::vec3 direction = BA - cubeContact; - - float lengthDirection = glm::length(direction); - - if (lengthDirection < EPSILON) { - // cubeCenterA is touching cube B surface, so we can't use the difference between those two - // points to compute the penetration direction. Instead we use the unitary components of - // cubeContact. - glm::modf(cubeContact / halfCubeSideB, direction); - lengthDirection = glm::length(direction); - } else if (lengthDirection > halfCubeSideA) { - collisions.deleteLastCollision(); - return NULL; - } - direction /= lengthDirection; - - // compute collision details - collision->_contactPoint = cubeCenterA + halfCubeSideA * direction; - collision->_penetration = halfCubeSideA * direction - (BA - cubeContact); - } else { - // cube center is inside cube - // --> push out nearest face - glm::vec3 direction; - BA /= maxBA; - glm::modf(BA, direction); - float lengthDirection = glm::length(direction); - direction /= lengthDirection; - - // compute collision details - collision->_floatData = cubeSideB; - collision->_vecData = cubeCenterB; - collision->_penetration = (halfCubeSideB * lengthDirection + halfCubeSideA - maxBA * glm::dot(BA, direction)) * direction; - collision->_contactPoint = cubeCenterA + halfCubeSideA * direction; - } - collision->_shapeA = NULL; - collision->_shapeB = NULL; - return collision; - } else if (halfCubeSideA + halfCubeSideB > distance) { - // NOTE: for cocentric approximation we collide sphere and cube as two spheres which means - // this algorithm will probably be wrong when both sphere and cube are very small (both ~EPSILON) - CollisionInfo* collision = collisions.getNewCollision(); - if (collision) { - // the penetration and contactPoint are undefined, so we pick a penetration direction (-yAxis) - collision->_penetration = (halfCubeSideA + halfCubeSideB) * glm::vec3(0.0f, -1.0f, 0.0f); - // contactPoint is on surface of A - collision->_contactPoint = cubeCenterA + collision->_penetration; - collision->_shapeA = NULL; - collision->_shapeB = NULL; - return collision; - } - } - return NULL; -} - -bool aaCubeVsAACube(const Shape* shapeA, const Shape* shapeB, CollisionList& collisions) { - // BA = B - A = from center of A to center of B - const AACubeShape* cubeA = static_cast(shapeA); - const AACubeShape* cubeB = static_cast(shapeB); - CollisionInfo* collision = aaCubeVsAACubeHelper( cubeA->getTranslation(), cubeA->getScale(), - cubeB->getTranslation(), cubeB->getScale(), collisions); - if (collision) { - collision->_shapeA = shapeA; - collision->_shapeB = shapeB; - return true; - } - return false; -} - -bool shapeVsList(const Shape* shapeA, const Shape* shapeB, CollisionList& collisions) { - bool touching = false; - const ListShape* listB = static_cast(shapeB); - for (int i = 0; i < listB->size() && !collisions.isFull(); ++i) { - const Shape* subShape = listB->getSubShape(i); - touching = collideShapes(shapeA, subShape, collisions) || touching; - } - return touching; -} - -bool listVsShape(const Shape* shapeA, const Shape* shapeB, CollisionList& collisions) { - bool touching = false; - const ListShape* listA = static_cast(shapeA); - for (int i = 0; i < listA->size() && !collisions.isFull(); ++i) { - const Shape* subShape = listA->getSubShape(i); - touching = collideShapes(subShape, shapeB, collisions) || touching; - } - return touching; -} - -bool listVsList(const Shape* shapeA, const Shape* shapeB, CollisionList& collisions) { - bool touching = false; - const ListShape* listA = static_cast(shapeA); - const ListShape* listB = static_cast(shapeB); - for (int i = 0; i < listA->size() && !collisions.isFull(); ++i) { - const Shape* subShape = listA->getSubShape(i); - for (int j = 0; j < listB->size() && !collisions.isFull(); ++j) { - touching = collideShapes(subShape, listB->getSubShape(j), collisions) || touching; - } - } - return touching; -} - -// helper function -/* KEEP THIS CODE -- this is how to collide the cube with stark face normals (no rounding). -* We might want to use this code later for sealing boundaries between adjacent voxels. -bool sphereAACube_StarkAngles(const glm::vec3& sphereCenter, float sphereRadius, const glm::vec3& cubeCenter, - float cubeSide, CollisionList& collisions) { - glm::vec3 BA = cubeCenter - sphereCenter; - float distance = glm::length(BA); - if (distance > EPSILON) { - BA /= distance; // BA is now normalized - // compute the nearest point on sphere - glm::vec3 surfaceA = sphereCenter + sphereRadius * BA; - // compute the nearest point on cube - float maxBA = glm::max(glm::max(fabsf(BA.x), fabsf(BA.y)), fabsf(BA.z)); - glm::vec3 surfaceB = cubeCenter - (0.5f * cubeSide / maxBA) * BA; - // collision happens when "vector to surfaceA from surfaceB" dots with BA to produce a positive value - glm::vec3 surfaceAB = surfaceA - surfaceB; - if (glm::dot(surfaceAB, BA) > 0.0f) { - CollisionInfo* collision = collisions.getNewCollision(); - if (collision) { - // penetration is parallel to box side direction - BA /= maxBA; - glm::vec3 direction; - glm::modf(BA, direction); - direction = glm::normalize(direction); - - // penetration is the projection of surfaceAB on direction - collision->_penetration = glm::dot(surfaceAB, direction) * direction; - // contactPoint is on surface of A - collision->_contactPoint = sphereCenter + sphereRadius * direction; - collision->_shapeA = NULL; - collision->_shapeB = NULL; - return true; - } - } - } else if (sphereRadius + 0.5f * cubeSide > distance) { - // NOTE: for cocentric approximation we collide sphere and cube as two spheres which means - // this algorithm will probably be wrong when both sphere and cube are very small (both ~EPSILON) - CollisionInfo* collision = collisions.getNewCollision(); - if (collision) { - // the penetration and contactPoint are undefined, so we pick a penetration direction (-yAxis) - collision->_penetration = (sphereRadius + 0.5f * cubeSide) * glm::vec3(0.0f, -1.0f, 0.0f); - // contactPoint is on surface of A - collision->_contactPoint = sphereCenter + collision->_penetration; - collision->_shapeA = NULL; - collision->_shapeB = NULL; - return true; - } - } - return false; -} -*/ - -bool sphereVsAACubeLegacy(const SphereShape* sphereA, const glm::vec3& cubeCenter, float cubeSide, CollisionList& collisions) { - return sphereVsAACubeLegacy(sphereA->getTranslation(), sphereA->getRadius(), cubeCenter, cubeSide, collisions); -} - -bool capsuleVsAACubeLegacy(const CapsuleShape* capsuleA, const glm::vec3& cubeCenter, float cubeSide, CollisionList& collisions) { - // find nerest approach of capsule line segment to cube - glm::vec3 capsuleAxis; - capsuleA->computeNormalizedAxis(capsuleAxis); - float offset = glm::dot(cubeCenter - capsuleA->getTranslation(), capsuleAxis); - float halfHeight = capsuleA->getHalfHeight(); - if (offset > halfHeight) { - offset = halfHeight; - } else if (offset < -halfHeight) { - offset = -halfHeight; - } - glm::vec3 nearestApproach = capsuleA->getTranslation() + offset * capsuleAxis; - // collide nearest approach like a sphere at that point - return sphereVsAACubeLegacy(nearestApproach, capsuleA->getRadius(), cubeCenter, cubeSide, collisions); -} - -bool findRayIntersection(const QVector& shapes, RayIntersectionInfo& intersection) { - int numShapes = shapes.size(); - bool hit = false; - for (int i = 0; i < numShapes; ++i) { - Shape* shape = shapes.at(i); - if (shape) { - if (shape->findRayIntersection(intersection)) { - hit = true; - } - } - } - return hit; -} - -} // namespace ShapeCollider diff --git a/libraries/shared/src/ShapeCollider.h b/libraries/shared/src/ShapeCollider.h deleted file mode 100644 index da37adcd49..0000000000 --- a/libraries/shared/src/ShapeCollider.h +++ /dev/null @@ -1,156 +0,0 @@ -// -// ShapeCollider.h -// libraries/shared/src -// -// Created by Andrew Meadows on 02/20/2014. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_ShapeCollider_h -#define hifi_ShapeCollider_h - -#include - -#include "CollisionInfo.h" -#include "RayIntersectionInfo.h" -#include "SharedUtil.h" - - -class Shape; -class SphereShape; -class CapsuleShape; - -namespace ShapeCollider { - - /// MUST CALL this FIRST before using the ShapeCollider - void initDispatchTable(); - - /// \param shapeA pointer to first shape (cannot be NULL) - /// \param shapeB pointer to second shape (cannot be NULL) - /// \param collisions[out] collision details - /// \return true if shapes collide - bool collideShapes(const Shape* shapeA, const Shape* shapeB, CollisionList& collisions); - - bool collideShapeWithShapes(const Shape* shapeA, const QVector& shapes, int startIndex, CollisionList& collisions); - bool collideShapesWithShapes(const QVector& shapesA, const QVector& shapesB, CollisionList& collisions); - - /// \param shapeA a pointer to a shape (cannot be NULL) - /// \param cubeCenter center of cube - /// \param cubeSide lenght of side of cube - /// \param collisions[out] average collision details - /// \return true if shapeA collides with axis aligned cube - bool collideShapeWithAACubeLegacy(const Shape* shapeA, const glm::vec3& cubeCenter, float cubeSide, CollisionList& collisions); - - /// \param sphereA pointer to first shape (cannot be NULL) - /// \param sphereB pointer to second shape (cannot be NULL) - /// \param[out] collisions where to append collision details - /// \return true if shapes collide - bool sphereVsSphere(const Shape* sphereA, const Shape* sphereB, CollisionList& collisions); - - /// \param sphereA pointer to first shape (cannot be NULL) - /// \param capsuleB pointer to second shape (cannot be NULL) - /// \param[out] collisions where to append collision details - /// \return true if shapes collide - bool sphereVsCapsule(const Shape* sphereA, const Shape* capsuleB, CollisionList& collisions); - - /// \param sphereA pointer to first shape (cannot be NULL) - /// \param planeB pointer to second shape (cannot be NULL) - /// \param[out] collisions where to append collision details - /// \return true if shapes collide - bool sphereVsPlane(const Shape* sphereA, const Shape* planeB, CollisionList& collisions); - - /// \param capsuleA pointer to first shape (cannot be NULL) - /// \param sphereB pointer to second shape (cannot be NULL) - /// \param[out] collisions where to append collision details - /// \return true if shapes collide - bool capsuleVsSphere(const Shape* capsuleA, const Shape* sphereB, CollisionList& collisions); - - /// \param capsuleA pointer to first shape (cannot be NULL) - /// \param capsuleB pointer to second shape (cannot be NULL) - /// \param[out] collisions where to append collision details - /// \return true if shapes collide - bool capsuleVsCapsule(const Shape* capsuleA, const Shape* capsuleB, CollisionList& collisions); - - /// \param capsuleA pointer to first shape (cannot be NULL) - /// \param planeB pointer to second shape (cannot be NULL) - /// \param[out] collisions where to append collision details - /// \return true if shapes collide - bool capsuleVsPlane(const Shape* capsuleA, const Shape* planeB, CollisionList& collisions); - - /// \param planeA pointer to first shape (cannot be NULL) - /// \param sphereB pointer to second shape (cannot be NULL) - /// \param[out] collisions where to append collision details - /// \return true if shapes collide - bool planeVsSphere(const Shape* planeA, const Shape* sphereB, CollisionList& collisions); - - /// \param planeA pointer to first shape (cannot be NULL) - /// \param capsuleB pointer to second shape (cannot be NULL) - /// \param[out] collisions where to append collision details - /// \return true if shapes collide - bool planeVsCapsule(const Shape* planeA, const Shape* capsuleB, CollisionList& collisions); - - /// \param planeA pointer to first shape (cannot be NULL) - /// \param planeB pointer to second shape (cannot be NULL) - /// \param[out] collisions where to append collision details - /// \return true if shapes collide - bool planeVsPlane(const Shape* planeA, const Shape* planeB, CollisionList& collisions); - - /// helper function for *VsAACube() methods - /// \param sphereCenter center of sphere - /// \param sphereRadius radius of sphere - /// \param cubeCenter center of AACube - /// \param cubeSide scale of cube - /// \param[out] collisions where to append collision details - /// \return valid pointer to CollisionInfo if sphere and cube overlap or NULL if not - CollisionInfo* sphereVsAACubeHelper(const glm::vec3& sphereCenter, float sphereRadius, - const glm::vec3& cubeCenter, float cubeSide, CollisionList& collisions); - - bool sphereVsAACube(const Shape* shapeA, const Shape* shapeB, CollisionList& collisions); - bool capsuleVsAACube(const Shape* shapeA, const Shape* shapeB, CollisionList& collisions); - bool aaCubeVsSphere(const Shape* shapeA, const Shape* shapeB, CollisionList& collisions); - bool aaCubeVsCapsule(const Shape* shapeA, const Shape* shapeB, CollisionList& collisions); - bool aaCubeVsAACube(const Shape* shapeA, const Shape* shapeB, CollisionList& collisions); - - /// \param shapeA pointer to first shape (cannot be NULL) - /// \param listB pointer to second shape (cannot be NULL) - /// \param[out] collisions where to append collision details - /// \return true if shapes collide - bool shapeVsList(const Shape* shapeA, const Shape* listB, CollisionList& collisions); - - /// \param listA pointer to first shape (cannot be NULL) - /// \param shapeB pointer to second shape (cannot be NULL) - /// \param[out] collisions where to append collision details - /// \return true if shapes collide - bool listVsShape(const Shape* listA, const Shape* shapeB, CollisionList& collisions); - - /// \param listA pointer to first shape (cannot be NULL) - /// \param listB pointer to second shape (cannot be NULL) - /// \param[out] collisions where to append collision details - /// \return true if shapes collide - bool listVsList(const Shape* listA, const Shape* listB, CollisionList& collisions); - - /// \param sphereA pointer to sphere (cannot be NULL) - /// \param cubeCenter center of cube - /// \param cubeSide lenght of side of cube - /// \param[out] collisions where to append collision details - /// \return true if sphereA collides with axis aligned cube - bool sphereVsAACubeLegacy(const SphereShape* sphereA, const glm::vec3& cubeCenter, float cubeSide, CollisionList& collisions); - - /// \param capsuleA pointer to capsule (cannot be NULL) - /// \param cubeCenter center of cube - /// \param cubeSide lenght of side of cube - /// \param[out] collisions where to append collision details - /// \return true if capsuleA collides with axis aligned cube - bool capsuleVsAACubeLegacy(const CapsuleShape* capsuleA, const glm::vec3& cubeCenter, float cubeSide, CollisionList& collisions); - - /// \param shapes list of pointers to shapes (shape pointers may be NULL) - /// \param intersection[out] struct with info about Ray and hit - /// \return true if ray hits any shape in shapes - bool findRayIntersection(const QVector& shapes, RayIntersectionInfo& intersection); - -} // namespace ShapeCollider - -#endif // hifi_ShapeCollider_h diff --git a/libraries/shared/src/SphereShape.cpp b/libraries/shared/src/SphereShape.cpp deleted file mode 100644 index 4c47ae91c0..0000000000 --- a/libraries/shared/src/SphereShape.cpp +++ /dev/null @@ -1,51 +0,0 @@ -// -// SphereShape.cpp -// libraries/shared/src -// -// Created by Andrew Meadows on 2014.06.17 -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include - -#include "SphereShape.h" - -bool SphereShape::findRayIntersection(RayIntersectionInfo& intersection) const { - float r2 = _boundingRadius * _boundingRadius; - - // compute closest approach (CA) - float a = glm::dot(_translation - intersection._rayStart, intersection._rayDirection); // a = distance from ray-start to CA - float b2 = glm::distance2(_translation, intersection._rayStart + a * intersection._rayDirection); // b2 = squared distance from sphere-center to CA - if (b2 > r2) { - // ray does not hit sphere - return false; - } - float c = sqrtf(r2 - b2); // c = distance from CA to sphere surface along intersection._rayDirection - float d2 = glm::distance2(intersection._rayStart, _translation); // d2 = squared distance from sphere-center to ray-start - float distance = FLT_MAX; - if (a < 0.0f) { - // ray points away from sphere-center - if (d2 > r2) { - // ray starts outside sphere - return false; - } - // ray starts inside sphere - distance = c + a; - } else if (d2 > r2) { - // ray starts outside sphere - distance = a - c; - } else { - // ray starts inside sphere - distance = a + c; - } - if (distance > 0.0f && distance < intersection._rayLength && distance < intersection._hitDistance) { - intersection._hitDistance = distance; - intersection._hitNormal = glm::normalize(intersection._rayStart + distance * intersection._rayDirection - _translation); - intersection._hitShape = const_cast(this); - return true; - } - return false; -} diff --git a/libraries/shared/src/SphereShape.h b/libraries/shared/src/SphereShape.h deleted file mode 100644 index 964881a715..0000000000 --- a/libraries/shared/src/SphereShape.h +++ /dev/null @@ -1,63 +0,0 @@ -// -// SphereShape.h -// libraries/shared/src -// -// Created by Andrew Meadows on 2014. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_SphereShape_h -#define hifi_SphereShape_h - -#include "NumericalConstants.h" -#include "Shape.h" - -class SphereShape : public Shape { -public: - SphereShape() : Shape(SPHERE_SHAPE) {} - - SphereShape(float radius) : Shape(SPHERE_SHAPE) { - _boundingRadius = radius; - } - - SphereShape(float radius, const glm::vec3& position) : Shape(SPHERE_SHAPE, position) { - _boundingRadius = radius; - } - - virtual ~SphereShape() {} - - float getRadius() const { return _boundingRadius; } - - void setRadius(float radius) { _boundingRadius = radius; } - - bool findRayIntersection(RayIntersectionInfo& intersection) const; - - float getVolume() const { return 1.3333333333f * PI * _boundingRadius * _boundingRadius * _boundingRadius; } -}; - -inline QDebug operator<<(QDebug debug, const SphereShape& shape) { - debug << "SphereShape[ (" - << "position: " - << shape.getTranslation().x << ", " << shape.getTranslation().y << ", " << shape.getTranslation().z - << "radius: " - << shape.getRadius() - << "]"; - - return debug; -} - -inline QDebug operator<<(QDebug debug, const SphereShape* shape) { - debug << "SphereShape[ (" - << "center: " - << shape->getTranslation().x << ", " << shape->getTranslation().y << ", " << shape->getTranslation().z - << "radius: " - << shape->getRadius() - << "]"; - - return debug; -} - -#endif // hifi_SphereShape_h diff --git a/libraries/shared/src/StreamUtils.cpp b/libraries/shared/src/StreamUtils.cpp index 5726728f30..d4378d82b3 100644 --- a/libraries/shared/src/StreamUtils.cpp +++ b/libraries/shared/src/StreamUtils.cpp @@ -65,38 +65,6 @@ QDataStream& operator>>(QDataStream& in, glm::quat& quaternion) { return in >> quaternion.x >> quaternion.y >> quaternion.z >> quaternion.w; } -// less common utils can be enabled with DEBUG -// FIXME, remove the second defined clause once these compile, or remove the -// functions. -#if defined(DEBUG) && defined(FIXED_STREAMS) - -std::ostream& operator<<(std::ostream& s, const CollisionInfo& c) { - s << "{penetration=" << c._penetration - << ", contactPoint=" << c._contactPoint - << ", addedVelocity=" << c._addedVelocity - << "}"; - return s; -} - -std::ostream& operator<<(std::ostream& s, const SphereShape& sphere) { - s << "{type='sphere', center=" << sphere.getPosition() - << ", radius=" << sphere.getRadius() - << "}"; - return s; -} - -std::ostream& operator<<(std::ostream& s, const CapsuleShape& capsule) { - s << "{type='capsule', center=" << capsule.getPosition() - << ", radius=" << capsule.getRadius() - << ", length=" << (2.0f * capsule.getHalfHeight()) - << ", begin=" << capsule.getStartPoint() - << ", end=" << capsule.getEndPoint() - << "}"; - return s; -} - -#endif // DEBUG - #ifndef QT_NO_DEBUG_STREAM #include diff --git a/libraries/shared/src/StreamUtils.h b/libraries/shared/src/StreamUtils.h index fd22f7c068..caf7b565f4 100644 --- a/libraries/shared/src/StreamUtils.h +++ b/libraries/shared/src/StreamUtils.h @@ -37,16 +37,6 @@ QDataStream& operator>>(QDataStream& in, glm::vec3& vector); QDataStream& operator<<(QDataStream& out, const glm::quat& quaternion); QDataStream& operator>>(QDataStream& in, glm::quat& quaternion); -// less common utils can be enabled with DEBUG -#ifdef DEBUG -class CollisionInfo; -class SphereShape; -class CapsuleShape; -std::ostream& operator<<(std::ostream& s, const CollisionInfo& c); -std::ostream& operator<<(std::ostream& s, const SphereShape& shape); -std::ostream& operator<<(std::ostream& s, const CapsuleShape& capsule); -#endif // DEBUG - #ifndef QT_NO_DEBUG_STREAM class QDebug; // Add support for writing these to qDebug(). diff --git a/tests/render-utils/CMakeLists.txt b/tests/render-utils/CMakeLists.txt index 4561b099e1..97d3214744 100644 --- a/tests/render-utils/CMakeLists.txt +++ b/tests/render-utils/CMakeLists.txt @@ -5,9 +5,8 @@ set(TARGET_NAME render-utils-test) setup_hifi_project(Quick Gui OpenGL) set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "Tests/manual-tests/") -#include_oglplus() - # link in the shared libraries link_hifi_libraries(render-utils gpu shared) -copy_dlls_beside_windows_executable() \ No newline at end of file +message(${PROJECT_BINARY_DIR}) +copy_dlls_beside_windows_executable() diff --git a/tests/render-utils/src/main.cpp b/tests/render-utils/src/main.cpp index 9abd533650..0fa261db8d 100644 --- a/tests/render-utils/src/main.cpp +++ b/tests/render-utils/src/main.cpp @@ -8,36 +8,23 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include -#include +#include +#include +#include -#include - -#include -#include -#include -#include -#include -#include - -#include #include -#include #include #include -#include -#include -#include + +#include +#include +#include +#include #include -#include #include #include - - -#include - class RateCounter { std::vector times; QElapsedTimer timer; @@ -68,7 +55,7 @@ public: float rate() const { if (elapsed() == 0.0f) { - return NAN; + return 0.0f; } return (float) count() / elapsed(); } @@ -111,8 +98,8 @@ public: // Qt Quick may need a depth and stencil buffer. Always make sure these are available. format.setDepthBufferSize(16); format.setStencilBufferSize(8); - format.setVersion(4, 5); - format.setProfile(QSurfaceFormat::OpenGLContextProfile::CompatibilityProfile); + format.setVersion(4, 1); + format.setProfile(QSurfaceFormat::OpenGLContextProfile::CoreProfile); format.setOption(QSurfaceFormat::DebugContext); setFormat(format); @@ -127,7 +114,6 @@ public: gpu::Context::init(); - { QOpenGLDebugLogger* logger = new QOpenGLDebugLogger(this); logger->initialize(); // initializes in the current context, i.e. ctx @@ -153,7 +139,6 @@ public: makeCurrent(); - setFramePosition(QPoint(-1000, 0)); resize(QSize(800, 600)); } @@ -184,6 +169,13 @@ static const glm::vec3 COLORS[4] = { { 1.0, 1.0, 1.0 }, { 0.5, 1.0, 0.5 }, { 1.0, 0.5, 0.5 }, { 0.5, 0.5, 1.0 } }; +void testShaderBuild(const char* vs_src, const char * fs_src) { + auto vs = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(vs_src))); + auto fs = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(fs_src))); + auto pr = gpu::ShaderPointer(gpu::Shader::createProgram(vs, fs)); + gpu::Shader::makeProgram(*pr); +} + void QTestWindow::draw() { if (!isVisible()) { return; @@ -203,8 +195,26 @@ void QTestWindow::draw() { } } +void messageHandler(QtMsgType type, const QMessageLogContext& context, const QString& message) { + if (!message.isEmpty()) { +#ifdef Q_OS_WIN + OutputDebugStringA(message.toLocal8Bit().constData()); + OutputDebugStringA("\n"); +#else + std::cout << message.toLocal8Bit().constData() << std::endl; +#endif + } +} + + +const char * LOG_FILTER_RULES = R"V0G0N( +hifi.gpu=true +)V0G0N"; + int main(int argc, char** argv) { QGuiApplication app(argc, argv); + qInstallMessageHandler(messageHandler); + QLoggingCategory::setFilterRules(LOG_FILTER_RULES); QTestWindow window; QTimer timer; timer.setInterval(1); diff --git a/tests/shaders/CMakeLists.txt b/tests/shaders/CMakeLists.txt new file mode 100644 index 0000000000..eefdf2aa3a --- /dev/null +++ b/tests/shaders/CMakeLists.txt @@ -0,0 +1,21 @@ + +set(TARGET_NAME shaders-test) + +# This is not a testcase -- just set it up as a regular hifi project +setup_hifi_project(Quick Gui OpenGL) +set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "Tests/manual-tests/") + +#include_oglplus() + +# link in the shared libraries +link_hifi_libraries(shared octree environment gpu model render fbx networking entities + script-engine physics + render-utils entities-renderer) + +include_directories("${PROJECT_BINARY_DIR}/../../libraries/gpu/") +include_directories("${PROJECT_BINARY_DIR}/../../libraries/render-utils/") +include_directories("${PROJECT_BINARY_DIR}/../../libraries/entities-renderer/") +include_directories("${PROJECT_BINARY_DIR}/../../libraries/model/") + +message(${PROJECT_BINARY_DIR}) +copy_dlls_beside_windows_executable() diff --git a/tests/shaders/src/main.cpp b/tests/shaders/src/main.cpp new file mode 100644 index 0000000000..c514532eac --- /dev/null +++ b/tests/shaders/src/main.cpp @@ -0,0 +1,371 @@ +// +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "../model/Skybox_vert.h" +#include "../model/Skybox_frag.h" + +#include "simple_vert.h" +#include "simple_frag.h" +#include "simple_textured_frag.h" +#include "simple_textured_emisive_frag.h" + +#include "deferred_light_vert.h" +#include "deferred_light_limited_vert.h" + +#include "directional_light_frag.h" +#include "directional_light_shadow_map_frag.h" +#include "directional_light_cascaded_shadow_map_frag.h" + +#include "directional_ambient_light_frag.h" +#include "directional_ambient_light_shadow_map_frag.h" +#include "directional_ambient_light_cascaded_shadow_map_frag.h" + +#include "directional_skybox_light_frag.h" +#include "directional_skybox_light_shadow_map_frag.h" +#include "directional_skybox_light_cascaded_shadow_map_frag.h" + +#include "point_light_frag.h" +#include "spot_light_frag.h" + +#include "standardTransformPNTC_vert.h" +#include "standardDrawTexture_frag.h" + +#include "model_vert.h" +#include "model_shadow_vert.h" +#include "model_normal_map_vert.h" +#include "model_lightmap_vert.h" +#include "model_lightmap_normal_map_vert.h" +#include "skin_model_vert.h" +#include "skin_model_shadow_vert.h" +#include "skin_model_normal_map_vert.h" + +#include "model_frag.h" +#include "model_shadow_frag.h" +#include "model_normal_map_frag.h" +#include "model_normal_specular_map_frag.h" +#include "model_specular_map_frag.h" +#include "model_lightmap_frag.h" +#include "model_lightmap_normal_map_frag.h" +#include "model_lightmap_normal_specular_map_frag.h" +#include "model_lightmap_specular_map_frag.h" +#include "model_translucent_frag.h" + +#include "untextured_particle_frag.h" +#include "untextured_particle_vert.h" +#include "textured_particle_frag.h" +#include "textured_particle_vert.h" + +#include "ambient_occlusion_vert.h" +#include "ambient_occlusion_frag.h" +#include "gaussian_blur_vertical_vert.h" +#include "gaussian_blur_horizontal_vert.h" +#include "gaussian_blur_frag.h" +#include "occlusion_blend_frag.h" + +#include "hit_effect_vert.h" +#include "hit_effect_frag.h" + +#include "overlay3D_vert.h" +#include "overlay3D_frag.h" + +#include "SkyFromSpace_vert.h" +#include "SkyFromSpace_frag.h" +#include "SkyFromAtmosphere_vert.h" +#include "SkyFromAtmosphere_frag.h" + +#include "Skybox_vert.h" +#include "Skybox_frag.h" + +#include "stars_vert.h" +#include "stars_frag.h" +#include "starsGrid_frag.h" + +#include "DrawTransformUnitQuad_vert.h" +#include "DrawTexcoordRectTransformUnitQuad_vert.h" +#include "DrawViewportQuadTransformTexcoord_vert.h" +#include "DrawTexture_frag.h" +#include "DrawTextureOpaque_frag.h" +#include "DrawColoredTexture_frag.h" + +#include "sdf_text3D_vert.h" +#include "sdf_text3D_frag.h" + + +class RateCounter { + std::vector times; + QElapsedTimer timer; +public: + RateCounter() { + timer.start(); + } + + void reset() { + times.clear(); + } + + unsigned int count() const { + return times.size() - 1; + } + + float elapsed() const { + if (times.size() < 1) { + return 0.0f; + } + float elapsed = *times.rbegin() - *times.begin(); + return elapsed; + } + + void increment() { + times.push_back(timer.elapsed() / 1000.0f); + } + + float rate() const { + if (elapsed() == 0.0f) { + return 0.0f; + } + return (float) count() / elapsed(); + } +}; + + +const QString& getQmlDir() { + static QString dir; + if (dir.isEmpty()) { + QDir path(__FILE__); + path.cdUp(); + dir = path.cleanPath(path.absoluteFilePath("../../../interface/resources/qml/")) + "/"; + qDebug() << "Qml Path: " << dir; + } + return dir; +} + +// Create a simple OpenGL window that renders text in various ways +class QTestWindow : public QWindow { + Q_OBJECT + + QOpenGLContext* _context{ nullptr }; + QSize _size; + //TextRenderer* _textRenderer[4]; + RateCounter fps; + +protected: + void renderText(); + +private: + void resizeWindow(const QSize& size) { + _size = size; + } + +public: + QTestWindow() { + setSurfaceType(QSurface::OpenGLSurface); + + QSurfaceFormat format; + // Qt Quick may need a depth and stencil buffer. Always make sure these are available. + format.setDepthBufferSize(16); + format.setStencilBufferSize(8); + format.setVersion(4, 1); + format.setProfile(QSurfaceFormat::OpenGLContextProfile::CoreProfile); + format.setOption(QSurfaceFormat::DebugContext); + + setFormat(format); + + _context = new QOpenGLContext; + _context->setFormat(format); + _context->create(); + + show(); + makeCurrent(); + + gpu::Context::init(); + + + { + QOpenGLDebugLogger* logger = new QOpenGLDebugLogger(this); + logger->initialize(); // initializes in the current context, i.e. ctx + logger->enableMessages(); + connect(logger, &QOpenGLDebugLogger::messageLogged, this, [&](const QOpenGLDebugMessage & debugMessage) { + qDebug() << debugMessage; + }); + // logger->startLogging(QOpenGLDebugLogger::SynchronousLogging); + } + qDebug() << (const char*)glGetString(GL_VERSION); + + //_textRenderer[0] = TextRenderer::getInstance(SANS_FONT_FAMILY, 12, false); + //_textRenderer[1] = TextRenderer::getInstance(SERIF_FONT_FAMILY, 12, false, + // TextRenderer::SHADOW_EFFECT); + //_textRenderer[2] = TextRenderer::getInstance(MONO_FONT_FAMILY, 48, -1, + // false, TextRenderer::OUTLINE_EFFECT); + //_textRenderer[3] = TextRenderer::getInstance(INCONSOLATA_FONT_FAMILY, 24); + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glClearColor(0.2f, 0.2f, 0.2f, 1); + glDisable(GL_DEPTH_TEST); + + makeCurrent(); + +// setFramePosition(QPoint(-1000, 0)); + resize(QSize(800, 600)); + } + + virtual ~QTestWindow() { + } + + void draw(); + void makeCurrent() { + _context->makeCurrent(this); + } + +protected: + void resizeEvent(QResizeEvent* ev) override { + resizeWindow(ev->size()); + } +}; + +void testShaderBuild(const char* vs_src, const char * fs_src) { + auto vs = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(vs_src))); + auto fs = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(fs_src))); + auto pr = gpu::ShaderPointer(gpu::Shader::createProgram(vs, fs)); + gpu::Shader::makeProgram(*pr); +} + +void QTestWindow::draw() { + if (!isVisible()) { + return; + } + + makeCurrent(); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glViewport(0, 0, _size.width() * devicePixelRatio(), _size.height() * devicePixelRatio()); + + static std::once_flag once; + std::call_once(once, [&]{ + testShaderBuild(sdf_text3D_vert, sdf_text3D_frag); + + testShaderBuild(DrawTransformUnitQuad_vert, DrawTexture_frag); + testShaderBuild(DrawTexcoordRectTransformUnitQuad_vert, DrawTexture_frag); + testShaderBuild(DrawViewportQuadTransformTexcoord_vert, DrawTexture_frag); + testShaderBuild(DrawTransformUnitQuad_vert, DrawTextureOpaque_frag); + testShaderBuild(DrawTransformUnitQuad_vert, DrawColoredTexture_frag); + + testShaderBuild(Skybox_vert, Skybox_frag); + testShaderBuild(simple_vert, simple_frag); + testShaderBuild(simple_vert, simple_textured_frag); + testShaderBuild(simple_vert, simple_textured_emisive_frag); + testShaderBuild(deferred_light_vert, directional_light_frag); + testShaderBuild(deferred_light_vert, directional_light_shadow_map_frag); + testShaderBuild(deferred_light_vert, directional_light_cascaded_shadow_map_frag); + testShaderBuild(deferred_light_vert, directional_ambient_light_frag); + testShaderBuild(deferred_light_vert, directional_ambient_light_shadow_map_frag); + testShaderBuild(deferred_light_vert, directional_ambient_light_cascaded_shadow_map_frag); + testShaderBuild(deferred_light_vert, directional_skybox_light_frag); + testShaderBuild(deferred_light_vert, directional_skybox_light_shadow_map_frag); + testShaderBuild(deferred_light_vert, directional_skybox_light_cascaded_shadow_map_frag); + testShaderBuild(deferred_light_limited_vert, point_light_frag); + testShaderBuild(deferred_light_limited_vert, spot_light_frag); + testShaderBuild(standardTransformPNTC_vert, standardDrawTexture_frag); + testShaderBuild(standardTransformPNTC_vert, DrawTextureOpaque_frag); + + testShaderBuild(standardTransformPNTC_vert, starsGrid_frag); + testShaderBuild(stars_vert, stars_frag); + + testShaderBuild(model_vert, model_frag); + testShaderBuild(model_normal_map_vert, model_normal_map_frag); + testShaderBuild(model_vert, model_specular_map_frag); + testShaderBuild(model_normal_map_vert, model_normal_specular_map_frag); + testShaderBuild(model_vert, model_translucent_frag); + testShaderBuild(model_normal_map_vert, model_translucent_frag); + testShaderBuild(model_lightmap_vert, model_lightmap_frag); + testShaderBuild(model_lightmap_normal_map_vert, model_lightmap_normal_map_frag); + testShaderBuild(model_lightmap_vert, model_lightmap_specular_map_frag); + testShaderBuild(model_lightmap_normal_map_vert, model_lightmap_normal_specular_map_frag); + + testShaderBuild(skin_model_vert, model_frag); + testShaderBuild(skin_model_normal_map_vert, model_normal_map_frag); + testShaderBuild(skin_model_vert, model_specular_map_frag); + testShaderBuild(skin_model_normal_map_vert, model_normal_specular_map_frag); + testShaderBuild(skin_model_vert, model_translucent_frag); + testShaderBuild(skin_model_normal_map_vert, model_translucent_frag); + + testShaderBuild(model_shadow_vert, model_shadow_frag); + testShaderBuild(untextured_particle_vert, untextured_particle_frag); + testShaderBuild(textured_particle_vert, textured_particle_frag); + + testShaderBuild(gaussian_blur_vertical_vert, gaussian_blur_frag); + testShaderBuild(gaussian_blur_horizontal_vert, gaussian_blur_frag); + testShaderBuild(ambient_occlusion_vert, ambient_occlusion_frag); + testShaderBuild(ambient_occlusion_vert, occlusion_blend_frag); + + testShaderBuild(hit_effect_vert, hit_effect_frag); + + testShaderBuild(overlay3D_vert, overlay3D_frag); + + testShaderBuild(SkyFromSpace_vert, SkyFromSpace_frag); + testShaderBuild(SkyFromAtmosphere_vert, SkyFromAtmosphere_frag); + + testShaderBuild(Skybox_vert, Skybox_frag); + + }); + + _context->swapBuffers(this); + glFinish(); + + fps.increment(); + if (fps.elapsed() >= 2.0f) { + qDebug() << "FPS: " << fps.rate(); + fps.reset(); + } +} + +void messageHandler(QtMsgType type, const QMessageLogContext& context, const QString& message) { + if (!message.isEmpty()) { +#ifdef Q_OS_WIN + OutputDebugStringA(message.toLocal8Bit().constData()); + OutputDebugStringA("\n"); +#else + std::cout << message.toLocal8Bit().constData() << std::endl; +#endif + } +} + + +const char * LOG_FILTER_RULES = R"V0G0N( +hifi.gpu=true +)V0G0N"; + +int main(int argc, char** argv) { + QGuiApplication app(argc, argv); + qInstallMessageHandler(messageHandler); + QLoggingCategory::setFilterRules(LOG_FILTER_RULES); + QTestWindow window; + QTimer timer; + timer.setInterval(1); + app.connect(&timer, &QTimer::timeout, &app, [&] { + window.draw(); + }); + timer.start(); + app.exec(); + return 0; +} + +#include "main.moc" diff --git a/tests/shared/src/GeometryUtilTests.cpp b/tests/shared/src/GeometryUtilTests.cpp new file mode 100644 index 0000000000..798951e304 --- /dev/null +++ b/tests/shared/src/GeometryUtilTests.cpp @@ -0,0 +1,160 @@ +// +// GeometryUtilTests.cpp +// tests/physics/src +// +// Created by Andrew Meadows on 2015.07.27 +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include + +#include "GeometryUtilTests.h" + +#include +#include +#include + +#include <../QTestExtensions.h> + + +QTEST_MAIN(GeometryUtilTests) + +float getErrorDifference(const float& a, const float& b) { + return fabsf(a - b); +} + +float getErrorDifference(const glm::vec3& a, const glm::vec3& b) { + return glm::distance(a, b); +} + +void GeometryUtilTests::testLocalRayRectangleIntersection() { + glm::vec3 xAxis(1.0f, 0.0f, 0.0f); + glm::vec3 yAxis(0.0f, 1.0f, 0.0f); + glm::vec3 zAxis(0.0f, 0.0f, 1.0f); + + // create a rectangle in the local frame on the XY plane with normal along -zAxis + // (this is the assumed local orientation of the rectangle in findRayRectangleIntersection()) + glm::vec2 rectDimensions(3.0f, 5.0f); + glm::vec3 rectCenter(0.0f, 0.0f, 0.0f); + glm::quat rectRotation = glm::quat(); // identity + + // create points for generating rays that hit the plane and don't + glm::vec3 rayStart(1.0f, 2.0f, 3.0f); + float delta = 0.1f; + + { // verify hit + glm::vec3 rayEnd = rectCenter + rectRotation * ((0.5f * rectDimensions.x - delta) * xAxis); + glm::vec3 rayHitDirection = glm::normalize(rayEnd - rayStart); + float expectedDistance = glm::length(rayEnd - rayStart); + + float distance = FLT_MAX; + bool hit = findRayRectangleIntersection(rayStart, rayHitDirection, rectRotation, rectCenter, rectDimensions, distance); + QCOMPARE(hit, true); + QCOMPARE_WITH_ABS_ERROR(distance, expectedDistance, EPSILON); + } + + { // verify miss + glm::vec3 rayEnd = rectCenter + rectRotation * ((0.5f * rectDimensions.y + delta) * yAxis); + glm::vec3 rayMissDirection = glm::normalize(rayEnd - rayStart); + float distance = FLT_MAX; + bool hit = findRayRectangleIntersection(rayStart, rayMissDirection, rectRotation, rectCenter, rectDimensions, distance); + QCOMPARE(hit, false); + QCOMPARE(distance, FLT_MAX); // distance should be unchanged + } + + { // hit with co-planer line + float yFraction = 0.25f; + rayStart = rectCenter + rectRotation * (rectDimensions.x * xAxis + yFraction * rectDimensions.y * yAxis); + + glm::vec3 rayEnd = rectCenter - rectRotation * (rectDimensions.x * xAxis + yFraction * rectDimensions.y * yAxis); + glm::vec3 rayHitDirection = glm::normalize(rayEnd - rayStart); + float expectedDistance = rectDimensions.x; + + float distance = FLT_MAX; + bool hit = findRayRectangleIntersection(rayStart, rayHitDirection, rectRotation, rectCenter, rectDimensions, distance); + QCOMPARE(hit, true); + QCOMPARE_WITH_ABS_ERROR(distance, expectedDistance, EPSILON); + } + + { // miss with co-planer line + float yFraction = 0.75f; + rayStart = rectCenter + rectRotation * (rectDimensions.x * xAxis + (yFraction * rectDimensions.y) * yAxis); + + glm::vec3 rayEnd = rectCenter + rectRotation * (- rectDimensions.x * xAxis + (yFraction * rectDimensions.y) * yAxis); + glm::vec3 rayHitDirection = glm::normalize(rayEnd - rayStart); + + float distance = FLT_MAX; + bool hit = findRayRectangleIntersection(rayStart, rayHitDirection, rectRotation, rectCenter, rectDimensions, distance); + QCOMPARE(hit, false); + QCOMPARE(distance, FLT_MAX); // distance should be unchanged + } +} + +void GeometryUtilTests::testWorldRayRectangleIntersection() { + glm::vec3 xAxis(1.0f, 0.0f, 0.0f); + glm::vec3 yAxis(0.0f, 1.0f, 0.0f); + glm::vec3 zAxis(0.0f, 0.0f, 1.0f); + + // create a rectangle in the local frame on the XY plane with normal along -zAxis + // (this is the assumed local orientation of the rectangle in findRayRectangleIntersection()) + // and then rotate and shift everything into the world frame + glm::vec2 rectDimensions(3.0f, 5.0f); + glm::vec3 rectCenter(0.7f, 0.5f, -0.3f); + glm::quat rectRotation = glm::quat(); // identity + + + // create points for generating rays that hit the plane and don't + glm::vec3 rayStart(1.0f, 2.0f, 3.0f); + float delta = 0.1f; + + { // verify hit + glm::vec3 rayEnd = rectCenter + rectRotation * ((0.5f * rectDimensions.x - delta) * xAxis); + glm::vec3 rayHitDirection = glm::normalize(rayEnd - rayStart); + float expectedDistance = glm::length(rayEnd - rayStart); + + float distance = FLT_MAX; + bool hit = findRayRectangleIntersection(rayStart, rayHitDirection, rectRotation, rectCenter, rectDimensions, distance); + QCOMPARE(hit, true); + QCOMPARE_WITH_ABS_ERROR(distance, expectedDistance, EPSILON); + } + + { // verify miss + glm::vec3 rayEnd = rectCenter + rectRotation * ((0.5f * rectDimensions.y + delta) * yAxis); + glm::vec3 rayMissDirection = glm::normalize(rayEnd - rayStart); + float distance = FLT_MAX; + bool hit = findRayRectangleIntersection(rayStart, rayMissDirection, rectRotation, rectCenter, rectDimensions, distance); + QCOMPARE(hit, false); + QCOMPARE(distance, FLT_MAX); // distance should be unchanged + } + + { // hit with co-planer line + float yFraction = 0.25f; + rayStart = rectCenter + rectRotation * (rectDimensions.x * xAxis + (yFraction * rectDimensions.y) * yAxis); + + glm::vec3 rayEnd = rectCenter - rectRotation * (rectDimensions.x * xAxis + (yFraction * rectDimensions.y) * yAxis); + glm::vec3 rayHitDirection = glm::normalize(rayEnd - rayStart); + float expectedDistance = rectDimensions.x; + + float distance = FLT_MAX; + bool hit = findRayRectangleIntersection(rayStart, rayHitDirection, rectRotation, rectCenter, rectDimensions, distance); + QCOMPARE(hit, true); + QCOMPARE_WITH_ABS_ERROR(distance, expectedDistance, EPSILON); + } + + { // miss with co-planer line + float yFraction = 0.75f; + rayStart = rectCenter + rectRotation * (rectDimensions.x * xAxis + (yFraction * rectDimensions.y) * yAxis); + + glm::vec3 rayEnd = rectCenter + rectRotation * (-rectDimensions.x * xAxis + (yFraction * rectDimensions.y) * yAxis); + glm::vec3 rayHitDirection = glm::normalize(rayEnd - rayStart); + + float distance = FLT_MAX; + bool hit = findRayRectangleIntersection(rayStart, rayHitDirection, rectRotation, rectCenter, rectDimensions, distance); + QCOMPARE(hit, false); + QCOMPARE(distance, FLT_MAX); // distance should be unchanged + } +} + diff --git a/tests/shared/src/GeometryUtilTests.h b/tests/shared/src/GeometryUtilTests.h new file mode 100644 index 0000000000..d75fce556e --- /dev/null +++ b/tests/shared/src/GeometryUtilTests.h @@ -0,0 +1,28 @@ +// +// GeometryUtilTests.h +// tests/physics/src +// +// Created by Andrew Meadows on 2014.05.30 +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_AngularConstraintTests_h +#define hifi_AngularConstraintTests_h + +#include +#include + +class GeometryUtilTests : public QObject { + Q_OBJECT +private slots: + void testLocalRayRectangleIntersection(); + void testWorldRayRectangleIntersection(); +}; + +float getErrorDifference(const float& a, const float& b); +float getErrorDifference(const glm::vec3& a, const glm::vec3& b); + +#endif // hifi_AngularConstraintTests_h diff --git a/tests/ui/CMakeLists.txt b/tests/ui/CMakeLists.txt index aa942f916d..ad1009d925 100644 --- a/tests/ui/CMakeLists.txt +++ b/tests/ui/CMakeLists.txt @@ -7,10 +7,7 @@ setup_hifi_project(Widgets OpenGL Network Qml Quick Script) set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "Tests/manual-tests/") if (WIN32) - add_dependency_external_projects(glew) - find_package(GLEW REQUIRED) - target_include_directories(${TARGET_NAME} PRIVATE ${GLEW_INCLUDE_DIRS}) - target_link_libraries(${TARGET_NAME} ${GLEW_LIBRARIES} wsock32.lib opengl32.lib Winmm.lib) + target_link_libraries(${TARGET_NAME} wsock32.lib opengl32.lib Winmm.lib) endif() # link in the shared libraries diff --git a/tests/ui/src/main.cpp b/tests/ui/src/main.cpp index e8ab7e02df..443e662bc1 100644 --- a/tests/ui/src/main.cpp +++ b/tests/ui/src/main.cpp @@ -68,7 +68,7 @@ public: float rate() const { if (elapsed() == 0.0f) { - return NAN; + return 0.0f; } return (float) count() / elapsed(); } diff --git a/tools/scribe/src/main.cpp b/tools/scribe/src/main.cpp index bf44721d45..13003f05cf 100755 --- a/tools/scribe/src/main.cpp +++ b/tools/scribe/src/main.cpp @@ -188,7 +188,6 @@ int main (int argc, char** argv) { std::ostringstream targetStringStream; if (makeCPlusPlus) { targetStringStream << "// File generated by Scribe " << vars["_SCRIBE_DATE"] << std::endl; - targetStringStream << "#ifndef scribe_" << targetName << "_h" << std::endl; targetStringStream << "#define scribe_" << targetName << "_h" << std::endl << std::endl;