From 874ccf0708d0be16aa4c67ed6c05633ff99ce03f Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 5 Nov 2014 10:57:06 -0800 Subject: [PATCH 001/502] add FindLibcuckoo module and instructions for dropping in libcuckoo --- .gitignore | 4 +++ cmake/modules/FindLibcuckoo.cmake | 29 +++++++++++++++++++ libraries/networking/CMakeLists.txt | 5 +++- .../networking/externals/libcuckoo/readme.txt | 14 +++++++++ 4 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 cmake/modules/FindLibcuckoo.cmake create mode 100644 libraries/networking/externals/libcuckoo/readme.txt diff --git a/.gitignore b/.gitignore index 6e6b69cb66..74a5748b85 100644 --- a/.gitignore +++ b/.gitignore @@ -32,5 +32,9 @@ DerivedData interface/external/*/* !interface/external/*/readme.txt +# ignore libraries externals +libraries/*/externals/*/* +!libraries/*/externals/*/readme.txt + # Ignore interfaceCache for Linux users interface/interfaceCache/ diff --git a/cmake/modules/FindLibcuckoo.cmake b/cmake/modules/FindLibcuckoo.cmake new file mode 100644 index 0000000000..d997f25449 --- /dev/null +++ b/cmake/modules/FindLibcuckoo.cmake @@ -0,0 +1,29 @@ +# FindLibCuckoo.cmake +# +# Try to find libcuckoo. +# +# You can provide a LIBCUCKOO_ROOT_DIR which contains src and include directories +# +# Once done this will define +# +# LIBCUCKOO_FOUND - system found libcuckoo +# LIBCUCKOO_INCLUDE_DIRS - the libcuckoo include directory +# +# Created on 5/11/2014 by Stephen Birarda +# 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("${MACRO_DIR}/HifiLibrarySearchHints.cmake") +hifi_library_search_hints("libcuckoo") + +find_path(LIBCUCKOO_INCLUDE_DIRS cuckoohash_map.hh PATH_SUFFIXES libcuckoo HINTS ${LIBCUCKOO_SEARCH_DIRS}) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args( + libcuckoo + "Could NOT find libcuckoo. Read libraries/networking/externals/libcuckoo/readme.txt" + LIBCUCKOO_INCLUDE_DIRS +) \ No newline at end of file diff --git a/libraries/networking/CMakeLists.txt b/libraries/networking/CMakeLists.txt index 50f41fe643..cf68bc464a 100644 --- a/libraries/networking/CMakeLists.txt +++ b/libraries/networking/CMakeLists.txt @@ -10,9 +10,12 @@ if (WIN32) target_link_libraries(${TARGET_NAME} ws2_32.lib) endif () -# find OpenSSL +# find required dependencies find_package(OpenSSL REQUIRED) +list(APPEND LIBCUCKOO_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/externals/libcuckoo") +find_package(libcuckoo REQUIRED) + if (APPLE AND ${OPENSSL_INCLUDE_DIR} STREQUAL "/usr/include") # this is a user on OS X using system OpenSSL, which is going to throw warnings since they're deprecating for their common crypto message(WARNING "The found version of OpenSSL is the OS X system version. This will produce deprecation warnings." diff --git a/libraries/networking/externals/libcuckoo/readme.txt b/libraries/networking/externals/libcuckoo/readme.txt new file mode 100644 index 0000000000..b86f8bc609 --- /dev/null +++ b/libraries/networking/externals/libcuckoo/readme.txt @@ -0,0 +1,14 @@ + +Instructions for adding the libcuckoo library to Interface +Stephen Birarda, November 5, 2014 + +1. Download the libcuckoo ZIP from the High Fidelity libcuckoo fork on Github. + https://github.com/highfidelity/libcuckoo/archive/master.zip + +2. Copy the libcuckoo folder from inside the ZIP to libraries/networking/externals/libcuckoo/. + + You should have the following structure: + + libraries/networking/externals/libcuckoo/libcuckoo/cuckoohash_map.hh + +3. Delete your build directory, run cmake and build, and you should be all set. From c8aeab53ba5022e062a8237ee8e303e99e345a2b Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 5 Nov 2014 11:42:18 -0800 Subject: [PATCH 002/502] changes for C++11 support --- CMakeLists.txt | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index b421040a50..938375ebc1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,6 +34,23 @@ elseif (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -fno-strict-aliasing") endif(WIN32) +include(CheckCXXCompilerFlag) +CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11) +CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X) + +if (COMPILER_SUPPORTS_CXX11) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") +elseif(COMPILER_SUPPORTS_CXX0X) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") +else() + message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.") +endif() + +if (APPLE) + set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LANGUAGE_STANDARD "c++0x") + set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY "libc++") +endif () + if (NOT QT_CMAKE_PREFIX_PATH) set(QT_CMAKE_PREFIX_PATH $ENV{QT_CMAKE_PREFIX_PATH}) endif () From 3f442039845a7b30fcf554c9820aab2ef3db5e7c Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 5 Nov 2014 11:42:40 -0800 Subject: [PATCH 003/502] remove getpid usage and replace with Qt solution --- libraries/shared/src/LogHandler.cpp | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/libraries/shared/src/LogHandler.cpp b/libraries/shared/src/LogHandler.cpp index a13f3a9dad..6abfd9e787 100644 --- a/libraries/shared/src/LogHandler.cpp +++ b/libraries/shared/src/LogHandler.cpp @@ -12,15 +12,7 @@ #include -#ifdef _WIN32 -#include -#define getpid _getpid -#define getppid _getpid // hack to build -#define pid_t int // hack to build -#elif __linux__ -#include // for getpid() on linux -#endif - +#include #include #include @@ -122,14 +114,8 @@ QString LogHandler::printMessage(LogMsgType type, const QMessageLogContext& cont prefixString.append(QString(" [%1]").arg(dateString)); if (_shouldOutputPID) { - prefixString.append(QString(" [%1").arg(getpid())); + prefixString.append(QString(" [%1]").arg(QCoreApplication::instance()->applicationPid())); - pid_t parentProcessID = getppid(); - if (parentProcessID != 0) { - prefixString.append(QString(":%1]").arg(parentProcessID)); - } else { - prefixString.append("]"); - } } if (!_targetName.isEmpty()) { From 161b3b83d71d6dfb6ff73400dd1196fff1f54d87 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 5 Nov 2014 11:44:56 -0800 Subject: [PATCH 004/502] find an installed version of libcuckoo --- cmake/modules/FindLibcuckoo.cmake | 2 +- libraries/networking/CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/modules/FindLibcuckoo.cmake b/cmake/modules/FindLibcuckoo.cmake index d997f25449..dad3d8513e 100644 --- a/cmake/modules/FindLibcuckoo.cmake +++ b/cmake/modules/FindLibcuckoo.cmake @@ -19,7 +19,7 @@ include("${MACRO_DIR}/HifiLibrarySearchHints.cmake") hifi_library_search_hints("libcuckoo") -find_path(LIBCUCKOO_INCLUDE_DIRS cuckoohash_map.hh PATH_SUFFIXES libcuckoo HINTS ${LIBCUCKOO_SEARCH_DIRS}) +find_path(LIBCUCKOO_INCLUDE_DIRS libcuckoo/cuckoohash_map.hh PATH_SUFFIXES include HINTS ${LIBCUCKOO_SEARCH_DIRS}) include(FindPackageHandleStandardArgs) find_package_handle_standard_args( diff --git a/libraries/networking/CMakeLists.txt b/libraries/networking/CMakeLists.txt index cf68bc464a..f10b7b2402 100644 --- a/libraries/networking/CMakeLists.txt +++ b/libraries/networking/CMakeLists.txt @@ -22,7 +22,7 @@ if (APPLE AND ${OPENSSL_INCLUDE_DIR} STREQUAL "/usr/include") "\nWe recommend you install a newer version (at least 1.0.1h) in a different directory and set OPENSSL_ROOT_DIR in your env so Cmake can find it.") endif () -include_directories(SYSTEM "${OPENSSL_INCLUDE_DIR}") +include_directories(SYSTEM "${OPENSSL_INCLUDE_DIR}" "${LIBCUCKOO_INCLUDE_DIRS}") # append OpenSSL to our list of libraries to link list(APPEND ${TARGET_NAME}_LIBRARIES_TO_LINK "${OPENSSL_LIBRARIES}") From 118b3133c564a64a547ebcbe2762edee6bc18d68 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 5 Nov 2014 11:45:14 -0800 Subject: [PATCH 005/502] change call to std::abs to abs in SequenceNumberStats --- libraries/networking/src/SequenceNumberStats.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/networking/src/SequenceNumberStats.cpp b/libraries/networking/src/SequenceNumberStats.cpp index f472159164..58c684e16b 100644 --- a/libraries/networking/src/SequenceNumberStats.cpp +++ b/libraries/networking/src/SequenceNumberStats.cpp @@ -68,7 +68,7 @@ SequenceNumberStats::ArrivalInfo SequenceNumberStats::sequenceNumberReceived(qui int expectedInt = (int)expected; // check if the gap between incoming and expected is reasonable, taking possible rollover into consideration - int absGap = std::abs(incomingInt - expectedInt); + int absGap = abs(incomingInt - expectedInt); if (absGap >= UINT16_RANGE - MAX_REASONABLE_SEQUENCE_GAP) { // rollover likely occurred between incoming and expected. // correct the larger of the two so that it's within [-UINT16_RANGE, -1] while the other remains within [0, UINT16_RANGE-1] From bff67077153fc18426b20c62bbc6b5a9c4c88966 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 5 Nov 2014 12:02:05 -0800 Subject: [PATCH 006/502] repair implicit cast of ints into unsigned colorBuffer --- interface/src/ui/TextRenderer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/ui/TextRenderer.cpp b/interface/src/ui/TextRenderer.cpp index 0db1ab5f00..71f10a8603 100644 --- a/interface/src/ui/TextRenderer.cpp +++ b/interface/src/ui/TextRenderer.cpp @@ -128,7 +128,7 @@ int TextRenderer::draw(int x, int y, const char* str) { leftBottom.x, rightTop.y, ls, tt, }; const int NUM_COLOR_SCALARS_PER_GLYPH = 4; - unsigned int colorBuffer[NUM_COLOR_SCALARS_PER_GLYPH] = { compactColor, compactColor, compactColor, compactColor }; + int colorBuffer[NUM_COLOR_SCALARS_PER_GLYPH] = { compactColor, compactColor, compactColor, compactColor }; gpu::Buffer::Size offset = sizeof(vertexBuffer) * _numGlyphsBatched; gpu::Buffer::Size colorOffset = sizeof(colorBuffer) * _numGlyphsBatched; From b8d0bd5d6bb527c0b560c3d3aa9564b433bbf793 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 5 Nov 2014 13:25:32 -0800 Subject: [PATCH 007/502] allow a target to bubble up required includes --- cmake/macros/LinkHifiLibraries.cmake | 4 ++++ cmake/macros/LinkSharedDependencies.cmake | 10 +++++++++- libraries/networking/CMakeLists.txt | 5 ++++- libraries/networking/src/LimitedNodeList.h | 2 ++ 4 files changed, 19 insertions(+), 2 deletions(-) diff --git a/cmake/macros/LinkHifiLibraries.cmake b/cmake/macros/LinkHifiLibraries.cmake index 9d73963fea..a46023fe9a 100644 --- a/cmake/macros/LinkHifiLibraries.cmake +++ b/cmake/macros/LinkHifiLibraries.cmake @@ -29,6 +29,10 @@ macro(LINK_HIFI_LIBRARIES) get_target_property(LINKED_TARGET_DEPENDENCY_LIBRARIES ${HIFI_LIBRARY} DEPENDENCY_LIBRARIES) list(APPEND ${TARGET_NAME}_LIBRARIES_TO_LINK ${LINKED_TARGET_DEPENDENCY_LIBRARIES}) + # ask the library what its include dependencies are and link them + get_target_property(LINKED_TARGET_DEPENDENCY_INCLUDES ${HIFI_LIBRARY} DEPENDENCY_INCLUDES) + list(APPEND ${TARGET_NAME}_DEPENDENCY_INCLUDES ${LINKED_TARGET_DEPENDENCY_INCLUDES}) + endforeach() endmacro(LINK_HIFI_LIBRARIES) \ No newline at end of file diff --git a/cmake/macros/LinkSharedDependencies.cmake b/cmake/macros/LinkSharedDependencies.cmake index ae478ca530..a73f57dc1d 100644 --- a/cmake/macros/LinkSharedDependencies.cmake +++ b/cmake/macros/LinkSharedDependencies.cmake @@ -17,9 +17,17 @@ macro(LINK_SHARED_DEPENDENCIES) target_link_libraries(${TARGET_NAME} ${${TARGET_NAME}_LIBRARIES_TO_LINK}) endif () + if (${TARGET_NAME}_DEPENDENCY_INCLUDES) + list(REMOVE_DUPLICATES ${TARGET_NAME}_DEPENDENCY_INCLUDES) + + # include those in our own target + include_directories(SYSTEM ${${TARGET_NAME}_DEPENDENCY_INCLUDES}) + endif () + # we've already linked our Qt modules, but we need to bubble them up to parents list(APPEND ${TARGET_NAME}_LIBRARIES_TO_LINK "${${TARGET}_QT_MODULES_TO_LINK}") # set the property on this target so it can be retreived by targets linking to us - set_target_properties(${TARGET_NAME} PROPERTIES DEPENDENCY_LIBRARIES "${${TARGET}_LIBRARIES_TO_LINK}") + set_target_properties(${TARGET_NAME} PROPERTIES DEPENDENCY_LIBRARIES "${${TARGET_NAME}_LIBRARIES_TO_LINK}") + set_target_properties(${TARGET_NAME} PROPERTIES DEPENDENCY_INCLUDES "${${TARGET_NAME}_DEPENDENCY_INCLUDES}") endmacro(LINK_SHARED_DEPENDENCIES) \ No newline at end of file diff --git a/libraries/networking/CMakeLists.txt b/libraries/networking/CMakeLists.txt index f10b7b2402..021401853f 100644 --- a/libraries/networking/CMakeLists.txt +++ b/libraries/networking/CMakeLists.txt @@ -22,10 +22,13 @@ if (APPLE AND ${OPENSSL_INCLUDE_DIR} STREQUAL "/usr/include") "\nWe recommend you install a newer version (at least 1.0.1h) in a different directory and set OPENSSL_ROOT_DIR in your env so Cmake can find it.") endif () -include_directories(SYSTEM "${OPENSSL_INCLUDE_DIR}" "${LIBCUCKOO_INCLUDE_DIRS}") +include_directories(SYSTEM "${OPENSSL_INCLUDE_DIR}") # append OpenSSL to our list of libraries to link list(APPEND ${TARGET_NAME}_LIBRARIES_TO_LINK "${OPENSSL_LIBRARIES}") +# append libcuckoo includes to our list of includes to bubble +list(APPEND ${TARGET_NAME}_DEPENDENCY_INCLUDES "${LIBCUCKOO_INCLUDE_DIRS}") + # call macro to link our dependencies and bubble them up via a property on our target link_shared_dependencies() \ No newline at end of file diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index 64495fbd34..9e5610ba4e 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -28,6 +28,8 @@ #include #include +#include + #include "DomainHandler.h" #include "Node.h" From 35d0d31350a0ade1641e2b9d55df2ed697b5c650 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 5 Nov 2014 13:54:38 -0800 Subject: [PATCH 008/502] change the NodeHash to a cuckoohash_map with CityHash --- cmake/modules/FindLibcuckoo.cmake | 9 +++++++ libraries/networking/CMakeLists.txt | 2 +- libraries/networking/src/LimitedNodeList.h | 8 ++++--- libraries/networking/src/UUIDCityHasher.cpp | 12 ++++++++++ libraries/networking/src/UUIDCityHasher.h | 26 +++++++++++++++++++++ 5 files changed, 53 insertions(+), 4 deletions(-) create mode 100644 libraries/networking/src/UUIDCityHasher.cpp create mode 100644 libraries/networking/src/UUIDCityHasher.h diff --git a/cmake/modules/FindLibcuckoo.cmake b/cmake/modules/FindLibcuckoo.cmake index dad3d8513e..4e87c650c2 100644 --- a/cmake/modules/FindLibcuckoo.cmake +++ b/cmake/modules/FindLibcuckoo.cmake @@ -21,9 +21,18 @@ hifi_library_search_hints("libcuckoo") find_path(LIBCUCKOO_INCLUDE_DIRS libcuckoo/cuckoohash_map.hh PATH_SUFFIXES include HINTS ${LIBCUCKOO_SEARCH_DIRS}) +find_library(CITYHASH_LIBRARY_RELEASE NAME cityhash PATH_SUFFIXES lib HINTS ${LIBCUCKOO_SEARCH_DIRS}) +find_library(CITYHASH_LIBRARY_DEBUG NAME cityhash PATH_SUFFIXES lib HINTS ${LIBCUCKOO_SEARCH_DIRS}) + +include(SelectLibraryConfigurations) +select_library_configurations(CITYHASH) + +set(LIBCUCKOO_LIBRARIES ${CITYHASH_LIBRARY}) + include(FindPackageHandleStandardArgs) find_package_handle_standard_args( libcuckoo "Could NOT find libcuckoo. Read libraries/networking/externals/libcuckoo/readme.txt" LIBCUCKOO_INCLUDE_DIRS + LIBCUCKOO_LIBRARIES ) \ No newline at end of file diff --git a/libraries/networking/CMakeLists.txt b/libraries/networking/CMakeLists.txt index 021401853f..b650c0942c 100644 --- a/libraries/networking/CMakeLists.txt +++ b/libraries/networking/CMakeLists.txt @@ -25,7 +25,7 @@ endif () include_directories(SYSTEM "${OPENSSL_INCLUDE_DIR}") # append OpenSSL to our list of libraries to link -list(APPEND ${TARGET_NAME}_LIBRARIES_TO_LINK "${OPENSSL_LIBRARIES}") +list(APPEND ${TARGET_NAME}_LIBRARIES_TO_LINK "${OPENSSL_LIBRARIES}" "${LIBCUCKOO_LIBRARIES}") # append libcuckoo includes to our list of includes to bubble list(APPEND ${TARGET_NAME}_DEPENDENCY_INCLUDES "${LIBCUCKOO_INCLUDE_DIRS}") diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index 9e5610ba4e..100e3a53ea 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -26,12 +26,13 @@ #include #include #include -#include +#include #include #include "DomainHandler.h" #include "Node.h" +#include "UUIDCityHasher.h" const int MAX_PACKET_SIZE = 1500; @@ -51,9 +52,10 @@ class HifiSockAddr; typedef QSet NodeSet; typedef QSharedPointer SharedNodePointer; -typedef QHash NodeHash; Q_DECLARE_METATYPE(SharedNodePointer) +typedef cuckoohash_map NodeHash; + typedef quint8 PingType_t; namespace PingType { const PingType_t Agnostic = 0; @@ -159,7 +161,7 @@ protected: void changeSocketBufferSizes(int numBytes); QUuid _sessionUUID; - NodeHash _nodeHash; + cuckoohash_map _nodeHash; QMutex _nodeHashMutex; QUdpSocket _nodeSocket; QUdpSocket* _dtlsSocket; diff --git a/libraries/networking/src/UUIDCityHasher.cpp b/libraries/networking/src/UUIDCityHasher.cpp new file mode 100644 index 0000000000..731e287fc0 --- /dev/null +++ b/libraries/networking/src/UUIDCityHasher.cpp @@ -0,0 +1,12 @@ +// +// UUIDCityHasher.cpp +// libraries/networking/src +// +// Created by Stephen Birarda on 2014-11-05. +// 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 "UUIDCityHasher.h" diff --git a/libraries/networking/src/UUIDCityHasher.h b/libraries/networking/src/UUIDCityHasher.h new file mode 100644 index 0000000000..e27e3bdf1b --- /dev/null +++ b/libraries/networking/src/UUIDCityHasher.h @@ -0,0 +1,26 @@ +// +// UUIDCityHasher.h +// libraries/networking/src +// +// Created by Stephen Birarda on 2014-11-05. +// 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_UUIDCityHasher_h +#define hifi_UUIDCityHasher_h + +#include + +#include "UUID.h" + +class UUIDCityHasher { +public: + size_t operator()(const QUuid& key) const { + return CityHash64(key.toRfc4122().constData(), NUM_BYTES_RFC4122_UUID); + } +}; + +#endif // hifi_UUIDCityHasher_h \ No newline at end of file From a492abc3a1410e5eaab76e72a203976c925b69ef Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 5 Nov 2014 14:40:56 -0800 Subject: [PATCH 009/502] complete LimitedNodeList changes for new cuckoo hash --- libraries/networking/src/LimitedNodeList.cpp | 133 ++++++------------- libraries/networking/src/LimitedNodeList.h | 9 +- libraries/networking/src/Node.cpp | 48 ++++--- libraries/networking/src/Node.h | 2 + libraries/networking/src/NodeList.cpp | 6 +- 5 files changed, 79 insertions(+), 119 deletions(-) diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index 043f0621bb..0f86719761 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -68,7 +68,6 @@ LimitedNodeList* LimitedNodeList::getInstance() { LimitedNodeList::LimitedNodeList(unsigned short socketListenPort, unsigned short dtlsListenPort) : _sessionUUID(), _nodeHash(), - _nodeHashMutex(QMutex::Recursive), _nodeSocket(this), _dtlsSocket(NULL), _localSockAddr(), @@ -344,18 +343,11 @@ int LimitedNodeList::findNodeAndUpdateWithDataFromPacket(const QByteArray& packe } SharedNodePointer LimitedNodeList::nodeWithUUID(const QUuid& nodeUUID, bool blockingLock) { - const int WAIT_TIME = 10; // wait up to 10ms in the try lock case - SharedNodePointer node; - // if caller wants us to block and guarantee the correct answer, then honor that request - if (blockingLock) { - // this will block till we can get access - QMutexLocker locker(&_nodeHashMutex); - node = _nodeHash.value(nodeUUID); - } else if (_nodeHashMutex.tryLock(WAIT_TIME)) { // some callers are willing to get wrong answers but not block - node = _nodeHash.value(nodeUUID); - _nodeHashMutex.unlock(); + try { + return _nodeHash[nodeUUID]; + } catch (std::out_of_range) { + return SharedNodePointer(); } - return node; } SharedNodePointer LimitedNodeList::sendingNodeForPacket(const QByteArray& packet) { @@ -365,22 +357,15 @@ SharedNodePointer LimitedNodeList::sendingNodeForPacket(const QByteArray& packet return nodeWithUUID(nodeUUID); } -NodeHash LimitedNodeList::getNodeHash() { - QMutexLocker locker(&_nodeHashMutex); - return NodeHash(_nodeHash); -} - void LimitedNodeList::eraseAllNodes() { qDebug() << "Clearing the NodeList. Deleting all nodes in list."; - QMutexLocker locker(&_nodeHashMutex); - - NodeHash::iterator nodeItem = _nodeHash.begin(); - - // iterate the nodes in the list - while (nodeItem != _nodeHash.end()) { - nodeItem = killNodeAtHashIterator(nodeItem); + // iterate the current nodes and note that they are going down + for (auto it = _nodeHash.cbegin(); !it.is_end(); it++) { + emit nodeKilled(it->second); } + + _nodeHash.clear(); } void LimitedNodeList::reset() { @@ -388,20 +373,13 @@ void LimitedNodeList::reset() { } void LimitedNodeList::killNodeWithUUID(const QUuid& nodeUUID) { - QMutexLocker locker(&_nodeHashMutex); - - NodeHash::iterator nodeItemToKill = _nodeHash.find(nodeUUID); - if (nodeItemToKill != _nodeHash.end()) { - killNodeAtHashIterator(nodeItemToKill); + SharedNodePointer matchingNode = nodeWithUUID(nodeUUID); + if (matchingNode) { + emit nodeKilled(matchingNode); + _nodeHash.erase(nodeUUID); } } -NodeHash::iterator LimitedNodeList::killNodeAtHashIterator(NodeHash::iterator& nodeItemToKill) { - qDebug() << "Killed" << *nodeItemToKill.value(); - emit nodeKilled(nodeItemToKill.value()); - return _nodeHash.erase(nodeItemToKill); -} - void LimitedNodeList::processKillNode(const QByteArray& dataByteArray) { // read the node id QUuid nodeUUID = QUuid::fromRfc4122(dataByteArray.mid(numBytesForPacketHeader(dataByteArray), NUM_BYTES_RFC4122_UUID)); @@ -411,62 +389,33 @@ void LimitedNodeList::processKillNode(const QByteArray& dataByteArray) { } SharedNodePointer LimitedNodeList::addOrUpdateNode(const QUuid& uuid, NodeType_t nodeType, - const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket) { - _nodeHashMutex.lock(); - - if (!_nodeHash.contains(uuid)) { - + const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket) { + try { + SharedNodePointer matchingNode = _nodeHash[uuid]; + matchingNode->updateSockets(publicSocket, localSocket); + return matchingNode; + } catch (std::out_of_range) { // we didn't have this node, so add them Node* newNode = new Node(uuid, nodeType, publicSocket, localSocket); SharedNodePointer newNodeSharedPointer(newNode, &QObject::deleteLater); _nodeHash.insert(newNode->getUUID(), newNodeSharedPointer); - _nodeHashMutex.unlock(); - qDebug() << "Added" << *newNode; - + emit nodeAdded(newNodeSharedPointer); - + return newNodeSharedPointer; - } else { - _nodeHashMutex.unlock(); - - return updateSocketsForNode(uuid, publicSocket, localSocket); } } -SharedNodePointer LimitedNodeList::updateSocketsForNode(const QUuid& uuid, - const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket) { - - SharedNodePointer matchingNode = nodeWithUUID(uuid); - - if (matchingNode) { - // perform appropriate updates to this node - QMutexLocker locker(&matchingNode->getMutex()); - - // check if we need to change this node's public or local sockets - if (publicSocket != matchingNode->getPublicSocket()) { - matchingNode->setPublicSocket(publicSocket); - qDebug() << "Public socket change for node" << *matchingNode; - } - - if (localSocket != matchingNode->getLocalSocket()) { - matchingNode->setLocalSocket(localSocket); - qDebug() << "Local socket change for node" << *matchingNode; - } - } - - return matchingNode; -} - unsigned LimitedNodeList::broadcastToNodes(const QByteArray& packet, const NodeSet& destinationNodeTypes) { unsigned n = 0; - - foreach (const SharedNodePointer& node, getNodeHash()) { - // only send to the NodeTypes we are asked to send to. - if (destinationNodeTypes.contains(node->getType())) { - writeDatagram(packet, node); + + SnapshotNodeHash snapshotHash = _nodeHash.snapshot_table(); + for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { + if (destinationNodeTypes.contains(it->second->getType())) { + writeDatagram(packet, it->second); ++n; } } @@ -510,9 +459,11 @@ QByteArray LimitedNodeList::constructPingReplyPacket(const QByteArray& pingPacke SharedNodePointer LimitedNodeList::soloNodeOfType(char nodeType) { if (memchr(SOLO_NODE_TYPES, nodeType, sizeof(SOLO_NODE_TYPES))) { - foreach (const SharedNodePointer& node, getNodeHash()) { - if (node->getType() == nodeType) { - return node; + SnapshotNodeHash snapshotHash = _nodeHash.snapshot_table(); + + for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { + if (it->second->getType() == nodeType) { + return it->second; } } } @@ -531,28 +482,20 @@ void LimitedNodeList::resetPacketStats() { } void LimitedNodeList::removeSilentNodes() { - - _nodeHashMutex.lock(); - NodeHash::iterator nodeItem = _nodeHash.begin(); - - while (nodeItem != _nodeHash.end()) { - SharedNodePointer node = nodeItem.value(); - + SnapshotNodeHash snapshotHash = _nodeHash.snapshot_table(); + + for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { + SharedNodePointer node = it->second; node->getMutex().lock(); - + if ((usecTimestampNow() - node->getLastHeardMicrostamp()) > (NODE_SILENCE_THRESHOLD_MSECS * 1000)) { - // call our private method to kill this node (removes it and emits the right signal) - nodeItem = killNodeAtHashIterator(nodeItem); - } else { - // we didn't kill this node, push the iterator forwards - ++nodeItem; + // call the NodeHash erase to get rid of this node + _nodeHash.erase(it->first); } node->getMutex().unlock(); } - - _nodeHashMutex.unlock(); } const uint32_t RFC_5389_MAGIC_COOKIE = 0x2112A442; diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index 100e3a53ea..81daa7ace8 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -55,6 +55,7 @@ typedef QSharedPointer SharedNodePointer; Q_DECLARE_METATYPE(SharedNodePointer) typedef cuckoohash_map NodeHash; +typedef std::vector > SnapshotNodeHash; typedef quint8 PingType_t; namespace PingType { @@ -95,7 +96,7 @@ public: void(*linkedDataCreateCallback)(Node *); - NodeHash getNodeHash(); + const NodeHash& getNodeHash() { return _nodeHash; } int size() const { return _nodeHash.size(); } SharedNodePointer nodeWithUUID(const QUuid& nodeUUID, bool blockingLock = true); @@ -154,15 +155,11 @@ protected: qint64 writeDatagram(const QByteArray& datagram, const HifiSockAddr& destinationSockAddr, const QUuid& connectionSecret); - - NodeHash::iterator killNodeAtHashIterator(NodeHash::iterator& nodeItemToKill); - void changeSocketBufferSizes(int numBytes); QUuid _sessionUUID; - cuckoohash_map _nodeHash; - QMutex _nodeHashMutex; + NodeHash _nodeHash; QUdpSocket _nodeSocket; QUdpSocket* _dtlsSocket; HifiSockAddr _localSockAddr; diff --git a/libraries/networking/src/Node.cpp b/libraries/networking/src/Node.cpp index c2b35d3b7d..de82dde7f0 100644 --- a/libraries/networking/src/Node.cpp +++ b/libraries/networking/src/Node.cpp @@ -94,30 +94,48 @@ void Node::updateClockSkewUsec(int clockSkewSample) { } void Node::setPublicSocket(const HifiSockAddr& publicSocket) { - if (_activeSocket == &_publicSocket) { - // if the active socket was the public socket then reset it to NULL - _activeSocket = NULL; + if (publicSocket != _publicSocket) { + if (_activeSocket == &_publicSocket) { + // if the active socket was the public socket then reset it to NULL + _activeSocket = NULL; + } + + if (!_publicSocket.isNull()) { + qDebug() << "Public socket change for node" << *this; + } + + _publicSocket = publicSocket; } - - _publicSocket = publicSocket; } void Node::setLocalSocket(const HifiSockAddr& localSocket) { - if (_activeSocket == &_localSocket) { - // if the active socket was the local socket then reset it to NULL - _activeSocket = NULL; + if (localSocket != _localSocket) { + if (_activeSocket == &_localSocket) { + // if the active socket was the local socket then reset it to NULL + _activeSocket = NULL; + } + + if (!_localSocket.isNull()) { + qDebug() << "Local socket change for node" << *this; + } + + _localSocket = localSocket; } - - _localSocket = localSocket; } void Node::setSymmetricSocket(const HifiSockAddr& symmetricSocket) { - if (_activeSocket == &_symmetricSocket) { - // if the active socket was the symmetric socket then reset it to NULL - _activeSocket = NULL; + if (symmetricSocket != _symmetricSocket) { + if (_activeSocket == &_symmetricSocket) { + // if the active socket was the symmetric socket then reset it to NULL + _activeSocket = NULL; + } + + if (!_symmetricSocket.isNull()) { + qDebug() << "Symmetric socket change for node" << *this; + } + + _symmetricSocket = symmetricSocket; } - - _symmetricSocket = symmetricSocket; } void Node::activateLocalSocket() { diff --git a/libraries/networking/src/Node.h b/libraries/networking/src/Node.h index acb6c6f453..05b32d0528 100644 --- a/libraries/networking/src/Node.h +++ b/libraries/networking/src/Node.h @@ -81,6 +81,8 @@ public: const HifiSockAddr& getSymmetricSocket() const { return _symmetricSocket; } virtual void setSymmetricSocket(const HifiSockAddr& symmetricSocket); + void updateSockets(const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket); + const HifiSockAddr* getActiveSocket() const { return _activeSocket; } void activatePublicSocket(); diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index ff3b86880d..6621a6d2e2 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -449,10 +449,10 @@ void NodeList::pingPunchForInactiveNode(const SharedNodePointer& node) { } void NodeList::pingInactiveNodes() { - foreach (const SharedNodePointer& node, getNodeHash()) { - if (!node->getActiveSocket()) { + for (auto it = _nodeHash.cbegin(); !it.is_end(); it++) { + if (!it->second->getActiveSocket()) { // we don't have an active link to this node, ping it to set that up - pingPunchForInactiveNode(node); + pingPunchForInactiveNode(it->second); } } } From 8a72cdd59d581c8455c7a0d76c494137a3fca10f Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 5 Nov 2014 15:09:54 -0800 Subject: [PATCH 010/502] leverage new libcuckoo hash outside LimitedNodeList --- assignment-client/src/audio/AudioMixer.cpp | 35 ++++++++++++---- assignment-client/src/avatars/AvatarMixer.cpp | 8 +++- .../src/entities/EntityServer.cpp | 11 +++-- .../octree/OctreeInboundPacketProcessor.cpp | 2 +- assignment-client/src/octree/OctreeServer.cpp | 9 ++-- domain-server/src/DomainServer.cpp | 42 ++++++++++++++----- interface/src/Application.cpp | 20 ++++++--- interface/src/MetavoxelSystem.cpp | 13 +++++- .../metavoxels/src/MetavoxelClientManager.cpp | 12 +++++- libraries/networking/src/LimitedNodeList.cpp | 11 +++-- libraries/networking/src/LimitedNodeList.h | 4 +- libraries/networking/src/Node.h | 2 - libraries/octree/src/JurisdictionListener.cpp | 8 ++-- .../octree/src/OctreeEditPacketSender.cpp | 28 ++++++++----- libraries/octree/src/OctreeHeadlessViewer.cpp | 10 +++-- libraries/script-engine/src/ScriptEngine.cpp | 6 ++- 16 files changed, 157 insertions(+), 64 deletions(-) diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index 6ca93a7b11..39011b8083 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -437,7 +437,12 @@ int AudioMixer::prepareMixForListeningNode(Node* node) { // loop through all other nodes that have sufficient audio to mix int streamsMixed = 0; - foreach (const SharedNodePointer& otherNode, NodeList::getInstance()->getNodeHash()) { + + NodeHashSnapshot snapshotHash = NodeList::getInstance()->getNodeHash().snapshot_table(); + + for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { + SharedNodePointer otherNode = it->second; + if (otherNode->getLinkedData()) { AudioMixerClientData* otherNodeClientData = (AudioMixerClientData*) otherNode->getLinkedData(); @@ -480,7 +485,11 @@ void AudioMixer::readPendingDatagram(const QByteArray& receivedPacket, const Hif QByteArray packet = receivedPacket; populatePacketHeader(packet, PacketTypeMuteEnvironment); - foreach (const SharedNodePointer& node, nodeList->getNodeHash()) { + NodeHashSnapshot snapshotHash = nodeList->getNodeHash().snapshot_table(); + + for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { + SharedNodePointer node = it->second; + if (node->getType() == NodeType::Agent && node->getActiveSocket() && node->getLinkedData() && node != nodeList->sendingNodeForPacket(receivedPacket)) { nodeList->writeDatagram(packet, packet.size(), node); } @@ -548,8 +557,10 @@ void AudioMixer::sendStatsPacket() { NodeList* nodeList = NodeList::getInstance(); int clientNumber = 0; - foreach (const SharedNodePointer& node, nodeList->getNodeHash()) { - + + NodeHashSnapshot snapshotHash = nodeList->getNodeHash().snapshot_table(); + + for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { // if we're too large, send the packet if (sizeOfStats > TOO_BIG_FOR_MTU) { nodeList->sendStatsToDomainServer(statsObject2); @@ -559,9 +570,9 @@ void AudioMixer::sendStatsPacket() { } clientNumber++; - AudioMixerClientData* clientData = static_cast(node->getLinkedData()); + AudioMixerClientData* clientData = static_cast(it->second->getLinkedData()); if (clientData) { - QString property = "jitterStats." + node->getUUID().toString(); + QString property = "jitterStats." + it->first.toString(); QString value = clientData->getAudioStreamStatsString(); statsObject2[qPrintable(property)] = value; somethingToSend = true; @@ -706,7 +717,11 @@ void AudioMixer::run() { _lastPerSecondCallbackTime = now; } - foreach (const SharedNodePointer& node, nodeList->getNodeHash()) { + NodeHashSnapshot snapshotHash = nodeList->getNodeHash().snapshot_table(); + + for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { + SharedNodePointer node = it->second; + if (node->getLinkedData()) { AudioMixerClientData* nodeData = (AudioMixerClientData*)node->getLinkedData(); @@ -873,7 +888,11 @@ void AudioMixer::perSecondActions() { _timeSpentPerHashMatchCallStats.getWindowSum() / WINDOW_LENGTH_USECS * 100.0, _timeSpentPerHashMatchCallStats.getCurrentIntervalSum() / USECS_PER_SECOND * 100.0); - foreach(const SharedNodePointer& node, NodeList::getInstance()->getNodeHash()) { + NodeHashSnapshot snapshotHash = NodeList::getInstance()->getNodeHash().snapshot_table(); + + for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { + SharedNodePointer node = it->second; + if (node->getLinkedData()) { AudioMixerClientData* nodeData = (AudioMixerClientData*)node->getLinkedData(); diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index 3ec7c5cfbf..3c2fa92c7c 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -122,7 +122,9 @@ void AvatarMixer::broadcastAvatarData() { AvatarMixerClientData* nodeData = NULL; AvatarMixerClientData* otherNodeData = NULL; - foreach (const SharedNodePointer& node, nodeList->getNodeHash()) { + NodeHashSnapshot snapshotHash = nodeList->getNodeHash().snapshot_table(); + for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { + SharedNodePointer node = it->second; if (node->getLinkedData() && node->getType() == NodeType::Agent && node->getActiveSocket() && (nodeData = reinterpret_cast(node->getLinkedData()))->getMutex().tryLock()) { ++_sumListeners; @@ -135,7 +137,9 @@ void AvatarMixer::broadcastAvatarData() { // this is an AGENT we have received head data from // send back a packet with other active node data to this node - foreach (const SharedNodePointer& otherNode, nodeList->getNodeHash()) { + NodeHashSnapshot snapshotHash = nodeList->getNodeHash().snapshot_table(); + for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { + SharedNodePointer otherNode = it->second; if (otherNode->getLinkedData() && otherNode->getUUID() != node->getUUID() && (otherNodeData = reinterpret_cast(otherNode->getLinkedData()))->getMutex().tryLock()) { diff --git a/assignment-client/src/entities/EntityServer.cpp b/assignment-client/src/entities/EntityServer.cpp index 2b7d6873cc..31999f91f7 100644 --- a/assignment-client/src/entities/EntityServer.cpp +++ b/assignment-client/src/entities/EntityServer.cpp @@ -123,9 +123,14 @@ void EntityServer::pruneDeletedEntities() { if (tree->hasAnyDeletedEntities()) { quint64 earliestLastDeletedEntitiesSent = usecTimestampNow() + 1; // in the future - foreach (const SharedNodePointer& otherNode, NodeList::getInstance()->getNodeHash()) { - if (otherNode->getLinkedData()) { - EntityNodeData* nodeData = static_cast(otherNode->getLinkedData()); + + NodeHashSnapshot snapshotHash = NodeList::getInstance()->getNodeHash().snapshot_table(); + + for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { + SharedNodePointer node = it->second; + + if (node->getLinkedData()) { + EntityNodeData* nodeData = static_cast(node->getLinkedData()); quint64 nodeLastDeletedEntitiesSentAt = nodeData->getLastDeletedEntitiesSentAt(); if (nodeLastDeletedEntitiesSentAt < earliestLastDeletedEntitiesSent) { earliestLastDeletedEntitiesSent = nodeLastDeletedEntitiesSentAt; diff --git a/assignment-client/src/octree/OctreeInboundPacketProcessor.cpp b/assignment-client/src/octree/OctreeInboundPacketProcessor.cpp index bd3a7ceee5..b85eb46ebc 100644 --- a/assignment-client/src/octree/OctreeInboundPacketProcessor.cpp +++ b/assignment-client/src/octree/OctreeInboundPacketProcessor.cpp @@ -248,7 +248,7 @@ int OctreeInboundPacketProcessor::sendNackPackets() { continue; } - const SharedNodePointer& destinationNode = NodeList::getInstance()->getNodeHash().value(nodeUUID); + const SharedNodePointer& destinationNode = NodeList::getInstance()->nodeWithUUID(nodeUUID); // retrieve sequence number stats of node, prune its missing set SequenceNumberStats& sequenceNumberStats = nodeStats.getIncomingEditSequenceNumberStats(); diff --git a/assignment-client/src/octree/OctreeServer.cpp b/assignment-client/src/octree/OctreeServer.cpp index 121cac0273..2b38ce3cdd 100644 --- a/assignment-client/src/octree/OctreeServer.cpp +++ b/assignment-client/src/octree/OctreeServer.cpp @@ -1137,9 +1137,12 @@ void OctreeServer::aboutToFinish() { qDebug() << qPrintable(_safeServerName) << "server STARTING about to finish..."; qDebug() << qPrintable(_safeServerName) << "inform Octree Inbound Packet Processor that we are shutting down..."; _octreeInboundPacketProcessor->shuttingDown(); - foreach (const SharedNodePointer& node, NodeList::getInstance()->getNodeHash()) { - qDebug() << qPrintable(_safeServerName) << "server about to finish while node still connected node:" << *node; - forceNodeShutdown(node); + + NodeHashSnapshot snapshotHash = NodeList::getInstance()->getNodeHash().snapshot_table(); + + for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { + qDebug() << qPrintable(_safeServerName) << "server about to finish while node still connected node:" << *it->second; + forceNodeShutdown(it->second); } qDebug() << qPrintable(_safeServerName) << "server ENDING about to finish..."; } diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index dbaaca43fa..5dddfd70dd 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -821,7 +821,10 @@ void DomainServer::sendDomainListToNode(const SharedNodePointer& node, const Hif if (nodeData->isAuthenticated()) { // if this authenticated node has any interest types, send back those nodes as well - foreach (const SharedNodePointer& otherNode, nodeList->getNodeHash()) { + NodeHashSnapshot snapshotHash = nodeList->getNodeHash().snapshot_table(); + + for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { + SharedNodePointer otherNode = it->second; // reset our nodeByteArray and nodeDataStream QByteArray nodeByteArray; @@ -960,7 +963,10 @@ void DomainServer::readAvailableDatagrams() { void DomainServer::setupPendingAssignmentCredits() { // enumerate the NodeList to find the assigned nodes - foreach (const SharedNodePointer& node, LimitedNodeList::getInstance()->getNodeHash()) { + NodeHashSnapshot snapshotHash = NodeList::getInstance()->getNodeHash().snapshot_table(); + + for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { + SharedNodePointer node = it->second; DomainServerNodeData* nodeData = reinterpret_cast(node->getLinkedData()); if (!nodeData->getAssignmentUUID().isNull() && !nodeData->getWalletUUID().isNull()) { @@ -1119,7 +1125,13 @@ void DomainServer::sendHeartbeatToDataServer(const QString& networkAddress) { // add the number of currently connected agent users int numConnectedAuthedUsers = 0; - foreach(const SharedNodePointer& node, LimitedNodeList::getInstance()->getNodeHash()) { + + NodeHashSnapshot snapshotHash = NodeList::getInstance()->getNodeHash().snapshot_table(); + + for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { + + SharedNodePointer node = it->second; + if (node->getLinkedData() && !static_cast(node->getLinkedData())->getUsername().isEmpty()) { ++numConnectedAuthedUsers; } @@ -1242,8 +1254,9 @@ void DomainServer::processDatagram(const QByteArray& receivedPacket, const HifiS parseNodeDataFromByteArray(packetStream, throwawayNodeType, nodePublicAddress, nodeLocalAddress, senderSockAddr); - SharedNodePointer checkInNode = nodeList->updateSocketsForNode(nodeUUID, - nodePublicAddress, nodeLocalAddress); + SharedNodePointer checkInNode = nodeList->nodeWithUUID(nodeUUID); + checkInNode->setPublicSocket(nodePublicAddress); + checkInNode->setLocalSocket(nodeLocalAddress); // update last receive to now quint64 timeNow = usecTimestampNow(); @@ -1425,7 +1438,12 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url QJsonObject assignedNodesJSON; // enumerate the NodeList to find the assigned nodes - foreach (const SharedNodePointer& node, LimitedNodeList::getInstance()->getNodeHash()) { + NodeHashSnapshot snapshotHash = NodeList::getInstance()->getNodeHash().snapshot_table(); + + for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { + + SharedNodePointer node = it->second; + DomainServerNodeData* nodeData = reinterpret_cast(node->getLinkedData()); if (!nodeData->getAssignmentUUID().isNull()) { @@ -1489,9 +1507,11 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url // enumerate the NodeList to find the assigned nodes LimitedNodeList* nodeList = LimitedNodeList::getInstance(); - foreach (const SharedNodePointer& node, nodeList->getNodeHash()) { + NodeHashSnapshot snapshotHash = nodeList->getNodeHash().snapshot_table(); + + for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { // add the node using the UUID as the key - nodesJSONArray.append(jsonObjectForNode(node)); + nodesJSONArray.append(jsonObjectForNode(it->second)); } rootJSON["nodes"] = nodesJSONArray; @@ -2023,8 +2043,10 @@ void DomainServer::addStaticAssignmentsToQueue() { bool foundMatchingAssignment = false; // enumerate the nodes and check if there is one with an attached assignment with matching UUID - foreach (const SharedNodePointer& node, LimitedNodeList::getInstance()->getNodeHash()) { - if (node->getUUID() == staticAssignment->data()->getUUID()) { + NodeHashSnapshot snapshotHash = NodeList::getInstance()->getNodeHash().snapshot_table(); + + for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { + if (it->first == staticAssignment->data()->getUUID()) { foundMatchingAssignment = true; } } diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 6d8b612bc3..f5842ed4c3 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2405,7 +2405,10 @@ int Application::sendNackPackets() { char packet[MAX_PACKET_SIZE]; // iterates thru all nodes in NodeList - foreach(const SharedNodePointer& node, NodeList::getInstance()->getNodeHash()) { + NodeHashSnapshot snapshotHash = NodeList::getInstance()->getNodeHash().snapshot_table(); + + for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { + SharedNodePointer node = it->second; if (node->getActiveSocket() && ( node->getType() == NodeType::VoxelServer @@ -2503,7 +2506,13 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node int inViewServers = 0; int unknownJurisdictionServers = 0; - foreach (const SharedNodePointer& node, NodeList::getInstance()->getNodeHash()) { + NodeList* nodeList = NodeList::getInstance(); + NodeHashSnapshot snapshotHash = nodeList->getNodeHash().snapshot_table(); + + for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { + + SharedNodePointer node = it->second; + // only send to the NodeTypes that are serverType if (node->getActiveSocket() && node->getType() == serverType) { totalServers++; @@ -2560,10 +2569,9 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node if (wantExtraDebugging) { qDebug("perServerPPS: %d perUnknownServer: %d", perServerPPS, perUnknownServer); } - - NodeList* nodeList = NodeList::getInstance(); - - foreach (const SharedNodePointer& node, nodeList->getNodeHash()) { + + for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { + SharedNodePointer node = it->second; // only send to the NodeTypes that are serverType if (node->getActiveSocket() && node->getType() == serverType) { diff --git a/interface/src/MetavoxelSystem.cpp b/interface/src/MetavoxelSystem.cpp index 4c0acc553a..20a7bc906f 100644 --- a/interface/src/MetavoxelSystem.cpp +++ b/interface/src/MetavoxelSystem.cpp @@ -163,7 +163,12 @@ void MetavoxelSystem::render() { } void MetavoxelSystem::refreshVoxelData() { - foreach (const SharedNodePointer& node, NodeList::getInstance()->getNodeHash()) { + NodeHashSnapshot snapshotHash = NodeList::getInstance()->getNodeHash().snapshot_table(); + + for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { + + SharedNodePointer node = it->second; + if (node->getType() == NodeType::MetavoxelServer) { QMutexLocker locker(&node->getMutex()); MetavoxelSystemClient* client = static_cast(node->getLinkedData()); @@ -685,7 +690,11 @@ MetavoxelClient* MetavoxelSystem::createClient(const SharedNodePointer& node) { } void MetavoxelSystem::guideToAugmented(MetavoxelVisitor& visitor, bool render) { - foreach (const SharedNodePointer& node, NodeList::getInstance()->getNodeHash()) { + NodeHashSnapshot snapshotHash = NodeList::getInstance()->getNodeHash().snapshot_table(); + + for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { + SharedNodePointer node = it->second; + if (node->getType() == NodeType::MetavoxelServer) { QMutexLocker locker(&node->getMutex()); MetavoxelSystemClient* client = static_cast(node->getLinkedData()); diff --git a/libraries/metavoxels/src/MetavoxelClientManager.cpp b/libraries/metavoxels/src/MetavoxelClientManager.cpp index f1c086da67..7765b8cda2 100644 --- a/libraries/metavoxels/src/MetavoxelClientManager.cpp +++ b/libraries/metavoxels/src/MetavoxelClientManager.cpp @@ -42,7 +42,11 @@ SharedObjectPointer MetavoxelClientManager::findFirstRaySpannerIntersection(cons const glm::vec3& direction, const AttributePointer& attribute, float& distance) { SharedObjectPointer closestSpanner; float closestDistance = FLT_MAX; - foreach (const SharedNodePointer& node, NodeList::getInstance()->getNodeHash()) { + + NodeHashSnapshot snapshotHash = NodeList::getInstance()->getNodeHash().snapshot_table(); + for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { + SharedNodePointer node = it->second; + if (node->getType() == NodeType::MetavoxelServer) { QMutexLocker locker(&node->getMutex()); MetavoxelClient* client = static_cast(node->getLinkedData()); @@ -115,7 +119,11 @@ MetavoxelClient* MetavoxelClientManager::createClient(const SharedNodePointer& n } void MetavoxelClientManager::guide(MetavoxelVisitor& visitor) { - foreach (const SharedNodePointer& node, NodeList::getInstance()->getNodeHash()) { + NodeHashSnapshot snapshotHash = NodeList::getInstance()->getNodeHash().snapshot_table(); + + for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { + SharedNodePointer node = it->second; + if (node->getType() == NodeType::MetavoxelServer) { QMutexLocker locker(&node->getMutex()); MetavoxelClient* client = static_cast(node->getLinkedData()); diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index 0f86719761..5a103076b6 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -392,7 +392,10 @@ SharedNodePointer LimitedNodeList::addOrUpdateNode(const QUuid& uuid, NodeType_t const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket) { try { SharedNodePointer matchingNode = _nodeHash[uuid]; - matchingNode->updateSockets(publicSocket, localSocket); + + matchingNode->setPublicSocket(publicSocket); + matchingNode->setLocalSocket(localSocket); + return matchingNode; } catch (std::out_of_range) { // we didn't have this node, so add them @@ -412,7 +415,7 @@ SharedNodePointer LimitedNodeList::addOrUpdateNode(const QUuid& uuid, NodeType_t unsigned LimitedNodeList::broadcastToNodes(const QByteArray& packet, const NodeSet& destinationNodeTypes) { unsigned n = 0; - SnapshotNodeHash snapshotHash = _nodeHash.snapshot_table(); + NodeHashSnapshot snapshotHash = _nodeHash.snapshot_table(); for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { if (destinationNodeTypes.contains(it->second->getType())) { writeDatagram(packet, it->second); @@ -459,7 +462,7 @@ QByteArray LimitedNodeList::constructPingReplyPacket(const QByteArray& pingPacke SharedNodePointer LimitedNodeList::soloNodeOfType(char nodeType) { if (memchr(SOLO_NODE_TYPES, nodeType, sizeof(SOLO_NODE_TYPES))) { - SnapshotNodeHash snapshotHash = _nodeHash.snapshot_table(); + NodeHashSnapshot snapshotHash = _nodeHash.snapshot_table(); for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { if (it->second->getType() == nodeType) { @@ -483,7 +486,7 @@ void LimitedNodeList::resetPacketStats() { void LimitedNodeList::removeSilentNodes() { - SnapshotNodeHash snapshotHash = _nodeHash.snapshot_table(); + NodeHashSnapshot snapshotHash = _nodeHash.snapshot_table(); for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { SharedNodePointer node = it->second; diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index 81daa7ace8..63f93458f3 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -55,7 +55,7 @@ typedef QSharedPointer SharedNodePointer; Q_DECLARE_METATYPE(SharedNodePointer) typedef cuckoohash_map NodeHash; -typedef std::vector > SnapshotNodeHash; +typedef std::vector > NodeHashSnapshot; typedef quint8 PingType_t; namespace PingType { @@ -104,8 +104,6 @@ public: SharedNodePointer addOrUpdateNode(const QUuid& uuid, NodeType_t nodeType, const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket); - SharedNodePointer updateSocketsForNode(const QUuid& uuid, - const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket); const HifiSockAddr& getLocalSockAddr() const { return _localSockAddr; } diff --git a/libraries/networking/src/Node.h b/libraries/networking/src/Node.h index 05b32d0528..acb6c6f453 100644 --- a/libraries/networking/src/Node.h +++ b/libraries/networking/src/Node.h @@ -81,8 +81,6 @@ public: const HifiSockAddr& getSymmetricSocket() const { return _symmetricSocket; } virtual void setSymmetricSocket(const HifiSockAddr& symmetricSocket); - void updateSockets(const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket); - const HifiSockAddr* getActiveSocket() const { return _activeSocket; } void activatePublicSocket(); diff --git a/libraries/octree/src/JurisdictionListener.cpp b/libraries/octree/src/JurisdictionListener.cpp index f3d9e31acc..606a6c13f2 100644 --- a/libraries/octree/src/JurisdictionListener.cpp +++ b/libraries/octree/src/JurisdictionListener.cpp @@ -40,9 +40,11 @@ bool JurisdictionListener::queueJurisdictionRequest() { NodeList* nodeList = NodeList::getInstance(); - foreach (const SharedNodePointer& node, nodeList->getNodeHash()) { - if (node->getType() == getNodeType() && node->getActiveSocket()) { - _packetSender.queuePacketForSending(node, QByteArray(reinterpret_cast(bufferOut), sizeOut)); + NodeHashSnapshot nodeHashSnapshot = nodeList->getNodeHash().snapshot_table(); + + for (auto it = nodeHashSnapshot.begin(); it != nodeHashSnapshot.end(); it++) { + if (it->second->getType() == getNodeType() && it->second->getActiveSocket()) { + _packetSender.queuePacketForSending(it->second, QByteArray(reinterpret_cast(bufferOut), sizeOut)); nodeCount++; } } diff --git a/libraries/octree/src/OctreeEditPacketSender.cpp b/libraries/octree/src/OctreeEditPacketSender.cpp index 65308f906f..19de2e37e9 100644 --- a/libraries/octree/src/OctreeEditPacketSender.cpp +++ b/libraries/octree/src/OctreeEditPacketSender.cpp @@ -52,12 +52,13 @@ bool OctreeEditPacketSender::serversExist() const { bool hasServers = false; bool atLeastOneJurisdictionMissing = false; // assume the best NodeList* nodeList = NodeList::getInstance(); - - foreach (const SharedNodePointer& node, nodeList->getNodeHash()) { - + + NodeHashSnapshot snapshotHash = nodeList->getNodeHash().snapshot_table(); + for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { // only send to the NodeTypes that are getMyNodeType() + SharedNodePointer node = it->second; if (node->getType() == getMyNodeType() && node->getActiveSocket()) { - + QUuid nodeUUID = node->getUUID(); // If we've got Jurisdictions set, then check to see if we know the jurisdiction for this server if (_serverJurisdictions) { @@ -86,8 +87,11 @@ void OctreeEditPacketSender::queuePacketToNode(const QUuid& nodeUUID, unsigned c bool wantDebug = false; NodeList* nodeList = NodeList::getInstance(); - - foreach (const SharedNodePointer& node, nodeList->getNodeHash()) { + + NodeHashSnapshot snapshotHash = nodeList->getNodeHash().snapshot_table(); + for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { + SharedNodePointer node = it->second; + // only send to the NodeTypes that are getMyNodeType() if (node->getType() == getMyNodeType() && ((node->getUUID() == nodeUUID) || (nodeUUID.isNull()))) { @@ -194,8 +198,10 @@ void OctreeEditPacketSender::queuePacketToNodes(unsigned char* buffer, size_t le // But we can't really do that with a packed message, since each edit message could be destined // for a different server... So we need to actually manage multiple queued packets... one // for each server - - foreach (const SharedNodePointer& node, NodeList::getInstance()->getNodeHash()) { + + NodeHashSnapshot snapshotHash = NodeList::getInstance()->getNodeHash().snapshot_table(); + for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { + SharedNodePointer node = it->second; // only send to the NodeTypes that are getMyNodeType() if (node->getActiveSocket() && node->getType() == getMyNodeType()) { QUuid nodeUUID = node->getUUID(); @@ -249,7 +255,9 @@ void OctreeEditPacketSender::queueOctreeEditMessage(PacketType type, unsigned ch _packetsQueueLock.lock(); - foreach (const SharedNodePointer& node, NodeList::getInstance()->getNodeHash()) { + NodeHashSnapshot snapshotHash = NodeList::getInstance()->getNodeHash().snapshot_table(); + for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { + SharedNodePointer node = it->second; // only send to the NodeTypes that are getMyNodeType() if (node->getActiveSocket() && node->getType() == getMyNodeType()) { QUuid nodeUUID = node->getUUID(); @@ -384,7 +392,7 @@ void OctreeEditPacketSender::processNackPacket(const QByteArray& packet) { // retrieve packet from history const QByteArray* packet = sentPacketHistory.getPacket(sequenceNumber); if (packet) { - const SharedNodePointer& node = NodeList::getInstance()->getNodeHash().value(sendingNodeUUID); + const SharedNodePointer& node = NodeList::getInstance()->nodeWithUUID(sendingNodeUUID); queuePacketForSending(node, *packet); } } diff --git a/libraries/octree/src/OctreeHeadlessViewer.cpp b/libraries/octree/src/OctreeHeadlessViewer.cpp index 2f21c7a899..b363c654c1 100644 --- a/libraries/octree/src/OctreeHeadlessViewer.cpp +++ b/libraries/octree/src/OctreeHeadlessViewer.cpp @@ -76,8 +76,10 @@ void OctreeHeadlessViewer::queryOctree() { int totalServers = 0; int inViewServers = 0; int unknownJurisdictionServers = 0; - - foreach (const SharedNodePointer& node, NodeList::getInstance()->getNodeHash()) { + + NodeHashSnapshot snapshotHash = NodeList::getInstance()->getNodeHash().snapshot_table(); + for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { + SharedNodePointer node = it->second; // only send to the NodeTypes that are serverType if (node->getActiveSocket() && node->getType() == serverType) { totalServers++; @@ -142,11 +144,11 @@ void OctreeHeadlessViewer::queryOctree() { NodeList* nodeList = NodeList::getInstance(); - foreach (const SharedNodePointer& node, nodeList->getNodeHash()) { + for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { + SharedNodePointer node = it->second; // only send to the NodeTypes that are serverType if (node->getActiveSocket() && node->getType() == serverType) { - // get the server bounds for this server QUuid nodeUUID = node->getUUID(); diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index fb98124fc9..340d5b3e20 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -520,7 +520,11 @@ void ScriptEngine::run() { // write audio packet to AudioMixer nodes NodeList* nodeList = NodeList::getInstance(); - foreach(const SharedNodePointer& node, nodeList->getNodeHash()) { + NodeHashSnapshot snapshotHash = nodeList->getNodeHash().snapshot_table(); + + for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { + SharedNodePointer node = it->second; + // only send to nodes of type AudioMixer if (node->getType() == NodeType::AudioMixer) { // pack sequence number From 63c5dacdd07a93cbb3455c453746aee09a5b5aa7 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 5 Nov 2014 15:12:42 -0800 Subject: [PATCH 011/502] final changes to use new hash from LimitedNodeList --- interface/src/ui/NodeBounds.cpp | 7 +++++-- interface/src/ui/OctreeStatsDialog.cpp | 6 ++++-- interface/src/ui/Stats.cpp | 7 +++++-- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/interface/src/ui/NodeBounds.cpp b/interface/src/ui/NodeBounds.cpp index 49509cc9cf..6298385c90 100644 --- a/interface/src/ui/NodeBounds.cpp +++ b/interface/src/ui/NodeBounds.cpp @@ -53,8 +53,11 @@ void NodeBounds::draw() { float selectedScale = 0; NodeList* nodeList = NodeList::getInstance(); - - foreach (const SharedNodePointer& node, nodeList->getNodeHash()) { + NodeHashSnapshot snapshotHash = nodeList->getNodeHash().snapshot_table(); + + for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { + SharedNodePointer node = it->second; + NodeType_t nodeType = node->getType(); if (nodeType == NodeType::VoxelServer && _showVoxelNodes) { diff --git a/interface/src/ui/OctreeStatsDialog.cpp b/interface/src/ui/OctreeStatsDialog.cpp index e51b9b1f42..8a6d6442f5 100644 --- a/interface/src/ui/OctreeStatsDialog.cpp +++ b/interface/src/ui/OctreeStatsDialog.cpp @@ -248,8 +248,10 @@ void OctreeStatsDialog::showOctreeServersOfType(int& serverCount, NodeType_t ser QLocale locale(QLocale::English); NodeList* nodeList = NodeList::getInstance(); - - foreach (const SharedNodePointer& node, nodeList->getNodeHash()) { + NodeHashSnapshot snapshotHash = nodeList->getNodeHash().snapshot_table(); + + for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { + SharedNodePointer node = it->second; // only send to the NodeTypes that are NodeType_t_VOXEL_SERVER if (node->getType() == serverType) { serverCount++; diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index 9bad475838..8e4b900180 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -328,8 +328,11 @@ void Stats::display( // Now handle voxel servers, since there could be more than one, we average their ping times unsigned long totalPingVoxel = 0; int voxelServerCount = 0; - - foreach (const SharedNodePointer& node, nodeList->getNodeHash()) { + + NodeHashSnapshot snapshotHash = nodeList->getNodeHash().snapshot_table(); + + for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { + SharedNodePointer node = it->second; // TODO: this should also support entities if (node->getType() == NodeType::VoxelServer) { totalPingVoxel += node->getPingMs(); From a39ed798aea41f9407bfee66869e77845f659573 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 5 Nov 2014 15:45:51 -0800 Subject: [PATCH 012/502] replace libcuckoo requirement with tbb --- cmake/modules/FindLibcuckoo.cmake | 38 ---- cmake/modules/FindTBB.cmake | 283 ++++++++++++++++++++++++++ libraries/networking/CMakeLists.txt | 8 +- libraries/networking/src/NodeList.cpp | 3 +- 4 files changed, 288 insertions(+), 44 deletions(-) delete mode 100644 cmake/modules/FindLibcuckoo.cmake create mode 100644 cmake/modules/FindTBB.cmake diff --git a/cmake/modules/FindLibcuckoo.cmake b/cmake/modules/FindLibcuckoo.cmake deleted file mode 100644 index 4e87c650c2..0000000000 --- a/cmake/modules/FindLibcuckoo.cmake +++ /dev/null @@ -1,38 +0,0 @@ -# FindLibCuckoo.cmake -# -# Try to find libcuckoo. -# -# You can provide a LIBCUCKOO_ROOT_DIR which contains src and include directories -# -# Once done this will define -# -# LIBCUCKOO_FOUND - system found libcuckoo -# LIBCUCKOO_INCLUDE_DIRS - the libcuckoo include directory -# -# Created on 5/11/2014 by Stephen Birarda -# 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("${MACRO_DIR}/HifiLibrarySearchHints.cmake") -hifi_library_search_hints("libcuckoo") - -find_path(LIBCUCKOO_INCLUDE_DIRS libcuckoo/cuckoohash_map.hh PATH_SUFFIXES include HINTS ${LIBCUCKOO_SEARCH_DIRS}) - -find_library(CITYHASH_LIBRARY_RELEASE NAME cityhash PATH_SUFFIXES lib HINTS ${LIBCUCKOO_SEARCH_DIRS}) -find_library(CITYHASH_LIBRARY_DEBUG NAME cityhash PATH_SUFFIXES lib HINTS ${LIBCUCKOO_SEARCH_DIRS}) - -include(SelectLibraryConfigurations) -select_library_configurations(CITYHASH) - -set(LIBCUCKOO_LIBRARIES ${CITYHASH_LIBRARY}) - -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args( - libcuckoo - "Could NOT find libcuckoo. Read libraries/networking/externals/libcuckoo/readme.txt" - LIBCUCKOO_INCLUDE_DIRS - LIBCUCKOO_LIBRARIES -) \ No newline at end of file diff --git a/cmake/modules/FindTBB.cmake b/cmake/modules/FindTBB.cmake new file mode 100644 index 0000000000..e5ca100391 --- /dev/null +++ b/cmake/modules/FindTBB.cmake @@ -0,0 +1,283 @@ +# Locate Intel Threading Building Blocks include paths and libraries +# FindTBB.cmake can be found at https://code.google.com/p/findtbb/ +# Written by Hannes Hofmann +# Improvements by Gino van den Bergen , +# Florian Uhlig , +# Jiri Marsik + +# The MIT License +# +# Copyright (c) 2011 Hannes Hofmann +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +# GvdB: This module uses the environment variable TBB_ARCH_PLATFORM which defines architecture and compiler. +# e.g. "ia32/vc8" or "em64t/cc4.1.0_libc2.4_kernel2.6.16.21" +# TBB_ARCH_PLATFORM is set by the build script tbbvars[.bat|.sh|.csh], which can be found +# in the TBB installation directory (TBB_INSTALL_DIR). +# +# GvdB: Mac OS X distribution places libraries directly in lib directory. +# +# For backwards compatibility, you may explicitely set the CMake variables TBB_ARCHITECTURE and TBB_COMPILER. +# TBB_ARCHITECTURE [ ia32 | em64t | itanium ] +# which architecture to use +# TBB_COMPILER e.g. vc9 or cc3.2.3_libc2.3.2_kernel2.4.21 or cc4.0.1_os10.4.9 +# which compiler to use (detected automatically on Windows) + +# This module respects +# TBB_INSTALL_DIR or $ENV{TBB21_INSTALL_DIR} or $ENV{TBB_INSTALL_DIR} + +# This module defines +# TBB_INCLUDE_DIRS, where to find task_scheduler_init.h, etc. +# TBB_LIBRARY_DIRS, where to find libtbb, libtbbmalloc +# TBB_DEBUG_LIBRARY_DIRS, where to find libtbb_debug, libtbbmalloc_debug +# TBB_INSTALL_DIR, the base TBB install directory +# TBB_LIBRARIES, the libraries to link against to use TBB. +# TBB_DEBUG_LIBRARIES, the libraries to link against to use TBB with debug symbols. +# TBB_FOUND, If false, don't try to use TBB. +# TBB_INTERFACE_VERSION, as defined in tbb/tbb_stddef.h + + +if (WIN32) + # has em64t/vc8 em64t/vc9 + # has ia32/vc7.1 ia32/vc8 ia32/vc9 + set(_TBB_DEFAULT_INSTALL_DIR "C:/Program Files/Intel/TBB" "C:/Program Files (x86)/Intel/TBB") + set(_TBB_LIB_NAME "tbb") + set(_TBB_LIB_MALLOC_NAME "${_TBB_LIB_NAME}malloc") + set(_TBB_LIB_DEBUG_NAME "${_TBB_LIB_NAME}_debug") + set(_TBB_LIB_MALLOC_DEBUG_NAME "${_TBB_LIB_MALLOC_NAME}_debug") + if (MSVC71) + set (_TBB_COMPILER "vc7.1") + endif(MSVC71) + if (MSVC80) + set(_TBB_COMPILER "vc8") + endif(MSVC80) + if (MSVC90) + set(_TBB_COMPILER "vc9") + endif(MSVC90) + if(MSVC10) + set(_TBB_COMPILER "vc10") + endif(MSVC10) + # Todo: add other Windows compilers such as ICL. + set(_TBB_ARCHITECTURE ${TBB_ARCHITECTURE}) +endif (WIN32) + +if (UNIX) + if (APPLE) + # MAC + set(_TBB_DEFAULT_INSTALL_DIR "/Library/Frameworks/Intel_TBB.framework/Versions") + # libs: libtbb.dylib, libtbbmalloc.dylib, *_debug + set(_TBB_LIB_NAME "tbb") + set(_TBB_LIB_MALLOC_NAME "${_TBB_LIB_NAME}malloc") + set(_TBB_LIB_DEBUG_NAME "${_TBB_LIB_NAME}_debug") + set(_TBB_LIB_MALLOC_DEBUG_NAME "${_TBB_LIB_MALLOC_NAME}_debug") + # default flavor on apple: ia32/cc4.0.1_os10.4.9 + # Jiri: There is no reason to presume there is only one flavor and + # that user's setting of variables should be ignored. + if(NOT TBB_COMPILER) + set(_TBB_COMPILER "cc4.0.1_os10.4.9") + elseif (NOT TBB_COMPILER) + set(_TBB_COMPILER ${TBB_COMPILER}) + endif(NOT TBB_COMPILER) + if(NOT TBB_ARCHITECTURE) + set(_TBB_ARCHITECTURE "ia32") + elseif(NOT TBB_ARCHITECTURE) + set(_TBB_ARCHITECTURE ${TBB_ARCHITECTURE}) + endif(NOT TBB_ARCHITECTURE) + else (APPLE) + # LINUX + set(_TBB_DEFAULT_INSTALL_DIR "/opt/intel/tbb" "/usr/local/include" "/usr/include") + set(_TBB_LIB_NAME "tbb") + set(_TBB_LIB_MALLOC_NAME "${_TBB_LIB_NAME}malloc") + set(_TBB_LIB_DEBUG_NAME "${_TBB_LIB_NAME}_debug") + set(_TBB_LIB_MALLOC_DEBUG_NAME "${_TBB_LIB_MALLOC_NAME}_debug") + # has em64t/cc3.2.3_libc2.3.2_kernel2.4.21 em64t/cc3.3.3_libc2.3.3_kernel2.6.5 em64t/cc3.4.3_libc2.3.4_kernel2.6.9 em64t/cc4.1.0_libc2.4_kernel2.6.16.21 + # has ia32/* + # has itanium/* + set(_TBB_COMPILER ${TBB_COMPILER}) + set(_TBB_ARCHITECTURE ${TBB_ARCHITECTURE}) + endif (APPLE) +endif (UNIX) + +if (CMAKE_SYSTEM MATCHES "SunOS.*") +# SUN +# not yet supported +# has em64t/cc3.4.3_kernel5.10 +# has ia32/* +endif (CMAKE_SYSTEM MATCHES "SunOS.*") + + +#-- Clear the public variables +set (TBB_FOUND "NO") + + +#-- Find TBB install dir and set ${_TBB_INSTALL_DIR} and cached ${TBB_INSTALL_DIR} +# first: use CMake variable TBB_INSTALL_DIR +if (TBB_INSTALL_DIR) + set (_TBB_INSTALL_DIR ${TBB_INSTALL_DIR}) +endif (TBB_INSTALL_DIR) +# second: use environment variable +if (NOT _TBB_INSTALL_DIR) + if (NOT "$ENV{TBB_INSTALL_DIR}" STREQUAL "") + set (_TBB_INSTALL_DIR $ENV{TBB_INSTALL_DIR}) + endif (NOT "$ENV{TBB_INSTALL_DIR}" STREQUAL "") + # Intel recommends setting TBB21_INSTALL_DIR + if (NOT "$ENV{TBB21_INSTALL_DIR}" STREQUAL "") + set (_TBB_INSTALL_DIR $ENV{TBB21_INSTALL_DIR}) + endif (NOT "$ENV{TBB21_INSTALL_DIR}" STREQUAL "") + if (NOT "$ENV{TBB22_INSTALL_DIR}" STREQUAL "") + set (_TBB_INSTALL_DIR $ENV{TBB22_INSTALL_DIR}) + endif (NOT "$ENV{TBB22_INSTALL_DIR}" STREQUAL "") + if (NOT "$ENV{TBB30_INSTALL_DIR}" STREQUAL "") + set (_TBB_INSTALL_DIR $ENV{TBB30_INSTALL_DIR}) + endif (NOT "$ENV{TBB30_INSTALL_DIR}" STREQUAL "") +endif (NOT _TBB_INSTALL_DIR) +# third: try to find path automatically +if (NOT _TBB_INSTALL_DIR) + if (_TBB_DEFAULT_INSTALL_DIR) + set (_TBB_INSTALL_DIR ${_TBB_DEFAULT_INSTALL_DIR}) + endif (_TBB_DEFAULT_INSTALL_DIR) +endif (NOT _TBB_INSTALL_DIR) +# sanity check +if (NOT _TBB_INSTALL_DIR) + message ("ERROR: Unable to find Intel TBB install directory. ${_TBB_INSTALL_DIR}") +else (NOT _TBB_INSTALL_DIR) +# finally: set the cached CMake variable TBB_INSTALL_DIR +if (NOT TBB_INSTALL_DIR) + set (TBB_INSTALL_DIR ${_TBB_INSTALL_DIR} CACHE PATH "Intel TBB install directory") + mark_as_advanced(TBB_INSTALL_DIR) +endif (NOT TBB_INSTALL_DIR) + + +#-- A macro to rewrite the paths of the library. This is necessary, because +# find_library() always found the em64t/vc9 version of the TBB libs +macro(TBB_CORRECT_LIB_DIR var_name) +# if (NOT "${_TBB_ARCHITECTURE}" STREQUAL "em64t") + string(REPLACE em64t "${_TBB_ARCHITECTURE}" ${var_name} ${${var_name}}) +# endif (NOT "${_TBB_ARCHITECTURE}" STREQUAL "em64t") + string(REPLACE ia32 "${_TBB_ARCHITECTURE}" ${var_name} ${${var_name}}) + string(REPLACE vc7.1 "${_TBB_COMPILER}" ${var_name} ${${var_name}}) + string(REPLACE vc8 "${_TBB_COMPILER}" ${var_name} ${${var_name}}) + string(REPLACE vc9 "${_TBB_COMPILER}" ${var_name} ${${var_name}}) + string(REPLACE vc10 "${_TBB_COMPILER}" ${var_name} ${${var_name}}) +endmacro(TBB_CORRECT_LIB_DIR var_content) + + +#-- Look for include directory and set ${TBB_INCLUDE_DIR} +set (TBB_INC_SEARCH_DIR ${_TBB_INSTALL_DIR}/include) +# Jiri: tbbvars now sets the CPATH environment variable to the directory +# containing the headers. +find_path(TBB_INCLUDE_DIR + tbb/task_scheduler_init.h + PATHS ${TBB_INC_SEARCH_DIR} ENV CPATH +) +mark_as_advanced(TBB_INCLUDE_DIR) + + +#-- Look for libraries +# GvdB: $ENV{TBB_ARCH_PLATFORM} is set by the build script tbbvars[.bat|.sh|.csh] +if (NOT $ENV{TBB_ARCH_PLATFORM} STREQUAL "") + set (_TBB_LIBRARY_DIR + ${_TBB_INSTALL_DIR}/lib/$ENV{TBB_ARCH_PLATFORM} + ${_TBB_INSTALL_DIR}/$ENV{TBB_ARCH_PLATFORM}/lib + ) +endif (NOT $ENV{TBB_ARCH_PLATFORM} STREQUAL "") +# Jiri: This block isn't mutually exclusive with the previous one +# (hence no else), instead I test if the user really specified +# the variables in question. +if ((NOT ${TBB_ARCHITECTURE} STREQUAL "") AND (NOT ${TBB_COMPILER} STREQUAL "")) + # HH: deprecated + message(STATUS "[Warning] FindTBB.cmake: The use of TBB_ARCHITECTURE and TBB_COMPILER is deprecated and may not be supported in future versions. Please set \$ENV{TBB_ARCH_PLATFORM} (using tbbvars.[bat|csh|sh]).") + # Jiri: It doesn't hurt to look in more places, so I store the hints from + # ENV{TBB_ARCH_PLATFORM} and the TBB_ARCHITECTURE and TBB_COMPILER + # variables and search them both. + set (_TBB_LIBRARY_DIR "${_TBB_INSTALL_DIR}/${_TBB_ARCHITECTURE}/${_TBB_COMPILER}/lib" ${_TBB_LIBRARY_DIR}) +endif ((NOT ${TBB_ARCHITECTURE} STREQUAL "") AND (NOT ${TBB_COMPILER} STREQUAL "")) + +# GvdB: Mac OS X distribution places libraries directly in lib directory. +list(APPEND _TBB_LIBRARY_DIR ${_TBB_INSTALL_DIR}/lib) + +# Jiri: No reason not to check the default paths. From recent versions, +# tbbvars has started exporting the LIBRARY_PATH and LD_LIBRARY_PATH +# variables, which now point to the directories of the lib files. +# It all makes more sense to use the ${_TBB_LIBRARY_DIR} as a HINTS +# argument instead of the implicit PATHS as it isn't hard-coded +# but computed by system introspection. Searching the LIBRARY_PATH +# and LD_LIBRARY_PATH environment variables is now even more important +# that tbbvars doesn't export TBB_ARCH_PLATFORM and it facilitates +# the use of TBB built from sources. +find_library(TBB_LIBRARY ${_TBB_LIB_NAME} HINTS ${_TBB_LIBRARY_DIR} + PATHS ENV LIBRARY_PATH ENV LD_LIBRARY_PATH) +find_library(TBB_MALLOC_LIBRARY ${_TBB_LIB_MALLOC_NAME} HINTS ${_TBB_LIBRARY_DIR} + PATHS ENV LIBRARY_PATH ENV LD_LIBRARY_PATH) + +#Extract path from TBB_LIBRARY name +get_filename_component(TBB_LIBRARY_DIR ${TBB_LIBRARY} PATH) + +#TBB_CORRECT_LIB_DIR(TBB_LIBRARY) +#TBB_CORRECT_LIB_DIR(TBB_MALLOC_LIBRARY) +mark_as_advanced(TBB_LIBRARY TBB_MALLOC_LIBRARY) + +#-- Look for debug libraries +# Jiri: Changed the same way as for the release libraries. +find_library(TBB_LIBRARY_DEBUG ${_TBB_LIB_DEBUG_NAME} HINTS ${_TBB_LIBRARY_DIR} + PATHS ENV LIBRARY_PATH ENV LD_LIBRARY_PATH) +find_library(TBB_MALLOC_LIBRARY_DEBUG ${_TBB_LIB_MALLOC_DEBUG_NAME} HINTS ${_TBB_LIBRARY_DIR} + PATHS ENV LIBRARY_PATH ENV LD_LIBRARY_PATH) + +# Jiri: Self-built TBB stores the debug libraries in a separate directory. +# Extract path from TBB_LIBRARY_DEBUG name +get_filename_component(TBB_LIBRARY_DEBUG_DIR ${TBB_LIBRARY_DEBUG} PATH) + +#TBB_CORRECT_LIB_DIR(TBB_LIBRARY_DEBUG) +#TBB_CORRECT_LIB_DIR(TBB_MALLOC_LIBRARY_DEBUG) +mark_as_advanced(TBB_LIBRARY_DEBUG TBB_MALLOC_LIBRARY_DEBUG) + + +if (TBB_INCLUDE_DIR) + if (TBB_LIBRARY) + set (TBB_FOUND "YES") + set (TBB_LIBRARIES ${TBB_LIBRARY} ${TBB_MALLOC_LIBRARY} ${TBB_LIBRARIES}) + set (TBB_DEBUG_LIBRARIES ${TBB_LIBRARY_DEBUG} ${TBB_MALLOC_LIBRARY_DEBUG} ${TBB_DEBUG_LIBRARIES}) + set (TBB_INCLUDE_DIRS ${TBB_INCLUDE_DIR} CACHE PATH "TBB include directory" FORCE) + set (TBB_LIBRARY_DIRS ${TBB_LIBRARY_DIR} CACHE PATH "TBB library directory" FORCE) + # Jiri: Self-built TBB stores the debug libraries in a separate directory. + set (TBB_DEBUG_LIBRARY_DIRS ${TBB_LIBRARY_DEBUG_DIR} CACHE PATH "TBB debug library directory" FORCE) + mark_as_advanced(TBB_INCLUDE_DIRS TBB_LIBRARY_DIRS TBB_DEBUG_LIBRARY_DIRS TBB_LIBRARIES TBB_DEBUG_LIBRARIES) + message(STATUS "Found Intel TBB") + endif (TBB_LIBRARY) +endif (TBB_INCLUDE_DIR) + +if (NOT TBB_FOUND) + message("ERROR: Intel TBB NOT found!") + message(STATUS "Looked for Threading Building Blocks in ${_TBB_INSTALL_DIR}") + # do only throw fatal, if this pkg is REQUIRED + if (TBB_FIND_REQUIRED) + message(FATAL_ERROR "Could NOT find TBB library.") + endif (TBB_FIND_REQUIRED) +endif (NOT TBB_FOUND) + +endif (NOT _TBB_INSTALL_DIR) + +if (TBB_FOUND) + set(TBB_INTERFACE_VERSION 0) + FILE(READ "${TBB_INCLUDE_DIRS}/tbb/tbb_stddef.h" _TBB_VERSION_CONTENTS) + STRING(REGEX REPLACE ".*#define TBB_INTERFACE_VERSION ([0-9]+).*" "\\1" TBB_INTERFACE_VERSION "${_TBB_VERSION_CONTENTS}") + set(TBB_INTERFACE_VERSION "${TBB_INTERFACE_VERSION}") +endif (TBB_FOUND) diff --git a/libraries/networking/CMakeLists.txt b/libraries/networking/CMakeLists.txt index b650c0942c..7c8b628183 100644 --- a/libraries/networking/CMakeLists.txt +++ b/libraries/networking/CMakeLists.txt @@ -12,9 +12,7 @@ endif () # find required dependencies find_package(OpenSSL REQUIRED) - -list(APPEND LIBCUCKOO_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/externals/libcuckoo") -find_package(libcuckoo REQUIRED) +find_package(TBB REQUIRED) if (APPLE AND ${OPENSSL_INCLUDE_DIR} STREQUAL "/usr/include") # this is a user on OS X using system OpenSSL, which is going to throw warnings since they're deprecating for their common crypto @@ -25,10 +23,10 @@ endif () include_directories(SYSTEM "${OPENSSL_INCLUDE_DIR}") # append OpenSSL to our list of libraries to link -list(APPEND ${TARGET_NAME}_LIBRARIES_TO_LINK "${OPENSSL_LIBRARIES}" "${LIBCUCKOO_LIBRARIES}") +list(APPEND ${TARGET_NAME}_LIBRARIES_TO_LINK "${OPENSSL_LIBRARIES}" "${TBB_LIBRARIES}") # append libcuckoo includes to our list of includes to bubble -list(APPEND ${TARGET_NAME}_DEPENDENCY_INCLUDES "${LIBCUCKOO_INCLUDE_DIRS}") +list(APPEND ${TARGET_NAME}_DEPENDENCY_INCLUDES "${TBB_INCLUDE_DIRS}") # call macro to link our dependencies and bubble them up via a property on our target link_shared_dependencies() \ No newline at end of file diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index 6621a6d2e2..fe8efe42c4 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -449,7 +449,8 @@ void NodeList::pingPunchForInactiveNode(const SharedNodePointer& node) { } void NodeList::pingInactiveNodes() { - for (auto it = _nodeHash.cbegin(); !it.is_end(); it++) { + NodeHashSnapshot snapshotHash = _nodeHash.snapshot_table(); + for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { if (!it->second->getActiveSocket()) { // we don't have an active link to this node, ping it to set that up pingPunchForInactiveNode(it->second); From e0c4f14c8163f55c4c28abca1fa9df461b256440 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 6 Nov 2014 11:19:16 -0800 Subject: [PATCH 013/502] move networking lib to TBB concurrent_unordered_map --- libraries/networking/src/LimitedNodeList.cpp | 63 ++++++++++---------- libraries/networking/src/LimitedNodeList.h | 63 +++++++++++++++----- libraries/networking/src/NodeList.cpp | 9 ++- libraries/networking/src/UUIDCityHasher.cpp | 12 ---- libraries/networking/src/UUIDCityHasher.h | 26 -------- libraries/networking/src/UUIDHasher.h | 26 ++++++++ 6 files changed, 108 insertions(+), 91 deletions(-) delete mode 100644 libraries/networking/src/UUIDCityHasher.cpp delete mode 100644 libraries/networking/src/UUIDCityHasher.h create mode 100644 libraries/networking/src/UUIDHasher.h diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index 5a103076b6..818d35c0e5 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -21,6 +21,8 @@ #include +#include + #include "AccountManager.h" #include "Assignment.h" #include "HifiSockAddr.h" @@ -342,9 +344,9 @@ int LimitedNodeList::findNodeAndUpdateWithDataFromPacket(const QByteArray& packe return 0; } -SharedNodePointer LimitedNodeList::nodeWithUUID(const QUuid& nodeUUID, bool blockingLock) { +SharedNodePointer LimitedNodeList::nodeWithUUID(const QUuid& nodeUUID) { try { - return _nodeHash[nodeUUID]; + return _nodeHash.at(nodeUUID); } catch (std::out_of_range) { return SharedNodePointer(); } @@ -360,12 +362,12 @@ SharedNodePointer LimitedNodeList::sendingNodeForPacket(const QByteArray& packet void LimitedNodeList::eraseAllNodes() { qDebug() << "Clearing the NodeList. Deleting all nodes in list."; - // iterate the current nodes and note that they are going down - for (auto it = _nodeHash.cbegin(); !it.is_end(); it++) { + // iterate the current nodes, emit that they are dying and remove them from the hash + QWriteLocker writeLock(&_nodeMutex); + for (NodeHash::iterator it = _nodeHash.begin(); it != _nodeHash.end(); ++it) { emit nodeKilled(it->second); + it = _nodeHash.unsafe_erase(it); } - - _nodeHash.clear(); } void LimitedNodeList::reset() { @@ -373,10 +375,13 @@ void LimitedNodeList::reset() { } void LimitedNodeList::killNodeWithUUID(const QUuid& nodeUUID) { - SharedNodePointer matchingNode = nodeWithUUID(nodeUUID); - if (matchingNode) { + NodeHash::iterator it = _nodeHash.find(nodeUUID); + if (it != _nodeHash.end()) { + SharedNodePointer matchingNode = it->second; + + QWriteLocker writeLocker(&_nodeMutex); + _nodeHash.unsafe_erase(it); emit nodeKilled(matchingNode); - _nodeHash.erase(nodeUUID); } } @@ -391,7 +396,7 @@ void LimitedNodeList::processKillNode(const QByteArray& dataByteArray) { SharedNodePointer LimitedNodeList::addOrUpdateNode(const QUuid& uuid, NodeType_t nodeType, const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket) { try { - SharedNodePointer matchingNode = _nodeHash[uuid]; + SharedNodePointer matchingNode = _nodeHash.at(uuid); matchingNode->setPublicSocket(publicSocket); matchingNode->setLocalSocket(localSocket); @@ -402,7 +407,7 @@ SharedNodePointer LimitedNodeList::addOrUpdateNode(const QUuid& uuid, NodeType_t Node* newNode = new Node(uuid, nodeType, publicSocket, localSocket); SharedNodePointer newNodeSharedPointer(newNode, &QObject::deleteLater); - _nodeHash.insert(newNode->getUUID(), newNodeSharedPointer); + _nodeHash.insert(UUIDNodePair(newNode->getUUID(), newNodeSharedPointer)); qDebug() << "Added" << *newNode; @@ -415,13 +420,12 @@ SharedNodePointer LimitedNodeList::addOrUpdateNode(const QUuid& uuid, NodeType_t unsigned LimitedNodeList::broadcastToNodes(const QByteArray& packet, const NodeSet& destinationNodeTypes) { unsigned n = 0; - NodeHashSnapshot snapshotHash = _nodeHash.snapshot_table(); - for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { - if (destinationNodeTypes.contains(it->second->getType())) { - writeDatagram(packet, it->second); + eachNode([&](const SharedNodePointer& node){ + if (destinationNodeTypes.contains(node->getType())) { + writeDatagram(packet, node); ++n; } - } + }); return n; } @@ -460,17 +464,9 @@ QByteArray LimitedNodeList::constructPingReplyPacket(const QByteArray& pingPacke } SharedNodePointer LimitedNodeList::soloNodeOfType(char nodeType) { - - if (memchr(SOLO_NODE_TYPES, nodeType, sizeof(SOLO_NODE_TYPES))) { - NodeHashSnapshot snapshotHash = _nodeHash.snapshot_table(); - - for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { - if (it->second->getType() == nodeType) { - return it->second; - } - } - } - return SharedNodePointer(); + return nodeMatchingPredicate([&](const SharedNodePointer& node){ + return node->getType() == nodeType; + }); } void LimitedNodeList::getPacketStats(float& packetsPerSecond, float& bytesPerSecond) { @@ -485,20 +481,21 @@ void LimitedNodeList::resetPacketStats() { } void LimitedNodeList::removeSilentNodes() { - - NodeHashSnapshot snapshotHash = _nodeHash.snapshot_table(); - - for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { + eachNodeHashIterator([this](NodeHash::iterator& it){ SharedNodePointer node = it->second; node->getMutex().lock(); if ((usecTimestampNow() - node->getLastHeardMicrostamp()) > (NODE_SILENCE_THRESHOLD_MSECS * 1000)) { // call the NodeHash erase to get rid of this node - _nodeHash.erase(it->first); + it = _nodeHash.unsafe_erase(it); + emit nodeKilled(node); + } else { + // we didn't erase this node, push the iterator forwards + ++it; } node->getMutex().unlock(); - } + }); } const uint32_t RFC_5389_MAGIC_COOKIE = 0x2112A442; diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index 63f93458f3..c7a8ccecf5 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -20,19 +20,18 @@ #include // not on windows, not needed for mac or windows #endif -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include -#include +#include #include "DomainHandler.h" #include "Node.h" -#include "UUIDCityHasher.h" +#include "UUIDHasher.h" const int MAX_PACKET_SIZE = 1500; @@ -54,8 +53,9 @@ typedef QSet NodeSet; typedef QSharedPointer SharedNodePointer; Q_DECLARE_METATYPE(SharedNodePointer) -typedef cuckoohash_map NodeHash; -typedef std::vector > NodeHashSnapshot; +using namespace tbb; +typedef std::pair UUIDNodePair; +typedef concurrent_unordered_map NodeHash; typedef quint8 PingType_t; namespace PingType { @@ -74,7 +74,6 @@ public: const QUuid& getSessionUUID() const { return _sessionUUID; } void setSessionUUID(const QUuid& sessionUUID); - void rebindNodeSocket(); QUdpSocket& getNodeSocket() { return _nodeSocket; } QUdpSocket& getDTLSSocket(); @@ -95,11 +94,10 @@ public: const HifiSockAddr& overridenSockAddr = HifiSockAddr()); void(*linkedDataCreateCallback)(Node *); - - const NodeHash& getNodeHash() { return _nodeHash; } + int size() const { return _nodeHash.size(); } - SharedNodePointer nodeWithUUID(const QUuid& nodeUUID, bool blockingLock = true); + SharedNodePointer nodeWithUUID(const QUuid& nodeUUID); SharedNodePointer sendingNodeForPacket(const QByteArray& packet); SharedNodePointer addOrUpdateNode(const QUuid& uuid, NodeType_t nodeType, @@ -128,6 +126,29 @@ public: void sendHeartbeatToIceServer(const HifiSockAddr& iceServerSockAddr, QUuid headerID = QUuid(), const QUuid& connectRequestID = QUuid()); + + template + void eachNode(NodeLambda functor) { + QReadLocker readLock(&_nodeMutex); + + for (NodeHash::const_iterator it = _nodeHash.cbegin(); it != _nodeHash.cend(); ++it) { + functor(it->second); + } + } + + template + SharedNodePointer nodeMatchingPredicate(const PredLambda predicate) { + QReadLocker readLock(&_nodeMutex); + + for (NodeHash::const_iterator it = _nodeHash.cbegin(); it != _nodeHash.cend(); ++it) { + if (predicate(it->second)) { + return it->second; + } + } + + return SharedNodePointer(); + } + public slots: void reset(); void eraseAllNodes(); @@ -158,6 +179,7 @@ protected: QUuid _sessionUUID; NodeHash _nodeHash; + QReadWriteLock _nodeMutex; QUdpSocket _nodeSocket; QUdpSocket* _dtlsSocket; HifiSockAddr _localSockAddr; @@ -166,6 +188,17 @@ protected: int _numCollectedPackets; int _numCollectedBytes; QElapsedTimer _packetStatTimer; + + template + void eachNodeHashIterator(IteratorLambda functor) { + QWriteLocker writeLock(&_nodeMutex); + NodeHash::iterator it = _nodeHash.begin(); + + while (it != _nodeHash.end()) { + functor(it); + } + } + }; #endif // hifi_LimitedNodeList_h diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index fe8efe42c4..bf992e7b88 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -449,13 +449,12 @@ void NodeList::pingPunchForInactiveNode(const SharedNodePointer& node) { } void NodeList::pingInactiveNodes() { - NodeHashSnapshot snapshotHash = _nodeHash.snapshot_table(); - for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { - if (!it->second->getActiveSocket()) { + eachNode([this](const SharedNodePointer& node){ + if (!node->getActiveSocket()) { // we don't have an active link to this node, ping it to set that up - pingPunchForInactiveNode(it->second); + pingPunchForInactiveNode(node); } - } + }); } void NodeList::activateSocketFromNodeCommunication(const QByteArray& packet, const SharedNodePointer& sendingNode) { diff --git a/libraries/networking/src/UUIDCityHasher.cpp b/libraries/networking/src/UUIDCityHasher.cpp deleted file mode 100644 index 731e287fc0..0000000000 --- a/libraries/networking/src/UUIDCityHasher.cpp +++ /dev/null @@ -1,12 +0,0 @@ -// -// UUIDCityHasher.cpp -// libraries/networking/src -// -// Created by Stephen Birarda on 2014-11-05. -// 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 "UUIDCityHasher.h" diff --git a/libraries/networking/src/UUIDCityHasher.h b/libraries/networking/src/UUIDCityHasher.h deleted file mode 100644 index e27e3bdf1b..0000000000 --- a/libraries/networking/src/UUIDCityHasher.h +++ /dev/null @@ -1,26 +0,0 @@ -// -// UUIDCityHasher.h -// libraries/networking/src -// -// Created by Stephen Birarda on 2014-11-05. -// 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_UUIDCityHasher_h -#define hifi_UUIDCityHasher_h - -#include - -#include "UUID.h" - -class UUIDCityHasher { -public: - size_t operator()(const QUuid& key) const { - return CityHash64(key.toRfc4122().constData(), NUM_BYTES_RFC4122_UUID); - } -}; - -#endif // hifi_UUIDCityHasher_h \ No newline at end of file diff --git a/libraries/networking/src/UUIDHasher.h b/libraries/networking/src/UUIDHasher.h new file mode 100644 index 0000000000..d5d16e21e9 --- /dev/null +++ b/libraries/networking/src/UUIDHasher.h @@ -0,0 +1,26 @@ +// +// UUIDHasher.h +// libraries/networking/src +// +// Created by Stephen Birarda on 2014-11-05. +// 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_UUIDHasher_h +#define hifi_UUIDHasher_h + +#include "UUID.h" + +class UUIDHasher { +public: + size_t operator()(const QUuid& uuid) const { + return uuid.data1 ^ uuid.data2 ^ (uuid.data3 << 16) + ^ ((uuid.data4[0] << 24) | (uuid.data4[1] << 16) | (uuid.data4[2] << 8) | uuid.data4[3]) + ^ ((uuid.data4[4] << 24) | (uuid.data4[5] << 16) | (uuid.data4[6] << 8) | uuid.data4[7]); + } +}; + +#endif // hifi_UUIDHasher_h \ No newline at end of file From c80633499fbfc67f87cbb2e363e9771630b36044 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 6 Nov 2014 11:35:07 -0800 Subject: [PATCH 014/502] make eachNode callers return bool to say if iteration should continue --- libraries/networking/src/LimitedNodeList.cpp | 2 ++ libraries/networking/src/LimitedNodeList.h | 4 +++- libraries/networking/src/NodeList.cpp | 2 ++ libraries/octree/src/JurisdictionListener.cpp | 14 ++++++-------- libraries/octree/src/OctreeEditPacketSender.cpp | 13 ++++++------- 5 files changed, 19 insertions(+), 16 deletions(-) diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index 818d35c0e5..2661c83b5c 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -425,6 +425,8 @@ unsigned LimitedNodeList::broadcastToNodes(const QByteArray& packet, const NodeS writeDatagram(packet, node); ++n; } + + return true; }); return n; diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index c7a8ccecf5..750e5b8688 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -132,7 +132,9 @@ public: QReadLocker readLock(&_nodeMutex); for (NodeHash::const_iterator it = _nodeHash.cbegin(); it != _nodeHash.cend(); ++it) { - functor(it->second); + if (!functor(it->second)) { + break; + } } } diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index bf992e7b88..7271dfe446 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -454,6 +454,8 @@ void NodeList::pingInactiveNodes() { // we don't have an active link to this node, ping it to set that up pingPunchForInactiveNode(node); } + + return true; }); } diff --git a/libraries/octree/src/JurisdictionListener.cpp b/libraries/octree/src/JurisdictionListener.cpp index 606a6c13f2..f16daf9f0d 100644 --- a/libraries/octree/src/JurisdictionListener.cpp +++ b/libraries/octree/src/JurisdictionListener.cpp @@ -38,16 +38,14 @@ bool JurisdictionListener::queueJurisdictionRequest() { int sizeOut = populatePacketHeader(reinterpret_cast(bufferOut), PacketTypeJurisdictionRequest); int nodeCount = 0; - NodeList* nodeList = NodeList::getInstance(); - - NodeHashSnapshot nodeHashSnapshot = nodeList->getNodeHash().snapshot_table(); - - for (auto it = nodeHashSnapshot.begin(); it != nodeHashSnapshot.end(); it++) { - if (it->second->getType() == getNodeType() && it->second->getActiveSocket()) { - _packetSender.queuePacketForSending(it->second, QByteArray(reinterpret_cast(bufferOut), sizeOut)); + NodeList::getInstance()->eachNode([&](const SharedNodePointer& node) { + if (node->getType() == getNodeType() && node->getActiveSocket()) { + _packetSender.queuePacketForSending(node, QByteArray(reinterpret_cast(bufferOut), sizeOut)); nodeCount++; } - } + + return true; + }); if (nodeCount > 0){ _packetSender.setPacketsPerSecond(nodeCount); diff --git a/libraries/octree/src/OctreeEditPacketSender.cpp b/libraries/octree/src/OctreeEditPacketSender.cpp index 19de2e37e9..1a126576d3 100644 --- a/libraries/octree/src/OctreeEditPacketSender.cpp +++ b/libraries/octree/src/OctreeEditPacketSender.cpp @@ -51,12 +51,8 @@ OctreeEditPacketSender::~OctreeEditPacketSender() { bool OctreeEditPacketSender::serversExist() const { bool hasServers = false; bool atLeastOneJurisdictionMissing = false; // assume the best - NodeList* nodeList = NodeList::getInstance(); - NodeHashSnapshot snapshotHash = nodeList->getNodeHash().snapshot_table(); - for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { - // only send to the NodeTypes that are getMyNodeType() - SharedNodePointer node = it->second; + NodeList::getInstance()->eachNode([&](const SharedNodePointer& node){ if (node->getType() == getMyNodeType() && node->getActiveSocket()) { QUuid nodeUUID = node->getUUID(); @@ -72,10 +68,13 @@ bool OctreeEditPacketSender::serversExist() const { } hasServers = true; } + if (atLeastOneJurisdictionMissing) { - break; // no point in looking further... + return false; // no point in looking further - return false from anonymous function + } else { + return true; } - } + }); return (hasServers && !atLeastOneJurisdictionMissing); } From da8fc5d5c578efb0dcc29c599c45cc00c15dd886 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 6 Nov 2014 11:43:20 -0800 Subject: [PATCH 015/502] migrate octree library to tbb concurrent map --- .../octree/src/OctreeEditPacketSender.cpp | 108 +++++++++--------- libraries/octree/src/OctreeHeadlessViewer.cpp | 54 ++++----- 2 files changed, 79 insertions(+), 83 deletions(-) diff --git a/libraries/octree/src/OctreeEditPacketSender.cpp b/libraries/octree/src/OctreeEditPacketSender.cpp index 1a126576d3..c0866a981e 100644 --- a/libraries/octree/src/OctreeEditPacketSender.cpp +++ b/libraries/octree/src/OctreeEditPacketSender.cpp @@ -85,54 +85,50 @@ void OctreeEditPacketSender::queuePacketToNode(const QUuid& nodeUUID, unsigned c size_t length, qint64 satoshiCost) { bool wantDebug = false; - NodeList* nodeList = NodeList::getInstance(); - - NodeHashSnapshot snapshotHash = nodeList->getNodeHash().snapshot_table(); - for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { - SharedNodePointer node = it->second; - + NodeList::getInstance()->eachNode([&](const SharedNodePointer& node){ // only send to the NodeTypes that are getMyNodeType() - if (node->getType() == getMyNodeType() && - ((node->getUUID() == nodeUUID) || (nodeUUID.isNull()))) { - if (node->getActiveSocket()) { - - // pack sequence number - int numBytesPacketHeader = numBytesForPacketHeader(reinterpret_cast(buffer)); - unsigned char* sequenceAt = buffer + numBytesPacketHeader; - quint16 sequence = _outgoingSequenceNumbers[nodeUUID]++; - memcpy(sequenceAt, &sequence, sizeof(quint16)); + if (node->getType() == getMyNodeType() + && ((node->getUUID() == nodeUUID) || (nodeUUID.isNull())) + && node->getActiveSocket()) { + + // pack sequence number + int numBytesPacketHeader = numBytesForPacketHeader(reinterpret_cast(buffer)); + unsigned char* sequenceAt = buffer + numBytesPacketHeader; + quint16 sequence = _outgoingSequenceNumbers[nodeUUID]++; + memcpy(sequenceAt, &sequence, sizeof(quint16)); + + // send packet + QByteArray packet(reinterpret_cast(buffer), length); + + queuePacketForSending(node, packet); + + if (hasDestinationWalletUUID() && satoshiCost > 0) { + // if we have a destination wallet UUID and a cost associated with this packet, signal that it + // needs to be sent + emit octreePaymentRequired(satoshiCost, nodeUUID, _destinationWalletUUID); + } + + // add packet to history + _sentPacketHistories[nodeUUID].packetSent(sequence, packet); + + // debugging output... + if (wantDebug) { + int numBytesPacketHeader = numBytesForPacketHeader(reinterpret_cast(buffer)); + unsigned short int sequence = (*((unsigned short int*)(buffer + numBytesPacketHeader))); + quint64 createdAt = (*((quint64*)(buffer + numBytesPacketHeader + sizeof(sequence)))); + quint64 queuedAt = usecTimestampNow(); + quint64 transitTime = queuedAt - createdAt; - // send packet - QByteArray packet(reinterpret_cast(buffer), length); - - queuePacketForSending(node, packet); - - if (hasDestinationWalletUUID() && satoshiCost > 0) { - // if we have a destination wallet UUID and a cost associated with this packet, signal that it - // needs to be sent - emit octreePaymentRequired(satoshiCost, nodeUUID, _destinationWalletUUID); - } - - // add packet to history - _sentPacketHistories[nodeUUID].packetSent(sequence, packet); - - // debugging output... - if (wantDebug) { - int numBytesPacketHeader = numBytesForPacketHeader(reinterpret_cast(buffer)); - unsigned short int sequence = (*((unsigned short int*)(buffer + numBytesPacketHeader))); - quint64 createdAt = (*((quint64*)(buffer + numBytesPacketHeader + sizeof(sequence)))); - quint64 queuedAt = usecTimestampNow(); - quint64 transitTime = queuedAt - createdAt; - - qDebug() << "OctreeEditPacketSender::queuePacketToNode() queued " << buffer[0] << - " - command to node bytes=" << length << - " satoshiCost=" << satoshiCost << - " sequence=" << sequence << - " transitTimeSoFar=" << transitTime << " usecs"; - } + qDebug() << "OctreeEditPacketSender::queuePacketToNode() queued " << buffer[0] << + " - command to node bytes=" << length << + " satoshiCost=" << satoshiCost << + " sequence=" << sequence << + " transitTimeSoFar=" << transitTime << " usecs"; } } - } + + return true; + }); } void OctreeEditPacketSender::processPreServerExistsPackets() { @@ -198,9 +194,7 @@ void OctreeEditPacketSender::queuePacketToNodes(unsigned char* buffer, size_t le // for a different server... So we need to actually manage multiple queued packets... one // for each server - NodeHashSnapshot snapshotHash = NodeList::getInstance()->getNodeHash().snapshot_table(); - for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { - SharedNodePointer node = it->second; + NodeList::getInstance()->eachNode([&](const SharedNodePointer& node){ // only send to the NodeTypes that are getMyNodeType() if (node->getActiveSocket() && node->getType() == getMyNodeType()) { QUuid nodeUUID = node->getUUID(); @@ -215,7 +209,9 @@ void OctreeEditPacketSender::queuePacketToNodes(unsigned char* buffer, size_t le queuePacketToNode(nodeUUID, buffer, length, satoshiCost); } } - } + + return true; + }); } @@ -254,9 +250,7 @@ void OctreeEditPacketSender::queueOctreeEditMessage(PacketType type, unsigned ch _packetsQueueLock.lock(); - NodeHashSnapshot snapshotHash = NodeList::getInstance()->getNodeHash().snapshot_table(); - for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { - SharedNodePointer node = it->second; + NodeList::getInstance()->eachNode([&](const SharedNodePointer& node){ // only send to the NodeTypes that are getMyNodeType() if (node->getActiveSocket() && node->getType() == getMyNodeType()) { QUuid nodeUUID = node->getUUID(); @@ -279,19 +273,19 @@ void OctreeEditPacketSender::queueOctreeEditMessage(PacketType type, unsigned ch if (isMyJurisdiction) { EditPacketBuffer& packetBuffer = _pendingEditPackets[nodeUUID]; packetBuffer._nodeUUID = nodeUUID; - + // If we're switching type, then we send the last one and start over if ((type != packetBuffer._currentType && packetBuffer._currentSize > 0) || (packetBuffer._currentSize + length >= (size_t)_maxPacketSize)) { releaseQueuedPacket(packetBuffer); initializePacket(packetBuffer, type); } - + // If the buffer is empty and not correctly initialized for our type... if (type != packetBuffer._currentType && packetBuffer._currentSize == 0) { initializePacket(packetBuffer, type); } - + // This is really the first time we know which server/node this particular edit message // is going to, so we couldn't adjust for clock skew till now. But here's our chance. // We call this virtual function that allows our specific type of EditPacketSender to @@ -299,13 +293,15 @@ void OctreeEditPacketSender::queueOctreeEditMessage(PacketType type, unsigned ch if (node->getClockSkewUsec() != 0) { adjustEditPacketForClockSkew(type, editPacketBuffer, length, node->getClockSkewUsec()); } - + memcpy(&packetBuffer._currentBuffer[packetBuffer._currentSize], editPacketBuffer, length); packetBuffer._currentSize += length; packetBuffer._satoshiCost += satoshiCost; } } - } + + return true; + }); _packetsQueueLock.unlock(); diff --git a/libraries/octree/src/OctreeHeadlessViewer.cpp b/libraries/octree/src/OctreeHeadlessViewer.cpp index b363c654c1..e40ae712e9 100644 --- a/libraries/octree/src/OctreeHeadlessViewer.cpp +++ b/libraries/octree/src/OctreeHeadlessViewer.cpp @@ -77,16 +77,14 @@ void OctreeHeadlessViewer::queryOctree() { int inViewServers = 0; int unknownJurisdictionServers = 0; - NodeHashSnapshot snapshotHash = NodeList::getInstance()->getNodeHash().snapshot_table(); - for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { - SharedNodePointer node = it->second; + NodeList::getInstance()->eachNode([&](const SharedNodePointer& node){ // only send to the NodeTypes that are serverType if (node->getActiveSocket() && node->getType() == serverType) { totalServers++; - + // get the server bounds for this server QUuid nodeUUID = node->getUUID(); - + // if we haven't heard from this voxel server, go ahead and send it a query, so we // can get the jurisdiction... jurisdictions.lockForRead(); @@ -95,18 +93,18 @@ void OctreeHeadlessViewer::queryOctree() { unknownJurisdictionServers++; } else { const JurisdictionMap& map = (jurisdictions)[nodeUUID]; - + unsigned char* rootCode = map.getRootOctalCode(); - + if (rootCode) { VoxelPositionSize rootDetails; voxelDetailsForCode(rootCode, rootDetails); jurisdictions.unlock(); AACube serverBounds(glm::vec3(rootDetails.x, rootDetails.y, rootDetails.z), rootDetails.s); serverBounds.scale(TREE_SCALE); - + ViewFrustum::location serverFrustumLocation = _viewFrustum.cubeInFrustum(serverBounds); - + if (serverFrustumLocation != ViewFrustum::OUTSIDE) { inViewServers++; } @@ -115,7 +113,9 @@ void OctreeHeadlessViewer::queryOctree() { } } } - } + + return true; + }); if (wantExtraDebugging) { qDebug("Servers: total %d, in view %d, unknown jurisdiction %d", @@ -143,18 +143,16 @@ void OctreeHeadlessViewer::queryOctree() { } NodeList* nodeList = NodeList::getInstance(); - - for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { - SharedNodePointer node = it->second; + nodeList->eachNode([&](const SharedNodePointer& node){ // only send to the NodeTypes that are serverType if (node->getActiveSocket() && node->getType() == serverType) { - + // get the server bounds for this server QUuid nodeUUID = node->getUUID(); - + bool inView = false; bool unknownView = false; - + // if we haven't heard from this voxel server, go ahead and send it a query, so we // can get the jurisdiction... jurisdictions.lockForRead(); @@ -166,16 +164,16 @@ void OctreeHeadlessViewer::queryOctree() { } } else { const JurisdictionMap& map = (jurisdictions)[nodeUUID]; - + unsigned char* rootCode = map.getRootOctalCode(); - + if (rootCode) { VoxelPositionSize rootDetails; voxelDetailsForCode(rootCode, rootDetails); jurisdictions.unlock(); AACube serverBounds(glm::vec3(rootDetails.x, rootDetails.y, rootDetails.z), rootDetails.s); serverBounds.scale(TREE_SCALE); - + ViewFrustum::location serverFrustumLocation = _viewFrustum.cubeInFrustum(serverBounds); if (serverFrustumLocation != ViewFrustum::OUTSIDE) { inView = true; @@ -189,7 +187,7 @@ void OctreeHeadlessViewer::queryOctree() { } } } - + if (inView) { _octreeQuery.setMaxOctreePacketsPerSecond(perServerPPS); if (wantExtraDebugging) { @@ -198,9 +196,9 @@ void OctreeHeadlessViewer::queryOctree() { } else if (unknownView) { if (wantExtraDebugging) { qDebug() << "no known jurisdiction for node " << *node << ", give it budget of " - << perUnknownServer << " to send us jurisdiction."; + << perUnknownServer << " to send us jurisdiction."; } - + // set the query's position/orientation to be degenerate in a manner that will get the scene quickly // If there's only one server, then don't do this, and just let the normal voxel query pass through // as expected... this way, we will actually get a valid scene if there is one to be seen @@ -224,19 +222,21 @@ void OctreeHeadlessViewer::queryOctree() { } // set up the packet for sending... unsigned char* endOfQueryPacket = queryPacket; - + // insert packet type/version and node UUID endOfQueryPacket += populatePacketHeader(reinterpret_cast(endOfQueryPacket), packetType); - + // encode the query data... endOfQueryPacket += _octreeQuery.getBroadcastData(endOfQueryPacket); - + int packetLength = endOfQueryPacket - queryPacket; - + // make sure we still have an active socket nodeList->writeUnverifiedDatagram(reinterpret_cast(queryPacket), packetLength, node); } - } + + return true; + }); } From 270823be438184199866abb885a2c475a84e65cd Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 6 Nov 2014 13:39:15 -0800 Subject: [PATCH 016/502] update domain-server to leverage intel tbb hash --- domain-server/src/DomainServer.cpp | 100 ++++++++----------- libraries/networking/src/LimitedNodeList.cpp | 7 +- 2 files changed, 42 insertions(+), 65 deletions(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 5dddfd70dd..cbd70f9edc 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -821,52 +821,50 @@ void DomainServer::sendDomainListToNode(const SharedNodePointer& node, const Hif if (nodeData->isAuthenticated()) { // if this authenticated node has any interest types, send back those nodes as well - NodeHashSnapshot snapshotHash = nodeList->getNodeHash().snapshot_table(); - - for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { - SharedNodePointer otherNode = it->second; - + nodeList->eachNode([&](const SharedNodePointer& otherNode){ // reset our nodeByteArray and nodeDataStream QByteArray nodeByteArray; QDataStream nodeDataStream(&nodeByteArray, QIODevice::Append); - + if (otherNode->getUUID() != node->getUUID() && nodeInterestList.contains(otherNode->getType())) { - + // don't send avatar nodes to other avatars, that will come from avatar mixer nodeDataStream << *otherNode.data(); - + // pack the secret that these two nodes will use to communicate with each other QUuid secretUUID = nodeData->getSessionSecretHash().value(otherNode->getUUID()); if (secretUUID.isNull()) { // generate a new secret UUID these two nodes can use secretUUID = QUuid::createUuid(); - + // set that on the current Node's sessionSecretHash nodeData->getSessionSecretHash().insert(otherNode->getUUID(), secretUUID); - + // set it on the other Node's sessionSecretHash reinterpret_cast(otherNode->getLinkedData()) ->getSessionSecretHash().insert(node->getUUID(), secretUUID); - + } - + nodeDataStream << secretUUID; - + if (broadcastPacket.size() + nodeByteArray.size() > dataMTU) { // we need to break here and start a new packet // so send the current one - + nodeList->writeDatagram(broadcastPacket, node, senderSockAddr); - + // reset the broadcastPacket structure broadcastPacket.resize(numBroadcastPacketLeadBytes); broadcastDataStream.device()->seek(numBroadcastPacketLeadBytes); } - + // append the nodeByteArray to the current state of broadcastDataStream broadcastPacket.append(nodeByteArray); } - } + + return true; + }); } // always write the last broadcastPacket @@ -963,17 +961,14 @@ void DomainServer::readAvailableDatagrams() { void DomainServer::setupPendingAssignmentCredits() { // enumerate the NodeList to find the assigned nodes - NodeHashSnapshot snapshotHash = NodeList::getInstance()->getNodeHash().snapshot_table(); - - for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { - SharedNodePointer node = it->second; + NodeList::getInstance()->eachNode([&](const SharedNodePointer& node){ DomainServerNodeData* nodeData = reinterpret_cast(node->getLinkedData()); - + if (!nodeData->getAssignmentUUID().isNull() && !nodeData->getWalletUUID().isNull()) { // check if we have a non-finalized transaction for this node to add this amount to TransactionHash::iterator i = _pendingAssignmentCredits.find(nodeData->getWalletUUID()); WalletTransaction* existingTransaction = NULL; - + while (i != _pendingAssignmentCredits.end() && i.key() == nodeData->getWalletUUID()) { if (!i.value()->isFinalized()) { existingTransaction = i.value(); @@ -982,16 +977,16 @@ void DomainServer::setupPendingAssignmentCredits() { ++i; } } - + qint64 elapsedMsecsSinceLastPayment = nodeData->getPaymentIntervalTimer().elapsed(); nodeData->getPaymentIntervalTimer().restart(); - + const float CREDITS_PER_HOUR = 0.10f; const float CREDITS_PER_MSEC = CREDITS_PER_HOUR / (60 * 60 * 1000); const int SATOSHIS_PER_MSEC = CREDITS_PER_MSEC * SATOSHIS_PER_CREDIT; - + float pendingCredits = elapsedMsecsSinceLastPayment * SATOSHIS_PER_MSEC; - + if (existingTransaction) { existingTransaction->incrementAmount(pendingCredits); } else { @@ -1000,7 +995,9 @@ void DomainServer::setupPendingAssignmentCredits() { _pendingAssignmentCredits.insert(nodeData->getWalletUUID(), freshTransaction); } } - } + + return true; + }); } void DomainServer::sendPendingTransactionsToServer() { @@ -1126,16 +1123,13 @@ void DomainServer::sendHeartbeatToDataServer(const QString& networkAddress) { // add the number of currently connected agent users int numConnectedAuthedUsers = 0; - NodeHashSnapshot snapshotHash = NodeList::getInstance()->getNodeHash().snapshot_table(); - - for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { - - SharedNodePointer node = it->second; - + NodeList::getInstance()->eachNode([&numConnectedAuthedUsers](const SharedNodePointer& node){ if (node->getLinkedData() && !static_cast(node->getLinkedData())->getUsername().isEmpty()) { ++numConnectedAuthedUsers; } - } + + return true; + }); const QString DOMAIN_HEARTBEAT_KEY = "heartbeat"; const QString HEARTBEAT_NUM_USERS_KEY = "num_users"; @@ -1438,20 +1432,17 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url QJsonObject assignedNodesJSON; // enumerate the NodeList to find the assigned nodes - NodeHashSnapshot snapshotHash = NodeList::getInstance()->getNodeHash().snapshot_table(); - - for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { - - SharedNodePointer node = it->second; - + NodeList::getInstance()->eachNode([this, &assignedNodesJSON](const SharedNodePointer& node){ DomainServerNodeData* nodeData = reinterpret_cast(node->getLinkedData()); - + if (!nodeData->getAssignmentUUID().isNull()) { // add the node using the UUID as the key QString uuidString = uuidStringWithoutCurlyBraces(nodeData->getAssignmentUUID()); assignedNodesJSON[uuidString] = jsonObjectForNode(node); } - } + + return true; + }); assignmentJSON["fulfilled"] = assignedNodesJSON; @@ -1505,14 +1496,12 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url QJsonArray nodesJSONArray; // enumerate the NodeList to find the assigned nodes - LimitedNodeList* nodeList = LimitedNodeList::getInstance(); - - NodeHashSnapshot snapshotHash = nodeList->getNodeHash().snapshot_table(); - - for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { + LimitedNodeList::getInstance()->eachNode([this, &nodesJSONArray](const SharedNodePointer& node){ // add the node using the UUID as the key - nodesJSONArray.append(jsonObjectForNode(it->second)); - } + nodesJSONArray.append(jsonObjectForNode(node)); + + return true; + }); rootJSON["nodes"] = nodesJSONArray; @@ -2040,18 +2029,9 @@ void DomainServer::addStaticAssignmentsToQueue() { QHash::iterator staticAssignment = staticHashCopy.begin(); while (staticAssignment != staticHashCopy.end()) { // add any of the un-matched static assignments to the queue - bool foundMatchingAssignment = false; // enumerate the nodes and check if there is one with an attached assignment with matching UUID - NodeHashSnapshot snapshotHash = NodeList::getInstance()->getNodeHash().snapshot_table(); - - for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { - if (it->first == staticAssignment->data()->getUUID()) { - foundMatchingAssignment = true; - } - } - - if (!foundMatchingAssignment) { + if (NodeList::getInstance()->nodeWithUUID(staticAssignment->data()->getUUID())) { // this assignment has not been fulfilled - reset the UUID and add it to the assignment queue refreshStaticAssignmentAndAddToQueue(*staticAssignment); } diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index 2661c83b5c..4202444749 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -345,11 +345,8 @@ int LimitedNodeList::findNodeAndUpdateWithDataFromPacket(const QByteArray& packe } SharedNodePointer LimitedNodeList::nodeWithUUID(const QUuid& nodeUUID) { - try { - return _nodeHash.at(nodeUUID); - } catch (std::out_of_range) { - return SharedNodePointer(); - } + NodeHash::const_iterator it = _nodeHash.find(nodeUUID); + return it == _nodeHash.cend() ? SharedNodePointer() : it->second; } SharedNodePointer LimitedNodeList::sendingNodeForPacket(const QByteArray& packet) { From e92376cf649192a5480d53332bcbb08c9749f41c Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 6 Nov 2014 13:41:55 -0800 Subject: [PATCH 017/502] distinguish between eachNode and eachNodeBreakable --- domain-server/src/DomainServer.cpp | 10 ---------- libraries/networking/src/LimitedNodeList.cpp | 2 -- libraries/networking/src/LimitedNodeList.h | 9 +++++++++ libraries/networking/src/NodeList.cpp | 2 -- libraries/octree/src/JurisdictionListener.cpp | 2 -- libraries/octree/src/OctreeEditPacketSender.cpp | 8 +------- libraries/octree/src/OctreeHeadlessViewer.cpp | 4 ---- 7 files changed, 10 insertions(+), 27 deletions(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index cbd70f9edc..cb4b1c8026 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -862,8 +862,6 @@ void DomainServer::sendDomainListToNode(const SharedNodePointer& node, const Hif // append the nodeByteArray to the current state of broadcastDataStream broadcastPacket.append(nodeByteArray); } - - return true; }); } @@ -995,8 +993,6 @@ void DomainServer::setupPendingAssignmentCredits() { _pendingAssignmentCredits.insert(nodeData->getWalletUUID(), freshTransaction); } } - - return true; }); } @@ -1127,8 +1123,6 @@ void DomainServer::sendHeartbeatToDataServer(const QString& networkAddress) { if (node->getLinkedData() && !static_cast(node->getLinkedData())->getUsername().isEmpty()) { ++numConnectedAuthedUsers; } - - return true; }); const QString DOMAIN_HEARTBEAT_KEY = "heartbeat"; @@ -1440,8 +1434,6 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url QString uuidString = uuidStringWithoutCurlyBraces(nodeData->getAssignmentUUID()); assignedNodesJSON[uuidString] = jsonObjectForNode(node); } - - return true; }); assignmentJSON["fulfilled"] = assignedNodesJSON; @@ -1499,8 +1491,6 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url LimitedNodeList::getInstance()->eachNode([this, &nodesJSONArray](const SharedNodePointer& node){ // add the node using the UUID as the key nodesJSONArray.append(jsonObjectForNode(node)); - - return true; }); rootJSON["nodes"] = nodesJSONArray; diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index 4202444749..ac63941882 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -422,8 +422,6 @@ unsigned LimitedNodeList::broadcastToNodes(const QByteArray& packet, const NodeS writeDatagram(packet, node); ++n; } - - return true; }); return n; diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index 750e5b8688..25c560b2e2 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -131,6 +131,15 @@ public: void eachNode(NodeLambda functor) { QReadLocker readLock(&_nodeMutex); + for (NodeHash::const_iterator it = _nodeHash.cbegin(); it != _nodeHash.cend(); ++it) { + functor(it->second); + } + } + + template + void eachNodeBreakable(BreakableNodeLambda functor) { + QReadLocker readLock(&_nodeMutex); + for (NodeHash::const_iterator it = _nodeHash.cbegin(); it != _nodeHash.cend(); ++it) { if (!functor(it->second)) { break; diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index 7271dfe446..bf992e7b88 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -454,8 +454,6 @@ void NodeList::pingInactiveNodes() { // we don't have an active link to this node, ping it to set that up pingPunchForInactiveNode(node); } - - return true; }); } diff --git a/libraries/octree/src/JurisdictionListener.cpp b/libraries/octree/src/JurisdictionListener.cpp index f16daf9f0d..bcd5e9ac1c 100644 --- a/libraries/octree/src/JurisdictionListener.cpp +++ b/libraries/octree/src/JurisdictionListener.cpp @@ -43,8 +43,6 @@ bool JurisdictionListener::queueJurisdictionRequest() { _packetSender.queuePacketForSending(node, QByteArray(reinterpret_cast(bufferOut), sizeOut)); nodeCount++; } - - return true; }); if (nodeCount > 0){ diff --git a/libraries/octree/src/OctreeEditPacketSender.cpp b/libraries/octree/src/OctreeEditPacketSender.cpp index c0866a981e..8c94316d28 100644 --- a/libraries/octree/src/OctreeEditPacketSender.cpp +++ b/libraries/octree/src/OctreeEditPacketSender.cpp @@ -52,7 +52,7 @@ bool OctreeEditPacketSender::serversExist() const { bool hasServers = false; bool atLeastOneJurisdictionMissing = false; // assume the best - NodeList::getInstance()->eachNode([&](const SharedNodePointer& node){ + NodeList::getInstance()->eachNodeBreakable([&](const SharedNodePointer& node){ if (node->getType() == getMyNodeType() && node->getActiveSocket()) { QUuid nodeUUID = node->getUUID(); @@ -126,8 +126,6 @@ void OctreeEditPacketSender::queuePacketToNode(const QUuid& nodeUUID, unsigned c " transitTimeSoFar=" << transitTime << " usecs"; } } - - return true; }); } @@ -209,8 +207,6 @@ void OctreeEditPacketSender::queuePacketToNodes(unsigned char* buffer, size_t le queuePacketToNode(nodeUUID, buffer, length, satoshiCost); } } - - return true; }); } @@ -299,8 +295,6 @@ void OctreeEditPacketSender::queueOctreeEditMessage(PacketType type, unsigned ch packetBuffer._satoshiCost += satoshiCost; } } - - return true; }); _packetsQueueLock.unlock(); diff --git a/libraries/octree/src/OctreeHeadlessViewer.cpp b/libraries/octree/src/OctreeHeadlessViewer.cpp index e40ae712e9..e0ca22e4e8 100644 --- a/libraries/octree/src/OctreeHeadlessViewer.cpp +++ b/libraries/octree/src/OctreeHeadlessViewer.cpp @@ -113,8 +113,6 @@ void OctreeHeadlessViewer::queryOctree() { } } } - - return true; }); if (wantExtraDebugging) { @@ -234,8 +232,6 @@ void OctreeHeadlessViewer::queryOctree() { // make sure we still have an active socket nodeList->writeUnverifiedDatagram(reinterpret_cast(queryPacket), packetLength, node); } - - return true; }); } From 948615afe5dc90e1187e1a2fff7493f9e8f19118 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 6 Nov 2014 13:44:03 -0800 Subject: [PATCH 018/502] move metavoxels library to tbb concurrent map --- .../metavoxels/src/MetavoxelClientManager.cpp | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/libraries/metavoxels/src/MetavoxelClientManager.cpp b/libraries/metavoxels/src/MetavoxelClientManager.cpp index 7765b8cda2..3148f870c2 100644 --- a/libraries/metavoxels/src/MetavoxelClientManager.cpp +++ b/libraries/metavoxels/src/MetavoxelClientManager.cpp @@ -43,24 +43,22 @@ SharedObjectPointer MetavoxelClientManager::findFirstRaySpannerIntersection(cons SharedObjectPointer closestSpanner; float closestDistance = FLT_MAX; - NodeHashSnapshot snapshotHash = NodeList::getInstance()->getNodeHash().snapshot_table(); - for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { - SharedNodePointer node = it->second; - + NodeList::getInstance()->eachNode([&](const SharedNodePointer& node){ if (node->getType() == NodeType::MetavoxelServer) { QMutexLocker locker(&node->getMutex()); MetavoxelClient* client = static_cast(node->getLinkedData()); if (client) { float clientDistance; SharedObjectPointer clientSpanner = client->getDataCopy().findFirstRaySpannerIntersection( - origin, direction, attribute, clientDistance); + origin, direction, attribute, clientDistance); if (clientSpanner && clientDistance < closestDistance) { closestSpanner = clientSpanner; closestDistance = clientDistance; } } } - } + }); + if (closestSpanner) { distance = closestDistance; } @@ -119,11 +117,7 @@ MetavoxelClient* MetavoxelClientManager::createClient(const SharedNodePointer& n } void MetavoxelClientManager::guide(MetavoxelVisitor& visitor) { - NodeHashSnapshot snapshotHash = NodeList::getInstance()->getNodeHash().snapshot_table(); - - for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { - SharedNodePointer node = it->second; - + NodeList::getInstance()->eachNode([&visitor](const SharedNodePointer& node){ if (node->getType() == NodeType::MetavoxelServer) { QMutexLocker locker(&node->getMutex()); MetavoxelClient* client = static_cast(node->getLinkedData()); @@ -131,7 +125,7 @@ void MetavoxelClientManager::guide(MetavoxelVisitor& visitor) { client->getDataCopy().guide(visitor); } } - } + }); } MetavoxelUpdater::MetavoxelUpdater(MetavoxelClientManager* clientManager) : From 51bc5d10b55de0654f471c2be8978d7b48de2edb Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 6 Nov 2014 13:46:26 -0800 Subject: [PATCH 019/502] fix network includes in LimitedNodeList --- libraries/networking/src/LimitedNodeList.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index 25c560b2e2..a29902a7c9 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -24,8 +24,8 @@ #include #include #include -#include -#include +#include +#include #include From 38f2b2ac6a841dafe5afc70de01df83f39060e92 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 6 Nov 2014 13:47:56 -0800 Subject: [PATCH 020/502] move script-engine library to intel tbb concurrent map --- libraries/script-engine/src/ScriptEngine.cpp | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 340d5b3e20..5b5dd6cd53 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -520,21 +520,17 @@ void ScriptEngine::run() { // write audio packet to AudioMixer nodes NodeList* nodeList = NodeList::getInstance(); - NodeHashSnapshot snapshotHash = nodeList->getNodeHash().snapshot_table(); - - for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { - SharedNodePointer node = it->second; - + nodeList->eachNode([this, &nodeList, &audioPacket, &numPreSequenceNumberBytes](const SharedNodePointer& node){ // only send to nodes of type AudioMixer if (node->getType() == NodeType::AudioMixer) { // pack sequence number quint16 sequence = _outgoingScriptAudioSequenceNumbers[node->getUUID()]++; memcpy(audioPacket.data() + numPreSequenceNumberBytes, &sequence, sizeof(quint16)); - + // send audio packet nodeList->writeDatagram(audioPacket, node); } - } + }); } } From 1a953b5906a9da2b6b29fc6c609180328cabf2b0 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 6 Nov 2014 13:53:10 -0800 Subject: [PATCH 021/502] migrate node hash calls from AudioMixer to new tbb format --- assignment-client/src/audio/AudioMixer.cpp | 52 +++++++------------ assignment-client/src/avatars/AvatarMixer.cpp | 12 ++--- 2 files changed, 22 insertions(+), 42 deletions(-) diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index 39011b8083..4236072857 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -438,16 +438,12 @@ int AudioMixer::prepareMixForListeningNode(Node* node) { // loop through all other nodes that have sufficient audio to mix int streamsMixed = 0; - NodeHashSnapshot snapshotHash = NodeList::getInstance()->getNodeHash().snapshot_table(); - - for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { - SharedNodePointer otherNode = it->second; - + NodeList::getInstance()->eachNode([&](const SharedNodePointer& otherNode){ if (otherNode->getLinkedData()) { AudioMixerClientData* otherNodeClientData = (AudioMixerClientData*) otherNode->getLinkedData(); - + // enumerate the ARBs attached to the otherNode and add all that should be added to mix - + const QHash& otherNodeAudioStreams = otherNodeClientData->getAudioStreams(); QHash::ConstIterator i; for (i = otherNodeAudioStreams.constBegin(); i != otherNodeAudioStreams.constEnd(); i++) { @@ -457,14 +453,15 @@ int AudioMixer::prepareMixForListeningNode(Node* node) { if (otherNodeStream->getType() == PositionalAudioStream::Microphone) { streamUUID = otherNode->getUUID(); } - + if (*otherNode != *node || otherNodeStream->shouldLoopbackForNode()) { - streamsMixed += addStreamToMixForListeningNodeWithStream(listenerNodeData, streamUUID, - otherNodeStream, nodeAudioStream); + streamsMixed += addStreamToMixForListeningNodeWithStream(listenerNodeData, streamUUID, + otherNodeStream, nodeAudioStream); } } } - } + }); + return streamsMixed; } @@ -485,16 +482,11 @@ void AudioMixer::readPendingDatagram(const QByteArray& receivedPacket, const Hif QByteArray packet = receivedPacket; populatePacketHeader(packet, PacketTypeMuteEnvironment); - NodeHashSnapshot snapshotHash = nodeList->getNodeHash().snapshot_table(); - - for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { - SharedNodePointer node = it->second; - + nodeList->eachNode([&](const SharedNodePointer& node){ if (node->getType() == NodeType::Agent && node->getActiveSocket() && node->getLinkedData() && node != nodeList->sendingNodeForPacket(receivedPacket)) { nodeList->writeDatagram(packet, packet.size(), node); } - } - + }); } else { // let processNodeData handle it. nodeList->processNodeData(senderSockAddr, receivedPacket); @@ -558,9 +550,8 @@ void AudioMixer::sendStatsPacket() { NodeList* nodeList = NodeList::getInstance(); int clientNumber = 0; - NodeHashSnapshot snapshotHash = nodeList->getNodeHash().snapshot_table(); - for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { + nodeList->eachNode([&](const SharedNodePointer& node) { // if we're too large, send the packet if (sizeOfStats > TOO_BIG_FOR_MTU) { nodeList->sendStatsToDomainServer(statsObject2); @@ -570,15 +561,15 @@ void AudioMixer::sendStatsPacket() { } clientNumber++; - AudioMixerClientData* clientData = static_cast(it->second->getLinkedData()); + AudioMixerClientData* clientData = static_cast(node->getLinkedData()); if (clientData) { - QString property = "jitterStats." + it->first.toString(); + QString property = "jitterStats." + node->getUUID().toString(); QString value = clientData->getAudioStreamStatsString(); statsObject2[qPrintable(property)] = value; somethingToSend = true; sizeOfStats += property.size() + value.size(); } - } + }); if (somethingToSend) { nodeList->sendStatsToDomainServer(statsObject2); @@ -717,10 +708,7 @@ void AudioMixer::run() { _lastPerSecondCallbackTime = now; } - NodeHashSnapshot snapshotHash = nodeList->getNodeHash().snapshot_table(); - - for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { - SharedNodePointer node = it->second; + nodeList->eachNode([&](const SharedNodePointer& node) { if (node->getLinkedData()) { AudioMixerClientData* nodeData = (AudioMixerClientData*)node->getLinkedData(); @@ -830,7 +818,7 @@ void AudioMixer::run() { ++_sumListeners; } } - } + }); ++_numStatFrames; @@ -888,11 +876,7 @@ void AudioMixer::perSecondActions() { _timeSpentPerHashMatchCallStats.getWindowSum() / WINDOW_LENGTH_USECS * 100.0, _timeSpentPerHashMatchCallStats.getCurrentIntervalSum() / USECS_PER_SECOND * 100.0); - NodeHashSnapshot snapshotHash = NodeList::getInstance()->getNodeHash().snapshot_table(); - - for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { - SharedNodePointer node = it->second; - + NodeList::getInstance()->eachNode([](const SharedNodePointer& node) { if (node->getLinkedData()) { AudioMixerClientData* nodeData = (AudioMixerClientData*)node->getLinkedData(); @@ -902,7 +886,7 @@ void AudioMixer::perSecondActions() { nodeData->printUpstreamDownstreamStats(); } } - } + }); } _datagramsReadPerCallStats.currentIntervalComplete(); diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index 3c2fa92c7c..107ce29ac9 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -122,9 +122,7 @@ void AvatarMixer::broadcastAvatarData() { AvatarMixerClientData* nodeData = NULL; AvatarMixerClientData* otherNodeData = NULL; - NodeHashSnapshot snapshotHash = nodeList->getNodeHash().snapshot_table(); - for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { - SharedNodePointer node = it->second; + nodeList->eachNode([&](const SharedNodePointer& node) { if (node->getLinkedData() && node->getType() == NodeType::Agent && node->getActiveSocket() && (nodeData = reinterpret_cast(node->getLinkedData()))->getMutex().tryLock()) { ++_sumListeners; @@ -137,9 +135,7 @@ void AvatarMixer::broadcastAvatarData() { // this is an AGENT we have received head data from // send back a packet with other active node data to this node - NodeHashSnapshot snapshotHash = nodeList->getNodeHash().snapshot_table(); - for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { - SharedNodePointer otherNode = it->second; + nodeList->eachNode([&](const SharedNodePointer& otherNode) { if (otherNode->getLinkedData() && otherNode->getUUID() != node->getUUID() && (otherNodeData = reinterpret_cast(otherNode->getLinkedData()))->getMutex().tryLock()) { @@ -207,13 +203,13 @@ void AvatarMixer::broadcastAvatarData() { otherNodeData->getMutex().unlock(); } - } + }); nodeList->writeDatagram(mixedAvatarByteArray, node); nodeData->getMutex().unlock(); } - } + }); _lastFrameTimestamp = QDateTime::currentMSecsSinceEpoch(); } From 881d03b11dd6060c0919d6006683ccbe256071bc Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 6 Nov 2014 13:54:40 -0800 Subject: [PATCH 022/502] migrate EntityServer and OctreeServer to tbb concurrent map --- assignment-client/src/entities/EntityServer.cpp | 9 +++------ assignment-client/src/octree/OctreeServer.cpp | 9 ++++----- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/assignment-client/src/entities/EntityServer.cpp b/assignment-client/src/entities/EntityServer.cpp index 31999f91f7..a39e7acbf4 100644 --- a/assignment-client/src/entities/EntityServer.cpp +++ b/assignment-client/src/entities/EntityServer.cpp @@ -124,11 +124,7 @@ void EntityServer::pruneDeletedEntities() { quint64 earliestLastDeletedEntitiesSent = usecTimestampNow() + 1; // in the future - NodeHashSnapshot snapshotHash = NodeList::getInstance()->getNodeHash().snapshot_table(); - - for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { - SharedNodePointer node = it->second; - + NodeList::getInstance()->eachNode([&earliestLastDeletedEntitiesSent](const SharedNodePointer& node) { if (node->getLinkedData()) { EntityNodeData* nodeData = static_cast(node->getLinkedData()); quint64 nodeLastDeletedEntitiesSentAt = nodeData->getLastDeletedEntitiesSentAt(); @@ -136,7 +132,8 @@ void EntityServer::pruneDeletedEntities() { earliestLastDeletedEntitiesSent = nodeLastDeletedEntitiesSentAt; } } - } + }); + tree->forgetEntitiesDeletedBefore(earliestLastDeletedEntitiesSent); } } diff --git a/assignment-client/src/octree/OctreeServer.cpp b/assignment-client/src/octree/OctreeServer.cpp index 2b38ce3cdd..e6211a046a 100644 --- a/assignment-client/src/octree/OctreeServer.cpp +++ b/assignment-client/src/octree/OctreeServer.cpp @@ -1138,12 +1138,11 @@ void OctreeServer::aboutToFinish() { qDebug() << qPrintable(_safeServerName) << "inform Octree Inbound Packet Processor that we are shutting down..."; _octreeInboundPacketProcessor->shuttingDown(); - NodeHashSnapshot snapshotHash = NodeList::getInstance()->getNodeHash().snapshot_table(); + NodeList::getInstance()->eachNode([this](const SharedNodePointer& node) { + qDebug() << qPrintable(_safeServerName) << "server about to finish while node still connected node:" << *node; + forceNodeShutdown(node); + }); - for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { - qDebug() << qPrintable(_safeServerName) << "server about to finish while node still connected node:" << *it->second; - forceNodeShutdown(it->second); - } qDebug() << qPrintable(_safeServerName) << "server ENDING about to finish..."; } From 0e9e8a003692a4ac4b42005da026a53c22b015a1 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 6 Nov 2014 13:56:19 -0800 Subject: [PATCH 023/502] remove libcuckoo and readme --- .gitignore | 4 ---- .../networking/externals/libcuckoo/readme.txt | 14 -------------- 2 files changed, 18 deletions(-) delete mode 100644 libraries/networking/externals/libcuckoo/readme.txt diff --git a/.gitignore b/.gitignore index 74a5748b85..6e6b69cb66 100644 --- a/.gitignore +++ b/.gitignore @@ -32,9 +32,5 @@ DerivedData interface/external/*/* !interface/external/*/readme.txt -# ignore libraries externals -libraries/*/externals/*/* -!libraries/*/externals/*/readme.txt - # Ignore interfaceCache for Linux users interface/interfaceCache/ diff --git a/libraries/networking/externals/libcuckoo/readme.txt b/libraries/networking/externals/libcuckoo/readme.txt deleted file mode 100644 index b86f8bc609..0000000000 --- a/libraries/networking/externals/libcuckoo/readme.txt +++ /dev/null @@ -1,14 +0,0 @@ - -Instructions for adding the libcuckoo library to Interface -Stephen Birarda, November 5, 2014 - -1. Download the libcuckoo ZIP from the High Fidelity libcuckoo fork on Github. - https://github.com/highfidelity/libcuckoo/archive/master.zip - -2. Copy the libcuckoo folder from inside the ZIP to libraries/networking/externals/libcuckoo/. - - You should have the following structure: - - libraries/networking/externals/libcuckoo/libcuckoo/cuckoohash_map.hh - -3. Delete your build directory, run cmake and build, and you should be all set. From 455cbac8a5d4a5c8f2a8869a56e366a288cdcaea Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 6 Nov 2014 15:16:45 -0800 Subject: [PATCH 024/502] repairs to node hash iterations in Application --- interface/src/Application.cpp | 87 ++++++++++++++++------------------- 1 file changed, 40 insertions(+), 47 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index f5842ed4c3..516701d085 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2405,75 +2405,73 @@ int Application::sendNackPackets() { char packet[MAX_PACKET_SIZE]; // iterates thru all nodes in NodeList - NodeHashSnapshot snapshotHash = NodeList::getInstance()->getNodeHash().snapshot_table(); + NodeList* nodeList = NodeList::getInstance(); - for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { - SharedNodePointer node = it->second; + nodeList->eachNode([&](const SharedNodePointer& node){ - if (node->getActiveSocket() && - ( node->getType() == NodeType::VoxelServer - || node->getType() == NodeType::EntityServer) - ) { - + if (node->getActiveSocket() + && (node->getType() == NodeType::VoxelServer || node->getType() == NodeType::EntityServer)) { + QUuid nodeUUID = node->getUUID(); - + // if there are octree packets from this node that are waiting to be processed, // don't send a NACK since the missing packets may be among those waiting packets. if (_octreeProcessor.hasPacketsToProcessFrom(nodeUUID)) { - continue; + return; } _octreeSceneStatsLock.lockForRead(); - + // retreive octree scene stats of this node if (_octreeServerSceneStats.find(nodeUUID) == _octreeServerSceneStats.end()) { _octreeSceneStatsLock.unlock(); - continue; + return; } - + // get sequence number stats of node, prune its missing set, and make a copy of the missing set SequenceNumberStats& sequenceNumberStats = _octreeServerSceneStats[nodeUUID].getIncomingOctreeSequenceNumberStats(); sequenceNumberStats.pruneMissingSet(); const QSet missingSequenceNumbers = sequenceNumberStats.getMissingSet(); - + _octreeSceneStatsLock.unlock(); - + // construct nack packet(s) for this node int numSequenceNumbersAvailable = missingSequenceNumbers.size(); QSet::const_iterator missingSequenceNumbersIterator = missingSequenceNumbers.constBegin(); while (numSequenceNumbersAvailable > 0) { - + char* dataAt = packet; int bytesRemaining = MAX_PACKET_SIZE; - + // pack header int numBytesPacketHeader = populatePacketHeader(packet, PacketTypeOctreeDataNack); dataAt += numBytesPacketHeader; bytesRemaining -= numBytesPacketHeader; - + // calculate and pack the number of sequence numbers int numSequenceNumbersRoomFor = (bytesRemaining - sizeof(uint16_t)) / sizeof(OCTREE_PACKET_SEQUENCE); uint16_t numSequenceNumbers = min(numSequenceNumbersAvailable, numSequenceNumbersRoomFor); uint16_t* numSequenceNumbersAt = (uint16_t*)dataAt; *numSequenceNumbersAt = numSequenceNumbers; dataAt += sizeof(uint16_t); - + // pack sequence numbers for (int i = 0; i < numSequenceNumbers; i++) { OCTREE_PACKET_SEQUENCE* sequenceNumberAt = (OCTREE_PACKET_SEQUENCE*)dataAt; *sequenceNumberAt = *missingSequenceNumbersIterator; dataAt += sizeof(OCTREE_PACKET_SEQUENCE); - + missingSequenceNumbersIterator++; } numSequenceNumbersAvailable -= numSequenceNumbers; - + // send it - NodeList::getInstance()->writeUnverifiedDatagram(packet, dataAt - packet, node); + nodeList->writeUnverifiedDatagram(packet, dataAt - packet, node); packetsSent++; } } - } + }); + return packetsSent; } @@ -2507,12 +2505,8 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node int unknownJurisdictionServers = 0; NodeList* nodeList = NodeList::getInstance(); - NodeHashSnapshot snapshotHash = nodeList->getNodeHash().snapshot_table(); - for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { - - SharedNodePointer node = it->second; - + nodeList->eachNode([&](const SharedNodePointer& node) { // only send to the NodeTypes that are serverType if (node->getActiveSocket() && node->getType() == serverType) { totalServers++; @@ -2543,7 +2537,7 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node } } } - } + }); if (wantExtraDebugging) { qDebug("Servers: total %d, in view %d, unknown jurisdiction %d", @@ -2570,18 +2564,17 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node qDebug("perServerPPS: %d perUnknownServer: %d", perServerPPS, perUnknownServer); } - for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { - SharedNodePointer node = it->second; + nodeList->eachNode([&](const SharedNodePointer& node){ // only send to the NodeTypes that are serverType if (node->getActiveSocket() && node->getType() == serverType) { - - + + // get the server bounds for this server QUuid nodeUUID = node->getUUID(); - + bool inView = false; bool unknownView = false; - + // if we haven't heard from this voxel server, go ahead and send it a query, so we // can get the jurisdiction... if (jurisdictions.find(nodeUUID) == jurisdictions.end()) { @@ -2591,15 +2584,15 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node } } else { const JurisdictionMap& map = (jurisdictions)[nodeUUID]; - + unsigned char* rootCode = map.getRootOctalCode(); - + if (rootCode) { VoxelPositionSize rootDetails; voxelDetailsForCode(rootCode, rootDetails); AACube serverBounds(glm::vec3(rootDetails.x, rootDetails.y, rootDetails.z), rootDetails.s); serverBounds.scale(TREE_SCALE); - + ViewFrustum::location serverFrustumLocation = _viewFrustum.cubeInFrustum(serverBounds); if (serverFrustumLocation != ViewFrustum::OUTSIDE) { inView = true; @@ -2612,15 +2605,15 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node } } } - + if (inView) { _octreeQuery.setMaxOctreePacketsPerSecond(perServerPPS); } else if (unknownView) { if (wantExtraDebugging) { qDebug() << "no known jurisdiction for node " << *node << ", give it budget of " - << perUnknownServer << " to send us jurisdiction."; + << perUnknownServer << " to send us jurisdiction."; } - + // set the query's position/orientation to be degenerate in a manner that will get the scene quickly // If there's only one server, then don't do this, and just let the normal voxel query pass through // as expected... this way, we will actually get a valid scene if there is one to be seen @@ -2644,22 +2637,22 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node } // set up the packet for sending... unsigned char* endOfQueryPacket = queryPacket; - + // insert packet type/version and node UUID endOfQueryPacket += populatePacketHeader(reinterpret_cast(endOfQueryPacket), packetType); - + // encode the query data... endOfQueryPacket += _octreeQuery.getBroadcastData(endOfQueryPacket); - + int packetLength = endOfQueryPacket - queryPacket; - + // make sure we still have an active socket nodeList->writeUnverifiedDatagram(reinterpret_cast(queryPacket), packetLength, node); - + // Feed number of bytes to corresponding channel of the bandwidth meter _bandwidthMeter.outputStream(BandwidthMeter::VOXELS).updateValue(packetLength); } - } + }); } ///////////////////////////////////////////////////////////////////////////////////// From aa7e99567253708152e69a5aff0681d1174631f6 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 6 Nov 2014 15:18:56 -0800 Subject: [PATCH 025/502] update MetavoxelSystem.cpp to new tbb node iteration --- interface/src/MetavoxelSystem.cpp | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/interface/src/MetavoxelSystem.cpp b/interface/src/MetavoxelSystem.cpp index 20a7bc906f..2ca17e32c1 100644 --- a/interface/src/MetavoxelSystem.cpp +++ b/interface/src/MetavoxelSystem.cpp @@ -163,12 +163,7 @@ void MetavoxelSystem::render() { } void MetavoxelSystem::refreshVoxelData() { - NodeHashSnapshot snapshotHash = NodeList::getInstance()->getNodeHash().snapshot_table(); - - for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { - - SharedNodePointer node = it->second; - + NodeList::getInstance()->eachNode([](const SharedNodePointer& node){ if (node->getType() == NodeType::MetavoxelServer) { QMutexLocker locker(&node->getMutex()); MetavoxelSystemClient* client = static_cast(node->getLinkedData()); @@ -176,7 +171,7 @@ void MetavoxelSystem::refreshVoxelData() { QMetaObject::invokeMethod(client, "refreshVoxelData"); } } - } + }); } class RayHeightfieldIntersectionVisitor : public RayIntersectionVisitor { @@ -690,11 +685,7 @@ MetavoxelClient* MetavoxelSystem::createClient(const SharedNodePointer& node) { } void MetavoxelSystem::guideToAugmented(MetavoxelVisitor& visitor, bool render) { - NodeHashSnapshot snapshotHash = NodeList::getInstance()->getNodeHash().snapshot_table(); - - for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { - SharedNodePointer node = it->second; - + NodeList::getInstance()->eachNode([&visitor, &render](const SharedNodePointer& node) { if (node->getType() == NodeType::MetavoxelServer) { QMutexLocker locker(&node->getMutex()); MetavoxelSystemClient* client = static_cast(node->getLinkedData()); @@ -708,7 +699,7 @@ void MetavoxelSystem::guideToAugmented(MetavoxelVisitor& visitor, bool render) { } } } - } + }); } Throttle::Throttle() : From d82e2fb8f448c8b8a40658a71be377c458bb655b Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 6 Nov 2014 15:21:18 -0800 Subject: [PATCH 026/502] update NodeBounds.cpp to new tbb node iteration --- interface/src/ui/NodeBounds.cpp | 38 +++++++++++++++------------------ 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/interface/src/ui/NodeBounds.cpp b/interface/src/ui/NodeBounds.cpp index 6298385c90..dedc687cc2 100644 --- a/interface/src/ui/NodeBounds.cpp +++ b/interface/src/ui/NodeBounds.cpp @@ -53,65 +53,61 @@ void NodeBounds::draw() { float selectedScale = 0; NodeList* nodeList = NodeList::getInstance(); - NodeHashSnapshot snapshotHash = nodeList->getNodeHash().snapshot_table(); - - for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { - SharedNodePointer node = it->second; - + nodeList->eachNode([&](const SharedNodePointer& node){ NodeType_t nodeType = node->getType(); - + if (nodeType == NodeType::VoxelServer && _showVoxelNodes) { serverJurisdictions = &voxelServerJurisdictions; } else if (nodeType == NodeType::EntityServer && _showEntityNodes) { serverJurisdictions = &entityServerJurisdictions; } else { - continue; + return; } - + QUuid nodeUUID = node->getUUID(); serverJurisdictions->lockForRead(); if (serverJurisdictions->find(nodeUUID) != serverJurisdictions->end()) { const JurisdictionMap& map = (*serverJurisdictions)[nodeUUID]; - + unsigned char* rootCode = map.getRootOctalCode(); - + if (rootCode) { VoxelPositionSize rootDetails; voxelDetailsForCode(rootCode, rootDetails); serverJurisdictions->unlock(); glm::vec3 location(rootDetails.x, rootDetails.y, rootDetails.z); location *= (float)TREE_SCALE; - + AACube serverBounds(location, rootDetails.s * TREE_SCALE); - + glm::vec3 center = serverBounds.getVertex(BOTTOM_RIGHT_NEAR) - + ((serverBounds.getVertex(TOP_LEFT_FAR) - serverBounds.getVertex(BOTTOM_RIGHT_NEAR)) / 2.0f); - + + ((serverBounds.getVertex(TOP_LEFT_FAR) - serverBounds.getVertex(BOTTOM_RIGHT_NEAR)) / 2.0f); + const float VOXEL_NODE_SCALE = 1.00f; const float ENTITY_NODE_SCALE = 0.99f; - + float scaleFactor = rootDetails.s * TREE_SCALE; - + // Scale by 0.92 - 1.00 depending on the scale of the node. This allows smaller nodes to scale in // a bit and not overlap larger nodes. scaleFactor *= 0.92 + (rootDetails.s * 0.08); - + // Scale different node types slightly differently because it's common for them to overlap. if (nodeType == NodeType::VoxelServer) { scaleFactor *= VOXEL_NODE_SCALE; } else if (nodeType == NodeType::EntityServer) { scaleFactor *= ENTITY_NODE_SCALE; } - + float red, green, blue; getColorForNodeType(nodeType, red, green, blue); drawNodeBorder(center, scaleFactor, red, green, blue); - + float distance; BoxFace face; bool inside = serverBounds.contains(mouseRayOrigin); bool colliding = serverBounds.findRayIntersection(mouseRayOrigin, mouseRayDirection, distance, face); - + // If the camera is inside a node it will be "selected" if you don't have your cursor over another node // that you aren't inside. if (colliding && (!selectedNode || (!inside && (distance < selectedDistance || selectedIsInside)))) { @@ -127,7 +123,7 @@ void NodeBounds::draw() { } else { serverJurisdictions->unlock(); } - } + }); if (selectedNode) { glPushMatrix(); From ce02d79d415e9ef4411ffc03fe971ccafb2d676c Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 6 Nov 2014 15:22:30 -0800 Subject: [PATCH 027/502] update OctreeStatsDialog to new tbb node iteration --- interface/src/ui/OctreeStatsDialog.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/interface/src/ui/OctreeStatsDialog.cpp b/interface/src/ui/OctreeStatsDialog.cpp index 8a6d6442f5..14da45e1d1 100644 --- a/interface/src/ui/OctreeStatsDialog.cpp +++ b/interface/src/ui/OctreeStatsDialog.cpp @@ -248,10 +248,8 @@ void OctreeStatsDialog::showOctreeServersOfType(int& serverCount, NodeType_t ser QLocale locale(QLocale::English); NodeList* nodeList = NodeList::getInstance(); - NodeHashSnapshot snapshotHash = nodeList->getNodeHash().snapshot_table(); - - for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { - SharedNodePointer node = it->second; + nodeList->eachNode([&](const SharedNodePointer& node){ + // only send to the NodeTypes that are NodeType_t_VOXEL_SERVER if (node->getType() == serverType) { serverCount++; @@ -422,7 +420,7 @@ void OctreeStatsDialog::showOctreeServersOfType(int& serverCount, NodeType_t ser serverDetails << linkDetails.str(); _labels[_voxelServerLables[serverCount - 1]]->setText(serverDetails.str().c_str()); } // is VOXEL_SERVER - } + }); } void OctreeStatsDialog::reject() { From 2f66e56e46eb3f900f2b9385259e6b319b7c2821 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 6 Nov 2014 15:23:30 -0800 Subject: [PATCH 028/502] update Stats to new tbb node iteration --- interface/src/ui/Stats.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index 8e4b900180..08eaac9334 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -329,10 +329,7 @@ void Stats::display( unsigned long totalPingVoxel = 0; int voxelServerCount = 0; - NodeHashSnapshot snapshotHash = nodeList->getNodeHash().snapshot_table(); - - for (auto it = snapshotHash.begin(); it != snapshotHash.end(); it++) { - SharedNodePointer node = it->second; + nodeList->eachNode([&totalPingVoxel, &pingVoxelMax, &voxelServerCount](const SharedNodePointer& node){ // TODO: this should also support entities if (node->getType() == NodeType::VoxelServer) { totalPingVoxel += node->getPingMs(); @@ -341,7 +338,7 @@ void Stats::display( pingVoxelMax = node->getPingMs(); } } - } + }); if (voxelServerCount) { pingVoxel = totalPingVoxel/voxelServerCount; From 996c76c723f4dd591707be56da8ad74ecbce06fb Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 6 Nov 2014 16:05:01 -0800 Subject: [PATCH 029/502] repairs for node teardown on domain dissappear or node disconnect --- domain-server/src/DomainServer.cpp | 4 +-- libraries/networking/src/LimitedNodeList.cpp | 34 ++++++++++++++++---- libraries/networking/src/LimitedNodeList.h | 2 ++ 3 files changed, 31 insertions(+), 9 deletions(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index cb4b1c8026..153fbae0c9 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -2019,9 +2019,9 @@ void DomainServer::addStaticAssignmentsToQueue() { QHash::iterator staticAssignment = staticHashCopy.begin(); while (staticAssignment != staticHashCopy.end()) { // add any of the un-matched static assignments to the queue - + // enumerate the nodes and check if there is one with an attached assignment with matching UUID - if (NodeList::getInstance()->nodeWithUUID(staticAssignment->data()->getUUID())) { + if (!NodeList::getInstance()->nodeWithUUID(staticAssignment->data()->getUUID())) { // this assignment has not been fulfilled - reset the UUID and add it to the assignment queue refreshStaticAssignmentAndAddToQueue(*staticAssignment); } diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index ac63941882..767935bf3d 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -359,11 +359,18 @@ SharedNodePointer LimitedNodeList::sendingNodeForPacket(const QByteArray& packet void LimitedNodeList::eraseAllNodes() { qDebug() << "Clearing the NodeList. Deleting all nodes in list."; + QSet killedNodes; + eachNode([&killedNodes](const SharedNodePointer& node){ + killedNodes.insert(node); + }); + // iterate the current nodes, emit that they are dying and remove them from the hash - QWriteLocker writeLock(&_nodeMutex); - for (NodeHash::iterator it = _nodeHash.begin(); it != _nodeHash.end(); ++it) { - emit nodeKilled(it->second); - it = _nodeHash.unsafe_erase(it); + _nodeMutex.lockForWrite(); + _nodeHash.clear(); + _nodeMutex.unlock(); + + foreach(const SharedNodePointer& killedNode, killedNodes) { + handleNodeKill(killedNode); } } @@ -378,7 +385,8 @@ void LimitedNodeList::killNodeWithUUID(const QUuid& nodeUUID) { QWriteLocker writeLocker(&_nodeMutex); _nodeHash.unsafe_erase(it); - emit nodeKilled(matchingNode); + + handleNodeKill(matchingNode); } } @@ -390,6 +398,11 @@ void LimitedNodeList::processKillNode(const QByteArray& dataByteArray) { killNodeWithUUID(nodeUUID); } +void LimitedNodeList::handleNodeKill(const SharedNodePointer& node) { + qDebug() << "Killed" << *node; + emit nodeKilled(node); +} + SharedNodePointer LimitedNodeList::addOrUpdateNode(const QUuid& uuid, NodeType_t nodeType, const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket) { try { @@ -478,14 +491,17 @@ void LimitedNodeList::resetPacketStats() { } void LimitedNodeList::removeSilentNodes() { - eachNodeHashIterator([this](NodeHash::iterator& it){ + QSet killedNodes; + + eachNodeHashIterator([&](NodeHash::iterator& it){ SharedNodePointer node = it->second; node->getMutex().lock(); if ((usecTimestampNow() - node->getLastHeardMicrostamp()) > (NODE_SILENCE_THRESHOLD_MSECS * 1000)) { // call the NodeHash erase to get rid of this node it = _nodeHash.unsafe_erase(it); - emit nodeKilled(node); + + killedNodes.insert(node); } else { // we didn't erase this node, push the iterator forwards ++it; @@ -493,6 +509,10 @@ void LimitedNodeList::removeSilentNodes() { node->getMutex().unlock(); }); + + foreach(const SharedNodePointer& killedNode, killedNodes) { + handleNodeKill(killedNode); + } } const uint32_t RFC_5389_MAGIC_COOKIE = 0x2112A442; diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index a29902a7c9..d713f69d29 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -187,6 +187,8 @@ protected: const QUuid& connectionSecret); void changeSocketBufferSizes(int numBytes); + + void handleNodeKill(const SharedNodePointer& node); QUuid _sessionUUID; NodeHash _nodeHash; From 0119797454535fb58cce7b71354d33abe0d7f78e Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Tue, 18 Nov 2014 02:26:11 +0100 Subject: [PATCH 030/502] virtual keyboard rendered --- examples/virtualKeyboard.js | 235 ++++++++++++++++++++++++++++++++++++ 1 file changed, 235 insertions(+) create mode 100644 examples/virtualKeyboard.js diff --git a/examples/virtualKeyboard.js b/examples/virtualKeyboard.js new file mode 100644 index 0000000000..109196008d --- /dev/null +++ b/examples/virtualKeyboard.js @@ -0,0 +1,235 @@ +const KBD_UPPERCASE_DEFAULT = 0; +const KBD_LOWERCASE_DEFAULT = 1; +const KBD_UPPERCASE_HOVER = 2; +const KBD_LOWERCASE_HOVER = 3; +const KBD_BACKGROUND = 4; + +const KEYBOARD_URL = "http://test.thoys.nl/hifi/images/virtualKeyboard/keyboard.svg"; + +const KEYBOARD_HEIGHT = 434.1; +const KEYBOARD_WIDTH = 1174.7; + +const BOUND_X = 0; +const BOUND_Y = 1; +const BOUND_W = 2; +const BOUND_H = 3; + +const KEY_STATE_LOWER = 0; +const KEY_STATE_UPPER = 1; + +function KeyboardKey(keyboard, key_properties) { + this.event = key_properties.event != undefined ? + key_properties.event : 'keypress'; + this.bounds = key_properties.bounds; + this.states = key_properties.states; + this.keyboard = keyboard; + this.key_state = key_properties.key_state != undefined ? key_properties.key_state : KBD_LOWERCASE_HOVER; + // one overlay per bound vector [this.bounds] + this.overlays = []; + this.updatePosition = function() { + }; + this.containsCoord = function(x, y) { + for (var i = 0; i < this.bounds.length; i++) { + if (x >= this.bounds[i][BOUND_X] && + x <= (this.bounds[i][BOUND_X] + this.bounds[i][BOUND_W]) && + y >= this.bounds[i][BOUND_Y] && + y <= (this.bounds[i][BOUND_Y] + this.bounds[i][BOUND_H])) + { + return true; + } + } + return false; + }; + this.remove = function() { + for (var i = 0; i < this.overlays.length; i++) { + Overlays.deleteOverlay(this.overlays[i]); + } + }; + this.isLoaded = function() { + for (var i = 0; i < this.overlays.length; i++) { + if (!Overlays.isLoaded(this.overlays[i])) { + return false; + } + } + return true; + }; + for (var i = 0; i < this.bounds.length; i++) { + var newOverlay = Overlays.cloneOverlay(this.keyboard.background); + Overlays.editOverlay(newOverlay, { + x: 50 + this.bounds[i][BOUND_X], + y: 50 + this.bounds[i][BOUND_Y], + width: this.bounds[i][BOUND_W], + height: this.bounds[i][BOUND_H], + subImage: {width: this.bounds[i][BOUND_W], height: this.bounds[i][BOUND_H], x: this.bounds[i][BOUND_X], y: (KEYBOARD_HEIGHT * this.key_state) + this.bounds[i][BOUND_Y]}, + alpha: 1 + }); + this.overlays.push(newOverlay); + } +} + +function Keyboard() { + this.background = Overlays.addOverlay("image", { + x: 50, + y: 50, + width: KEYBOARD_WIDTH, + height: KEYBOARD_HEIGHT, + subImage: {width: KEYBOARD_WIDTH, height: KEYBOARD_HEIGHT, y: KEYBOARD_HEIGHT * KBD_BACKGROUND}, + imageURL: KEYBOARD_URL, + alpha: 1 + }); + this.updatePosition = function() { + + }; + this.getFocussedKey = function() { + + }; + this.remove = function() { + Overlays.deleteOverlay(this.background); + for (var i = 0; i < this.keys.length; i++) { + this.keys[i].remove(); + } + }; + + this.onKeyPress = null; + this.onKeyDown = null; + this.onKeyUp = null; + this.onSubmit = null; + + this.keys = []; + // + // keyProperties contains the key data + // + // coords [[x,y,w,h],[x,y,w,h]] + // states array of 1 or 2 objects [lowercase, uppercase] each object contains a charCode and a char + var keyProperties = [ + {bounds: [[12, 12, 65, 52]], states: [{charCode: 192, char: '~'}]}, + {bounds: [[84, 12, 65, 52]], states: [{charCode: 192, char: '!'}]}, + {bounds: [[156, 12, 65, 52]], states: [{charCode: 192, char: '@'}]}, + {bounds: [[228, 12, 65, 52]], states: [{charCode: 192, char: '#'}]}, + {bounds: [[300, 12, 65, 52]], states: [{charCode: 192, char: '$'}]}, + {bounds: [[372, 12, 65, 52]], states: [{charCode: 192, char: '%'}]}, + {bounds: [[445, 12, 65, 52]], states: [{charCode: 192, char: '^'}]}, + {bounds: [[517, 12, 65, 52]], states: [{charCode: 192, char: '&'}]}, + {bounds: [[589, 12, 65, 52]], states: [{charCode: 192, char: '*'}]}, + {bounds: [[662, 12, 65, 52]], states: [{charCode: 192, char: '('}]}, + {bounds: [[734, 12, 65, 52]], states: [{charCode: 192, char: ')'}]}, + {bounds: [[806, 12, 65, 52]], states: [{charCode: 192, char: '_'}]}, + {bounds: [[881, 12, 65, 52]], states: [{charCode: 192, char: '{'}]}, + {bounds: [[953, 12, 65, 52]], states: [{charCode: 192, char: '}'}]}, + {bounds: [[1025, 12, 65, 52]], states: [{charCode: 192, char: '<'}]}, + {bounds: [[1097, 12, 65, 52]], states: [{charCode: 192, char: '>'}]}, + + {bounds: [[12, 71, 65, 63]], states: [{charCode: 192, char: '`'}]}, + {bounds: [[84, 71, 65, 63]], states: [{charCode: 192, char: '1'}]}, + {bounds: [[156, 71, 65, 63]], states: [{charCode: 192, char: '2'}]}, + {bounds: [[228, 71, 65, 63]], states: [{charCode: 192, char: '3'}]}, + {bounds: [[300, 71, 65, 63]], states: [{charCode: 192, char: '4'}]}, + {bounds: [[372, 71, 65, 63]], states: [{charCode: 192, char: '5'}]}, + {bounds: [[445, 71, 65, 63]], states: [{charCode: 192, char: '6'}]}, + {bounds: [[517, 71, 65, 63]], states: [{charCode: 192, char: '7'}], key_state: KBD_UPPERCASE_DEFAULT}, + {bounds: [[589, 71, 65, 63]], states: [{charCode: 192, char: '8'}]}, + {bounds: [[661, 71, 65, 63]], states: [{charCode: 192, char: '9'}]}, + {bounds: [[733, 71, 65, 63]], states: [{charCode: 192, char: '0'}]}, + {bounds: [[806, 71, 65, 63]], states: [{charCode: 192, char: '-'}]}, + {bounds: [[880, 71, 65, 63]], states: [{charCode: 192, char: '='}]}, + {bounds: [[953, 71, 65, 63]], states: [{charCode: 192, char: '+'}]}, + {bounds: [[1024, 71, 139, 63]], event: 'delete'}, + + // enter key has 2 bounds and one state + {bounds: [[11, 143, 98, 71], [11, 213, 121, 62]], event: 'enter'}, + + {bounds: [[118, 142, 64, 63]], states: [{charCode: 192, char: 'q'}, {charCode: 192, char: 'Q'}]}, + {bounds: [[190, 142, 64, 63]], states: [{charCode: 192, char: 'w'}, {charCode: 192, char: 'W'}]}, + {bounds: [[262, 142, 64, 63]], states: [{charCode: 192, char: 'e'}, {charCode: 192, char: 'E'}]}, + {bounds: [[334, 142, 64, 63]], states: [{charCode: 192, char: 'r'}, {charCode: 192, char: 'R'}]}, + {bounds: [[407, 142, 64, 63]], states: [{charCode: 192, char: 't'}, {charCode: 192, char: 'T'}]}, + {bounds: [[479, 142, 64, 63]], states: [{charCode: 192, char: 'y'}, {charCode: 192, char: 'Y'}]}, + {bounds: [[551, 142, 65, 63]], states: [{charCode: 192, char: 'u'}, {charCode: 192, char: 'U'}]}, + {bounds: [[623, 142, 65, 63]], states: [{charCode: 192, char: 'i'}, {charCode: 192, char: 'I'}]}, + {bounds: [[695, 142, 65, 63]], states: [{charCode: 192, char: 'o'}, {charCode: 192, char: 'O'}]}, + {bounds: [[768, 142, 64, 63]], states: [{charCode: 192, char: 'p'}, {charCode: 192, char: 'P'}]}, + {bounds: [[840, 142, 64, 63]], states: [{charCode: 192, char: '['}]}, + {bounds: [[912, 142, 65, 63]], states: [{charCode: 192, char: ']'}]}, + {bounds: [[984, 142, 65, 63]], states: [{charCode: 192, char: '\\'}]}, + {bounds: [[1055, 142, 65, 63]], states: [{charCode: 192, char: '|'}]}, + + {bounds: [[1126, 143, 35, 72], [1008, 214, 153, 62]], event: 'enter'}, + + {bounds: [[140, 213, 65, 63]], states: [{charCode: 192, char: 'a'}, {charCode: 192, char: 'A'}]}, + {bounds: [[211, 213, 64, 63]], states: [{charCode: 192, char: 's'}, {charCode: 192, char: 'S'}]}, + {bounds: [[283, 213, 65, 63]], states: [{charCode: 192, char: 'd'}, {charCode: 192, char: 'D'}]}, + {bounds: [[355, 213, 65, 63]], states: [{charCode: 192, char: 'f'}, {charCode: 192, char: 'F'}]}, + {bounds: [[428, 213, 64, 63]], states: [{charCode: 192, char: 'g'}, {charCode: 192, char: 'G'}]}, + {bounds: [[500, 213, 64, 63]], states: [{charCode: 192, char: 'h'}, {charCode: 192, char: 'H'}]}, + {bounds: [[572, 213, 65, 63]], states: [{charCode: 192, char: 'j'}, {charCode: 192, char: 'J'}]}, + {bounds: [[644, 213, 65, 63]], states: [{charCode: 192, char: 'k'}, {charCode: 192, char: 'K'}]}, + {bounds: [[716, 213, 65, 63]], states: [{charCode: 192, char: 'l'}, {charCode: 192, char: 'L'}]}, + {bounds: [[789, 213, 64, 63]], states: [{charCode: 192, char: ';'}]}, + {bounds: [[861, 213, 64, 63]], states: [{charCode: 192, char: '\''}]}, + {bounds: [[934, 213, 65, 63]], states: [{charCode: 192, char: ':'}]}, + + {bounds: [[12, 283, 157, 63]], event: 'shift'}, + + {bounds: [[176, 283, 65, 63]], states: [{charCode: 192, char: 'z'}, {charCode: 192, char: 'Z'}]}, + {bounds: [[249, 283, 64, 63]], states: [{charCode: 192, char: 'x'}, {charCode: 192, char: 'X'}]}, + {bounds: [[321, 283, 64, 63]], states: [{charCode: 192, char: 'c'}, {charCode: 192, char: 'C'}]}, + {bounds: [[393, 283, 64, 63]], states: [{charCode: 192, char: 'v'}, {charCode: 192, char: 'V'}]}, + {bounds: [[465, 283, 65, 63]], states: [{charCode: 192, char: 'b'}, {charCode: 192, char: 'B'}]}, + {bounds: [[537, 283, 65, 63]], states: [{charCode: 192, char: 'n'}, {charCode: 192, char: 'N'}]}, + {bounds: [[610, 283, 64, 63]], states: [{charCode: 192, char: 'm'}, {charCode: 192, char: 'M'}]}, + {bounds: [[682, 283, 64, 63]], states: [{charCode: 192, char: ','}]}, + {bounds: [[754, 283, 65, 63]], states: [{charCode: 192, char: '.'}]}, + {bounds: [[826, 283, 65, 63]], states: [{charCode: 192, char: '/'}]}, + {bounds: [[899, 283, 64, 63]], states: [{charCode: 192, char: '?'}], key_state: KBD_UPPERCASE_DEFAULT}, + + {bounds: [[972, 283, 190, 63]], event: 'shift'}, + + {bounds: [[249, 355, 573, 67]], states: [{charCode: 192, char: ' '}]}, + + {bounds: [[899, 355, 263, 67]], event: 'submit'} + + + + ]; + + this.keys_in_waitingline = []; + this.keys_being_downloaded = []; + + for (var i = 0; i < keyProperties.length; i++) { + //this.keys_in_waitingline.push(keyProperties[i]); + //this.keys.push(new KeyboardKey(this, keyProperties[i])); + } + var tthis = this; + this.keyboardtextureloaded = function() { + if (Overlays.isLoaded(tthis.background)) { + Script.clearInterval(tthis.keyboardtextureloaded_timer); + for (var i = 0; i < keyProperties.length; i++) { + tthis.keys.push(new KeyboardKey(tthis, keyProperties[i])); + } + } + }; + this.keyboardtextureloaded_timer = Script.setInterval(this.keyboardtextureloaded, 250); +} + +var keyboard = new Keyboard(); +keyboard.onKeyPress = function() { + print("Key press event test"); +}; + +function scriptEnding() { + keyboard.remove(); +} +function mousePressEvent(event) { + //var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y}); + //if (clickedOverlay != 0) { + // Overlays.deleteOverlay(clickedOverlay); + //} +} + +function onUpdate() { + MyAvatar.getHeadFinalYaw(); + MyAvatar.getHeadFinalPitch(); +} + +Script.update.connect(onUpdate); +Script.scriptEnding.connect(scriptEnding); \ No newline at end of file From d52f410c03d309542f2ffc33655e38676a360de0 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Tue, 18 Nov 2014 03:11:47 +0100 Subject: [PATCH 031/502] virtualKeyboard: added cursor which responds to HMD --- examples/virtualKeyboard.js | 67 ++++++++++++++++++++++++++++++------- 1 file changed, 54 insertions(+), 13 deletions(-) diff --git a/examples/virtualKeyboard.js b/examples/virtualKeyboard.js index 109196008d..4e871a79ab 100644 --- a/examples/virtualKeyboard.js +++ b/examples/virtualKeyboard.js @@ -1,3 +1,16 @@ +// +// virtualKeyboard.js +// examples +// +// Created by Thijs Wenker on 11/18/14. +// Copyright 2014 High Fidelity, Inc. +// +// Control a virtual keyboard using your favorite HMD. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + const KBD_UPPERCASE_DEFAULT = 0; const KBD_LOWERCASE_DEFAULT = 1; const KBD_UPPERCASE_HOVER = 2; @@ -5,9 +18,15 @@ const KBD_LOWERCASE_HOVER = 3; const KBD_BACKGROUND = 4; const KEYBOARD_URL = "http://test.thoys.nl/hifi/images/virtualKeyboard/keyboard.svg"; +const CURSOR_URL = "http://test.thoys.nl/hifi/images/virtualKeyboard/cursor.svg"; -const KEYBOARD_HEIGHT = 434.1; const KEYBOARD_WIDTH = 1174.7; +const KEYBOARD_HEIGHT = 434.1; + +const CURSOR_WIDTH = 33.9; +const CURSOR_HEIGHT = 33.9; + +const VIEW_ANGLE = 60.0; const BOUND_X = 0; const BOUND_Y = 1; @@ -216,20 +235,42 @@ keyboard.onKeyPress = function() { print("Key press event test"); }; +function Cursor() { + var tthis = this; + var dimensions = Controller.getViewportDimensions(); + this.overlay = Overlays.addOverlay("image", { + x: dimensions.x / 2, + y: dimensions.y / 2, + width: CURSOR_WIDTH, + height: CURSOR_HEIGHT, + imageURL: CURSOR_URL, + alpha: 1 + }); + this.remove = function() { + Overlays.deleteOverlay(this.overlay); + }; + this.update = function() { + var screen_angle = 60; + var dimensions = Controller.getViewportDimensions(); + var editobject = {};//{x: dimensions.x / 2, y: dimensions.y / 2}; + if (MyAvatar.getHeadFinalYaw() <= (VIEW_ANGLE / 2) && MyAvatar.getHeadFinalYaw() >= -1 * (VIEW_ANGLE / 2)) { + angle = ((-1 * MyAvatar.getHeadFinalYaw()) + (VIEW_ANGLE / 2)) / VIEW_ANGLE; + editobject.x = angle * dimensions.x; + } + if (MyAvatar.getHeadFinalPitch() <= (VIEW_ANGLE / 2) && MyAvatar.getHeadFinalPitch() >= -1 * (VIEW_ANGLE / 2)) { + angle = ((-1 * MyAvatar.getHeadFinalPitch()) + (VIEW_ANGLE / 2)) / VIEW_ANGLE; + // print(angle * dimensions.y); + editobject.y = angle * dimensions.y; + } + Overlays.editOverlay(tthis.overlay, editobject); + }; + Script.update.connect(this.update); +} +var cursor = new Cursor(); function scriptEnding() { keyboard.remove(); -} -function mousePressEvent(event) { - //var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y}); - //if (clickedOverlay != 0) { - // Overlays.deleteOverlay(clickedOverlay); - //} + cursor.remove(); + Overlays.deleteOverlay(cursor); } -function onUpdate() { - MyAvatar.getHeadFinalYaw(); - MyAvatar.getHeadFinalPitch(); -} - -Script.update.connect(onUpdate); Script.scriptEnding.connect(scriptEnding); \ No newline at end of file From f1543a9d36a149d9b9cf9d9b90fcf150701add8f Mon Sep 17 00:00:00 2001 From: Adrianl3d Date: Wed, 19 Nov 2014 04:36:57 +1000 Subject: [PATCH 032/502] Added notifications.js Creates overlay notifications from events and key strokes. improved fading. --- examples/notifications.js | 378 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 378 insertions(+) create mode 100644 examples/notifications.js diff --git a/examples/notifications.js b/examples/notifications.js new file mode 100644 index 0000000000..6eb5e25566 --- /dev/null +++ b/examples/notifications.js @@ -0,0 +1,378 @@ +// +// notifications.js +// Created by Adrian +// +// Adrian McCarlie 8-10-14 +// This script demonstrates on-screen overlay type notifications. +// 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 + +// This script demonstrates notifications created via a number of ways, such as: +// Simple key press alerts, which only depend on a key being pressed, +// dummy examples of this are "q", "w", "e", "r", and "SPACEBAR". +// actual working examples are "a" for left turn, "d" for right turn and Ctrl/s for snapshot. + +// System generated alerts such as users joining and leaving and chat messages which mention this user. +// System generated alerts which originate with a user interface event such as Window Resize, and Mic Mute/Unmute. +// Mic Mute/Unmute may appear to be a key press alert, but it actually gets the call from the system as mic is muted and unmuted, +// so the mic mute/unmute will also trigger the notification by clicking the Mic Mute button at the top of the screen. + + +// To add a new System notification type: +// +// 1. Set the Event Connector at the bottom of the script. +// example: +// GlobalServices.incomingMessage.connect(onIncomingMessage); +// +// 2. Create a new function to produce a text string, do not include new line returns. +// example: +// function onIncomingMessage(user, message) { +// //do stuff here; +// var text = "This is a notification"; +// wordWrap(text); +// } +// +// This new function must call wordWrap(text) if the length of message is longer than 42 chars or unknown. +// wordWrap() will format the text to fit the notifications overlay and send it to createNotification(text). +// If the message is 42 chars or less you should bypass wordWrap() and call createNotification() directly. + + +// To add a keypress driven notification: +// +// 1. Add a key to the keyPressEvent(key). +// 2. Declare a text string. +// 3. Call createNotifications(text) parsing the text. +// example: +// if (key.text == "a") { +// var noteString = "Turning to the Left"; +// createNotification(noteString); +// } + + +var width = 340.0; //width of notification overlay +var height = 40.0; // height of a single line notification overlay +var windowDimensions = Controller.getViewportDimensions(); // get the size of the interface window +var overlayLocationX = (windowDimensions.x - (width + 60.0));// positions window 60px from the right of the interface window +var buttonLocationX = overlayLocationX + (width - 28.0); +var locationY = 20.0; // position down from top of interface window +var topMargin = 13.0; +var leftMargin = 10.0; +var textColor = { red: 228, green: 228, blue: 228}; // text color +var backColor = { red: 38, green: 38, blue: 38}; // background color +var backgroundAlpha = 0; +var fontSize = 12.0; +var persistTime = 5.0; // time in seconds before notification fades +var clickedText = false; +var frame = 0; +var ourWidth = Window.innerWidth; +var ourHeight = Window.innerHeight; +var text = "placeholder"; +var last_users = GlobalServices.onlineUsers; +var users =[]; +var ctrlIsPressed = false; +var ready = true; + +// When our script shuts down, we should clean up all of our overlays +function scriptEnding() { + for (i = 0; i < notifications.length; i++){ + Overlays.deleteOverlay(notifications[i]); + Overlays.deleteOverlay(buttons[i]); + } +} +Script.scriptEnding.connect(scriptEnding); + +var notifications = []; +var buttons = []; +var times = []; +var heights = []; +var myAlpha = []; +var arrays = []; + +// This function creates and sizes the overlays +function createNotification(text){ + var count = (text.match(/\n/g) || []).length; + var breakPoint = 43.0; // length when new line is added + var extraLine = 0; + var breaks = 0; + var height = 40.0; + var stack = 0; + if (text.length >= breakPoint){ + breaks = count; + } + var extraLine = breaks * 16.0; + for (i = 0; i < heights.length; i++){ + stack = stack + heights[i]; + } + var level = (stack + 20.0 ); + height = height + extraLine; + var overlayProperties = { + x: overlayLocationX, + y: level, + width: width, + height: height, + color: textColor, + backgroundColor: backColor, + alpha: backgroundAlpha, + topargin: topMargin, + leftMargin: leftMargin, + font: {size: fontSize}, + text: text, + }; + var bLevel = level + 12.0; + var buttonProperties = { + x: buttonLocationX, + y: bLevel, + width: 15.0,//37 + height: 15.0,//35 + subImage: { x: 0, y: 0, width: 10, height: 10 }, + imageURL: "http://hifi-public.s3.amazonaws.com/images/close-small-light.svg", + color: { red: 255, green: 255, blue: 255}, + visible: true, + alpha: backgroundAlpha, + }; + + Notify(overlayProperties, buttonProperties, height); + +} + +// Pushes data to each array and sets up data for 2nd dimension array +// to handle auxiliary data not carried by the overlay class +// specifically notification "heights", "times" of creation, and . +function Notify (notice, button, height ){ + + notifications.push((Overlays.addOverlay("text",notice))); + buttons.push((Overlays.addOverlay("image",button))); + times.push(new Date().getTime() / 1000); + height = height + 1.0; + heights.push(height); + myAlpha.push(0); + var last = notifications.length - 1; + createArrays(notifications[last], buttons[last], times[last], heights[last], myAlpha[last]); + fadeIn(notifications[last], buttons[last]) +} + +function fadeIn(noticeIn, buttonIn){ + var myLength = arrays.length; + var q = 0; + var pauseTimer = null; + pauseTimer = Script.setInterval(function() { + q++; + qFade = q / 10.0; + Overlays.editOverlay(noticeIn, {alpha: qFade}); + Overlays.editOverlay(buttonIn, {alpha: qFade}); + if (q >= 9.0) { + Script.clearInterval(pauseTimer); + } + }, 10); +} + + +// push data from above to the 2 dimensional array +function createArrays(notice, button, createTime, height, myAlpha){ + arrays.push([notice, button, createTime, height, myAlpha]); +} +// handles mouse clicks on buttons +function mousePressEvent(event) { + var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y}); //identify which overlay was clicked + for (i = 0; i < buttons.length; i++){ //if user clicked a button + if(clickedOverlay == buttons[i]){ + Overlays.deleteOverlay(notifications[i]); + Overlays.deleteOverlay(buttons[i]); + notifications.splice(i, 1); + buttons.splice(i, 1); + times.splice(i, 1); + heights.splice(i, 1); + myAlpha.splice(i, 1); + arrays.splice(i, 1); + } + } +} + +// Control key remains active only while key is held down +function keyReleaseEvent(key){ + if (key.key == 16777249){ + ctrlIsPressed = false; + } +} + +// Triggers notification on specific key driven events +function keyPressEvent(key) { + if (key.key == 16777249){ + ctrlIsPressed = true; + } + if (key.text == "a") { + var noteString = "Turning to the Left"; + createNotification(noteString); + } + if (key.text == "d") { + var noteString = "Turning to the Right"; + createNotification(noteString); + } + if (key.text == "s") { + if (ctrlIsPressed == true){ + var noteString = "You have taken a snapshot"; + createNotification(noteString); + } + } + if (key.text == "q") { + var noteString = "Enable Scripted Motor control is now on."; + wordWrap(noteString); + } + if (key.text == "w") { + var noteString = "This notification spans 2 lines. The overlay will resize to fit new lines."; + var noteString = "editVoxels.js stopped, editModels.js stopped, selectAudioDevice.js stopped."; + wordWrap(noteString); + } + if (key.text == "e") { + var noteString = "This is an example of a multiple line notification. This notification will span 3 lines." + wordWrap(noteString); + } + if (key.text == "r") { + var noteString = "This is a very long line of text that we are going to use in this example to divide it into rows of maximum 43 chars and see how many lines we use."; + wordWrap(noteString); + } + if (key.text == "SPACE") { + var noteString = "You have pressed the Spacebar, This is an example of a multiple line notification. Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam."; + wordWrap(noteString); + } +} + +// formats string to add newline every 43 chars +function wordWrap(str){ + var result = stringDivider(str, 43.0, "\n"); + createNotification(result); +} +// wraps whole word to newline +function stringDivider(str, slotWidth, spaceReplacer) { + if (str.length>slotWidth) { + var p=slotWidth; + for (; p > 0 && str[p] != ' '; p--) { + } + if (p > 0) { + var left = str.substring(0, p); + var right = str.substring(p + 1); + return left + spaceReplacer + stringDivider(right, slotWidth, spaceReplacer); + } + } + return str; +} + +//This fires a notification on window resize +function checkSize(){ + if((Window.innerWidth!=ourWidth)||(Window.innerHeight!=ourHeight)){ + var windowResize = "Window has been resized"; + ourWidth = Window.innerWidth; + ourHeight = Window.innerHeight; + windowDimensions = Controller.getViewportDimensions(); + overlayLocationX = (windowDimensions.x - (width + 60.0)); + buttonLocationX = overlayLocationX + (width - 35.0); + createNotification(windowResize) + } +} + +// Triggers notification if a user logs on or off +function onOnlineUsersChanged(users) { + var joiners = []; + var leavers = []; + for (user in users) { + if (last_users.indexOf(users[user]) == -1.0) { + joiners.push(users[user]); + createNotification(users[user] + " Has joined"); + } + } + for (user in last_users) { + if (users.indexOf(last_users[user]) == -1.0) { + leavers.push(last_users[user]); + createNotification(last_users[user] + " Has left"); + } + } + last_users = users; +} + +// Triggers notification if @MyUserName is mentioned in chat and returns the message to the notification. +function onIncomingMessage(user, message) { + var myMessage = message; + var alertMe = "@" + GlobalServices.myUsername; + var thisAlert = user + ": " + myMessage; + if (myMessage.indexOf(alertMe) > -1.0) { + wordWrap(thisAlert); + } +} +// Triggers mic mute notification +function onMuteStateChanged() { + var muteState = AudioDevice.getMuted() ? "Muted" : "Unmuted"; + var muteString = "Microphone is set to " + muteState; + createNotification(muteString); +} + +function update(){ + frame++; + if ((frame % 60.0) == 0) { // only update once a second + checkSize(); // checks for size change to trigger windowResize notification + locationY = 20.0; + for (var i = 0; i < arrays.length; i++){ //repositions overlays as others fade + var nextOverlay = Overlays.getOverlayAtPoint({x: overlayLocationX, y: locationY }); + Overlays.editOverlay(notifications[i], { x:overlayLocationX, y:locationY}); + Overlays.editOverlay(buttons[i], { x:buttonLocationX, y:locationY + 12.0}); + locationY=locationY + arrays[i][3]; + } + } + + // This checks the age of the notification and prepares to fade it after 9.0 seconds (var persistTime - 1) + for (var i = 0; i < arrays.length; i++){ + if (ready){ + var j = arrays[i][2]; + var k = j + persistTime; + if (k < (new Date().getTime() / 1000)){ + ready = false; + noticeOut = arrays[i][0]; + buttonOut = arrays[i][1]; + var arraysOut = i; + fadeOut(noticeOut, buttonOut, arraysOut); + } + } + } +} + +// this fades the notification ready for dismissal, and removes it from the arrays +function fadeOut(noticeOut, buttonOut, arraysOut){ + var myLength = arrays.length; + var r = 9.0; + var pauseTimer = null; + pauseTimer = Script.setInterval(function() { + r--; + rFade = r / 10.0; + Overlays.editOverlay(noticeOut, {alpha: rFade}); + Overlays.editOverlay(buttonOut, {alpha: rFade}); + if (r < 0) { + dismiss(noticeOut, buttonOut, arraysOut); + arrays.splice(arraysOut, 1); + ready = true; + Script.clearInterval(pauseTimer); + } + }, 20); +} + +// This handles the final dismissal of a notification after fading +function dismiss(firstNoteOut, firstButOut, firstOut){ +var working = firstOut + Overlays.deleteOverlay(firstNoteOut); + Overlays.deleteOverlay(firstButOut); + notifications.splice(firstOut, 1); + buttons.splice(firstOut, 1); + times.splice(firstOut, 1); + heights.splice(firstOut, 1); + myAlpha.splice(firstOut,1); + +} + +onMuteStateChanged(); +AudioDevice.muteToggled.connect(onMuteStateChanged); +Controller.keyPressEvent.connect(keyPressEvent); +Controller.mousePressEvent.connect(mousePressEvent); +GlobalServices.onlineUsersChanged.connect(onOnlineUsersChanged); +GlobalServices.incomingMessage.connect(onIncomingMessage); +Controller.keyReleaseEvent.connect(keyReleaseEvent); +Script.update.connect(update); From 7dc35bb3490cbf3e2465d188bc9cbbd41fae796b Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Wed, 19 Nov 2014 03:12:22 +0100 Subject: [PATCH 033/502] virtual-keyboard: - positioned in bottom - keyboard hover-able --- examples/virtualKeyboard.js | 185 ++++++++++++++++++++++++++++-------- 1 file changed, 147 insertions(+), 38 deletions(-) diff --git a/examples/virtualKeyboard.js b/examples/virtualKeyboard.js index 4e871a79ab..41ddfa75ae 100644 --- a/examples/virtualKeyboard.js +++ b/examples/virtualKeyboard.js @@ -27,6 +27,7 @@ const CURSOR_WIDTH = 33.9; const CURSOR_HEIGHT = 33.9; const VIEW_ANGLE = 60.0; +const VIEW_ANGLE_BY_TWO = VIEW_ANGLE / 2; const BOUND_X = 0; const BOUND_Y = 1; @@ -36,13 +37,31 @@ const BOUND_H = 3; const KEY_STATE_LOWER = 0; const KEY_STATE_UPPER = 1; +var cursor = null; +var keyboard = new Keyboard(); + +keyboard.onKeyPress = function() { + print("Key press event test"); +}; + +keyboard.onFullyLoaded = function() { + print("Virtual-keyboard fully loaded."); + // the cursor is being loaded after the keyboard, else it will be on the background of the keyboard + cursor = new Cursor(); + cursor.onUpdate = function(position) { + keyboard.setFocusPosition(position.x, position.y); + }; +}; + function KeyboardKey(keyboard, key_properties) { + var tthis = this; + this._focus = false; this.event = key_properties.event != undefined ? key_properties.event : 'keypress'; this.bounds = key_properties.bounds; this.states = key_properties.states; this.keyboard = keyboard; - this.key_state = key_properties.key_state != undefined ? key_properties.key_state : KBD_LOWERCASE_HOVER; + this.key_state = key_properties.key_state != undefined ? key_properties.key_state : KBD_LOWERCASE_DEFAULT; // one overlay per bound vector [this.bounds] this.overlays = []; this.updatePosition = function() { @@ -59,6 +78,33 @@ function KeyboardKey(keyboard, key_properties) { } return false; }; + this.updateState = function() { + tthis.setState(eval('KBD_' + (tthis.keyboard.shift ? 'UPPERCASE' : 'LOWERCASE') + '_' + (tthis._focus ? 'HOVER' : 'DEFAULT'))); + }; + this.blur = function() { + tthis._focus = false; + tthis.updateState(); + }; + this.focus = function() { + tthis._focus = true; + tthis.updateState(); + }; + this.setState = function(state) { + tthis.key_state = state; + for (var i = 0; i < tthis.bounds.length; i++) { + Overlays.editOverlay(tthis.overlays[i], { + subImage: {width: tthis.bounds[i][BOUND_W], height: tthis.bounds[i][BOUND_H], x: tthis.bounds[i][BOUND_X], y: (KEYBOARD_HEIGHT * tthis.key_state) + tthis.bounds[i][BOUND_Y]} + }); + } + }; + this.updatePosition = function() { + for (var i = 0; i < tthis.bounds.length; i++) { + Overlays.editOverlay(tthis.overlays[i], { + x: tthis.keyboard.x + tthis.bounds[i][BOUND_X], + y: tthis.keyboard.y + tthis.bounds[i][BOUND_Y], + }); + } + }; this.remove = function() { for (var i = 0; i < this.overlays.length; i++) { Overlays.deleteOverlay(this.overlays[i]); @@ -67,7 +113,7 @@ function KeyboardKey(keyboard, key_properties) { this.isLoaded = function() { for (var i = 0; i < this.overlays.length; i++) { if (!Overlays.isLoaded(this.overlays[i])) { - return false; + return false; } } return true; @@ -75,8 +121,8 @@ function KeyboardKey(keyboard, key_properties) { for (var i = 0; i < this.bounds.length; i++) { var newOverlay = Overlays.cloneOverlay(this.keyboard.background); Overlays.editOverlay(newOverlay, { - x: 50 + this.bounds[i][BOUND_X], - y: 50 + this.bounds[i][BOUND_Y], + x: this.keyboard.x + this.bounds[i][BOUND_X], + y: this.keyboard.y + this.bounds[i][BOUND_Y], width: this.bounds[i][BOUND_W], height: this.bounds[i][BOUND_H], subImage: {width: this.bounds[i][BOUND_W], height: this.bounds[i][BOUND_H], x: this.bounds[i][BOUND_X], y: (KEYBOARD_HEIGHT * this.key_state) + this.bounds[i][BOUND_Y]}, @@ -87,21 +133,66 @@ function KeyboardKey(keyboard, key_properties) { } function Keyboard() { + var tthis = this; + var dimensions = Controller.getViewportDimensions(); + this.focussed_key = -1; + this.shift = false; + this.x = (dimensions.x / 2) - (KEYBOARD_WIDTH / 2); + this.y = dimensions.y - KEYBOARD_HEIGHT; this.background = Overlays.addOverlay("image", { - x: 50, - y: 50, + x: this.x, + y: this.y, width: KEYBOARD_WIDTH, height: KEYBOARD_HEIGHT, subImage: {width: KEYBOARD_WIDTH, height: KEYBOARD_HEIGHT, y: KEYBOARD_HEIGHT * KBD_BACKGROUND}, imageURL: KEYBOARD_URL, alpha: 1 }); + + this.setFocusPosition = function(x, y) { + var localx = x - tthis.x; + var localy = y - tthis.y; + var new_focus_key = -1; + if (localx >= 0 && localy >= 0 && localx <= KEYBOARD_WIDTH && localy <= KEYBOARD_HEIGHT) { + for (var i = 0; i < tthis.keys.length; i++) { + if (tthis.keys[i].containsCoord(localx, localy)) { + //print(tthis.keys[i].states[0].char); + new_focus_key = i; + break; + } + } + } + if (new_focus_key != tthis.focussed_key) { + print(new_focus_key); + if (tthis.focussed_key != -1) { + tthis.keys[tthis.focussed_key].blur(); + } + tthis.focussed_key = new_focus_key; + if (tthis.focussed_key != -1) { + tthis.keys[tthis.focussed_key].focus(); + } + } + return tthis; + }; + + this.pressFocussedKey = function() { + if (tthis.focussed_key != -1) { + this.onKeyPress(tthis.keys[tthis.focussed_key]); + } + return tthis; + }; + this.updatePosition = function() { }; + this.getFocussedKey = function() { - + if (tthis.focussed_key == -1) { + return null; + } + return tthis.keys[tthis.focussed_key]; }; + this.remove = function() { Overlays.deleteOverlay(this.background); for (var i = 0; i < this.keys.length; i++) { @@ -113,6 +204,7 @@ function Keyboard() { this.onKeyDown = null; this.onKeyUp = null; this.onSubmit = null; + this.onFullyLoaded = null; this.keys = []; // @@ -145,7 +237,7 @@ function Keyboard() { {bounds: [[300, 71, 65, 63]], states: [{charCode: 192, char: '4'}]}, {bounds: [[372, 71, 65, 63]], states: [{charCode: 192, char: '5'}]}, {bounds: [[445, 71, 65, 63]], states: [{charCode: 192, char: '6'}]}, - {bounds: [[517, 71, 65, 63]], states: [{charCode: 192, char: '7'}], key_state: KBD_UPPERCASE_DEFAULT}, + {bounds: [[517, 71, 65, 63]], states: [{charCode: 192, char: '7'}]}, {bounds: [[589, 71, 65, 63]], states: [{charCode: 192, char: '8'}]}, {bounds: [[661, 71, 65, 63]], states: [{charCode: 192, char: '9'}]}, {bounds: [[733, 71, 65, 63]], states: [{charCode: 192, char: '0'}]}, @@ -199,48 +291,37 @@ function Keyboard() { {bounds: [[682, 283, 64, 63]], states: [{charCode: 192, char: ','}]}, {bounds: [[754, 283, 65, 63]], states: [{charCode: 192, char: '.'}]}, {bounds: [[826, 283, 65, 63]], states: [{charCode: 192, char: '/'}]}, - {bounds: [[899, 283, 64, 63]], states: [{charCode: 192, char: '?'}], key_state: KBD_UPPERCASE_DEFAULT}, + {bounds: [[899, 283, 64, 63]], states: [{charCode: 192, char: '?'}]}, {bounds: [[972, 283, 190, 63]], event: 'shift'}, {bounds: [[249, 355, 573, 67]], states: [{charCode: 192, char: ' '}]}, {bounds: [[899, 355, 263, 67]], event: 'submit'} - - - ]; - this.keys_in_waitingline = []; - this.keys_being_downloaded = []; - - for (var i = 0; i < keyProperties.length; i++) { - //this.keys_in_waitingline.push(keyProperties[i]); - //this.keys.push(new KeyboardKey(this, keyProperties[i])); - } - var tthis = this; this.keyboardtextureloaded = function() { if (Overlays.isLoaded(tthis.background)) { Script.clearInterval(tthis.keyboardtextureloaded_timer); for (var i = 0; i < keyProperties.length; i++) { tthis.keys.push(new KeyboardKey(tthis, keyProperties[i])); } + if (keyboard.onFullyLoaded != null) { + tthis.onFullyLoaded(); + } } }; this.keyboardtextureloaded_timer = Script.setInterval(this.keyboardtextureloaded, 250); } -var keyboard = new Keyboard(); -keyboard.onKeyPress = function() { - print("Key press event test"); -}; - function Cursor() { var tthis = this; var dimensions = Controller.getViewportDimensions(); + this.x = dimensions.x / 2; + this.y = dimensions.y / 2; this.overlay = Overlays.addOverlay("image", { - x: dimensions.x / 2, - y: dimensions.y / 2, + x: this.x, + y: this.y, width: CURSOR_WIDTH, height: CURSOR_HEIGHT, imageURL: CURSOR_URL, @@ -249,28 +330,56 @@ function Cursor() { this.remove = function() { Overlays.deleteOverlay(this.overlay); }; + this.getPosition = function() { + return {x: tthis.getX(), y: tthis.getY()}; + }; + this.getX = function() { + return tthis.x; + }; + this.getY = function() { + return tthis.y; + }; + this.onUpdate = null; this.update = function() { - var screen_angle = 60; var dimensions = Controller.getViewportDimensions(); - var editobject = {};//{x: dimensions.x / 2, y: dimensions.y / 2}; - if (MyAvatar.getHeadFinalYaw() <= (VIEW_ANGLE / 2) && MyAvatar.getHeadFinalYaw() >= -1 * (VIEW_ANGLE / 2)) { - angle = ((-1 * MyAvatar.getHeadFinalYaw()) + (VIEW_ANGLE / 2)) / VIEW_ANGLE; - editobject.x = angle * dimensions.x; + var editobject = {}; + if (MyAvatar.getHeadFinalYaw() <= VIEW_ANGLE_BY_TWO && MyAvatar.getHeadFinalYaw() >= -1 * VIEW_ANGLE_BY_TWO) { + angle = ((-1 * MyAvatar.getHeadFinalYaw()) + VIEW_ANGLE_BY_TWO) / VIEW_ANGLE; + tthis.x = angle * dimensions.x; + editobject.x = tthis.x - (CURSOR_WIDTH / 2); } - if (MyAvatar.getHeadFinalPitch() <= (VIEW_ANGLE / 2) && MyAvatar.getHeadFinalPitch() >= -1 * (VIEW_ANGLE / 2)) { - angle = ((-1 * MyAvatar.getHeadFinalPitch()) + (VIEW_ANGLE / 2)) / VIEW_ANGLE; - // print(angle * dimensions.y); - editobject.y = angle * dimensions.y; + if (MyAvatar.getHeadFinalPitch() <= VIEW_ANGLE_BY_TWO && MyAvatar.getHeadFinalPitch() >= -1 * VIEW_ANGLE_BY_TWO) { + angle = ((-1 * MyAvatar.getHeadFinalPitch()) + VIEW_ANGLE_BY_TWO) / VIEW_ANGLE; + tthis.y = angle * dimensions.y; + editobject.y = tthis.y - (CURSOR_HEIGHT / 2); + } + if (Object.keys(editobject).length > 0) { + Overlays.editOverlay(tthis.overlay, editobject); + if (tthis.onUpdate != null) { + tthis.onUpdate(tthis.getPosition()); + } } - Overlays.editOverlay(tthis.overlay, editobject); }; Script.update.connect(this.update); } -var cursor = new Cursor(); + +function keyPressEvent(key) { + if (key.text === "SPACE") { + print("pressed space"); + + for (var i = 0; i < keyboard.keys.length; i++) { + print(i + " = " + keyboard.keys[i].key_state); + } + } +} + function scriptEnding() { keyboard.remove(); cursor.remove(); Overlays.deleteOverlay(cursor); + Controller.releaseKeyEvents({text: "SPACE"}); } +Controller.captureKeyEvents({text: "SPACE"}); +Controller.keyPressEvent.connect(keyPressEvent); Script.scriptEnding.connect(scriptEnding); \ No newline at end of file From 4eb4330e84560cf40e18b7b0f890904e03df71b7 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Wed, 19 Nov 2014 23:08:50 +0100 Subject: [PATCH 034/502] virtualkeyboard now scales to the viewportdimensions --- examples/virtualKeyboard.js | 79 ++++++++++++++++++++++++++++--------- 1 file changed, 61 insertions(+), 18 deletions(-) diff --git a/examples/virtualKeyboard.js b/examples/virtualKeyboard.js index 41ddfa75ae..e99a70faed 100644 --- a/examples/virtualKeyboard.js +++ b/examples/virtualKeyboard.js @@ -39,6 +39,7 @@ const KEY_STATE_UPPER = 1; var cursor = null; var keyboard = new Keyboard(); +var text = null; keyboard.onKeyPress = function() { print("Key press event test"); @@ -46,6 +47,20 @@ keyboard.onKeyPress = function() { keyboard.onFullyLoaded = function() { print("Virtual-keyboard fully loaded."); + var dimensions = Controller.getViewportDimensions(); + text = Overlays.addOverlay("text", { + x: 0,//(dimensions.x / 2) - (KEYBOARD_WIDTH / 2), + y: dimensions.y - keyboard.height() - 60, + width: dimensions.x, + height: 50, + backgroundColor: { red: 255, green: 255, blue: 255}, + color: { red: 0, green: 0, blue: 0}, + topMargin: 10, + leftMargin: 8, + font: {size: 28}, + text: "", + alpha: 0.8 + }); // the cursor is being loaded after the keyboard, else it will be on the background of the keyboard cursor = new Cursor(); cursor.onUpdate = function(position) { @@ -56,6 +71,7 @@ keyboard.onFullyLoaded = function() { function KeyboardKey(keyboard, key_properties) { var tthis = this; this._focus = false; + this._beingpressed = false; this.event = key_properties.event != undefined ? key_properties.event : 'keypress'; this.bounds = key_properties.bounds; @@ -81,6 +97,22 @@ function KeyboardKey(keyboard, key_properties) { this.updateState = function() { tthis.setState(eval('KBD_' + (tthis.keyboard.shift ? 'UPPERCASE' : 'LOWERCASE') + '_' + (tthis._focus ? 'HOVER' : 'DEFAULT'))); }; + this.updateColor = function() { + var colorIntensity = _beingpressed ? 128 : 255; + for (var i = 0; i < tthis.bounds.length; i++) { + Overlays.editOverlay(tthis.overlays[i], + {color: {red: colorIntensity, green: colorIntensity, blue: colorIntensity}} + ); + } + }; + this.press = function() { + tthis._beingpressed = true; + tthis.updateColor(); + }; + this.release = function() { + tthis._beingpressed = false; + tthis.updateColor(); + }; this.blur = function() { tthis._focus = false; tthis.updateState(); @@ -121,10 +153,10 @@ function KeyboardKey(keyboard, key_properties) { for (var i = 0; i < this.bounds.length; i++) { var newOverlay = Overlays.cloneOverlay(this.keyboard.background); Overlays.editOverlay(newOverlay, { - x: this.keyboard.x + this.bounds[i][BOUND_X], - y: this.keyboard.y + this.bounds[i][BOUND_Y], - width: this.bounds[i][BOUND_W], - height: this.bounds[i][BOUND_H], + x: this.keyboard.x + this.bounds[i][BOUND_X] * keyboard.scale, + y: this.keyboard.y + this.bounds[i][BOUND_Y] * keyboard.scale, + width: this.bounds[i][BOUND_W] * keyboard.scale, + height: this.bounds[i][BOUND_H] * keyboard.scale, subImage: {width: this.bounds[i][BOUND_W], height: this.bounds[i][BOUND_H], x: this.bounds[i][BOUND_X], y: (KEYBOARD_HEIGHT * this.key_state) + this.bounds[i][BOUND_Y]}, alpha: 1 }); @@ -136,22 +168,30 @@ function Keyboard() { var tthis = this; var dimensions = Controller.getViewportDimensions(); this.focussed_key = -1; + this.scale = dimensions.x / KEYBOARD_WIDTH; this.shift = false; - this.x = (dimensions.x / 2) - (KEYBOARD_WIDTH / 2); - this.y = dimensions.y - KEYBOARD_HEIGHT; + this.width = function() { + return KEYBOARD_WIDTH * tthis.scale; + }; + this.height = function() { + return KEYBOARD_HEIGHT * tthis.scale; + }; + this.x = (dimensions.x / 2) - (this.width() / 2); + this.y = dimensions.y - this.height(); this.background = Overlays.addOverlay("image", { x: this.x, y: this.y, - width: KEYBOARD_WIDTH, - height: KEYBOARD_HEIGHT, + width: this.width(), + height: this.height(), subImage: {width: KEYBOARD_WIDTH, height: KEYBOARD_HEIGHT, y: KEYBOARD_HEIGHT * KBD_BACKGROUND}, imageURL: KEYBOARD_URL, alpha: 1 }); this.setFocusPosition = function(x, y) { - var localx = x - tthis.x; - var localy = y - tthis.y; + // set to local unscaled position + var localx = (x - tthis.x) / tthis.scale; + var localy = (y - tthis.y) / tthis.scale; var new_focus_key = -1; if (localx >= 0 && localy >= 0 && localx <= KEYBOARD_WIDTH && localy <= KEYBOARD_HEIGHT) { for (var i = 0; i < tthis.keys.length; i++) { @@ -163,7 +203,7 @@ function Keyboard() { } } if (new_focus_key != tthis.focussed_key) { - print(new_focus_key); + //print(new_focus_key); if (tthis.focussed_key != -1) { tthis.keys[tthis.focussed_key].blur(); } @@ -179,6 +219,7 @@ function Keyboard() { if (tthis.focussed_key != -1) { this.onKeyPress(tthis.keys[tthis.focussed_key]); } + return tthis; }; @@ -366,20 +407,22 @@ function Cursor() { function keyPressEvent(key) { if (key.text === "SPACE") { print("pressed space"); + } +} - for (var i = 0; i < keyboard.keys.length; i++) { - print(i + " = " + keyboard.keys[i].key_state); - } +function keyReleaseEvent(key) { + if (key.text === "SPACE") { + print("released space"); } } function scriptEnding() { keyboard.remove(); cursor.remove(); - Overlays.deleteOverlay(cursor); - Controller.releaseKeyEvents({text: "SPACE"}); + Overlays.deleteOverlay(text); + Controller.releaseKeyEvents({key: 32}); } - -Controller.captureKeyEvents({text: "SPACE"}); +Controller.captureKeyEvents({key: 32}); Controller.keyPressEvent.connect(keyPressEvent); +Controller.keyReleaseEvent.connect(keyReleaseEvent); Script.scriptEnding.connect(scriptEnding); \ No newline at end of file From 764ad724711e6cd5285af19a34b48e0afec2afd2 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 20 Nov 2014 09:54:41 -0800 Subject: [PATCH 035/502] adding the light map support from FBX --- .../resources/shaders/model_normal_map.frag | 2 +- interface/src/ModelUploader.cpp | 8 + interface/src/renderer/GeometryCache.cpp | 28 +- interface/src/renderer/GeometryCache.h | 4 +- interface/src/renderer/Model.cpp | 520 +++++++++++++----- interface/src/renderer/Model.h | 58 +- interface/src/renderer/TextureCache.h | 4 +- libraries/fbx/src/FBXReader.cpp | 37 ++ libraries/fbx/src/FBXReader.h | 2 + 9 files changed, 525 insertions(+), 138 deletions(-) diff --git a/interface/resources/shaders/model_normal_map.frag b/interface/resources/shaders/model_normal_map.frag index f5a1047b2b..af107e9d3c 100644 --- a/interface/resources/shaders/model_normal_map.frag +++ b/interface/resources/shaders/model_normal_map.frag @@ -4,7 +4,7 @@ // model_normal_map.frag // fragment shader // -// Created by Andrzej Kapolka on 10/29/13. +// Created by Andrzej Kapolka on 10/14/13. // Copyright 2013 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. diff --git a/interface/src/ModelUploader.cpp b/interface/src/ModelUploader.cpp index 2599f39e83..d9e8ed0c40 100644 --- a/interface/src/ModelUploader.cpp +++ b/interface/src/ModelUploader.cpp @@ -522,6 +522,14 @@ bool ModelUploader::addTextures(const QString& texdir, const FBXGeometry& geomet } _textureFilenames.insert(part.specularTexture.filename); } + if (!part.emissiveTexture.filename.isEmpty() && part.emissiveTexture.content.isEmpty() && + !_textureFilenames.contains(part.emissiveTexture.filename)) { + if (!addPart(texdir + "/" + part.emissiveTexture.filename, + QString("texture%1").arg(++_texturesCount), true)) { + return false; + } + _textureFilenames.insert(part.emissiveTexture.filename); + } } } diff --git a/interface/src/renderer/GeometryCache.cpp b/interface/src/renderer/GeometryCache.cpp index 9052ec910f..cca0d120c2 100644 --- a/interface/src/renderer/GeometryCache.cpp +++ b/interface/src/renderer/GeometryCache.cpp @@ -575,7 +575,8 @@ bool NetworkGeometry::isLoadedWithTextures() const { foreach (const NetworkMeshPart& part, mesh.parts) { if ((part.diffuseTexture && !part.diffuseTexture->isLoaded()) || (part.normalTexture && !part.normalTexture->isLoaded()) || - (part.specularTexture && !part.specularTexture->isLoaded())) { + (part.specularTexture && !part.specularTexture->isLoaded()) || + (part.emissiveTexture && !part.emissiveTexture->isLoaded())) { return false; } } @@ -668,6 +669,9 @@ void NetworkGeometry::setLoadPriority(const QPointer& owner, float prio if (part.specularTexture) { part.specularTexture->setLoadPriority(owner, priority); } + if (part.emissiveTexture) { + part.emissiveTexture->setLoadPriority(owner, priority); + } } } } @@ -688,6 +692,9 @@ void NetworkGeometry::setLoadPriorities(const QHash, float>& p if (part.specularTexture) { part.specularTexture->setLoadPriorities(priorities); } + if (part.emissiveTexture) { + part.emissiveTexture->setLoadPriorities(priorities); + } } } } @@ -708,6 +715,9 @@ void NetworkGeometry::clearLoadPriority(const QPointer& owner) { if (part.specularTexture) { part.specularTexture->clearLoadPriority(owner); } + if (part.emissiveTexture) { + part.emissiveTexture->clearLoadPriority(owner); + } } } } @@ -733,6 +743,10 @@ void NetworkGeometry::setTextureWithNameToURL(const QString& name, const QUrl& u part.specularTexture = Application::getInstance()->getTextureCache()->getTexture(url, DEFAULT_TEXTURE, false, QByteArray()); part.specularTexture->setLoadPriorities(_loadPriorities); + } else if (part.emissiveTextureName == name) { + part.emissiveTexture = Application::getInstance()->getTextureCache()->getTexture(url, DEFAULT_TEXTURE, + false, QByteArray()); + part.emissiveTexture->setLoadPriorities(_loadPriorities); } } } @@ -764,6 +778,11 @@ QStringList NetworkGeometry::getTextureNames() const { QString textureURL = part.specularTexture->getURL().toString(); result << part.specularTextureName + ":" + textureURL; } + + if (!part.emissiveTextureName.isEmpty()) { + QString textureURL = part.emissiveTexture->getURL().toString(); + result << part.emissiveTextureName + ":" + textureURL; + } } } return result; @@ -911,6 +930,13 @@ void NetworkGeometry::setGeometry(const FBXGeometry& geometry) { networkPart.specularTextureName = part.specularTexture.name; networkPart.specularTexture->setLoadPriorities(_loadPriorities); } + if (!part.emissiveTexture.filename.isEmpty()) { + networkPart.emissiveTexture = Application::getInstance()->getTextureCache()->getTexture( + _textureBase.resolved(QUrl(part.emissiveTexture.filename)), EMISSIVE_TEXTURE, + false, part.emissiveTexture.content); + networkPart.emissiveTextureName = part.emissiveTexture.name; + networkPart.emissiveTexture->setLoadPriorities(_loadPriorities); + } networkMesh.parts.append(networkPart); totalIndices += (part.quadIndices.size() + part.triangleIndices.size()); diff --git a/interface/src/renderer/GeometryCache.h b/interface/src/renderer/GeometryCache.h index e58177533c..6faad93fe4 100644 --- a/interface/src/renderer/GeometryCache.h +++ b/interface/src/renderer/GeometryCache.h @@ -155,7 +155,9 @@ public: QSharedPointer normalTexture; QString specularTextureName; QSharedPointer specularTexture; - + QString emissiveTextureName; + QSharedPointer emissiveTexture; + bool isTranslucent() const; }; diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index fc3845d94f..c3e21aea7c 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -70,6 +70,11 @@ ProgramObject Model::_specularMapProgram; ProgramObject Model::_normalSpecularMapProgram; ProgramObject Model::_translucentProgram; +ProgramObject Model::_emissiveProgram; +ProgramObject Model::_emissiveNormalMapProgram; +ProgramObject Model::_emissiveSpecularMapProgram; +ProgramObject Model::_emissiveNormalSpecularMapProgram; + ProgramObject Model::_shadowProgram; ProgramObject Model::_skinProgram; @@ -78,6 +83,11 @@ ProgramObject Model::_skinSpecularMapProgram; ProgramObject Model::_skinNormalSpecularMapProgram; ProgramObject Model::_skinTranslucentProgram; +ProgramObject Model::_skinEmissiveProgram; +ProgramObject Model::_skinEmissiveNormalMapProgram; +ProgramObject Model::_skinEmissiveSpecularMapProgram; +ProgramObject Model::_skinEmissiveNormalSpecularMapProgram; + ProgramObject Model::_skinShadowProgram; Model::Locations Model::_locations; @@ -86,6 +96,11 @@ Model::Locations Model::_specularMapLocations; Model::Locations Model::_normalSpecularMapLocations; Model::Locations Model::_translucentLocations; +Model::Locations Model::_emissiveLocations; +Model::Locations Model::_emissiveNormalMapLocations; +Model::Locations Model::_emissiveSpecularMapLocations; +Model::Locations Model::_emissiveNormalSpecularMapLocations; + Model::SkinLocations Model::_skinLocations; Model::SkinLocations Model::_skinNormalMapLocations; Model::SkinLocations Model::_skinSpecularMapLocations; @@ -93,6 +108,11 @@ Model::SkinLocations Model::_skinNormalSpecularMapLocations; Model::SkinLocations Model::_skinShadowLocations; Model::SkinLocations Model::_skinTranslucentLocations; +Model::SkinLocations Model::_skinEmissiveLocations; +Model::SkinLocations Model::_skinEmissiveNormalMapLocations; +Model::SkinLocations Model::_skinEmissiveSpecularMapLocations; +Model::SkinLocations Model::_skinEmissiveNormalSpecularMapLocations; + void Model::setScale(const glm::vec3& scale) { setScaleInternal(scale); // if anyone sets scale manually, then we are no longer scaled to fit @@ -268,6 +288,39 @@ void Model::init() { _translucentProgram.link(); initProgram(_translucentProgram, _translucentLocations); + + // Emissive + _emissiveProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/model.vert"); + _emissiveProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + "shaders/model_emissive.frag"); + _emissiveProgram.link(); + + initProgram(_emissiveProgram, _emissiveLocations); + + _emissiveNormalMapProgram.addShaderFromSourceFile(QGLShader::Vertex, + Application::resourcesPath() + "shaders/model_normal_map.vert"); + _emissiveNormalMapProgram.addShaderFromSourceFile(QGLShader::Fragment, + Application::resourcesPath() + "shaders/model_emissive_normal_map.frag"); + _emissiveNormalMapProgram.link(); + + initProgram(_emissiveNormalMapProgram, _emissiveNormalMapLocations); + + _emissiveSpecularMapProgram.addShaderFromSourceFile(QGLShader::Vertex, + Application::resourcesPath() + "shaders/model.vert"); + _emissiveSpecularMapProgram.addShaderFromSourceFile(QGLShader::Fragment, + Application::resourcesPath() + "shaders/model_emissive_specular_map.frag"); + _emissiveSpecularMapProgram.link(); + + initProgram(_emissiveSpecularMapProgram, _emissiveSpecularMapLocations); + + _emissiveNormalSpecularMapProgram.addShaderFromSourceFile(QGLShader::Vertex, + Application::resourcesPath() + "shaders/model_normal_map.vert"); + _emissiveNormalSpecularMapProgram.addShaderFromSourceFile(QGLShader::Fragment, + Application::resourcesPath() + "shaders/model_emissive_normal_specular_map.frag"); + _emissiveNormalSpecularMapProgram.link(); + + initProgram(_emissiveNormalSpecularMapProgram, _emissiveNormalSpecularMapLocations, 2); + // end emissive + _shadowProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/model_shadow.vert"); _shadowProgram.addShaderFromSourceFile(QGLShader::Fragment, @@ -319,6 +372,38 @@ void Model::init() { _skinTranslucentProgram.link(); initSkinProgram(_skinTranslucentProgram, _skinTranslucentLocations); + + + _skinEmissiveProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/skin_model.vert"); + _skinEmissiveProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + "shaders/model_emissive.frag"); + _skinEmissiveProgram.link(); + + initSkinProgram(_skinEmissiveProgram, _skinEmissiveLocations); + + _skinEmissiveNormalMapProgram.addShaderFromSourceFile(QGLShader::Vertex, + Application::resourcesPath() + "shaders/skin_model_normal_map.vert"); + _skinEmissiveNormalMapProgram.addShaderFromSourceFile(QGLShader::Fragment, + Application::resourcesPath() + "shaders/model_emissive_normal_map.frag"); + _skinEmissiveNormalMapProgram.link(); + + initSkinProgram(_skinEmissiveNormalMapProgram, _skinEmissiveNormalMapLocations); + + _skinEmissiveSpecularMapProgram.addShaderFromSourceFile(QGLShader::Vertex, + Application::resourcesPath() + "shaders/skin_model.vert"); + _skinEmissiveSpecularMapProgram.addShaderFromSourceFile(QGLShader::Fragment, + Application::resourcesPath() + "shaders/model_emissive_specular_map.frag"); + _skinEmissiveSpecularMapProgram.link(); + + initSkinProgram(_skinEmissiveSpecularMapProgram, _skinEmissiveSpecularMapLocations); + + _skinEmissiveNormalSpecularMapProgram.addShaderFromSourceFile(QGLShader::Vertex, + Application::resourcesPath() + "shaders/skin_model_normal_map.vert"); + _skinEmissiveNormalSpecularMapProgram.addShaderFromSourceFile(QGLShader::Fragment, + Application::resourcesPath() + "shaders/model_emissive_normal_specular_map.frag"); + _skinEmissiveNormalSpecularMapProgram.link(); + + initSkinProgram(_skinEmissiveNormalSpecularMapProgram, _skinEmissiveNormalSpecularMapLocations, 2); + } } @@ -621,14 +706,23 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) { //renderMeshes(RenderMode mode, bool translucent, float alphaThreshold, bool hasTangents, bool hasSpecular, book isSkinned, args); int opaqueMeshPartsRendered = 0; - opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, false, args); - opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, true, args); - opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, false, args); - opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, true, args); - opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, false, args); - opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, args); - opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, false, args); - opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, true, args); + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, false, false, args); + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, false, true, args); + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, true, false, args); + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, true, true, args); + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, false, false, args); + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, false, true, args); + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, true, false, args); + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, true, true, args); + + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, false, false, args); + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, false, true, args); + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, false, args); + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, true, args); + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, false, false, args); + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, false, true, args); + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, true, false, args); + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, true, true, args); // render translucent meshes afterwards //Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(false, true, true); @@ -642,14 +736,14 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) { int translucentMeshPartsRendered = 0; const float MOSTLY_OPAQUE_THRESHOLD = 0.75f; - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, false, args); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, true, args); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, false, args); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, args); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, false, args); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, true, args); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, true, false, args); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, true, true, args); + translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, false, false, args); + translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, false, true, args); + translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, true, false, args); + translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, true, true, args); + translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, false, false, args); + translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, false, true, args); + translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, false, args); + translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, true, args); GLBATCH(glDisable)(GL_ALPHA_TEST); GLBATCH(glEnable)(GL_BLEND); @@ -666,14 +760,14 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) { if (mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE) { const float MOSTLY_TRANSPARENT_THRESHOLD = 0.0f; - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, args); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, true, args); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, false, args); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, args); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, false, args); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, true, args); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, true, false, args); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, true, true, args); + translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, false, args); + translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, true, args); + translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, true, false, args); + translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, true, true, args); + translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, false, false, args); + translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, false, true, args); + translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, false, args); + translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, true, args); } GLBATCH(glDepthMask)(true); @@ -1562,15 +1656,24 @@ void Model::endScene(RenderMode mode, RenderArgs* args) { int opaqueMeshPartsRendered = 0; // now, for each model in the scene, render the mesh portions - opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, false, args); - opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, true, args); - opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, false, args); - opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, true, args); - opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, false, args); - opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, args); - opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, false, args); - opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, true, args); - + /* opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, false, false, args); + opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, false, true, args); + opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, true, false, args); + opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, true, true, args); + opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, false, false, args); + opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, false, true, args); + opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, true, false, args); + opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, true, true, args); +*/ + opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, false, false, args); + opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, false, true, args); + opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, false, args); + opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, true, args); + opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, false, false, args); + opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, false, true, args); + opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, true, false, args); + opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, true, true, args); + // render translucent meshes afterwards //Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(false, true, true); { @@ -1583,15 +1686,15 @@ void Model::endScene(RenderMode mode, RenderArgs* args) { int translucentParts = 0; const float MOSTLY_OPAQUE_THRESHOLD = 0.75f; - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, false, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, true, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, false, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, false, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, true, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, true, false, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, true, true, args); - + /* translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, false, false, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, false, true, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, true, false, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, true, true, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, false, false, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, false, true, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, false, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, true, args); + */ GLBATCH(glDisable)(GL_ALPHA_TEST); GLBATCH(glEnable)(GL_BLEND); GLBATCH(glDepthMask)(false); @@ -1607,15 +1710,15 @@ void Model::endScene(RenderMode mode, RenderArgs* args) { if (mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE) { const float MOSTLY_TRANSPARENT_THRESHOLD = 0.0f; - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, true, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, false, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, false, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, true, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, true, false, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, true, true, args); - } + /* translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, false, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, true, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, true, false, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, true, true, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, false, false, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, false, true, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, false, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, true, args); + */ } GLBATCH(glDepthMask)(true); GLBATCH(glDepthFunc)(GL_LESS); @@ -1689,7 +1792,17 @@ void Model::segregateMeshGroups() { _meshesOpaqueSkinned.clear(); _meshesOpaqueTangentsSpecularSkinned.clear(); _meshesOpaqueSpecularSkinned.clear(); - + + _meshesOpaqueEmissiveTangents.clear(); + _meshesOpaqueEmissive.clear(); + _meshesOpaqueEmissiveTangentsSpecular.clear(); + _meshesOpaqueEmissiveSpecular.clear(); + + _meshesOpaqueEmissiveTangentsSkinned.clear(); + _meshesOpaqueEmissiveSkinned.clear(); + _meshesOpaqueEmissiveTangentsSpecularSkinned.clear(); + _meshesOpaqueEmissiveSpecularSkinned.clear(); + _unsortedMeshesTranslucentTangents.clear(); _unsortedMeshesTranslucent.clear(); _unsortedMeshesTranslucentTangentsSpecular.clear(); @@ -1710,6 +1823,16 @@ void Model::segregateMeshGroups() { _unsortedMeshesOpaqueTangentsSpecularSkinned.clear(); _unsortedMeshesOpaqueSpecularSkinned.clear(); + _unsortedMeshesOpaqueEmissiveTangents.clear(); + _unsortedMeshesOpaqueEmissive.clear(); + _unsortedMeshesOpaqueEmissiveTangentsSpecular.clear(); + _unsortedMeshesOpaqueEmissiveSpecular.clear(); + + _unsortedMeshesOpaqueEmissiveTangentsSkinned.clear(); + _unsortedMeshesOpaqueEmissiveSkinned.clear(); + _unsortedMeshesOpaqueEmissiveTangentsSpecularSkinned.clear(); + _unsortedMeshesOpaqueEmissiveSpecularSkinned.clear(); + const FBXGeometry& geometry = _geometry->getFBXGeometry(); const QVector& networkMeshes = _geometry->getMeshes(); @@ -1723,6 +1846,7 @@ void Model::segregateMeshGroups() { bool translucentMesh = networkMesh.getTranslucentPartCount(mesh) == networkMesh.parts.size(); bool hasTangents = !mesh.tangents.isEmpty(); bool hasSpecular = mesh.hasSpecularTexture(); + bool hasEmissive = mesh.hasEmissiveTexture(); bool isSkinned = state.clusterMatrices.size() > 1; QString materialID; @@ -1741,71 +1865,108 @@ void Model::segregateMeshGroups() { qDebug() << "materialID:" << materialID << "parts:" << mesh.parts.size(); } - if (translucentMesh && !hasTangents && !hasSpecular && !isSkinned) { + if ( !hasEmissive) { + if (translucentMesh && !hasTangents && !hasSpecular && !isSkinned) { - _unsortedMeshesTranslucent.insertMulti(materialID, i); + _unsortedMeshesTranslucent.insertMulti(materialID, i); - } else if (translucentMesh && hasTangents && !hasSpecular && !isSkinned) { + } else if (translucentMesh && hasTangents && !hasSpecular && !isSkinned) { - _unsortedMeshesTranslucentTangents.insertMulti(materialID, i); + _unsortedMeshesTranslucentTangents.insertMulti(materialID, i); - } else if (translucentMesh && hasTangents && hasSpecular && !isSkinned) { + } else if (translucentMesh && hasTangents && hasSpecular && !isSkinned) { - _unsortedMeshesTranslucentTangentsSpecular.insertMulti(materialID, i); + _unsortedMeshesTranslucentTangentsSpecular.insertMulti(materialID, i); - } else if (translucentMesh && !hasTangents && hasSpecular && !isSkinned) { + } else if (translucentMesh && !hasTangents && hasSpecular && !isSkinned) { - _unsortedMeshesTranslucentSpecular.insertMulti(materialID, i); + _unsortedMeshesTranslucentSpecular.insertMulti(materialID, i); - } else if (translucentMesh && hasTangents && !hasSpecular && isSkinned) { + } else if (translucentMesh && hasTangents && !hasSpecular && isSkinned) { - _unsortedMeshesTranslucentTangentsSkinned.insertMulti(materialID, i); + _unsortedMeshesTranslucentTangentsSkinned.insertMulti(materialID, i); - } else if (translucentMesh && !hasTangents && !hasSpecular && isSkinned) { + } else if (translucentMesh && !hasTangents && !hasSpecular && isSkinned) { - _unsortedMeshesTranslucentSkinned.insertMulti(materialID, i); + _unsortedMeshesTranslucentSkinned.insertMulti(materialID, i); - } else if (translucentMesh && hasTangents && hasSpecular && isSkinned) { + } else if (translucentMesh && hasTangents && hasSpecular && isSkinned) { - _unsortedMeshesTranslucentTangentsSpecularSkinned.insertMulti(materialID, i); + _unsortedMeshesTranslucentTangentsSpecularSkinned.insertMulti(materialID, i); - } else if (translucentMesh && !hasTangents && hasSpecular && isSkinned) { + } else if (translucentMesh && !hasTangents && hasSpecular && isSkinned) { - _unsortedMeshesTranslucentSpecularSkinned.insertMulti(materialID, i); + _unsortedMeshesTranslucentSpecularSkinned.insertMulti(materialID, i); - } else if (!translucentMesh && !hasTangents && !hasSpecular && !isSkinned) { + } else if (!translucentMesh && !hasTangents && !hasSpecular && !isSkinned) { - _unsortedMeshesOpaque.insertMulti(materialID, i); + _unsortedMeshesOpaque.insertMulti(materialID, i); - } else if (!translucentMesh && hasTangents && !hasSpecular && !isSkinned) { + } else if (!translucentMesh && hasTangents && !hasSpecular && !isSkinned) { - _unsortedMeshesOpaqueTangents.insertMulti(materialID, i); + _unsortedMeshesOpaqueTangents.insertMulti(materialID, i); - } else if (!translucentMesh && hasTangents && hasSpecular && !isSkinned) { + } else if (!translucentMesh && hasTangents && hasSpecular && !isSkinned) { - _unsortedMeshesOpaqueTangentsSpecular.insertMulti(materialID, i); + _unsortedMeshesOpaqueTangentsSpecular.insertMulti(materialID, i); - } else if (!translucentMesh && !hasTangents && hasSpecular && !isSkinned) { + } else if (!translucentMesh && !hasTangents && hasSpecular && !isSkinned) { - _unsortedMeshesOpaqueSpecular.insertMulti(materialID, i); + _unsortedMeshesOpaqueSpecular.insertMulti(materialID, i); - } else if (!translucentMesh && hasTangents && !hasSpecular && isSkinned) { + } else if (!translucentMesh && hasTangents && !hasSpecular && isSkinned) { - _unsortedMeshesOpaqueTangentsSkinned.insertMulti(materialID, i); + _unsortedMeshesOpaqueTangentsSkinned.insertMulti(materialID, i); - } else if (!translucentMesh && !hasTangents && !hasSpecular && isSkinned) { + } else if (!translucentMesh && !hasTangents && !hasSpecular && isSkinned) { - _unsortedMeshesOpaqueSkinned.insertMulti(materialID, i); + _unsortedMeshesOpaqueSkinned.insertMulti(materialID, i); - } else if (!translucentMesh && hasTangents && hasSpecular && isSkinned) { + } else if (!translucentMesh && hasTangents && hasSpecular && isSkinned) { - _unsortedMeshesOpaqueTangentsSpecularSkinned.insertMulti(materialID, i); + _unsortedMeshesOpaqueTangentsSpecularSkinned.insertMulti(materialID, i); - } else if (!translucentMesh && !hasTangents && hasSpecular && isSkinned) { + } else if (!translucentMesh && !hasTangents && hasSpecular && isSkinned) { - _unsortedMeshesOpaqueSpecularSkinned.insertMulti(materialID, i); + _unsortedMeshesOpaqueSpecularSkinned.insertMulti(materialID, i); + } else { + qDebug() << "unexpected!!! this mesh didn't fall into any or our groups???"; + } } else { - qDebug() << "unexpected!!! this mesh didn't fall into any or our groups???"; + if (!translucentMesh && !hasTangents && !hasSpecular && !isSkinned) { + + _unsortedMeshesOpaqueEmissive.insertMulti(materialID, i); + + } else if (!translucentMesh && hasTangents && !hasSpecular && !isSkinned) { + + _unsortedMeshesOpaqueEmissiveTangents.insertMulti(materialID, i); + + } else if (!translucentMesh && hasTangents && hasSpecular && !isSkinned) { + + _unsortedMeshesOpaqueEmissiveTangentsSpecular.insertMulti(materialID, i); + + } else if (!translucentMesh && !hasTangents && hasSpecular && !isSkinned) { + + _unsortedMeshesOpaqueEmissiveSpecular.insertMulti(materialID, i); + + } else if (!translucentMesh && hasTangents && !hasSpecular && isSkinned) { + + _unsortedMeshesOpaqueEmissiveTangentsSkinned.insertMulti(materialID, i); + + } else if (!translucentMesh && !hasTangents && !hasSpecular && isSkinned) { + + _unsortedMeshesOpaqueEmissiveSkinned.insertMulti(materialID, i); + + } else if (!translucentMesh && hasTangents && hasSpecular && isSkinned) { + + _unsortedMeshesOpaqueEmissiveTangentsSpecularSkinned.insertMulti(materialID, i); + + } else if (!translucentMesh && !hasTangents && hasSpecular && isSkinned) { + + _unsortedMeshesOpaqueEmissiveSpecularSkinned.insertMulti(materialID, i); + } else { + qDebug() << "unexpected!!! this mesh didn't fall into any or our groups???"; + } } } @@ -1873,6 +2034,38 @@ void Model::segregateMeshGroups() { _meshesOpaqueSpecularSkinned.append(i); } + foreach(int i, _unsortedMeshesOpaqueEmissive) { + _meshesOpaqueEmissive.append(i); + } + + foreach(int i, _unsortedMeshesOpaqueEmissiveTangents) { + _meshesOpaqueEmissiveTangents.append(i); + } + + foreach(int i, _unsortedMeshesOpaqueEmissiveTangentsSpecular) { + _meshesOpaqueEmissiveTangentsSpecular.append(i); + } + + foreach(int i, _unsortedMeshesOpaqueEmissiveSpecular) { + _meshesOpaqueEmissiveSpecular.append(i); + } + + foreach(int i, _unsortedMeshesOpaqueEmissiveSkinned) { + _meshesOpaqueEmissiveSkinned.append(i); + } + + foreach(int i, _unsortedMeshesOpaqueEmissiveTangentsSkinned) { + _meshesOpaqueEmissiveTangentsSkinned.append(i); + } + + foreach(int i, _unsortedMeshesOpaqueEmissiveTangentsSpecularSkinned) { + _meshesOpaqueEmissiveTangentsSpecularSkinned.append(i); + } + + foreach(int i, _unsortedMeshesOpaqueEmissiveSpecularSkinned) { + _meshesOpaqueEmissiveSpecularSkinned.append(i); + } + _unsortedMeshesTranslucentTangents.clear(); _unsortedMeshesTranslucent.clear(); _unsortedMeshesTranslucentTangentsSpecular.clear(); @@ -1893,10 +2086,20 @@ void Model::segregateMeshGroups() { _unsortedMeshesOpaqueTangentsSpecularSkinned.clear(); _unsortedMeshesOpaqueSpecularSkinned.clear(); + _unsortedMeshesOpaqueEmissiveTangents.clear(); + _unsortedMeshesOpaqueEmissive.clear(); + _unsortedMeshesOpaqueEmissiveTangentsSpecular.clear(); + _unsortedMeshesOpaqueEmissiveSpecular.clear(); + + _unsortedMeshesOpaqueEmissiveTangentsSkinned.clear(); + _unsortedMeshesOpaqueEmissiveSkinned.clear(); + _unsortedMeshesOpaqueEmissiveTangentsSpecularSkinned.clear(); + _unsortedMeshesOpaqueEmissiveSpecularSkinned.clear(); + _meshGroupsKnown = true; } -QVector* Model::pickMeshList(bool translucent, float alphaThreshold, bool hasTangents, bool hasSpecular, bool isSkinned) { +QVector* Model::pickMeshList(bool translucent, float alphaThreshold, bool hasEmissive, bool hasTangents, bool hasSpecular, bool isSkinned) { PROFILE_RANGE(__FUNCTION__); // depending on which parameters we were called with, pick the correct mesh group to render @@ -1917,22 +2120,41 @@ QVector* Model::pickMeshList(bool translucent, float alphaThreshold, bool h whichList = &_meshesTranslucentTangentsSpecularSkinned; } else if (translucent && !hasTangents && hasSpecular && isSkinned) { whichList = &_meshesTranslucentSpecularSkinned; - } else if (!translucent && !hasTangents && !hasSpecular && !isSkinned) { + + } else if (!translucent && !hasEmissive && !hasTangents && !hasSpecular && !isSkinned) { whichList = &_meshesOpaque; - } else if (!translucent && hasTangents && !hasSpecular && !isSkinned) { + } else if (!translucent && !hasEmissive && hasTangents && !hasSpecular && !isSkinned) { whichList = &_meshesOpaqueTangents; - } else if (!translucent && hasTangents && hasSpecular && !isSkinned) { + } else if (!translucent && !hasEmissive && hasTangents && hasSpecular && !isSkinned) { whichList = &_meshesOpaqueTangentsSpecular; - } else if (!translucent && !hasTangents && hasSpecular && !isSkinned) { + } else if (!translucent && !hasEmissive && !hasTangents && hasSpecular && !isSkinned) { whichList = &_meshesOpaqueSpecular; - } else if (!translucent && hasTangents && !hasSpecular && isSkinned) { + } else if (!translucent && !hasEmissive && hasTangents && !hasSpecular && isSkinned) { whichList = &_meshesOpaqueTangentsSkinned; - } else if (!translucent && !hasTangents && !hasSpecular && isSkinned) { + } else if (!translucent && !hasEmissive && !hasTangents && !hasSpecular && isSkinned) { whichList = &_meshesOpaqueSkinned; - } else if (!translucent && hasTangents && hasSpecular && isSkinned) { + } else if (!translucent && !hasEmissive && hasTangents && hasSpecular && isSkinned) { whichList = &_meshesOpaqueTangentsSpecularSkinned; - } else if (!translucent && !hasTangents && hasSpecular && isSkinned) { + } else if (!translucent && !hasEmissive && !hasTangents && hasSpecular && isSkinned) { whichList = &_meshesOpaqueSpecularSkinned; + + } else if (!translucent && hasEmissive && !hasTangents && !hasSpecular && !isSkinned) { + whichList = &_meshesOpaqueEmissive; + } else if (!translucent && hasEmissive && hasTangents && !hasSpecular && !isSkinned) { + whichList = &_meshesOpaqueEmissiveTangents; + } else if (!translucent && hasEmissive && hasTangents && hasSpecular && !isSkinned) { + whichList = &_meshesOpaqueEmissiveTangentsSpecular; + } else if (!translucent && hasEmissive && !hasTangents && hasSpecular && !isSkinned) { + whichList = &_meshesOpaqueEmissiveSpecular; + } else if (!translucent && hasEmissive && hasTangents && !hasSpecular && isSkinned) { + whichList = &_meshesOpaqueEmissiveTangentsSkinned; + } else if (!translucent && hasEmissive && !hasTangents && !hasSpecular && isSkinned) { + whichList = &_meshesOpaqueEmissiveSkinned; + } else if (!translucent && hasEmissive && hasTangents && hasSpecular && isSkinned) { + whichList = &_meshesOpaqueEmissiveTangentsSpecularSkinned; + } else if (!translucent && hasEmissive && !hasTangents && hasSpecular && isSkinned) { + whichList = &_meshesOpaqueEmissiveSpecularSkinned; + } else { qDebug() << "unexpected!!! this mesh didn't fall into any or our groups???"; } @@ -1940,14 +2162,15 @@ QVector* Model::pickMeshList(bool translucent, float alphaThreshold, bool h } void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, - bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args, - SkinLocations*& skinLocations, GLenum& specularTextureUnit) { + bool hasEmissive, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args, + SkinLocations*& skinLocations, GLenum& specularTextureUnit, GLenum& emissiveTextureUnit) { ProgramObject* program = &_program; Locations* locations = &_locations; ProgramObject* skinProgram = &_skinProgram; skinLocations = &_skinLocations; specularTextureUnit = 0; + emissiveTextureUnit = 0; if (mode == SHADOW_RENDER_MODE) { program = &_shadowProgram; skinProgram = &_skinShadowProgram; @@ -1958,27 +2181,59 @@ void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, f skinProgram = &_skinTranslucentProgram; skinLocations = &_skinTranslucentLocations; - } else if (hasTangents) { - if (hasSpecular) { - program = &_normalSpecularMapProgram; - locations = &_normalSpecularMapLocations; - skinProgram = &_skinNormalSpecularMapProgram; - skinLocations = &_skinNormalSpecularMapLocations; - specularTextureUnit = GL_TEXTURE2; + } else if (hasEmissive) { + if (hasTangents) { + if (hasSpecular) { + program = &_emissiveNormalSpecularMapProgram; + locations = &_emissiveNormalSpecularMapLocations; + skinProgram = &_skinEmissiveNormalSpecularMapProgram; + skinLocations = &_skinEmissiveNormalSpecularMapLocations; + specularTextureUnit = GL_TEXTURE2; + emissiveTextureUnit = GL_TEXTURE3; + } else { + program = &_emissiveNormalMapProgram; + locations = &_emissiveNormalMapLocations; + skinProgram = &_skinEmissiveNormalMapProgram; + skinLocations = &_skinEmissiveNormalMapLocations; + emissiveTextureUnit = GL_TEXTURE3; + } + } else if (hasSpecular) { + program = &_emissiveSpecularMapProgram; + locations = &_emissiveSpecularMapLocations; + skinProgram = &_skinEmissiveSpecularMapProgram; + skinLocations = &_skinEmissiveSpecularMapLocations; + specularTextureUnit = GL_TEXTURE1; + emissiveTextureUnit = GL_TEXTURE3; } else { - program = &_normalMapProgram; - locations = &_normalMapLocations; - skinProgram = &_skinNormalMapProgram; - skinLocations = &_skinNormalMapLocations; + program = &_emissiveProgram; + locations = &_emissiveLocations; + skinProgram = &_skinEmissiveProgram; + skinLocations = &_skinEmissiveLocations; + emissiveTextureUnit = GL_TEXTURE3; } - } else if (hasSpecular) { - program = &_specularMapProgram; - locations = &_specularMapLocations; - skinProgram = &_skinSpecularMapProgram; - skinLocations = &_skinSpecularMapLocations; - specularTextureUnit = GL_TEXTURE1; - } - + } else { + if (hasTangents) { + if (hasSpecular) { + program = &_normalSpecularMapProgram; + locations = &_normalSpecularMapLocations; + skinProgram = &_skinNormalSpecularMapProgram; + skinLocations = &_skinNormalSpecularMapLocations; + specularTextureUnit = GL_TEXTURE2; + } else { + program = &_normalMapProgram; + locations = &_normalMapLocations; + skinProgram = &_skinNormalMapProgram; + skinLocations = &_skinNormalMapLocations; + } + } else if (hasSpecular) { + program = &_specularMapProgram; + locations = &_specularMapLocations; + skinProgram = &_skinSpecularMapProgram; + skinLocations = &_skinSpecularMapLocations; + specularTextureUnit = GL_TEXTURE1; + } + } + ProgramObject* activeProgram = program; Locations* activeLocations = locations; @@ -1996,7 +2251,7 @@ void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, f } int Model::renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, - bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args) { + bool hasEmissive, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args) { PROFILE_RANGE(__FUNCTION__); int meshPartsRendered = 0; @@ -2004,18 +2259,19 @@ int Model::renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool bool pickProgramsNeeded = true; SkinLocations* skinLocations; GLenum specularTextureUnit; + GLenum emissiveTextureUnit; foreach(Model* model, _modelsInScene) { - QVector* whichList = model->pickMeshList(translucent, alphaThreshold, hasTangents, hasSpecular, isSkinned); + QVector* whichList = model->pickMeshList(translucent, alphaThreshold, hasEmissive, hasTangents, hasSpecular, isSkinned); if (whichList) { QVector& list = *whichList; if (list.size() > 0) { if (pickProgramsNeeded) { - pickPrograms(batch, mode, translucent, alphaThreshold, hasTangents, hasSpecular, isSkinned, args, skinLocations, specularTextureUnit); + pickPrograms(batch, mode, translucent, alphaThreshold, hasEmissive, hasTangents, hasSpecular, isSkinned, args, skinLocations, specularTextureUnit, emissiveTextureUnit); pickProgramsNeeded = false; } model->setupBatchTransform(batch); - meshPartsRendered += model->renderMeshesFromList(list, batch, mode, translucent, alphaThreshold, args, skinLocations, specularTextureUnit); + meshPartsRendered += model->renderMeshesFromList(list, batch, mode, translucent, alphaThreshold, args, skinLocations, specularTextureUnit, emissiveTextureUnit); GLBATCH(glPopMatrix)(); } } @@ -2028,12 +2284,12 @@ int Model::renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool } int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, - bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args) { + bool hasEmissive, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args) { PROFILE_RANGE(__FUNCTION__); int meshPartsRendered = 0; - QVector* whichList = pickMeshList(translucent, alphaThreshold, hasTangents, hasSpecular, isSkinned); + QVector* whichList = pickMeshList(translucent, alphaThreshold, hasEmissive, hasTangents, hasSpecular, isSkinned); if (!whichList) { qDebug() << "unexpected!!! we don't know which list of meshes to render..."; @@ -2048,8 +2304,9 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl SkinLocations* skinLocations; GLenum specularTextureUnit; - pickPrograms(batch, mode, translucent, alphaThreshold, hasTangents, hasSpecular, isSkinned, args, skinLocations, specularTextureUnit); - meshPartsRendered = renderMeshesFromList(list, batch, mode, translucent, alphaThreshold, args, skinLocations, specularTextureUnit); + GLenum emissiveTextureUnit; + pickPrograms(batch, mode, translucent, alphaThreshold, hasEmissive, hasTangents, hasSpecular, isSkinned, args, skinLocations, specularTextureUnit, emissiveTextureUnit); + meshPartsRendered = renderMeshesFromList(list, batch, mode, translucent, alphaThreshold, args, skinLocations, specularTextureUnit, emissiveTextureUnit); GLBATCH(glUseProgram)(0); return meshPartsRendered; @@ -2057,7 +2314,7 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, RenderArgs* args, - SkinLocations* skinLocations, GLenum specularTextureUnit) { + SkinLocations* skinLocations, GLenum specularTextureUnit, GLenum emissiveTextureUnit) { PROFILE_RANGE(__FUNCTION__); bool dontCullOutOfViewMeshParts = Menu::getInstance()->isOptionChecked(MenuOption::DontCullOutOfViewMeshParts); bool cullTooSmallMeshParts = !Menu::getInstance()->isOptionChecked(MenuOption::DontCullTooSmallMeshParts); @@ -2198,6 +2455,15 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod Application::getInstance()->getTextureCache()->getWhiteTextureID() : specularMap->getID()); GLBATCH(glActiveTexture)(GL_TEXTURE0); } + + if (emissiveTextureUnit) { + GLBATCH(glActiveTexture)(emissiveTextureUnit); + Texture* emissiveMap = networkPart.emissiveTexture.data(); + GLBATCH(glBindTexture)(GL_TEXTURE_2D, !emissiveMap ? + Application::getInstance()->getTextureCache()->getWhiteTextureID() : emissiveMap->getID()); + GLBATCH(glActiveTexture)(GL_TEXTURE0); + } + if (args) { args->_materialSwitches++; } @@ -2238,6 +2504,12 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod GLBATCH(glActiveTexture)(GL_TEXTURE0); } + if (emissiveTextureUnit) { + GLBATCH(glActiveTexture)(emissiveTextureUnit); + GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0); + GLBATCH(glActiveTexture)(GL_TEXTURE0); + } + GLBATCH(glPopMatrix)(); } diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 4dceb07655..c1ae190a1e 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -303,7 +303,12 @@ private: static ProgramObject _specularMapProgram; static ProgramObject _normalSpecularMapProgram; static ProgramObject _translucentProgram; - + + static ProgramObject _emissiveProgram; + static ProgramObject _emissiveNormalMapProgram; + static ProgramObject _emissiveSpecularMapProgram; + static ProgramObject _emissiveNormalSpecularMapProgram; + static ProgramObject _shadowProgram; static ProgramObject _skinProgram; @@ -311,7 +316,12 @@ private: static ProgramObject _skinSpecularMapProgram; static ProgramObject _skinNormalSpecularMapProgram; static ProgramObject _skinTranslucentProgram; - + + static ProgramObject _skinEmissiveProgram; + static ProgramObject _skinEmissiveNormalMapProgram; + static ProgramObject _skinEmissiveSpecularMapProgram; + static ProgramObject _skinEmissiveNormalSpecularMapProgram; + static ProgramObject _skinShadowProgram; static int _normalMapTangentLocation; @@ -328,6 +338,11 @@ private: static Locations _specularMapLocations; static Locations _normalSpecularMapLocations; static Locations _translucentLocations; + + static Locations _emissiveLocations; + static Locations _emissiveNormalMapLocations; + static Locations _emissiveSpecularMapLocations; + static Locations _emissiveNormalSpecularMapLocations; static void initProgram(ProgramObject& program, Locations& locations, int specularTextureUnit = 1); @@ -344,7 +359,12 @@ private: static SkinLocations _skinNormalSpecularMapLocations; static SkinLocations _skinShadowLocations; static SkinLocations _skinTranslucentLocations; - + + static SkinLocations _skinEmissiveLocations; + static SkinLocations _skinEmissiveNormalMapLocations; + static SkinLocations _skinEmissiveSpecularMapLocations; + static SkinLocations _skinEmissiveNormalSpecularMapLocations; + static void initSkinProgram(ProgramObject& program, SkinLocations& locations, int specularTextureUnit = 1); QVector _calculatedMeshBoxes; @@ -376,6 +396,16 @@ private: QMap _unsortedMeshesOpaqueTangentsSpecularSkinned; QMap _unsortedMeshesOpaqueSpecularSkinned; + QMap _unsortedMeshesOpaqueEmissive; + QMap _unsortedMeshesOpaqueEmissiveTangents; + QMap _unsortedMeshesOpaqueEmissiveTangentsSpecular; + QMap _unsortedMeshesOpaqueEmissiveSpecular; + + QMap _unsortedMeshesOpaqueEmissiveSkinned; + QMap _unsortedMeshesOpaqueEmissiveTangentsSkinned; + QMap _unsortedMeshesOpaqueEmissiveTangentsSpecularSkinned; + QMap _unsortedMeshesOpaqueEmissiveSpecularSkinned; + QVector _meshesTranslucent; QVector _meshesTranslucentTangents; QVector _meshesTranslucentTangentsSpecular; @@ -396,6 +426,16 @@ private: QVector _meshesOpaqueTangentsSpecularSkinned; QVector _meshesOpaqueSpecularSkinned; + QVector _meshesOpaqueEmissive; + QVector _meshesOpaqueEmissiveTangents; + QVector _meshesOpaqueEmissiveTangentsSpecular; + QVector _meshesOpaqueEmissiveSpecular; + + QVector _meshesOpaqueEmissiveSkinned; + QVector _meshesOpaqueEmissiveTangentsSkinned; + QVector _meshesOpaqueEmissiveTangentsSpecularSkinned; + QVector _meshesOpaqueEmissiveSpecularSkinned; + // Scene rendering support static QVector _modelsInScene; static gpu::Batch _sceneRenderBatch; @@ -407,19 +447,19 @@ private: void renderSetup(RenderArgs* args); bool renderCore(float alpha, RenderMode mode, RenderArgs* args); int renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, - bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args = NULL); + bool hasEmissive, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args = NULL); void setupBatchTransform(gpu::Batch& batch); - QVector* pickMeshList(bool translucent, float alphaThreshold, bool hasTangents, bool hasSpecular, bool isSkinned); + QVector* pickMeshList(bool translucent, float alphaThreshold, bool hasEmissive, bool hasTangents, bool hasSpecular, bool isSkinned); int renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, - RenderArgs* args, SkinLocations* skinLocations, GLenum specularTextureUnit); + RenderArgs* args, SkinLocations* skinLocations, GLenum specularTextureUnit, GLenum emissiveTextureUnit); static void pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, - bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args, - SkinLocations*& skinLocations, GLenum& specularTextureUnit); + bool hasEmissive, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args, + SkinLocations*& skinLocations, GLenum& specularTextureUnit, GLenum& emissiveTextureUnit); static int renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, - bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args); + bool hasEmissive, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args); }; diff --git a/interface/src/renderer/TextureCache.h b/interface/src/renderer/TextureCache.h index fd9131fe23..66734da9cd 100644 --- a/interface/src/renderer/TextureCache.h +++ b/interface/src/renderer/TextureCache.h @@ -25,7 +25,7 @@ class NetworkTexture; typedef QSharedPointer NetworkTexturePointer; -enum TextureType { DEFAULT_TEXTURE, NORMAL_TEXTURE, SPECULAR_TEXTURE, SPLAT_TEXTURE }; +enum TextureType { DEFAULT_TEXTURE, NORMAL_TEXTURE, SPECULAR_TEXTURE, EMISSIVE_TEXTURE, SPLAT_TEXTURE }; /// Stores cached textures, including render-to-texture targets. class TextureCache : public ResourceCache { @@ -67,7 +67,7 @@ public: /// Returns the ID of the primary framebuffer object's specular texture. GLuint getPrimarySpecularTextureID(); - + /// Enables or disables draw buffers on the primary framebuffer. Note: the primary framebuffer must be bound. void setPrimaryDrawBuffers(bool color, bool normal = false, bool specular = false); diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 4ffd3f6286..7c71bd6c15 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -41,6 +41,15 @@ bool FBXMesh::hasSpecularTexture() const { return false; } +bool FBXMesh::hasEmissiveTexture() const { + foreach (const FBXMeshPart& part, parts) { + if (!part.emissiveTexture.filename.isEmpty()) { + return true; + } + } + return false; +} + QStringList FBXGeometry::getJointNames() const { QStringList names; foreach (const FBXJoint& joint, joints) { @@ -1045,6 +1054,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) QHash diffuseTextures; QHash bumpTextures; QHash specularTextures; + QHash emissiveTextures; QHash localRotations; QHash xComponents; QHash yComponents; @@ -1417,6 +1427,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) ooChildToParent.insert(childID, parentID); } if (connection.properties.at(0) == "OP") { + int counter = 0; QByteArray type = connection.properties.at(3).toByteArray().toLower(); if (type.contains("diffuse")) { diffuseTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1)); @@ -1438,6 +1449,15 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) } else if (type == "d|z") { zComponents.insert(getID(connection.properties, 2), getID(connection.properties, 1)); + + } else if (type.contains("shininess")) { + counter++; + + } else if (type.contains("emissive")) { + emissiveTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1)); + + } else { + counter++; } } parentMap.insert(getID(connection.properties, 1), getID(connection.properties, 2)); @@ -1666,6 +1686,20 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) if (!specularTextureID.isNull()) { specularTexture = getTexture(specularTextureID, textureNames, textureFilenames, textureContent); } + + FBXTexture emissiveTexture; + QString emissiveTextureID = emissiveTextures.value(childID); + if (!emissiveTextureID.isNull()) { + emissiveTexture = getTexture(emissiveTextureID, textureNames, textureFilenames, textureContent); + + // FBX files generated by 3DSMax have an intermediate texture parent, apparently + foreach (const QString& childTextureID, childMap.values(diffuseTextureID)) { + if (textureFilenames.contains(childTextureID)) { + emissiveTexture = getTexture(emissiveTextureID, textureNames, textureFilenames, textureContent); + } + } + } + for (int j = 0; j < extracted.partMaterialTextures.size(); j++) { if (extracted.partMaterialTextures.at(j).first == materialIndex) { @@ -1684,6 +1718,9 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) if (!specularTexture.filename.isNull()) { part.specularTexture = specularTexture; } + if (!emissiveTexture.filename.isNull()) { + part.emissiveTexture = emissiveTexture; + } part.materialID = material.id; } } diff --git a/libraries/fbx/src/FBXReader.h b/libraries/fbx/src/FBXReader.h index 3c9e918686..9299b88b5a 100644 --- a/libraries/fbx/src/FBXReader.h +++ b/libraries/fbx/src/FBXReader.h @@ -120,6 +120,7 @@ public: FBXTexture diffuseTexture; FBXTexture normalTexture; FBXTexture specularTexture; + FBXTexture emissiveTexture; QString materialID; }; @@ -147,6 +148,7 @@ public: QVector blendshapes; bool hasSpecularTexture() const; + bool hasEmissiveTexture() const; }; /// A single animation frame extracted from an FBX document. From fefe9bdb8768a75a86724d977f22443bd1b42475 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Thu, 20 Nov 2014 22:40:49 +0100 Subject: [PATCH 036/502] virtual-keyboard: rescale-able --- examples/virtualKeyboard.js | 60 ++++++++++++++++++++++++++----------- 1 file changed, 43 insertions(+), 17 deletions(-) diff --git a/examples/virtualKeyboard.js b/examples/virtualKeyboard.js index e99a70faed..d7065e8c76 100644 --- a/examples/virtualKeyboard.js +++ b/examples/virtualKeyboard.js @@ -37,6 +37,7 @@ const BOUND_H = 3; const KEY_STATE_LOWER = 0; const KEY_STATE_UPPER = 1; +var windowDimensions = Controller.getViewportDimensions(); var cursor = null; var keyboard = new Keyboard(); var text = null; @@ -49,7 +50,7 @@ keyboard.onFullyLoaded = function() { print("Virtual-keyboard fully loaded."); var dimensions = Controller.getViewportDimensions(); text = Overlays.addOverlay("text", { - x: 0,//(dimensions.x / 2) - (KEYBOARD_WIDTH / 2), + x: 0, y: dimensions.y - keyboard.height() - 60, width: dimensions.x, height: 50, @@ -129,11 +130,13 @@ function KeyboardKey(keyboard, key_properties) { }); } }; - this.updatePosition = function() { + this.rescale = function() { for (var i = 0; i < tthis.bounds.length; i++) { Overlays.editOverlay(tthis.overlays[i], { - x: tthis.keyboard.x + tthis.bounds[i][BOUND_X], - y: tthis.keyboard.y + tthis.bounds[i][BOUND_Y], + x: tthis.keyboard.getX() + tthis.bounds[i][BOUND_X] * keyboard.scale, + y: tthis.keyboard.getY() + tthis.bounds[i][BOUND_Y] * keyboard.scale, + width: this.bounds[i][BOUND_W] * keyboard.scale, + height: this.bounds[i][BOUND_H] * keyboard.scale }); } }; @@ -153,8 +156,8 @@ function KeyboardKey(keyboard, key_properties) { for (var i = 0; i < this.bounds.length; i++) { var newOverlay = Overlays.cloneOverlay(this.keyboard.background); Overlays.editOverlay(newOverlay, { - x: this.keyboard.x + this.bounds[i][BOUND_X] * keyboard.scale, - y: this.keyboard.y + this.bounds[i][BOUND_Y] * keyboard.scale, + x: this.keyboard.getX() + this.bounds[i][BOUND_X] * keyboard.scale, + y: this.keyboard.getY() + this.bounds[i][BOUND_Y] * keyboard.scale, width: this.bounds[i][BOUND_W] * keyboard.scale, height: this.bounds[i][BOUND_H] * keyboard.scale, subImage: {width: this.bounds[i][BOUND_W], height: this.bounds[i][BOUND_H], x: this.bounds[i][BOUND_X], y: (KEYBOARD_HEIGHT * this.key_state) + this.bounds[i][BOUND_Y]}, @@ -166,9 +169,8 @@ function KeyboardKey(keyboard, key_properties) { function Keyboard() { var tthis = this; - var dimensions = Controller.getViewportDimensions(); this.focussed_key = -1; - this.scale = dimensions.x / KEYBOARD_WIDTH; + this.scale = windowDimensions.x / KEYBOARD_WIDTH; this.shift = false; this.width = function() { return KEYBOARD_WIDTH * tthis.scale; @@ -176,22 +178,38 @@ function Keyboard() { this.height = function() { return KEYBOARD_HEIGHT * tthis.scale; }; - this.x = (dimensions.x / 2) - (this.width() / 2); - this.y = dimensions.y - this.height(); + this.getX = function() { + return (windowDimensions.x / 2) - (this.width() / 2); + }; + this.getY = function() { + return windowDimensions.y - this.height(); + }; this.background = Overlays.addOverlay("image", { - x: this.x, - y: this.y, + x: this.getX(), + y: this.getY(), width: this.width(), height: this.height(), subImage: {width: KEYBOARD_WIDTH, height: KEYBOARD_HEIGHT, y: KEYBOARD_HEIGHT * KBD_BACKGROUND}, imageURL: KEYBOARD_URL, alpha: 1 }); + this.rescale = function() { + this.scale = windowDimensions.x / KEYBOARD_WIDTH; + Overlays.editOverlay(tthis.background, { + x: this.getX(), + y: this.getY(), + width: this.width(), + height: this.height() + }); + for (var i = 0; i < tthis.keys.length; i++) { + tthis.keys[i].rescale(); + } + }; this.setFocusPosition = function(x, y) { // set to local unscaled position - var localx = (x - tthis.x) / tthis.scale; - var localy = (y - tthis.y) / tthis.scale; + var localx = (x - tthis.getX()) / tthis.scale; + var localy = (y - tthis.getY()) / tthis.scale; var new_focus_key = -1; if (localx >= 0 && localy >= 0 && localx <= KEYBOARD_WIDTH && localy <= KEYBOARD_HEIGHT) { for (var i = 0; i < tthis.keys.length; i++) { @@ -382,16 +400,24 @@ function Cursor() { }; this.onUpdate = null; this.update = function() { - var dimensions = Controller.getViewportDimensions(); + var newWindowDimensions = Controller.getViewportDimensions(); + if (newWindowDimensions.x != windowDimensions.x || newWindowDimensions.y != windowDimensions.y) { + windowDimensions = newWindowDimensions; + keyboard.rescale(); + Overlays.editOverlay(text, { + y: windowDimensions.y - keyboard.height() - 60, + width: windowDimensions.x + }); + } var editobject = {}; if (MyAvatar.getHeadFinalYaw() <= VIEW_ANGLE_BY_TWO && MyAvatar.getHeadFinalYaw() >= -1 * VIEW_ANGLE_BY_TWO) { angle = ((-1 * MyAvatar.getHeadFinalYaw()) + VIEW_ANGLE_BY_TWO) / VIEW_ANGLE; - tthis.x = angle * dimensions.x; + tthis.x = angle * windowDimensions.x; editobject.x = tthis.x - (CURSOR_WIDTH / 2); } if (MyAvatar.getHeadFinalPitch() <= VIEW_ANGLE_BY_TWO && MyAvatar.getHeadFinalPitch() >= -1 * VIEW_ANGLE_BY_TWO) { angle = ((-1 * MyAvatar.getHeadFinalPitch()) + VIEW_ANGLE_BY_TWO) / VIEW_ANGLE; - tthis.y = angle * dimensions.y; + tthis.y = angle * windowDimensions.y; editobject.y = tthis.y - (CURSOR_HEIGHT / 2); } if (Object.keys(editobject).length > 0) { From 2b57f68857530b5b630558aa60c9abd5e1532656 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Fri, 21 Nov 2014 02:07:11 +0100 Subject: [PATCH 037/502] virtual-keyboard: - shift key functions - keys show pressed while pressing them - keyboard.onKeyPress and onKeyRelease are functional --- examples/virtualKeyboard.js | 64 +++++++++++++++++++++++++++++-------- 1 file changed, 50 insertions(+), 14 deletions(-) diff --git a/examples/virtualKeyboard.js b/examples/virtualKeyboard.js index d7065e8c76..ce3677bec3 100644 --- a/examples/virtualKeyboard.js +++ b/examples/virtualKeyboard.js @@ -26,7 +26,9 @@ const KEYBOARD_HEIGHT = 434.1; const CURSOR_WIDTH = 33.9; const CURSOR_HEIGHT = 33.9; -const VIEW_ANGLE = 60.0; +// VIEW_ANGLE can be adjusted to your likings, the smaller the faster movement. +// Try setting it to 60 if it goes too fast for you. +const VIEW_ANGLE = 30.0; const VIEW_ANGLE_BY_TWO = VIEW_ANGLE / 2; const BOUND_X = 0; @@ -81,7 +83,12 @@ function KeyboardKey(keyboard, key_properties) { this.key_state = key_properties.key_state != undefined ? key_properties.key_state : KBD_LOWERCASE_DEFAULT; // one overlay per bound vector [this.bounds] this.overlays = []; - this.updatePosition = function() { + this.getKeyEvent = function() { + if (tthis.event == 'keypress') { + var state = tthis.states[(tthis.keyboard.shift ? 1 : 2) % tthis.states.length]; + return {key: state.charCode, char: state.char, event: tthis.event}; + } + return {event: tthis.event}; }; this.containsCoord = function(x, y) { for (var i = 0; i < this.bounds.length; i++) { @@ -99,7 +106,7 @@ function KeyboardKey(keyboard, key_properties) { tthis.setState(eval('KBD_' + (tthis.keyboard.shift ? 'UPPERCASE' : 'LOWERCASE') + '_' + (tthis._focus ? 'HOVER' : 'DEFAULT'))); }; this.updateColor = function() { - var colorIntensity = _beingpressed ? 128 : 255; + var colorIntensity = this._beingpressed ? 128 : 255; for (var i = 0; i < tthis.bounds.length; i++) { Overlays.editOverlay(tthis.overlays[i], {color: {red: colorIntensity, green: colorIntensity, blue: colorIntensity}} @@ -221,7 +228,6 @@ function Keyboard() { } } if (new_focus_key != tthis.focussed_key) { - //print(new_focus_key); if (tthis.focussed_key != -1) { tthis.keys[tthis.focussed_key].blur(); } @@ -235,14 +241,44 @@ function Keyboard() { this.pressFocussedKey = function() { if (tthis.focussed_key != -1) { - this.onKeyPress(tthis.keys[tthis.focussed_key]); + if (tthis.keys[tthis.focussed_key].event == 'shift') { + tthis.toggleShift(); + } else { + tthis.keys[tthis.focussed_key].press(); + } + if (this.onKeyPress != null) { + this.onKeyPress(tthis.keys[tthis.focussed_key].getKeyEvent()); + } } return tthis; }; - - this.updatePosition = function() { - + + this.releaseKeys = function() { + for (var i = 0; i < tthis.keys.length; i++) { + if (tthis.keys[i]._beingpressed) { + if (tthis.keys[i].event != 'shift') { + tthis.keys[i].release(); + } + if (this.onKeyRelease != null) { + this.onKeyRelease(tthis.keys[i].getKeyEvent()); + } + } + } + }; + + this.toggleShift = function() { + tthis.shift = !tthis.shift; + for (var i = 0; i < tthis.keys.length; i++) { + tthis.keys[i].updateState(); + if (tthis.keys[i].event == 'shift') { + if (tthis.shift) { + tthis.keys[i].press(); + continue; + } + tthis.keys[i].release(); + } + } }; this.getFocussedKey = function() { @@ -260,8 +296,7 @@ function Keyboard() { }; this.onKeyPress = null; - this.onKeyDown = null; - this.onKeyUp = null; + this.onKeyRelease = null; this.onSubmit = null; this.onFullyLoaded = null; @@ -354,7 +389,7 @@ function Keyboard() { {bounds: [[972, 283, 190, 63]], event: 'shift'}, - {bounds: [[249, 355, 573, 67]], states: [{charCode: 192, char: ' '}]}, + {bounds: [[249, 355, 573, 67]], states: [{charCode: 32, char: ' '}]}, {bounds: [[899, 355, 263, 67]], event: 'submit'} ]; @@ -375,9 +410,8 @@ function Keyboard() { function Cursor() { var tthis = this; - var dimensions = Controller.getViewportDimensions(); - this.x = dimensions.x / 2; - this.y = dimensions.y / 2; + this.x = windowDimensions.x / 2; + this.y = windowDimensions.y / 2; this.overlay = Overlays.addOverlay("image", { x: this.x, y: this.y, @@ -433,12 +467,14 @@ function Cursor() { function keyPressEvent(key) { if (key.text === "SPACE") { print("pressed space"); + keyboard.pressFocussedKey(); } } function keyReleaseEvent(key) { if (key.text === "SPACE") { print("released space"); + keyboard.releaseKeys(); } } From a60374e4c11de48cb8ed713d684226d5f518d33a Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Fri, 21 Nov 2014 02:59:05 +0100 Subject: [PATCH 038/502] virtual-keyboard: added text-entity example --- examples/virtualKeyboard.js | 86 ++++++++++++++++++++++++++++++------- 1 file changed, 70 insertions(+), 16 deletions(-) diff --git a/examples/virtualKeyboard.js b/examples/virtualKeyboard.js index ce3677bec3..5829a4fd2b 100644 --- a/examples/virtualKeyboard.js +++ b/examples/virtualKeyboard.js @@ -6,6 +6,10 @@ // Copyright 2014 High Fidelity, Inc. // // Control a virtual keyboard using your favorite HMD. +// Usage: Enable VR-mode and go to First person mode, +// look at the key that you would like to press, and press the spacebar on your "REAL" keyboard. +// +// leased some code from newEditEntities.js for Text Entity example // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -20,6 +24,8 @@ const KBD_BACKGROUND = 4; const KEYBOARD_URL = "http://test.thoys.nl/hifi/images/virtualKeyboard/keyboard.svg"; const CURSOR_URL = "http://test.thoys.nl/hifi/images/virtualKeyboard/cursor.svg"; +const SPACEBAR_CHARCODE = 32; + const KEYBOARD_WIDTH = 1174.7; const KEYBOARD_HEIGHT = 434.1; @@ -31,6 +37,11 @@ const CURSOR_HEIGHT = 33.9; const VIEW_ANGLE = 30.0; const VIEW_ANGLE_BY_TWO = VIEW_ANGLE / 2; +const SPAWN_DISTANCE = 1; +const DEFAULT_TEXT_DIMENSION_X = 1; +const DEFAULT_TEXT_DIMENSION_Y = 1; +const DEFAULT_TEXT_DIMENSION_Z = 0.02; + const BOUND_X = 0; const BOUND_Y = 1; const BOUND_W = 2; @@ -43,9 +54,55 @@ var windowDimensions = Controller.getViewportDimensions(); var cursor = null; var keyboard = new Keyboard(); var text = null; +var textText = ""; +function appendChar(char) { + textText += char; + updateTextOverlay(); + Overlays.editOverlay(text, {text: textText}); +} +function deleteChar() { + if (textText.length > 0) { + textText = textText.substring(0, textText.length - 1); + updateTextOverlay(); + } +} +function updateTextOverlay() { + Overlays.editOverlay(text, {text: textText}); +} +keyboard.onKeyPress = function(event) { + if (event.event == 'keypress') { + appendChar(event.char); + } else if (event.event == 'enter') { + appendChar("\n"); + } +}; -keyboard.onKeyPress = function() { - print("Key press event test"); +keyboard.onKeyRelease = function(event) { + print("Key release event test"); + // you can cancel a key by releasing its focusing before releasing it + if (event.focus) { + if (event.event == 'delete') { + deleteChar(); + } else if (event.event == 'submit') { + print(textText); + + var position = Vec3.sum(MyAvatar.position, Vec3.multiply(Quat.getFront(MyAvatar.orientation), SPAWN_DISTANCE)); + + if (position.x > 0 && position.y > 0 && position.z > 0) { + Entities.addEntity({ + type: "Text", + position: position, + dimensions: { x: DEFAULT_TEXT_DIMENSION_X, y: DEFAULT_TEXT_DIMENSION_Y, z: DEFAULT_TEXT_DIMENSION_Z }, + backgroundColor: { red: 0, green: 0, blue: 0 }, + textColor: { red: 255, green: 255, blue: 255 }, + text: textText, + lineHight: "0.1" + }); + } + textText = ""; + updateTextOverlay(); + } + } }; keyboard.onFullyLoaded = function() { @@ -53,9 +110,9 @@ keyboard.onFullyLoaded = function() { var dimensions = Controller.getViewportDimensions(); text = Overlays.addOverlay("text", { x: 0, - y: dimensions.y - keyboard.height() - 60, + y: dimensions.y - keyboard.height() - 260, width: dimensions.x, - height: 50, + height: 250, backgroundColor: { red: 255, green: 255, blue: 255}, color: { red: 0, green: 0, blue: 0}, topMargin: 10, @@ -86,9 +143,9 @@ function KeyboardKey(keyboard, key_properties) { this.getKeyEvent = function() { if (tthis.event == 'keypress') { var state = tthis.states[(tthis.keyboard.shift ? 1 : 2) % tthis.states.length]; - return {key: state.charCode, char: state.char, event: tthis.event}; + return {key: state.charCode, char: state.char, event: tthis.event, focus: tthis._focus}; } - return {event: tthis.event}; + return {event: tthis.event, focus: tthis._focus}; }; this.containsCoord = function(x, y) { for (var i = 0; i < this.bounds.length; i++) { @@ -221,7 +278,6 @@ function Keyboard() { if (localx >= 0 && localy >= 0 && localx <= KEYBOARD_WIDTH && localy <= KEYBOARD_HEIGHT) { for (var i = 0; i < tthis.keys.length; i++) { if (tthis.keys[i].containsCoord(localx, localy)) { - //print(tthis.keys[i].states[0].char); new_focus_key = i; break; } @@ -439,7 +495,7 @@ function Cursor() { windowDimensions = newWindowDimensions; keyboard.rescale(); Overlays.editOverlay(text, { - y: windowDimensions.y - keyboard.height() - 60, + y: windowDimensions.y - keyboard.height() - 260, width: windowDimensions.x }); } @@ -464,16 +520,14 @@ function Cursor() { Script.update.connect(this.update); } -function keyPressEvent(key) { - if (key.text === "SPACE") { - print("pressed space"); +function keyPressEvent(event) { + if (event.key === SPACEBAR_CHARCODE) { keyboard.pressFocussedKey(); } } -function keyReleaseEvent(key) { - if (key.text === "SPACE") { - print("released space"); +function keyReleaseEvent(event) { + if (event.key === SPACEBAR_CHARCODE) { keyboard.releaseKeys(); } } @@ -482,9 +536,9 @@ function scriptEnding() { keyboard.remove(); cursor.remove(); Overlays.deleteOverlay(text); - Controller.releaseKeyEvents({key: 32}); + Controller.releaseKeyEvents({key: SPACEBAR_CHARCODE}); } -Controller.captureKeyEvents({key: 32}); +Controller.captureKeyEvents({key: SPACEBAR_CHARCODE}); Controller.keyPressEvent.connect(keyPressEvent); Controller.keyReleaseEvent.connect(keyReleaseEvent); Script.scriptEnding.connect(scriptEnding); \ No newline at end of file From ab2fa16be3f2f600b36803d61d7752877e119546 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 21 Nov 2014 12:06:46 -0800 Subject: [PATCH 039/502] Update edit entities moveUp arrow position --- examples/libraries/entitySelectionTool.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/examples/libraries/entitySelectionTool.js b/examples/libraries/entitySelectionTool.js index e760fb0463..b0fc68b60c 100644 --- a/examples/libraries/entitySelectionTool.js +++ b/examples/libraries/entitySelectionTool.js @@ -260,6 +260,7 @@ SelectionDisplay = (function () { var grabberColorFace = { red: 120, green: 120, blue: 120 }; var grabberLineWidth = 0.5; var grabberSolid = true; + var grabberMoveUpPosition = { x: 0, y: 0, z: 0 }; var grabberPropertiesCorner = { position: { x:0, y: 0, z: 0}, @@ -1093,7 +1094,8 @@ SelectionDisplay = (function () { Overlays.editOverlay(grabberEdgeFL, { visible: stretchHandlesVisible, rotation: rotation, position: EdgeFL }); var grabberMoveUpOffset = 0.1; - Overlays.editOverlay(grabberMoveUp, { visible: activeTool == null || mode == "TRANSLATE_UP_DOWN", position: { x: position.x, y: position.y + worldTop + grabberMoveUpOffset, z: position.z } }); + grabberMoveUpPosition = { x: position.x, y: position.y + worldTop + grabberMoveUpOffset, z: position.z } + Overlays.editOverlay(grabberMoveUp, { visible: activeTool == null || mode == "TRANSLATE_UP_DOWN" }); }; that.setOverlaysVisible = function(isVisible) { @@ -2297,8 +2299,10 @@ SelectionDisplay = (function () { Overlays.editOverlay(rollHandle, { scale: handleSize, }); + var pos = Vec3.sum(grabberMoveUpPosition, { x: 0, y: Vec3.length(diff) * GRABBER_DISTANCE_TO_SIZE_RATIO * 3, z: 0 }); Overlays.editOverlay(grabberMoveUp, { - scale: handleSize, + position: pos, + scale: handleSize / 2, }); } } From 6cd96c95f4e5a90aa52921c9c30ea8f904800db3 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Fri, 21 Nov 2014 16:26:58 -0800 Subject: [PATCH 040/502] Include a context in the Bitstream so that streamed objects can find their LOD. --- libraries/metavoxels/src/Bitstream.cpp | 1 + libraries/metavoxels/src/Bitstream.h | 8 ++++++++ libraries/metavoxels/src/MetavoxelData.cpp | 10 ++++++++++ 3 files changed, 19 insertions(+) diff --git a/libraries/metavoxels/src/Bitstream.cpp b/libraries/metavoxels/src/Bitstream.cpp index e9ac3d6319..7bfd9c91ff 100644 --- a/libraries/metavoxels/src/Bitstream.cpp +++ b/libraries/metavoxels/src/Bitstream.cpp @@ -151,6 +151,7 @@ Bitstream::Bitstream(QDataStream& underlying, MetadataType metadataType, Generic _position(0), _metadataType(metadataType), _genericsMode(genericsMode), + _context(NULL), _objectStreamerStreamer(*this), _typeStreamerStreamer(*this), _attributeStreamer(*this), diff --git a/libraries/metavoxels/src/Bitstream.h b/libraries/metavoxels/src/Bitstream.h index 1fd9205387..8e40ed9240 100644 --- a/libraries/metavoxels/src/Bitstream.h +++ b/libraries/metavoxels/src/Bitstream.h @@ -342,6 +342,12 @@ public: /// Returns a reference to the underlying data stream. QDataStream& getUnderlying() { return _underlying; } + /// Sets the context pointer. + void setContext(void* context) { _context = context; } + + /// Returns the context pointer. + void* getContext() const { return _context; } + /// Substitutes the supplied metaobject for the given class name's default mapping. This is mostly useful for testing the /// process of mapping between different types, but may in the future be used for permanently renaming classes. void addMetaObjectSubstitution(const QByteArray& className, const QMetaObject* metaObject); @@ -562,6 +568,8 @@ private: MetadataType _metadataType; GenericsMode _genericsMode; + void* _context; + RepeatedValueStreamer _objectStreamerStreamer; RepeatedValueStreamer _typeStreamerStreamer; RepeatedValueStreamer _attributeStreamer; diff --git a/libraries/metavoxels/src/MetavoxelData.cpp b/libraries/metavoxels/src/MetavoxelData.cpp index c340a7dd4a..2f20899ffb 100644 --- a/libraries/metavoxels/src/MetavoxelData.cpp +++ b/libraries/metavoxels/src/MetavoxelData.cpp @@ -577,7 +577,9 @@ void MetavoxelData::read(Bitstream& in, const MetavoxelLOD& lod) { } MetavoxelStreamBase base = { attribute, in, lod, lod }; MetavoxelStreamState state = { base, getMinimum(), _size }; + in.setContext(&base); attribute->readMetavoxelRoot(*this, state); + in.setContext(NULL); } } @@ -587,7 +589,9 @@ void MetavoxelData::write(Bitstream& out, const MetavoxelLOD& lod) const { out << it.key(); MetavoxelStreamBase base = { it.key(), out, lod, lod }; MetavoxelStreamState state = { base, getMinimum(), _size }; + out.setContext(&base); it.key()->writeMetavoxelRoot(*it.value(), state); + out.setContext(NULL); } out << AttributePointer(); } @@ -622,6 +626,7 @@ void MetavoxelData::readDelta(const MetavoxelData& reference, const MetavoxelLOD MetavoxelStreamBase base = { attribute, in, lod, referenceLOD }; MetavoxelStreamState state = { base, minimum, _size }; MetavoxelNode* oldRoot = _roots.value(attribute); + in.setContext(&base); if (oldRoot) { bool changed; in >> changed; @@ -637,6 +642,7 @@ void MetavoxelData::readDelta(const MetavoxelData& reference, const MetavoxelLOD } else { attribute->readMetavoxelRoot(*this, state); } + in.setContext(NULL); } forever { @@ -657,7 +663,9 @@ void MetavoxelData::readDelta(const MetavoxelData& reference, const MetavoxelLOD it != remainingRoots.constEnd(); it++) { MetavoxelStreamBase base = { it.key(), in, lod, referenceLOD }; MetavoxelStreamState state = { base, minimum, _size }; + in.setContext(&base); it.key()->readMetavoxelSubdivision(*this, state); + in.setContext(NULL); } } } @@ -693,6 +701,7 @@ void MetavoxelData::writeDelta(const MetavoxelData& reference, const MetavoxelLO MetavoxelNode* referenceRoot = expandedReference->_roots.value(it.key()); MetavoxelStreamBase base = { it.key(), out, lod, referenceLOD }; MetavoxelStreamState state = { base, minimum, _size }; + out.setContext(&base); if (it.value() != referenceRoot || becameSubdivided) { out << it.key(); if (referenceRoot) { @@ -707,6 +716,7 @@ void MetavoxelData::writeDelta(const MetavoxelData& reference, const MetavoxelLO it.key()->writeMetavoxelRoot(*it.value(), state); } } + out.setContext(NULL); } out << AttributePointer(); From 6a66351e7f87c286ea5bfa8a477e56c23fbcdb32 Mon Sep 17 00:00:00 2001 From: Adrianl3d Date: Sat, 22 Nov 2014 10:39:34 +1000 Subject: [PATCH 041/502] Clean up code Fix indentations, whitespace, and layout --- examples/notifications.js | 487 +++++++++++++++++++------------------- 1 file changed, 243 insertions(+), 244 deletions(-) diff --git a/examples/notifications.js b/examples/notifications.js index 6eb5e25566..3357d55096 100644 --- a/examples/notifications.js +++ b/examples/notifications.js @@ -1,54 +1,54 @@ // -// notifications.js -// Created by Adrian +// notifications.js +// Created by Adrian // -// Adrian McCarlie 8-10-14 -// This script demonstrates on-screen overlay type notifications. +// Adrian McCarlie 8-10-14 +// This script demonstrates on-screen overlay type notifications. // 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 -// This script demonstrates notifications created via a number of ways, such as: -// Simple key press alerts, which only depend on a key being pressed, -// dummy examples of this are "q", "w", "e", "r", and "SPACEBAR". -// actual working examples are "a" for left turn, "d" for right turn and Ctrl/s for snapshot. +// This script demonstrates notifications created via a number of ways, such as: +// Simple key press alerts, which only depend on a key being pressed, +// dummy examples of this are "q", "w", "e", "r", and "SPACEBAR". +// actual working examples are "a" for left turn, "d" for right turn and Ctrl/s for snapshot. -// System generated alerts such as users joining and leaving and chat messages which mention this user. -// System generated alerts which originate with a user interface event such as Window Resize, and Mic Mute/Unmute. -// Mic Mute/Unmute may appear to be a key press alert, but it actually gets the call from the system as mic is muted and unmuted, -// so the mic mute/unmute will also trigger the notification by clicking the Mic Mute button at the top of the screen. +// System generated alerts such as users joining and leaving and chat messages which mention this user. +// System generated alerts which originate with a user interface event such as Window Resize, and Mic Mute/Unmute. +// Mic Mute/Unmute may appear to be a key press alert, but it actually gets the call from the system as mic is muted and unmuted, +// so the mic mute/unmute will also trigger the notification by clicking the Mic Mute button at the top of the screen. -// To add a new System notification type: +// To add a new System notification type: // -// 1. Set the Event Connector at the bottom of the script. -// example: -// GlobalServices.incomingMessage.connect(onIncomingMessage); +// 1. Set the Event Connector at the bottom of the script. +// example: +// GlobalServices.incomingMessage.connect(onIncomingMessage); // -// 2. Create a new function to produce a text string, do not include new line returns. -// example: -// function onIncomingMessage(user, message) { -// //do stuff here; -// var text = "This is a notification"; -// wordWrap(text); -// } +// 2. Create a new function to produce a text string, do not include new line returns. +// example: +// function onIncomingMessage(user, message) { +// //do stuff here; +// var text = "This is a notification"; +// wordWrap(text); +// } // -// This new function must call wordWrap(text) if the length of message is longer than 42 chars or unknown. -// wordWrap() will format the text to fit the notifications overlay and send it to createNotification(text). -// If the message is 42 chars or less you should bypass wordWrap() and call createNotification() directly. +// This new function must call wordWrap(text) if the length of message is longer than 42 chars or unknown. +// wordWrap() will format the text to fit the notifications overlay and send it to createNotification(text). +// If the message is 42 chars or less you should bypass wordWrap() and call createNotification() directly. -// To add a keypress driven notification: +// To add a keypress driven notification: // -// 1. Add a key to the keyPressEvent(key). -// 2. Declare a text string. -// 3. Call createNotifications(text) parsing the text. -// example: -// if (key.text == "a") { -// var noteString = "Turning to the Left"; -// createNotification(noteString); -// } +// 1. Add a key to the keyPressEvent(key). +// 2. Declare a text string. +// 3. Call createNotifications(text) parsing the text. +// example: +// if (key.text == "a") { +// var noteString = "Turning to the Left"; +// createNotification(noteString); +// } var width = 340.0; //width of notification overlay @@ -70,16 +70,16 @@ var ourWidth = Window.innerWidth; var ourHeight = Window.innerHeight; var text = "placeholder"; var last_users = GlobalServices.onlineUsers; -var users =[]; +var users = []; var ctrlIsPressed = false; var ready = true; -// When our script shuts down, we should clean up all of our overlays +// When our script shuts down, we should clean up all of our overlays function scriptEnding() { - for (i = 0; i < notifications.length; i++){ - Overlays.deleteOverlay(notifications[i]); - Overlays.deleteOverlay(buttons[i]); - } + for (i = 0; i < notifications.length; i++){ + Overlays.deleteOverlay(notifications[i]); + Overlays.deleteOverlay(buttons[i]); + } } Script.scriptEnding.connect(scriptEnding); @@ -90,164 +90,164 @@ var heights = []; var myAlpha = []; var arrays = []; -// This function creates and sizes the overlays +// This function creates and sizes the overlays function createNotification(text){ - var count = (text.match(/\n/g) || []).length; - var breakPoint = 43.0; // length when new line is added - var extraLine = 0; - var breaks = 0; - var height = 40.0; - var stack = 0; - if (text.length >= breakPoint){ - breaks = count; - } - var extraLine = breaks * 16.0; - for (i = 0; i < heights.length; i++){ - stack = stack + heights[i]; - } - var level = (stack + 20.0 ); - height = height + extraLine; - var overlayProperties = { - x: overlayLocationX, - y: level, - width: width, - height: height, - color: textColor, - backgroundColor: backColor, - alpha: backgroundAlpha, - topargin: topMargin, - leftMargin: leftMargin, - font: {size: fontSize}, - text: text, - }; - var bLevel = level + 12.0; - var buttonProperties = { - x: buttonLocationX, - y: bLevel, - width: 15.0,//37 - height: 15.0,//35 - subImage: { x: 0, y: 0, width: 10, height: 10 }, - imageURL: "http://hifi-public.s3.amazonaws.com/images/close-small-light.svg", - color: { red: 255, green: 255, blue: 255}, - visible: true, - alpha: backgroundAlpha, - }; + var count = (text.match(/\n/g) || []).length; + var breakPoint = 43.0; // length when new line is added + var extraLine = 0; + var breaks = 0; + var height = 40.0; + var stack = 0; + if (text.length >= breakPoint){ + breaks = count; + } + var extraLine = breaks * 16.0; + for (i = 0; i < heights.length; i++){ + stack = stack + heights[i]; + } + var level = (stack + 20.0 ); + height = height + extraLine; + var overlayProperties = { + x: overlayLocationX, + y: level, + width: width, + height: height, + color: textColor, + backgroundColor: backColor, + alpha: backgroundAlpha, + topMargin: topMargin, + leftMargin: leftMargin, + font: {size: fontSize}, + text: text, + }; + var bLevel = level + 12.0; + var buttonProperties = { + x: buttonLocationX, + y: bLevel, + width: 15.0, + height: 15.0, + subImage: { x: 0, y: 0, width: 10, height: 10 }, + imageURL: "http://hifi-public.s3.amazonaws.com/images/close-small-light.svg", + color: { red: 255, green: 255, blue: 255}, + visible: true, + alpha: backgroundAlpha, + }; - Notify(overlayProperties, buttonProperties, height); + Notify(overlayProperties, buttonProperties, height); } -// Pushes data to each array and sets up data for 2nd dimension array -// to handle auxiliary data not carried by the overlay class -// specifically notification "heights", "times" of creation, and . -function Notify (notice, button, height ){ +// Pushes data to each array and sets up data for 2nd dimension array +// to handle auxiliary data not carried by the overlay class +// specifically notification "heights", "times" of creation, and . +function Notify(notice, button, height){ - notifications.push((Overlays.addOverlay("text",notice))); - buttons.push((Overlays.addOverlay("image",button))); - times.push(new Date().getTime() / 1000); - height = height + 1.0; - heights.push(height); - myAlpha.push(0); - var last = notifications.length - 1; - createArrays(notifications[last], buttons[last], times[last], heights[last], myAlpha[last]); - fadeIn(notifications[last], buttons[last]) + notifications.push((Overlays.addOverlay("text",notice))); + buttons.push((Overlays.addOverlay("image",button))); + times.push(new Date().getTime() / 1000); + height = height + 1.0; + heights.push(height); + myAlpha.push(0); + var last = notifications.length - 1; + createArrays(notifications[last], buttons[last], times[last], heights[last], myAlpha[last]); + fadeIn(notifications[last], buttons[last]) } function fadeIn(noticeIn, buttonIn){ - var myLength = arrays.length; - var q = 0; - var pauseTimer = null; - pauseTimer = Script.setInterval(function() { - q++; - qFade = q / 10.0; - Overlays.editOverlay(noticeIn, {alpha: qFade}); - Overlays.editOverlay(buttonIn, {alpha: qFade}); - if (q >= 9.0) { - Script.clearInterval(pauseTimer); - } - }, 10); + var myLength = arrays.length; + var q = 0; + var pauseTimer = null; + pauseTimer = Script.setInterval(function() { + q++; + qFade = q / 10.0; + Overlays.editOverlay(noticeIn, {alpha: qFade}); + Overlays.editOverlay(buttonIn, {alpha: qFade}); + if (q >= 9.0) { + Script.clearInterval(pauseTimer); + } + }, 10); } -// push data from above to the 2 dimensional array +// push data from above to the 2 dimensional array function createArrays(notice, button, createTime, height, myAlpha){ - arrays.push([notice, button, createTime, height, myAlpha]); + arrays.push([notice, button, createTime, height, myAlpha]); } -// handles mouse clicks on buttons +// handles mouse clicks on buttons function mousePressEvent(event) { - var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y}); //identify which overlay was clicked - for (i = 0; i < buttons.length; i++){ //if user clicked a button - if(clickedOverlay == buttons[i]){ - Overlays.deleteOverlay(notifications[i]); - Overlays.deleteOverlay(buttons[i]); - notifications.splice(i, 1); - buttons.splice(i, 1); - times.splice(i, 1); - heights.splice(i, 1); - myAlpha.splice(i, 1); - arrays.splice(i, 1); - } - } + var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y}); //identify which overlay was clicked + for (i = 0; i < buttons.length; i++){ //if user clicked a button + if(clickedOverlay == buttons[i]){ + Overlays.deleteOverlay(notifications[i]); + Overlays.deleteOverlay(buttons[i]); + notifications.splice(i, 1); + buttons.splice(i, 1); + times.splice(i, 1); + heights.splice(i, 1); + myAlpha.splice(i, 1); + arrays.splice(i, 1); + } + } } -// Control key remains active only while key is held down +// Control key remains active only while key is held down function keyReleaseEvent(key){ - if (key.key == 16777249){ - ctrlIsPressed = false; - } + if (key.key == 16777249){ + ctrlIsPressed = false; + } } -// Triggers notification on specific key driven events +// Triggers notification on specific key driven events function keyPressEvent(key) { - if (key.key == 16777249){ - ctrlIsPressed = true; - } - if (key.text == "a") { - var noteString = "Turning to the Left"; - createNotification(noteString); - } - if (key.text == "d") { - var noteString = "Turning to the Right"; - createNotification(noteString); - } - if (key.text == "s") { - if (ctrlIsPressed == true){ - var noteString = "You have taken a snapshot"; - createNotification(noteString); - } - } - if (key.text == "q") { - var noteString = "Enable Scripted Motor control is now on."; - wordWrap(noteString); - } - if (key.text == "w") { - var noteString = "This notification spans 2 lines. The overlay will resize to fit new lines."; - var noteString = "editVoxels.js stopped, editModels.js stopped, selectAudioDevice.js stopped."; - wordWrap(noteString); - } - if (key.text == "e") { - var noteString = "This is an example of a multiple line notification. This notification will span 3 lines." - wordWrap(noteString); - } - if (key.text == "r") { - var noteString = "This is a very long line of text that we are going to use in this example to divide it into rows of maximum 43 chars and see how many lines we use."; - wordWrap(noteString); - } - if (key.text == "SPACE") { - var noteString = "You have pressed the Spacebar, This is an example of a multiple line notification. Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam."; - wordWrap(noteString); - } + if (key.key == 16777249){ + ctrlIsPressed = true; + } + if (key.text == "a") { + var noteString = "Turning to the Left"; + createNotification(noteString); + } + if (key.text == "d") { + var noteString = "Turning to the Right"; + createNotification(noteString); + } + if (key.text == "s") { + if (ctrlIsPressed == true){ + var noteString = "You have taken a snapshot"; + createNotification(noteString); + } + } + if (key.text == "q") { + var noteString = "Enable Scripted Motor control is now on."; + wordWrap(noteString); + } + if (key.text == "w") { + var noteString = "This notification spans 2 lines. The overlay will resize to fit new lines."; + var noteString = "editVoxels.js stopped, editModels.js stopped, selectAudioDevice.js stopped."; + wordWrap(noteString); + } + if (key.text == "e") { + var noteString = "This is an example of a multiple line notification. This notification will span 3 lines." + wordWrap(noteString); + } + if (key.text == "r") { + var noteString = "This is a very long line of text that we are going to use in this example to divide it into rows of maximum 43 chars and see how many lines we use."; + wordWrap(noteString); + } + if (key.text == "SPACE") { + var noteString = "You have pressed the Spacebar, This is an example of a multiple line notification. Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam."; + wordWrap(noteString); + } } -// formats string to add newline every 43 chars +// formats string to add newline every 43 chars function wordWrap(str){ - var result = stringDivider(str, 43.0, "\n"); - createNotification(result); + var result = stringDivider(str, 43.0, "\n"); + createNotification(result); } -// wraps whole word to newline +// wraps whole word to newline function stringDivider(str, slotWidth, spaceReplacer) { - if (str.length>slotWidth) { - var p=slotWidth; + if (str.length > slotWidth) { + var p = slotWidth; for (; p > 0 && str[p] != ' '; p--) { } if (p > 0) { @@ -259,27 +259,27 @@ function stringDivider(str, slotWidth, spaceReplacer) { return str; } -//This fires a notification on window resize +// This fires a notification on window resize function checkSize(){ - if((Window.innerWidth!=ourWidth)||(Window.innerHeight!=ourHeight)){ - var windowResize = "Window has been resized"; - ourWidth = Window.innerWidth; - ourHeight = Window.innerHeight; - windowDimensions = Controller.getViewportDimensions(); - overlayLocationX = (windowDimensions.x - (width + 60.0)); - buttonLocationX = overlayLocationX + (width - 35.0); - createNotification(windowResize) - } + if((Window.innerWidth!=ourWidth)||(Window.innerHeight!=ourHeight)){ + var windowResize = "Window has been resized"; + ourWidth = Window.innerWidth; + ourHeight = Window.innerHeight; + windowDimensions = Controller.getViewportDimensions(); + overlayLocationX = (windowDimensions.x - (width + 60.0)); + buttonLocationX = overlayLocationX + (width - 35.0); + createNotification(windowResize) + } } -// Triggers notification if a user logs on or off +// Triggers notification if a user logs on or off function onOnlineUsersChanged(users) { var joiners = []; var leavers = []; for (user in users) { - if (last_users.indexOf(users[user]) == -1.0) { - joiners.push(users[user]); - createNotification(users[user] + " Has joined"); + if (last_users.indexOf(users[user]) == -1.0) { + joiners.push(users[user]); + createNotification(users[user] + " Has joined"); } } for (user in last_users) { @@ -291,81 +291,80 @@ function onOnlineUsersChanged(users) { last_users = users; } -// Triggers notification if @MyUserName is mentioned in chat and returns the message to the notification. +// Triggers notification if @MyUserName is mentioned in chat and returns the message to the notification. function onIncomingMessage(user, message) { var myMessage = message; var alertMe = "@" + GlobalServices.myUsername; var thisAlert = user + ": " + myMessage; if (myMessage.indexOf(alertMe) > -1.0) { - wordWrap(thisAlert); - } + wordWrap(thisAlert); + } } -// Triggers mic mute notification +// Triggers mic mute notification function onMuteStateChanged() { - var muteState = AudioDevice.getMuted() ? "Muted" : "Unmuted"; - var muteString = "Microphone is set to " + muteState; - createNotification(muteString); + var muteState = AudioDevice.getMuted() ? "Muted" : "Unmuted"; + var muteString = "Microphone is set to " + muteState; + createNotification(muteString); } function update(){ - frame++; - if ((frame % 60.0) == 0) { // only update once a second - checkSize(); // checks for size change to trigger windowResize notification - locationY = 20.0; - for (var i = 0; i < arrays.length; i++){ //repositions overlays as others fade - var nextOverlay = Overlays.getOverlayAtPoint({x: overlayLocationX, y: locationY }); - Overlays.editOverlay(notifications[i], { x:overlayLocationX, y:locationY}); - Overlays.editOverlay(buttons[i], { x:buttonLocationX, y:locationY + 12.0}); - locationY=locationY + arrays[i][3]; - } - } + frame++; + if ((frame % 60.0) == 0) { // only update once a second + checkSize(); // checks for size change to trigger windowResize notification + locationY = 20.0; + for (var i = 0; i < arrays.length; i++){ //repositions overlays as others fade + var nextOverlay = Overlays.getOverlayAtPoint({x: overlayLocationX, y: locationY }); + Overlays.editOverlay(notifications[i], { x:overlayLocationX, y:locationY}); + Overlays.editOverlay(buttons[i], { x:buttonLocationX, y:locationY + 12.0}); + locationY=locationY + arrays[i][3]; + } + } - // This checks the age of the notification and prepares to fade it after 9.0 seconds (var persistTime - 1) - for (var i = 0; i < arrays.length; i++){ - if (ready){ - var j = arrays[i][2]; - var k = j + persistTime; - if (k < (new Date().getTime() / 1000)){ - ready = false; - noticeOut = arrays[i][0]; - buttonOut = arrays[i][1]; - var arraysOut = i; - fadeOut(noticeOut, buttonOut, arraysOut); - } - } - } +// This checks the age of the notification and prepares to fade it after 9.0 seconds (var persistTime - 1) + for (var i = 0; i < arrays.length; i++){ + if (ready){ + var j = arrays[i][2]; + var k = j + persistTime; + if (k < (new Date().getTime() / 1000)){ + ready = false; + noticeOut = arrays[i][0]; + buttonOut = arrays[i][1]; + var arraysOut = i; + fadeOut(noticeOut, buttonOut, arraysOut); + } + } + } } -// this fades the notification ready for dismissal, and removes it from the arrays +// this fades the notification ready for dismissal, and removes it from the arrays function fadeOut(noticeOut, buttonOut, arraysOut){ - var myLength = arrays.length; - var r = 9.0; - var pauseTimer = null; - pauseTimer = Script.setInterval(function() { - r--; - rFade = r / 10.0; - Overlays.editOverlay(noticeOut, {alpha: rFade}); - Overlays.editOverlay(buttonOut, {alpha: rFade}); - if (r < 0) { - dismiss(noticeOut, buttonOut, arraysOut); - arrays.splice(arraysOut, 1); - ready = true; - Script.clearInterval(pauseTimer); - } - }, 20); + var myLength = arrays.length; + var r = 9.0; + var pauseTimer = null; + pauseTimer = Script.setInterval(function() { + r--; + rFade = r / 10.0; + Overlays.editOverlay(noticeOut, {alpha: rFade}); + Overlays.editOverlay(buttonOut, {alpha: rFade}); + if (r < 0) { + dismiss(noticeOut, buttonOut, arraysOut); + arrays.splice(arraysOut, 1); + ready = true; + Script.clearInterval(pauseTimer); + } + }, 20); } -// This handles the final dismissal of a notification after fading +// This handles the final dismissal of a notification after fading function dismiss(firstNoteOut, firstButOut, firstOut){ var working = firstOut - Overlays.deleteOverlay(firstNoteOut); - Overlays.deleteOverlay(firstButOut); - notifications.splice(firstOut, 1); - buttons.splice(firstOut, 1); - times.splice(firstOut, 1); - heights.splice(firstOut, 1); - myAlpha.splice(firstOut,1); - + Overlays.deleteOverlay(firstNoteOut); + Overlays.deleteOverlay(firstButOut); + notifications.splice(firstOut, 1); + buttons.splice(firstOut, 1); + times.splice(firstOut, 1); + heights.splice(firstOut, 1); + myAlpha.splice(firstOut,1); } onMuteStateChanged(); From 282732677fb7be2ce4393a7f724a8dfe2699b089 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Fri, 21 Nov 2014 16:45:39 -0800 Subject: [PATCH 042/502] Catch and log BitstreamExceptions when reading datagrams. --- .../metavoxels/src/DatagramSequencer.cpp | 61 ++++++++++--------- 1 file changed, 33 insertions(+), 28 deletions(-) diff --git a/libraries/metavoxels/src/DatagramSequencer.cpp b/libraries/metavoxels/src/DatagramSequencer.cpp index d97ed67644..1aeef8e450 100644 --- a/libraries/metavoxels/src/DatagramSequencer.cpp +++ b/libraries/metavoxels/src/DatagramSequencer.cpp @@ -239,39 +239,44 @@ void DatagramSequencer::receivedDatagram(const QByteArray& datagram) { _sendRecords.erase(_sendRecords.begin(), it + 1); } - // alert external parties so that they can read the middle - emit readyToRead(_inputStream); - - // read and dispatch the high-priority messages - int highPriorityMessageCount; - _inputStream >> highPriorityMessageCount; - int newHighPriorityMessages = highPriorityMessageCount - _receivedHighPriorityMessages; - for (int i = 0; i < highPriorityMessageCount; i++) { - QVariant data; - _inputStream >> data; - if (i >= _receivedHighPriorityMessages) { - emit receivedHighPriorityMessage(data); + try { + // alert external parties so that they can read the middle + emit readyToRead(_inputStream); + + // read and dispatch the high-priority messages + int highPriorityMessageCount; + _inputStream >> highPriorityMessageCount; + int newHighPriorityMessages = highPriorityMessageCount - _receivedHighPriorityMessages; + for (int i = 0; i < highPriorityMessageCount; i++) { + QVariant data; + _inputStream >> data; + if (i >= _receivedHighPriorityMessages) { + emit receivedHighPriorityMessage(data); + } } - } - _receivedHighPriorityMessages = highPriorityMessageCount; + _receivedHighPriorityMessages = highPriorityMessageCount; + + // read the reliable data, if any + quint32 reliableChannels; + _incomingPacketStream >> reliableChannels; + for (quint32 i = 0; i < reliableChannels; i++) { + quint32 channelIndex; + _incomingPacketStream >> channelIndex; + getReliableInputChannel(channelIndex)->readData(_incomingPacketStream); + } + + // record the receipt + ReceiveRecord record = { _incomingPacketNumber, _inputStream.getAndResetReadMappings(), newHighPriorityMessages }; + _receiveRecords.append(record); + + emit receiveRecorded(); - // read the reliable data, if any - quint32 reliableChannels; - _incomingPacketStream >> reliableChannels; - for (quint32 i = 0; i < reliableChannels; i++) { - quint32 channelIndex; - _incomingPacketStream >> channelIndex; - getReliableInputChannel(channelIndex)->readData(_incomingPacketStream); + } catch (const BitstreamException& e) { + qWarning() << "Error reading datagram:" << e.getDescription(); } _incomingPacketStream.device()->seek(0); - _inputStream.reset(); - - // record the receipt - ReceiveRecord record = { _incomingPacketNumber, _inputStream.getAndResetReadMappings(), newHighPriorityMessages }; - _receiveRecords.append(record); - - emit receiveRecorded(); + _inputStream.reset(); } void DatagramSequencer::sendClearSharedObjectMessage(int id) { From 87471df7a193a114ed77bf14b8a1e72c4c86fcff Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Fri, 21 Nov 2014 18:08:34 -0800 Subject: [PATCH 043/502] First version of the lighmap working --- interface/resources/shaders/model.vert | 6 +- .../resources/shaders/model_normal_map.vert | 6 +- interface/resources/shaders/skin_model.vert | 4 +- .../shaders/skin_model_normal_map.vert | 4 +- interface/src/gpu/Stream.h | 1 + interface/src/renderer/GeometryCache.cpp | 7 +- interface/src/renderer/Model.cpp | 384 +++++++----------- interface/src/renderer/Model.h | 68 ++-- libraries/fbx/src/FBXReader.cpp | 260 +++++++++++- libraries/fbx/src/FBXReader.h | 8 +- libraries/shared/src/Transform.h | 20 +- 11 files changed, 468 insertions(+), 300 deletions(-) diff --git a/interface/resources/shaders/model.vert b/interface/resources/shaders/model.vert index a304187591..5ae6ea1cb6 100644 --- a/interface/resources/shaders/model.vert +++ b/interface/resources/shaders/model.vert @@ -11,6 +11,10 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +const int MAX_TEXCOORDS = 2; + +uniform mat4 texcoordMatrices[MAX_TEXCOORDS]; + // the interpolated normal varying vec4 normal; @@ -22,7 +26,7 @@ void main(void) { gl_FrontColor = gl_Color * gl_FrontMaterial.diffuse; // and the texture coordinates - gl_TexCoord[0] = gl_MultiTexCoord0; + gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.f, 1.f); // use standard pipeline transform gl_Position = ftransform(); diff --git a/interface/resources/shaders/model_normal_map.vert b/interface/resources/shaders/model_normal_map.vert index 9fde196b06..2e98b8c4fc 100644 --- a/interface/resources/shaders/model_normal_map.vert +++ b/interface/resources/shaders/model_normal_map.vert @@ -11,6 +11,10 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +const int MAX_TEXCOORDS = 2; + +uniform mat4 texcoordMatrices[MAX_TEXCOORDS]; + // the tangent vector attribute vec3 tangent; @@ -29,7 +33,7 @@ void main(void) { gl_FrontColor = gl_Color * gl_FrontMaterial.diffuse; // and the texture coordinates - gl_TexCoord[0] = gl_MultiTexCoord0; + gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.f, 1.f); // use standard pipeline transform gl_Position = ftransform(); diff --git a/interface/resources/shaders/skin_model.vert b/interface/resources/shaders/skin_model.vert index 072bf3c336..a8c25e885b 100644 --- a/interface/resources/shaders/skin_model.vert +++ b/interface/resources/shaders/skin_model.vert @@ -11,10 +11,12 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +const int MAX_TEXCOORDS = 2; const int MAX_CLUSTERS = 128; const int INDICES_PER_VERTEX = 4; uniform mat4 clusterMatrices[MAX_CLUSTERS]; +uniform mat4 texcoordMatrices[MAX_TEXCOORDS]; attribute vec4 clusterIndices; attribute vec4 clusterWeights; @@ -38,7 +40,7 @@ void main(void) { gl_FrontColor = gl_FrontMaterial.diffuse; // and the texture coordinates - gl_TexCoord[0] = gl_MultiTexCoord0; + gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.f, 1.f); gl_Position = gl_ModelViewProjectionMatrix * position; } diff --git a/interface/resources/shaders/skin_model_normal_map.vert b/interface/resources/shaders/skin_model_normal_map.vert index ac6c77f7cb..bbe5da35af 100644 --- a/interface/resources/shaders/skin_model_normal_map.vert +++ b/interface/resources/shaders/skin_model_normal_map.vert @@ -11,10 +11,12 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +const int MAX_TEXCOORDS = 2; const int MAX_CLUSTERS = 128; const int INDICES_PER_VERTEX = 4; uniform mat4 clusterMatrices[MAX_CLUSTERS]; +uniform mat4 texcoordMatrices[MAX_TEXCOORDS]; // the tangent vector attribute vec3 tangent; @@ -46,7 +48,7 @@ void main(void) { gl_FrontColor = gl_FrontMaterial.diffuse; // and the texture coordinates - gl_TexCoord[0] = gl_MultiTexCoord0; + gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.f, 1.f); gl_Position = gl_ModelViewProjectionMatrix * interpolatedPosition; } diff --git a/interface/src/gpu/Stream.h b/interface/src/gpu/Stream.h index 84b2edc5f3..d024182531 100644 --- a/interface/src/gpu/Stream.h +++ b/interface/src/gpu/Stream.h @@ -34,6 +34,7 @@ public: TANGENT, SKIN_CLUSTER_INDEX, SKIN_CLUSTER_WEIGHT, + TEXCOORD1, NUM_INPUT_SLOTS, }; diff --git a/interface/src/renderer/GeometryCache.cpp b/interface/src/renderer/GeometryCache.cpp index b0636d3321..04ff7bdecd 100644 --- a/interface/src/renderer/GeometryCache.cpp +++ b/interface/src/renderer/GeometryCache.cpp @@ -964,7 +964,8 @@ void NetworkGeometry::setGeometry(const FBXGeometry& geometry) { int tangentsOffset = normalsOffset + mesh.normals.size() * sizeof(glm::vec3); int colorsOffset = tangentsOffset + mesh.tangents.size() * sizeof(glm::vec3); int texCoordsOffset = colorsOffset + mesh.colors.size() * sizeof(glm::vec3); - int clusterIndicesOffset = texCoordsOffset + mesh.texCoords.size() * sizeof(glm::vec2); + int texCoords1Offset = texCoordsOffset + mesh.texCoords.size() * sizeof(glm::vec2); + int clusterIndicesOffset = texCoords1Offset + mesh.texCoords1.size() * sizeof(glm::vec2); int clusterWeightsOffset = clusterIndicesOffset + mesh.clusterIndices.size() * sizeof(glm::vec4); networkMesh._vertexBuffer->resize(clusterWeightsOffset + mesh.clusterWeights.size() * sizeof(glm::vec4)); @@ -977,6 +978,8 @@ void NetworkGeometry::setGeometry(const FBXGeometry& geometry) { networkMesh._vertexBuffer->setSubData(colorsOffset, mesh.colors.size() * sizeof(glm::vec3), (gpu::Resource::Byte*) mesh.colors.constData()); networkMesh._vertexBuffer->setSubData(texCoordsOffset, mesh.texCoords.size() * sizeof(glm::vec2), (gpu::Resource::Byte*) mesh.texCoords.constData()); + networkMesh._vertexBuffer->setSubData(texCoords1Offset, + mesh.texCoords1.size() * sizeof(glm::vec2), (gpu::Resource::Byte*) mesh.texCoords1.constData()); networkMesh._vertexBuffer->setSubData(clusterIndicesOffset, mesh.clusterIndices.size() * sizeof(glm::vec4), (gpu::Resource::Byte*) mesh.clusterIndices.constData()); networkMesh._vertexBuffer->setSubData(clusterWeightsOffset, @@ -989,6 +992,7 @@ void NetworkGeometry::setGeometry(const FBXGeometry& geometry) { if (mesh.tangents.size()) networkMesh._vertexStream->addBuffer(networkMesh._vertexBuffer, tangentsOffset, sizeof(glm::vec3)); if (mesh.colors.size()) networkMesh._vertexStream->addBuffer(networkMesh._vertexBuffer, colorsOffset, sizeof(glm::vec3)); if (mesh.texCoords.size()) networkMesh._vertexStream->addBuffer(networkMesh._vertexBuffer, texCoordsOffset, sizeof(glm::vec2)); + if (mesh.texCoords1.size()) networkMesh._vertexStream->addBuffer(networkMesh._vertexBuffer, texCoords1Offset, sizeof(glm::vec2)); if (mesh.clusterIndices.size()) networkMesh._vertexStream->addBuffer(networkMesh._vertexBuffer, clusterIndicesOffset, sizeof(glm::vec4)); if (mesh.clusterWeights.size()) networkMesh._vertexStream->addBuffer(networkMesh._vertexBuffer, clusterWeightsOffset, sizeof(glm::vec4)); @@ -999,6 +1003,7 @@ void NetworkGeometry::setGeometry(const FBXGeometry& geometry) { if (mesh.tangents.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::TANGENT, channelNum++, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ)); if (mesh.colors.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::COLOR, channelNum++, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::RGB)); if (mesh.texCoords.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::TEXCOORD, channelNum++, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::UV)); + if (mesh.texCoords1.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::TEXCOORD1, channelNum++, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::UV)); if (mesh.clusterIndices.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::SKIN_CLUSTER_INDEX, channelNum++, gpu::Element(gpu::VEC4, gpu::NFLOAT, gpu::XYZW)); if (mesh.clusterWeights.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::SKIN_CLUSTER_WEIGHT, channelNum++, gpu::Element(gpu::VEC4, gpu::NFLOAT, gpu::XYZW)); } diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index a4c4e51d69..d2a2378689 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -70,10 +70,10 @@ ProgramObject Model::_specularMapProgram; ProgramObject Model::_normalSpecularMapProgram; ProgramObject Model::_translucentProgram; -ProgramObject Model::_emissiveProgram; -ProgramObject Model::_emissiveNormalMapProgram; -ProgramObject Model::_emissiveSpecularMapProgram; -ProgramObject Model::_emissiveNormalSpecularMapProgram; +ProgramObject Model::_lightmapProgram; +ProgramObject Model::_lightmapNormalMapProgram; +ProgramObject Model::_lightmapSpecularMapProgram; +ProgramObject Model::_lightmapNormalSpecularMapProgram; ProgramObject Model::_shadowProgram; @@ -83,11 +83,6 @@ ProgramObject Model::_skinSpecularMapProgram; ProgramObject Model::_skinNormalSpecularMapProgram; ProgramObject Model::_skinTranslucentProgram; -ProgramObject Model::_skinEmissiveProgram; -ProgramObject Model::_skinEmissiveNormalMapProgram; -ProgramObject Model::_skinEmissiveSpecularMapProgram; -ProgramObject Model::_skinEmissiveNormalSpecularMapProgram; - ProgramObject Model::_skinShadowProgram; Model::Locations Model::_locations; @@ -96,10 +91,10 @@ Model::Locations Model::_specularMapLocations; Model::Locations Model::_normalSpecularMapLocations; Model::Locations Model::_translucentLocations; -Model::Locations Model::_emissiveLocations; -Model::Locations Model::_emissiveNormalMapLocations; -Model::Locations Model::_emissiveSpecularMapLocations; -Model::Locations Model::_emissiveNormalSpecularMapLocations; +Model::Locations Model::_lightmapLocations; +Model::Locations Model::_lightmapNormalMapLocations; +Model::Locations Model::_lightmapSpecularMapLocations; +Model::Locations Model::_lightmapNormalSpecularMapLocations; Model::SkinLocations Model::_skinLocations; Model::SkinLocations Model::_skinNormalMapLocations; @@ -108,11 +103,6 @@ Model::SkinLocations Model::_skinNormalSpecularMapLocations; Model::SkinLocations Model::_skinShadowLocations; Model::SkinLocations Model::_skinTranslucentLocations; -Model::SkinLocations Model::_skinEmissiveLocations; -Model::SkinLocations Model::_skinEmissiveNormalMapLocations; -Model::SkinLocations Model::_skinEmissiveSpecularMapLocations; -Model::SkinLocations Model::_skinEmissiveNormalSpecularMapLocations; - void Model::setScale(const glm::vec3& scale) { setScaleInternal(scale); // if anyone sets scale manually, then we are no longer scaled to fit @@ -160,17 +150,40 @@ void Model::initProgram(ProgramObject& program, Model::Locations& locations, int glBindAttribLocation(program.programId(), gpu::Stream::TANGENT, "tangent"); + glBindAttribLocation(program.programId(), gpu::Stream::TEXCOORD1, "texcoord1"); + glLinkProgram(program.programId()); locations.tangent = program.attributeLocation("tangent"); locations.alphaThreshold = program.uniformLocation("alphaThreshold"); + locations.texcoordMatrices = program.uniformLocation("texcoordMatrices"); + + program.setUniformValue("diffuseMap", 0); program.setUniformValue("normalMap", 1); - program.setUniformValue("specularMap", specularTextureUnit); + int loc = program.uniformLocation("specularMap"); + if (loc >= 0) { + program.setUniformValue("specularMap", 2); + locations.specularTextureUnit = 2; + } else { + locations.specularTextureUnit = -1; + } + + loc = program.uniformLocation("emissiveMap"); + if (loc >= 0) { + program.setUniformValue("emissiveMap", 3); + locations.emissiveTextureUnit = 3; + } else { + locations.emissiveTextureUnit = -1; + } + + if (!program.isLinked()) { + program.release(); + } program.release(); @@ -289,37 +302,37 @@ void Model::init() { initProgram(_translucentProgram, _translucentLocations); - // Emissive - _emissiveProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/model.vert"); - _emissiveProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + "shaders/model_emissive.frag"); - _emissiveProgram.link(); + // Lightmap + _lightmapProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/model_lightmap.vert"); + _lightmapProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + "shaders/model_lightmap.frag"); + _lightmapProgram.link(); - initProgram(_emissiveProgram, _emissiveLocations); + initProgram(_lightmapProgram, _lightmapLocations); - _emissiveNormalMapProgram.addShaderFromSourceFile(QGLShader::Vertex, - Application::resourcesPath() + "shaders/model_normal_map.vert"); - _emissiveNormalMapProgram.addShaderFromSourceFile(QGLShader::Fragment, - Application::resourcesPath() + "shaders/model_emissive_normal_map.frag"); - _emissiveNormalMapProgram.link(); + _lightmapNormalMapProgram.addShaderFromSourceFile(QGLShader::Vertex, + Application::resourcesPath() + "shaders/model_lightmap_normal_map.vert"); + _lightmapNormalMapProgram.addShaderFromSourceFile(QGLShader::Fragment, + Application::resourcesPath() + "shaders/model_lightmap_normal_map.frag"); + _lightmapNormalMapProgram.link(); - initProgram(_emissiveNormalMapProgram, _emissiveNormalMapLocations); + initProgram(_lightmapNormalMapProgram, _lightmapNormalMapLocations); - _emissiveSpecularMapProgram.addShaderFromSourceFile(QGLShader::Vertex, - Application::resourcesPath() + "shaders/model.vert"); - _emissiveSpecularMapProgram.addShaderFromSourceFile(QGLShader::Fragment, - Application::resourcesPath() + "shaders/model_emissive_specular_map.frag"); - _emissiveSpecularMapProgram.link(); + _lightmapSpecularMapProgram.addShaderFromSourceFile(QGLShader::Vertex, + Application::resourcesPath() + "shaders/model_lightmap.vert"); + _lightmapSpecularMapProgram.addShaderFromSourceFile(QGLShader::Fragment, + Application::resourcesPath() + "shaders/model_lightmap_specular_map.frag"); + _lightmapSpecularMapProgram.link(); - initProgram(_emissiveSpecularMapProgram, _emissiveSpecularMapLocations); + initProgram(_lightmapSpecularMapProgram, _lightmapSpecularMapLocations); - _emissiveNormalSpecularMapProgram.addShaderFromSourceFile(QGLShader::Vertex, - Application::resourcesPath() + "shaders/model_normal_map.vert"); - _emissiveNormalSpecularMapProgram.addShaderFromSourceFile(QGLShader::Fragment, - Application::resourcesPath() + "shaders/model_emissive_normal_specular_map.frag"); - _emissiveNormalSpecularMapProgram.link(); + _lightmapNormalSpecularMapProgram.addShaderFromSourceFile(QGLShader::Vertex, + Application::resourcesPath() + "shaders/model_lightmap_normal_map.vert"); + _lightmapNormalSpecularMapProgram.addShaderFromSourceFile(QGLShader::Fragment, + Application::resourcesPath() + "shaders/model_lightmap_normal_specular_map.frag"); + _lightmapNormalSpecularMapProgram.link(); - initProgram(_emissiveNormalSpecularMapProgram, _emissiveNormalSpecularMapLocations, 2); - // end emissive + initProgram(_lightmapNormalSpecularMapProgram, _lightmapNormalSpecularMapLocations, 2); + // end lightmap _shadowProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/model_shadow.vert"); @@ -374,36 +387,6 @@ void Model::init() { initSkinProgram(_skinTranslucentProgram, _skinTranslucentLocations); - _skinEmissiveProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/skin_model.vert"); - _skinEmissiveProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + "shaders/model_emissive.frag"); - _skinEmissiveProgram.link(); - - initSkinProgram(_skinEmissiveProgram, _skinEmissiveLocations); - - _skinEmissiveNormalMapProgram.addShaderFromSourceFile(QGLShader::Vertex, - Application::resourcesPath() + "shaders/skin_model_normal_map.vert"); - _skinEmissiveNormalMapProgram.addShaderFromSourceFile(QGLShader::Fragment, - Application::resourcesPath() + "shaders/model_emissive_normal_map.frag"); - _skinEmissiveNormalMapProgram.link(); - - initSkinProgram(_skinEmissiveNormalMapProgram, _skinEmissiveNormalMapLocations); - - _skinEmissiveSpecularMapProgram.addShaderFromSourceFile(QGLShader::Vertex, - Application::resourcesPath() + "shaders/skin_model.vert"); - _skinEmissiveSpecularMapProgram.addShaderFromSourceFile(QGLShader::Fragment, - Application::resourcesPath() + "shaders/model_emissive_specular_map.frag"); - _skinEmissiveSpecularMapProgram.link(); - - initSkinProgram(_skinEmissiveSpecularMapProgram, _skinEmissiveSpecularMapLocations); - - _skinEmissiveNormalSpecularMapProgram.addShaderFromSourceFile(QGLShader::Vertex, - Application::resourcesPath() + "shaders/skin_model_normal_map.vert"); - _skinEmissiveNormalSpecularMapProgram.addShaderFromSourceFile(QGLShader::Fragment, - Application::resourcesPath() + "shaders/model_emissive_normal_specular_map.frag"); - _skinEmissiveNormalSpecularMapProgram.link(); - - initSkinProgram(_skinEmissiveNormalSpecularMapProgram, _skinEmissiveNormalSpecularMapLocations, 2); - } } @@ -716,13 +699,9 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) { opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, true, true, args); opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, false, false, args); - opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, false, true, args); opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, false, args); - opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, true, args); opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, false, false, args); - opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, false, true, args); opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, true, false, args); - opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, true, true, args); // render translucent meshes afterwards //Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(false, true, true); @@ -1666,13 +1645,9 @@ void Model::endScene(RenderMode mode, RenderArgs* args) { opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, true, true, args); */ opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, false, false, args); - opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, false, true, args); opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, false, args); - opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, true, args); opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, false, false, args); - opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, false, true, args); opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, true, false, args); - opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, true, true, args); // render translucent meshes afterwards //Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(false, true, true); @@ -1793,15 +1768,10 @@ void Model::segregateMeshGroups() { _meshesOpaqueTangentsSpecularSkinned.clear(); _meshesOpaqueSpecularSkinned.clear(); - _meshesOpaqueEmissiveTangents.clear(); - _meshesOpaqueEmissive.clear(); - _meshesOpaqueEmissiveTangentsSpecular.clear(); - _meshesOpaqueEmissiveSpecular.clear(); - - _meshesOpaqueEmissiveTangentsSkinned.clear(); - _meshesOpaqueEmissiveSkinned.clear(); - _meshesOpaqueEmissiveTangentsSpecularSkinned.clear(); - _meshesOpaqueEmissiveSpecularSkinned.clear(); + _meshesOpaqueLightmapTangents.clear(); + _meshesOpaqueLightmap.clear(); + _meshesOpaqueLightmapTangentsSpecular.clear(); + _meshesOpaqueLightmapSpecular.clear(); _unsortedMeshesTranslucentTangents.clear(); _unsortedMeshesTranslucent.clear(); @@ -1823,15 +1793,10 @@ void Model::segregateMeshGroups() { _unsortedMeshesOpaqueTangentsSpecularSkinned.clear(); _unsortedMeshesOpaqueSpecularSkinned.clear(); - _unsortedMeshesOpaqueEmissiveTangents.clear(); - _unsortedMeshesOpaqueEmissive.clear(); - _unsortedMeshesOpaqueEmissiveTangentsSpecular.clear(); - _unsortedMeshesOpaqueEmissiveSpecular.clear(); - - _unsortedMeshesOpaqueEmissiveTangentsSkinned.clear(); - _unsortedMeshesOpaqueEmissiveSkinned.clear(); - _unsortedMeshesOpaqueEmissiveTangentsSpecularSkinned.clear(); - _unsortedMeshesOpaqueEmissiveSpecularSkinned.clear(); + _unsortedMeshesOpaqueLightmapTangents.clear(); + _unsortedMeshesOpaqueLightmap.clear(); + _unsortedMeshesOpaqueLightmapTangentsSpecular.clear(); + _unsortedMeshesOpaqueLightmapSpecular.clear(); const FBXGeometry& geometry = _geometry->getFBXGeometry(); const QVector& networkMeshes = _geometry->getMeshes(); @@ -1846,7 +1811,7 @@ void Model::segregateMeshGroups() { bool translucentMesh = networkMesh.getTranslucentPartCount(mesh) == networkMesh.parts.size(); bool hasTangents = !mesh.tangents.isEmpty(); bool hasSpecular = mesh.hasSpecularTexture(); - bool hasEmissive = mesh.hasEmissiveTexture(); + bool haslightmap = mesh.hasEmissiveTexture(); bool isSkinned = state.clusterMatrices.size() > 1; QString materialID; @@ -1865,7 +1830,7 @@ void Model::segregateMeshGroups() { qDebug() << "materialID:" << materialID << "parts:" << mesh.parts.size(); } - if ( !hasEmissive) { + if ( !haslightmap) { if (translucentMesh && !hasTangents && !hasSpecular && !isSkinned) { _unsortedMeshesTranslucent.insertMulti(materialID, i); @@ -1935,35 +1900,20 @@ void Model::segregateMeshGroups() { } else { if (!translucentMesh && !hasTangents && !hasSpecular && !isSkinned) { - _unsortedMeshesOpaqueEmissive.insertMulti(materialID, i); + _unsortedMeshesOpaqueLightmap.insertMulti(materialID, i); } else if (!translucentMesh && hasTangents && !hasSpecular && !isSkinned) { - _unsortedMeshesOpaqueEmissiveTangents.insertMulti(materialID, i); + _unsortedMeshesOpaqueLightmapTangents.insertMulti(materialID, i); } else if (!translucentMesh && hasTangents && hasSpecular && !isSkinned) { - _unsortedMeshesOpaqueEmissiveTangentsSpecular.insertMulti(materialID, i); + _unsortedMeshesOpaqueLightmapTangentsSpecular.insertMulti(materialID, i); } else if (!translucentMesh && !hasTangents && hasSpecular && !isSkinned) { - _unsortedMeshesOpaqueEmissiveSpecular.insertMulti(materialID, i); + _unsortedMeshesOpaqueLightmapSpecular.insertMulti(materialID, i); - } else if (!translucentMesh && hasTangents && !hasSpecular && isSkinned) { - - _unsortedMeshesOpaqueEmissiveTangentsSkinned.insertMulti(materialID, i); - - } else if (!translucentMesh && !hasTangents && !hasSpecular && isSkinned) { - - _unsortedMeshesOpaqueEmissiveSkinned.insertMulti(materialID, i); - - } else if (!translucentMesh && hasTangents && hasSpecular && isSkinned) { - - _unsortedMeshesOpaqueEmissiveTangentsSpecularSkinned.insertMulti(materialID, i); - - } else if (!translucentMesh && !hasTangents && hasSpecular && isSkinned) { - - _unsortedMeshesOpaqueEmissiveSpecularSkinned.insertMulti(materialID, i); } else { qDebug() << "unexpected!!! this mesh didn't fall into any or our groups???"; } @@ -2034,36 +1984,20 @@ void Model::segregateMeshGroups() { _meshesOpaqueSpecularSkinned.append(i); } - foreach(int i, _unsortedMeshesOpaqueEmissive) { - _meshesOpaqueEmissive.append(i); + foreach(int i, _unsortedMeshesOpaqueLightmap) { + _meshesOpaqueLightmap.append(i); } - foreach(int i, _unsortedMeshesOpaqueEmissiveTangents) { - _meshesOpaqueEmissiveTangents.append(i); + foreach(int i, _unsortedMeshesOpaqueLightmapTangents) { + _meshesOpaqueLightmapTangents.append(i); } - foreach(int i, _unsortedMeshesOpaqueEmissiveTangentsSpecular) { - _meshesOpaqueEmissiveTangentsSpecular.append(i); + foreach(int i, _unsortedMeshesOpaqueLightmapTangentsSpecular) { + _meshesOpaqueLightmapTangentsSpecular.append(i); } - foreach(int i, _unsortedMeshesOpaqueEmissiveSpecular) { - _meshesOpaqueEmissiveSpecular.append(i); - } - - foreach(int i, _unsortedMeshesOpaqueEmissiveSkinned) { - _meshesOpaqueEmissiveSkinned.append(i); - } - - foreach(int i, _unsortedMeshesOpaqueEmissiveTangentsSkinned) { - _meshesOpaqueEmissiveTangentsSkinned.append(i); - } - - foreach(int i, _unsortedMeshesOpaqueEmissiveTangentsSpecularSkinned) { - _meshesOpaqueEmissiveTangentsSpecularSkinned.append(i); - } - - foreach(int i, _unsortedMeshesOpaqueEmissiveSpecularSkinned) { - _meshesOpaqueEmissiveSpecularSkinned.append(i); + foreach(int i, _unsortedMeshesOpaqueLightmapSpecular) { + _meshesOpaqueLightmapSpecular.append(i); } _unsortedMeshesTranslucentTangents.clear(); @@ -2086,20 +2020,15 @@ void Model::segregateMeshGroups() { _unsortedMeshesOpaqueTangentsSpecularSkinned.clear(); _unsortedMeshesOpaqueSpecularSkinned.clear(); - _unsortedMeshesOpaqueEmissiveTangents.clear(); - _unsortedMeshesOpaqueEmissive.clear(); - _unsortedMeshesOpaqueEmissiveTangentsSpecular.clear(); - _unsortedMeshesOpaqueEmissiveSpecular.clear(); - - _unsortedMeshesOpaqueEmissiveTangentsSkinned.clear(); - _unsortedMeshesOpaqueEmissiveSkinned.clear(); - _unsortedMeshesOpaqueEmissiveTangentsSpecularSkinned.clear(); - _unsortedMeshesOpaqueEmissiveSpecularSkinned.clear(); + _unsortedMeshesOpaqueLightmapTangents.clear(); + _unsortedMeshesOpaqueLightmap.clear(); + _unsortedMeshesOpaqueLightmapTangentsSpecular.clear(); + _unsortedMeshesOpaqueLightmapSpecular.clear(); _meshGroupsKnown = true; } -QVector* Model::pickMeshList(bool translucent, float alphaThreshold, bool hasEmissive, bool hasTangents, bool hasSpecular, bool isSkinned) { +QVector* Model::pickMeshList(bool translucent, float alphaThreshold, bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned) { PROFILE_RANGE(__FUNCTION__); // depending on which parameters we were called with, pick the correct mesh group to render @@ -2121,39 +2050,31 @@ QVector* Model::pickMeshList(bool translucent, float alphaThreshold, bool h } else if (translucent && !hasTangents && hasSpecular && isSkinned) { whichList = &_meshesTranslucentSpecularSkinned; - } else if (!translucent && !hasEmissive && !hasTangents && !hasSpecular && !isSkinned) { + } else if (!translucent && !hasLightmap && !hasTangents && !hasSpecular && !isSkinned) { whichList = &_meshesOpaque; - } else if (!translucent && !hasEmissive && hasTangents && !hasSpecular && !isSkinned) { + } else if (!translucent && !hasLightmap && hasTangents && !hasSpecular && !isSkinned) { whichList = &_meshesOpaqueTangents; - } else if (!translucent && !hasEmissive && hasTangents && hasSpecular && !isSkinned) { + } else if (!translucent && !hasLightmap && hasTangents && hasSpecular && !isSkinned) { whichList = &_meshesOpaqueTangentsSpecular; - } else if (!translucent && !hasEmissive && !hasTangents && hasSpecular && !isSkinned) { + } else if (!translucent && !hasLightmap && !hasTangents && hasSpecular && !isSkinned) { whichList = &_meshesOpaqueSpecular; - } else if (!translucent && !hasEmissive && hasTangents && !hasSpecular && isSkinned) { + } else if (!translucent && !hasLightmap && hasTangents && !hasSpecular && isSkinned) { whichList = &_meshesOpaqueTangentsSkinned; - } else if (!translucent && !hasEmissive && !hasTangents && !hasSpecular && isSkinned) { + } else if (!translucent && !hasLightmap && !hasTangents && !hasSpecular && isSkinned) { whichList = &_meshesOpaqueSkinned; - } else if (!translucent && !hasEmissive && hasTangents && hasSpecular && isSkinned) { + } else if (!translucent && !hasLightmap && hasTangents && hasSpecular && isSkinned) { whichList = &_meshesOpaqueTangentsSpecularSkinned; - } else if (!translucent && !hasEmissive && !hasTangents && hasSpecular && isSkinned) { + } else if (!translucent && !hasLightmap && !hasTangents && hasSpecular && isSkinned) { whichList = &_meshesOpaqueSpecularSkinned; - } else if (!translucent && hasEmissive && !hasTangents && !hasSpecular && !isSkinned) { - whichList = &_meshesOpaqueEmissive; - } else if (!translucent && hasEmissive && hasTangents && !hasSpecular && !isSkinned) { - whichList = &_meshesOpaqueEmissiveTangents; - } else if (!translucent && hasEmissive && hasTangents && hasSpecular && !isSkinned) { - whichList = &_meshesOpaqueEmissiveTangentsSpecular; - } else if (!translucent && hasEmissive && !hasTangents && hasSpecular && !isSkinned) { - whichList = &_meshesOpaqueEmissiveSpecular; - } else if (!translucent && hasEmissive && hasTangents && !hasSpecular && isSkinned) { - whichList = &_meshesOpaqueEmissiveTangentsSkinned; - } else if (!translucent && hasEmissive && !hasTangents && !hasSpecular && isSkinned) { - whichList = &_meshesOpaqueEmissiveSkinned; - } else if (!translucent && hasEmissive && hasTangents && hasSpecular && isSkinned) { - whichList = &_meshesOpaqueEmissiveTangentsSpecularSkinned; - } else if (!translucent && hasEmissive && !hasTangents && hasSpecular && isSkinned) { - whichList = &_meshesOpaqueEmissiveSpecularSkinned; + } else if (!translucent && hasLightmap && !hasTangents && !hasSpecular && !isSkinned) { + whichList = &_meshesOpaqueLightmap; + } else if (!translucent && hasLightmap && hasTangents && !hasSpecular && !isSkinned) { + whichList = &_meshesOpaqueLightmapTangents; + } else if (!translucent && hasLightmap && hasTangents && hasSpecular && !isSkinned) { + whichList = &_meshesOpaqueLightmapTangentsSpecular; + } else if (!translucent && hasLightmap && !hasTangents && hasSpecular && !isSkinned) { + whichList = &_meshesOpaqueLightmapSpecular; } else { qDebug() << "unexpected!!! this mesh didn't fall into any or our groups???"; @@ -2162,15 +2083,13 @@ QVector* Model::pickMeshList(bool translucent, float alphaThreshold, bool h } void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, - bool hasEmissive, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args, - SkinLocations*& skinLocations, GLenum& specularTextureUnit, GLenum& emissiveTextureUnit) { + bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args, + Locations*& locations, SkinLocations*& skinLocations) { ProgramObject* program = &_program; - Locations* locations = &_locations; + locations = &_locations; ProgramObject* skinProgram = &_skinProgram; skinLocations = &_skinLocations; - specularTextureUnit = 0; - emissiveTextureUnit = 0; if (mode == SHADOW_RENDER_MODE) { program = &_shadowProgram; skinProgram = &_skinShadowProgram; @@ -2181,35 +2100,29 @@ void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, f skinProgram = &_skinTranslucentProgram; skinLocations = &_skinTranslucentLocations; - } else if (hasEmissive) { + } else if (hasLightmap) { if (hasTangents) { if (hasSpecular) { - program = &_emissiveNormalSpecularMapProgram; - locations = &_emissiveNormalSpecularMapLocations; - skinProgram = &_skinEmissiveNormalSpecularMapProgram; - skinLocations = &_skinEmissiveNormalSpecularMapLocations; - specularTextureUnit = GL_TEXTURE2; - emissiveTextureUnit = GL_TEXTURE3; + program = &_lightmapNormalSpecularMapProgram; + locations = &_lightmapNormalSpecularMapLocations; + skinProgram = NULL; + skinLocations = NULL; } else { - program = &_emissiveNormalMapProgram; - locations = &_emissiveNormalMapLocations; - skinProgram = &_skinEmissiveNormalMapProgram; - skinLocations = &_skinEmissiveNormalMapLocations; - emissiveTextureUnit = GL_TEXTURE3; + program = &_lightmapNormalMapProgram; + locations = &_lightmapNormalMapLocations; + skinProgram = NULL; + skinLocations = NULL; } } else if (hasSpecular) { - program = &_emissiveSpecularMapProgram; - locations = &_emissiveSpecularMapLocations; - skinProgram = &_skinEmissiveSpecularMapProgram; - skinLocations = &_skinEmissiveSpecularMapLocations; - specularTextureUnit = GL_TEXTURE1; - emissiveTextureUnit = GL_TEXTURE3; + program = &_lightmapSpecularMapProgram; + locations = &_lightmapSpecularMapLocations; + skinProgram = NULL; + skinLocations = NULL; } else { - program = &_emissiveProgram; - locations = &_emissiveLocations; - skinProgram = &_skinEmissiveProgram; - skinLocations = &_skinEmissiveLocations; - emissiveTextureUnit = GL_TEXTURE3; + program = &_lightmapProgram; + locations = &_lightmapLocations; + skinProgram = NULL; + skinLocations = NULL; } } else { if (hasTangents) { @@ -2218,7 +2131,6 @@ void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, f locations = &_normalSpecularMapLocations; skinProgram = &_skinNormalSpecularMapProgram; skinLocations = &_skinNormalSpecularMapLocations; - specularTextureUnit = GL_TEXTURE2; } else { program = &_normalMapProgram; locations = &_normalMapLocations; @@ -2230,7 +2142,6 @@ void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, f locations = &_specularMapLocations; skinProgram = &_skinSpecularMapProgram; skinLocations = &_skinSpecularMapLocations; - specularTextureUnit = GL_TEXTURE1; } } @@ -2240,6 +2151,7 @@ void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, f if (isSkinned) { activeProgram = skinProgram; activeLocations = skinLocations; + locations = skinLocations; } // This code replace the "bind()" on the QGLProgram if (!activeProgram->isLinked()) { @@ -2251,27 +2163,26 @@ void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, f } int Model::renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, - bool hasEmissive, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args) { + bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args) { PROFILE_RANGE(__FUNCTION__); int meshPartsRendered = 0; bool pickProgramsNeeded = true; + Locations* locations; SkinLocations* skinLocations; - GLenum specularTextureUnit; - GLenum emissiveTextureUnit; foreach(Model* model, _modelsInScene) { - QVector* whichList = model->pickMeshList(translucent, alphaThreshold, hasEmissive, hasTangents, hasSpecular, isSkinned); + QVector* whichList = model->pickMeshList(translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned); if (whichList) { QVector& list = *whichList; if (list.size() > 0) { if (pickProgramsNeeded) { - pickPrograms(batch, mode, translucent, alphaThreshold, hasEmissive, hasTangents, hasSpecular, isSkinned, args, skinLocations, specularTextureUnit, emissiveTextureUnit); + pickPrograms(batch, mode, translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned, args, locations, skinLocations); pickProgramsNeeded = false; } model->setupBatchTransform(batch); - meshPartsRendered += model->renderMeshesFromList(list, batch, mode, translucent, alphaThreshold, args, skinLocations, specularTextureUnit, emissiveTextureUnit); + meshPartsRendered += model->renderMeshesFromList(list, batch, mode, translucent, alphaThreshold, args, locations, skinLocations); GLBATCH(glPopMatrix)(); } } @@ -2284,12 +2195,12 @@ int Model::renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool } int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, - bool hasEmissive, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args) { + bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args) { PROFILE_RANGE(__FUNCTION__); int meshPartsRendered = 0; - QVector* whichList = pickMeshList(translucent, alphaThreshold, hasEmissive, hasTangents, hasSpecular, isSkinned); + QVector* whichList = pickMeshList(translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned); if (!whichList) { qDebug() << "unexpected!!! we don't know which list of meshes to render..."; @@ -2302,11 +2213,10 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl return 0; } + Locations* locations; SkinLocations* skinLocations; - GLenum specularTextureUnit; - GLenum emissiveTextureUnit; - pickPrograms(batch, mode, translucent, alphaThreshold, hasEmissive, hasTangents, hasSpecular, isSkinned, args, skinLocations, specularTextureUnit, emissiveTextureUnit); - meshPartsRendered = renderMeshesFromList(list, batch, mode, translucent, alphaThreshold, args, skinLocations, specularTextureUnit, emissiveTextureUnit); + pickPrograms(batch, mode, translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned, args, locations, skinLocations); + meshPartsRendered = renderMeshesFromList(list, batch, mode, translucent, alphaThreshold, args, locations, skinLocations); GLBATCH(glUseProgram)(0); return meshPartsRendered; @@ -2314,7 +2224,7 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, RenderArgs* args, - SkinLocations* skinLocations, GLenum specularTextureUnit, GLenum emissiveTextureUnit) { + Locations* locations, SkinLocations* skinLocations) { PROFILE_RANGE(__FUNCTION__); bool dontCullOutOfViewMeshParts = Menu::getInstance()->isOptionChecked(MenuOption::DontCullOutOfViewMeshParts); bool cullTooSmallMeshParts = !Menu::getInstance()->isOptionChecked(MenuOption::DontCullTooSmallMeshParts); @@ -2431,7 +2341,7 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod GLBATCH(glMaterialfv)(GL_FRONT, GL_DIFFUSE, (const float*)&diffuse); GLBATCH(glMaterialfv)(GL_FRONT, GL_SPECULAR, (const float*)&specular); GLBATCH(glMaterialf)(GL_FRONT, GL_SHININESS, (part.shininess > 128.0f ? 128.0f: part.shininess)); - + Texture* diffuseMap = networkPart.diffuseTexture.data(); if (mesh.isEye && diffuseMap) { diffuseMap = (_dilatedTextures[i][j] = @@ -2439,7 +2349,18 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod } GLBATCH(glBindTexture)(GL_TEXTURE_2D, !diffuseMap ? Application::getInstance()->getTextureCache()->getWhiteTextureID() : diffuseMap->getID()); - + + if (locations->texcoordMatrices >= 0) { + glm::mat4 texcoordTransform[2]; + if (!part.diffuseTexture.transform.isIdentity()) { + part.diffuseTexture.transform.getMatrix(texcoordTransform[0]); + } + if (!part.emissiveTexture.transform.isIdentity()) { + part.emissiveTexture.transform.getMatrix(texcoordTransform[1]); + } + GLBATCH(glUniformMatrix4fv)(locations->texcoordMatrices, 2, false, (const float*) &texcoordTransform); + } + if (!mesh.tangents.isEmpty()) { GLBATCH(glActiveTexture)(GL_TEXTURE1); Texture* normalMap = networkPart.normalTexture.data(); @@ -2448,19 +2369,20 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod GLBATCH(glActiveTexture)(GL_TEXTURE0); } - if (specularTextureUnit) { - GLBATCH(glActiveTexture)(specularTextureUnit); + if (locations->specularTextureUnit >= 0) { + GLBATCH(glActiveTexture)(GL_TEXTURE0 + locations->specularTextureUnit); Texture* specularMap = networkPart.specularTexture.data(); GLBATCH(glBindTexture)(GL_TEXTURE_2D, !specularMap ? Application::getInstance()->getTextureCache()->getWhiteTextureID() : specularMap->getID()); GLBATCH(glActiveTexture)(GL_TEXTURE0); } - if (emissiveTextureUnit) { - GLBATCH(glActiveTexture)(emissiveTextureUnit); + if (locations->emissiveTextureUnit >= 0) { + GLBATCH(glActiveTexture)(GL_TEXTURE0 + locations->emissiveTextureUnit); Texture* emissiveMap = networkPart.emissiveTexture.data(); GLBATCH(glBindTexture)(GL_TEXTURE_2D, !emissiveMap ? Application::getInstance()->getTextureCache()->getWhiteTextureID() : emissiveMap->getID()); + // GLBATCH(glBindTexture)(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getWhiteTextureID()); GLBATCH(glActiveTexture)(GL_TEXTURE0); } @@ -2498,14 +2420,14 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod GLBATCH(glActiveTexture)(GL_TEXTURE0); } - if (specularTextureUnit) { - GLBATCH(glActiveTexture)(specularTextureUnit); + if (locations->specularTextureUnit >= 0) { + GLBATCH(glActiveTexture)(GL_TEXTURE0 + locations->specularTextureUnit); GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0); GLBATCH(glActiveTexture)(GL_TEXTURE0); } - if (emissiveTextureUnit) { - GLBATCH(glActiveTexture)(emissiveTextureUnit); + if (locations->emissiveTextureUnit >= 0) { + GLBATCH(glActiveTexture)(GL_TEXTURE0 + locations->emissiveTextureUnit); GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0); GLBATCH(glActiveTexture)(GL_TEXTURE0); } diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index c1ae190a1e..7a3457423e 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -304,10 +304,10 @@ private: static ProgramObject _normalSpecularMapProgram; static ProgramObject _translucentProgram; - static ProgramObject _emissiveProgram; - static ProgramObject _emissiveNormalMapProgram; - static ProgramObject _emissiveSpecularMapProgram; - static ProgramObject _emissiveNormalSpecularMapProgram; + static ProgramObject _lightmapProgram; + static ProgramObject _lightmapNormalMapProgram; + static ProgramObject _lightmapSpecularMapProgram; + static ProgramObject _lightmapNormalSpecularMapProgram; static ProgramObject _shadowProgram; @@ -317,11 +317,6 @@ private: static ProgramObject _skinNormalSpecularMapProgram; static ProgramObject _skinTranslucentProgram; - static ProgramObject _skinEmissiveProgram; - static ProgramObject _skinEmissiveNormalMapProgram; - static ProgramObject _skinEmissiveSpecularMapProgram; - static ProgramObject _skinEmissiveNormalSpecularMapProgram; - static ProgramObject _skinShadowProgram; static int _normalMapTangentLocation; @@ -331,6 +326,9 @@ private: public: int tangent; int alphaThreshold; + int texcoordMatrices; + int specularTextureUnit; + int emissiveTextureUnit; }; static Locations _locations; @@ -339,10 +337,10 @@ private: static Locations _normalSpecularMapLocations; static Locations _translucentLocations; - static Locations _emissiveLocations; - static Locations _emissiveNormalMapLocations; - static Locations _emissiveSpecularMapLocations; - static Locations _emissiveNormalSpecularMapLocations; + static Locations _lightmapLocations; + static Locations _lightmapNormalMapLocations; + static Locations _lightmapSpecularMapLocations; + static Locations _lightmapNormalSpecularMapLocations; static void initProgram(ProgramObject& program, Locations& locations, int specularTextureUnit = 1); @@ -350,7 +348,7 @@ private: public: int clusterMatrices; int clusterIndices; - int clusterWeights; + int clusterWeights; }; static SkinLocations _skinLocations; @@ -360,11 +358,6 @@ private: static SkinLocations _skinShadowLocations; static SkinLocations _skinTranslucentLocations; - static SkinLocations _skinEmissiveLocations; - static SkinLocations _skinEmissiveNormalMapLocations; - static SkinLocations _skinEmissiveSpecularMapLocations; - static SkinLocations _skinEmissiveNormalSpecularMapLocations; - static void initSkinProgram(ProgramObject& program, SkinLocations& locations, int specularTextureUnit = 1); QVector _calculatedMeshBoxes; @@ -396,15 +389,10 @@ private: QMap _unsortedMeshesOpaqueTangentsSpecularSkinned; QMap _unsortedMeshesOpaqueSpecularSkinned; - QMap _unsortedMeshesOpaqueEmissive; - QMap _unsortedMeshesOpaqueEmissiveTangents; - QMap _unsortedMeshesOpaqueEmissiveTangentsSpecular; - QMap _unsortedMeshesOpaqueEmissiveSpecular; - - QMap _unsortedMeshesOpaqueEmissiveSkinned; - QMap _unsortedMeshesOpaqueEmissiveTangentsSkinned; - QMap _unsortedMeshesOpaqueEmissiveTangentsSpecularSkinned; - QMap _unsortedMeshesOpaqueEmissiveSpecularSkinned; + QMap _unsortedMeshesOpaqueLightmap; + QMap _unsortedMeshesOpaqueLightmapTangents; + QMap _unsortedMeshesOpaqueLightmapTangentsSpecular; + QMap _unsortedMeshesOpaqueLightmapSpecular; QVector _meshesTranslucent; QVector _meshesTranslucentTangents; @@ -426,15 +414,11 @@ private: QVector _meshesOpaqueTangentsSpecularSkinned; QVector _meshesOpaqueSpecularSkinned; - QVector _meshesOpaqueEmissive; - QVector _meshesOpaqueEmissiveTangents; - QVector _meshesOpaqueEmissiveTangentsSpecular; - QVector _meshesOpaqueEmissiveSpecular; + QVector _meshesOpaqueLightmap; + QVector _meshesOpaqueLightmapTangents; + QVector _meshesOpaqueLightmapTangentsSpecular; + QVector _meshesOpaqueLightmapSpecular; - QVector _meshesOpaqueEmissiveSkinned; - QVector _meshesOpaqueEmissiveTangentsSkinned; - QVector _meshesOpaqueEmissiveTangentsSpecularSkinned; - QVector _meshesOpaqueEmissiveSpecularSkinned; // Scene rendering support static QVector _modelsInScene; @@ -447,19 +431,19 @@ private: void renderSetup(RenderArgs* args); bool renderCore(float alpha, RenderMode mode, RenderArgs* args); int renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, - bool hasEmissive, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args = NULL); + bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args = NULL); void setupBatchTransform(gpu::Batch& batch); - QVector* pickMeshList(bool translucent, float alphaThreshold, bool hasEmissive, bool hasTangents, bool hasSpecular, bool isSkinned); + QVector* pickMeshList(bool translucent, float alphaThreshold, bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned); int renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, - RenderArgs* args, SkinLocations* skinLocations, GLenum specularTextureUnit, GLenum emissiveTextureUnit); + RenderArgs* args, Locations* locations, SkinLocations* skinLocations); static void pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, - bool hasEmissive, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args, - SkinLocations*& skinLocations, GLenum& specularTextureUnit, GLenum& emissiveTextureUnit); + bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args, + Locations*& locations, SkinLocations*& skinLocations); static int renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, - bool hasEmissive, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args); + bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args); }; diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 2a97c50fea..130f1db550 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -32,6 +32,48 @@ using namespace std; +struct TextureParam { + glm::vec2 UVTranslation; + glm::vec2 UVScaling; + glm::vec4 cropping; + std::string UVSet; + + glm::vec3 translation; + glm::vec3 rotation; + glm::vec3 scaling; + uint8_t alphaSource; + uint8_t currentTextureBlendMode; + bool useMaterial; + + template + bool assign(T& ref, const T& v) { + if (ref == v) { + return false; + } else { + ref = v; + isDefault = false; + return true; + } + } + + bool isDefault; + + TextureParam() : + UVTranslation(0.0f), + UVScaling(1.0f), + cropping(0.0f), + UVSet("map1"), + translation(0.0f), + rotation(0.0f), + scaling(1.0f), + alphaSource(0), + currentTextureBlendMode(0), + useMaterial(true), + isDefault(true) + {} +}; + + bool FBXMesh::hasSpecularTexture() const { foreach (const FBXMeshPart& part, parts) { if (!part.specularTexture.filename.isEmpty()) { @@ -718,6 +760,7 @@ class Vertex { public: int originalIndex; glm::vec2 texCoord; + glm::vec2 texCoord1; }; uint qHash(const Vertex& vertex, uint seed = 0) { @@ -725,7 +768,7 @@ uint qHash(const Vertex& vertex, uint seed = 0) { } bool operator==(const Vertex& v1, const Vertex& v2) { - return v1.originalIndex == v2.originalIndex && v1.texCoord == v2.texCoord; + return v1.originalIndex == v2.originalIndex && v1.texCoord == v2.texCoord && v1.texCoord1 == v2.texCoord1; } class ExtractedMesh { @@ -734,6 +777,16 @@ public: QMultiHash newIndices; QVector > blendshapeIndexMaps; QVector > partMaterialTextures; + QHash texcoordSetMap; + std::map texcoordSetMap2; +}; + +class AttributeData { +public: + QVector texCoords; + QVector texCoordIndices; + std::string name; + int index; }; class MeshData { @@ -748,6 +801,8 @@ public: QVector texCoordIndices; QHash indices; + + std::vector attributes; }; void appendIndex(MeshData& data, QVector& indices, int index) { @@ -789,6 +844,20 @@ void appendIndex(MeshData& data, QVector& indices, int index) { vertex.texCoord = data.texCoords.at(texCoordIndex); } } + + bool hasMoreTexcoords = (data.attributes.size() > 1); + if (hasMoreTexcoords) { + if (data.attributes[1].texCoordIndices.empty()) { + if (index < data.attributes[1].texCoords.size()) { + vertex.texCoord1 = data.attributes[1].texCoords.at(index); + } + } else if (index < data.attributes[1].texCoordIndices.size()) { + int texCoordIndex = data.attributes[1].texCoordIndices.at(index); + if (texCoordIndex >= 0 && texCoordIndex < data.attributes[1].texCoords.size()) { + vertex.texCoord1 = data.attributes[1].texCoords.at(texCoordIndex); + } + } + } QHash::const_iterator it = data.indices.find(vertex); if (it == data.indices.constEnd()) { @@ -799,7 +868,7 @@ void appendIndex(MeshData& data, QVector& indices, int index) { data.extracted.mesh.vertices.append(position); data.extracted.mesh.normals.append(normal); data.extracted.mesh.texCoords.append(vertex.texCoord); - + if (hasMoreTexcoords) { data.extracted.mesh.texCoords1.append(vertex.texCoord1); } } else { indices.append(*it); data.extracted.mesh.normals[*it] += normal; @@ -838,13 +907,61 @@ ExtractedMesh extractMesh(const FBXNode& object) { // hack to work around wacky Makehuman exports data.normalsByVertex = true; } - } else if (child.name == "LayerElementUV" && child.properties.at(0).toInt() == 0) { - foreach (const FBXNode& subdata, child.children) { - if (subdata.name == "UV") { - data.texCoords = createVec2Vector(getDoubleVector(subdata)); + } else if (child.name == "LayerElementUV") { + if (child.properties.at(0).toInt() == 0) { + AttributeData attrib; + attrib.index = child.properties.at(0).toInt(); + int unknown = 0; + foreach (const FBXNode& subdata, child.children) { + if (subdata.name == "UV") { + data.texCoords = createVec2Vector(getDoubleVector(subdata)); + attrib.texCoords = createVec2Vector(getDoubleVector(subdata)); + } else if (subdata.name == "UVIndex") { + data.texCoordIndices = getIntVector(subdata); + attrib.texCoordIndices = getIntVector(subdata); + } else if (subdata.name == "Name") { + attrib.name = subdata.properties.at(0).toString().toStdString(); + } else { + std::string subname = subdata.name.data(); + if (subdata.name == "Version") { + } else if (subdata.name == "MappingInformationType") { + } else if (subdata.name == "ReferenceInformationType") { + } else { + unknown++; + } + } + } + data.extracted.texcoordSetMap.insert(QString(attrib.name.c_str()), data.attributes.size()); + data.attributes.push_back(attrib); + } else { + AttributeData attrib; + attrib.index = child.properties.at(0).toInt(); + int unknown = 0; + foreach (const FBXNode& subdata, child.children) { + if (subdata.name == "UV") { + attrib.texCoords = createVec2Vector(getDoubleVector(subdata)); + } else if (subdata.name == "UVIndex") { + attrib.texCoordIndices = getIntVector(subdata); + } else if (subdata.name == "Name") { + attrib.name = subdata.properties.at(0).toString().toStdString(); + } else { + std::string subname = subdata.name.data(); + if (subdata.name == "Version") { + } else if (subdata.name == "MappingInformationType") { + } else if (subdata.name == "ReferenceInformationType") { + } else { + unknown++; + } + } + } - } else if (subdata.name == "UVIndex") { - data.texCoordIndices = getIntVector(subdata); + QHash::iterator it = data.extracted.texcoordSetMap.find(QString(attrib.name.c_str())); + if (it == data.extracted.texcoordSetMap.end()) { + data.extracted.texcoordSetMap.insert(QString(attrib.name.c_str()), data.attributes.size()); + data.attributes.push_back(attrib); + } else { + // WTF same names for different UVs? + unknown = data.attributes.size(); } } } else if (child.name == "LayerElementMaterial") { @@ -1014,11 +1131,27 @@ public: FBXTexture getTexture(const QString& textureID, const QHash& textureNames, const QHash& textureFilenames, - const QHash& textureContent) { + const QHash& textureContent, + const QHash& textureParams) { FBXTexture texture; texture.filename = textureFilenames.value(textureID); texture.name = textureNames.value(textureID); texture.content = textureContent.value(texture.filename); + texture.transform.setIdentity(); + texture.texcoordSet = 0; + QHash::const_iterator it = textureParams.constFind(textureID); + if (it != textureParams.end()) { + const TextureParam& p = (*it); + texture.transform.setTranslation(p.translation); + texture.transform.setRotation(glm::quat(glm::radians(p.rotation))); + texture.transform.setScale(p.scaling); + if (p.UVSet != "map1" || (p.UVSet != "UVSet0")) { + texture.texcoordSet = 1; + } + + texture.texcoordSetName = p.UVSet; + + } return texture; } @@ -1034,6 +1167,23 @@ bool checkMaterialsHaveTextures(const QHash& materials, return false; } +int matchTextureUVSetToAttributeChannel(const std::string& texUVSetName, const QHash& texcoordChannels) { + if (texUVSetName.empty()) { + return 0; + } else { + QHash::const_iterator tcUnit = texcoordChannels.find(QString(texUVSetName.c_str())); + if (tcUnit != texcoordChannels.end()) { + int channel = (*tcUnit); + if (channel >= 2) { + channel = 0; + } + return channel; + } else { + return 0; + } + } +} + FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) { QHash meshes; QHash modelIDsToNames; @@ -1048,6 +1198,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) QHash animationCurves; QHash textureNames; QHash textureFilenames; + QHash textureParams; QHash textureContent; QHash materials; QHash typeFlags; @@ -1109,7 +1260,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) } } QMultiHash blendshapeChannelIndices; - + int unknown = 0; FBXGeometry geometry; float unitScaleFactor = 1.0f; foreach (const FBXNode& child, node.children) { @@ -1312,7 +1463,10 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) models.insert(getID(object.properties), model); } else if (object.name == "Texture") { + TextureParam tex; + bool texparam = false; foreach (const FBXNode& subobject, object.children) { + std::string subname = subobject.name.data(); if (subobject.name == "RelativeFilename") { // trim off any path information QByteArray filename = subobject.properties.at(0).toByteArray(); @@ -1323,8 +1477,60 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) QString name = QString(subobject.properties.at(0).toByteArray()); name = name.left(name.indexOf('[')); textureNames.insert(getID(object.properties), name); + } else if (subobject.name == "Texture_Alpha_Source") { + tex.assign(tex.alphaSource, subobject.properties.at(0).value()); + } else if (subobject.name == "ModelUVTranslation") { + tex.assign(tex.UVTranslation, glm::vec2(subobject.properties.at(0).value(), + subobject.properties.at(1).value())); + } else if (subobject.name == "ModelUVScaling") { + tex.assign(tex.UVScaling, glm::vec2(subobject.properties.at(0).value(), + subobject.properties.at(1).value())); + } else if (subobject.name == "Cropping") { + tex.assign(tex.cropping, glm::vec4(subobject.properties.at(0).value(), + subobject.properties.at(1).value(), + subobject.properties.at(2).value(), + subobject.properties.at(3).value())); + } else if (subobject.name == "Properties70") { + + QByteArray propertyName; + int index; + propertyName = "P"; + index = 4; + foreach (const FBXNode& property, subobject.children) { + if (property.name == propertyName) { + QString v = property.properties.at(0).toString(); + std::string propName = v.toStdString(); + if (property.properties.at(0) == "UVSet") { + tex.assign(tex.UVSet, property.properties.at(index).toString().toStdString()); + } else if (property.properties.at(0) == "CurrentTextureBlendMode") { + tex.assign(tex.currentTextureBlendMode, property.properties.at(index).value()); + } else if (property.properties.at(0) == "UseMaterial") { + tex.assign(tex.useMaterial, property.properties.at(index).value()); + } else if (property.properties.at(0) == "Translation") { + tex.assign(tex.translation, getVec3(property.properties, index)); + } else if (property.properties.at(0) == "Rotation") { + tex.assign(tex.rotation, getVec3(property.properties, index)); + } else if (property.properties.at(0) == "Scaling") { + tex.assign(tex.scaling, getVec3(property.properties, index)); + } else { + unknown++; + } + } + } + } else { + if (subobject.name == "Type") { + } else if (subobject.name == "Version") { + } else if (subobject.name == "FileName") { + } else if (subobject.name == "Media") { + } else { + unknown++; + } } } + + if (!tex.isDefault) { + textureParams.insert(getID(object.properties), tex); + } } else if (object.name == "Video") { QByteArray filename; QByteArray content; @@ -1670,47 +1876,63 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) const QString& childID = children.at(i); if (materials.contains(childID)) { Material material = materials.value(childID); - + bool detectDifferentUVs = false; FBXTexture diffuseTexture; QString diffuseTextureID = diffuseTextures.value(childID); if (!diffuseTextureID.isNull()) { - diffuseTexture = getTexture(diffuseTextureID, textureNames, textureFilenames, textureContent); + diffuseTexture = getTexture(diffuseTextureID, textureNames, textureFilenames, textureContent, textureParams); // FBX files generated by 3DSMax have an intermediate texture parent, apparently foreach (const QString& childTextureID, childMap.values(diffuseTextureID)) { if (textureFilenames.contains(childTextureID)) { - diffuseTexture = getTexture(diffuseTextureID, textureNames, textureFilenames, textureContent); + diffuseTexture = getTexture(diffuseTextureID, textureNames, textureFilenames, textureContent, textureParams); } } + diffuseTexture.texcoordSet = matchTextureUVSetToAttributeChannel(diffuseTexture.texcoordSetName, extracted.texcoordSetMap); + + detectDifferentUVs = (diffuseTexture.texcoordSet != 0) || (!diffuseTexture.transform.isIdentity()); } FBXTexture normalTexture; QString bumpTextureID = bumpTextures.value(childID); if (!bumpTextureID.isNull()) { - normalTexture = getTexture(bumpTextureID, textureNames, textureFilenames, textureContent); + normalTexture = getTexture(bumpTextureID, textureNames, textureFilenames, textureContent, textureParams); generateTangents = true; + + normalTexture.texcoordSet = matchTextureUVSetToAttributeChannel(normalTexture.texcoordSetName, extracted.texcoordSetMap); + + detectDifferentUVs |= (normalTexture.texcoordSet != 0) || (!normalTexture.transform.isIdentity()); } FBXTexture specularTexture; QString specularTextureID = specularTextures.value(childID); if (!specularTextureID.isNull()) { - specularTexture = getTexture(specularTextureID, textureNames, textureFilenames, textureContent); + specularTexture = getTexture(specularTextureID, textureNames, textureFilenames, textureContent, textureParams); + specularTexture.texcoordSet = matchTextureUVSetToAttributeChannel(specularTexture.texcoordSetName, extracted.texcoordSetMap); + detectDifferentUVs |= (specularTexture.texcoordSet != 0) || (!specularTexture.transform.isIdentity()); } FBXTexture emissiveTexture; QString emissiveTextureID = emissiveTextures.value(childID); if (!emissiveTextureID.isNull()) { - emissiveTexture = getTexture(emissiveTextureID, textureNames, textureFilenames, textureContent); + emissiveTexture = getTexture(emissiveTextureID, textureNames, textureFilenames, textureContent, textureParams); // FBX files generated by 3DSMax have an intermediate texture parent, apparently foreach (const QString& childTextureID, childMap.values(diffuseTextureID)) { if (textureFilenames.contains(childTextureID)) { - emissiveTexture = getTexture(emissiveTextureID, textureNames, textureFilenames, textureContent); + emissiveTexture = getTexture(emissiveTextureID, textureNames, textureFilenames, textureContent, textureParams); } } + + emissiveTexture.texcoordSet = matchTextureUVSetToAttributeChannel(emissiveTexture.texcoordSetName, extracted.texcoordSetMap); + + detectDifferentUVs |= (emissiveTexture.texcoordSet != 0) || (!emissiveTexture.transform.isIdentity()); + } + + if (detectDifferentUVs) { + detectDifferentUVs = false; } - for (int j = 0; j < extracted.partMaterialTextures.size(); j++) { if (extracted.partMaterialTextures.at(j).first == materialIndex) { FBXMeshPart& part = extracted.mesh.parts[j]; @@ -1737,7 +1959,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) materialIndex++; } else if (textureFilenames.contains(childID)) { - FBXTexture texture = getTexture(childID, textureNames, textureFilenames, textureContent); + FBXTexture texture = getTexture(childID, textureNames, textureFilenames, textureContent, textureParams); for (int j = 0; j < extracted.partMaterialTextures.size(); j++) { int partTexture = extracted.partMaterialTextures.at(j).second; if (partTexture == textureIndex && !(partTexture == 0 && materialsHaveTextures)) { diff --git a/libraries/fbx/src/FBXReader.h b/libraries/fbx/src/FBXReader.h index 892dd7a2fd..60e8ea2448 100644 --- a/libraries/fbx/src/FBXReader.h +++ b/libraries/fbx/src/FBXReader.h @@ -19,6 +19,7 @@ #include #include +#include #include #include @@ -102,6 +103,10 @@ public: QString name; QByteArray filename; QByteArray content; + + Transform transform; + int texcoordSet; + std::string texcoordSetName; }; /// A single part of a mesh (with the same material). @@ -136,13 +141,14 @@ public: QVector tangents; QVector colors; QVector texCoords; + QVector texCoords1; QVector clusterIndices; QVector clusterWeights; QVector clusters; Extents meshExtents; - + bool isEye; QVector blendshapes; diff --git a/libraries/shared/src/Transform.h b/libraries/shared/src/Transform.h index 5ce5667a81..4adeccb46f 100644 --- a/libraries/shared/src/Transform.h +++ b/libraries/shared/src/Transform.h @@ -136,7 +136,10 @@ protected: void invalidCache() const { _flags.set(FLAG_CACHE_INVALID, true); } void flagTranslation() { _flags.set(FLAG_TRANSLATION, true); } + void unflagTranslation() { _flags.set(FLAG_TRANSLATION, false); } + void flagRotation() { _flags.set(FLAG_ROTATION, true); } + void unflagRotation() { _flags.set(FLAG_ROTATION, false); } void flagScaling() { _flags.set(FLAG_SCALING, true); } void unflagScaling() { _flags.set(FLAG_SCALING, false); } @@ -162,17 +165,23 @@ inline const Transform::Vec3& Transform::getTranslation() const { inline void Transform::setTranslation(const Vec3& translation) { invalidCache(); - flagTranslation(); + if (translation == Vec3()) { + unflagTranslation(); + } else { + flagTranslation(); + } _translation = translation; } inline void Transform::preTranslate(const Vec3& translation) { + if (translation == Vec3() ) return; invalidCache(); flagTranslation(); _translation += translation; } inline void Transform::postTranslate(const Vec3& translation) { + if (translation == Vec3() ) return; invalidCache(); flagTranslation(); @@ -192,11 +201,16 @@ inline const Transform::Quat& Transform::getRotation() const { inline void Transform::setRotation(const Quat& rotation) { invalidCache(); - flagRotation(); + if (rotation == Quat()) { + unflagRotation(); + } else { + flagRotation(); + } _rotation = rotation; } inline void Transform::preRotate(const Quat& rotation) { + if (rotation == Quat()) return; invalidCache(); if (isRotating()) { _rotation = rotation * _rotation; @@ -204,10 +218,12 @@ inline void Transform::preRotate(const Quat& rotation) { _rotation = rotation; } flagRotation(); + _translation = glm::rotate(rotation, _translation); } inline void Transform::postRotate(const Quat& rotation) { + if (rotation == Quat()) return; invalidCache(); if (isNonUniform()) { From 2edd2525763245693e8aa693a5fe8394b95e6a83 Mon Sep 17 00:00:00 2001 From: Adrianl3d Date: Sat, 22 Nov 2014 21:47:14 +1000 Subject: [PATCH 044/502] Fix persist time Set persist time to 10 secs --- examples/notifications.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/notifications.js b/examples/notifications.js index 3357d55096..3d0b05521d 100644 --- a/examples/notifications.js +++ b/examples/notifications.js @@ -63,7 +63,7 @@ var textColor = { red: 228, green: 228, blue: 228}; // text color var backColor = { red: 38, green: 38, blue: 38}; // background color var backgroundAlpha = 0; var fontSize = 12.0; -var persistTime = 5.0; // time in seconds before notification fades +var persistTime = 10.0; // time in seconds before notification fades var clickedText = false; var frame = 0; var ourWidth = Window.innerWidth; From e12f64bae41fe6d037fa4d2e4589048c56b7182d Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Sun, 23 Nov 2014 17:15:14 +0100 Subject: [PATCH 045/502] virtual-keyboard: - added keycodes - resizes the example text entity based on text size - adds the author of the text entity in the bottom right corner --- examples/virtualKeyboard.js | 171 +++++++++++++++++++++--------------- 1 file changed, 99 insertions(+), 72 deletions(-) diff --git a/examples/virtualKeyboard.js b/examples/virtualKeyboard.js index 5829a4fd2b..cd2ce9f7ba 100644 --- a/examples/virtualKeyboard.js +++ b/examples/virtualKeyboard.js @@ -38,8 +38,6 @@ const VIEW_ANGLE = 30.0; const VIEW_ANGLE_BY_TWO = VIEW_ANGLE / 2; const SPAWN_DISTANCE = 1; -const DEFAULT_TEXT_DIMENSION_X = 1; -const DEFAULT_TEXT_DIMENSION_Y = 1; const DEFAULT_TEXT_DIMENSION_Z = 0.02; const BOUND_X = 0; @@ -50,11 +48,18 @@ const BOUND_H = 3; const KEY_STATE_LOWER = 0; const KEY_STATE_UPPER = 1; +const TEXT_MARGIN_TOP = 0.15; +const TEXT_MARGIN_LEFT = 0.15; +const TEXT_MARGIN_RIGHT = 0.17; +const TEXT_MARGIN_BOTTOM = 0.17; + var windowDimensions = Controller.getViewportDimensions(); var cursor = null; var keyboard = new Keyboard(); var text = null; var textText = ""; +var textSizeMeasureOverlay = Overlays.addOverlay("text3d", {visible: false}); + function appendChar(char) { textText += char; updateTextOverlay(); @@ -88,15 +93,36 @@ keyboard.onKeyRelease = function(event) { var position = Vec3.sum(MyAvatar.position, Vec3.multiply(Quat.getFront(MyAvatar.orientation), SPAWN_DISTANCE)); + var textLines = textText.split("\n"); + var maxLineWidth = 0; + for (textLine in textLines) { + var lineWidth = Overlays.textWidth(textSizeMeasureOverlay, textLines[textLine]); + if (lineWidth > maxLineWidth) { + maxLineWidth = lineWidth; + } + } + var usernameLine = "--" + GlobalServices.myUsername; + var usernameWidth = Overlays.textWidth(textSizeMeasureOverlay, usernameLine); + if (maxLineWidth < usernameWidth) { + maxLineWidth = usernameWidth; + } else { + var spaceableWidth = maxLineWidth - usernameWidth; + var spaceWidth = Overlays.textWidth(textSizeMeasureOverlay, " "); + var numberOfSpaces = Math.floor(spaceableWidth / spaceWidth); + for (var i = 0; i < numberOfSpaces; i++) { + usernameLine = " " + usernameLine; + } + } + var dimension_x = maxLineWidth + TEXT_MARGIN_RIGHT + TEXT_MARGIN_LEFT; if (position.x > 0 && position.y > 0 && position.z > 0) { Entities.addEntity({ type: "Text", + rotation: MyAvatar.orientation, position: position, - dimensions: { x: DEFAULT_TEXT_DIMENSION_X, y: DEFAULT_TEXT_DIMENSION_Y, z: DEFAULT_TEXT_DIMENSION_Z }, + dimensions: { x: dimension_x, y: (textLines.length + 1) * 0.14 + TEXT_MARGIN_TOP + TEXT_MARGIN_BOTTOM, z: DEFAULT_TEXT_DIMENSION_Z }, backgroundColor: { red: 0, green: 0, blue: 0 }, textColor: { red: 255, green: 255, blue: 255 }, - text: textText, - lineHight: "0.1" + text: textText + "\n" + usernameLine }); } textText = ""; @@ -363,85 +389,85 @@ function Keyboard() { // coords [[x,y,w,h],[x,y,w,h]] // states array of 1 or 2 objects [lowercase, uppercase] each object contains a charCode and a char var keyProperties = [ - {bounds: [[12, 12, 65, 52]], states: [{charCode: 192, char: '~'}]}, - {bounds: [[84, 12, 65, 52]], states: [{charCode: 192, char: '!'}]}, - {bounds: [[156, 12, 65, 52]], states: [{charCode: 192, char: '@'}]}, - {bounds: [[228, 12, 65, 52]], states: [{charCode: 192, char: '#'}]}, - {bounds: [[300, 12, 65, 52]], states: [{charCode: 192, char: '$'}]}, - {bounds: [[372, 12, 65, 52]], states: [{charCode: 192, char: '%'}]}, - {bounds: [[445, 12, 65, 52]], states: [{charCode: 192, char: '^'}]}, - {bounds: [[517, 12, 65, 52]], states: [{charCode: 192, char: '&'}]}, - {bounds: [[589, 12, 65, 52]], states: [{charCode: 192, char: '*'}]}, - {bounds: [[662, 12, 65, 52]], states: [{charCode: 192, char: '('}]}, - {bounds: [[734, 12, 65, 52]], states: [{charCode: 192, char: ')'}]}, - {bounds: [[806, 12, 65, 52]], states: [{charCode: 192, char: '_'}]}, - {bounds: [[881, 12, 65, 52]], states: [{charCode: 192, char: '{'}]}, - {bounds: [[953, 12, 65, 52]], states: [{charCode: 192, char: '}'}]}, - {bounds: [[1025, 12, 65, 52]], states: [{charCode: 192, char: '<'}]}, - {bounds: [[1097, 12, 65, 52]], states: [{charCode: 192, char: '>'}]}, + {bounds: [[12, 12, 65, 52]], states: [{charCode: 126, char: '~'}]}, + {bounds: [[84, 12, 65, 52]], states: [{charCode: 33, char: '!'}]}, + {bounds: [[156, 12, 65, 52]], states: [{charCode: 64, char: '@'}]}, + {bounds: [[228, 12, 65, 52]], states: [{charCode: 35, char: '#'}]}, + {bounds: [[300, 12, 65, 52]], states: [{charCode: 36, char: '$'}]}, + {bounds: [[372, 12, 65, 52]], states: [{charCode: 37, char: '%'}]}, + {bounds: [[445, 12, 65, 52]], states: [{charCode: 94, char: '^'}]}, + {bounds: [[517, 12, 65, 52]], states: [{charCode: 38, char: '&'}]}, + {bounds: [[589, 12, 65, 52]], states: [{charCode: 42, char: '*'}]}, + {bounds: [[662, 12, 65, 52]], states: [{charCode: 40, char: '('}]}, + {bounds: [[734, 12, 65, 52]], states: [{charCode: 41, char: ')'}]}, + {bounds: [[806, 12, 65, 52]], states: [{charCode: 95, char: '_'}]}, + {bounds: [[881, 12, 65, 52]], states: [{charCode: 123, char: '{'}]}, + {bounds: [[953, 12, 65, 52]], states: [{charCode: 125, char: '}'}]}, + {bounds: [[1025, 12, 65, 52]], states: [{charCode: 60, char: '<'}]}, + {bounds: [[1097, 12, 65, 52]], states: [{charCode: 62, char: '>'}]}, - {bounds: [[12, 71, 65, 63]], states: [{charCode: 192, char: '`'}]}, - {bounds: [[84, 71, 65, 63]], states: [{charCode: 192, char: '1'}]}, - {bounds: [[156, 71, 65, 63]], states: [{charCode: 192, char: '2'}]}, - {bounds: [[228, 71, 65, 63]], states: [{charCode: 192, char: '3'}]}, - {bounds: [[300, 71, 65, 63]], states: [{charCode: 192, char: '4'}]}, - {bounds: [[372, 71, 65, 63]], states: [{charCode: 192, char: '5'}]}, - {bounds: [[445, 71, 65, 63]], states: [{charCode: 192, char: '6'}]}, - {bounds: [[517, 71, 65, 63]], states: [{charCode: 192, char: '7'}]}, - {bounds: [[589, 71, 65, 63]], states: [{charCode: 192, char: '8'}]}, - {bounds: [[661, 71, 65, 63]], states: [{charCode: 192, char: '9'}]}, - {bounds: [[733, 71, 65, 63]], states: [{charCode: 192, char: '0'}]}, - {bounds: [[806, 71, 65, 63]], states: [{charCode: 192, char: '-'}]}, - {bounds: [[880, 71, 65, 63]], states: [{charCode: 192, char: '='}]}, - {bounds: [[953, 71, 65, 63]], states: [{charCode: 192, char: '+'}]}, + {bounds: [[12, 71, 65, 63]], states: [{charCode: 96, char: '`'}]}, + {bounds: [[84, 71, 65, 63]], states: [{charCode: 49, char: '1'}]}, + {bounds: [[156, 71, 65, 63]], states: [{charCode: 50, char: '2'}]}, + {bounds: [[228, 71, 65, 63]], states: [{charCode: 51, char: '3'}]}, + {bounds: [[300, 71, 65, 63]], states: [{charCode: 52, char: '4'}]}, + {bounds: [[372, 71, 65, 63]], states: [{charCode: 53, char: '5'}]}, + {bounds: [[445, 71, 65, 63]], states: [{charCode: 54, char: '6'}]}, + {bounds: [[517, 71, 65, 63]], states: [{charCode: 55, char: '7'}]}, + {bounds: [[589, 71, 65, 63]], states: [{charCode: 56, char: '8'}]}, + {bounds: [[661, 71, 65, 63]], states: [{charCode: 57, char: '9'}]}, + {bounds: [[733, 71, 65, 63]], states: [{charCode: 48, char: '0'}]}, + {bounds: [[806, 71, 65, 63]], states: [{charCode: 45, char: '-'}]}, + {bounds: [[880, 71, 65, 63]], states: [{charCode: 61, char: '='}]}, + {bounds: [[953, 71, 65, 63]], states: [{charCode: 43, char: '+'}]}, {bounds: [[1024, 71, 139, 63]], event: 'delete'}, // enter key has 2 bounds and one state {bounds: [[11, 143, 98, 71], [11, 213, 121, 62]], event: 'enter'}, - {bounds: [[118, 142, 64, 63]], states: [{charCode: 192, char: 'q'}, {charCode: 192, char: 'Q'}]}, - {bounds: [[190, 142, 64, 63]], states: [{charCode: 192, char: 'w'}, {charCode: 192, char: 'W'}]}, - {bounds: [[262, 142, 64, 63]], states: [{charCode: 192, char: 'e'}, {charCode: 192, char: 'E'}]}, - {bounds: [[334, 142, 64, 63]], states: [{charCode: 192, char: 'r'}, {charCode: 192, char: 'R'}]}, - {bounds: [[407, 142, 64, 63]], states: [{charCode: 192, char: 't'}, {charCode: 192, char: 'T'}]}, - {bounds: [[479, 142, 64, 63]], states: [{charCode: 192, char: 'y'}, {charCode: 192, char: 'Y'}]}, - {bounds: [[551, 142, 65, 63]], states: [{charCode: 192, char: 'u'}, {charCode: 192, char: 'U'}]}, - {bounds: [[623, 142, 65, 63]], states: [{charCode: 192, char: 'i'}, {charCode: 192, char: 'I'}]}, - {bounds: [[695, 142, 65, 63]], states: [{charCode: 192, char: 'o'}, {charCode: 192, char: 'O'}]}, - {bounds: [[768, 142, 64, 63]], states: [{charCode: 192, char: 'p'}, {charCode: 192, char: 'P'}]}, - {bounds: [[840, 142, 64, 63]], states: [{charCode: 192, char: '['}]}, - {bounds: [[912, 142, 65, 63]], states: [{charCode: 192, char: ']'}]}, - {bounds: [[984, 142, 65, 63]], states: [{charCode: 192, char: '\\'}]}, - {bounds: [[1055, 142, 65, 63]], states: [{charCode: 192, char: '|'}]}, + {bounds: [[118, 142, 64, 63]], states: [{charCode: 113, char: 'q'}, {charCode: 81, char: 'Q'}]}, + {bounds: [[190, 142, 64, 63]], states: [{charCode: 119, char: 'w'}, {charCode: 87, char: 'W'}]}, + {bounds: [[262, 142, 64, 63]], states: [{charCode: 101, char: 'e'}, {charCode: 69, char: 'E'}]}, + {bounds: [[334, 142, 64, 63]], states: [{charCode: 114, char: 'r'}, {charCode: 82, char: 'R'}]}, + {bounds: [[407, 142, 64, 63]], states: [{charCode: 116, char: 't'}, {charCode: 84, char: 'T'}]}, + {bounds: [[479, 142, 64, 63]], states: [{charCode: 121, char: 'y'}, {charCode: 89, char: 'Y'}]}, + {bounds: [[551, 142, 65, 63]], states: [{charCode: 117, char: 'u'}, {charCode: 85, char: 'U'}]}, + {bounds: [[623, 142, 65, 63]], states: [{charCode: 105, char: 'i'}, {charCode: 73, char: 'I'}]}, + {bounds: [[695, 142, 65, 63]], states: [{charCode: 111, char: 'o'}, {charCode: 79, char: 'O'}]}, + {bounds: [[768, 142, 64, 63]], states: [{charCode: 112, char: 'p'}, {charCode: 80, char: 'P'}]}, + {bounds: [[840, 142, 64, 63]], states: [{charCode: 91, char: '['}]}, + {bounds: [[912, 142, 65, 63]], states: [{charCode: 93, char: ']'}]}, + {bounds: [[984, 142, 65, 63]], states: [{charCode: 92, char: '\\'}]}, + {bounds: [[1055, 142, 65, 63]], states: [{charCode: 124, char: '|'}]}, {bounds: [[1126, 143, 35, 72], [1008, 214, 153, 62]], event: 'enter'}, - {bounds: [[140, 213, 65, 63]], states: [{charCode: 192, char: 'a'}, {charCode: 192, char: 'A'}]}, - {bounds: [[211, 213, 64, 63]], states: [{charCode: 192, char: 's'}, {charCode: 192, char: 'S'}]}, - {bounds: [[283, 213, 65, 63]], states: [{charCode: 192, char: 'd'}, {charCode: 192, char: 'D'}]}, - {bounds: [[355, 213, 65, 63]], states: [{charCode: 192, char: 'f'}, {charCode: 192, char: 'F'}]}, - {bounds: [[428, 213, 64, 63]], states: [{charCode: 192, char: 'g'}, {charCode: 192, char: 'G'}]}, - {bounds: [[500, 213, 64, 63]], states: [{charCode: 192, char: 'h'}, {charCode: 192, char: 'H'}]}, - {bounds: [[572, 213, 65, 63]], states: [{charCode: 192, char: 'j'}, {charCode: 192, char: 'J'}]}, - {bounds: [[644, 213, 65, 63]], states: [{charCode: 192, char: 'k'}, {charCode: 192, char: 'K'}]}, - {bounds: [[716, 213, 65, 63]], states: [{charCode: 192, char: 'l'}, {charCode: 192, char: 'L'}]}, - {bounds: [[789, 213, 64, 63]], states: [{charCode: 192, char: ';'}]}, - {bounds: [[861, 213, 64, 63]], states: [{charCode: 192, char: '\''}]}, - {bounds: [[934, 213, 65, 63]], states: [{charCode: 192, char: ':'}]}, + {bounds: [[140, 213, 65, 63]], states: [{charCode: 97, char: 'a'}, {charCode: 65, char: 'A'}]}, + {bounds: [[211, 213, 64, 63]], states: [{charCode: 115, char: 's'}, {charCode: 83, char: 'S'}]}, + {bounds: [[283, 213, 65, 63]], states: [{charCode: 100, char: 'd'}, {charCode: 68, char: 'D'}]}, + {bounds: [[355, 213, 65, 63]], states: [{charCode: 102, char: 'f'}, {charCode: 70, char: 'F'}]}, + {bounds: [[428, 213, 64, 63]], states: [{charCode: 103, char: 'g'}, {charCode: 71, char: 'G'}]}, + {bounds: [[500, 213, 64, 63]], states: [{charCode: 104, char: 'h'}, {charCode: 72, char: 'H'}]}, + {bounds: [[572, 213, 65, 63]], states: [{charCode: 106, char: 'j'}, {charCode: 74, char: 'J'}]}, + {bounds: [[644, 213, 65, 63]], states: [{charCode: 107, char: 'k'}, {charCode: 75, char: 'K'}]}, + {bounds: [[716, 213, 65, 63]], states: [{charCode: 108, char: 'l'}, {charCode: 76, char: 'L'}]}, + {bounds: [[789, 213, 64, 63]], states: [{charCode: 59, char: ';'}]}, + {bounds: [[861, 213, 64, 63]], states: [{charCode: 39, char: '\''}]}, + {bounds: [[934, 213, 65, 63]], states: [{charCode: 58, char: ':'}]}, {bounds: [[12, 283, 157, 63]], event: 'shift'}, - {bounds: [[176, 283, 65, 63]], states: [{charCode: 192, char: 'z'}, {charCode: 192, char: 'Z'}]}, - {bounds: [[249, 283, 64, 63]], states: [{charCode: 192, char: 'x'}, {charCode: 192, char: 'X'}]}, - {bounds: [[321, 283, 64, 63]], states: [{charCode: 192, char: 'c'}, {charCode: 192, char: 'C'}]}, - {bounds: [[393, 283, 64, 63]], states: [{charCode: 192, char: 'v'}, {charCode: 192, char: 'V'}]}, - {bounds: [[465, 283, 65, 63]], states: [{charCode: 192, char: 'b'}, {charCode: 192, char: 'B'}]}, - {bounds: [[537, 283, 65, 63]], states: [{charCode: 192, char: 'n'}, {charCode: 192, char: 'N'}]}, - {bounds: [[610, 283, 64, 63]], states: [{charCode: 192, char: 'm'}, {charCode: 192, char: 'M'}]}, - {bounds: [[682, 283, 64, 63]], states: [{charCode: 192, char: ','}]}, - {bounds: [[754, 283, 65, 63]], states: [{charCode: 192, char: '.'}]}, - {bounds: [[826, 283, 65, 63]], states: [{charCode: 192, char: '/'}]}, - {bounds: [[899, 283, 64, 63]], states: [{charCode: 192, char: '?'}]}, + {bounds: [[176, 283, 65, 63]], states: [{charCode: 122, char: 'z'}, {charCode: 90, char: 'Z'}]}, + {bounds: [[249, 283, 64, 63]], states: [{charCode: 120, char: 'x'}, {charCode: 88, char: 'X'}]}, + {bounds: [[321, 283, 64, 63]], states: [{charCode: 99, char: 'c'}, {charCode: 67, char: 'C'}]}, + {bounds: [[393, 283, 64, 63]], states: [{charCode: 118, char: 'v'}, {charCode: 86, char: 'V'}]}, + {bounds: [[465, 283, 65, 63]], states: [{charCode: 98, char: 'b'}, {charCode: 66, char: 'B'}]}, + {bounds: [[537, 283, 65, 63]], states: [{charCode: 110, char: 'n'}, {charCode: 78, char: 'N'}]}, + {bounds: [[610, 283, 64, 63]], states: [{charCode: 109, char: 'm'}, {charCode: 77, char: 'M'}]}, + {bounds: [[682, 283, 64, 63]], states: [{charCode: 44, char: ','}]}, + {bounds: [[754, 283, 65, 63]], states: [{charCode: 46, char: '.'}]}, + {bounds: [[826, 283, 65, 63]], states: [{charCode: 47, char: '/'}]}, + {bounds: [[899, 283, 64, 63]], states: [{charCode: 63, char: '?'}]}, {bounds: [[972, 283, 190, 63]], event: 'shift'}, @@ -536,6 +562,7 @@ function scriptEnding() { keyboard.remove(); cursor.remove(); Overlays.deleteOverlay(text); + Overlays.deleteOverlay(textSizeMeasureOverlay); Controller.releaseKeyEvents({key: SPACEBAR_CHARCODE}); } Controller.captureKeyEvents({key: SPACEBAR_CHARCODE}); From ffe66cd5c5b8e1d658c09739fcf37111ac7953d3 Mon Sep 17 00:00:00 2001 From: Adrianl3d Date: Tue, 25 Nov 2014 04:23:00 +1000 Subject: [PATCH 046/502] Clean up code Fix code to standards --- examples/notifications.js | 72 +++++++++++++++++++-------------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/examples/notifications.js b/examples/notifications.js index 3d0b05521d..16e9dd70b2 100644 --- a/examples/notifications.js +++ b/examples/notifications.js @@ -76,7 +76,7 @@ var ready = true; // When our script shuts down, we should clean up all of our overlays function scriptEnding() { - for (i = 0; i < notifications.length; i++){ + for (i = 0; i < notifications.length; i++) { Overlays.deleteOverlay(notifications[i]); Overlays.deleteOverlay(buttons[i]); } @@ -91,23 +91,23 @@ var myAlpha = []; var arrays = []; // This function creates and sizes the overlays -function createNotification(text){ +function createNotification(text) { var count = (text.match(/\n/g) || []).length; var breakPoint = 43.0; // length when new line is added var extraLine = 0; - var breaks = 0; + var breaks = 0; var height = 40.0; var stack = 0; - if (text.length >= breakPoint){ + if (text.length >= breakPoint) { breaks = count; } - var extraLine = breaks * 16.0; - for (i = 0; i < heights.length; i++){ + var extraLine = breaks * 16.0; + for (i = 0; i < heights.length; i++) { stack = stack + heights[i]; } - var level = (stack + 20.0 ); + var level = (stack + 20.0); height = height + extraLine; - var overlayProperties = { + var overlayProperties = { x: overlayLocationX, y: level, width: width, @@ -142,18 +142,18 @@ function createNotification(text){ // specifically notification "heights", "times" of creation, and . function Notify(notice, button, height){ - notifications.push((Overlays.addOverlay("text",notice))); + notifications.push((Overlays.addOverlay("text", notice))); buttons.push((Overlays.addOverlay("image",button))); times.push(new Date().getTime() / 1000); height = height + 1.0; heights.push(height); myAlpha.push(0); var last = notifications.length - 1; - createArrays(notifications[last], buttons[last], times[last], heights[last], myAlpha[last]); + createArrays(notifications[last], buttons[last], times[last], heights[last], myAlpha[last]); fadeIn(notifications[last], buttons[last]) } -function fadeIn(noticeIn, buttonIn){ +function fadeIn(noticeIn, buttonIn) { var myLength = arrays.length; var q = 0; var pauseTimer = null; @@ -170,14 +170,14 @@ function fadeIn(noticeIn, buttonIn){ // push data from above to the 2 dimensional array -function createArrays(notice, button, createTime, height, myAlpha){ +function createArrays(notice, button, createTime, height, myAlpha) { arrays.push([notice, button, createTime, height, myAlpha]); } // handles mouse clicks on buttons function mousePressEvent(event) { var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y}); //identify which overlay was clicked - for (i = 0; i < buttons.length; i++){ //if user clicked a button - if(clickedOverlay == buttons[i]){ + for (i = 0; i < buttons.length; i++) { //if user clicked a button + if(clickedOverlay == buttons[i]) { Overlays.deleteOverlay(notifications[i]); Overlays.deleteOverlay(buttons[i]); notifications.splice(i, 1); @@ -191,25 +191,25 @@ function mousePressEvent(event) { } // Control key remains active only while key is held down -function keyReleaseEvent(key){ - if (key.key == 16777249){ +function keyReleaseEvent(key) { + if (key.key == 16777249) { ctrlIsPressed = false; } } // Triggers notification on specific key driven events function keyPressEvent(key) { - if (key.key == 16777249){ + if (key.key == 16777249) { ctrlIsPressed = true; } if (key.text == "a") { - var noteString = "Turning to the Left"; + var noteString = "Turning to the Left"; createNotification(noteString); } if (key.text == "d") { - var noteString = "Turning to the Right"; + var noteString = "Turning to the Right"; createNotification(noteString); - } + } if (key.text == "s") { if (ctrlIsPressed == true){ var noteString = "You have taken a snapshot"; @@ -219,20 +219,20 @@ function keyPressEvent(key) { if (key.text == "q") { var noteString = "Enable Scripted Motor control is now on."; wordWrap(noteString); - } + } if (key.text == "w") { var noteString = "This notification spans 2 lines. The overlay will resize to fit new lines."; var noteString = "editVoxels.js stopped, editModels.js stopped, selectAudioDevice.js stopped."; wordWrap(noteString); - } + } if (key.text == "e") { var noteString = "This is an example of a multiple line notification. This notification will span 3 lines." wordWrap(noteString); - } + } if (key.text == "r") { var noteString = "This is a very long line of text that we are going to use in this example to divide it into rows of maximum 43 chars and see how many lines we use."; wordWrap(noteString); - } + } if (key.text == "SPACE") { var noteString = "You have pressed the Spacebar, This is an example of a multiple line notification. Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam."; wordWrap(noteString); @@ -240,7 +240,7 @@ function keyPressEvent(key) { } // formats string to add newline every 43 chars -function wordWrap(str){ +function wordWrap(str) { var result = stringDivider(str, 43.0, "\n"); createNotification(result); } @@ -261,7 +261,7 @@ function stringDivider(str, slotWidth, spaceReplacer) { // This fires a notification on window resize function checkSize(){ - if((Window.innerWidth!=ourWidth)||(Window.innerHeight!=ourHeight)){ + if((Window.innerWidth != ourWidth)||(Window.innerHeight != ourHeight)) { var windowResize = "Window has been resized"; ourWidth = Window.innerWidth; ourHeight = Window.innerHeight; @@ -285,7 +285,7 @@ function onOnlineUsersChanged(users) { for (user in last_users) { if (users.indexOf(last_users[user]) == -1.0) { leavers.push(last_users[user]); - createNotification(last_users[user] + " Has left"); + createNotification(last_users[user] + " Has left"); } } last_users = users; @@ -312,20 +312,20 @@ function update(){ if ((frame % 60.0) == 0) { // only update once a second checkSize(); // checks for size change to trigger windowResize notification locationY = 20.0; - for (var i = 0; i < arrays.length; i++){ //repositions overlays as others fade - var nextOverlay = Overlays.getOverlayAtPoint({x: overlayLocationX, y: locationY }); + for (var i = 0; i < arrays.length; i++) { //repositions overlays as others fade + var nextOverlay = Overlays.getOverlayAtPoint({x: overlayLocationX, y: locationY}); Overlays.editOverlay(notifications[i], { x:overlayLocationX, y:locationY}); Overlays.editOverlay(buttons[i], { x:buttonLocationX, y:locationY + 12.0}); - locationY=locationY + arrays[i][3]; + locationY = locationY + arrays[i][3]; } } // This checks the age of the notification and prepares to fade it after 9.0 seconds (var persistTime - 1) - for (var i = 0; i < arrays.length; i++){ + for (var i = 0; i < arrays.length; i++) { if (ready){ var j = arrays[i][2]; var k = j + persistTime; - if (k < (new Date().getTime() / 1000)){ + if (k < (new Date().getTime() / 1000)) { ready = false; noticeOut = arrays[i][0]; buttonOut = arrays[i][1]; @@ -337,8 +337,8 @@ function update(){ } // this fades the notification ready for dismissal, and removes it from the arrays -function fadeOut(noticeOut, buttonOut, arraysOut){ - var myLength = arrays.length; +function fadeOut(noticeOut, buttonOut, arraysOut) { + var myLength = arrays.length; var r = 9.0; var pauseTimer = null; pauseTimer = Script.setInterval(function() { @@ -356,8 +356,8 @@ function fadeOut(noticeOut, buttonOut, arraysOut){ } // This handles the final dismissal of a notification after fading -function dismiss(firstNoteOut, firstButOut, firstOut){ -var working = firstOut +function dismiss(firstNoteOut, firstButOut, firstOut) { + var working = firstOut Overlays.deleteOverlay(firstNoteOut); Overlays.deleteOverlay(firstButOut); notifications.splice(firstOut, 1); From 8b23a2cd1ee95f0b0648361350827a18cc8be060 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 24 Nov 2014 10:33:31 -0800 Subject: [PATCH 047/502] adding the shader files for the lightmap case --- .../resources/shaders/model_lightmap.frag | 36 +++++++++++++ .../resources/shaders/model_lightmap.vert | 40 ++++++++++++++ .../shaders/model_lightmap_normal_map.frag | 49 +++++++++++++++++ .../shaders/model_lightmap_normal_map.vert | 46 ++++++++++++++++ .../model_lightmap_normal_specular_map.frag | 53 +++++++++++++++++++ .../shaders/model_lightmap_specular_map.frag | 39 ++++++++++++++ 6 files changed, 263 insertions(+) create mode 100644 interface/resources/shaders/model_lightmap.frag create mode 100644 interface/resources/shaders/model_lightmap.vert create mode 100644 interface/resources/shaders/model_lightmap_normal_map.frag create mode 100644 interface/resources/shaders/model_lightmap_normal_map.vert create mode 100644 interface/resources/shaders/model_lightmap_normal_specular_map.frag create mode 100644 interface/resources/shaders/model_lightmap_specular_map.frag diff --git a/interface/resources/shaders/model_lightmap.frag b/interface/resources/shaders/model_lightmap.frag new file mode 100644 index 0000000000..0b7798f610 --- /dev/null +++ b/interface/resources/shaders/model_lightmap.frag @@ -0,0 +1,36 @@ +#version 120 + +// +// model_lightmap.frag +// fragment shader +// +// Created by Samuel Gateau on 11/19/14. +// Copyright 2013 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 +// + +// the diffuse texture +uniform sampler2D diffuseMap; + +// the emissive map texture +uniform sampler2D emissiveMap; + +// the alpha threshold +uniform float alphaThreshold; + +// the interpolated normal +varying vec4 normal; + +// the interpolated texcoord1 +varying vec2 interpolatedTexcoord1; + +void main(void) { + // set the diffuse, normal, specular data + vec4 diffuse = texture2D(diffuseMap, gl_TexCoord[0].st); + vec4 emissive = texture2D(emissiveMap, interpolatedTexcoord1.st); + gl_FragData[0] = vec4(diffuse.rgb * (vec3(0.3) + emissive.rgb), mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); + gl_FragData[1] = normalize(normal) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0); + gl_FragData[2] = vec4(gl_FrontMaterial.specular.rgb, gl_FrontMaterial.shininess / 128.0); +} diff --git a/interface/resources/shaders/model_lightmap.vert b/interface/resources/shaders/model_lightmap.vert new file mode 100644 index 0000000000..021db11796 --- /dev/null +++ b/interface/resources/shaders/model_lightmap.vert @@ -0,0 +1,40 @@ +#version 120 + +// +// model_lightmap.vert +// vertex shader +// +// Created by Sam Gateau on 11/21/14. +// Copyright 2013 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 +// + +const int MAX_TEXCOORDS = 2; + +uniform mat4 texcoordMatrices[MAX_TEXCOORDS]; + +attribute vec2 texcoord1; + +// the interpolated normal +varying vec4 normal; + +// the interpolated texcoord1 +varying vec2 interpolatedTexcoord1; + +void main(void) { + // transform and store the normal for interpolation + normal = normalize(gl_ModelViewMatrix * vec4(gl_Normal, 0.0)); + + // pass along the diffuse color + gl_FrontColor = gl_Color * gl_FrontMaterial.diffuse; + + // and the texture coordinates + gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.f, 1.f); + interpolatedTexcoord1 = vec2(texcoordMatrices[1] * vec4(texcoord1.xy, 0.f, 1.f)).xy; + + // use standard pipeline transform + gl_Position = ftransform(); +} + diff --git a/interface/resources/shaders/model_lightmap_normal_map.frag b/interface/resources/shaders/model_lightmap_normal_map.frag new file mode 100644 index 0000000000..d63fd91fd0 --- /dev/null +++ b/interface/resources/shaders/model_lightmap_normal_map.frag @@ -0,0 +1,49 @@ +#version 120 + +// +// model_lightmap_normal_map.frag +// fragment shader +// +// Created by Samuel Gateau on 11/19/14. +// Copyright 2013 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 +// + +// the diffuse texture +uniform sampler2D diffuseMap; + +// the normal map texture +uniform sampler2D normalMap; + +// the emissive map texture +uniform sampler2D emissiveMap; + +// the alpha threshold +uniform float alphaThreshold; + +// the interpolated normal +varying vec4 interpolatedNormal; + +// the interpolated tangent +varying vec4 interpolatedTangent; + +varying vec2 interpolatedTexcoord1; + +void main(void) { + // compute the view normal from the various bits + vec3 normalizedNormal = normalize(vec3(interpolatedNormal)); + vec3 normalizedTangent = normalize(vec3(interpolatedTangent)); + vec3 normalizedBitangent = normalize(cross(normalizedNormal, normalizedTangent)); + vec3 localNormal = vec3(texture2D(normalMap, gl_TexCoord[0].st)) - 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); + gl_FragData[0] = vec4(gl_Color.rgb * emissive.rgb, mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); + gl_FragData[1] = viewNormal + vec4(0.5, 0.5, 0.5, 1.0); + gl_FragData[2] = vec4(gl_FrontMaterial.specular.rgb, gl_FrontMaterial.shininess / 128.0); +} diff --git a/interface/resources/shaders/model_lightmap_normal_map.vert b/interface/resources/shaders/model_lightmap_normal_map.vert new file mode 100644 index 0000000000..08eca835c9 --- /dev/null +++ b/interface/resources/shaders/model_lightmap_normal_map.vert @@ -0,0 +1,46 @@ +#version 120 + +// +// model_lightmap_normal_map.vert +// vertex shader +// +// Created by Sam Gateau on 11/21/14. +// Copyright 2013 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 +// + +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; + +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 + gl_FrontColor = gl_Color * gl_FrontMaterial.diffuse; + + // and the texture coordinates + gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.f, 1.f); + interpolatedTexcoord1 = vec2(texcoordMatrices[1] * vec4(texcoord1.xy, 0.f, 1.f)).xy; + + // use standard pipeline transform + gl_Position = ftransform(); +} diff --git a/interface/resources/shaders/model_lightmap_normal_specular_map.frag b/interface/resources/shaders/model_lightmap_normal_specular_map.frag new file mode 100644 index 0000000000..9b602c5a3b --- /dev/null +++ b/interface/resources/shaders/model_lightmap_normal_specular_map.frag @@ -0,0 +1,53 @@ +#version 120 + +// +// model_lightmap_normal_specular_map.frag +// fragment shader +// +// Created by Samuel Gateau on 11/19/14. +// 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 +// + +// the diffuse texture +uniform sampler2D diffuseMap; + +// the emissive map texture +uniform sampler2D emissiveMap; + +// the normal map texture +uniform sampler2D normalMap; + +// the specular map texture +uniform sampler2D specularMap; + +// the alpha threshold +uniform float alphaThreshold; + +// the interpolated normal +varying vec4 interpolatedNormal; + +// the interpolated tangent +varying vec4 interpolatedTangent; + +varying vec2 interpolatedTexcoord1; + +void main(void) { + // compute the view normal from the various bits + vec3 normalizedNormal = normalize(vec3(interpolatedNormal)); + vec3 normalizedTangent = normalize(vec3(interpolatedTangent)); + vec3 normalizedBitangent = normalize(cross(normalizedNormal, normalizedTangent)); + vec3 localNormal = vec3(texture2D(normalMap, gl_TexCoord[0].st)) - 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); + gl_FragData[0] = vec4(gl_Color.rgb * emissive.rgb, mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); + gl_FragData[1] = viewNormal + vec4(0.5, 0.5, 0.5, 1.0); + gl_FragData[2] = vec4(gl_FrontMaterial.specular.rgb * texture2D(specularMap, gl_TexCoord[0].st).rgb, + gl_FrontMaterial.shininess / 128.0); +} diff --git a/interface/resources/shaders/model_lightmap_specular_map.frag b/interface/resources/shaders/model_lightmap_specular_map.frag new file mode 100644 index 0000000000..d60f21dffb --- /dev/null +++ b/interface/resources/shaders/model_lightmap_specular_map.frag @@ -0,0 +1,39 @@ +#version 120 + +// +// model_lightmap_specular_map.frag +// fragment shader +// +// Created by Samuel Gateau on 11/19/14. +// 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 +// + +// the diffuse texture +uniform sampler2D diffuseMap; + +// the emissive map texture +uniform sampler2D emissiveMap; + +// the specular texture +uniform sampler2D specularMap; + +// the alpha threshold +uniform float alphaThreshold; + +// the interpolated normal +varying vec4 normal; + +varying vec2 interpolatedTexcoord1; + +void main(void) { + // set the diffuse, normal, specular data + vec4 diffuse = texture2D(diffuseMap, gl_TexCoord[0].st); + vec4 emissive = texture2D(emissiveMap, interpolatedTexcoord1.st); + gl_FragData[0] = vec4(gl_Color.rgb * emissive.rgb, mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); + gl_FragData[1] = normalize(normal) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0); + gl_FragData[2] = vec4(gl_FrontMaterial.specular.rgb * texture2D(specularMap, gl_TexCoord[0].st).rgb, + gl_FrontMaterial.shininess / 128.0); +} From 6591f4dac296ce51dc23b307a766dbf9d061c3d3 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 24 Nov 2014 11:18:21 -0800 Subject: [PATCH 048/502] adjust lighmap shading equation --- interface/resources/shaders/model_lightmap.frag | 2 +- interface/resources/shaders/model_lightmap_normal_map.frag | 2 +- .../resources/shaders/model_lightmap_normal_specular_map.frag | 2 +- interface/resources/shaders/model_lightmap_specular_map.frag | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/interface/resources/shaders/model_lightmap.frag b/interface/resources/shaders/model_lightmap.frag index 0b7798f610..67d9cd0218 100644 --- a/interface/resources/shaders/model_lightmap.frag +++ b/interface/resources/shaders/model_lightmap.frag @@ -30,7 +30,7 @@ void main(void) { // set the diffuse, normal, specular data vec4 diffuse = texture2D(diffuseMap, gl_TexCoord[0].st); vec4 emissive = texture2D(emissiveMap, interpolatedTexcoord1.st); - gl_FragData[0] = vec4(diffuse.rgb * (vec3(0.3) + emissive.rgb), mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); + gl_FragData[0] = vec4(gl_Color.rgb * diffuse.rgb * (vec3(0.1) + 4 * emissive.rgb), mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); gl_FragData[1] = normalize(normal) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0); gl_FragData[2] = vec4(gl_FrontMaterial.specular.rgb, gl_FrontMaterial.shininess / 128.0); } diff --git a/interface/resources/shaders/model_lightmap_normal_map.frag b/interface/resources/shaders/model_lightmap_normal_map.frag index d63fd91fd0..6d3e3aa861 100644 --- a/interface/resources/shaders/model_lightmap_normal_map.frag +++ b/interface/resources/shaders/model_lightmap_normal_map.frag @@ -43,7 +43,7 @@ void main(void) { // set the diffuse, normal, specular data vec4 diffuse = texture2D(diffuseMap, gl_TexCoord[0].st); vec4 emissive = texture2D(emissiveMap, interpolatedTexcoord1.st); - gl_FragData[0] = vec4(gl_Color.rgb * emissive.rgb, mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); + gl_FragData[0] = vec4(gl_Color.rgb * diffuse.rgb * (vec3(0.1) + 4 * emissive.rgb), mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); gl_FragData[1] = viewNormal + vec4(0.5, 0.5, 0.5, 1.0); gl_FragData[2] = vec4(gl_FrontMaterial.specular.rgb, gl_FrontMaterial.shininess / 128.0); } diff --git a/interface/resources/shaders/model_lightmap_normal_specular_map.frag b/interface/resources/shaders/model_lightmap_normal_specular_map.frag index 9b602c5a3b..89333bbcef 100644 --- a/interface/resources/shaders/model_lightmap_normal_specular_map.frag +++ b/interface/resources/shaders/model_lightmap_normal_specular_map.frag @@ -46,7 +46,7 @@ void main(void) { // set the diffuse, normal, specular data vec4 diffuse = texture2D(diffuseMap, gl_TexCoord[0].st); vec4 emissive = texture2D(emissiveMap, interpolatedTexcoord1.st); - gl_FragData[0] = vec4(gl_Color.rgb * emissive.rgb, mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); + gl_FragData[0] = vec4(gl_Color.rgb * diffuse.rgb * (vec3(0.1) + 4 * emissive.rgb), mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); gl_FragData[1] = viewNormal + vec4(0.5, 0.5, 0.5, 1.0); gl_FragData[2] = vec4(gl_FrontMaterial.specular.rgb * texture2D(specularMap, gl_TexCoord[0].st).rgb, gl_FrontMaterial.shininess / 128.0); diff --git a/interface/resources/shaders/model_lightmap_specular_map.frag b/interface/resources/shaders/model_lightmap_specular_map.frag index d60f21dffb..3526ecdf9c 100644 --- a/interface/resources/shaders/model_lightmap_specular_map.frag +++ b/interface/resources/shaders/model_lightmap_specular_map.frag @@ -32,7 +32,7 @@ void main(void) { // set the diffuse, normal, specular data vec4 diffuse = texture2D(diffuseMap, gl_TexCoord[0].st); vec4 emissive = texture2D(emissiveMap, interpolatedTexcoord1.st); - gl_FragData[0] = vec4(gl_Color.rgb * emissive.rgb, mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); + gl_FragData[0] = vec4(gl_Color.rgb * diffuse.rgb * (vec3(0.1) + 4 * emissive.rgb), mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); gl_FragData[1] = normalize(normal) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0); gl_FragData[2] = vec4(gl_FrontMaterial.specular.rgb * texture2D(specularMap, gl_TexCoord[0].st).rgb, gl_FrontMaterial.shininess / 128.0); From f67b4b9ff4fa043e9805944110594c5d4346615a Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 24 Nov 2014 11:44:54 -0800 Subject: [PATCH 049/502] clean out comments so the 2 rendering modes for entities work, scene batch or per model batch --- interface/src/renderer/Model.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index d2a2378689..3f68201386 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -1635,7 +1635,7 @@ void Model::endScene(RenderMode mode, RenderArgs* args) { int opaqueMeshPartsRendered = 0; // now, for each model in the scene, render the mesh portions - /* opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, false, false, args); + opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, false, false, args); opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, false, true, args); opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, true, false, args); opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, true, true, args); @@ -1643,7 +1643,7 @@ void Model::endScene(RenderMode mode, RenderArgs* args) { opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, false, true, args); opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, true, false, args); opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, true, true, args); -*/ + opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, false, false, args); opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, false, args); opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, false, false, args); @@ -1661,7 +1661,7 @@ void Model::endScene(RenderMode mode, RenderArgs* args) { int translucentParts = 0; const float MOSTLY_OPAQUE_THRESHOLD = 0.75f; - /* translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, false, false, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, false, false, args); translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, false, true, args); translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, true, false, args); translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, true, true, args); @@ -1669,7 +1669,7 @@ void Model::endScene(RenderMode mode, RenderArgs* args) { translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, false, true, args); translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, false, args); translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, true, args); - */ + GLBATCH(glDisable)(GL_ALPHA_TEST); GLBATCH(glEnable)(GL_BLEND); GLBATCH(glDepthMask)(false); @@ -1685,7 +1685,7 @@ void Model::endScene(RenderMode mode, RenderArgs* args) { if (mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE) { const float MOSTLY_TRANSPARENT_THRESHOLD = 0.0f; - /* translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, false, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, false, args); translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, true, args); translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, true, false, args); translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, true, true, args); @@ -1693,7 +1693,7 @@ void Model::endScene(RenderMode mode, RenderArgs* args) { translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, false, true, args); translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, false, args); translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, true, args); - */ } + } GLBATCH(glDepthMask)(true); GLBATCH(glDepthFunc)(GL_LESS); From 08772bbae0fef5b79f49a03c5a7a996126d4f463 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 24 Nov 2014 13:07:22 -0800 Subject: [PATCH 050/502] remove spatial audio menu items --- interface/src/Audio.cpp | 6 ++-- interface/src/AudioReflector.cpp | 48 +++++++++++++++++------------ interface/src/Menu.cpp | 52 -------------------------------- interface/src/Menu.h | 12 -------- interface/src/ui/Stats.cpp | 43 +++++++++++++------------- 5 files changed, 55 insertions(+), 106 deletions(-) diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index 75b8c252f7..167c44111e 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -989,7 +989,8 @@ void Audio::processReceivedSamples(const QByteArray& inputBuffer, QByteArray& ou QByteArray buffer = inputBuffer; // Accumulate direct transmission of audio from sender to receiver - if (Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingIncludeOriginal)) { + bool includeOriginal = true; // Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingIncludeOriginal) + if (includeOriginal) { emit preProcessOriginalInboundAudio(sampleTime, buffer, _desiredOutputFormat); addSpatialAudioToBuffer(sampleTime, buffer, numNetworkOutputSamples); } @@ -1264,7 +1265,8 @@ void Audio::selectAudioSourceSine440() { } void Audio::toggleAudioSpatialProcessing() { - _processSpatialAudio = !_processSpatialAudio; + // spatial audio disabled for now + _processSpatialAudio = false; //!_processSpatialAudio; if (_processSpatialAudio) { _spatialAudioStart = 0; _spatialAudioFinish = 0; diff --git a/interface/src/AudioReflector.cpp b/interface/src/AudioReflector.cpp index e18a0ad36e..8a23ecee79 100644 --- a/interface/src/AudioReflector.cpp +++ b/interface/src/AudioReflector.cpp @@ -66,10 +66,15 @@ AudioReflector::AudioReflector(QObject* parent) : } bool AudioReflector::haveAttributesChanged() { - bool withDiffusion = Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingWithDiffusions); - bool dontDistanceAttenuate = Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingDontDistanceAttenuate); - bool alternateDistanceAttenuate = Menu::getInstance()->isOptionChecked( - MenuOption::AudioSpatialProcessingAlternateDistanceAttenuate); + + // Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingWithDiffusions); + bool withDiffusion = true; + + // Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingDontDistanceAttenuate); + bool dontDistanceAttenuate = false; + + //Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingAlternateDistanceAttenuate); + bool alternateDistanceAttenuate = false; bool attributesChange = (_withDiffusion != withDiffusion || _lastPreDelay != _preDelay @@ -107,7 +112,8 @@ void AudioReflector::render() { calculateAllReflections(); // only render if we've been asked to do so - if (Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingRenderPaths)) { + bool renderPaths = false; // Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingRenderPaths) + if (renderPaths) { drawRays(); } } @@ -116,7 +122,8 @@ void AudioReflector::render() { // = 3ms per meter float AudioReflector::getDelayFromDistance(float distance) { float delay = (_soundMsPerMeter * distance); - if (Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingPreDelay)) { + bool includePreDelay = true; // Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingPreDelay) + if (includePreDelay) { delay += _preDelay; } return delay; @@ -126,12 +133,11 @@ float AudioReflector::getDelayFromDistance(float distance) { float AudioReflector::getDistanceAttenuationCoefficient(float distance) { - bool doDistanceAttenuation = !Menu::getInstance()->isOptionChecked( - MenuOption::AudioSpatialProcessingDontDistanceAttenuate); + //!Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingDontDistanceAttenuate); + bool doDistanceAttenuation = true; - bool originalFormula = !Menu::getInstance()->isOptionChecked( - MenuOption::AudioSpatialProcessingAlternateDistanceAttenuate); - + //!Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingAlternateDistanceAttenuate); + bool originalFormula = true; float distanceCoefficient = 1.0f; @@ -170,7 +176,8 @@ float AudioReflector::getDistanceAttenuationCoefficient(float distance) { } glm::vec3 AudioReflector::getFaceNormal(BoxFace face) { - bool wantSlightRandomness = Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingSlightlyRandomSurfaces); + // Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingSlightlyRandomSurfaces); + bool wantSlightRandomness = true; glm::vec3 faceNormal; const float MIN_RANDOM_LENGTH = 0.99f; const float MAX_RANDOM_LENGTH = 1.0f; @@ -202,8 +209,8 @@ const int NUMBER_OF_CHANNELS = 2; void AudioReflector::injectAudiblePoint(AudioSource source, const AudiblePoint& audiblePoint, const QByteArray& samples, unsigned int sampleTime, int sampleRate) { - bool wantEarSeparation = Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingSeparateEars); - bool wantStereo = Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingStereoSource); + bool wantEarSeparation = true; // Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingSeparateEars); + bool wantStereo = true; // Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingStereoSource); glm::vec3 rightEarPosition = wantEarSeparation ? _myAvatar->getHead()->getRightEarPosition() : _myAvatar->getHead()->getPosition(); glm::vec3 leftEarPosition = wantEarSeparation ? _myAvatar->getHead()->getLeftEarPosition() : @@ -316,7 +323,8 @@ void AudioReflector::preProcessOriginalInboundAudio(unsigned int sampleTime, } void AudioReflector::processLocalAudio(unsigned int sampleTime, const QByteArray& samples, const QAudioFormat& format) { - if (Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingProcessLocalAudio)) { + bool processLocalAudio = true; // Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingProcessLocalAudio) + if (processLocalAudio) { const int NUM_CHANNELS_INPUT = 1; const int NUM_CHANNELS_OUTPUT = 2; const int EXPECTED_SAMPLE_RATE = 24000; @@ -458,7 +466,7 @@ void AudioReflector::identifyAudioSources() { void AudioReflector::calculateAllReflections() { // only recalculate when we've moved, or if the attributes have changed // TODO: what about case where new voxels are added in front of us??? - bool wantHeadOrientation = Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingHeadOriented); + bool wantHeadOrientation = true; // Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingHeadOriented); glm::quat orientation = wantHeadOrientation ? _myAvatar->getHead()->getFinalOrientationInWorldFrame() : _myAvatar->getOrientation(); glm::vec3 origin = _myAvatar->getHead()->getPosition(); glm::vec3 listenerPosition = _myAvatar->getHead()->getPosition(); @@ -505,7 +513,8 @@ void AudioReflector::drawRays() { } } - if (Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingProcessLocalAudio)) { + bool processLocalAudio = true; // Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingProcessLocalAudio) + if (processLocalAudio) { // draw the paths for local audio foreach(AudioPath* const& path, _localAudioPaths) { // if this is an original reflection, draw it in RED @@ -575,7 +584,8 @@ void AudioReflector::analyzePaths() { float initialAttenuation = 1.0f; - float preDelay = Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingPreDelay) ? _preDelay : 0.0f; + bool wantPreDelay = true; // Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingPreDelay) + float preDelay = wantPreDelay ? _preDelay : 0.0f; // NOTE: we're still calculating our initial paths based on the listeners position. But the analysis code has been // updated to support individual sound sources (which is how we support diffusion), we can use this new paradigm to @@ -701,7 +711,7 @@ void AudioReflector::handlePathPoint(AudioPath* path, float distance, OctreeElem float reflectiveAttenuation = currentReflectiveAttenuation * material.reflectiveRatio; float totalDiffusionAttenuation = currentReflectiveAttenuation * material.diffusionRatio; - bool wantDiffusions = Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingWithDiffusions); + bool wantDiffusions = true; // Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingWithDiffusions); int fanout = wantDiffusions ? _diffusionFanout : 0; float partialDiffusionAttenuation = fanout < 1 ? 0.0f : totalDiffusionAttenuation / (float)fanout; diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index db5cd5170d..baac3629ac 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -620,58 +620,6 @@ Menu::Menu() : audioScopeFramesGroup->addAction(fiftyFrames); } - QMenu* spatialAudioMenu = audioDebugMenu->addMenu("Spatial Audio"); - - addCheckableActionToQMenuAndActionHash(spatialAudioMenu, MenuOption::AudioSpatialProcessing, - Qt::CTRL | Qt::SHIFT | Qt::Key_M, - false, - appInstance->getAudio(), - SLOT(toggleAudioSpatialProcessing())); - - addCheckableActionToQMenuAndActionHash(spatialAudioMenu, MenuOption::AudioSpatialProcessingIncludeOriginal, - Qt::CTRL | Qt::SHIFT | Qt::Key_O, - true); - - addCheckableActionToQMenuAndActionHash(spatialAudioMenu, MenuOption::AudioSpatialProcessingSeparateEars, - Qt::CTRL | Qt::SHIFT | Qt::Key_E, - true); - - addCheckableActionToQMenuAndActionHash(spatialAudioMenu, MenuOption::AudioSpatialProcessingPreDelay, - Qt::CTRL | Qt::SHIFT | Qt::Key_D, - true); - - addCheckableActionToQMenuAndActionHash(spatialAudioMenu, MenuOption::AudioSpatialProcessingStereoSource, - Qt::CTRL | Qt::SHIFT | Qt::Key_S, - true); - - addCheckableActionToQMenuAndActionHash(spatialAudioMenu, MenuOption::AudioSpatialProcessingHeadOriented, - Qt::CTRL | Qt::SHIFT | Qt::Key_H, - true); - - addCheckableActionToQMenuAndActionHash(spatialAudioMenu, MenuOption::AudioSpatialProcessingWithDiffusions, - Qt::CTRL | Qt::SHIFT | Qt::Key_W, - true); - - addCheckableActionToQMenuAndActionHash(spatialAudioMenu, MenuOption::AudioSpatialProcessingRenderPaths, - Qt::CTRL | Qt::SHIFT | Qt::Key_R, - true); - - addCheckableActionToQMenuAndActionHash(spatialAudioMenu, MenuOption::AudioSpatialProcessingSlightlyRandomSurfaces, - Qt::CTRL | Qt::SHIFT | Qt::Key_X, - true); - - addCheckableActionToQMenuAndActionHash(spatialAudioMenu, MenuOption::AudioSpatialProcessingProcessLocalAudio, - Qt::CTRL | Qt::SHIFT | Qt::Key_A, - true); - - addCheckableActionToQMenuAndActionHash(spatialAudioMenu, MenuOption::AudioSpatialProcessingDontDistanceAttenuate, - Qt::CTRL | Qt::SHIFT | Qt::Key_Y, - false); - - addCheckableActionToQMenuAndActionHash(spatialAudioMenu, MenuOption::AudioSpatialProcessingAlternateDistanceAttenuate, - Qt::CTRL | Qt::SHIFT | Qt::Key_U, - false); - addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::AudioStats, Qt::CTRL | Qt::Key_A, false, diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 7e153eba5e..6ba34ca2b9 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -341,18 +341,6 @@ namespace MenuOption { const QString AudioScopeTwentyFrames = "Twenty"; const QString AudioStats = "Audio Stats"; const QString AudioStatsShowInjectedStreams = "Audio Stats Show Injected Streams"; - const QString AudioSpatialProcessingAlternateDistanceAttenuate = "Alternate distance attenuation"; - const QString AudioSpatialProcessing = "Audio Spatial Processing"; - const QString AudioSpatialProcessingDontDistanceAttenuate = "Don't calculate distance attenuation"; - const QString AudioSpatialProcessingHeadOriented = "Head Oriented"; - const QString AudioSpatialProcessingIncludeOriginal = "Includes Network Original"; - const QString AudioSpatialProcessingPreDelay = "Add Pre-Delay"; - const QString AudioSpatialProcessingProcessLocalAudio = "Process Local Audio"; - const QString AudioSpatialProcessingRenderPaths = "Render Paths"; - const QString AudioSpatialProcessingSeparateEars = "Separate Ears"; - const QString AudioSpatialProcessingSlightlyRandomSurfaces = "Slightly Random Surfaces"; - const QString AudioSpatialProcessingStereoSource = "Stereo Source"; - const QString AudioSpatialProcessingWithDiffusions = "With Diffusions"; const QString AudioSourceInject = "Generated Audio"; const QString AudioSourcePinkNoise = "Pink Noise"; const QString AudioSourceSine440 = "Sine 440hz"; diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index e0e589b627..953c964afd 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -460,7 +460,8 @@ void Stats::display( VoxelSystem* voxels = Application::getInstance()->getVoxels(); lines = _expanded ? 14 : 3; - if (_expanded && Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessing)) { + bool wantSpatialProcessing = false; // Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessing) + if (_expanded && wantSpatialProcessing) { lines += 10; // spatial audio processing adds 1 spacing line and 8 extra lines of info } @@ -652,7 +653,7 @@ void Stats::display( drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)voxelStats.str().c_str(), color); } - if (_expanded && Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessing)) { + if (_expanded && wantSpatialProcessing) { verticalOffset += STATS_PELS_PER_LINE; // space one line... const AudioReflector* audioReflector = Application::getInstance()->getAudioReflector(); @@ -660,23 +661,24 @@ void Stats::display( // add some reflection stats char reflectionsStatus[128]; + bool includeOriginal = true; //Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingIncludeOriginal) + bool separateEars = true; //Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingSeparateEars) + bool stereoSource = true; //Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingStereoSource) + bool randomSurfaces = true; //Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingSlightlyRandomSurfaces) + sprintf(reflectionsStatus, "Reflections: %d, Original: %s, Ears: %s, Source: %s, Normals: %s", audioReflector->getReflections(), - (Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingIncludeOriginal) - ? "included" : "silent"), - (Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingSeparateEars) - ? "two" : "one"), - (Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingStereoSource) - ? "stereo" : "mono"), - (Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingSlightlyRandomSurfaces) - ? "random" : "regular") + (includeOriginal ? "included" : "silent"), + (separateEars ? "two" : "one"), + (stereoSource ? "stereo" : "mono"), + (randomSurfaces ? "random" : "regular") ); verticalOffset += STATS_PELS_PER_LINE; drawText(horizontalOffset, verticalOffset, scale, rotation, font, reflectionsStatus, color); - float preDelay = Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingPreDelay) ? - audioReflector->getPreDelay() : 0.0f; + bool wantPreDelay = true; //Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingPreDelay) + float preDelay = wantPreDelay ? audioReflector->getPreDelay() : 0.0f; sprintf(reflectionsStatus, "Delay: pre: %6.3f, average %6.3f, max %6.3f, min %6.3f, speed: %6.3f", preDelay, @@ -688,12 +690,12 @@ void Stats::display( verticalOffset += STATS_PELS_PER_LINE; drawText(horizontalOffset, verticalOffset, scale, rotation, font, reflectionsStatus, color); - - bool distanceAttenuationDisabled = Menu::getInstance()->isOptionChecked( - MenuOption::AudioSpatialProcessingDontDistanceAttenuate); - bool alternateDistanceAttenuationEnabled = Menu::getInstance()->isOptionChecked( - MenuOption::AudioSpatialProcessingAlternateDistanceAttenuate); + //Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingDontDistanceAttenuate); + bool distanceAttenuationDisabled = false; + + // Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingAlternateDistanceAttenuate); + bool alternateDistanceAttenuationEnabled = false; sprintf(reflectionsStatus, "Attenuation: average %5.3f, max %5.3f, min %5.3f, %s: %5.3f", audioReflector->getAverageAttenuation(), @@ -706,15 +708,14 @@ void Stats::display( verticalOffset += STATS_PELS_PER_LINE; drawText(horizontalOffset, verticalOffset, scale, rotation, font, reflectionsStatus, color); - sprintf(reflectionsStatus, "Local Audio: %s Attenuation: %5.3f", - (Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingProcessLocalAudio) - ? "yes" : "no"), + bool localAudio = true; // Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingProcessLocalAudio); + sprintf(reflectionsStatus, "Local Audio: %s Attenuation: %5.3f", (localAudio ? "yes" : "no"), audioReflector->getLocalAudioAttenuationFactor()); verticalOffset += STATS_PELS_PER_LINE; drawText(horizontalOffset, verticalOffset, scale, rotation, font, reflectionsStatus, color); - bool diffusionEnabled = Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingWithDiffusions); + bool diffusionEnabled = true; //Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingWithDiffusions); int fanout = diffusionEnabled ? audioReflector->getDiffusionFanout() : 0; int diffusionPaths = diffusionEnabled ? audioReflector->getDiffusionPathCount() : 0; sprintf(reflectionsStatus, "Diffusion: %s, Fanout: %d, Paths: %d", From 68e2df8fc2e02dc0223ebe271ac90a48726936b9 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 24 Nov 2014 14:35:42 -0800 Subject: [PATCH 051/502] add a emissive parameter value to the lightmap shaders --- interface/resources/shaders/model.vert | 2 +- .../resources/shaders/model_lightmap.frag | 5 +++-- .../resources/shaders/model_lightmap.vert | 4 ++-- .../shaders/model_lightmap_normal_map.frag | 5 +++-- .../model_lightmap_normal_specular_map.frag | 5 +++-- .../shaders/model_lightmap_specular_map.frag | 5 +++-- .../resources/shaders/model_normal_map.vert | 2 +- interface/src/gpu/Batch.h | 2 ++ interface/src/gpu/GLBackend.cpp | 18 ++++++++++++++++++ interface/src/gpu/GLBackend.h | 1 + interface/src/renderer/GeometryCache.cpp | 2 ++ interface/src/renderer/Model.cpp | 5 +++++ interface/src/renderer/Model.h | 1 + 13 files changed, 45 insertions(+), 12 deletions(-) diff --git a/interface/resources/shaders/model.vert b/interface/resources/shaders/model.vert index 5ae6ea1cb6..bb0cb32d05 100644 --- a/interface/resources/shaders/model.vert +++ b/interface/resources/shaders/model.vert @@ -26,7 +26,7 @@ void main(void) { gl_FrontColor = gl_Color * gl_FrontMaterial.diffuse; // and the texture coordinates - gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.f, 1.f); + gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.0, 1.0); // use standard pipeline transform gl_Position = ftransform(); diff --git a/interface/resources/shaders/model_lightmap.frag b/interface/resources/shaders/model_lightmap.frag index 67d9cd0218..b93f0abc6f 100644 --- a/interface/resources/shaders/model_lightmap.frag +++ b/interface/resources/shaders/model_lightmap.frag @@ -14,8 +14,9 @@ // the diffuse texture uniform sampler2D diffuseMap; -// the emissive map texture +// the emissive map texture and parameters uniform sampler2D emissiveMap; +uniform vec2 emissiveParams; // the alpha threshold uniform float alphaThreshold; @@ -30,7 +31,7 @@ void main(void) { // set the diffuse, normal, specular data vec4 diffuse = texture2D(diffuseMap, gl_TexCoord[0].st); vec4 emissive = texture2D(emissiveMap, interpolatedTexcoord1.st); - gl_FragData[0] = vec4(gl_Color.rgb * diffuse.rgb * (vec3(0.1) + 4 * emissive.rgb), mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); + gl_FragData[0] = vec4(gl_Color.rgb * diffuse.rgb * (vec3(emissiveParams.x) + emissiveParams.y * emissive.rgb), mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); gl_FragData[1] = normalize(normal) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0); gl_FragData[2] = vec4(gl_FrontMaterial.specular.rgb, gl_FrontMaterial.shininess / 128.0); } diff --git a/interface/resources/shaders/model_lightmap.vert b/interface/resources/shaders/model_lightmap.vert index 021db11796..ff1b07e503 100644 --- a/interface/resources/shaders/model_lightmap.vert +++ b/interface/resources/shaders/model_lightmap.vert @@ -31,8 +31,8 @@ void main(void) { gl_FrontColor = gl_Color * gl_FrontMaterial.diffuse; // and the texture coordinates - gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.f, 1.f); - interpolatedTexcoord1 = vec2(texcoordMatrices[1] * vec4(texcoord1.xy, 0.f, 1.f)).xy; + 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; // use standard pipeline transform gl_Position = ftransform(); diff --git a/interface/resources/shaders/model_lightmap_normal_map.frag b/interface/resources/shaders/model_lightmap_normal_map.frag index 6d3e3aa861..475126eb0c 100644 --- a/interface/resources/shaders/model_lightmap_normal_map.frag +++ b/interface/resources/shaders/model_lightmap_normal_map.frag @@ -17,8 +17,9 @@ uniform sampler2D diffuseMap; // the normal map texture uniform sampler2D normalMap; -// the emissive map texture +// the emissive map texture and parameters uniform sampler2D emissiveMap; +uniform vec2 emissiveParams; // the alpha threshold uniform float alphaThreshold; @@ -43,7 +44,7 @@ void main(void) { // set the diffuse, normal, specular data vec4 diffuse = texture2D(diffuseMap, gl_TexCoord[0].st); vec4 emissive = texture2D(emissiveMap, interpolatedTexcoord1.st); - gl_FragData[0] = vec4(gl_Color.rgb * diffuse.rgb * (vec3(0.1) + 4 * emissive.rgb), mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); + gl_FragData[0] = vec4(gl_Color.rgb * diffuse.rgb * (vec3(emissiveParams.x) + emissiveParams.y * emissive.rgb), mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); gl_FragData[1] = viewNormal + vec4(0.5, 0.5, 0.5, 1.0); gl_FragData[2] = vec4(gl_FrontMaterial.specular.rgb, gl_FrontMaterial.shininess / 128.0); } diff --git a/interface/resources/shaders/model_lightmap_normal_specular_map.frag b/interface/resources/shaders/model_lightmap_normal_specular_map.frag index 89333bbcef..4d0d29ed71 100644 --- a/interface/resources/shaders/model_lightmap_normal_specular_map.frag +++ b/interface/resources/shaders/model_lightmap_normal_specular_map.frag @@ -14,8 +14,9 @@ // the diffuse texture uniform sampler2D diffuseMap; -// the emissive map texture +// the emissive map texture and parameters uniform sampler2D emissiveMap; +uniform vec2 emissiveParams; // the normal map texture uniform sampler2D normalMap; @@ -46,7 +47,7 @@ void main(void) { // set the diffuse, normal, specular data vec4 diffuse = texture2D(diffuseMap, gl_TexCoord[0].st); vec4 emissive = texture2D(emissiveMap, interpolatedTexcoord1.st); - gl_FragData[0] = vec4(gl_Color.rgb * diffuse.rgb * (vec3(0.1) + 4 * emissive.rgb), mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); + gl_FragData[0] = vec4(gl_Color.rgb * diffuse.rgb * (vec3(emissiveParams.x) + emissiveParams.y * emissive.rgb), mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); gl_FragData[1] = viewNormal + vec4(0.5, 0.5, 0.5, 1.0); gl_FragData[2] = vec4(gl_FrontMaterial.specular.rgb * texture2D(specularMap, gl_TexCoord[0].st).rgb, gl_FrontMaterial.shininess / 128.0); diff --git a/interface/resources/shaders/model_lightmap_specular_map.frag b/interface/resources/shaders/model_lightmap_specular_map.frag index 3526ecdf9c..c616764cae 100644 --- a/interface/resources/shaders/model_lightmap_specular_map.frag +++ b/interface/resources/shaders/model_lightmap_specular_map.frag @@ -14,8 +14,9 @@ // the diffuse texture uniform sampler2D diffuseMap; -// the emissive map texture +// the emissive map texture and parameters uniform sampler2D emissiveMap; +uniform vec2 emissiveParams; // the specular texture uniform sampler2D specularMap; @@ -32,7 +33,7 @@ void main(void) { // set the diffuse, normal, specular data vec4 diffuse = texture2D(diffuseMap, gl_TexCoord[0].st); vec4 emissive = texture2D(emissiveMap, interpolatedTexcoord1.st); - gl_FragData[0] = vec4(gl_Color.rgb * diffuse.rgb * (vec3(0.1) + 4 * emissive.rgb), mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); + gl_FragData[0] = vec4(gl_Color.rgb * diffuse.rgb * (vec3(emissiveParams.x) + emissiveParams.y * emissive.rgb), mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); gl_FragData[1] = normalize(normal) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0); gl_FragData[2] = vec4(gl_FrontMaterial.specular.rgb * texture2D(specularMap, gl_TexCoord[0].st).rgb, gl_FrontMaterial.shininess / 128.0); diff --git a/interface/resources/shaders/model_normal_map.vert b/interface/resources/shaders/model_normal_map.vert index 2e98b8c4fc..3d91a75c63 100644 --- a/interface/resources/shaders/model_normal_map.vert +++ b/interface/resources/shaders/model_normal_map.vert @@ -33,7 +33,7 @@ void main(void) { gl_FrontColor = gl_Color * gl_FrontMaterial.diffuse; // and the texture coordinates - gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.f, 1.f); + gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.0, 1.0); // use standard pipeline transform gl_Position = ftransform(); diff --git a/interface/src/gpu/Batch.h b/interface/src/gpu/Batch.h index d006473b50..5304740dd3 100644 --- a/interface/src/gpu/Batch.h +++ b/interface/src/gpu/Batch.h @@ -116,6 +116,7 @@ public: void _glUseProgram(GLuint program); void _glUniform1f(GLint location, GLfloat v0); + void _glUniform2f(GLint location, GLfloat v0, GLfloat v1); void _glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); void _glMatrixMode(GLenum mode); @@ -185,6 +186,7 @@ public: COMMAND_glUseProgram, COMMAND_glUniform1f, + COMMAND_glUniform2f, COMMAND_glUniformMatrix4fv, COMMAND_glMatrixMode, diff --git a/interface/src/gpu/GLBackend.cpp b/interface/src/gpu/GLBackend.cpp index d6e1a011a3..1f8e7bf99f 100644 --- a/interface/src/gpu/GLBackend.cpp +++ b/interface/src/gpu/GLBackend.cpp @@ -53,6 +53,7 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] = (&::gpu::GLBackend::do_glUseProgram), (&::gpu::GLBackend::do_glUniform1f), + (&::gpu::GLBackend::do_glUniform2f), (&::gpu::GLBackend::do_glUniformMatrix4fv), (&::gpu::GLBackend::do_glMatrixMode), @@ -691,6 +692,23 @@ void GLBackend::do_glUniform1f(Batch& batch, uint32 paramOffset) { CHECK_GL_ERROR(); } +void Batch::_glUniform2f(GLint location, GLfloat v0, GLfloat v1) { + ADD_COMMAND_GL(glUniform2f); + + _params.push_back(v1); + _params.push_back(v0); + _params.push_back(location); + + DO_IT_NOW(_glUniform2f, 1); +} +void GLBackend::do_glUniform2f(Batch& batch, uint32 paramOffset) { + glUniform2f( + batch._params[paramOffset + 2]._int, + batch._params[paramOffset + 1]._float, + batch._params[paramOffset + 0]._float); + CHECK_GL_ERROR(); +} + void Batch::_glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) { ADD_COMMAND_GL(glUniformMatrix4fv); diff --git a/interface/src/gpu/GLBackend.h b/interface/src/gpu/GLBackend.h index 71869229fd..0e4b38d89e 100644 --- a/interface/src/gpu/GLBackend.h +++ b/interface/src/gpu/GLBackend.h @@ -147,6 +147,7 @@ protected: void do_glUseProgram(Batch& batch, uint32 paramOffset); void do_glUniform1f(Batch& batch, uint32 paramOffset); + void do_glUniform2f(Batch& batch, uint32 paramOffset); void do_glUniformMatrix4fv(Batch& batch, uint32 paramOffset); void do_glMatrixMode(Batch& batch, uint32 paramOffset); diff --git a/interface/src/renderer/GeometryCache.cpp b/interface/src/renderer/GeometryCache.cpp index 04ff7bdecd..ab27678546 100644 --- a/interface/src/renderer/GeometryCache.cpp +++ b/interface/src/renderer/GeometryCache.cpp @@ -830,6 +830,8 @@ void GeometryReader::run() { } try { QMetaObject::invokeMethod(geometry.data(), "setGeometry", Q_ARG(const FBXGeometry&, + + _url.path().toLower().endsWith(".svo") ? readSVO(_reply->readAll()) : readFBX(_reply->readAll(), _mapping))); } catch (const QString& error) { diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 3f68201386..2c43113b62 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -160,6 +160,8 @@ void Model::initProgram(ProgramObject& program, Model::Locations& locations, int locations.texcoordMatrices = program.uniformLocation("texcoordMatrices"); + locations.emissiveParams = program.uniformLocation("emissiveParams"); + program.setUniformValue("diffuseMap", 0); @@ -2378,6 +2380,9 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod } if (locations->emissiveTextureUnit >= 0) { + assert(locations->emissiveParams >= 0); // we should have the emissiveParams defined in the shader + GLBATCH(glUniform2f)(locations->emissiveParams, 0.1f, 4.0f); + GLBATCH(glActiveTexture)(GL_TEXTURE0 + locations->emissiveTextureUnit); Texture* emissiveMap = networkPart.emissiveTexture.data(); GLBATCH(glBindTexture)(GL_TEXTURE_2D, !emissiveMap ? diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 7a3457423e..d24e4d9f2e 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -329,6 +329,7 @@ private: int texcoordMatrices; int specularTextureUnit; int emissiveTextureUnit; + int emissiveParams; }; static Locations _locations; From 6a63099a0f339b4aae9d792b804209cec8bfeed0 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 24 Nov 2014 15:24:20 -0800 Subject: [PATCH 052/502] Fixed syntax issues and review critics, put all the debugging code in a #define block --- interface/src/renderer/GeometryCache.cpp | 1 - interface/src/renderer/Model.cpp | 7 +-- libraries/fbx/src/FBXReader.cpp | 57 +++++++++++++++--------- 3 files changed, 39 insertions(+), 26 deletions(-) diff --git a/interface/src/renderer/GeometryCache.cpp b/interface/src/renderer/GeometryCache.cpp index ab27678546..c7d8b7fc8a 100644 --- a/interface/src/renderer/GeometryCache.cpp +++ b/interface/src/renderer/GeometryCache.cpp @@ -971,7 +971,6 @@ void NetworkGeometry::setGeometry(const FBXGeometry& geometry) { int clusterWeightsOffset = clusterIndicesOffset + mesh.clusterIndices.size() * sizeof(glm::vec4); networkMesh._vertexBuffer->resize(clusterWeightsOffset + mesh.clusterWeights.size() * sizeof(glm::vec4)); - //networkMesh.vertexBuffer.allocate(clusterWeightsOffset + mesh.clusterWeights.size() * sizeof(glm::vec4)); networkMesh._vertexBuffer->setSubData(0, mesh.vertices.size() * sizeof(glm::vec3), (gpu::Resource::Byte*) mesh.vertices.constData()); networkMesh._vertexBuffer->setSubData(normalsOffset, mesh.normals.size() * sizeof(glm::vec3), (gpu::Resource::Byte*) mesh.normals.constData()); diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 2c43113b62..ddcdfe3a84 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -387,8 +387,6 @@ void Model::init() { _skinTranslucentProgram.link(); initSkinProgram(_skinTranslucentProgram, _skinTranslucentLocations); - - } } @@ -1813,7 +1811,7 @@ void Model::segregateMeshGroups() { bool translucentMesh = networkMesh.getTranslucentPartCount(mesh) == networkMesh.parts.size(); bool hasTangents = !mesh.tangents.isEmpty(); bool hasSpecular = mesh.hasSpecularTexture(); - bool haslightmap = mesh.hasEmissiveTexture(); + bool hasLightmap = mesh.hasEmissiveTexture(); bool isSkinned = state.clusterMatrices.size() > 1; QString materialID; @@ -1832,7 +1830,7 @@ void Model::segregateMeshGroups() { qDebug() << "materialID:" << materialID << "parts:" << mesh.parts.size(); } - if ( !haslightmap) { + if (!hasLightmap) { if (translucentMesh && !hasTangents && !hasSpecular && !isSkinned) { _unsortedMeshesTranslucent.insertMulti(materialID, i); @@ -2387,7 +2385,6 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod Texture* emissiveMap = networkPart.emissiveTexture.data(); GLBATCH(glBindTexture)(GL_TEXTURE_2D, !emissiveMap ? Application::getInstance()->getTextureCache()->getWhiteTextureID() : emissiveMap->getID()); - // GLBATCH(glBindTexture)(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getWhiteTextureID()); GLBATCH(glActiveTexture)(GL_TEXTURE0); } diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 130f1db550..0cebacf51a 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -30,6 +30,10 @@ #include "FBXReader.h" + +// TOOL: Uncomment the following line to enable the filtering of all the unkwnon fields of a node so we can break point easily while loading a model with problems... +//#define DEBUG_FBXREADER + using namespace std; struct TextureParam { @@ -868,7 +872,9 @@ void appendIndex(MeshData& data, QVector& indices, int index) { data.extracted.mesh.vertices.append(position); data.extracted.mesh.normals.append(normal); data.extracted.mesh.texCoords.append(vertex.texCoord); - if (hasMoreTexcoords) { data.extracted.mesh.texCoords1.append(vertex.texCoord1); } + if (hasMoreTexcoords) { + data.extracted.mesh.texCoords1.append(vertex.texCoord1); + } } else { indices.append(*it); data.extracted.mesh.normals[*it] += normal; @@ -911,7 +917,6 @@ ExtractedMesh extractMesh(const FBXNode& object) { if (child.properties.at(0).toInt() == 0) { AttributeData attrib; attrib.index = child.properties.at(0).toInt(); - int unknown = 0; foreach (const FBXNode& subdata, child.children) { if (subdata.name == "UV") { data.texCoords = createVec2Vector(getDoubleVector(subdata)); @@ -921,22 +926,25 @@ ExtractedMesh extractMesh(const FBXNode& object) { attrib.texCoordIndices = getIntVector(subdata); } else if (subdata.name == "Name") { attrib.name = subdata.properties.at(0).toString().toStdString(); - } else { + } +#if defined(DEBUG_FBXREADER) + else { + int unknown = 0; std::string subname = subdata.name.data(); - if (subdata.name == "Version") { - } else if (subdata.name == "MappingInformationType") { - } else if (subdata.name == "ReferenceInformationType") { + if ( (subdata.name == "Version") + || (subdata.name == "MappingInformationType") + || (subdata.name == "ReferenceInformationType") ) { } else { unknown++; } } +#endif } data.extracted.texcoordSetMap.insert(QString(attrib.name.c_str()), data.attributes.size()); data.attributes.push_back(attrib); } else { AttributeData attrib; attrib.index = child.properties.at(0).toInt(); - int unknown = 0; foreach (const FBXNode& subdata, child.children) { if (subdata.name == "UV") { attrib.texCoords = createVec2Vector(getDoubleVector(subdata)); @@ -944,15 +952,19 @@ ExtractedMesh extractMesh(const FBXNode& object) { attrib.texCoordIndices = getIntVector(subdata); } else if (subdata.name == "Name") { attrib.name = subdata.properties.at(0).toString().toStdString(); - } else { + } +#if defined(DEBUG_FBXREADER) + else { + int unknown = 0; std::string subname = subdata.name.data(); - if (subdata.name == "Version") { - } else if (subdata.name == "MappingInformationType") { - } else if (subdata.name == "ReferenceInformationType") { + if ( (subdata.name == "Version") + || (subdata.name == "MappingInformationType") + || (subdata.name == "ReferenceInformationType") ) { } else { unknown++; } } +#endif } QHash::iterator it = data.extracted.texcoordSetMap.find(QString(attrib.name.c_str())); @@ -961,7 +973,7 @@ ExtractedMesh extractMesh(const FBXNode& object) { data.attributes.push_back(attrib); } else { // WTF same names for different UVs? - unknown = data.attributes.size(); + qDebug() << "LayerElementUV #" << attrib.index << " is reusing the same name as #" << (*it) << ". Skip this texcoord attribute."; } } } else if (child.name == "LayerElementMaterial") { @@ -1145,12 +1157,10 @@ FBXTexture getTexture(const QString& textureID, texture.transform.setTranslation(p.translation); texture.transform.setRotation(glm::quat(glm::radians(p.rotation))); texture.transform.setScale(p.scaling); - if (p.UVSet != "map1" || (p.UVSet != "UVSet0")) { + if ((p.UVSet != "map1") || (p.UVSet != "UVSet0")) { texture.texcoordSet = 1; } - texture.texcoordSetName = p.UVSet; - } return texture; } @@ -1260,7 +1270,9 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) } } QMultiHash blendshapeChannelIndices; +#if defined(DEBUG_FBXREADER) int unknown = 0; +#endif FBXGeometry geometry; float unitScaleFactor = 1.0f; foreach (const FBXNode& child, node.children) { @@ -1466,7 +1478,6 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) TextureParam tex; bool texparam = false; foreach (const FBXNode& subobject, object.children) { - std::string subname = subobject.name.data(); if (subobject.name == "RelativeFilename") { // trim off any path information QByteArray filename = subobject.properties.at(0).toByteArray(); @@ -1491,7 +1502,6 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) subobject.properties.at(2).value(), subobject.properties.at(3).value())); } else if (subobject.name == "Properties70") { - QByteArray propertyName; int index; propertyName = "P"; @@ -1499,7 +1509,6 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) foreach (const FBXNode& property, subobject.children) { if (property.name == propertyName) { QString v = property.properties.at(0).toString(); - std::string propName = v.toStdString(); if (property.properties.at(0) == "UVSet") { tex.assign(tex.UVSet, property.properties.at(index).toString().toStdString()); } else if (property.properties.at(0) == "CurrentTextureBlendMode") { @@ -1512,20 +1521,28 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) tex.assign(tex.rotation, getVec3(property.properties, index)); } else if (property.properties.at(0) == "Scaling") { tex.assign(tex.scaling, getVec3(property.properties, index)); - } else { + } +#if defined(DEBUG_FBXREADER) + else { + std::string propName = v.toStdString(); unknown++; } +#endif } } - } else { + } +#if defined(DEBUG_FBXREADER) + else { if (subobject.name == "Type") { } else if (subobject.name == "Version") { } else if (subobject.name == "FileName") { } else if (subobject.name == "Media") { } else { + std::string subname = subobject.name.data(); unknown++; } } +#endif } if (!tex.isDefault) { From 1f10a44ae496d7017450e145c916e86891377a54 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 24 Nov 2014 15:38:12 -0800 Subject: [PATCH 053/502] More typos in glsl --- interface/resources/shaders/model_lightmap_normal_map.vert | 4 ++-- interface/resources/shaders/skin_model.vert | 2 +- interface/resources/shaders/skin_model_normal_map.vert | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/interface/resources/shaders/model_lightmap_normal_map.vert b/interface/resources/shaders/model_lightmap_normal_map.vert index 08eca835c9..4faf5688cf 100644 --- a/interface/resources/shaders/model_lightmap_normal_map.vert +++ b/interface/resources/shaders/model_lightmap_normal_map.vert @@ -38,8 +38,8 @@ void main(void) { gl_FrontColor = gl_Color * gl_FrontMaterial.diffuse; // and the texture coordinates - gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.f, 1.f); - interpolatedTexcoord1 = vec2(texcoordMatrices[1] * vec4(texcoord1.xy, 0.f, 1.f)).xy; + 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; // use standard pipeline transform gl_Position = ftransform(); diff --git a/interface/resources/shaders/skin_model.vert b/interface/resources/shaders/skin_model.vert index a8c25e885b..fd4dea51bb 100644 --- a/interface/resources/shaders/skin_model.vert +++ b/interface/resources/shaders/skin_model.vert @@ -40,7 +40,7 @@ void main(void) { gl_FrontColor = gl_FrontMaterial.diffuse; // and the texture coordinates - gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.f, 1.f); + gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.0, 1.0); gl_Position = gl_ModelViewProjectionMatrix * position; } diff --git a/interface/resources/shaders/skin_model_normal_map.vert b/interface/resources/shaders/skin_model_normal_map.vert index bbe5da35af..5814dfc584 100644 --- a/interface/resources/shaders/skin_model_normal_map.vert +++ b/interface/resources/shaders/skin_model_normal_map.vert @@ -48,7 +48,7 @@ void main(void) { gl_FrontColor = gl_FrontMaterial.diffuse; // and the texture coordinates - gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.f, 1.f); + gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.0, 1.0); gl_Position = gl_ModelViewProjectionMatrix * interpolatedPosition; } From 4fbb0949786cfed4138610a32bf8b6db798756a4 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 24 Nov 2014 15:39:34 -0800 Subject: [PATCH 054/502] No reason to change that... --- interface/resources/shaders/model_normal_map.frag | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/shaders/model_normal_map.frag b/interface/resources/shaders/model_normal_map.frag index af107e9d3c..f5a1047b2b 100644 --- a/interface/resources/shaders/model_normal_map.frag +++ b/interface/resources/shaders/model_normal_map.frag @@ -4,7 +4,7 @@ // model_normal_map.frag // fragment shader // -// Created by Andrzej Kapolka on 10/14/13. +// Created by Andrzej Kapolka on 10/29/13. // Copyright 2013 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. From af875eb5af43cf9748fcb1fb82e7aec2f994c4bc Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Mon, 24 Nov 2014 16:45:34 -0800 Subject: [PATCH 055/502] Allow shared objects to write extra, non-property data. --- libraries/metavoxels/src/Bitstream.cpp | 46 ++++++++++++++++++++--- libraries/metavoxels/src/Bitstream.h | 12 ++++++ libraries/metavoxels/src/SharedObject.cpp | 16 ++++++++ libraries/metavoxels/src/SharedObject.h | 15 +++++++- 4 files changed, 83 insertions(+), 6 deletions(-) diff --git a/libraries/metavoxels/src/Bitstream.cpp b/libraries/metavoxels/src/Bitstream.cpp index 7bfd9c91ff..e4af43feee 100644 --- a/libraries/metavoxels/src/Bitstream.cpp +++ b/libraries/metavoxels/src/Bitstream.cpp @@ -1156,6 +1156,16 @@ Bitstream& Bitstream::operator<(const ObjectStreamer* streamer) { return *this; } +static MappedObjectStreamer* createMappedObjectStreamer(const QMetaObject* metaObject, + const QVector& properties) { + for (const QMetaObject* super = metaObject; super; super = super->superClass()) { + if (super == &SharedObject::staticMetaObject) { + return new SharedObjectStreamer(metaObject, properties); + } + } + return new MappedObjectStreamer(metaObject, properties); +} + Bitstream& Bitstream::operator>(ObjectStreamerPointer& streamer) { QByteArray className; *this >> className; @@ -1231,7 +1241,7 @@ Bitstream& Bitstream::operator>(ObjectStreamerPointer& streamer) { } else if (metaObject) { const QVector& localProperties = streamer->getProperties(); if (localProperties.size() != properties.size()) { - streamer = ObjectStreamerPointer(new MappedObjectStreamer(metaObject, properties)); + streamer = ObjectStreamerPointer(createMappedObjectStreamer(metaObject, properties)); return *this; } for (int i = 0; i < localProperties.size(); i++) { @@ -1239,13 +1249,13 @@ Bitstream& Bitstream::operator>(ObjectStreamerPointer& streamer) { const StreamerPropertyPair& localProperty = localProperties.at(i); if (property.first != localProperty.first || property.second.propertyIndex() != localProperty.second.propertyIndex()) { - streamer = ObjectStreamerPointer(new MappedObjectStreamer(metaObject, properties)); + streamer = ObjectStreamerPointer(createMappedObjectStreamer(metaObject, properties)); return *this; } } return *this; } - streamer = ObjectStreamerPointer(new MappedObjectStreamer(metaObject, properties)); + streamer = ObjectStreamerPointer(createMappedObjectStreamer(metaObject, properties)); return *this; } @@ -1671,7 +1681,7 @@ QHash Bitstream::createObjectStreamer properties.append(StreamerPropertyPair(streamer->getSelf(), property)); } } - ObjectStreamerPointer streamer = ObjectStreamerPointer(new MappedObjectStreamer(metaObject, properties)); + ObjectStreamerPointer streamer = ObjectStreamerPointer(createMappedObjectStreamer(metaObject, properties)); streamer->_self = streamer; objectStreamers.insert(metaObject, streamer.data()); } @@ -2122,7 +2132,7 @@ JSONReader::JSONReader(const QJsonDocument& document, Bitstream::GenericsMode ge if (matches) { _objectStreamers.insert(name, baseStreamer->getSelf()); } else { - _objectStreamers.insert(name, ObjectStreamerPointer(new MappedObjectStreamer(metaObject, properties))); + _objectStreamers.insert(name, ObjectStreamerPointer(createMappedObjectStreamer(metaObject, properties))); } } @@ -2437,6 +2447,32 @@ QObject* MappedObjectStreamer::readRawDelta(Bitstream& in, const QObject* refere return object; } +SharedObjectStreamer::SharedObjectStreamer(const QMetaObject* metaObject, const QVector& properties) : + MappedObjectStreamer(metaObject, properties) { +} + +void SharedObjectStreamer::write(Bitstream& out, const QObject* object) const { + MappedObjectStreamer::write(out, object); + static_cast(object)->writeExtra(out); +} + +void SharedObjectStreamer::writeRawDelta(Bitstream& out, const QObject* object, const QObject* reference) const { + MappedObjectStreamer::writeRawDelta(out, object, reference); + static_cast(object)->writeExtraDelta(out, static_cast(reference)); +} + +QObject* SharedObjectStreamer::read(Bitstream& in, QObject* object) const { + QObject* result = MappedObjectStreamer::read(in, object); + static_cast(result)->readExtra(in); + return result; +} + +QObject* SharedObjectStreamer::readRawDelta(Bitstream& in, const QObject* reference, QObject* object) const { + QObject* result = MappedObjectStreamer::readRawDelta(in, reference, object); + static_cast(result)->readExtraDelta(in, static_cast(reference)); + return result; +} + GenericObjectStreamer::GenericObjectStreamer(const QByteArray& name, const QVector& properties, const QByteArray& hash) : ObjectStreamer(&GenericSharedObject::staticMetaObject), diff --git a/libraries/metavoxels/src/Bitstream.h b/libraries/metavoxels/src/Bitstream.h index 8e40ed9240..e5aa30fac5 100644 --- a/libraries/metavoxels/src/Bitstream.h +++ b/libraries/metavoxels/src/Bitstream.h @@ -1133,6 +1133,18 @@ private: QVector _properties; }; +/// A streamer that maps to a local shared object class. Shared objects can write extra, non-property data. +class SharedObjectStreamer : public MappedObjectStreamer { +public: + + SharedObjectStreamer(const QMetaObject* metaObject, const QVector& properties); + + virtual void write(Bitstream& out, const QObject* object) const; + virtual void writeRawDelta(Bitstream& out, const QObject* object, const QObject* reference) const; + virtual QObject* read(Bitstream& in, QObject* object = NULL) const; + virtual QObject* readRawDelta(Bitstream& in, const QObject* reference, QObject* object = NULL) const; +}; + typedef QPair StreamerNamePair; /// A streamer for generic objects. diff --git a/libraries/metavoxels/src/SharedObject.cpp b/libraries/metavoxels/src/SharedObject.cpp index bf9b123a36..e57b7d9a8e 100644 --- a/libraries/metavoxels/src/SharedObject.cpp +++ b/libraries/metavoxels/src/SharedObject.cpp @@ -131,6 +131,22 @@ void SharedObject::dump(QDebug debug) const { } } +void SharedObject::writeExtra(Bitstream& out) const { + // nothing by default +} + +void SharedObject::readExtra(Bitstream& in) { + // nothing by default +} + +void SharedObject::writeExtraDelta(Bitstream& out, const SharedObject* reference) const { + // nothing by default +} + +void SharedObject::readExtraDelta(Bitstream& in, const SharedObject* reference) { + // nothing by default +} + QAtomicInt SharedObject::_nextID(1); WeakSharedObjectHash SharedObject::_weakHash; QReadWriteLock SharedObject::_weakHashLock; diff --git a/libraries/metavoxels/src/SharedObject.h b/libraries/metavoxels/src/SharedObject.h index 157987ed6f..7f44ffec82 100644 --- a/libraries/metavoxels/src/SharedObject.h +++ b/libraries/metavoxels/src/SharedObject.h @@ -24,6 +24,7 @@ class QComboBox; +class Bitstream; class SharedObject; typedef QHash > WeakSharedObjectHash; @@ -76,9 +77,21 @@ public: /// this is an instance of a superclass of the other object's class) rather than simply returning false. virtual bool equals(const SharedObject* other, bool sharedAncestry = false) const; - // Dumps the contents of this object to the debug output. + /// Dumps the contents of this object to the debug output. virtual void dump(QDebug debug = QDebug(QtDebugMsg)) const; + /// Writes the non-property contents of this object to the specified stream. + virtual void writeExtra(Bitstream& out) const; + + /// Reads the non-property contents of this object from the specified stream. + virtual void readExtra(Bitstream& in); + + /// Writes the delta-encoded non-property contents of this object to the specified stream. + virtual void writeExtraDelta(Bitstream& out, const SharedObject* reference) const; + + /// Reads the delta-encoded non-property contents of this object from the specified stream. + virtual void readExtraDelta(Bitstream& in, const SharedObject* reference); + private: int _id; From ce103acdf6c8b312d75d0234380c1eb4666ec832 Mon Sep 17 00:00:00 2001 From: dev Date: Mon, 24 Nov 2014 18:32:36 -0800 Subject: [PATCH 056/502] More debugging of the FBXReader in order to understand how to interpret the material fields --- interface/src/renderer/Model.cpp | 14 +++++++++++--- libraries/fbx/src/FBXReader.cpp | 22 ++++++++++++++++++++++ 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index ddcdfe3a84..e6dc3ce74e 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -2347,8 +2347,12 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod diffuseMap = (_dilatedTextures[i][j] = static_cast(diffuseMap)->getDilatedTexture(_pupilDilation)).data(); } - GLBATCH(glBindTexture)(GL_TEXTURE_2D, !diffuseMap ? - Application::getInstance()->getTextureCache()->getWhiteTextureID() : diffuseMap->getID()); + static bool showDiffuse = true; + if (showDiffuse && diffuseMap) { + GLBATCH(glBindTexture)(GL_TEXTURE_2D, diffuseMap->getID()); + } else { + GLBATCH(glBindTexture)(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getWhiteTextureID()); + } if (locations->texcoordMatrices >= 0) { glm::mat4 texcoordTransform[2]; @@ -2379,7 +2383,11 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod if (locations->emissiveTextureUnit >= 0) { assert(locations->emissiveParams >= 0); // we should have the emissiveParams defined in the shader - GLBATCH(glUniform2f)(locations->emissiveParams, 0.1f, 4.0f); + static float emissiveOffset = 0.1f; + static float emissiveScale = 1.0f; + //GLBATCH(glUniform2f)(locations->emissiveParams, 0.1f, 4.0f); + GLBATCH(glUniform2f)(locations->emissiveParams, emissiveOffset, emissiveScale); + GLBATCH(glActiveTexture)(GL_TEXTURE0 + locations->emissiveTextureUnit); Texture* emissiveMap = networkPart.emissiveTexture.data(); diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 0cebacf51a..b54abedc33 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -1597,9 +1597,28 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) } else if (property.properties.at(0) == "Opacity") { material.opacity = property.properties.at(index).value(); } +#if defined(DEBUG_FBXREADER) + else { + const std::string propname = property.properties.at(0).toString().toStdString(); + if (propname == "EmissiveFactor") { + } + } +#endif } } } +#if defined(DEBUG_FBXREADER) + else { + std::string propname = subobject.name.data(); + int unknown = 0; + if ( (propname == "Version") + ||(propname == "ShadingModel") + ||(propname == "Multilayer")) { + } else { + unknown++; + } + } +#endif } material.id = getID(object.properties); materials.insert(material.id, material); @@ -1687,7 +1706,10 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) } else if (type.contains("emissive")) { emissiveTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1)); + } else if (type.contains("ambient")) { + emissiveTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1)); } else { + std::string typenam = type.data(); counter++; } } From 01867e2459b81eceee5cc0e2ec623fc3211478b6 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Mon, 24 Nov 2014 18:32:47 -0800 Subject: [PATCH 057/502] Display "--" for ping values if not yet valid --- interface/src/ui/Stats.cpp | 33 +++++++++++++++++++++++-------- libraries/networking/src/Node.cpp | 1 + 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index e0e589b627..dd0c9f5a64 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -316,14 +316,14 @@ void Stats::display( horizontalOffset = _lastHorizontalOffset + _generalStatsWidth +1; if (Menu::getInstance()->isOptionChecked(MenuOption::TestPing)) { - int pingAudio = 0, pingAvatar = 0, pingVoxel = 0, pingVoxelMax = 0; + int pingAudio = -1, pingAvatar = -1, pingVoxel = -1, pingVoxelMax = -1; NodeList* nodeList = NodeList::getInstance(); SharedNodePointer audioMixerNode = nodeList->soloNodeOfType(NodeType::AudioMixer); SharedNodePointer avatarMixerNode = nodeList->soloNodeOfType(NodeType::AvatarMixer); - pingAudio = audioMixerNode ? audioMixerNode->getPingMs() : 0; - pingAvatar = avatarMixerNode ? avatarMixerNode->getPingMs() : 0; + pingAudio = audioMixerNode ? audioMixerNode->getPingMs() : -1; + pingAvatar = avatarMixerNode ? avatarMixerNode->getPingMs() : -1; // Now handle voxel servers, since there could be more than one, we average their ping times unsigned long totalPingVoxel = 0; @@ -354,12 +354,25 @@ void Stats::display( char audioPing[30]; - sprintf(audioPing, "Audio ping: %d", pingAudio); - + if (pingAudio >= 0) { + sprintf(audioPing, "Audio ping: %d", pingAudio); + } else { + sprintf(audioPing, "Audio ping: --"); + } + char avatarPing[30]; - sprintf(avatarPing, "Avatar ping: %d", pingAvatar); + if (pingAvatar >= 0) { + sprintf(avatarPing, "Avatar ping: %d", pingAvatar); + } else { + sprintf(avatarPing, "Avatar ping: --"); + } + char voxelAvgPing[30]; - sprintf(voxelAvgPing, "Voxel avg ping: %d", pingVoxel); + if (pingVoxel >= 0) { + sprintf(voxelAvgPing, "Voxel avg ping: %d", pingVoxel); + } else { + sprintf(voxelAvgPing, "Voxel avg ping: --"); + } verticalOffset += STATS_PELS_PER_LINE; drawText(horizontalOffset, verticalOffset, scale, rotation, font, audioPing, color); @@ -370,7 +383,11 @@ void Stats::display( if (_expanded) { char voxelMaxPing[30]; - sprintf(voxelMaxPing, "Voxel max ping: %d", pingVoxelMax); + if (pingVoxel >= 0) { // Average is only meaningful if pingVoxel is valid. + sprintf(voxelMaxPing, "Voxel max ping: %d", pingVoxelMax); + } else { + sprintf(voxelMaxPing, "Voxel max ping: --"); + } verticalOffset += STATS_PELS_PER_LINE; drawText(horizontalOffset, verticalOffset, scale, rotation, font, voxelMaxPing, color); diff --git a/libraries/networking/src/Node.cpp b/libraries/networking/src/Node.cpp index c2b35d3b7d..be03ba9350 100644 --- a/libraries/networking/src/Node.cpp +++ b/libraries/networking/src/Node.cpp @@ -52,6 +52,7 @@ Node::Node(const QUuid& uuid, NodeType_t type, const HifiSockAddr& publicSocket, _bytesReceivedMovingAverage(NULL), _linkedData(NULL), _isAlive(true), + _pingMs(-1), // "Uninitialized" _clockSkewUsec(0), _mutex(), _clockSkewMovingPercentile(30, 0.8f) // moving 80th percentile of 30 samples From 732ad8f9933f9eb2d8b50037ab3a6ecea244e95e Mon Sep 17 00:00:00 2001 From: David Rowe Date: Mon, 24 Nov 2014 18:33:10 -0800 Subject: [PATCH 058/502] Use valid font for Windows so that '-'s are displayed --- interface/src/Util.cpp | 3 ++- interface/src/ui/BandwidthMeter.cpp | 2 +- interface/src/ui/TextRenderer.h | 6 ++++++ 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/interface/src/Util.cpp b/interface/src/Util.cpp index c2e9a2d7e3..c4f2ec8468 100644 --- a/interface/src/Util.cpp +++ b/interface/src/Util.cpp @@ -100,7 +100,8 @@ static TextRenderer* textRenderer(int mono) { static TextRenderer* monoRenderer = TextRenderer::getInstance(MONO_FONT_FAMILY); static TextRenderer* proportionalRenderer = TextRenderer::getInstance(SANS_FONT_FAMILY, -1, -1, false, TextRenderer::SHADOW_EFFECT); - static TextRenderer* inconsolataRenderer = TextRenderer::getInstance(INCONSOLATA_FONT_FAMILY, -1, QFont::Bold, false); + static TextRenderer* inconsolataRenderer = TextRenderer::getInstance(INCONSOLATA_FONT_FAMILY, -1, INCONSOLATA_FONT_WEIGHT, + false); switch (mono) { case 1: return monoRenderer; diff --git a/interface/src/ui/BandwidthMeter.cpp b/interface/src/ui/BandwidthMeter.cpp index 327f266106..a0a8129229 100644 --- a/interface/src/ui/BandwidthMeter.cpp +++ b/interface/src/ui/BandwidthMeter.cpp @@ -50,7 +50,7 @@ BandwidthMeter::ChannelInfo BandwidthMeter::_CHANNELS[] = { }; BandwidthMeter::BandwidthMeter() : - _textRenderer(TextRenderer::getInstance(INCONSOLATA_FONT_FAMILY, -1, QFont::Bold, false)), + _textRenderer(TextRenderer::getInstance(INCONSOLATA_FONT_FAMILY, -1, INCONSOLATA_FONT_WEIGHT, false)), _scaleMaxIndex(INITIAL_SCALE_MAXIMUM_INDEX) { _channels = static_cast( malloc(sizeof(_CHANNELS)) ); diff --git a/interface/src/ui/TextRenderer.h b/interface/src/ui/TextRenderer.h index 9afb885e35..2ffd8b24b7 100644 --- a/interface/src/ui/TextRenderer.h +++ b/interface/src/ui/TextRenderer.h @@ -35,7 +35,13 @@ const char SOLID_BLOCK_CHAR = 127; #define MONO_FONT_FAMILY "Courier" // the Inconsolata font family +#ifdef Q_OS_WIN +#define INCONSOLATA_FONT_FAMILY "Fixedsys" +#define INCONSOLATA_FONT_WEIGHT QFont::Normal +#else #define INCONSOLATA_FONT_FAMILY "Inconsolata" +#define INCONSOLATA_FONT_WEIGHT QFont::Bold +#endif class Glyph; From 1c636fe6b281f4e4549e1bcb82529691123b7893 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 24 Nov 2014 20:37:09 -0800 Subject: [PATCH 059/502] more correct entity list maintenance --- libraries/entities/src/EntityTree.cpp | 49 ++++++++++++++++++++------- 1 file changed, 37 insertions(+), 12 deletions(-) diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index b25b153f44..bb201b6f86 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -653,7 +653,6 @@ void EntityTree::update() { } void EntityTree::updateChangedEntities(quint64 now, QSet& entitiesToDelete) { - // TODO: switch these to iterators so we can remove items that get deleted foreach (EntityItem* thisEntity, _changedEntities) { // check to see if the lifetime has expired, for immortal entities this is always false if (thisEntity->lifetimeHasExpired()) { @@ -675,15 +674,17 @@ void EntityTree::updateMovingEntities(quint64 now, QSet& entitiesT { PerformanceTimer perfTimer("_movingEntities"); - // TODO: switch these to iterators so we can remove items that get deleted - for (int i = 0; i < _movingEntities.size(); i++) { - EntityItem* thisEntity = _movingEntities[i]; + QList::iterator item_itr = _movingEntities.begin(); + while (item_itr != _movingEntities.end()) { + EntityItem* thisEntity = *item_itr; // always check to see if the lifetime has expired, for immortal entities this is always false if (thisEntity->lifetimeHasExpired()) { qDebug() << "Lifetime has expired for entity:" << thisEntity->getEntityItemID(); entitiesToDelete << thisEntity->getEntityItemID(); - clearEntityState(thisEntity); + // remove thisEntity from the list + item_itr = _movingEntities.erase(item_itr); + thisEntity->setSimulationState(EntityItem::Static); } else { AACube oldCube = thisEntity->getMaximumAACube(); thisEntity->update(now); @@ -694,10 +695,22 @@ void EntityTree::updateMovingEntities(quint64 now, QSet& entitiesT if (!domainBounds.touches(newCube)) { qDebug() << "Entity " << thisEntity->getEntityItemID() << " moved out of domain bounds."; entitiesToDelete << thisEntity->getEntityItemID(); - clearEntityState(thisEntity); + // remove thisEntity from the list + item_itr = _movingEntities.erase(item_itr); + thisEntity->setSimulationState(EntityItem::Static); } else { moveOperator.addEntityToMoveList(thisEntity, oldCube, newCube); - updateEntityState(thisEntity); + EntityItem::SimulationState newState = thisEntity->computeSimulationState(); + if (newState != EntityItem::Moving) { + if (newState == EntityItem::Mortal) { + _mortalEntities.push_back(thisEntity); + } + // remove thisEntity from the list + item_itr = _movingEntities.erase(item_itr); + thisEntity->setSimulationState(newState); + } else { + ++item_itr; + } } } } @@ -710,18 +723,30 @@ void EntityTree::updateMovingEntities(quint64 now, QSet& entitiesT } void EntityTree::updateMortalEntities(quint64 now, QSet& entitiesToDelete) { - // TODO: switch these to iterators so we can remove items that get deleted - for (int i = 0; i < _mortalEntities.size(); i++) { - EntityItem* thisEntity = _mortalEntities[i]; + QList::iterator item_itr = _mortalEntities.begin(); + while (item_itr != _mortalEntities.end()) { + EntityItem* thisEntity = *item_itr; thisEntity->update(now); // always check to see if the lifetime has expired, for immortal entities this is always false if (thisEntity->lifetimeHasExpired()) { qDebug() << "Lifetime has expired for entity:" << thisEntity->getEntityItemID(); entitiesToDelete << thisEntity->getEntityItemID(); - clearEntityState(thisEntity); + // remove thisEntity from the list + item_itr = _mortalEntities.erase(item_itr); + thisEntity->setSimulationState(EntityItem::Static); } else { // check to see if this entity is no longer moving - updateEntityState(thisEntity); + EntityItem::SimulationState newState = thisEntity->computeSimulationState(); + if (newState != EntityItem::Mortal) { + if (newState == EntityItem::Moving) { + _movingEntities.push_back(thisEntity); + } + // remove thisEntity from the list + item_itr = _mortalEntities.erase(item_itr); + thisEntity->setSimulationState(newState); + } else { + ++item_itr; + } } } } From 8966ab32d8cb0b40f77b19d65c15ef3d2f748ed1 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 24 Nov 2014 20:37:52 -0800 Subject: [PATCH 060/502] add lifetime to gun bullets --- examples/gun.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/examples/gun.js b/examples/gun.js index fff78496b2..2386e61539 100644 --- a/examples/gun.js +++ b/examples/gun.js @@ -96,6 +96,7 @@ function printVector(string, vector) { function shootBullet(position, velocity) { var BULLET_SIZE = 0.01; + var BULLET_LIFETIME = 20.0; var BULLET_GRAVITY = -0.02; Entities.addEntity( { type: "Sphere", @@ -103,6 +104,7 @@ function shootBullet(position, velocity) { dimensions: { x: BULLET_SIZE, y: BULLET_SIZE, z: BULLET_SIZE }, color: { red: 10, green: 10, blue: 10 }, velocity: velocity, + lifetime: BULLET_LIFETIME, gravity: { x: 0, y: BULLET_GRAVITY, z: 0 }, damping: 0 }); @@ -118,6 +120,7 @@ function shootBullet(position, velocity) { function shootTarget() { var TARGET_SIZE = 0.25; var TARGET_GRAVITY = -0.6; + var TARGET_LIFETIME = 300.0; var TARGET_UP_VELOCITY = 3.0; var TARGET_FWD_VELOCITY = 5.0; var DISTANCE_TO_LAUNCH_FROM = 3.0; @@ -140,7 +143,7 @@ function shootTarget() { color: { red: 0, green: 200, blue: 200 }, velocity: velocity, gravity: { x: 0, y: TARGET_GRAVITY, z: 0 }, - lifetime: 1000.0, + lifetime: TARGET_LIFETIME, damping: 0.99 }); // Record start time From 1b1482bab3c28e78e871a67584062b2e59ea0bb2 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 24 Nov 2014 21:00:04 -0800 Subject: [PATCH 061/502] Adjust size of stretch overlays to be smaller --- examples/libraries/entitySelectionTool.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/libraries/entitySelectionTool.js b/examples/libraries/entitySelectionTool.js index b0fc68b60c..08ac077a34 100644 --- a/examples/libraries/entitySelectionTool.js +++ b/examples/libraries/entitySelectionTool.js @@ -205,7 +205,7 @@ SelectionDisplay = (function () { var MINIMUM_DIMENSION = 0.001; - var GRABBER_DISTANCE_TO_SIZE_RATIO = 0.015; + var GRABBER_DISTANCE_TO_SIZE_RATIO = 0.0075; var spaceMode = SPACE_LOCAL; var mode = "UNKNOWN"; From 1d865ace9d41bd5336cee93d4a16f014df6c6772 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 24 Nov 2014 21:16:29 -0800 Subject: [PATCH 062/502] Add drawInFront property to Base3DOverlay --- interface/src/ui/overlays/Base3DOverlay.cpp | 16 +++++++++++++++- interface/src/ui/overlays/Base3DOverlay.h | 6 ++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/interface/src/ui/overlays/Base3DOverlay.cpp b/interface/src/ui/overlays/Base3DOverlay.cpp index 5a5bfcd937..5c6af97bf1 100644 --- a/interface/src/ui/overlays/Base3DOverlay.cpp +++ b/interface/src/ui/overlays/Base3DOverlay.cpp @@ -27,7 +27,8 @@ Base3DOverlay::Base3DOverlay() : _rotation(), _isSolid(DEFAULT_IS_SOLID), _isDashedLine(DEFAULT_IS_DASHED_LINE), - _ignoreRayIntersection(false) + _ignoreRayIntersection(false), + _drawInFront(false) { } @@ -45,9 +46,22 @@ Base3DOverlay::Base3DOverlay(const Base3DOverlay* base3DOverlay) : Base3DOverlay::~Base3DOverlay() { } +void Base3DOverlay::setDrawInFront(bool value) { + _drawInFront = value; + emit drawInFrontUpdated(value); +} + void Base3DOverlay::setProperties(const QScriptValue& properties) { Overlay::setProperties(properties); + QScriptValue drawInFront = properties.property("drawInFront"); + + if (drawInFront.isValid()) { + bool value = drawInFront.toVariant().toBool(); + setDrawInFront(value); + _drawInFront = value; + } + QScriptValue position = properties.property("position"); // if "position" property was not there, check to see if they included aliases: start, point, p1 diff --git a/interface/src/ui/overlays/Base3DOverlay.h b/interface/src/ui/overlays/Base3DOverlay.h index 8304883e3c..46d99cf3de 100644 --- a/interface/src/ui/overlays/Base3DOverlay.h +++ b/interface/src/ui/overlays/Base3DOverlay.h @@ -36,6 +36,7 @@ public: bool getIsSolidLine() const { return !_isDashedLine; } const glm::quat& getRotation() const { return _rotation; } bool getIgnoreRayIntersection() const { return _ignoreRayIntersection; } + bool getDrawInFront() const { return _drawInFront; } // setters void setPosition(const glm::vec3& position) { _position = position; } @@ -44,6 +45,7 @@ public: void setIsDashedLine(bool isDashedLine) { _isDashedLine = isDashedLine; } void setRotation(const glm::quat& value) { _rotation = value; } void setIgnoreRayIntersection(bool value) { _ignoreRayIntersection = value; } + void setDrawInFront(bool value); virtual void setProperties(const QScriptValue& properties); virtual QScriptValue getProperty(const QString& property); @@ -55,6 +57,9 @@ public: return findRayIntersection(origin, direction, distance, face); } +signals: + void drawInFrontUpdated(bool newValue); + protected: void drawDashedLine(const glm::vec3& start, const glm::vec3& end); @@ -64,6 +69,7 @@ protected: bool _isSolid; bool _isDashedLine; bool _ignoreRayIntersection; + bool _drawInFront; }; #endif // hifi_Base3DOverlay_h From e574c5766b566a2d6abc0a2d07df8c11cac88711 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 24 Nov 2014 22:28:27 -0800 Subject: [PATCH 063/502] EntityItem::setSimulationState() now public --- libraries/entities/src/EntityItem.h | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 3f63c96c4e..c1b1f243ef 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -292,16 +292,10 @@ public: uint32_t getUpdateFlags() const { return _updateFlags; } void clearUpdateFlags() { _updateFlags = 0; } -#ifdef USE_BULLET_PHYSICS - EntityMotionState* getMotionState() const { return _motionState; } - virtual EntityMotionState* createMotionState() { return NULL; } - void destroyMotionState(); -#endif // USE_BULLET_PHYSICS SimulationState getSimulationState() const { return _simulationState; } -protected: - friend class EntityTree; void setSimulationState(SimulationState state) { _simulationState = state; } +protected: virtual void initFromEntityItemID(const EntityItemID& entityItemID); // maybe useful to allow subclasses to init virtual void recalculateCollisionShape(); From 0d9855574065f6ad4a392d22a1a7936f11896aa0 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 24 Nov 2014 22:29:24 -0800 Subject: [PATCH 064/502] add EntitySimulation and SimpleEntitySimulation --- libraries/entities/src/EntitySimulation.h | 37 +++ .../entities/src/SimpleEntitySimulation.cpp | 213 ++++++++++++++++++ .../entities/src/SimpleEntitySimulation.h | 46 ++++ 3 files changed, 296 insertions(+) create mode 100644 libraries/entities/src/EntitySimulation.h create mode 100644 libraries/entities/src/SimpleEntitySimulation.cpp create mode 100644 libraries/entities/src/SimpleEntitySimulation.h diff --git a/libraries/entities/src/EntitySimulation.h b/libraries/entities/src/EntitySimulation.h new file mode 100644 index 0000000000..230e744a16 --- /dev/null +++ b/libraries/entities/src/EntitySimulation.h @@ -0,0 +1,37 @@ +// +// EntitySimulation.h +// libraries/entities/src +// +// Created by Andrew Meadows on 2014.11.24 +// 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_EntitySimulation_h +#define hifi_EntitySimulation_h + +#include + +#include "EntityItemID.h" +#include "EntityTree.h" + +class EntitySimulation { +public: + EntitySimulation(EntityTree* tree) : _myTree(tree) { assert(tree); } + virtual ~EntitySimulation() { _myTree = NULL; } + + /// \sideeffect For each EntityItem* that EntitySimulation puts on entitiesToDelete it will automatically + /// removeEntity() on any internal lists -- no need to call removeEntity() for that one later. + virtual void update(QSet& entitiesToDelete) = 0; + + virtual void addEntity(EntityItem* entity) = 0; + virtual void removeEntity(EntityItem* entity) = 0; + virtual void updateEntity(EntityItem* entity) = 0; + +protected: + EntityTree* _myTree; +}; + +#endif // hifi_EntitySimulation_h diff --git a/libraries/entities/src/SimpleEntitySimulation.cpp b/libraries/entities/src/SimpleEntitySimulation.cpp new file mode 100644 index 0000000000..d8edfb8ba7 --- /dev/null +++ b/libraries/entities/src/SimpleEntitySimulation.cpp @@ -0,0 +1,213 @@ +// +// SimpleEntitySimulation.cpp +// libraries/entities/src +// +// Created by Andrew Meadows on 2014.11.24 +// 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 "EntityItem.h" +#include "MovingEntitiesOperator.h" +#include "SimpleEntitySimulation.h" + +void SimpleEntitySimulation::update(QSet& entitiesToDelete) { + quint64 now = usecTimestampNow(); + updateChangedEntities(now, entitiesToDelete); + updateMovingEntities(now, entitiesToDelete); + updateMortalEntities(now, entitiesToDelete); +} + +void SimpleEntitySimulation::addEntity(EntityItem* entity) { + assert(entity && entity->getSimulationState() == EntityItem::Static); + EntityItem::SimulationState state = entity->computeSimulationState(); + switch(state) { + case EntityItem::Moving: + _movingEntities.push_back(entity); + entity->setSimulationState(state); + break; + case EntityItem::Mortal: + _mortalEntities.push_back(entity); + entity->setSimulationState(state); + break; + case EntityItem::Static: + default: + break; + } +} + +void SimpleEntitySimulation::removeEntity(EntityItem* entity) { + assert(entity); + // make sure to remove it from any of our simulation lists + EntityItem::SimulationState state = entity->getSimulationState(); + switch (state) { + case EntityItem::Moving: + _movingEntities.removeAll(entity); + break; + case EntityItem::Mortal: + _mortalEntities.removeAll(entity); + break; + + default: + break; + } + _changedEntities.remove(entity); +} + +void SimpleEntitySimulation::updateEntity(EntityItem* entity) { + assert(entity); + // we'll deal with thsi change later + _changedEntities.insert(entity); +} + +void SimpleEntitySimulation::updateChangedEntities(quint64 now, QSet& entitiesToDelete) { + foreach (EntityItem* entity, _changedEntities) { + // check to see if the lifetime has expired, for immortal entities this is always false + if (entity->lifetimeHasExpired()) { + qDebug() << "Lifetime has expired for entity:" << entity->getEntityItemID(); + entitiesToDelete << entity->getEntityItemID(); + clearEntityState(entity); + } else { + updateEntityState(entity); + } + entity->clearUpdateFlags(); + } + _changedEntities.clear(); +} + +void SimpleEntitySimulation::updateMovingEntities(quint64 now, QSet& entitiesToDelete) { + if (_movingEntities.size() > 0) { + PerformanceTimer perfTimer("_movingEntities"); + MovingEntitiesOperator moveOperator(_myTree); + QList::iterator item_itr = _movingEntities.begin(); + while (item_itr != _movingEntities.end()) { + EntityItem* thisEntity = *item_itr; + + // always check to see if the lifetime has expired, for immortal entities this is always false + if (thisEntity->lifetimeHasExpired()) { + qDebug() << "Lifetime has expired for entity:" << thisEntity->getEntityItemID(); + entitiesToDelete << thisEntity->getEntityItemID(); + // remove thisEntity from the list + item_itr = _movingEntities.erase(item_itr); + thisEntity->setSimulationState(EntityItem::Static); + } else { + AACube oldCube = thisEntity->getMaximumAACube(); + thisEntity->update(now); + AACube newCube = thisEntity->getMaximumAACube(); + + // check to see if this movement has sent the entity outside of the domain. + AACube domainBounds(glm::vec3(0.0f,0.0f,0.0f), 1.0f); + if (!domainBounds.touches(newCube)) { + qDebug() << "Entity " << thisEntity->getEntityItemID() << " moved out of domain bounds."; + entitiesToDelete << thisEntity->getEntityItemID(); + // remove thisEntity from the list + item_itr = _movingEntities.erase(item_itr); + thisEntity->setSimulationState(EntityItem::Static); + } else { + moveOperator.addEntityToMoveList(thisEntity, oldCube, newCube); + EntityItem::SimulationState newState = thisEntity->computeSimulationState(); + if (newState != EntityItem::Moving) { + if (newState == EntityItem::Mortal) { + _mortalEntities.push_back(thisEntity); + } + // remove thisEntity from the list + item_itr = _movingEntities.erase(item_itr); + thisEntity->setSimulationState(newState); + } else { + ++item_itr; + } + } + } + } + if (moveOperator.hasMovingEntities()) { + PerformanceTimer perfTimer("recurseTreeWithOperator"); + _myTree->recurseTreeWithOperator(&moveOperator); + } + } +} + +void SimpleEntitySimulation::updateMortalEntities(quint64 now, QSet& entitiesToDelete) { + QList::iterator item_itr = _mortalEntities.begin(); + while (item_itr != _mortalEntities.end()) { + EntityItem* thisEntity = *item_itr; + thisEntity->update(now); + // always check to see if the lifetime has expired, for immortal entities this is always false + if (thisEntity->lifetimeHasExpired()) { + qDebug() << "Lifetime has expired for entity:" << thisEntity->getEntityItemID(); + entitiesToDelete << thisEntity->getEntityItemID(); + // remove thisEntity from the list + item_itr = _mortalEntities.erase(item_itr); + thisEntity->setSimulationState(EntityItem::Static); + } else { + // check to see if this entity is no longer moving + EntityItem::SimulationState newState = thisEntity->computeSimulationState(); + if (newState != EntityItem::Mortal) { + if (newState == EntityItem::Moving) { + _movingEntities.push_back(thisEntity); + } + // remove thisEntity from the list + item_itr = _mortalEntities.erase(item_itr); + thisEntity->setSimulationState(newState); + } else { + ++item_itr; + } + } + } +} + +void SimpleEntitySimulation::updateEntityState(EntityItem* entity) { + EntityItem::SimulationState oldState = entity->getSimulationState(); + EntityItem::SimulationState newState = entity->computeSimulationState(); + if (newState != oldState) { + switch (oldState) { + case EntityItem::Moving: + _movingEntities.removeAll(entity); + break; + + case EntityItem::Mortal: + _mortalEntities.removeAll(entity); + break; + + default: + break; + } + + switch (newState) { + case EntityItem::Moving: + _movingEntities.push_back(entity); + break; + + case EntityItem::Mortal: + _mortalEntities.push_back(entity); + break; + + default: + break; + } + entity->setSimulationState(newState); + } +} + +void SimpleEntitySimulation::clearEntityState(EntityItem* entity) { + EntityItem::SimulationState oldState = entity->getSimulationState(); + switch (oldState) { + case EntityItem::Moving: + _movingEntities.removeAll(entity); + break; + + case EntityItem::Mortal: + _mortalEntities.removeAll(entity); + break; + + default: + break; + } + entity->setSimulationState(EntityItem::Static); +} + + diff --git a/libraries/entities/src/SimpleEntitySimulation.h b/libraries/entities/src/SimpleEntitySimulation.h new file mode 100644 index 0000000000..bc79bf9958 --- /dev/null +++ b/libraries/entities/src/SimpleEntitySimulation.h @@ -0,0 +1,46 @@ +// +// SimpleEntitySimulation.h +// libraries/entities/src +// +// Created by Andrew Meadows on 2014.11.24 +// 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_SimpleEntitySimulation_h +#define hifi_SimpleEntitySimulation_h + +#include "EntitySimulation.h" + +/// provides simple velocity + gravity extrapolation of EntityItem's + +class SimpleEntitySimulation : public EntitySimulation { +public: + SimpleEntitySimulation(EntityTree* tree) : EntitySimulation(tree) { } + virtual ~SimpleEntitySimulation() { } + + virtual void update(QSet& entitiesToDelete); + + virtual void addEntity(EntityItem* entity); + virtual void removeEntity(EntityItem* entity); + virtual void updateEntity(EntityItem* entity); + +private: + void updateEntityState(EntityItem* entity); + void clearEntityState(EntityItem* entity); + + QList& getMovingEntities() { return _movingEntities; } + + void updateChangedEntities(quint64 now, QSet& entitiesToDelete); + void updateMovingEntities(quint64 now, QSet& entitiesToDelete); + void updateMortalEntities(quint64 now, QSet& entitiesToDelete); + +private: + QList _movingEntities; // entities that need to be updated + QList _mortalEntities; // non-moving entities that need to be checked for expiry + QSet _changedEntities; // entities that have changed in the last frame +}; + +#endif // hifi_SimpleEntitySimulation_h From 0b46e35f31df467faf1c698adc429a3156025b89 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 24 Nov 2014 23:19:13 -0800 Subject: [PATCH 065/502] Add support for separate list of 3d overlays to be drawn in front --- interface/src/ui/overlays/Base3DOverlay.cpp | 7 +- interface/src/ui/overlays/Overlays.cpp | 99 ++++++++++++++++----- interface/src/ui/overlays/Overlays.h | 12 +++ 3 files changed, 92 insertions(+), 26 deletions(-) diff --git a/interface/src/ui/overlays/Base3DOverlay.cpp b/interface/src/ui/overlays/Base3DOverlay.cpp index 5c6af97bf1..b3dc377282 100644 --- a/interface/src/ui/overlays/Base3DOverlay.cpp +++ b/interface/src/ui/overlays/Base3DOverlay.cpp @@ -47,8 +47,10 @@ Base3DOverlay::~Base3DOverlay() { } void Base3DOverlay::setDrawInFront(bool value) { - _drawInFront = value; - emit drawInFrontUpdated(value); + if (value != _drawInFront) { + _drawInFront = value; + emit drawInFrontUpdated(value); + } } void Base3DOverlay::setProperties(const QScriptValue& properties) { @@ -59,7 +61,6 @@ void Base3DOverlay::setProperties(const QScriptValue& properties) { if (drawInFront.isValid()) { bool value = drawInFront.toVariant().toBool(); setDrawInFront(value); - _drawInFront = value; } QScriptValue position = properties.property("position"); diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index d6dbb0861e..5de410c1d9 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -29,7 +29,8 @@ #include "TextOverlay.h" #include "Text3DOverlay.h" -Overlays::Overlays() : _nextOverlayID(1) { +Overlays::Overlays() : _nextOverlayID(1), _overlaySignalMapper() { + connect(&_overlaySignalMapper, SIGNAL(mapped(int)), this, SLOT(handleOverlayDrawInFrontUpdated(unsigned int))); } Overlays::~Overlays() { @@ -70,6 +71,9 @@ void Overlays::update(float deltatime) { foreach(Overlay* thisOverlay, _overlays3D) { thisOverlay->update(deltatime); } + foreach(Overlay* thisOverlay, _overlays3DFront) { + thisOverlay->update(deltatime); + } } if (!_overlaysToDelete.isEmpty()) { @@ -94,8 +98,16 @@ void Overlays::render2D() { } void Overlays::render3D(RenderArgs::RenderMode renderMode, RenderArgs::RenderSide renderSide) { + render3DOverlays(_overlays3D, renderMode, renderSide); +} + +void Overlays::render3DFront(RenderArgs::RenderMode renderMode, RenderArgs::RenderSide renderSide) { + render3DOverlays(_overlays3DFront, renderMode, renderSide); +} + +void Overlays::render3DOverlays(QMap& overlays, RenderArgs::RenderMode renderMode, RenderArgs::RenderSide renderSide) { QReadLocker lock(&_lock); - if (_overlays3D.size() == 0) { + if (overlays.size() == 0) { return; } bool myAvatarComputed = false; @@ -111,7 +123,7 @@ void Overlays::render3D(RenderArgs::RenderMode renderMode, RenderArgs::RenderSid renderMode, renderSide, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - foreach(Overlay* thisOverlay, _overlays3D) { + foreach(Overlay* thisOverlay, overlays) { glPushMatrix(); switch (thisOverlay->getAnchor()) { case Overlay::MY_AVATAR: @@ -188,7 +200,15 @@ unsigned int Overlays::addOverlay(Overlay* overlay) { unsigned int thisID = _nextOverlayID; _nextOverlayID++; if (overlay->is3D()) { - _overlays3D[thisID] = overlay; + Base3DOverlay* overlay3D = static_cast(overlay); + if (overlay3D->getDrawInFront()) { + _overlays3DFront[thisID] = overlay; + } else { + _overlays3D[thisID] = overlay; + } + + _overlaySignalMapper.setMapping(overlay3D, thisID); + connect(overlay3D, SIGNAL(drawInFrontUpdated(bool)), &_overlaySignalMapper, SLOT(map())); } else { _overlays2D[thisID] = overlay; } @@ -213,6 +233,8 @@ bool Overlays::editOverlay(unsigned int id, const QScriptValue& properties) { thisOverlay = _overlays2D[id]; } else if (_overlays3D.contains(id)) { thisOverlay = _overlays3D[id]; + } else if (_overlays3DFront.contains(id)) { + thisOverlay = _overlays3DFront[id]; } if (thisOverlay) { thisOverlay->setProperties(properties); @@ -230,6 +252,8 @@ void Overlays::deleteOverlay(unsigned int id) { overlayToDelete = _overlays2D.take(id); } else if (_overlays3D.contains(id)) { overlayToDelete = _overlays3D.take(id); + } else if (_overlays3DFront.contains(id)) { + overlayToDelete = _overlays3DFront.take(id); } else { return; } @@ -239,6 +263,22 @@ void Overlays::deleteOverlay(unsigned int id) { _overlaysToDelete.push_back(overlayToDelete); } +void Overlays::handleOverlayDrawInFrontUpdated(int overlayID) { + if (_overlays3D.contains(overlayID)) { + Base3DOverlay* overlay = static_cast(_overlays3D[overlayID]); + if (overlay->getDrawInFront()) { + _overlays3D.remove(overlayID); + _overlays3DFront[overlayID] = overlay; + } + } else if (_overlays3DFront.contains(overlayID)) { + Base3DOverlay* overlay = static_cast(_overlays3DFront[overlayID]); + if (!overlay->getDrawInFront()) { + _overlays3DFront.remove(overlayID); + _overlays3D[overlayID] = overlay; + } + } +} + unsigned int Overlays::getOverlayAtPoint(const glm::vec2& point) { QReadLocker lock(&_lock); QMapIterator i(_overlays2D); @@ -262,6 +302,8 @@ OverlayPropertyResult Overlays::getProperty(unsigned int id, const QString& prop thisOverlay = _overlays2D[id]; } else if (_overlays3D.contains(id)) { thisOverlay = _overlays3D[id]; + } else if (_overlays3DFront.contains(id)) { + thisOverlay = _overlays3DFront[id]; } if (thisOverlay) { result.value = thisOverlay->getProperty(property); @@ -300,30 +342,39 @@ void OverlayPropertyResultFromScriptValue(const QScriptValue& value, OverlayProp } RayToOverlayIntersectionResult Overlays::findRayIntersection(const PickRay& ray) { + QMap overlayMaps[] = { _overlays3DFront, _overlays3D }; + float bestDistance = std::numeric_limits::max(); RayToOverlayIntersectionResult result; - QMapIterator i(_overlays3D); - i.toBack(); - while (i.hasPrevious()) { - i.previous(); - unsigned int thisID = i.key(); - Base3DOverlay* thisOverlay = static_cast(i.value()); - if (thisOverlay->getVisible() && !thisOverlay->getIgnoreRayIntersection() && thisOverlay->isLoaded()) { - float thisDistance; - BoxFace thisFace; - QString thisExtraInfo; - if (thisOverlay->findRayIntersectionExtraInfo(ray.origin, ray.direction, thisDistance, thisFace, thisExtraInfo)) { - if (thisDistance < bestDistance) { - bestDistance = thisDistance; - result.intersects = true; - result.distance = thisDistance; - result.face = thisFace; - result.overlayID = thisID; - result.intersection = ray.origin + (ray.direction * thisDistance); - result.extraInfo = thisExtraInfo; + for (int idx = 0; idx < 2; idx++) { + QMapIterator i(overlayMaps[idx]); + i.toBack(); + while (i.hasPrevious()) { + i.previous(); + unsigned int thisID = i.key(); + Base3DOverlay* thisOverlay = static_cast(i.value()); + if (thisOverlay->getVisible() && !thisOverlay->getIgnoreRayIntersection() && thisOverlay->isLoaded()) { + float thisDistance; + BoxFace thisFace; + QString thisExtraInfo; + if (thisOverlay->findRayIntersectionExtraInfo(ray.origin, ray.direction, thisDistance, thisFace, thisExtraInfo)) { + if (thisDistance < bestDistance) { + bestDistance = thisDistance; + result.intersects = true; + result.distance = thisDistance; + result.face = thisFace; + result.overlayID = thisID; + result.intersection = ray.origin + (ray.direction * thisDistance); + result.extraInfo = thisExtraInfo; + } } } } + if (result.intersects) { + // We first check the front overlays - if one has been intersected, prefer + // it over any other overlays and return it immediately. + break; + } } return result; } @@ -412,6 +463,8 @@ bool Overlays::isLoaded(unsigned int id) { thisOverlay = _overlays2D[id]; } else if (_overlays3D.contains(id)) { thisOverlay = _overlays3D[id]; + } else if (_overlays3DFront.contains(id)) { + thisOverlay = _overlays3DFront[id]; } else { return false; // not found } diff --git a/interface/src/ui/overlays/Overlays.h b/interface/src/ui/overlays/Overlays.h index 2cd80041cd..c46d9474da 100644 --- a/interface/src/ui/overlays/Overlays.h +++ b/interface/src/ui/overlays/Overlays.h @@ -13,6 +13,7 @@ #include #include +#include #include "Overlay.h" @@ -53,6 +54,8 @@ public: void update(float deltatime); void render3D(RenderArgs::RenderMode renderMode = RenderArgs::DEFAULT_RENDER_MODE, RenderArgs::RenderSide renderSide = RenderArgs::MONO); + void render3DFront(RenderArgs::RenderMode renderMode = RenderArgs::DEFAULT_RENDER_MODE, + RenderArgs::RenderSide renderSide = RenderArgs::MONO); void render2D(); public slots: @@ -88,10 +91,19 @@ public slots: /// overlay; in meters if it is a 3D text overlay float textWidth(unsigned int id, const QString& text) const; +protected: + void render3DOverlays(QMap& overlays, RenderArgs::RenderMode renderMode, RenderArgs::RenderSide renderSide); + +private slots: + /// QSignalMapper unfortunately does not work with unsigned integers. + void handleOverlayDrawInFrontUpdated(int overlayID); + private: QMap _overlays2D; QMap _overlays3D; + QMap _overlays3DFront; QList _overlaysToDelete; + QSignalMapper _overlaySignalMapper; unsigned int _nextOverlayID; QGLWidget* _parent; QReadWriteLock _lock; From 8b982872c2d59370e7de9cd22abbea7d53da8467 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 24 Nov 2014 23:19:53 -0800 Subject: [PATCH 066/502] Add calls to Overlays::render3DFront() --- interface/src/Application.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 4e8b95862a..8d1e77ed25 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2839,6 +2839,11 @@ void Application::updateShadowMap() { _overlays.render3D(RenderArgs::SHADOW_RENDER_MODE); } + { + PerformanceTimer perfTimer("3dOverlaysFront"); + _overlays.render3DFront(RenderArgs::SHADOW_RENDER_MODE); + } + glDisable(GL_POLYGON_OFFSET_FILL); glPopMatrix(); @@ -3135,6 +3140,13 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly, RenderAr if (Menu::getInstance()->isOptionChecked(MenuOption::Wireframe)) { glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); } + + // Render 3D overlays that should be drawn in front + { + PerformanceTimer perfTimer("3dOverlaysFront"); + glClear(GL_DEPTH_BUFFER_BIT); + _overlays.render3DFront(); + } } void Application::updateUntranslatedViewMatrix(const glm::vec3& viewMatrixTranslation) { From 925c2a8f6c10bcd568e4131b3b76f5d67716874e Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 25 Nov 2014 08:34:44 -0800 Subject: [PATCH 067/502] Update array to use pointers --- interface/src/ui/overlays/Overlays.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 5de410c1d9..2d4edca781 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -342,12 +342,12 @@ void OverlayPropertyResultFromScriptValue(const QScriptValue& value, OverlayProp } RayToOverlayIntersectionResult Overlays::findRayIntersection(const PickRay& ray) { - QMap overlayMaps[] = { _overlays3DFront, _overlays3D }; + QMap* overlayMaps[] = { &_overlays3DFront, &_overlays3D }; float bestDistance = std::numeric_limits::max(); RayToOverlayIntersectionResult result; for (int idx = 0; idx < 2; idx++) { - QMapIterator i(overlayMaps[idx]); + QMapIterator i(*overlayMaps[idx]); i.toBack(); while (i.hasPrevious()) { i.previous(); From 4febc45b6a04d2e9cd2fe3fc7091802de8f30666 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 25 Nov 2014 08:44:38 -0800 Subject: [PATCH 068/502] Add drawInFront to Base3DOverlay::getProperty --- interface/src/ui/overlays/Base3DOverlay.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/interface/src/ui/overlays/Base3DOverlay.cpp b/interface/src/ui/overlays/Base3DOverlay.cpp index b3dc377282..1c80b62782 100644 --- a/interface/src/ui/overlays/Base3DOverlay.cpp +++ b/interface/src/ui/overlays/Base3DOverlay.cpp @@ -166,6 +166,9 @@ QScriptValue Base3DOverlay::getProperty(const QString& property) { if (property == "ignoreRayIntersection") { return _ignoreRayIntersection; } + if (property == "drawInFront") { + return _drawInFront; + } return Overlay::getProperty(property); } From a28d74570d5d066d3bd454484617daf76a3637e1 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 25 Nov 2014 09:25:22 -0800 Subject: [PATCH 069/502] bug fixes in setFullscreen() and setEnableVRMode() --- interface/src/Application.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 58b28fcef9..cd7dc813a6 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1568,6 +1568,10 @@ void Application::checkBandwidthMeterClick() { } void Application::setFullscreen(bool fullscreen) { + if (Menu::getInstance()->isOptionChecked(MenuOption::Fullscreen) != fullscreen) { + Menu::getInstance()->getActionForOption(MenuOption::Fullscreen)->setChecked(fullscreen); + } + if (Menu::getInstance()->isOptionChecked(MenuOption::EnableVRMode)) { if (fullscreen) { // Menu show() after hide() doesn't work with Rift VR display so set height instead. @@ -1578,6 +1582,7 @@ void Application::setFullscreen(bool fullscreen) { } _window->setWindowState(fullscreen ? (_window->windowState() | Qt::WindowFullScreen) : (_window->windowState() & ~Qt::WindowFullScreen)); + _window->show(); } void Application::setEnable3DTVMode(bool enable3DTVMode) { @@ -1585,6 +1590,10 @@ void Application::setEnable3DTVMode(bool enable3DTVMode) { } void Application::setEnableVRMode(bool enableVRMode) { + if (Menu::getInstance()->isOptionChecked(MenuOption::EnableVRMode) != enableVRMode) { + Menu::getInstance()->getActionForOption(MenuOption::EnableVRMode)->setChecked(enableVRMode); + } + if (enableVRMode) { if (!OculusManager::isConnected()) { // attempt to reconnect the Oculus manager - it's possible this was a workaround From e9812d060890d5a130a510378c66a812b91bb46d Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 25 Nov 2014 09:25:49 -0800 Subject: [PATCH 070/502] added similarStrings() helper --- libraries/shared/src/SharedUtil.cpp | 21 +++++++++++++++++++++ libraries/shared/src/SharedUtil.h | 2 +- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/libraries/shared/src/SharedUtil.cpp b/libraries/shared/src/SharedUtil.cpp index c376836d24..7b5a0bb15d 100644 --- a/libraries/shared/src/SharedUtil.cpp +++ b/libraries/shared/src/SharedUtil.cpp @@ -655,3 +655,24 @@ QString formatSecondsElapsed(float seconds) { } return result; } + +bool similarStrings(const QString& stringA, const QString& stringB) { + QStringList aWords = stringA.split(" "); + QStringList bWords = stringB.split(" "); + float aWordsInB = 0.0f; + foreach(QString aWord, aWords) { + if (bWords.contains(aWord)) { + aWordsInB += 1.0f; + } + } + float bWordsInA = 0.0f; + foreach(QString bWord, bWords) { + if (aWords.contains(bWord)) { + bWordsInA += 1.0f; + } + } + float similarity = 0.5f * (aWordsInB / (float)bWords.size()) + 0.5f * (bWordsInA / (float)aWords.size()); + const float SIMILAR_ENOUGH = 0.5f; // half the words the same is similar enough for us + return similarity >= SIMILAR_ENOUGH; +} + diff --git a/libraries/shared/src/SharedUtil.h b/libraries/shared/src/SharedUtil.h index 01edcc01b9..61b7365877 100644 --- a/libraries/shared/src/SharedUtil.h +++ b/libraries/shared/src/SharedUtil.h @@ -131,6 +131,6 @@ bool isNaN(float value); QString formatUsecTime(float usecs, int prec = 3); QString formatSecondsElapsed(float seconds); - +bool similarStrings(const QString& stringA, const QString& stringB); #endif // hifi_SharedUtil_h From e35242345c2643b8f6c6c399abda7a0315e73994 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 25 Nov 2014 09:26:24 -0800 Subject: [PATCH 071/502] first cut at HMD Tools dialog --- interface/src/Application.h | 2 + interface/src/Menu.cpp | 18 ++++ interface/src/Menu.h | 6 ++ interface/src/devices/OculusManager.cpp | 64 +++++++++++- interface/src/devices/OculusManager.h | 4 + interface/src/ui/HMDToolsDialog.cpp | 131 ++++++++++++++++++++++++ interface/src/ui/HMDToolsDialog.h | 43 ++++++++ 7 files changed, 266 insertions(+), 2 deletions(-) create mode 100644 interface/src/ui/HMDToolsDialog.cpp create mode 100644 interface/src/ui/HMDToolsDialog.h diff --git a/interface/src/Application.h b/interface/src/Application.h index c75202d96f..9f2cdbd520 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -71,6 +71,7 @@ #include "scripting/ControllerScriptingInterface.h" #include "ui/BandwidthDialog.h" #include "ui/BandwidthMeter.h" +#include "ui/HMDToolsDialog.h" #include "ui/ModelsBrowser.h" #include "ui/NodeBounds.h" #include "ui/OctreeStatsDialog.h" @@ -395,6 +396,7 @@ private slots: void connectedToDomain(const QString& hostname); + friend class HMDToolsDialog; void setFullscreen(bool fullscreen); void setEnable3DTVMode(bool enable3DTVMode); void setEnableVRMode(bool enableVRMode); diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index db5cd5170d..151e9682ed 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -97,6 +97,7 @@ Menu::Menu() : _jsConsole(NULL), _octreeStatsDialog(NULL), _lodToolsDialog(NULL), + _hmdToolsDialog(NULL), _newLocationDialog(NULL), _userLocationsDialog(NULL), #if defined(Q_OS_MAC) || defined(Q_OS_WIN) @@ -334,6 +335,7 @@ Menu::Menu() : appInstance, SLOT(cameraMenuChanged())); addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::UserInterface, Qt::Key_Slash, true); + addActionToQMenuAndActionHash(viewMenu, MenuOption::HMDTools, 0, this, SLOT(hmdTools())); addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::EnableVRMode, 0, false, appInstance, @@ -1646,6 +1648,22 @@ void Menu::lodToolsClosed() { } } +void Menu::hmdTools() { + if (!_hmdToolsDialog) { + _hmdToolsDialog = new HMDToolsDialog(Application::getInstance()->getGLWidget()); + connect(_hmdToolsDialog, SIGNAL(closed()), SLOT(hmdToolsClosed())); + _hmdToolsDialog->show(); + } + _hmdToolsDialog->raise(); +} + +void Menu::hmdToolsClosed() { + if (_hmdToolsDialog) { + delete _hmdToolsDialog; + _hmdToolsDialog = NULL; + } +} + void Menu::cycleFrustumRenderMode() { _frustumDrawMode = (FrustumDrawMode)((_frustumDrawMode + 1) % FRUSTUM_DRAW_MODE_COUNT); updateFrustumRenderModeAction(); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 7e153eba5e..e41e2f35ea 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -76,6 +76,7 @@ class QSettings; class AnimationsDialog; class AttachmentsDialog; class BandwidthDialog; +class HMDToolsDialog; class LodToolsDialog; class MetavoxelEditor; class MetavoxelNetworkSimulator; @@ -120,6 +121,7 @@ public: ViewFrustumOffset getViewFrustumOffset() const { return _viewFrustumOffset; } OctreeStatsDialog* getOctreeStatsDialog() const { return _octreeStatsDialog; } LodToolsDialog* getLodToolsDialog() const { return _lodToolsDialog; } + HMDToolsDialog* getHMDToolsDialog() const { return _hmdToolsDialog; } int getMaxVoxels() const { return _maxVoxels; } QAction* getUseVoxelShader() const { return _useVoxelShader; } @@ -183,6 +185,7 @@ public slots: void bandwidthDetails(); void octreeStatsDetails(); void lodTools(); + void hmdTools(); void loadSettings(QSettings* settings = NULL); void saveSettings(QSettings* settings = NULL); void importSettings(); @@ -217,6 +220,7 @@ private slots: void bandwidthDetailsClosed(); void octreeStatsDetailsClosed(); void lodToolsClosed(); + void hmdToolsClosed(); void cycleFrustumRenderMode(); void runTests(); void showMetavoxelEditor(); @@ -284,6 +288,7 @@ private: QDialog* _jsConsole; OctreeStatsDialog* _octreeStatsDialog; LodToolsDialog* _lodToolsDialog; + HMDToolsDialog* _hmdToolsDialog; QPointer _newLocationDialog; QPointer _userLocationsDialog; #if defined(Q_OS_MAC) || defined(Q_OS_WIN) @@ -412,6 +417,7 @@ namespace MenuOption { const QString NamesAboveHeads = "Names Above Heads"; const QString GoToUser = "Go To User"; const QString HeadMouse = "Head Mouse"; + const QString HMDTools = "HMD Tools"; const QString IncreaseAvatarSize = "Increase Avatar Size"; const QString IncreaseVoxelSize = "Increase Voxel Size"; const QString KeyboardMotorControl = "Enable Keyboard Motor Control"; diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index e68a08a8f4..dfec98c358 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -14,9 +14,14 @@ #include "OculusManager.h" +#include +#include #include +#include #include + +#include #include #include "Application.h" @@ -75,9 +80,7 @@ glm::vec3 OculusManager::_rightEyePosition = glm::vec3(); void OculusManager::connect() { #ifdef HAVE_LIBOVR _calibrationState = UNCALIBRATED; - qDebug() << "Oculus SDK" << OVR_VERSION_STRING; - ovr_Initialize(); _ovrHmd = ovrHmd_Create(0); @@ -86,6 +89,7 @@ void OculusManager::connect() { UserActivityLogger::getInstance().connectedDevice("hmd", "oculus"); } _isConnected = true; + #if defined(__APPLE__) || defined(_WIN32) _eyeFov[0] = _ovrHmd->DefaultEyeFov[0]; _eyeFov[1] = _ovrHmd->DefaultEyeFov[1]; @@ -715,3 +719,59 @@ void OculusManager::overrideOffAxisFrustum(float& left, float& right, float& bot } #endif } + +int OculusManager::getHMDScreen() { + int hmdScreenIndex = -1; // unknown +#ifdef HAVE_LIBOVR + // TODO: it might be smarter to handle multiple HMDs connected in this case. but for now, + // we will simply assume the initialization code that set up _ovrHmd picked the best hmd + + if (_ovrHmd) { + QString productNameFromOVR = _ovrHmd->ProductName; + + int hmdWidth = _ovrHmd->Resolution.w; + int hmdHeight = _ovrHmd->Resolution.h; + int hmdAtX = _ovrHmd->WindowsPos.x; + int hmdAtY = _ovrHmd->WindowsPos.y; + + // we will score the likelihood that each screen is a match based on the following + // rubrik of potential matching features + const int EXACT_NAME_MATCH = 100; + const int SIMILAR_NAMES = 10; + const int EXACT_LOCATION_MATCH = 50; + const int EXACT_RESOLUTION_MATCH = 25; + + int bestMatchScore = 0; + + // look at the display list and see if we can find the best match + QDesktopWidget* desktop = QApplication::desktop(); + int screenNumber = 0; + foreach (QScreen* screen, QGuiApplication::screens()) { + QString screenName = screen->name(); + QRect screenRect = desktop->screenGeometry(screenNumber); + + int screenScore = 0; + if (screenName == productNameFromOVR) { + screenScore += EXACT_NAME_MATCH; + } + if (similarStrings(screenName, productNameFromOVR)) { + screenScore += SIMILAR_NAMES; + } + if (hmdWidth == screenRect.width() && hmdHeight == screenRect.height()) { + screenScore += EXACT_RESOLUTION_MATCH; + } + if (hmdAtX == screenRect.x() && hmdAtY == screenRect.y()) { + screenScore += EXACT_LOCATION_MATCH; + } + if (screenScore > bestMatchScore) { + bestMatchScore = screenScore; + hmdScreenIndex = screenNumber; + } + + screenNumber++; + } + } +#endif + return hmdScreenIndex; +} + diff --git a/interface/src/devices/OculusManager.h b/interface/src/devices/OculusManager.h index 20e43d572c..2e0354f61a 100644 --- a/interface/src/devices/OculusManager.h +++ b/interface/src/devices/OculusManager.h @@ -52,11 +52,15 @@ public: static glm::vec3 getLeftEyePosition() { return _leftEyePosition; } static glm::vec3 getRightEyePosition() { return _rightEyePosition; } + static int getHMDScreen(); + private: #ifdef HAVE_LIBOVR static void generateDistortionMesh(); static void renderDistortionMesh(ovrPosef eyeRenderPose[ovrEye_Count]); + static bool similarNames(const QString& nameA,const QString& nameB); + struct DistortionVertex { glm::vec2 pos; glm::vec2 texR; diff --git a/interface/src/ui/HMDToolsDialog.cpp b/interface/src/ui/HMDToolsDialog.cpp new file mode 100644 index 0000000000..11cc652c37 --- /dev/null +++ b/interface/src/ui/HMDToolsDialog.cpp @@ -0,0 +1,131 @@ +// +// HMDToolsDialog.cpp +// interface/src/ui +// +// Created by Brad Hefta-Gaub on 7/19/13. +// Copyright 2013 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 "Menu.h" +#include "devices/OculusManager.h" +#include "ui/HMDToolsDialog.h" + + +HMDToolsDialog::HMDToolsDialog(QWidget* parent) : + QDialog(parent, Qt::Window | Qt::WindowCloseButtonHint | Qt::WindowStaysOnTopHint) +{ + this->setWindowTitle("HMD Tools"); + + // Create layouter + QFormLayout* form = new QFormLayout(); + + // Add a button to enter + QPushButton* enterModeButton = new QPushButton("Enter HMD Mode"); + form->addRow("", enterModeButton); + connect(enterModeButton,SIGNAL(clicked(bool)),this,SLOT(enterModeClicked(bool))); + + // Add a button to leave + QPushButton* leaveModeButton = new QPushButton("Leave HMD Mode"); + form->addRow("", leaveModeButton); + connect(leaveModeButton,SIGNAL(clicked(bool)),this,SLOT(leaveModeClicked(bool))); + + this->QDialog::setLayout(form); + + + _wasMoved = false; + + _previousRect = Application::getInstance()->getWindow()->rect(); + + + // QDesktopWidget::screenCountChanged() SIGNAL +} + +HMDToolsDialog::~HMDToolsDialog() { +} + +void HMDToolsDialog::enterModeClicked(bool checked) { + qDebug() << "enterModeClicked"; + + int hmdScreen = OculusManager::getHMDScreen(); + + // hack to test... + if (hmdScreen == -1) { + hmdScreen = 0; + } + + if (hmdScreen >= 0) { + QWindow* mainWindow = Application::getInstance()->getWindow()->windowHandle(); + QScreen* targetScreen = QGuiApplication::screens()[hmdScreen]; + + _previousRect = Application::getInstance()->getWindow()->rect(); + qDebug() << "_previousRect:" << _previousRect; + _previousRect = QRect(mainWindow->mapToGlobal(_previousRect.topLeft()), + mainWindow->mapToGlobal(_previousRect.bottomRight())); + qDebug() << "after mapping... _previousRect:" << _previousRect; + + _previousScreen = mainWindow->screen(); + qDebug() << "_previousScreen:" << _previousScreen; + + QRect rect = QApplication::desktop()->screenGeometry(hmdScreen); + + qDebug() << "about to move to:" << rect.topLeft(); + + mainWindow->setScreen(targetScreen); + mainWindow->setGeometry(rect); + + _wasMoved = true; + } + Application::getInstance()->setFullscreen(true); + Application::getInstance()->setEnableVRMode(true); +} + +void HMDToolsDialog::moveWindowAfterLeaveMode() { + qDebug() << "moveWindowAfterLeaveMode"; + QWindow* mainWindow = Application::getInstance()->getWindow()->windowHandle(); + mainWindow->setScreen(_previousScreen); + mainWindow->setGeometry(_previousRect); +} + +void HMDToolsDialog::leaveModeClicked(bool checked) { + qDebug() << "leaveModeClicked"; + + Application::getInstance()->setFullscreen(false); + Application::getInstance()->setEnableVRMode(false); + + if (_wasMoved) { + QWindow* mainWindow = Application::getInstance()->getWindow()->windowHandle(); + mainWindow->setScreen(_previousScreen); + mainWindow->setGeometry(_previousRect); + + const int SLIGHT_DELAY = 1500; + QTimer::singleShot(SLIGHT_DELAY, this, SLOT(moveWindowAfterLeaveMode())); + } + _wasMoved = false; +} + +void HMDToolsDialog::reject() { + // Just regularly close upon ESC + this->QDialog::close(); +} + +void HMDToolsDialog::closeEvent(QCloseEvent* event) { + this->QDialog::closeEvent(event); + emit closed(); +} + + diff --git a/interface/src/ui/HMDToolsDialog.h b/interface/src/ui/HMDToolsDialog.h new file mode 100644 index 0000000000..ac6bebc5f4 --- /dev/null +++ b/interface/src/ui/HMDToolsDialog.h @@ -0,0 +1,43 @@ +// +// HMDToolsDialog.h +// interface/src/ui +// +// Created by Brad Hefta-Gaub on 7/19/13. +// Copyright 2013 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_HMDToolsDialog_h +#define hifi_HMDToolsDialog_h + +#include + +class HMDToolsDialog : public QDialog { + Q_OBJECT +public: + // Sets up the UI + HMDToolsDialog(QWidget* parent); + ~HMDToolsDialog(); + +signals: + void closed(); + +public slots: + void reject(); + void enterModeClicked(bool checked); + void leaveModeClicked(bool checked); + void moveWindowAfterLeaveMode(); + +protected: + // Emits a 'closed' signal when this dialog is closed. + void closeEvent(QCloseEvent*); + +private: + bool _wasMoved; + QRect _previousRect; + QScreen* _previousScreen; +}; + +#endif // hifi_HMDToolsDialog_h From 649ae4a4485398843842d35c33ecdb4118a6aebf Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 25 Nov 2014 09:49:10 -0800 Subject: [PATCH 072/502] Update 3D overlays to only use one list --- interface/src/Application.cpp | 8 +- interface/src/ui/overlays/Base3DOverlay.cpp | 7 -- interface/src/ui/overlays/Base3DOverlay.h | 5 +- interface/src/ui/overlays/Overlays.cpp | 108 ++++++-------------- interface/src/ui/overlays/Overlays.h | 13 +-- 5 files changed, 37 insertions(+), 104 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 8d1e77ed25..de889c7f61 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2836,12 +2836,12 @@ void Application::updateShadowMap() { // render JS/scriptable overlays { PerformanceTimer perfTimer("3dOverlays"); - _overlays.render3D(RenderArgs::SHADOW_RENDER_MODE); + _overlays.render3D(false, RenderArgs::SHADOW_RENDER_MODE); } { PerformanceTimer perfTimer("3dOverlaysFront"); - _overlays.render3DFront(RenderArgs::SHADOW_RENDER_MODE); + _overlays.render3D(true, RenderArgs::SHADOW_RENDER_MODE); } glDisable(GL_POLYGON_OFFSET_FILL); @@ -3056,7 +3056,7 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly, RenderAr // render JS/scriptable overlays { PerformanceTimer perfTimer("3dOverlays"); - _overlays.render3D(); + _overlays.render3D(false); } // render the ambient occlusion effect if enabled @@ -3145,7 +3145,7 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly, RenderAr { PerformanceTimer perfTimer("3dOverlaysFront"); glClear(GL_DEPTH_BUFFER_BIT); - _overlays.render3DFront(); + _overlays.render3D(true); } } diff --git a/interface/src/ui/overlays/Base3DOverlay.cpp b/interface/src/ui/overlays/Base3DOverlay.cpp index 1c80b62782..55b4c88812 100644 --- a/interface/src/ui/overlays/Base3DOverlay.cpp +++ b/interface/src/ui/overlays/Base3DOverlay.cpp @@ -46,13 +46,6 @@ Base3DOverlay::Base3DOverlay(const Base3DOverlay* base3DOverlay) : Base3DOverlay::~Base3DOverlay() { } -void Base3DOverlay::setDrawInFront(bool value) { - if (value != _drawInFront) { - _drawInFront = value; - emit drawInFrontUpdated(value); - } -} - void Base3DOverlay::setProperties(const QScriptValue& properties) { Overlay::setProperties(properties); diff --git a/interface/src/ui/overlays/Base3DOverlay.h b/interface/src/ui/overlays/Base3DOverlay.h index 46d99cf3de..d57f9731c4 100644 --- a/interface/src/ui/overlays/Base3DOverlay.h +++ b/interface/src/ui/overlays/Base3DOverlay.h @@ -45,7 +45,7 @@ public: void setIsDashedLine(bool isDashedLine) { _isDashedLine = isDashedLine; } void setRotation(const glm::quat& value) { _rotation = value; } void setIgnoreRayIntersection(bool value) { _ignoreRayIntersection = value; } - void setDrawInFront(bool value); + void setDrawInFront(bool value) { _drawInFront = value; } virtual void setProperties(const QScriptValue& properties); virtual QScriptValue getProperty(const QString& property); @@ -57,9 +57,6 @@ public: return findRayIntersection(origin, direction, distance, face); } -signals: - void drawInFrontUpdated(bool newValue); - protected: void drawDashedLine(const glm::vec3& start, const glm::vec3& end); diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 2d4edca781..151e3c3ba7 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -29,8 +29,7 @@ #include "TextOverlay.h" #include "Text3DOverlay.h" -Overlays::Overlays() : _nextOverlayID(1), _overlaySignalMapper() { - connect(&_overlaySignalMapper, SIGNAL(mapped(int)), this, SLOT(handleOverlayDrawInFrontUpdated(unsigned int))); +Overlays::Overlays() : _nextOverlayID(1) { } Overlays::~Overlays() { @@ -71,9 +70,6 @@ void Overlays::update(float deltatime) { foreach(Overlay* thisOverlay, _overlays3D) { thisOverlay->update(deltatime); } - foreach(Overlay* thisOverlay, _overlays3DFront) { - thisOverlay->update(deltatime); - } } if (!_overlaysToDelete.isEmpty()) { @@ -97,17 +93,9 @@ void Overlays::render2D() { } } -void Overlays::render3D(RenderArgs::RenderMode renderMode, RenderArgs::RenderSide renderSide) { - render3DOverlays(_overlays3D, renderMode, renderSide); -} - -void Overlays::render3DFront(RenderArgs::RenderMode renderMode, RenderArgs::RenderSide renderSide) { - render3DOverlays(_overlays3DFront, renderMode, renderSide); -} - -void Overlays::render3DOverlays(QMap& overlays, RenderArgs::RenderMode renderMode, RenderArgs::RenderSide renderSide) { +void Overlays::render3D(bool drawFront, RenderArgs::RenderMode renderMode, RenderArgs::RenderSide renderSide) { QReadLocker lock(&_lock); - if (overlays.size() == 0) { + if (_overlays3D.size() == 0) { return; } bool myAvatarComputed = false; @@ -123,7 +111,11 @@ void Overlays::render3DOverlays(QMap& overlays, RenderAr renderMode, renderSide, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - foreach(Overlay* thisOverlay, overlays) { + foreach(Overlay* thisOverlay, _overlays3D) { + Base3DOverlay* overlay3D = static_cast(thisOverlay); + if (overlay3D->getDrawInFront() != drawFront) { + continue; + } glPushMatrix(); switch (thisOverlay->getAnchor()) { case Overlay::MY_AVATAR: @@ -200,15 +192,7 @@ unsigned int Overlays::addOverlay(Overlay* overlay) { unsigned int thisID = _nextOverlayID; _nextOverlayID++; if (overlay->is3D()) { - Base3DOverlay* overlay3D = static_cast(overlay); - if (overlay3D->getDrawInFront()) { - _overlays3DFront[thisID] = overlay; - } else { - _overlays3D[thisID] = overlay; - } - - _overlaySignalMapper.setMapping(overlay3D, thisID); - connect(overlay3D, SIGNAL(drawInFrontUpdated(bool)), &_overlaySignalMapper, SLOT(map())); + _overlays3D[thisID] = overlay; } else { _overlays2D[thisID] = overlay; } @@ -233,8 +217,6 @@ bool Overlays::editOverlay(unsigned int id, const QScriptValue& properties) { thisOverlay = _overlays2D[id]; } else if (_overlays3D.contains(id)) { thisOverlay = _overlays3D[id]; - } else if (_overlays3DFront.contains(id)) { - thisOverlay = _overlays3DFront[id]; } if (thisOverlay) { thisOverlay->setProperties(properties); @@ -252,8 +234,6 @@ void Overlays::deleteOverlay(unsigned int id) { overlayToDelete = _overlays2D.take(id); } else if (_overlays3D.contains(id)) { overlayToDelete = _overlays3D.take(id); - } else if (_overlays3DFront.contains(id)) { - overlayToDelete = _overlays3DFront.take(id); } else { return; } @@ -263,22 +243,6 @@ void Overlays::deleteOverlay(unsigned int id) { _overlaysToDelete.push_back(overlayToDelete); } -void Overlays::handleOverlayDrawInFrontUpdated(int overlayID) { - if (_overlays3D.contains(overlayID)) { - Base3DOverlay* overlay = static_cast(_overlays3D[overlayID]); - if (overlay->getDrawInFront()) { - _overlays3D.remove(overlayID); - _overlays3DFront[overlayID] = overlay; - } - } else if (_overlays3DFront.contains(overlayID)) { - Base3DOverlay* overlay = static_cast(_overlays3DFront[overlayID]); - if (!overlay->getDrawInFront()) { - _overlays3DFront.remove(overlayID); - _overlays3D[overlayID] = overlay; - } - } -} - unsigned int Overlays::getOverlayAtPoint(const glm::vec2& point) { QReadLocker lock(&_lock); QMapIterator i(_overlays2D); @@ -302,8 +266,6 @@ OverlayPropertyResult Overlays::getProperty(unsigned int id, const QString& prop thisOverlay = _overlays2D[id]; } else if (_overlays3D.contains(id)) { thisOverlay = _overlays3D[id]; - } else if (_overlays3DFront.contains(id)) { - thisOverlay = _overlays3DFront[id]; } if (thisOverlay) { result.value = thisOverlay->getProperty(property); @@ -342,39 +304,33 @@ void OverlayPropertyResultFromScriptValue(const QScriptValue& value, OverlayProp } RayToOverlayIntersectionResult Overlays::findRayIntersection(const PickRay& ray) { - QMap* overlayMaps[] = { &_overlays3DFront, &_overlays3D }; - float bestDistance = std::numeric_limits::max(); + float bestIsFront = false; RayToOverlayIntersectionResult result; - for (int idx = 0; idx < 2; idx++) { - QMapIterator i(*overlayMaps[idx]); - i.toBack(); - while (i.hasPrevious()) { - i.previous(); - unsigned int thisID = i.key(); - Base3DOverlay* thisOverlay = static_cast(i.value()); - if (thisOverlay->getVisible() && !thisOverlay->getIgnoreRayIntersection() && thisOverlay->isLoaded()) { - float thisDistance; - BoxFace thisFace; - QString thisExtraInfo; - if (thisOverlay->findRayIntersectionExtraInfo(ray.origin, ray.direction, thisDistance, thisFace, thisExtraInfo)) { - if (thisDistance < bestDistance) { - bestDistance = thisDistance; - result.intersects = true; - result.distance = thisDistance; - result.face = thisFace; - result.overlayID = thisID; - result.intersection = ray.origin + (ray.direction * thisDistance); - result.extraInfo = thisExtraInfo; - } + QMapIterator i(_overlays3D); + i.toBack(); + while (i.hasPrevious()) { + i.previous(); + unsigned int thisID = i.key(); + Base3DOverlay* thisOverlay = static_cast(i.value()); + if (thisOverlay->getVisible() && !thisOverlay->getIgnoreRayIntersection() && thisOverlay->isLoaded()) { + float thisDistance; + BoxFace thisFace; + QString thisExtraInfo; + if (thisOverlay->findRayIntersectionExtraInfo(ray.origin, ray.direction, thisDistance, thisFace, thisExtraInfo)) { + bool isDrawInFront = thisOverlay->getDrawInFront(); + if (thisDistance < bestDistance && (!bestIsFront || isDrawInFront)) { + bestIsFront = isDrawInFront; + bestDistance = thisDistance; + result.intersects = true; + result.distance = thisDistance; + result.face = thisFace; + result.overlayID = thisID; + result.intersection = ray.origin + (ray.direction * thisDistance); + result.extraInfo = thisExtraInfo; } } } - if (result.intersects) { - // We first check the front overlays - if one has been intersected, prefer - // it over any other overlays and return it immediately. - break; - } } return result; } @@ -463,8 +419,6 @@ bool Overlays::isLoaded(unsigned int id) { thisOverlay = _overlays2D[id]; } else if (_overlays3D.contains(id)) { thisOverlay = _overlays3D[id]; - } else if (_overlays3DFront.contains(id)) { - thisOverlay = _overlays3DFront[id]; } else { return false; // not found } diff --git a/interface/src/ui/overlays/Overlays.h b/interface/src/ui/overlays/Overlays.h index c46d9474da..7acc2c7878 100644 --- a/interface/src/ui/overlays/Overlays.h +++ b/interface/src/ui/overlays/Overlays.h @@ -52,9 +52,7 @@ public: ~Overlays(); void init(QGLWidget* parent); void update(float deltatime); - void render3D(RenderArgs::RenderMode renderMode = RenderArgs::DEFAULT_RENDER_MODE, - RenderArgs::RenderSide renderSide = RenderArgs::MONO); - void render3DFront(RenderArgs::RenderMode renderMode = RenderArgs::DEFAULT_RENDER_MODE, + void render3D(bool drawFront, RenderArgs::RenderMode renderMode = RenderArgs::DEFAULT_RENDER_MODE, RenderArgs::RenderSide renderSide = RenderArgs::MONO); void render2D(); @@ -91,19 +89,10 @@ public slots: /// overlay; in meters if it is a 3D text overlay float textWidth(unsigned int id, const QString& text) const; -protected: - void render3DOverlays(QMap& overlays, RenderArgs::RenderMode renderMode, RenderArgs::RenderSide renderSide); - -private slots: - /// QSignalMapper unfortunately does not work with unsigned integers. - void handleOverlayDrawInFrontUpdated(int overlayID); - private: QMap _overlays2D; QMap _overlays3D; - QMap _overlays3DFront; QList _overlaysToDelete; - QSignalMapper _overlaySignalMapper; unsigned int _nextOverlayID; QGLWidget* _parent; QReadWriteLock _lock; From b97870f32ed55314188547b8d3d99e2350458f19 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 25 Nov 2014 12:01:29 -0800 Subject: [PATCH 073/502] Update extra entity tool stretch handles to be optionally visible --- examples/libraries/entitySelectionTool.js | 44 ++++++++++++----------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/examples/libraries/entitySelectionTool.js b/examples/libraries/entitySelectionTool.js index 08ac077a34..d820cf733f 100644 --- a/examples/libraries/entitySelectionTool.js +++ b/examples/libraries/entitySelectionTool.js @@ -206,6 +206,8 @@ SelectionDisplay = (function () { var MINIMUM_DIMENSION = 0.001; var GRABBER_DISTANCE_TO_SIZE_RATIO = 0.0075; + + var showExtendedStretchHandles = false; var spaceMode = SPACE_LOCAL; var mode = "UNKNOWN"; @@ -1057,21 +1059,23 @@ SelectionDisplay = (function () { EdgeFL = Vec3.sum(position, EdgeFL); var stretchHandlesVisible = spaceMode == SPACE_LOCAL; + var extendedStretchHandlesVisible = stretchHandlesVisible && showExtendedStretchHandles; Overlays.editOverlay(grabberLBN, { visible: stretchHandlesVisible, rotation: rotation, position: LBN }); Overlays.editOverlay(grabberRBN, { visible: stretchHandlesVisible, rotation: rotation, position: RBN }); Overlays.editOverlay(grabberLBF, { visible: stretchHandlesVisible, rotation: rotation, position: LBF }); Overlays.editOverlay(grabberRBF, { visible: stretchHandlesVisible, rotation: rotation, position: RBF }); - Overlays.editOverlay(grabberLTN, { visible: stretchHandlesVisible, rotation: rotation, position: LTN }); - Overlays.editOverlay(grabberRTN, { visible: stretchHandlesVisible, rotation: rotation, position: RTN }); - Overlays.editOverlay(grabberLTF, { visible: stretchHandlesVisible, rotation: rotation, position: LTF }); - Overlays.editOverlay(grabberRTF, { visible: stretchHandlesVisible, rotation: rotation, position: RTF }); + + Overlays.editOverlay(grabberLTN, { visible: extendedStretchHandlesVisible, rotation: rotation, position: LTN }); + Overlays.editOverlay(grabberRTN, { visible: extendedStretchHandlesVisible, rotation: rotation, position: RTN }); + Overlays.editOverlay(grabberLTF, { visible: extendedStretchHandlesVisible, rotation: rotation, position: LTF }); + Overlays.editOverlay(grabberRTF, { visible: extendedStretchHandlesVisible, rotation: rotation, position: RTF }); Overlays.editOverlay(grabberTOP, { visible: stretchHandlesVisible, rotation: rotation, position: TOP }); Overlays.editOverlay(grabberBOTTOM, { visible: stretchHandlesVisible, rotation: rotation, position: BOTTOM }); - Overlays.editOverlay(grabberLEFT, { visible: stretchHandlesVisible, rotation: rotation, position: LEFT }); - Overlays.editOverlay(grabberRIGHT, { visible: stretchHandlesVisible, rotation: rotation, position: RIGHT }); - Overlays.editOverlay(grabberNEAR, { visible: stretchHandlesVisible, rotation: rotation, position: NEAR }); - Overlays.editOverlay(grabberFAR, { visible: stretchHandlesVisible, rotation: rotation, position: FAR }); + Overlays.editOverlay(grabberLEFT, { visible: extendedStretchHandlesVisible, rotation: rotation, position: LEFT }); + Overlays.editOverlay(grabberRIGHT, { visible: extendedStretchHandlesVisible, rotation: rotation, position: RIGHT }); + Overlays.editOverlay(grabberNEAR, { visible: extendedStretchHandlesVisible, rotation: rotation, position: NEAR }); + Overlays.editOverlay(grabberFAR, { visible: extendedStretchHandlesVisible, rotation: rotation, position: FAR }); Overlays.editOverlay(selectionBox, { position: position, @@ -1080,18 +1084,18 @@ SelectionDisplay = (function () { visible: !(mode == "ROTATE_YAW" || mode == "ROTATE_PITCH" || mode == "ROTATE_ROLL"), }); - Overlays.editOverlay(grabberEdgeTR, { visible: stretchHandlesVisible, rotation: rotation, position: EdgeTR }); - Overlays.editOverlay(grabberEdgeTL, { visible: stretchHandlesVisible, rotation: rotation, position: EdgeTL }); - Overlays.editOverlay(grabberEdgeTF, { visible: stretchHandlesVisible, rotation: rotation, position: EdgeTF }); - Overlays.editOverlay(grabberEdgeTN, { visible: stretchHandlesVisible, rotation: rotation, position: EdgeTN }); + Overlays.editOverlay(grabberEdgeTR, { visible: extendedStretchHandlesVisible, rotation: rotation, position: EdgeTR }); + Overlays.editOverlay(grabberEdgeTL, { visible: extendedStretchHandlesVisible, rotation: rotation, position: EdgeTL }); + Overlays.editOverlay(grabberEdgeTF, { visible: extendedStretchHandlesVisible, rotation: rotation, position: EdgeTF }); + Overlays.editOverlay(grabberEdgeTN, { visible: extendedStretchHandlesVisible, rotation: rotation, position: EdgeTN }); Overlays.editOverlay(grabberEdgeBR, { visible: stretchHandlesVisible, rotation: rotation, position: EdgeBR }); Overlays.editOverlay(grabberEdgeBL, { visible: stretchHandlesVisible, rotation: rotation, position: EdgeBL }); Overlays.editOverlay(grabberEdgeBF, { visible: stretchHandlesVisible, rotation: rotation, position: EdgeBF }); Overlays.editOverlay(grabberEdgeBN, { visible: stretchHandlesVisible, rotation: rotation, position: EdgeBN }); - Overlays.editOverlay(grabberEdgeNR, { visible: stretchHandlesVisible, rotation: rotation, position: EdgeNR }); - Overlays.editOverlay(grabberEdgeNL, { visible: stretchHandlesVisible, rotation: rotation, position: EdgeNL }); - Overlays.editOverlay(grabberEdgeFR, { visible: stretchHandlesVisible, rotation: rotation, position: EdgeFR }); - Overlays.editOverlay(grabberEdgeFL, { visible: stretchHandlesVisible, rotation: rotation, position: EdgeFL }); + Overlays.editOverlay(grabberEdgeNR, { visible: extendedStretchHandlesVisible, rotation: rotation, position: EdgeNR }); + Overlays.editOverlay(grabberEdgeNL, { visible: extendedStretchHandlesVisible, rotation: rotation, position: EdgeNL }); + Overlays.editOverlay(grabberEdgeFR, { visible: extendedStretchHandlesVisible, rotation: rotation, position: EdgeFR }); + Overlays.editOverlay(grabberEdgeFL, { visible: extendedStretchHandlesVisible, rotation: rotation, position: EdgeFL }); var grabberMoveUpOffset = 0.1; grabberMoveUpPosition = { x: position.x, y: position.y + worldTop + grabberMoveUpOffset, z: position.z } @@ -1507,10 +1511,10 @@ SelectionDisplay = (function () { addStretchTool(grabberEdgeTL, "STRETCH_EdgeTL", null, {x: -1, y: 1, z: 0}); addStretchTool(grabberEdgeTF, "STRETCH_EdgeTF", null, {x: 0, y: 1, z: -1}); addStretchTool(grabberEdgeTN, "STRETCH_EdgeTN", null, {x: 0, y: 1, z: 1}); - addStretchTool(grabberEdgeBR, "STRETCH_EdgeBR", null, {x: 1, y: -1, z: 0}); - addStretchTool(grabberEdgeBL, "STRETCH_EdgeBL", null, {x: -1, y: -1, z: 0}); - addStretchTool(grabberEdgeBF, "STRETCH_EdgeBF", null, {x: 0, y: -1, z: 1}); - addStretchTool(grabberEdgeBN, "STRETCH_EdgeBN", null, {x: 0, y: -1, z: -1}); + addStretchTool(grabberEdgeBR, "STRETCH_EdgeBR", null, {x: -1, y: 0, z: 0}); + addStretchTool(grabberEdgeBL, "STRETCH_EdgeBL", null, {x: 1, y: 0, z: 0}); + addStretchTool(grabberEdgeBF, "STRETCH_EdgeBF", null, {x: 0, y: 0, z: -1}); + addStretchTool(grabberEdgeBN, "STRETCH_EdgeBN", null, {x: 0, y: 0, z: 1}); addStretchTool(grabberEdgeNR, "STRETCH_EdgeNR", null, {x: -1, y: 0, z: 1}); addStretchTool(grabberEdgeNL, "STRETCH_EdgeNL", null, {x: 1, y: 0, z: 1}); addStretchTool(grabberEdgeFR, "STRETCH_EdgeFR", null, {x: -1, y: 0, z: -1}); From b3ca6fda72c18a4a37207581942c992eb91ed2a4 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 25 Nov 2014 12:04:11 -0800 Subject: [PATCH 074/502] Update entity tool grabbers look and size --- examples/libraries/entitySelectionTool.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/examples/libraries/entitySelectionTool.js b/examples/libraries/entitySelectionTool.js index d820cf733f..38ec0ba1ea 100644 --- a/examples/libraries/entitySelectionTool.js +++ b/examples/libraries/entitySelectionTool.js @@ -273,6 +273,8 @@ SelectionDisplay = (function () { visible: false, dashed: false, lineWidth: grabberLineWidth, + drawInFront: true, + borderSize: 1.4, }; var grabberPropertiesEdge = { @@ -284,6 +286,8 @@ SelectionDisplay = (function () { visible: false, dashed: false, lineWidth: grabberLineWidth, + drawInFront: true, + borderSize: 1.4, }; var grabberPropertiesFace = { @@ -295,6 +299,8 @@ SelectionDisplay = (function () { visible: false, dashed: false, lineWidth: grabberLineWidth, + drawInFront: true, + borderSize: 1.4, }; var highlightBox = Overlays.addOverlay("cube", { @@ -328,7 +334,8 @@ SelectionDisplay = (function () { visible: false, size: 0.1, scale: 0.1, - isFacingAvatar: true + isFacingAvatar: true, + drawInFront: true, }); // var normalLine = Overlays.addOverlay("line3d", { @@ -2293,7 +2300,7 @@ SelectionDisplay = (function () { size: grabberSize, }); } - var handleSize = Vec3.length(diff) * GRABBER_DISTANCE_TO_SIZE_RATIO * 5; + var handleSize = Vec3.length(diff) * GRABBER_DISTANCE_TO_SIZE_RATIO * 10; Overlays.editOverlay(yawHandle, { scale: handleSize, }); From c5f2b3b5885fd675f0f223c882b555154078aa7a Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 25 Nov 2014 12:05:13 -0800 Subject: [PATCH 075/502] Add borderSize to Cube3DOverlay --- interface/src/ui/overlays/Cube3DOverlay.cpp | 42 +++++++++++++++++++-- interface/src/ui/overlays/Cube3DOverlay.h | 10 +++++ 2 files changed, 49 insertions(+), 3 deletions(-) diff --git a/interface/src/ui/overlays/Cube3DOverlay.cpp b/interface/src/ui/overlays/Cube3DOverlay.cpp index 9c478c4465..223a695328 100644 --- a/interface/src/ui/overlays/Cube3DOverlay.cpp +++ b/interface/src/ui/overlays/Cube3DOverlay.cpp @@ -19,7 +19,7 @@ #include "Cube3DOverlay.h" #include "renderer/GlowEffect.h" -Cube3DOverlay::Cube3DOverlay() { +Cube3DOverlay::Cube3DOverlay() : _borderSize(0) { } Cube3DOverlay::Cube3DOverlay(const Cube3DOverlay* cube3DOverlay) : @@ -63,8 +63,25 @@ void Cube3DOverlay::render(RenderArgs* args) { glm::vec3 positionToCenter = center - position; glTranslatef(positionToCenter.x, positionToCenter.y, positionToCenter.z); if (_isSolid) { - glScalef(dimensions.x, dimensions.y, dimensions.z); - Application::getInstance()->getDeferredLightingEffect()->renderSolidCube(1.0f); + if (_borderSize > 0) { + // Disable writing to the depth mask so that the following draw + // will not be occluded by this one. This means the border + // could be covered by overlays that are further back and drawn + // later, but this is good enough for the use-case. + glDepthMask(GL_FALSE); + glPushMatrix(); + glColor4f(MAX_COLOR, MAX_COLOR, MAX_COLOR, 1.0f); + glScalef(dimensions.x * _borderSize, dimensions.y * _borderSize, dimensions.z * _borderSize); + Application::getInstance()->getDeferredLightingEffect()->renderSolidCube(1.0f); + glPopMatrix(); + glDepthMask(GL_TRUE); + } + + glPushMatrix(); + glColor4f(color.red / MAX_COLOR, color.green / MAX_COLOR, color.blue / MAX_COLOR, alpha); + glScalef(dimensions.x, dimensions.y, dimensions.z); + Application::getInstance()->getDeferredLightingEffect()->renderSolidCube(1.0f); + glPopMatrix(); } else { glLineWidth(_lineWidth); @@ -111,3 +128,22 @@ void Cube3DOverlay::render(RenderArgs* args) { Cube3DOverlay* Cube3DOverlay::createClone() const { return new Cube3DOverlay(this); } + +void Cube3DOverlay::setProperties(const QScriptValue& properties) { + Volume3DOverlay::setProperties(properties); + + QScriptValue borderSize = properties.property("borderSize"); + + if (borderSize.isValid()) { + float value = borderSize.toVariant().toFloat(); + setBorderSize(value); + } +} + +QScriptValue Cube3DOverlay::getProperty(const QString& property) { + if (property == "borderSize") { + return _borderSize; + } + + return Volume3DOverlay::getProperty(property); +} diff --git a/interface/src/ui/overlays/Cube3DOverlay.h b/interface/src/ui/overlays/Cube3DOverlay.h index 9c199f2b7b..16705a9c71 100644 --- a/interface/src/ui/overlays/Cube3DOverlay.h +++ b/interface/src/ui/overlays/Cube3DOverlay.h @@ -23,6 +23,16 @@ public: virtual void render(RenderArgs* args); virtual Cube3DOverlay* createClone() const; + + float getBorderSize() const { return _borderSize; } + + void setBorderSize(float value) { _borderSize = value; } + + virtual void setProperties(const QScriptValue& properties); + virtual QScriptValue getProperty(const QString& property); + +private: + float _borderSize; }; From f8c8ed868e2a652459c6a2646493bc8b842ef25b Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 25 Nov 2014 12:08:48 -0800 Subject: [PATCH 076/502] Update float that should be bool --- interface/src/ui/overlays/Overlays.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 151e3c3ba7..455b73fb80 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -305,7 +305,7 @@ void OverlayPropertyResultFromScriptValue(const QScriptValue& value, OverlayProp RayToOverlayIntersectionResult Overlays::findRayIntersection(const PickRay& ray) { float bestDistance = std::numeric_limits::max(); - float bestIsFront = false; + bool bestIsFront = false; RayToOverlayIntersectionResult result; QMapIterator i(_overlays3D); i.toBack(); From 2cb30c215787447221403f3ecd39bf76bb2bc478 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 25 Nov 2014 12:17:46 -0800 Subject: [PATCH 077/502] Update color used for Cube3DOverlay border --- interface/src/ui/overlays/Cube3DOverlay.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/ui/overlays/Cube3DOverlay.cpp b/interface/src/ui/overlays/Cube3DOverlay.cpp index 223a695328..1f3413908e 100644 --- a/interface/src/ui/overlays/Cube3DOverlay.cpp +++ b/interface/src/ui/overlays/Cube3DOverlay.cpp @@ -70,7 +70,7 @@ void Cube3DOverlay::render(RenderArgs* args) { // later, but this is good enough for the use-case. glDepthMask(GL_FALSE); glPushMatrix(); - glColor4f(MAX_COLOR, MAX_COLOR, MAX_COLOR, 1.0f); + glColor4f(1.0f, 1.0f, 1.0f, alpha); glScalef(dimensions.x * _borderSize, dimensions.y * _borderSize, dimensions.z * _borderSize); Application::getInstance()->getDeferredLightingEffect()->renderSolidCube(1.0f); glPopMatrix(); From 75d560744bac087757ff76c44ae1917fe3e3f8db Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 25 Nov 2014 12:34:03 -0800 Subject: [PATCH 078/502] Update rotation handles to drawInFront = true --- examples/libraries/entitySelectionTool.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/examples/libraries/entitySelectionTool.js b/examples/libraries/entitySelectionTool.js index 38ec0ba1ea..813bf015d1 100644 --- a/examples/libraries/entitySelectionTool.js +++ b/examples/libraries/entitySelectionTool.js @@ -542,7 +542,8 @@ SelectionDisplay = (function () { visible: false, size: 0.1, scale: 0.1, - isFacingAvatar: false + isFacingAvatar: false, + drawInFront: true, }); @@ -554,7 +555,8 @@ SelectionDisplay = (function () { visible: false, size: 0.1, scale: 0.1, - isFacingAvatar: false + isFacingAvatar: false, + drawInFront: true, }); @@ -566,7 +568,8 @@ SelectionDisplay = (function () { visible: false, size: 0.1, scale: 0.1, - isFacingAvatar: false + isFacingAvatar: false, + drawInFront: true, }); var allOverlays = [ From 0b23b57e1e45d02e7f1a1e65c171fc23e221480d Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 25 Nov 2014 12:43:01 -0800 Subject: [PATCH 079/502] Update border comment in Cube3DOverlay --- interface/src/ui/overlays/Cube3DOverlay.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/interface/src/ui/overlays/Cube3DOverlay.cpp b/interface/src/ui/overlays/Cube3DOverlay.cpp index 1f3413908e..8e37dedd77 100644 --- a/interface/src/ui/overlays/Cube3DOverlay.cpp +++ b/interface/src/ui/overlays/Cube3DOverlay.cpp @@ -64,10 +64,12 @@ void Cube3DOverlay::render(RenderArgs* args) { glTranslatef(positionToCenter.x, positionToCenter.y, positionToCenter.z); if (_isSolid) { if (_borderSize > 0) { - // Disable writing to the depth mask so that the following draw - // will not be occluded by this one. This means the border - // could be covered by overlays that are further back and drawn - // later, but this is good enough for the use-case. + // Draw a cube at a larger size behind the main cube, creating + // a border effect. + // Disable writing to the depth mask so that the "border" cube will not + // occlude the main cube. This means the border could be covered by + // overlays that are further back and drawn later, but this is good + // enough for the use-case. glDepthMask(GL_FALSE); glPushMatrix(); glColor4f(1.0f, 1.0f, 1.0f, alpha); From 6108f7d9cd1e60c2bfdc465c09e50b030c8808be Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 25 Nov 2014 12:45:20 -0800 Subject: [PATCH 080/502] fix bug in resetSensors moving cursor to center of window on multiple screen systems --- interface/src/Application.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index cd7dc813a6..90b4501662 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3502,7 +3502,6 @@ void Application::deleteVoxelAt(const VoxelDetail& voxel) { } } - void Application::resetSensors() { _mouseX = _glWidget->width() / 2; _mouseY = _glWidget->height() / 2; @@ -3516,7 +3515,11 @@ void Application::resetSensors() { _prioVR.reset(); //_leapmotion.reset(); - QCursor::setPos(_mouseX, _mouseY); + QScreen* currentScreen = _window->windowHandle()->screen(); + QWindow* mainWindow = _window->windowHandle(); + QPoint windowCenter = mainWindow->geometry().center(); + QCursor::setPos(currentScreen, windowCenter); + _myAvatar->reset(); QMetaObject::invokeMethod(&_audio, "reset", Qt::QueuedConnection); From bc376a0a15cec15a5e935f74a32cd2f794d7b226 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 25 Nov 2014 12:46:00 -0800 Subject: [PATCH 081/502] more improvements to HMD Tools --- interface/src/ui/HMDToolsDialog.cpp | 34 ++++++++++++++++++++++------- interface/src/ui/HMDToolsDialog.h | 2 ++ 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/interface/src/ui/HMDToolsDialog.cpp b/interface/src/ui/HMDToolsDialog.cpp index 11cc652c37..4f4c624065 100644 --- a/interface/src/ui/HMDToolsDialog.cpp +++ b/interface/src/ui/HMDToolsDialog.cpp @@ -51,8 +51,8 @@ HMDToolsDialog::HMDToolsDialog(QWidget* parent) : _previousRect = Application::getInstance()->getWindow()->rect(); - - // QDesktopWidget::screenCountChanged() SIGNAL + + Application::getInstance()->getWindow()->activateWindow(); } HMDToolsDialog::~HMDToolsDialog() { @@ -70,7 +70,7 @@ void HMDToolsDialog::enterModeClicked(bool checked) { if (hmdScreen >= 0) { QWindow* mainWindow = Application::getInstance()->getWindow()->windowHandle(); - QScreen* targetScreen = QGuiApplication::screens()[hmdScreen]; + _hmdScreen = QGuiApplication::screens()[hmdScreen]; _previousRect = Application::getInstance()->getWindow()->rect(); qDebug() << "_previousRect:" << _previousRect; @@ -85,27 +85,36 @@ void HMDToolsDialog::enterModeClicked(bool checked) { qDebug() << "about to move to:" << rect.topLeft(); - mainWindow->setScreen(targetScreen); + mainWindow->setScreen(_hmdScreen); mainWindow->setGeometry(rect); _wasMoved = true; } Application::getInstance()->setFullscreen(true); Application::getInstance()->setEnableVRMode(true); + + const int SLIGHT_DELAY = 500; + QTimer::singleShot(SLIGHT_DELAY, this, SLOT(activateWindowAfterEnterMode())); } -void HMDToolsDialog::moveWindowAfterLeaveMode() { - qDebug() << "moveWindowAfterLeaveMode"; +void HMDToolsDialog::activateWindowAfterEnterMode() { + qDebug() << "activateWindowAfterEnterMode"; + Application::getInstance()->getWindow()->activateWindow(); + QWindow* mainWindow = Application::getInstance()->getWindow()->windowHandle(); - mainWindow->setScreen(_previousScreen); - mainWindow->setGeometry(_previousRect); + QPoint windowCenter = mainWindow->geometry().center(); + //QPoint desktopCenter = mainWindow->mapToGlobal(windowCenter); + qDebug() << "windowCenter:" << windowCenter; + QCursor::setPos(_hmdScreen, windowCenter); } + void HMDToolsDialog::leaveModeClicked(bool checked) { qDebug() << "leaveModeClicked"; Application::getInstance()->setFullscreen(false); Application::getInstance()->setEnableVRMode(false); + Application::getInstance()->getWindow()->activateWindow(); if (_wasMoved) { QWindow* mainWindow = Application::getInstance()->getWindow()->windowHandle(); @@ -118,6 +127,15 @@ void HMDToolsDialog::leaveModeClicked(bool checked) { _wasMoved = false; } +void HMDToolsDialog::moveWindowAfterLeaveMode() { + qDebug() << "moveWindowAfterLeaveMode"; + QWindow* mainWindow = Application::getInstance()->getWindow()->windowHandle(); + mainWindow->setScreen(_previousScreen); + mainWindow->setGeometry(_previousRect); + Application::getInstance()->getWindow()->activateWindow(); +} + + void HMDToolsDialog::reject() { // Just regularly close upon ESC this->QDialog::close(); diff --git a/interface/src/ui/HMDToolsDialog.h b/interface/src/ui/HMDToolsDialog.h index ac6bebc5f4..9620a0529d 100644 --- a/interface/src/ui/HMDToolsDialog.h +++ b/interface/src/ui/HMDToolsDialog.h @@ -28,6 +28,7 @@ public slots: void reject(); void enterModeClicked(bool checked); void leaveModeClicked(bool checked); + void activateWindowAfterEnterMode(); void moveWindowAfterLeaveMode(); protected: @@ -38,6 +39,7 @@ private: bool _wasMoved; QRect _previousRect; QScreen* _previousScreen; + QScreen* _hmdScreen; }; #endif // hifi_HMDToolsDialog_h From aa44906841a7129d8d9cbddc9fa5985f49fd36da Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 25 Nov 2014 13:27:16 -0800 Subject: [PATCH 082/502] make HMD tools a checkable menu --- interface/src/Menu.cpp | 24 +++++++++++++++++------- interface/src/Menu.h | 2 +- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 1c1f9aec23..ac93a71bc0 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -335,7 +335,12 @@ Menu::Menu() : appInstance, SLOT(cameraMenuChanged())); addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::UserInterface, Qt::Key_Slash, true); - addActionToQMenuAndActionHash(viewMenu, MenuOption::HMDTools, 0, this, SLOT(hmdTools())); + addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::HMDTools, Qt::META | Qt::Key_H, + false, + this, + SLOT(hmdTools(bool))); + + addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::EnableVRMode, 0, false, appInstance, @@ -1596,13 +1601,18 @@ void Menu::lodToolsClosed() { } } -void Menu::hmdTools() { - if (!_hmdToolsDialog) { - _hmdToolsDialog = new HMDToolsDialog(Application::getInstance()->getGLWidget()); - connect(_hmdToolsDialog, SIGNAL(closed()), SLOT(hmdToolsClosed())); - _hmdToolsDialog->show(); +void Menu::hmdTools(bool showTools) { + if (showTools) { + if (!_hmdToolsDialog) { + _hmdToolsDialog = new HMDToolsDialog(Application::getInstance()->getGLWidget()); + connect(_hmdToolsDialog, SIGNAL(closed()), SLOT(hmdToolsClosed())); + _hmdToolsDialog->show(); + } + _hmdToolsDialog->raise(); + } else { + hmdToolsClosed(); } - _hmdToolsDialog->raise(); + Application::getInstance()->getWindow()->activateWindow(); } void Menu::hmdToolsClosed() { diff --git a/interface/src/Menu.h b/interface/src/Menu.h index db836dc690..0d46c4020d 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -185,7 +185,7 @@ public slots: void bandwidthDetails(); void octreeStatsDetails(); void lodTools(); - void hmdTools(); + void hmdTools(bool showTools); void loadSettings(QSettings* settings = NULL); void saveSettings(QSettings* settings = NULL); void importSettings(); From 8d3f4a627b0d5ecce94cf67d41205bcc6efe04f5 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 25 Nov 2014 14:10:44 -0800 Subject: [PATCH 083/502] Working on quadtree for heightfields. --- .../src/metavoxels/MetavoxelServer.cpp | 2 +- libraries/metavoxels/src/MetavoxelData.cpp | 28 ++ libraries/metavoxels/src/MetavoxelData.h | 11 + .../metavoxels/src/MetavoxelMessages.cpp | 6 +- libraries/metavoxels/src/Spanner.cpp | 372 +++++++++++++++++- libraries/metavoxels/src/Spanner.h | 82 ++++ libraries/networking/src/PacketHeaders.cpp | 2 +- 7 files changed, 496 insertions(+), 7 deletions(-) diff --git a/assignment-client/src/metavoxels/MetavoxelServer.cpp b/assignment-client/src/metavoxels/MetavoxelServer.cpp index 314ffb28e4..89b3102391 100644 --- a/assignment-client/src/metavoxels/MetavoxelServer.cpp +++ b/assignment-client/src/metavoxels/MetavoxelServer.cpp @@ -311,7 +311,7 @@ MetavoxelPersister::MetavoxelPersister(MetavoxelServer* server) : const char* SAVE_FILE = "/resources/metavoxels.dat"; const int FILE_MAGIC = 0xDADAFACE; -const int FILE_VERSION = 1; +const int FILE_VERSION = 2; void MetavoxelPersister::load() { QString path = QCoreApplication::applicationDirPath() + SAVE_FILE; diff --git a/libraries/metavoxels/src/MetavoxelData.cpp b/libraries/metavoxels/src/MetavoxelData.cpp index 2f20899ffb..860ab3e5e9 100644 --- a/libraries/metavoxels/src/MetavoxelData.cpp +++ b/libraries/metavoxels/src/MetavoxelData.cpp @@ -56,6 +56,34 @@ bool MetavoxelLOD::becameSubdividedOrCollapsed(const glm::vec3& minimum, float s return true; } +bool MetavoxelLOD::shouldSubdivide(const glm::vec2& minimum, float size, float multiplier) const { + return size >= glm::distance(glm::vec2(position), minimum + glm::vec2(size, size) * 0.5f) * threshold * multiplier; +} + +bool MetavoxelLOD::becameSubdivided(const glm::vec2& minimum, float size, + const MetavoxelLOD& reference, float multiplier) const { + if (position == reference.position && threshold >= reference.threshold) { + return false; // first off, nothing becomes subdivided if it doesn't change + } + if (!shouldSubdivide(minimum, size, multiplier)) { + return false; // this one must be subdivided + } + // TODO: find some way of culling subtrees that can't possibly contain subdivided nodes + return true; +} + +bool MetavoxelLOD::becameSubdividedOrCollapsed(const glm::vec2& minimum, float size, + const MetavoxelLOD& reference, float multiplier) const { + if (position == reference.position && threshold == reference.threshold) { + return false; // first off, nothing becomes subdivided or collapsed if it doesn't change + } + if (!(shouldSubdivide(minimum, size, multiplier) || reference.shouldSubdivide(minimum, size, multiplier))) { + return false; // this one or the reference must be subdivided + } + // TODO: find some way of culling subtrees that can't possibly contain subdivided or collapsed nodes + return true; +} + MetavoxelData::MetavoxelData() : _size(1.0f) { } diff --git a/libraries/metavoxels/src/MetavoxelData.h b/libraries/metavoxels/src/MetavoxelData.h index 7bfd2a7522..56d9dd3a8a 100644 --- a/libraries/metavoxels/src/MetavoxelData.h +++ b/libraries/metavoxels/src/MetavoxelData.h @@ -53,6 +53,17 @@ public: /// enabled or disabled as compared to the reference. bool becameSubdividedOrCollapsed(const glm::vec3& minimum, float size, const MetavoxelLOD& reference, float multiplier = 1.0f) const; + + /// Checks whether, according to this LOD, we should subdivide the described region. + bool shouldSubdivide(const glm::vec2& minimum, float size, float multiplier = 1.0f) const; + + /// Checks whether the node or any of the nodes underneath it have had subdivision enabled as compared to the reference. + bool becameSubdivided(const glm::vec2& minimum, float size, const MetavoxelLOD& reference, float multiplier = 1.0f) const; + + /// Checks whether the node or any of the nodes underneath it have had subdivision + /// enabled or disabled as compared to the reference. + bool becameSubdividedOrCollapsed(const glm::vec2& minimum, float size, + const MetavoxelLOD& reference, float multiplier = 1.0f) const; }; DECLARE_STREAMABLE_METATYPE(MetavoxelLOD) diff --git a/libraries/metavoxels/src/MetavoxelMessages.cpp b/libraries/metavoxels/src/MetavoxelMessages.cpp index a4d2569de0..1225752df7 100644 --- a/libraries/metavoxels/src/MetavoxelMessages.cpp +++ b/libraries/metavoxels/src/MetavoxelMessages.cpp @@ -123,11 +123,9 @@ RemoveSpannerEdit::RemoveSpannerEdit(const AttributePointer& attribute, int id) void RemoveSpannerEdit::apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const { SharedObject* object = objects.value(id); - if (!object) { - qDebug() << "Missing object to remove" << id; - return; + if (object) { + data.remove(attribute, object); } - data.remove(attribute, object); } ClearSpannersEdit::ClearSpannersEdit(const AttributePointer& attribute) : diff --git a/libraries/metavoxels/src/Spanner.cpp b/libraries/metavoxels/src/Spanner.cpp index 617d753414..7c58b7f297 100644 --- a/libraries/metavoxels/src/Spanner.cpp +++ b/libraries/metavoxels/src/Spanner.cpp @@ -24,6 +24,7 @@ #include +#include "MetavoxelData.h" #include "Spanner.h" using namespace std; @@ -1107,9 +1108,306 @@ template<> void Bitstream::readRawDelta(HeightfieldMaterialPointer& value, const } } +bool HeightfieldStreamState::shouldSubdivide() const { + return base.lod.shouldSubdivide(minimum, size); +} + +bool HeightfieldStreamState::shouldSubdivideReference() const { + return base.referenceLOD.shouldSubdivide(minimum, size); +} + +bool HeightfieldStreamState::becameSubdivided() const { + return base.lod.becameSubdivided(minimum, size, base.referenceLOD); +} + +bool HeightfieldStreamState::becameSubdividedOrCollapsed() const { + return base.lod.becameSubdividedOrCollapsed(minimum, size, base.referenceLOD); +} + +const int X_MAXIMUM_FLAG = 1; +const int Y_MAXIMUM_FLAG = 2; +const int MAXIMUM_FLAG_MASK = X_MAXIMUM_FLAG | Y_MAXIMUM_FLAG; + +static glm::vec2 getNextMinimum(const glm::vec2& minimum, float nextSize, int index) { + return minimum + glm::vec2( + (index & X_MAXIMUM_FLAG) ? nextSize : 0.0f, + (index & Y_MAXIMUM_FLAG) ? nextSize : 0.0f); +} + +void HeightfieldStreamState::setMinimum(const glm::vec2& lastMinimum, int index) { + minimum = getNextMinimum(lastMinimum, size, index); +} + +HeightfieldNode::HeightfieldNode(const HeightfieldHeightPointer& height, const HeightfieldColorPointer& color, + const HeightfieldMaterialPointer& material) : + _height(height), + _color(color), + _material(material) { +} + +bool HeightfieldNode::isLeaf() const { + for (int i = 0; i < CHILD_COUNT; i++) { + if (_children[i]) { + return false; + } + } + return true; +} + +void HeightfieldNode::read(HeightfieldStreamState& state) { + clearChildren(); + + if (!state.shouldSubdivide()) { + state.base.stream >> _height >> _color >> _material; + return; + } + bool leaf; + state.base.stream >> leaf; + if (leaf) { + state.base.stream >> _height >> _color >> _material; + + } else { + HeightfieldStreamState nextState = { state.base, glm::vec2(), state.size * 0.5f }; + for (int i = 0; i < CHILD_COUNT; i++) { + nextState.setMinimum(state.minimum, i); + _children[i] = new HeightfieldNode(); + _children[i]->read(nextState); + } + mergeChildren(); + } +} + +void HeightfieldNode::write(HeightfieldStreamState& state) const { + if (!state.shouldSubdivide()) { + state.base.stream << _height << _color << _material; + return; + } + bool leaf = isLeaf(); + state.base.stream << leaf; + if (leaf) { + state.base.stream << _height << _color << _material; + + } else { + HeightfieldStreamState nextState = { state.base, glm::vec2(), state.size * 0.5f }; + for (int i = 0; i < CHILD_COUNT; i++) { + nextState.setMinimum(state.minimum, i); + _children[i]->write(nextState); + } + } +} + +void HeightfieldNode::readDelta(const HeightfieldNodePointer& reference, HeightfieldStreamState& state) { + clearChildren(); + + if (!state.shouldSubdivide()) { + state.base.stream.readDelta(_height, reference->getHeight()); + state.base.stream.readDelta(_color, reference->getColor()); + state.base.stream.readDelta(_material, reference->getMaterial()); + return; + } + bool leaf; + state.base.stream >> leaf; + if (leaf) { + state.base.stream.readDelta(_height, reference->getHeight()); + state.base.stream.readDelta(_color, reference->getColor()); + state.base.stream.readDelta(_material, reference->getMaterial()); + + } else { + HeightfieldStreamState nextState = { state.base, glm::vec2(), state.size * 0.5f }; + if (reference->isLeaf() || !state.shouldSubdivideReference()) { + for (int i = 0; i < CHILD_COUNT; i++) { + nextState.setMinimum(state.minimum, i); + _children[i] = new HeightfieldNode(); + _children[i]->read(nextState); + } + } else { + for (int i = 0; i < CHILD_COUNT; i++) { + nextState.setMinimum(state.minimum, i); + bool changed; + state.base.stream >> changed; + if (changed) { + _children[i] = new HeightfieldNode(); + _children[i]->readDelta(reference->getChild(i), nextState); + } else { + if (nextState.becameSubdividedOrCollapsed()) { + _children[i] = reference->getChild(i)->readSubdivision(nextState); + + } else { + _children[i] = reference->getChild(i); + } + } + } + } + mergeChildren(); + } +} + +void HeightfieldNode::writeDelta(const HeightfieldNodePointer& reference, HeightfieldStreamState& state) const { + if (!state.shouldSubdivide()) { + state.base.stream.writeDelta(_height, reference->getHeight()); + state.base.stream.writeDelta(_color, reference->getColor()); + state.base.stream.writeDelta(_material, reference->getMaterial()); + return; + } + bool leaf = isLeaf(); + state.base.stream << leaf; + if (leaf) { + state.base.stream.writeDelta(_height, reference->getHeight()); + state.base.stream.writeDelta(_color, reference->getColor()); + state.base.stream.writeDelta(_material, reference->getMaterial()); + + } else { + HeightfieldStreamState nextState = { state.base, glm::vec2(), state.size * 0.5f }; + if (reference->isLeaf() || !state.shouldSubdivideReference()) { + for (int i = 0; i < CHILD_COUNT; i++) { + nextState.setMinimum(state.minimum, i); + _children[i]->write(nextState); + } + } else { + for (int i = 0; i < CHILD_COUNT; i++) { + nextState.setMinimum(state.minimum, i); + if (_children[i] == reference->getChild(i)) { + state.base.stream << false; + if (nextState.becameSubdivided()) { + _children[i]->writeSubdivision(nextState); + } + } else { + state.base.stream << true; + _children[i]->writeDelta(reference->getChild(i), nextState); + } + } + } + } +} + +HeightfieldNode* HeightfieldNode::readSubdivision(HeightfieldStreamState& state) { + if (state.shouldSubdivide()) { + if (!state.shouldSubdivideReference()) { + bool leaf; + state.base.stream >> leaf; + if (leaf) { + return isLeaf() ? this : new HeightfieldNode(_height, _color, _material); + + } else { + HeightfieldNode* newNode = new HeightfieldNode(_height, _color, _material); + HeightfieldStreamState nextState = { state.base, glm::vec2(), state.size * 0.5f }; + for (int i = 0; i < CHILD_COUNT; i++) { + nextState.setMinimum(state.minimum, i); + newNode->_children[i] = new HeightfieldNode(); + newNode->_children[i]->readSubdivided(nextState, state, this); + } + return newNode; + } + } else if (!isLeaf()) { + HeightfieldNode* node = this; + HeightfieldStreamState nextState = { state.base, glm::vec2(), state.size * 0.5f }; + for (int i = 0; i < CHILD_COUNT; i++) { + nextState.setMinimum(state.minimum, i); + if (nextState.becameSubdividedOrCollapsed()) { + HeightfieldNode* child = _children[i]->readSubdivision(nextState); + if (_children[i] != child) { + if (node == this) { + node = new HeightfieldNode(*this); + } + node->_children[i] = child; + } + } + } + if (node != this) { + node->mergeChildren(); + } + return node; + } + } else if (!isLeaf()) { + return new HeightfieldNode(_height, _color, _material); + } + return this; +} + +void HeightfieldNode::writeSubdivision(HeightfieldStreamState& state) const { + if (!state.shouldSubdivide()) { + return; + } + bool leaf = isLeaf(); + if (!state.shouldSubdivideReference()) { + state.base.stream << leaf; + if (!leaf) { + HeightfieldStreamState nextState = { state.base, glm::vec2(), state.size * 0.5f }; + for (int i = 0; i < CHILD_COUNT; i++) { + nextState.setMinimum(state.minimum, i); + _children[i]->writeSubdivided(nextState, state, this); + } + } + } else if (!leaf) { + HeightfieldStreamState nextState = { state.base, glm::vec2(), state.size * 0.5f }; + for (int i = 0; i < CHILD_COUNT; i++) { + nextState.setMinimum(state.minimum, i); + if (nextState.becameSubdivided()) { + _children[i]->writeSubdivision(nextState); + } + } + } +} + +void HeightfieldNode::readSubdivided(HeightfieldStreamState& state, const HeightfieldStreamState& ancestorState, + const HeightfieldNode* ancestor) { + clearChildren(); + + if (!state.shouldSubdivide()) { + // TODO: subdivision encoding + state.base.stream >> _height >> _color >> _material; + return; + } + bool leaf; + state.base.stream >> leaf; + if (leaf) { + state.base.stream >> _height >> _color >> _material; + + } else { + HeightfieldStreamState nextState = { state.base, glm::vec2(), state.size * 0.5f }; + for (int i = 0; i < CHILD_COUNT; i++) { + nextState.setMinimum(state.minimum, i); + _children[i] = new HeightfieldNode(); + _children[i]->readSubdivided(nextState, ancestorState, ancestor); + } + mergeChildren(); + } +} + +void HeightfieldNode::writeSubdivided(HeightfieldStreamState& state, const HeightfieldStreamState& ancestorState, + const HeightfieldNode* ancestor) const { + if (!state.shouldSubdivide()) { + // TODO: subdivision encoding + state.base.stream << _height << _color << _material; + return; + } + bool leaf = isLeaf(); + state.base.stream << leaf; + if (leaf) { + state.base.stream << _height << _color << _material; + + } else { + HeightfieldStreamState nextState = { state.base, glm::vec2(), state.size * 0.5f }; + for (int i = 0; i < CHILD_COUNT; i++) { + nextState.setMinimum(state.minimum, i); + _children[i]->writeSubdivided(nextState, ancestorState, ancestor); + } + } +} + +void HeightfieldNode::clearChildren() { + for (int i = 0; i < CHILD_COUNT; i++) { + _children[i].reset(); + } +} + +void HeightfieldNode::mergeChildren() { +} + Heightfield::Heightfield() : _aspectY(1.0f), - _aspectZ(1.0f) { + _aspectZ(1.0f), + _root(new HeightfieldNode()) { connect(this, &Heightfield::translationChanged, this, &Heightfield::updateBounds); connect(this, &Heightfield::rotationChanged, this, &Heightfield::updateBounds); @@ -2115,6 +2413,69 @@ bool Heightfield::intersects(const glm::vec3& start, const glm::vec3& end, float return false; } +void Heightfield::writeExtra(Bitstream& out) const { + MetavoxelLOD lod; + if (out.getContext()) { + lod = transformLOD(static_cast(out.getContext())->lod); + } + HeightfieldStreamBase base = { out, lod, lod }; + HeightfieldStreamState state = { base, glm::vec2(), 1.0f }; + _root->write(state); +} + +void Heightfield::readExtra(Bitstream& in) { + MetavoxelLOD lod; + if (in.getContext()) { + lod = transformLOD(static_cast(in.getContext())->lod); + } + HeightfieldStreamBase base = { in, lod, lod }; + HeightfieldStreamState state = { base, glm::vec2(), 1.0f }; + _root = new HeightfieldNode(); + _root->read(state); +} + +void Heightfield::writeExtraDelta(Bitstream& out, const SharedObject* reference) const { + MetavoxelLOD lod, referenceLOD; + if (out.getContext()) { + MetavoxelStreamBase* base = static_cast(out.getContext()); + lod = transformLOD(base->lod); + referenceLOD = transformLOD(base->referenceLOD); + } + HeightfieldStreamBase base = { out, lod, referenceLOD }; + HeightfieldStreamState state = { base, glm::vec2(), 1.0f }; + const HeightfieldNodePointer& referenceRoot = static_cast(reference)->getRoot(); + if (_root == referenceRoot) { + out << false; + if (state.becameSubdivided()) { + _root->writeSubdivision(state); + } + } else { + out << true; + _root->writeDelta(referenceRoot, state); + } +} + +void Heightfield::readExtraDelta(Bitstream& in, const SharedObject* reference) { + MetavoxelLOD lod, referenceLOD; + if (in.getContext()) { + MetavoxelStreamBase* base = static_cast(in.getContext()); + lod = transformLOD(base->lod); + referenceLOD = transformLOD(base->referenceLOD); + } + HeightfieldStreamBase base = { in, lod, referenceLOD }; + HeightfieldStreamState state = { base, glm::vec2(), 1.0f }; + + bool changed; + in >> changed; + if (changed) { + _root = new HeightfieldNode(); + _root->readDelta(static_cast(reference)->getRoot(), state); + + } else if (state.becameSubdividedOrCollapsed()) { + _root = _root->readSubdivision(state); + } +} + QByteArray Heightfield::getRendererClassName() const { return "HeightfieldRenderer"; } @@ -2124,3 +2485,12 @@ void Heightfield::updateBounds() { glm::mat4 rotationMatrix = glm::mat4_cast(getRotation()); setBounds(glm::translate(getTranslation()) * rotationMatrix * Box(glm::vec3(), extent)); } + +MetavoxelLOD Heightfield::transformLOD(const MetavoxelLOD& lod) const { + // after transforming into unit space, we scale the threshold in proportion to vertical distance + glm::vec3 inverseScale(1.0f / getScale(), 1.0f / (getScale() * _aspectY), 1.0f / (getScale() * _aspectZ)); + glm::vec3 position = glm::inverse(getRotation()) * (lod.position - getTranslation()) * inverseScale; + const float THRESHOLD_MULTIPLIER = 2.0f; + return MetavoxelLOD(glm::vec3(position.x, position.z, 0.0f), lod.threshold * + qMax(0.5f, glm::abs(position.y - 0.5f)) * THRESHOLD_MULTIPLIER); +} diff --git a/libraries/metavoxels/src/Spanner.h b/libraries/metavoxels/src/Spanner.h index 7fe32b56a6..bb79a6fc51 100644 --- a/libraries/metavoxels/src/Spanner.h +++ b/libraries/metavoxels/src/Spanner.h @@ -20,6 +20,7 @@ class HeightfieldColor; class HeightfieldHeight; class HeightfieldMaterial; +class HeightfieldNode; class SpannerRenderer; /// An object that spans multiple octree cells. @@ -458,6 +459,75 @@ Bitstream& operator>>(Bitstream& in, HeightfieldMaterialPointer& value); template<> void Bitstream::writeRawDelta(const HeightfieldMaterialPointer& value, const HeightfieldMaterialPointer& reference); template<> void Bitstream::readRawDelta(HeightfieldMaterialPointer& value, const HeightfieldMaterialPointer& reference); +typedef QExplicitlySharedDataPointer HeightfieldNodePointer; + +/// Holds the base state used in streaming heightfield data. +class HeightfieldStreamBase { +public: + Bitstream& stream; + const MetavoxelLOD& lod; + const MetavoxelLOD& referenceLOD; +}; + +/// Holds the state used in streaming a heightfield node. +class HeightfieldStreamState { +public: + HeightfieldStreamBase& base; + glm::vec2 minimum; + float size; + + bool shouldSubdivide() const; + bool shouldSubdivideReference() const; + bool becameSubdivided() const; + bool becameSubdividedOrCollapsed() const; + + void setMinimum(const glm::vec2& lastMinimum, int index); +}; + +/// A node in a heightfield quadtree. +class HeightfieldNode : public QSharedData { +public: + + static const int CHILD_COUNT = 4; + + HeightfieldNode(const HeightfieldHeightPointer& height = HeightfieldHeightPointer(), + const HeightfieldColorPointer& color = HeightfieldColorPointer(), + const HeightfieldMaterialPointer& material = HeightfieldMaterialPointer()); + + const HeightfieldHeightPointer& getHeight() const { return _height; } + const HeightfieldColorPointer& getColor() const { return _color; } + const HeightfieldMaterialPointer& getMaterial() const { return _material; } + + bool isLeaf() const; + + const HeightfieldNodePointer& getChild(int index) const { return _children[index]; } + + void read(HeightfieldStreamState& state); + void write(HeightfieldStreamState& state) const; + + void readDelta(const HeightfieldNodePointer& reference, HeightfieldStreamState& state); + void writeDelta(const HeightfieldNodePointer& reference, HeightfieldStreamState& state) const; + + HeightfieldNode* readSubdivision(HeightfieldStreamState& state); + void writeSubdivision(HeightfieldStreamState& state) const; + + void readSubdivided(HeightfieldStreamState& state, const HeightfieldStreamState& ancestorState, + const HeightfieldNode* ancestor); + void writeSubdivided(HeightfieldStreamState& state, const HeightfieldStreamState& ancestorState, + const HeightfieldNode* ancestor) const; + +private: + + void clearChildren(); + void mergeChildren(); + + HeightfieldHeightPointer _height; + HeightfieldColorPointer _color; + HeightfieldMaterialPointer _material; + + HeightfieldNodePointer _children[CHILD_COUNT]; +}; + /// A heightfield represented as a spanner. class Heightfield : public Transformable { Q_OBJECT @@ -486,6 +556,8 @@ public: void setMaterial(const HeightfieldMaterialPointer& material); const HeightfieldMaterialPointer& getMaterial() const { return _material; } + const HeightfieldNodePointer& getRoot() const { return _root; } + virtual bool isHeightfield() const; virtual float getHeight(const glm::vec3& location) const; @@ -508,6 +580,11 @@ public: virtual bool contains(const glm::vec3& point); virtual bool intersects(const glm::vec3& start, const glm::vec3& end, float& distance, glm::vec3& normal); + virtual void writeExtra(Bitstream& out) const; + virtual void readExtra(Bitstream& in); + virtual void writeExtraDelta(Bitstream& out, const SharedObject* reference) const; + virtual void readExtraDelta(Bitstream& in, const SharedObject* reference); + signals: void aspectYChanged(float aspectY); @@ -526,11 +603,16 @@ private slots: private: + MetavoxelLOD transformLOD(const MetavoxelLOD& lod) const; + float _aspectY; float _aspectZ; + HeightfieldHeightPointer _height; HeightfieldColorPointer _color; HeightfieldMaterialPointer _material; + + HeightfieldNodePointer _root; }; #endif // hifi_Spanner_h diff --git a/libraries/networking/src/PacketHeaders.cpp b/libraries/networking/src/PacketHeaders.cpp index b1c47c0ebf..3f08cdec69 100644 --- a/libraries/networking/src/PacketHeaders.cpp +++ b/libraries/networking/src/PacketHeaders.cpp @@ -81,7 +81,7 @@ PacketVersion versionForPacketType(PacketType type) { case PacketTypeAudioStreamStats: return 1; case PacketTypeMetavoxelData: - return 9; + return 10; case PacketTypeVoxelData: return VERSION_VOXELS_HAS_FILE_BREAKS; default: From a987e7ce10f0283682eab01d77a21e4802a64f65 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 25 Nov 2014 15:32:02 -0800 Subject: [PATCH 084/502] When we set heightfield layers, break it up into quadtree. --- libraries/metavoxels/src/Spanner.cpp | 103 ++++++++++++++++++++++++++- libraries/metavoxels/src/Spanner.h | 11 ++- 2 files changed, 109 insertions(+), 5 deletions(-) diff --git a/libraries/metavoxels/src/Spanner.cpp b/libraries/metavoxels/src/Spanner.cpp index 7c58b7f297..a57cc8a31c 100644 --- a/libraries/metavoxels/src/Spanner.cpp +++ b/libraries/metavoxels/src/Spanner.cpp @@ -1145,6 +1145,94 @@ HeightfieldNode::HeightfieldNode(const HeightfieldHeightPointer& height, const H _material(material) { } +const int HEIGHT_LEAF_SIZE = 256 + HeightfieldHeight::HEIGHT_EXTENSION; + +void HeightfieldNode::setContents(const HeightfieldHeightPointer& height, const HeightfieldColorPointer& color, + const HeightfieldMaterialPointer& material) { + clearChildren(); + + int heightWidth = height->getWidth(); + if (heightWidth <= HEIGHT_LEAF_SIZE) { + _height = height; + _color = color; + _material = material; + return; + } + int heightHeight = height->getContents().size() / heightWidth; + int innerChildHeightWidth = (heightWidth - HeightfieldHeight::HEIGHT_EXTENSION) / 2; + int innerChildHeightHeight = (heightHeight - HeightfieldHeight::HEIGHT_EXTENSION) / 2; + int childHeightWidth = innerChildHeightWidth + HeightfieldHeight::HEIGHT_EXTENSION; + int childHeightHeight = innerChildHeightHeight + HeightfieldHeight::HEIGHT_EXTENSION; + + for (int i = 0; i < CHILD_COUNT; i++) { + QVector childHeightContents(childHeightWidth * childHeightHeight); + quint16* heightDest = childHeightContents.data(); + bool maximumX = (i & X_MAXIMUM_FLAG), maximumY = (i & Y_MAXIMUM_FLAG); + const quint16* heightSrc = height->getContents().constData() + (maximumY ? innerChildHeightHeight * heightWidth : 0) + + (maximumX ? innerChildHeightWidth : 0); + for (int z = 0; z < childHeightHeight; z++, heightDest += childHeightWidth, heightSrc += heightWidth) { + memcpy(heightDest, heightSrc, childHeightWidth * sizeof(quint16)); + } + + HeightfieldColorPointer childColor; + if (color) { + int colorWidth = color->getWidth(); + int colorHeight = color->getContents().size() / (colorWidth * DataBlock::COLOR_BYTES); + int innerChildColorWidth = (colorWidth - HeightfieldData::SHARED_EDGE) / 2; + int innerChildColorHeight = (colorHeight - HeightfieldData::SHARED_EDGE) / 2; + int childColorWidth = innerChildColorWidth + HeightfieldData::SHARED_EDGE; + int childColorHeight = innerChildColorHeight + HeightfieldData::SHARED_EDGE; + QByteArray childColorContents(childColorWidth * childColorHeight * DataBlock::COLOR_BYTES, 0); + char* dest = childColorContents.data(); + const char* src = color->getContents().constData() + ((maximumY ? innerChildColorHeight * colorWidth : 0) + + (maximumX ? innerChildColorWidth : 0)) * DataBlock::COLOR_BYTES; + for (int z = 0; z < childColorHeight; z++, dest += childColorWidth * DataBlock::COLOR_BYTES, + src += colorWidth * DataBlock::COLOR_BYTES) { + memcpy(dest, src, childColorWidth * DataBlock::COLOR_BYTES); + } + childColor = new HeightfieldColor(childColorWidth, childColorContents); + } + + HeightfieldMaterialPointer childMaterial; + if (material) { + int materialWidth = material->getWidth(); + int materialHeight = material->getContents().size() / materialWidth; + int innerChildMaterialWidth = (materialWidth - HeightfieldData::SHARED_EDGE) / 2; + int innerChildMaterialHeight = (materialHeight - HeightfieldData::SHARED_EDGE) / 2; + int childMaterialWidth = innerChildMaterialWidth + HeightfieldData::SHARED_EDGE; + int childMaterialHeight = innerChildMaterialHeight + HeightfieldData::SHARED_EDGE; + QByteArray childMaterialContents(childMaterialWidth * childMaterialHeight, 0); + QVector childMaterials; + uchar* dest = (uchar*)childMaterialContents.data(); + const uchar* src = (const uchar*)material->getContents().data() + + (maximumY ? innerChildMaterialHeight * materialWidth : 0) + (maximumX ? innerChildMaterialWidth : 0); + QHash materialMap; + for (int z = 0; z < childMaterialHeight; z++, dest += childMaterialWidth, src += materialWidth) { + const uchar* lineSrc = src; + for (uchar* lineDest = dest, *end = dest + childMaterialWidth; lineDest != end; lineDest++, lineSrc++) { + int value = *lineSrc; + if (value != 0) { + int& mapping = materialMap[value]; + if (mapping == 0) { + childMaterials.append(material->getMaterials().at(value - 1)); + mapping = childMaterials.size(); + } + value = mapping; + } + *lineDest = value; + } + } + childMaterial = new HeightfieldMaterial(childMaterialWidth, childMaterialContents, childMaterials); + } + + _children[i] = new HeightfieldNode(); + _children[i]->setContents(HeightfieldHeightPointer(new HeightfieldHeight(childHeightWidth, childHeightContents)), + childColor, childMaterial); + } + + mergeChildren(); +} + bool HeightfieldNode::isLeaf() const { for (int i = 0; i < CHILD_COUNT; i++) { if (_children[i]) { @@ -1406,8 +1494,7 @@ void HeightfieldNode::mergeChildren() { Heightfield::Heightfield() : _aspectY(1.0f), - _aspectZ(1.0f), - _root(new HeightfieldNode()) { + _aspectZ(1.0f) { connect(this, &Heightfield::translationChanged, this, &Heightfield::updateBounds); connect(this, &Heightfield::rotationChanged, this, &Heightfield::updateBounds); @@ -1415,6 +1502,11 @@ Heightfield::Heightfield() : connect(this, &Heightfield::aspectYChanged, this, &Heightfield::updateBounds); connect(this, &Heightfield::aspectZChanged, this, &Heightfield::updateBounds); updateBounds(); + + connect(this, &Heightfield::heightChanged, this, &Heightfield::updateRoot); + connect(this, &Heightfield::colorChanged, this, &Heightfield::updateRoot); + connect(this, &Heightfield::materialChanged, this, &Heightfield::updateRoot); + updateRoot(); } void Heightfield::setAspectY(float aspectY) { @@ -2486,6 +2578,13 @@ void Heightfield::updateBounds() { setBounds(glm::translate(getTranslation()) * rotationMatrix * Box(glm::vec3(), extent)); } +void Heightfield::updateRoot() { + _root = new HeightfieldNode(); + if (_height) { + _root->setContents(_height, _color, _material); + } +} + MetavoxelLOD Heightfield::transformLOD(const MetavoxelLOD& lod) const { // after transforming into unit space, we scale the threshold in proportion to vertical distance glm::vec3 inverseScale(1.0f / getScale(), 1.0f / (getScale() * _aspectY), 1.0f / (getScale() * _aspectZ)); diff --git a/libraries/metavoxels/src/Spanner.h b/libraries/metavoxels/src/Spanner.h index bb79a6fc51..d67c23909d 100644 --- a/libraries/metavoxels/src/Spanner.h +++ b/libraries/metavoxels/src/Spanner.h @@ -494,6 +494,9 @@ public: const HeightfieldColorPointer& color = HeightfieldColorPointer(), const HeightfieldMaterialPointer& material = HeightfieldMaterialPointer()); + void setContents(const HeightfieldHeightPointer& height, const HeightfieldColorPointer& color, + const HeightfieldMaterialPointer& material); + const HeightfieldHeightPointer& getHeight() const { return _height; } const HeightfieldColorPointer& getColor() const { return _color; } const HeightfieldMaterialPointer& getMaterial() const { return _material; } @@ -533,9 +536,10 @@ class Heightfield : public Transformable { Q_OBJECT Q_PROPERTY(float aspectY MEMBER _aspectY WRITE setAspectY NOTIFY aspectYChanged) Q_PROPERTY(float aspectZ MEMBER _aspectZ WRITE setAspectZ NOTIFY aspectZChanged) - Q_PROPERTY(HeightfieldHeightPointer height MEMBER _height WRITE setHeight NOTIFY heightChanged) - Q_PROPERTY(HeightfieldColorPointer color MEMBER _color WRITE setColor NOTIFY colorChanged) - Q_PROPERTY(HeightfieldMaterialPointer material MEMBER _material WRITE setMaterial NOTIFY materialChanged DESIGNABLE false) + Q_PROPERTY(HeightfieldHeightPointer height MEMBER _height WRITE setHeight NOTIFY heightChanged STORED false) + Q_PROPERTY(HeightfieldColorPointer color MEMBER _color WRITE setColor NOTIFY colorChanged STORED false) + Q_PROPERTY(HeightfieldMaterialPointer material MEMBER _material WRITE setMaterial NOTIFY materialChanged STORED false + DESIGNABLE false) public: @@ -600,6 +604,7 @@ protected: private slots: void updateBounds(); + void updateRoot(); private: From 77077f4e9c71ef66d34fdd30c70e833e8e042315 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 25 Nov 2014 18:17:28 -0800 Subject: [PATCH 085/502] hack a separate emissive information in the g-buffer --- .../resources/shaders/directional_light.frag | 45 ++++++++++++------- .../resources/shaders/model_lightmap.frag | 6 +-- interface/src/renderer/GeometryCache.cpp | 11 ++++- interface/src/renderer/Model.cpp | 8 ++-- libraries/fbx/src/FBXReader.cpp | 24 +++++----- libraries/fbx/src/FBXReader.h | 1 + 6 files changed, 58 insertions(+), 37 deletions(-) diff --git a/interface/resources/shaders/directional_light.frag b/interface/resources/shaders/directional_light.frag index da48149001..d4a6f5a28b 100644 --- a/interface/resources/shaders/directional_light.frag +++ b/interface/resources/shaders/directional_light.frag @@ -36,25 +36,36 @@ uniform vec2 depthTexCoordOffset; uniform vec2 depthTexCoordScale; void main(void) { + float depthVal = texture2D(depthMap, gl_TexCoord[0].st).r; + vec4 normalVal = texture2D(normalMap, gl_TexCoord[0].st); + vec4 diffuseVal = texture2D(diffuseMap, gl_TexCoord[0].st); + vec4 specularVal = texture2D(specularMap, gl_TexCoord[0].st); + // compute the view space position using the depth - float z = near / (texture2D(depthMap, gl_TexCoord[0].st).r * depthScale - 1.0); + float z = near / (depthVal * depthScale - 1.0); vec4 position = vec4((depthTexCoordOffset + gl_TexCoord[0].st * depthTexCoordScale) * z, z, 0.0); // get the normal from the map - vec4 normal = texture2D(normalMap, gl_TexCoord[0].st); - vec4 normalizedNormal = normalize(normal * 2.0 - vec4(1.0, 1.0, 1.0, 2.0)); - - // compute the base color based on OpenGL lighting model - float diffuse = dot(normalizedNormal, gl_LightSource[0].position); - float facingLight = step(0.0, diffuse); - vec4 baseColor = texture2D(diffuseMap, gl_TexCoord[0].st) * (gl_FrontLightModelProduct.sceneColor + - gl_FrontLightProduct[0].ambient + gl_FrontLightProduct[0].diffuse * (diffuse * facingLight)); - - // compute the specular multiplier (sans exponent) - float specular = facingLight * max(0.0, dot(normalize(gl_LightSource[0].position - normalize(position)), - normalizedNormal)); - - // add specular contribution - vec4 specularColor = texture2D(specularMap, gl_TexCoord[0].st); - gl_FragColor = vec4(baseColor.rgb + pow(specular, specularColor.a * 128.0) * specularColor.rgb, normal.a); + vec4 normal = normalVal; + if (normalVal.a == 0.5) { + normal.a = 1.0; + normalVal.a = 0.0; + gl_FragColor = vec4(diffuseVal.rgb * specularColor.rgb, normal.a); + } else { + vec3 normalizedNormal = normalize(normal.xyz * 2.0 - vec3(1.0)); + + // compute the base color based on OpenGL lighting model + float diffuse = dot(normalizedNormal, gl_LightSource[0].position.xyz); + float facingLight = step(0.0, diffuse); + vec3 baseColor = diffuseVal.rgb * (gl_FrontLightModelProduct.sceneColor.rgb + + gl_FrontLightProduct[0].ambient.rgb + gl_FrontLightProduct[0].diffuse.rgb * (diffuse * facingLight)); + + // compute the specular multiplier (sans exponent) + float specular = facingLight * max(0.0, dot(normalize(gl_LightSource[0].position.xyz - normalize(position.xyz)), + normalizedNormal)); + + // add specular contribution + vec4 specularColor = specularVal; + gl_FragColor = vec4(baseColor.rgb + pow(specular, specularColor.a * 128.0) * specularColor.rgb, normal.a); + } } diff --git a/interface/resources/shaders/model_lightmap.frag b/interface/resources/shaders/model_lightmap.frag index b93f0abc6f..7c352b877e 100644 --- a/interface/resources/shaders/model_lightmap.frag +++ b/interface/resources/shaders/model_lightmap.frag @@ -31,7 +31,7 @@ void main(void) { // set the diffuse, normal, specular data vec4 diffuse = texture2D(diffuseMap, gl_TexCoord[0].st); vec4 emissive = texture2D(emissiveMap, interpolatedTexcoord1.st); - gl_FragData[0] = vec4(gl_Color.rgb * diffuse.rgb * (vec3(emissiveParams.x) + emissiveParams.y * emissive.rgb), mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); - gl_FragData[1] = normalize(normal) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0); - gl_FragData[2] = vec4(gl_FrontMaterial.specular.rgb, gl_FrontMaterial.shininess / 128.0); + gl_FragData[0] = vec4(gl_Color.rgb * diffuse.rgb, mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); + gl_FragData[1] = normalize(normal) * 0.5 + vec4(0.5, 0.5, 0.5, 0.5); + gl_FragData[2] = vec4((vec3(emissiveParams.x) + emissiveParams.y * emissive.rgb), gl_FrontMaterial.shininess / 128.0); } diff --git a/interface/src/renderer/GeometryCache.cpp b/interface/src/renderer/GeometryCache.cpp index c7d8b7fc8a..5ef90732ef 100644 --- a/interface/src/renderer/GeometryCache.cpp +++ b/interface/src/renderer/GeometryCache.cpp @@ -829,10 +829,17 @@ void GeometryReader::run() { return; } try { - QMetaObject::invokeMethod(geometry.data(), "setGeometry", Q_ARG(const FBXGeometry&, + std::string urlname = _url.path().toLower().toStdString(); + FBXGeometry fbxgeo; + if (_url.path().toLower().endsWith(".svo")) { + fbxgeo = readSVO(_reply->readAll()); + } else { + fbxgeo = readFBX(_reply->readAll(), _mapping); + } + QMetaObject::invokeMethod(geometry.data(), "setGeometry", Q_ARG(const FBXGeometry&, fbxgeo)); - _url.path().toLower().endsWith(".svo") ? readSVO(_reply->readAll()) : readFBX(_reply->readAll(), _mapping))); + // _url.path().toLower().endsWith(".svo") ? readSVO(_reply->readAll()) : readFBX(_reply->readAll(), _mapping))); } catch (const QString& error) { qDebug() << "Error reading " << _url << ": " << error; diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index e6dc3ce74e..2e17cc2605 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -2382,12 +2382,10 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod } if (locations->emissiveTextureUnit >= 0) { - assert(locations->emissiveParams >= 0); // we should have the emissiveParams defined in the shader - static float emissiveOffset = 0.1f; - static float emissiveScale = 1.0f; - //GLBATCH(glUniform2f)(locations->emissiveParams, 0.1f, 4.0f); + // assert(locations->emissiveParams >= 0); // we should have the emissiveParams defined in the shader + float emissiveOffset = part.emissiveParams.x; + float emissiveScale = part.emissiveParams.y; GLBATCH(glUniform2f)(locations->emissiveParams, emissiveOffset, emissiveScale); - GLBATCH(glActiveTexture)(GL_TEXTURE0 + locations->emissiveTextureUnit); Texture* emissiveMap = networkPart.emissiveTexture.data(); diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index b54abedc33..fd9190f597 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -1216,6 +1216,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) QHash bumpTextures; QHash specularTextures; QHash emissiveTextures; + QHash ambientTextures; QHash localRotations; QHash xComponents; QHash yComponents; @@ -1707,7 +1708,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) emissiveTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1)); } else if (type.contains("ambient")) { - emissiveTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1)); + ambientTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1)); } else { std::string typenam = type.data(); counter++; @@ -1952,19 +1953,20 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) } FBXTexture emissiveTexture; + glm::vec2 emissiveParams(0.f, 1.f); QString emissiveTextureID = emissiveTextures.value(childID); - if (!emissiveTextureID.isNull()) { - emissiveTexture = getTexture(emissiveTextureID, textureNames, textureFilenames, textureContent, textureParams); - - // FBX files generated by 3DSMax have an intermediate texture parent, apparently - foreach (const QString& childTextureID, childMap.values(diffuseTextureID)) { - if (textureFilenames.contains(childTextureID)) { - emissiveTexture = getTexture(emissiveTextureID, textureNames, textureFilenames, textureContent, textureParams); - } + QString ambientTextureID = ambientTextures.value(childID); + if (!emissiveTextureID.isNull() || !ambientTextureID.isNull()) { + + if (!emissiveTextureID.isNull()) { + emissiveTexture = getTexture(emissiveTextureID, textureNames, textureFilenames, textureContent, textureParams); + emissiveParams.y = 4.0f; + } else if (!ambientTextureID.isNull()) { + emissiveTexture = getTexture(ambientTextureID, textureNames, textureFilenames, textureContent, textureParams); } emissiveTexture.texcoordSet = matchTextureUVSetToAttributeChannel(emissiveTexture.texcoordSetName, extracted.texcoordSetMap); - + detectDifferentUVs |= (emissiveTexture.texcoordSet != 0) || (!emissiveTexture.transform.isIdentity()); } @@ -1992,6 +1994,8 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) if (!emissiveTexture.filename.isNull()) { part.emissiveTexture = emissiveTexture; } + part.emissiveParams = emissiveParams; + part.materialID = material.id; } } diff --git a/libraries/fbx/src/FBXReader.h b/libraries/fbx/src/FBXReader.h index 60e8ea2448..d92f787050 100644 --- a/libraries/fbx/src/FBXReader.h +++ b/libraries/fbx/src/FBXReader.h @@ -119,6 +119,7 @@ public: glm::vec3 diffuseColor; glm::vec3 specularColor; glm::vec3 emissiveColor; + glm::vec2 emissiveParams; float shininess; float opacity; From 7f14a6692233210aee91eee27c1bf48102efe8f3 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 25 Nov 2014 18:27:09 -0800 Subject: [PATCH 086/502] More work on heightfield quadtrees. --- interface/src/ui/MetavoxelEditor.cpp | 67 +------------ libraries/metavoxels/src/Spanner.cpp | 145 +++++++++++++++++++++++++++ 2 files changed, 149 insertions(+), 63 deletions(-) diff --git a/interface/src/ui/MetavoxelEditor.cpp b/interface/src/ui/MetavoxelEditor.cpp index b6b43c4baf..cf28a79995 100644 --- a/interface/src/ui/MetavoxelEditor.cpp +++ b/interface/src/ui/MetavoxelEditor.cpp @@ -792,76 +792,17 @@ void ImportHeightfieldTool::renderPreview() { static_cast(_spanner.data())->getRenderer()->render(); } -const int HEIGHTFIELD_BLOCK_SIZE = 256; - void ImportHeightfieldTool::apply() { AttributePointer attribute = AttributeRegistry::getInstance()->getAttribute(_editor->getSelectedAttribute()); if (!(_height->getHeight() && attribute)) { return; } - int width = _height->getHeight()->getWidth(); - const QVector& contents = _height->getHeight()->getContents(); - int height = contents.size() / width; - int innerWidth = width - HeightfieldHeight::HEIGHT_EXTENSION; - int innerHeight = height - HeightfieldHeight::HEIGHT_EXTENSION; - float scale = pow(2.0, _scale->value()); - - for (int i = 0; i < innerHeight; i += HEIGHTFIELD_BLOCK_SIZE) { - for (int j = 0; j < innerWidth; j += HEIGHTFIELD_BLOCK_SIZE) { - Heightfield* heightfield = new Heightfield(); - - int extendedHeightSize = HEIGHTFIELD_BLOCK_SIZE + HeightfieldHeight::HEIGHT_EXTENSION; - QVector heightContents(extendedHeightSize * extendedHeightSize); - quint16* dest = heightContents.data(); - const quint16* src = contents.constData() + i * width + j; - int copyWidth = qMin(width - j, extendedHeightSize); - int copyHeight = qMin(height - i, extendedHeightSize); - for (int z = 0; z < copyHeight; z++, src += width, dest += extendedHeightSize) { - memcpy(dest, src, copyWidth * sizeof(quint16)); - } - heightfield->setHeight(HeightfieldHeightPointer(new HeightfieldHeight(extendedHeightSize, heightContents))); - - int materialWidth = HEIGHTFIELD_BLOCK_SIZE + HeightfieldData::SHARED_EDGE; - int materialHeight = materialWidth; - if (_color->getColor()) { - int colorWidth = _color->getColor()->getWidth(); - const QByteArray& contents = _color->getColor()->getContents(); - int colorHeight = contents.size() / (colorWidth * DataBlock::COLOR_BYTES); - int innerColorWidth = colorWidth - HeightfieldData::SHARED_EDGE; - int innerColorHeight = colorHeight - HeightfieldData::SHARED_EDGE; - materialWidth = HEIGHTFIELD_BLOCK_SIZE * innerColorWidth / innerWidth + HeightfieldData::SHARED_EDGE; - materialHeight = HEIGHTFIELD_BLOCK_SIZE * innerColorHeight / innerHeight + HeightfieldData::SHARED_EDGE; - QByteArray colorContents(materialWidth * materialHeight * DataBlock::COLOR_BYTES, 0); - int colorI = i * (materialWidth - HeightfieldData::SHARED_EDGE) / HEIGHTFIELD_BLOCK_SIZE; - int colorJ = j * (materialHeight - HeightfieldData::SHARED_EDGE) / HEIGHTFIELD_BLOCK_SIZE; - char* dest = colorContents.data(); - const char* src = contents.constData() + (colorI * colorWidth + colorJ) * DataBlock::COLOR_BYTES; - int copyWidth = qMin(colorWidth - colorJ, materialWidth); - int copyHeight = qMin(colorHeight - colorI, materialHeight); - for (int z = 0; z < copyHeight; z++, src += colorWidth * DataBlock::COLOR_BYTES, - dest += materialWidth * DataBlock::COLOR_BYTES) { - memcpy(dest, src, copyWidth * DataBlock::COLOR_BYTES); - } - heightfield->setColor(HeightfieldColorPointer(new HeightfieldColor(materialWidth, colorContents))); - - } else { - heightfield->setColor(HeightfieldColorPointer(new HeightfieldColor(materialWidth, - QByteArray(materialWidth * materialHeight * DataBlock::COLOR_BYTES, 0xFF)))); - } - heightfield->setMaterial(HeightfieldMaterialPointer(new HeightfieldMaterial(materialWidth, - QByteArray(materialWidth * materialHeight, 0), QVector()))); - - heightfield->setScale(scale); - heightfield->setAspectY(_heightScale->value() / scale); - heightfield->setTranslation(_translation->getValue() + glm::vec3((j / HEIGHTFIELD_BLOCK_SIZE) * scale, - _heightOffset->value(), (i / HEIGHTFIELD_BLOCK_SIZE) * scale)); - - MetavoxelEditMessage message = { QVariant::fromValue(InsertSpannerEdit(attribute, heightfield)) }; - Application::getInstance()->getMetavoxels()->applyEdit(message, true); - } - } + MetavoxelEditMessage message = { QVariant::fromValue(InsertSpannerEdit(attribute, _spanner)) }; + Application::getInstance()->getMetavoxels()->applyEdit(message, true); } +const int HEIGHTFIELD_BLOCK_SIZE = 256; + void ImportHeightfieldTool::updateSpanner() { Heightfield* heightfield = static_cast(_spanner.data()); heightfield->setHeight(_height->getHeight()); diff --git a/libraries/metavoxels/src/Spanner.cpp b/libraries/metavoxels/src/Spanner.cpp index a57cc8a31c..07eb2d02a3 100644 --- a/libraries/metavoxels/src/Spanner.cpp +++ b/libraries/metavoxels/src/Spanner.cpp @@ -1490,6 +1490,151 @@ void HeightfieldNode::clearChildren() { } void HeightfieldNode::mergeChildren() { + if (isLeaf()) { + return; + } + int heightWidth = 0; + int heightHeight = 0; + int colorWidth = 0; + int colorHeight = 0; + int materialWidth = 0; + int materialHeight = 0; + for (int i = 0; i < CHILD_COUNT; i++) { + HeightfieldHeightPointer childHeight = _children[i]->getHeight(); + if (childHeight) { + int childHeightWidth = childHeight->getWidth(); + int childHeightHeight = childHeight->getContents().size() / childHeightWidth; + heightWidth = qMax(heightWidth, childHeightWidth); + heightHeight = qMax(heightHeight, childHeightHeight); + } + HeightfieldColorPointer childColor = _children[i]->getColor(); + if (childColor) { + int childColorWidth = childColor->getWidth(); + int childColorHeight = childColor->getContents().size() / (childColorWidth * DataBlock::COLOR_BYTES); + colorWidth = qMax(colorWidth, childColorWidth); + colorHeight = qMax(colorHeight, childColorHeight); + } + HeightfieldMaterialPointer childMaterial = _children[i]->getMaterial(); + if (childMaterial) { + int childMaterialWidth = childMaterial->getWidth(); + int childMaterialHeight = childMaterial->getContents().size() / childMaterialWidth; + materialWidth = qMax(materialWidth, childMaterialWidth); + materialHeight = qMax(materialHeight, childMaterialHeight); + } + } + if (heightWidth > 0) { + QVector heightContents(heightWidth * heightHeight); + for (int i = 0; i < CHILD_COUNT; i++) { + HeightfieldHeightPointer childHeight = _children[i]->getHeight(); + int childHeightWidth = childHeight->getWidth(); + int childHeightHeight = childHeight->getContents().size() / childHeightWidth; + if (childHeightWidth != heightWidth || childHeightHeight != heightHeight) { + qWarning() << "Height dimension mismatch [heightWidth=" << heightWidth << ", heightHeight=" << heightHeight << + ", childHeightWidth=" << childHeightWidth << ", childHeightHeight=" << childHeightHeight << "]"; + continue; + } + int innerHeightWidth = heightWidth - HeightfieldHeight::HEIGHT_EXTENSION; + int innerHeightHeight = heightHeight - HeightfieldHeight::HEIGHT_EXTENSION; + int innerQuadrantHeightWidth = innerHeightWidth / 2; + int innerQuadrantHeightHeight = innerHeightHeight / 2; + int quadrantHeightWidth = innerQuadrantHeightWidth + HeightfieldHeight::HEIGHT_EXTENSION - 1; + int quadrantHeightHeight = innerQuadrantHeightHeight + HeightfieldHeight::HEIGHT_EXTENSION - 1; + quint16* dest = heightContents.data() + (i & Y_MAXIMUM_FLAG ? (innerQuadrantHeightHeight + 1) * heightWidth : 0) + + (i & X_MAXIMUM_FLAG ? innerQuadrantHeightWidth + 1 : 0); + const quint16* src = childHeight->getContents().constData(); + for (int z = 0; z < quadrantHeightHeight; z++, dest += heightWidth, src += heightWidth * 2) { + const quint16* lineSrc = src; + for (quint16* lineDest = dest, *end = dest + quadrantHeightWidth; lineDest != end; lineDest++, lineSrc += 2) { + *lineDest = *lineSrc; + } + } + } + _height = new HeightfieldHeight(heightWidth, heightContents); + + } else { + _height.reset(); + } + if (colorWidth > 0) { + QByteArray colorContents(colorWidth * colorHeight * DataBlock::COLOR_BYTES, 0); + for (int i = 0; i < CHILD_COUNT; i++) { + HeightfieldColorPointer childColor = _children[i]->getColor(); + int childColorWidth = childColor->getWidth(); + int childColorHeight = childColor->getContents().size() / (childColorWidth * DataBlock::COLOR_BYTES); + if (childColorWidth != colorWidth || childColorHeight != colorHeight) { + qWarning() << "Color dimension mismatch [colorWidth=" << colorWidth << ", colorHeight=" << colorHeight << + ", childColorWidth=" << childColorWidth << ", childColorHeight=" << childColorHeight << "]"; + continue; + } + int innerColorWidth = colorWidth - HeightfieldData::SHARED_EDGE; + int innerColorHeight = colorHeight - HeightfieldData::SHARED_EDGE; + int innerQuadrantColorWidth = innerColorWidth / 2; + int innerQuadrantColorHeight = innerColorHeight / 2; + int quadrantColorWidth = innerQuadrantColorWidth + HeightfieldData::SHARED_EDGE; + int quadrantColorHeight = innerQuadrantColorHeight + HeightfieldData::SHARED_EDGE; + char* dest = colorContents.data() + ((i & Y_MAXIMUM_FLAG ? innerQuadrantColorHeight * colorWidth : 0) + + (i & X_MAXIMUM_FLAG ? innerQuadrantColorWidth : 0)) * DataBlock::COLOR_BYTES; + const char* src = childColor->getContents().constData(); + for (int z = 0; z < quadrantColorHeight; z++, dest += colorWidth * DataBlock::COLOR_BYTES, + src += colorWidth * DataBlock::COLOR_BYTES * 2) { + const char* lineSrc = src; + for (char* lineDest = dest, *end = dest + quadrantColorWidth * DataBlock::COLOR_BYTES; + lineDest != end; lineDest += DataBlock::COLOR_BYTES, lineSrc += DataBlock::COLOR_BYTES * 2) { + lineDest[0] = lineSrc[0]; + lineDest[1] = lineSrc[1]; + lineDest[2] = lineSrc[2]; + } + } + } + _color = new HeightfieldColor(colorWidth, colorContents); + + } else { + _color.reset(); + } + if (materialWidth > 0) { + QByteArray materialContents(materialWidth * materialHeight, 0); + QVector materials; + for (int i = 0; i < CHILD_COUNT; i++) { + HeightfieldMaterialPointer childMaterial = _children[i]->getMaterial(); + int childMaterialWidth = childMaterial->getWidth(); + int childMaterialHeight = childMaterial->getContents().size() / childMaterialWidth; + if (childMaterialWidth != materialWidth || childMaterialHeight != materialHeight) { + qWarning() << "Material dimension mismatch [materialWidth=" << materialWidth << ", materialHeight=" << + materialHeight << ", childMaterialWidth=" << childMaterialWidth << ", childMaterialHeight=" << + childMaterialHeight << "]"; + continue; + } + int innerMaterialWidth = materialWidth - HeightfieldData::SHARED_EDGE; + int innerMaterialHeight = materialHeight - HeightfieldData::SHARED_EDGE; + int innerQuadrantMaterialWidth = innerMaterialWidth / 2; + int innerQuadrantMaterialHeight = innerMaterialHeight / 2; + int quadrantMaterialWidth = innerQuadrantMaterialWidth + HeightfieldData::SHARED_EDGE; + int quadrantMaterialHeight = innerQuadrantMaterialHeight + HeightfieldData::SHARED_EDGE; + uchar* dest = (uchar*)materialContents.data() + + (i & Y_MAXIMUM_FLAG ? innerQuadrantMaterialHeight * materialWidth : 0) + + (i & X_MAXIMUM_FLAG ? innerQuadrantMaterialWidth : 0); + const uchar* src = (const uchar*)childMaterial->getContents().constData(); + QHash materialMap; + for (int z = 0; z < quadrantMaterialHeight; z++, dest += materialWidth, src += materialWidth * 2) { + const uchar* lineSrc = src; + for (uchar* lineDest = dest, *end = dest + quadrantMaterialWidth; lineDest != end; lineDest++, lineSrc += 2) { + int value = *lineSrc; + if (value != 0) { + int& mapping = materialMap[value]; + if (mapping == 0) { + mapping = getMaterialIndex(childMaterial->getMaterials().at(value - 1), + materials, materialContents); + } + value = mapping; + } + *lineDest = value; + } + } + } + _material = new HeightfieldMaterial(materialWidth, materialContents, materials); + + } else { + _material.reset(); + } } Heightfield::Heightfield() : From ff4d28abebb34dfda671506f5d70ea21025fc867 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 25 Nov 2014 18:27:49 -0800 Subject: [PATCH 087/502] hack a separate emissive information in the g-buffer --- interface/resources/shaders/directional_light.frag | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/resources/shaders/directional_light.frag b/interface/resources/shaders/directional_light.frag index d4a6f5a28b..906a33ea74 100644 --- a/interface/resources/shaders/directional_light.frag +++ b/interface/resources/shaders/directional_light.frag @@ -47,10 +47,10 @@ void main(void) { // get the normal from the map vec4 normal = normalVal; - if (normalVal.a == 0.5) { + if ((normalVal.a >= 0.45) && (normalVal.a <= 0.55)) { normal.a = 1.0; normalVal.a = 0.0; - gl_FragColor = vec4(diffuseVal.rgb * specularColor.rgb, normal.a); + gl_FragColor = vec4(diffuseVal.rgb * specularVal.rgb, 1.0); } else { vec3 normalizedNormal = normalize(normal.xyz * 2.0 - vec3(1.0)); From f6a6e185cfae5691c4300b8101d644cdae1d4eb2 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 25 Nov 2014 18:53:27 -0800 Subject: [PATCH 088/502] Heightfield import simplifications. --- interface/src/ui/MetavoxelEditor.cpp | 37 ++++++++++------------------ interface/src/ui/MetavoxelEditor.h | 4 +-- 2 files changed, 14 insertions(+), 27 deletions(-) diff --git a/interface/src/ui/MetavoxelEditor.cpp b/interface/src/ui/MetavoxelEditor.cpp index cf28a79995..65faa938e2 100644 --- a/interface/src/ui/MetavoxelEditor.cpp +++ b/interface/src/ui/MetavoxelEditor.cpp @@ -732,11 +732,11 @@ HeightfieldTool::HeightfieldTool(MetavoxelEditor* editor, const QString& name) : layout()->addWidget(widget); _form->addRow("Translation:", _translation = new Vec3Editor(widget)); - _form->addRow("Scale:", _scale = new QDoubleSpinBox()); - _scale->setMinimum(-FLT_MAX); - _scale->setMaximum(FLT_MAX); - _scale->setPrefix("2^"); - _scale->setValue(2.0); + _form->addRow("Spacing:", _spacing = new QDoubleSpinBox()); + _spacing->setMaximum(FLT_MAX); + _spacing->setDecimals(3); + _spacing->setSingleStep(0.001); + _spacing->setValue(1.0); QPushButton* applyButton = new QPushButton("Apply"); layout()->addWidget(applyButton); @@ -747,28 +747,20 @@ bool HeightfieldTool::appliesTo(const AttributePointer& attribute) const { return attribute->inherits("SpannerSetAttribute"); } -void HeightfieldTool::render() { - float scale = pow(2.0, _scale->value()); - _translation->setSingleStep(scale); - glm::vec3 quantizedTranslation = scale * glm::floor(_translation->getValue() / scale); - _translation->setValue(quantizedTranslation); -} - ImportHeightfieldTool::ImportHeightfieldTool(MetavoxelEditor* editor) : HeightfieldTool(editor, "Import Heightfield"), _spanner(new Heightfield()) { _form->addRow("Height Scale:", _heightScale = new QDoubleSpinBox()); - const double MAX_OFFSET_SCALE = 100000.0; - _heightScale->setMaximum(MAX_OFFSET_SCALE); + _heightScale->setMaximum(FLT_MAX); _heightScale->setSingleStep(0.01); - _heightScale->setValue(8.0); + _heightScale->setValue(16.0); connect(_heightScale, static_cast(&QDoubleSpinBox::valueChanged), this, &ImportHeightfieldTool::updateSpanner); _form->addRow("Height Offset:", _heightOffset = new QDoubleSpinBox()); - _heightOffset->setMinimum(-MAX_OFFSET_SCALE); - _heightOffset->setMaximum(MAX_OFFSET_SCALE); + _heightOffset->setMinimum(-FLT_MAX); + _heightOffset->setMaximum(FLT_MAX); _heightOffset->setSingleStep(0.01); connect(_heightOffset, static_cast(&QDoubleSpinBox::valueChanged), this, &ImportHeightfieldTool::updateSpanner); @@ -780,7 +772,7 @@ ImportHeightfieldTool::ImportHeightfieldTool(MetavoxelEditor* editor) : connect(_color, &HeightfieldColorEditor::colorChanged, this, &ImportHeightfieldTool::updateSpanner); connect(_translation, &Vec3Editor::valueChanged, this, &ImportHeightfieldTool::updateSpanner); - connect(_scale, static_cast(&QDoubleSpinBox::valueChanged), this, + connect(_spacing, static_cast(&QDoubleSpinBox::valueChanged), this, &ImportHeightfieldTool::updateSpanner); } @@ -801,22 +793,19 @@ void ImportHeightfieldTool::apply() { Application::getInstance()->getMetavoxels()->applyEdit(message, true); } -const int HEIGHTFIELD_BLOCK_SIZE = 256; - void ImportHeightfieldTool::updateSpanner() { Heightfield* heightfield = static_cast(_spanner.data()); heightfield->setHeight(_height->getHeight()); heightfield->setColor(_color->getColor()); - float scale = pow(2.0, _scale->value()); + float scale = 1.0f; float aspectZ = 1.0f; if (_height->getHeight()) { int width = _height->getHeight()->getWidth(); int innerWidth = width - HeightfieldHeight::HEIGHT_EXTENSION; int innerHeight = _height->getHeight()->getContents().size() / width - HeightfieldHeight::HEIGHT_EXTENSION; - float widthBlocks = glm::ceil((float)innerWidth / HEIGHTFIELD_BLOCK_SIZE); - scale *= widthBlocks; - aspectZ = glm::ceil((float)innerHeight / HEIGHTFIELD_BLOCK_SIZE) / widthBlocks; + scale = innerWidth * _spacing->value(); + aspectZ = (float)innerHeight / innerWidth; } heightfield->setScale(scale); heightfield->setAspectY(_heightScale->value() / scale); diff --git a/interface/src/ui/MetavoxelEditor.h b/interface/src/ui/MetavoxelEditor.h index cccb41ecfc..4e870a9982 100644 --- a/interface/src/ui/MetavoxelEditor.h +++ b/interface/src/ui/MetavoxelEditor.h @@ -260,8 +260,6 @@ public: virtual bool appliesTo(const AttributePointer& attribute) const; - virtual void render(); - protected slots: virtual void apply() = 0; @@ -270,7 +268,7 @@ protected: QFormLayout* _form; Vec3Editor* _translation; - QDoubleSpinBox* _scale; + QDoubleSpinBox* _spacing; }; /// Allows importing a heightfield. From f111fb2c4b0211a8151356b0ee5d3988dafbaa67 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 25 Nov 2014 20:36:39 -0800 Subject: [PATCH 089/502] added a comment to clarify why getCameraOrientation has an oculus special case --- interface/src/avatar/Head.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index e237d0ae6b..9f59fb38b7 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -273,7 +273,8 @@ void Head::setCorrectedLookAtPosition(glm::vec3 correctedLookAtPosition) { _correctedLookAtPosition = correctedLookAtPosition; } -glm::quat Head::getCameraOrientation () const { +glm::quat Head::getCameraOrientation() const { + // this is used to support driving toward where you're head is looking if (OculusManager::isConnected()) { return getOrientation(); } From e94db7bbc2b12010dfa31e9d0da5b4de603d4d53 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 25 Nov 2014 20:37:13 -0800 Subject: [PATCH 090/502] removed some debug, added a resetSensors() on exit of HMD mode --- interface/src/ui/HMDToolsDialog.cpp | 23 +---------------------- 1 file changed, 1 insertion(+), 22 deletions(-) diff --git a/interface/src/ui/HMDToolsDialog.cpp b/interface/src/ui/HMDToolsDialog.cpp index 4f4c624065..1e251248c3 100644 --- a/interface/src/ui/HMDToolsDialog.cpp +++ b/interface/src/ui/HMDToolsDialog.cpp @@ -59,32 +59,17 @@ HMDToolsDialog::~HMDToolsDialog() { } void HMDToolsDialog::enterModeClicked(bool checked) { - qDebug() << "enterModeClicked"; - int hmdScreen = OculusManager::getHMDScreen(); - // hack to test... - if (hmdScreen == -1) { - hmdScreen = 0; - } - if (hmdScreen >= 0) { QWindow* mainWindow = Application::getInstance()->getWindow()->windowHandle(); _hmdScreen = QGuiApplication::screens()[hmdScreen]; _previousRect = Application::getInstance()->getWindow()->rect(); - qDebug() << "_previousRect:" << _previousRect; _previousRect = QRect(mainWindow->mapToGlobal(_previousRect.topLeft()), mainWindow->mapToGlobal(_previousRect.bottomRight())); - qDebug() << "after mapping... _previousRect:" << _previousRect; - _previousScreen = mainWindow->screen(); - qDebug() << "_previousScreen:" << _previousScreen; - QRect rect = QApplication::desktop()->screenGeometry(hmdScreen); - - qDebug() << "about to move to:" << rect.topLeft(); - mainWindow->setScreen(_hmdScreen); mainWindow->setGeometry(rect); @@ -98,20 +83,14 @@ void HMDToolsDialog::enterModeClicked(bool checked) { } void HMDToolsDialog::activateWindowAfterEnterMode() { - qDebug() << "activateWindowAfterEnterMode"; Application::getInstance()->getWindow()->activateWindow(); - QWindow* mainWindow = Application::getInstance()->getWindow()->windowHandle(); QPoint windowCenter = mainWindow->geometry().center(); - //QPoint desktopCenter = mainWindow->mapToGlobal(windowCenter); - qDebug() << "windowCenter:" << windowCenter; QCursor::setPos(_hmdScreen, windowCenter); } void HMDToolsDialog::leaveModeClicked(bool checked) { - qDebug() << "leaveModeClicked"; - Application::getInstance()->setFullscreen(false); Application::getInstance()->setEnableVRMode(false); Application::getInstance()->getWindow()->activateWindow(); @@ -128,11 +107,11 @@ void HMDToolsDialog::leaveModeClicked(bool checked) { } void HMDToolsDialog::moveWindowAfterLeaveMode() { - qDebug() << "moveWindowAfterLeaveMode"; QWindow* mainWindow = Application::getInstance()->getWindow()->windowHandle(); mainWindow->setScreen(_previousScreen); mainWindow->setGeometry(_previousRect); Application::getInstance()->getWindow()->activateWindow(); + Application::getInstance()->resetSensors(); } From 53ecf97df2d25a58c502b78c856f5eb849941c64 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 25 Nov 2014 21:58:26 -0800 Subject: [PATCH 091/502] fix broken camera after leaving oculus/hmd mode --- interface/src/Application.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 31b1dd66f6..1a7ccf21ee 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -668,6 +668,8 @@ void Application::paintGL() { // Update camera position if (!OculusManager::isConnected()) { + _myCamera.setHmdPosition(glm::vec3()); + _myCamera.setHmdRotation(glm::quat()); _myCamera.update(1.0f / _fps); } From ee46c781c46ed56313656e7fc8a328a1935d2997 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 26 Nov 2014 08:40:11 -0800 Subject: [PATCH 092/502] expand comment --- interface/src/avatar/Head.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index 9f59fb38b7..660ebfcbb3 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -274,7 +274,11 @@ void Head::setCorrectedLookAtPosition(glm::vec3 correctedLookAtPosition) { } glm::quat Head::getCameraOrientation() const { - // this is used to support driving toward where you're head is looking + // NOTE: Head::getCameraOrientation() is not used for orienting the camera "view" while in Oculus mode, so + // you may wonder why this code is here. This method will be called while in Oculus mode to determine how + // to change the driving direction while in Oculus mode. It is used to support driving toward where you're + // head is looking. Note that in oculus mode, your actual camera view and where your head is looking is not + // always the same. if (OculusManager::isConnected()) { return getOrientation(); } From 821cf46ee99b11545d56a0f83560f0e6d057c1f5 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 26 Nov 2014 09:11:26 -0800 Subject: [PATCH 093/502] don't delete the HMDToolsDialog on hide, keep it around till app exit. --- interface/src/Menu.cpp | 12 +++++++----- interface/src/ui/HMDToolsDialog.cpp | 3 +++ 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index ac93a71bc0..2c7b4a9efd 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -659,6 +659,10 @@ Menu::Menu() : Menu::~Menu() { bandwidthDetailsClosed(); octreeStatsDetailsClosed(); + if (_hmdToolsDialog) { + delete _hmdToolsDialog; + _hmdToolsDialog = NULL; + } } void Menu::loadSettings(QSettings* settings) { @@ -1606,8 +1610,8 @@ void Menu::hmdTools(bool showTools) { if (!_hmdToolsDialog) { _hmdToolsDialog = new HMDToolsDialog(Application::getInstance()->getGLWidget()); connect(_hmdToolsDialog, SIGNAL(closed()), SLOT(hmdToolsClosed())); - _hmdToolsDialog->show(); } + _hmdToolsDialog->show(); _hmdToolsDialog->raise(); } else { hmdToolsClosed(); @@ -1616,10 +1620,8 @@ void Menu::hmdTools(bool showTools) { } void Menu::hmdToolsClosed() { - if (_hmdToolsDialog) { - delete _hmdToolsDialog; - _hmdToolsDialog = NULL; - } + Menu::getInstance()->getActionForOption(MenuOption::HMDTools)->setChecked(false); + _hmdToolsDialog->hide(); } void Menu::cycleFrustumRenderMode() { diff --git a/interface/src/ui/HMDToolsDialog.cpp b/interface/src/ui/HMDToolsDialog.cpp index 1e251248c3..3cbbb5daf2 100644 --- a/interface/src/ui/HMDToolsDialog.cpp +++ b/interface/src/ui/HMDToolsDialog.cpp @@ -123,6 +123,9 @@ void HMDToolsDialog::reject() { void HMDToolsDialog::closeEvent(QCloseEvent* event) { this->QDialog::closeEvent(event); emit closed(); + + // TODO: consider if we want to prevent closing of this window + //event->ignore(); } From 59eeeb90067462a0fbd94976de15fab2f4034c51 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 26 Nov 2014 10:11:29 -0800 Subject: [PATCH 094/502] add debug details to HMDTools --- interface/src/ui/HMDToolsDialog.cpp | 43 ++++++++++++++++++++++++++--- interface/src/ui/HMDToolsDialog.h | 4 +++ 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/interface/src/ui/HMDToolsDialog.cpp b/interface/src/ui/HMDToolsDialog.cpp index 3cbbb5daf2..80fb6a93d6 100644 --- a/interface/src/ui/HMDToolsDialog.cpp +++ b/interface/src/ui/HMDToolsDialog.cpp @@ -44,20 +44,52 @@ HMDToolsDialog::HMDToolsDialog(QWidget* parent) : form->addRow("", leaveModeButton); connect(leaveModeButton,SIGNAL(clicked(bool)),this,SLOT(leaveModeClicked(bool))); + // Create a label with debug details... + _debugDetails = new QLabel(); + _debugDetails->setText(getDebugDetails()); + const int WIDTH = 350; + const int HEIGHT = 100; + _debugDetails->setFixedSize(WIDTH, HEIGHT); + form->addRow("", _debugDetails); + this->QDialog::setLayout(form); - _wasMoved = false; - _previousRect = Application::getInstance()->getWindow()->rect(); - - Application::getInstance()->getWindow()->activateWindow(); + + QWindow* mainWindow = Application::getInstance()->getWindow()->windowHandle(); + connect(mainWindow, &QWindow::screenChanged, this, &HMDToolsDialog::applicationWindowScreenChanged); } HMDToolsDialog::~HMDToolsDialog() { } +void HMDToolsDialog::applicationWindowScreenChanged(QScreen* screen) { + _debugDetails->setText(getDebugDetails()); +} + +QString HMDToolsDialog::getDebugDetails() const { + QString results; + + int hmdScreenNumber = OculusManager::getHMDScreen(); + if (hmdScreenNumber > 0) { + results += "HMD Screen: " + QGuiApplication::screens()[hmdScreenNumber]->name() + "\n"; + } else { + results += "HMD Screen Name: Unknown\n"; + } + + int desktopPrimaryScreenNumber = QApplication::desktop()->primaryScreen(); + QScreen* desktopPrimaryScreen = QGuiApplication::screens()[desktopPrimaryScreenNumber]; + results += "Desktop's Primary Screen: " + desktopPrimaryScreen->name() + "\n"; + + results += "Application Primary Screen: " + QGuiApplication::primaryScreen()->name() + "\n"; + QScreen* mainWindowScreen = Application::getInstance()->getWindow()->windowHandle()->screen(); + results += "Application Main Window Screen: " + mainWindowScreen->name() + "\n"; + + return results; +} + void HMDToolsDialog::enterModeClicked(bool checked) { int hmdScreen = OculusManager::getHMDScreen(); @@ -74,6 +106,9 @@ void HMDToolsDialog::enterModeClicked(bool checked) { mainWindow->setGeometry(rect); _wasMoved = true; + } else { + // if we're on a single screen setup, then hide our tools window when entering HMD mode + hide(); } Application::getInstance()->setFullscreen(true); Application::getInstance()->setEnableVRMode(true); diff --git a/interface/src/ui/HMDToolsDialog.h b/interface/src/ui/HMDToolsDialog.h index 9620a0529d..c2a36f5a30 100644 --- a/interface/src/ui/HMDToolsDialog.h +++ b/interface/src/ui/HMDToolsDialog.h @@ -20,6 +20,8 @@ public: // Sets up the UI HMDToolsDialog(QWidget* parent); ~HMDToolsDialog(); + + QString getDebugDetails() const; signals: void closed(); @@ -30,6 +32,7 @@ public slots: void leaveModeClicked(bool checked); void activateWindowAfterEnterMode(); void moveWindowAfterLeaveMode(); + void applicationWindowScreenChanged(QScreen* screen); protected: // Emits a 'closed' signal when this dialog is closed. @@ -40,6 +43,7 @@ private: QRect _previousRect; QScreen* _previousScreen; QScreen* _hmdScreen; + QLabel* _debugDetails; }; #endif // hifi_HMDToolsDialog_h From c58061792198f2693578edb456ba2e45b9b38776 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 26 Nov 2014 10:23:44 -0800 Subject: [PATCH 095/502] better mirrored monitor support --- interface/src/ui/HMDToolsDialog.cpp | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/interface/src/ui/HMDToolsDialog.cpp b/interface/src/ui/HMDToolsDialog.cpp index 80fb6a93d6..70d5d836fc 100644 --- a/interface/src/ui/HMDToolsDialog.cpp +++ b/interface/src/ui/HMDToolsDialog.cpp @@ -73,7 +73,7 @@ QString HMDToolsDialog::getDebugDetails() const { QString results; int hmdScreenNumber = OculusManager::getHMDScreen(); - if (hmdScreenNumber > 0) { + if (hmdScreenNumber >= 0) { results += "HMD Screen: " + QGuiApplication::screens()[hmdScreenNumber]->name() + "\n"; } else { results += "HMD Screen Name: Unknown\n"; @@ -91,7 +91,10 @@ QString HMDToolsDialog::getDebugDetails() const { } void HMDToolsDialog::enterModeClicked(bool checked) { + _debugDetails->setText(getDebugDetails()); + int hmdScreen = OculusManager::getHMDScreen(); + qDebug() << "enterModeClicked().... hmdScreen:" << hmdScreen; if (hmdScreen >= 0) { QWindow* mainWindow = Application::getInstance()->getWindow()->windowHandle(); @@ -106,10 +109,14 @@ void HMDToolsDialog::enterModeClicked(bool checked) { mainWindow->setGeometry(rect); _wasMoved = true; - } else { - // if we're on a single screen setup, then hide our tools window when entering HMD mode - hide(); } + + + // if we're on a single screen setup, then hide our tools window when entering HMD mode + if (QApplication::desktop()->screenCount() == 1) { + close(); + } + Application::getInstance()->setFullscreen(true); Application::getInstance()->setEnableVRMode(true); @@ -126,6 +133,8 @@ void HMDToolsDialog::activateWindowAfterEnterMode() { void HMDToolsDialog::leaveModeClicked(bool checked) { + _debugDetails->setText(getDebugDetails()); + Application::getInstance()->setFullscreen(false); Application::getInstance()->setEnableVRMode(false); Application::getInstance()->getWindow()->activateWindow(); @@ -152,15 +161,13 @@ void HMDToolsDialog::moveWindowAfterLeaveMode() { void HMDToolsDialog::reject() { // Just regularly close upon ESC - this->QDialog::close(); + close(); } void HMDToolsDialog::closeEvent(QCloseEvent* event) { + // TODO: consider if we want to prevent closing of this window with event->ignore(); this->QDialog::closeEvent(event); emit closed(); - - // TODO: consider if we want to prevent closing of this window - //event->ignore(); } From 3262c9a8bd60d9a7012d6a69c3be14938c8ef683 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 26 Nov 2014 10:27:03 -0800 Subject: [PATCH 096/502] don't lookup entity when deleting script --- interface/external/gverb/readme.txt | 2 +- interface/src/entities/EntityTreeRenderer.cpp | 18 +++++------------- interface/src/entities/EntityTreeRenderer.h | 1 - 3 files changed, 6 insertions(+), 15 deletions(-) diff --git a/interface/external/gverb/readme.txt b/interface/external/gverb/readme.txt index 1a85659b91..aa2fe8a602 100644 --- a/interface/external/gverb/readme.txt +++ b/interface/external/gverb/readme.txt @@ -1,7 +1,7 @@ Instructions for adding the Gverb library to Interface (This is a required library) -Clément Brisset, October 22nd, 2014 +Clément Brisset, Octobre 22nd, 2014 1. Go to https://github.com/highfidelity/gverb Or download the sources directly via this link: diff --git a/interface/src/entities/EntityTreeRenderer.cpp b/interface/src/entities/EntityTreeRenderer.cpp index 192b42c58b..5aacd36a12 100644 --- a/interface/src/entities/EntityTreeRenderer.cpp +++ b/interface/src/entities/EntityTreeRenderer.cpp @@ -195,22 +195,14 @@ QScriptValue EntityTreeRenderer::loadEntityScript(EntityItem* entity) { return entityScriptObject; // newly constructed } -QScriptValue EntityTreeRenderer::getPreviouslyLoadedEntityScript(const EntityItemID& entityItemID) { - EntityItem* entity = static_cast(_tree)->findEntityByEntityItemID(entityItemID); - return getPreviouslyLoadedEntityScript(entity); -} - - -QScriptValue EntityTreeRenderer::getPreviouslyLoadedEntityScript(EntityItem* entity) { - if (entity) { - EntityItemID entityID = entity->getEntityItemID(); - if (_entityScripts.contains(entityID)) { - EntityScriptDetails details = _entityScripts[entityID]; - return details.scriptObject; // previously loaded - } +QScriptValue EntityTreeRenderer::getPreviouslyLoadedEntityScript(const EntityItemID& entityID) { + if (_entityScripts.contains(entityID)) { + EntityScriptDetails details = _entityScripts[entityID]; + return details.scriptObject; // previously loaded } return QScriptValue(); // no script } + void EntityTreeRenderer::setTree(Octree* newTree) { OctreeRenderer::setTree(newTree); static_cast(_tree)->setFBXService(this); diff --git a/interface/src/entities/EntityTreeRenderer.h b/interface/src/entities/EntityTreeRenderer.h index e5eba79e0d..9f06011d30 100644 --- a/interface/src/entities/EntityTreeRenderer.h +++ b/interface/src/entities/EntityTreeRenderer.h @@ -131,7 +131,6 @@ private: QScriptValue loadEntityScript(EntityItem* entity); QScriptValue loadEntityScript(const EntityItemID& entityItemID); QScriptValue getPreviouslyLoadedEntityScript(const EntityItemID& entityItemID); - QScriptValue getPreviouslyLoadedEntityScript(EntityItem* entity); QString loadScriptContents(const QString& scriptMaybeURLorText); QScriptValueList createMouseEventArgs(const EntityItemID& entityID, QMouseEvent* event, unsigned int deviceID); QScriptValueList createMouseEventArgs(const EntityItemID& entityID, const MouseEvent& mouseEvent); From 419e00cbdc6dc1c9f2225ed8aced45c1841a82c4 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 26 Nov 2014 10:41:23 -0800 Subject: [PATCH 097/502] fix typo from overwrite of gverb/readme.txt --- interface/external/gverb/readme.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/external/gverb/readme.txt b/interface/external/gverb/readme.txt index aa2fe8a602..2f8991b1d4 100644 --- a/interface/external/gverb/readme.txt +++ b/interface/external/gverb/readme.txt @@ -1,7 +1,7 @@ Instructions for adding the Gverb library to Interface (This is a required library) -Clément Brisset, Octobre 22nd, 2014 +Clément Brisset, October 22nd, 2014 1. Go to https://github.com/highfidelity/gverb Or download the sources directly via this link: @@ -12,4 +12,4 @@ Clément Brisset, Octobre 22nd, 2014 3. Place the directories “include” and “src” in interface/external/gverb (Normally next to this readme) -4. Clear your build directory, run cmake, build and you should be all set. \ No newline at end of file +4. Clear your build directory, run cmake, build and you should be all set. From ad6680553c643bbb9f7d2b9d3c53127e09667e9a Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 26 Nov 2014 10:46:47 -0800 Subject: [PATCH 098/502] snap cursor to center of HMD tools dialog when shown, or app when the dialog is hidden --- interface/src/ui/HMDToolsDialog.cpp | 15 +++++++++++++++ interface/src/ui/HMDToolsDialog.h | 7 +++++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/interface/src/ui/HMDToolsDialog.cpp b/interface/src/ui/HMDToolsDialog.cpp index 70d5d836fc..141b0d61ad 100644 --- a/interface/src/ui/HMDToolsDialog.cpp +++ b/interface/src/ui/HMDToolsDialog.cpp @@ -170,4 +170,19 @@ void HMDToolsDialog::closeEvent(QCloseEvent* event) { emit closed(); } +void HMDToolsDialog::centerCursorOnWidget(QWidget* widget) { + QWindow* window = widget->windowHandle(); + QScreen* screen = window->screen(); + QPoint windowCenter = window->geometry().center(); + QCursor::setPos(screen, windowCenter); +} + +void HMDToolsDialog::showEvent(QShowEvent* event) { + centerCursorOnWidget(this); +} + +void HMDToolsDialog::hideEvent(QHideEvent* event) { + centerCursorOnWidget(Application::getInstance()->getWindow()); +} + diff --git a/interface/src/ui/HMDToolsDialog.h b/interface/src/ui/HMDToolsDialog.h index c2a36f5a30..f1a5f582cd 100644 --- a/interface/src/ui/HMDToolsDialog.h +++ b/interface/src/ui/HMDToolsDialog.h @@ -35,10 +35,13 @@ public slots: void applicationWindowScreenChanged(QScreen* screen); protected: - // Emits a 'closed' signal when this dialog is closed. - void closeEvent(QCloseEvent*); + virtual void closeEvent(QCloseEvent*); // Emits a 'closed' signal when this dialog is closed. + virtual void showEvent(QShowEvent* event); + virtual void hideEvent(QHideEvent* event); private: + void centerCursorOnWidget(QWidget* widget); + bool _wasMoved; QRect _previousRect; QScreen* _previousScreen; From 0c5a97841185dd5db6728116db07f86c96a84a89 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 26 Nov 2014 10:53:38 -0800 Subject: [PATCH 099/502] fix crash in activateWindowAfterEnterMode in no oculus case --- interface/src/ui/HMDToolsDialog.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/interface/src/ui/HMDToolsDialog.cpp b/interface/src/ui/HMDToolsDialog.cpp index 141b0d61ad..9a409b17f1 100644 --- a/interface/src/ui/HMDToolsDialog.cpp +++ b/interface/src/ui/HMDToolsDialog.cpp @@ -126,9 +126,9 @@ void HMDToolsDialog::enterModeClicked(bool checked) { void HMDToolsDialog::activateWindowAfterEnterMode() { Application::getInstance()->getWindow()->activateWindow(); - QWindow* mainWindow = Application::getInstance()->getWindow()->windowHandle(); - QPoint windowCenter = mainWindow->geometry().center(); - QCursor::setPos(_hmdScreen, windowCenter); + + // center the cursor on the main application window + centerCursorOnWidget(Application::getInstance()->getWindow()); } @@ -178,10 +178,12 @@ void HMDToolsDialog::centerCursorOnWidget(QWidget* widget) { } void HMDToolsDialog::showEvent(QShowEvent* event) { + // center the cursor on the hmd tools dialog centerCursorOnWidget(this); } void HMDToolsDialog::hideEvent(QHideEvent* event) { + // center the cursor on the main application window centerCursorOnWidget(Application::getInstance()->getWindow()); } From 5f58c76842879b8b15e6f8c3a317a45b82c82df1 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 26 Nov 2014 12:03:10 -0800 Subject: [PATCH 100/502] Fix hands being put in face if Leap on HMD is set but Leap not connected The joints were reporting themselves as "active" even though the Leap wasn't connected, both at startup if not connected and after unplugging. --- interface/src/devices/Leapmotion.cpp | 18 +++++++++++------- interface/src/devices/MotionTracker.cpp | 4 ++-- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/interface/src/devices/Leapmotion.cpp b/interface/src/devices/Leapmotion.cpp index 62037ae7f6..6a47eadb96 100644 --- a/interface/src/devices/Leapmotion.cpp +++ b/interface/src/devices/Leapmotion.cpp @@ -135,16 +135,20 @@ glm::vec3 vec3FromLeapVector(const Leap::Vector& vec) { void Leapmotion::update() { #ifdef HAVE_LEAPMOTION - // Check that the controller is actually active + bool wasActive = _active; _active = _controller.isConnected(); - if (!_active) { - return; + + if (_active || wasActive) { + // Go through all the joints and increment their counter since last update. + // Increment all counters once after controller first becomes inactive so that each joint reports itself as inactive. + // TODO C++11 for (auto jointIt = _jointsArray.begin(); jointIt != _jointsArray.end(); jointIt++) { + for (JointTracker::Vector::iterator jointIt = _jointsArray.begin(); jointIt != _jointsArray.end(); jointIt++) { + (*jointIt).tickNewFrame(); + } } - // go through all the joints and increment their counter since last update - // TODO C++11 for (auto jointIt = _jointsArray.begin(); jointIt != _jointsArray.end(); jointIt++) { - for (JointTracker::Vector::iterator jointIt = _jointsArray.begin(); jointIt != _jointsArray.end(); jointIt++) { - (*jointIt).tickNewFrame(); + if (!_active) { + return; } // Get the most recent frame and report some basic information diff --git a/interface/src/devices/MotionTracker.cpp b/interface/src/devices/MotionTracker.cpp index 6b81c94f82..d5272888e7 100644 --- a/interface/src/devices/MotionTracker.cpp +++ b/interface/src/devices/MotionTracker.cpp @@ -119,14 +119,14 @@ MotionTracker::JointTracker::JointTracker() : _absFrame(), _semantic(""), _parent(INVALID_PARENT), - _lastUpdate(0) + _lastUpdate(1) // Joint inactive { } MotionTracker::JointTracker::JointTracker(const Semantic& semantic, Index parent) : _semantic(semantic), _parent(parent), - _lastUpdate(0) + _lastUpdate(1) // Joint inactive { } From 5871ecd85cc72997d17f16a08aab9ea600af2b12 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 26 Nov 2014 12:03:27 -0800 Subject: [PATCH 101/502] Stop incrementing counter after limit reached --- examples/leapHands.js | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/examples/leapHands.js b/examples/leapHands.js index 04253c8ab6..6bdca051be 100644 --- a/examples/leapHands.js +++ b/examples/leapHands.js @@ -471,17 +471,20 @@ var leapHands = (function () { } else { - hands[h].inactiveCount += 1; + if (hands[h].inactiveCount < MAX_HAND_INACTIVE_COUNT) { - if (hands[h].inactiveCount === MAX_HAND_INACTIVE_COUNT) { - if (h === 0) { - MyAvatar.clearJointData("LeftHand"); - MyAvatar.clearJointData("LeftForeArm"); - MyAvatar.clearJointData("LeftArm"); - } else { - MyAvatar.clearJointData("RightHand"); - MyAvatar.clearJointData("RightForeArm"); - MyAvatar.clearJointData("RightArm"); + hands[h].inactiveCount += 1; + + if (hands[h].inactiveCount === MAX_HAND_INACTIVE_COUNT) { + if (h === 0) { + MyAvatar.clearJointData("LeftHand"); + MyAvatar.clearJointData("LeftForeArm"); + MyAvatar.clearJointData("LeftArm"); + } else { + MyAvatar.clearJointData("RightHand"); + MyAvatar.clearJointData("RightForeArm"); + MyAvatar.clearJointData("RightArm"); + } } } } From 208eb663bddb8a8bda402263a72a24fd7dba6202 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 26 Nov 2014 12:07:39 -0800 Subject: [PATCH 102/502] prevent HMD tools from being moved to HMD screen --- interface/src/ui/HMDToolsDialog.cpp | 70 ++++++++++++++++++++++++++++- interface/src/ui/HMDToolsDialog.h | 5 +++ 2 files changed, 74 insertions(+), 1 deletion(-) diff --git a/interface/src/ui/HMDToolsDialog.cpp b/interface/src/ui/HMDToolsDialog.cpp index 9a409b17f1..a5e54fa546 100644 --- a/interface/src/ui/HMDToolsDialog.cpp +++ b/interface/src/ui/HMDToolsDialog.cpp @@ -27,7 +27,10 @@ HMDToolsDialog::HMDToolsDialog(QWidget* parent) : - QDialog(parent, Qt::Window | Qt::WindowCloseButtonHint | Qt::WindowStaysOnTopHint) + QDialog(parent, Qt::Window | Qt::WindowCloseButtonHint | Qt::WindowStaysOnTopHint) , + _previousScreen(NULL), + _hmdScreen(NULL), + _previousDialogScreen(NULL) { this->setWindowTitle("HMD Tools"); @@ -58,8 +61,18 @@ HMDToolsDialog::HMDToolsDialog(QWidget* parent) : _previousRect = Application::getInstance()->getWindow()->rect(); Application::getInstance()->getWindow()->activateWindow(); + // watch for our application window moving screens. If it does we want to update our screen details QWindow* mainWindow = Application::getInstance()->getWindow()->windowHandle(); connect(mainWindow, &QWindow::screenChanged, this, &HMDToolsDialog::applicationWindowScreenChanged); + + // watch for our dialog window moving screens. If it does we want to enforce our rules about what screens we're + // allowed on + QWindow* dialogWindow = windowHandle(); + connect(dialogWindow, &QWindow::screenChanged, this, &HMDToolsDialog::dialogWindowScreenChanged); + connect(dialogWindow, &QWindow::xChanged, this, &HMDToolsDialog::dialogWindowGeometryChanged); + connect(dialogWindow, &QWindow::yChanged, this, &HMDToolsDialog::dialogWindowGeometryChanged); + connect(dialogWindow, &QWindow::widthChanged, this, &HMDToolsDialog::dialogWindowGeometryChanged); + connect(dialogWindow, &QWindow::heightChanged, this, &HMDToolsDialog::dialogWindowGeometryChanged); } HMDToolsDialog::~HMDToolsDialog() { @@ -69,6 +82,61 @@ void HMDToolsDialog::applicationWindowScreenChanged(QScreen* screen) { _debugDetails->setText(getDebugDetails()); } +void HMDToolsDialog::dialogWindowGeometryChanged(int arg) { + QWindow* dialogWindow = windowHandle(); + _previousDialogRect = rect(); + _previousDialogRect = QRect(dialogWindow->mapToGlobal(_previousDialogRect.topLeft()), + dialogWindow->mapToGlobal(_previousDialogRect.bottomRight())); + _previousDialogScreen = dialogWindow->screen(); +} + +void HMDToolsDialog::dialogWindowScreenChanged(QScreen* screen) { + _debugDetails->setText(getDebugDetails()); + + // if we have more than one screen, and a known hmdScreen then try to + // keep our dialog off of the hmdScreen + if (QApplication::desktop()->screenCount() > 1) { + int hmdScreenNumber = OculusManager::getHMDScreen(); + + if (hmdScreenNumber >= 0) { + QScreen* hmdScreen = QGuiApplication::screens()[hmdScreenNumber]; + + if (screen == hmdScreen) { + qDebug() << "HMD Tools: Whoa! What are you doing? You don't want to move me to the HMD Screen!"; + QWindow* dialogWindow = windowHandle(); + + // try to pick a better screen + QScreen* betterScreen = NULL; + + QWindow* appWindow = Application::getInstance()->getWindow()->windowHandle(); + QScreen* appScreen = appWindow->screen(); + + if (_previousDialogScreen && _previousDialogScreen != hmdScreen) { + // first, if the previous dialog screen is not the HMD screen, then move it there. + betterScreen = appScreen; + } else if (appScreen != hmdScreen) { + // second, if the application screen is not the HMD screen, then move it there. + betterScreen = appScreen; + } else if (_previousScreen && _previousScreen != hmdScreen) { + // third, if the application screen is the HMD screen, we want to move it to + // the previous screen + betterScreen = _previousScreen; + } else { + // last, if we can't use the previous screen the use the primary desktop screen + int desktopPrimaryScreenNumber = QApplication::desktop()->primaryScreen(); + QScreen* desktopPrimaryScreen = QGuiApplication::screens()[desktopPrimaryScreenNumber]; + betterScreen = desktopPrimaryScreen; + } + + if (betterScreen) { + dialogWindow->setScreen(betterScreen); + dialogWindow->setGeometry(_previousDialogRect); + } + } + } + } +} + QString HMDToolsDialog::getDebugDetails() const { QString results; diff --git a/interface/src/ui/HMDToolsDialog.h b/interface/src/ui/HMDToolsDialog.h index f1a5f582cd..4fe0dd626f 100644 --- a/interface/src/ui/HMDToolsDialog.h +++ b/interface/src/ui/HMDToolsDialog.h @@ -33,6 +33,8 @@ public slots: void activateWindowAfterEnterMode(); void moveWindowAfterLeaveMode(); void applicationWindowScreenChanged(QScreen* screen); + void dialogWindowScreenChanged(QScreen* screen); + void dialogWindowGeometryChanged(int arg); protected: virtual void closeEvent(QCloseEvent*); // Emits a 'closed' signal when this dialog is closed. @@ -47,6 +49,9 @@ private: QScreen* _previousScreen; QScreen* _hmdScreen; QLabel* _debugDetails; + + QRect _previousDialogRect; + QScreen* _previousDialogScreen; }; #endif // hifi_HMDToolsDialog_h From dd3a7b9b9dc20c396a482973b973aaa741cf4d7d Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 26 Nov 2014 12:12:43 -0800 Subject: [PATCH 103/502] EntitySimulation takes EntityItem* rather than ID --- .../src/entities}/EntityCollisionSystem.cpp | 0 .../src/entities}/EntityCollisionSystem.h | 0 .../entities/src/DeleteEntityOperator.cpp | 15 +- libraries/entities/src/EntitySimulation.cpp | 20 ++ libraries/entities/src/EntitySimulation.h | 28 +- libraries/entities/src/EntityTree.cpp | 258 ++++-------------- libraries/entities/src/EntityTree.h | 22 +- libraries/entities/src/EntityTreeElement.cpp | 1 - .../entities/src/SimpleEntitySimulation.cpp | 89 +++--- .../entities/src/SimpleEntitySimulation.h | 21 +- 10 files changed, 162 insertions(+), 292 deletions(-) rename {libraries/entities/src => interface/src/entities}/EntityCollisionSystem.cpp (100%) rename {libraries/entities/src => interface/src/entities}/EntityCollisionSystem.h (100%) create mode 100644 libraries/entities/src/EntitySimulation.cpp diff --git a/libraries/entities/src/EntityCollisionSystem.cpp b/interface/src/entities/EntityCollisionSystem.cpp similarity index 100% rename from libraries/entities/src/EntityCollisionSystem.cpp rename to interface/src/entities/EntityCollisionSystem.cpp diff --git a/libraries/entities/src/EntityCollisionSystem.h b/interface/src/entities/EntityCollisionSystem.h similarity index 100% rename from libraries/entities/src/EntityCollisionSystem.h rename to interface/src/entities/EntityCollisionSystem.h diff --git a/libraries/entities/src/DeleteEntityOperator.cpp b/libraries/entities/src/DeleteEntityOperator.cpp index 5b0ada4ec1..12441e5427 100644 --- a/libraries/entities/src/DeleteEntityOperator.cpp +++ b/libraries/entities/src/DeleteEntityOperator.cpp @@ -48,9 +48,6 @@ void DeleteEntityOperator::addEntityIDToDeleteList(const EntityItemID& searchEnt details.cube = details.containingElement->getAACube(); _entitiesToDelete << details; _lookingCount++; - _tree->trackDeletedEntity(searchEntityID); - // before deleting any entity make sure to remove it from our Mortal, Changing, and Moving lists - _tree->removeEntityFromSimulationLists(searchEntityID); } } } @@ -78,13 +75,9 @@ bool DeleteEntityOperator::preRecursion(OctreeElement* element) { EntityTreeElement* entityTreeElement = static_cast(element); // In Pre-recursion, we're generally deciding whether or not we want to recurse this - // path of the tree. For this operation, we want to recurse the branch of the tree if - // and of the following are true: - // * We have not yet found the old entity, and this branch contains our old entity - // * We have not yet found the new entity, and this branch contains our new entity - // - // Note: it's often the case that the branch in question contains both the old entity - // and the new entity. + // path of the tree. For this operation, we want to recurse the branch of the tree if: + // * We have not yet found the all entities, and + // * this branch contains our some of the entities we're looking for. bool keepSearching = false; // assume we don't need to search any more @@ -100,6 +93,8 @@ bool DeleteEntityOperator::preRecursion(OctreeElement* element) { if (entityTreeElement == details.containingElement) { EntityItemID entityItemID = details.entity->getEntityItemID(); EntityItem* theEntity = entityTreeElement->getEntityWithEntityItemID(entityItemID); // find the actual entity + assert(theEntity); + _tree->trackDeletedEntity(theEntity); entityTreeElement->removeEntityItem(theEntity); // remove it from the element _tree->setContainingElement(entityItemID, NULL); // update or id to element lookup delete theEntity; // now actually delete the entity! diff --git a/libraries/entities/src/EntitySimulation.cpp b/libraries/entities/src/EntitySimulation.cpp new file mode 100644 index 0000000000..8058c2f24e --- /dev/null +++ b/libraries/entities/src/EntitySimulation.cpp @@ -0,0 +1,20 @@ +// +// EntitySimulation.cpp +// libraries/entities/src +// +// Created by Andrew Meadows on 2014.11.24 +// 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 "EntitySimulation.h" + +void EntitySimulation::setEntityTree(EntityTree* tree) { + if (_entityTree && _entityTree != tree) { + clearEntities(); + } + _entityTree = tree; +} + diff --git a/libraries/entities/src/EntitySimulation.h b/libraries/entities/src/EntitySimulation.h index 230e744a16..770d6ebdb0 100644 --- a/libraries/entities/src/EntitySimulation.h +++ b/libraries/entities/src/EntitySimulation.h @@ -14,24 +14,36 @@ #include -#include "EntityItemID.h" #include "EntityTree.h" class EntitySimulation { public: - EntitySimulation(EntityTree* tree) : _myTree(tree) { assert(tree); } - virtual ~EntitySimulation() { _myTree = NULL; } + EntitySimulation() : _entityTree(NULL) { } + virtual ~EntitySimulation() {} - /// \sideeffect For each EntityItem* that EntitySimulation puts on entitiesToDelete it will automatically - /// removeEntity() on any internal lists -- no need to call removeEntity() for that one later. - virtual void update(QSet& entitiesToDelete) = 0; + /// \param tree pointer to EntityTree which is stored internally + virtual void setEntityTree(EntityTree* tree); + /// \param[out] entitiesToDelete list of entities removed from simulation and should be deleted. + virtual void update(QSet& entitiesToDelete) = 0; + + /// \param entity pointer to EntityItem to add to the simulation + /// \sideeffect the EntityItem::_simulationState member may be updated to indicate membership to internal list virtual void addEntity(EntityItem* entity) = 0; + + /// \param entity pointer to EntityItem to removed from the simulation + /// \sideeffect the EntityItem::_simulationState member may be updated to indicate non-membership to internal list virtual void removeEntity(EntityItem* entity) = 0; - virtual void updateEntity(EntityItem* entity) = 0; + + /// \param entity pointer to EntityItem to that may have changed in a way that would affect its simulation + virtual void entityChanged(EntityItem* entity) = 0; + + virtual void clearEntities() = 0; + + EntityTree* getEntityTree() { return _entityTree; } protected: - EntityTree* _myTree; + EntityTree* _entityTree; }; #endif // hifi_EntitySimulation_h diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index bb201b6f86..5d4c5b0fc4 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -12,13 +12,14 @@ #include #include "EntityTree.h" +#include "EntitySimulation.h" #include "AddEntityOperator.h" #include "DeleteEntityOperator.h" #include "MovingEntitiesOperator.h" #include "UpdateEntityOperator.h" -EntityTree::EntityTree(bool shouldReaverage) : Octree(shouldReaverage) { +EntityTree::EntityTree(bool shouldReaverage) : Octree(shouldReaverage), _simulation(NULL) { _rootElement = createNewElement(); } @@ -34,14 +35,14 @@ EntityTreeElement* EntityTree::createNewElement(unsigned char * octalCode) { void EntityTree::eraseAllOctreeElements(bool createNewRoot) { // this would be a good place to clean up our entities... + if (_simulation) { + _simulation->clearEntities(); + } foreach (EntityTreeElement* element, _entityToElementMap) { element->cleanupEntities(); } _entityToElementMap.clear(); Octree::eraseAllOctreeElements(createNewRoot); - _movingEntities.clear(); - _mortalEntities.clear(); - _changedEntities.clear(); } bool EntityTree::handlesEditPacketType(PacketType packetType) const { @@ -89,13 +90,14 @@ void EntityTree::addEntityItem(EntityItem* entityItem) { recurseTreeWithOperator(&theOperator); // check to see if we need to simulate this entity.. - updateEntityState(entityItem); + if (_simulation) { + _simulation->addEntity(entityItem); + } _isDirty = true; } bool EntityTree::updateEntity(const EntityItemID& entityID, const EntityItemProperties& properties) { - // You should not call this on existing entities that are already part of the tree! Call updateEntity() EntityTreeElement* containingElement = getContainingElement(entityID); if (!containingElement) { qDebug() << "UNEXPECTED!!!! EntityTree::updateEntity() entityID doesn't exist!!! entityID=" << entityID; @@ -119,6 +121,9 @@ bool EntityTree::updateEntity(const EntityItemID& entityID, const EntityItemProp UpdateEntityOperator theOperator(this, containingElement, existingEntity, tempProperties); recurseTreeWithOperator(&theOperator); _isDirty = true; + if (_simulation && existingEntity->getUpdateFlags() != 0) { + _simulation->entityChanged(existingEntity); + } } } } else { @@ -129,13 +134,14 @@ bool EntityTree::updateEntity(const EntityItemID& entityID, const EntityItemProp recurseTreeWithOperator(&theOperator); _isDirty = true; - updateEntityState(existingEntity); + if (_simulation && existingEntity->getUpdateFlags() != 0) { + _simulation->entityChanged(existingEntity); + } QString entityScriptAfter = existingEntity->getScript(); if (entityScriptBefore != entityScriptAfter) { emitEntityScriptChanging(entityID); // the entity script has changed } - } containingElement = getContainingElement(entityID); @@ -179,13 +185,16 @@ EntityItem* EntityTree::addEntity(const EntityItemID& entityID, const EntityItem } -void EntityTree::trackDeletedEntity(const EntityItemID& entityID) { +void EntityTree::trackDeletedEntity(EntityItem* entity) { + if (_simulation) { + _simulation->removeEntity(entity); + } // this is only needed on the server to send delete messages for recently deleted entities to the viewers if (getIsServer()) { // set up the deleted entities ID quint64 deletedAt = usecTimestampNow(); _recentlyDeletedEntitiesLock.lockForWrite(); - _recentlyDeletedEntityItemIDs.insert(deletedAt, entityID.id); + _recentlyDeletedEntityItemIDs.insert(deletedAt, entity->getEntityItemID().id); _recentlyDeletedEntitiesLock.unlock(); } } @@ -198,6 +207,19 @@ void EntityTree::emitEntityScriptChanging(const EntityItemID& entityItemID) { emit entityScriptChanging(entityItemID); } +void EntityTree::setSimulation(EntitySimulation* simulation) { + if (simulation) { + // assert that the simulation's backpointer has already been properly connected + assert(simulation->getEntityTree() == this); + } + if (_simulation && _simulation != simulation) { + // It's important to clearEntities() on the simulation since taht will update each + // EntityItem::_simulationState correctly so as to not confuse the next _simulation. + _simulation->clearEntities(); + } + _simulation = simulation; +} + void EntityTree::deleteEntity(const EntityItemID& entityID) { emit deletingEntity(entityID); @@ -220,29 +242,6 @@ void EntityTree::deleteEntities(QSet entityIDs) { _isDirty = true; } -void EntityTree::removeEntityFromSimulationLists(const EntityItemID& entityID) { - EntityItem* theEntity = findEntityByEntityItemID(entityID); - - if (theEntity) { - // make sure to remove it from any of our simulation lists - EntityItem::SimulationState theState = theEntity->getSimulationState(); - switch (theState) { - case EntityItem::Moving: - _movingEntities.removeAll(theEntity); - break; - - case EntityItem::Mortal: - _mortalEntities.removeAll(theEntity); - break; - - default: - break; - } - _changedEntities.remove(theEntity); - } -} - - /// This method is used to find and fix entity IDs that are shifting from creator token based to known ID based entity IDs. /// This should only be used on a client side (viewing) tree. The typical usage is that a local editor has been creating /// entities in the local tree, those entities have creatorToken based entity IDs. But those entity edits are also sent up to @@ -575,183 +574,29 @@ void EntityTree::releaseSceneEncodeData(OctreeElementExtraEncodeData* extraEncod extraEncodeData->clear(); } -void EntityTree::updateEntityState(EntityItem* entity) { - EntityItem::SimulationState oldState = entity->getSimulationState(); - EntityItem::SimulationState newState = entity->computeSimulationState(); - if (newState != oldState) { - switch (oldState) { - case EntityItem::Moving: - _movingEntities.removeAll(entity); - break; - - case EntityItem::Mortal: - _mortalEntities.removeAll(entity); - break; - - default: - break; - } - - switch (newState) { - case EntityItem::Moving: - _movingEntities.push_back(entity); - break; - - case EntityItem::Mortal: - _mortalEntities.push_back(entity); - break; - - default: - break; - } - entity->setSimulationState(newState); - } -} - -void EntityTree::clearEntityState(EntityItem* entity) { - EntityItem::SimulationState oldState = entity->getSimulationState(); - switch (oldState) { - case EntityItem::Moving: - _movingEntities.removeAll(entity); - break; - - case EntityItem::Mortal: - _mortalEntities.removeAll(entity); - break; - - default: - break; - } - entity->setSimulationState(EntityItem::Static); -} - void EntityTree::entityChanged(EntityItem* entity) { - _changedEntities.insert(entity); + if (_simulation) { + _simulation->entityChanged(entity); + } } void EntityTree::update() { - // our new strategy should be to segregate entities into three classes: - // 1) stationary things that are not changing - most models - // 2) mortal things - these are stationary but have a lifetime - then need to be checked, - // can be touched linearly, and won't change the tree - // 2) changing things - like things animating they can be touched linearly and they don't change the tree - // 3) moving things - these need to scan the tree and update accordingly - // finally - all things that need to be deleted, can be handled on a single delete pass. - // - // TODO: theoretically we could combine the move and delete tree passes... - lockForWrite(); - quint64 now = usecTimestampNow(); - QSet entitiesToDelete; - updateChangedEntities(now, entitiesToDelete); - updateMovingEntities(now, entitiesToDelete); - updateMortalEntities(now, entitiesToDelete); - - if (entitiesToDelete.size() > 0) { - deleteEntities(entitiesToDelete); - } - unlock(); -} - -void EntityTree::updateChangedEntities(quint64 now, QSet& entitiesToDelete) { - foreach (EntityItem* thisEntity, _changedEntities) { - // check to see if the lifetime has expired, for immortal entities this is always false - if (thisEntity->lifetimeHasExpired()) { - qDebug() << "Lifetime has expired for entity:" << thisEntity->getEntityItemID(); - entitiesToDelete << thisEntity->getEntityItemID(); - clearEntityState(thisEntity); - } else { - updateEntityState(thisEntity); - } - thisEntity->clearUpdateFlags(); - } - _changedEntities.clear(); -} - -void EntityTree::updateMovingEntities(quint64 now, QSet& entitiesToDelete) { - PerformanceTimer perfTimer("updateMovingEntities"); - if (_movingEntities.size() > 0) { - MovingEntitiesOperator moveOperator(this); - { - PerformanceTimer perfTimer("_movingEntities"); - - QList::iterator item_itr = _movingEntities.begin(); - while (item_itr != _movingEntities.end()) { - EntityItem* thisEntity = *item_itr; - - // always check to see if the lifetime has expired, for immortal entities this is always false - if (thisEntity->lifetimeHasExpired()) { - qDebug() << "Lifetime has expired for entity:" << thisEntity->getEntityItemID(); - entitiesToDelete << thisEntity->getEntityItemID(); - // remove thisEntity from the list - item_itr = _movingEntities.erase(item_itr); - thisEntity->setSimulationState(EntityItem::Static); - } else { - AACube oldCube = thisEntity->getMaximumAACube(); - thisEntity->update(now); - AACube newCube = thisEntity->getMaximumAACube(); - - // check to see if this movement has sent the entity outside of the domain. - AACube domainBounds(glm::vec3(0.0f,0.0f,0.0f), 1.0f); - if (!domainBounds.touches(newCube)) { - qDebug() << "Entity " << thisEntity->getEntityItemID() << " moved out of domain bounds."; - entitiesToDelete << thisEntity->getEntityItemID(); - // remove thisEntity from the list - item_itr = _movingEntities.erase(item_itr); - thisEntity->setSimulationState(EntityItem::Static); - } else { - moveOperator.addEntityToMoveList(thisEntity, oldCube, newCube); - EntityItem::SimulationState newState = thisEntity->computeSimulationState(); - if (newState != EntityItem::Moving) { - if (newState == EntityItem::Mortal) { - _mortalEntities.push_back(thisEntity); - } - // remove thisEntity from the list - item_itr = _movingEntities.erase(item_itr); - thisEntity->setSimulationState(newState); - } else { - ++item_itr; - } - } - } + if (_simulation) { + lockForWrite(); + QSet entitiesToDelete; + _simulation->update(entitiesToDelete); + if (entitiesToDelete.size() > 0) { + // translate into list of ID's + QSet idsToDelete; + foreach (EntityItem* entity, entitiesToDelete) { + idsToDelete.insert(entity->getEntityItemID()); } + deleteEntities(idsToDelete); } - if (moveOperator.hasMovingEntities()) { - PerformanceTimer perfTimer("recurseTreeWithOperator"); - recurseTreeWithOperator(&moveOperator); - } + unlock(); } } -void EntityTree::updateMortalEntities(quint64 now, QSet& entitiesToDelete) { - QList::iterator item_itr = _mortalEntities.begin(); - while (item_itr != _mortalEntities.end()) { - EntityItem* thisEntity = *item_itr; - thisEntity->update(now); - // always check to see if the lifetime has expired, for immortal entities this is always false - if (thisEntity->lifetimeHasExpired()) { - qDebug() << "Lifetime has expired for entity:" << thisEntity->getEntityItemID(); - entitiesToDelete << thisEntity->getEntityItemID(); - // remove thisEntity from the list - item_itr = _mortalEntities.erase(item_itr); - thisEntity->setSimulationState(EntityItem::Static); - } else { - // check to see if this entity is no longer moving - EntityItem::SimulationState newState = thisEntity->computeSimulationState(); - if (newState != EntityItem::Mortal) { - if (newState == EntityItem::Moving) { - _movingEntities.push_back(thisEntity); - } - // remove thisEntity from the list - item_itr = _mortalEntities.erase(item_itr); - thisEntity->setSimulationState(newState); - } else { - ++item_itr; - } - } - } -} - - bool EntityTree::hasEntitiesDeletedSince(quint64 sinceTime) { // we can probably leverage the ordered nature of QMultiMap to do this quickly... bool hasSomethingNewer = false; @@ -966,19 +811,16 @@ int EntityTree::processEraseMessageDetails(const QByteArray& dataByteArray, cons EntityTreeElement* EntityTree::getContainingElement(const EntityItemID& entityItemID) /*const*/ { // TODO: do we need to make this thread safe? Or is it acceptable as is - if (_entityToElementMap.contains(entityItemID)) { - return _entityToElementMap.value(entityItemID); - } else if (entityItemID.creatorTokenID != UNKNOWN_ENTITY_TOKEN){ + EntityTreeElement* element = _entityToElementMap.value(entityItemID); + if (!element && entityItemID.creatorTokenID != UNKNOWN_ENTITY_TOKEN){ // check the creator token version too... EntityItemID creatorTokenOnly; creatorTokenOnly.id = UNKNOWN_ENTITY_ID; creatorTokenOnly.creatorTokenID = entityItemID.creatorTokenID; creatorTokenOnly.isKnownID = false; - if (_entityToElementMap.contains(creatorTokenOnly)) { - return _entityToElementMap.value(creatorTokenOnly); - } + element = _entityToElementMap.value(creatorTokenOnly); } - return NULL; + return element; } // TODO: do we need to make this thread safe? Or is it acceptable as is diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index 7370ebadc6..db128e4563 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -19,6 +19,7 @@ class Model; +class EntitySimulation; class NewlyCreatedEntityHook { public: @@ -84,7 +85,7 @@ public: bool updateEntity(const EntityItemID& entityID, const EntityItemProperties& properties); void deleteEntity(const EntityItemID& entityID); void deleteEntities(QSet entityIDs); - void removeEntityFromSimulationLists(const EntityItemID& entityID); + void removeEntityFromSimulation(EntityItem* entity); const EntityItem* findClosestEntity(glm::vec3 position, float targetRadius); EntityItem* findEntityByID(const QUuid& id); @@ -137,18 +138,15 @@ public: void sendEntities(EntityEditPacketSender* packetSender, EntityTree* localTree, float x, float y, float z); - void updateEntityState(EntityItem* entity); - void clearEntityState(EntityItem* entity); - void entityChanged(EntityItem* entity); - void trackDeletedEntity(const EntityItemID& entityID); + void trackDeletedEntity(EntityItem* entity); void emitAddingEntity(const EntityItemID& entityItemID); void emitEntityScriptChanging(const EntityItemID& entityItemID); - QList& getMovingEntities() { return _movingEntities; } - + void setSimulation(EntitySimulation* simulation); + signals: void deletingEntity(const EntityItemID& entityID); void addingEntity(const EntityItemID& entityID); @@ -157,10 +155,6 @@ signals: private: - void updateChangedEntities(quint64 now, QSet& entitiesToDelete); - void updateMovingEntities(quint64 now, QSet& entitiesToDelete); - void updateMortalEntities(quint64 now, QSet& entitiesToDelete); - static bool findNearPointOperation(OctreeElement* element, void* extraData); static bool findInSphereOperation(OctreeElement* element, void* extraData); static bool findInCubeOperation(OctreeElement* element, void* extraData); @@ -176,11 +170,7 @@ private: EntityItemFBXService* _fbxService; QHash _entityToElementMap; - - QList _movingEntities; // entities that need to be updated - QList _mortalEntities; // entities that need to be checked for expiry - - QSet _changedEntities; // entities that have changed in the last frame + EntitySimulation* _simulation; }; #endif // hifi_EntityTree_h diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index 2646cc0dfd..17f7456670 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -768,7 +768,6 @@ int EntityTreeElement::readElementDataFromBuffer(const unsigned char* data, int addEntityItem(entityItem); // add this new entity to this elements entities entityItemID = entityItem->getEntityItemID(); _myTree->setContainingElement(entityItemID, this); - _myTree->updateEntityState(entityItem); _myTree->emitAddingEntity(entityItemID); // we just added an entity } } diff --git a/libraries/entities/src/SimpleEntitySimulation.cpp b/libraries/entities/src/SimpleEntitySimulation.cpp index d8edfb8ba7..b3316978a9 100644 --- a/libraries/entities/src/SimpleEntitySimulation.cpp +++ b/libraries/entities/src/SimpleEntitySimulation.cpp @@ -16,7 +16,7 @@ #include "MovingEntitiesOperator.h" #include "SimpleEntitySimulation.h" -void SimpleEntitySimulation::update(QSet& entitiesToDelete) { +void SimpleEntitySimulation::update(QSet& entitiesToDelete) { quint64 now = usecTimestampNow(); updateChangedEntities(now, entitiesToDelete); updateMovingEntities(now, entitiesToDelete); @@ -56,21 +56,32 @@ void SimpleEntitySimulation::removeEntity(EntityItem* entity) { default: break; } + entity->setSimulationState(EntityItem::Static); _changedEntities.remove(entity); } -void SimpleEntitySimulation::updateEntity(EntityItem* entity) { +void SimpleEntitySimulation::entityChanged(EntityItem* entity) { assert(entity); - // we'll deal with thsi change later + // we batch all changes and deal with them in updateChangedEntities() _changedEntities.insert(entity); } + +void SimpleEntitySimulation::clearEntities() { + foreach (EntityItem* entity, _changedEntities) { + entity->clearUpdateFlags(); + entity->setSimulationState(EntityItem::Static); + } + _changedEntities.clear(); + _movingEntities.clear(); + _mortalEntities.clear(); +} -void SimpleEntitySimulation::updateChangedEntities(quint64 now, QSet& entitiesToDelete) { +void SimpleEntitySimulation::updateChangedEntities(quint64 now, QSet& entitiesToDelete) { foreach (EntityItem* entity, _changedEntities) { // check to see if the lifetime has expired, for immortal entities this is always false if (entity->lifetimeHasExpired()) { qDebug() << "Lifetime has expired for entity:" << entity->getEntityItemID(); - entitiesToDelete << entity->getEntityItemID(); + entitiesToDelete.insert(entity); clearEntityState(entity); } else { updateEntityState(entity); @@ -80,44 +91,44 @@ void SimpleEntitySimulation::updateChangedEntities(quint64 now, QSet& entitiesToDelete) { - if (_movingEntities.size() > 0) { +void SimpleEntitySimulation::updateMovingEntities(quint64 now, QSet& entitiesToDelete) { + if (_entityTree && _movingEntities.size() > 0) { PerformanceTimer perfTimer("_movingEntities"); - MovingEntitiesOperator moveOperator(_myTree); + MovingEntitiesOperator moveOperator(_entityTree); QList::iterator item_itr = _movingEntities.begin(); while (item_itr != _movingEntities.end()) { - EntityItem* thisEntity = *item_itr; + EntityItem* entity = *item_itr; // always check to see if the lifetime has expired, for immortal entities this is always false - if (thisEntity->lifetimeHasExpired()) { - qDebug() << "Lifetime has expired for entity:" << thisEntity->getEntityItemID(); - entitiesToDelete << thisEntity->getEntityItemID(); - // remove thisEntity from the list + if (entity->lifetimeHasExpired()) { + qDebug() << "Lifetime has expired for entity:" << entity->getEntityItemID(); + entitiesToDelete.insert(entity); + // remove entity from the list item_itr = _movingEntities.erase(item_itr); - thisEntity->setSimulationState(EntityItem::Static); + entity->setSimulationState(EntityItem::Static); } else { - AACube oldCube = thisEntity->getMaximumAACube(); - thisEntity->update(now); - AACube newCube = thisEntity->getMaximumAACube(); + AACube oldCube = entity->getMaximumAACube(); + entity->update(now); + AACube newCube = entity->getMaximumAACube(); // check to see if this movement has sent the entity outside of the domain. AACube domainBounds(glm::vec3(0.0f,0.0f,0.0f), 1.0f); if (!domainBounds.touches(newCube)) { - qDebug() << "Entity " << thisEntity->getEntityItemID() << " moved out of domain bounds."; - entitiesToDelete << thisEntity->getEntityItemID(); - // remove thisEntity from the list + qDebug() << "Entity " << entity->getEntityItemID() << " moved out of domain bounds."; + entitiesToDelete.insert(entity); + // remove entity from the list item_itr = _movingEntities.erase(item_itr); - thisEntity->setSimulationState(EntityItem::Static); + entity->setSimulationState(EntityItem::Static); } else { - moveOperator.addEntityToMoveList(thisEntity, oldCube, newCube); - EntityItem::SimulationState newState = thisEntity->computeSimulationState(); + moveOperator.addEntityToMoveList(entity, oldCube, newCube); + EntityItem::SimulationState newState = entity->computeSimulationState(); if (newState != EntityItem::Moving) { if (newState == EntityItem::Mortal) { - _mortalEntities.push_back(thisEntity); + _mortalEntities.push_back(entity); } - // remove thisEntity from the list + // remove entity from the list item_itr = _movingEntities.erase(item_itr); - thisEntity->setSimulationState(newState); + entity->setSimulationState(newState); } else { ++item_itr; } @@ -126,33 +137,33 @@ void SimpleEntitySimulation::updateMovingEntities(quint64 now, QSetrecurseTreeWithOperator(&moveOperator); + _entityTree->recurseTreeWithOperator(&moveOperator); } } } -void SimpleEntitySimulation::updateMortalEntities(quint64 now, QSet& entitiesToDelete) { +void SimpleEntitySimulation::updateMortalEntities(quint64 now, QSet& entitiesToDelete) { QList::iterator item_itr = _mortalEntities.begin(); while (item_itr != _mortalEntities.end()) { - EntityItem* thisEntity = *item_itr; - thisEntity->update(now); + EntityItem* entity = *item_itr; // always check to see if the lifetime has expired, for immortal entities this is always false - if (thisEntity->lifetimeHasExpired()) { - qDebug() << "Lifetime has expired for entity:" << thisEntity->getEntityItemID(); - entitiesToDelete << thisEntity->getEntityItemID(); - // remove thisEntity from the list + if (entity->lifetimeHasExpired()) { + qDebug() << "Lifetime has expired for entity:" << entity->getEntityItemID(); + entitiesToDelete.insert(entity); + // remove entity from the list item_itr = _mortalEntities.erase(item_itr); - thisEntity->setSimulationState(EntityItem::Static); + entity->setSimulationState(EntityItem::Static); } else { // check to see if this entity is no longer moving - EntityItem::SimulationState newState = thisEntity->computeSimulationState(); + EntityItem::SimulationState newState = entity->computeSimulationState(); if (newState != EntityItem::Mortal) { if (newState == EntityItem::Moving) { - _movingEntities.push_back(thisEntity); + entity->update(now); + _movingEntities.push_back(entity); } - // remove thisEntity from the list + // remove entity from the list item_itr = _mortalEntities.erase(item_itr); - thisEntity->setSimulationState(newState); + entity->setSimulationState(newState); } else { ++item_itr; } diff --git a/libraries/entities/src/SimpleEntitySimulation.h b/libraries/entities/src/SimpleEntitySimulation.h index bc79bf9958..7d0e8f0113 100644 --- a/libraries/entities/src/SimpleEntitySimulation.h +++ b/libraries/entities/src/SimpleEntitySimulation.h @@ -18,29 +18,30 @@ class SimpleEntitySimulation : public EntitySimulation { public: - SimpleEntitySimulation(EntityTree* tree) : EntitySimulation(tree) { } - virtual ~SimpleEntitySimulation() { } + SimpleEntitySimulation() : EntitySimulation() { } + virtual ~SimpleEntitySimulation() { setEntityTree(NULL); } - virtual void update(QSet& entitiesToDelete); + virtual void update(QSet& entitiesToDelete); virtual void addEntity(EntityItem* entity); virtual void removeEntity(EntityItem* entity); - virtual void updateEntity(EntityItem* entity); + virtual void entityChanged(EntityItem* entity); -private: + virtual void clearEntities(); + +protected: void updateEntityState(EntityItem* entity); void clearEntityState(EntityItem* entity); QList& getMovingEntities() { return _movingEntities; } - void updateChangedEntities(quint64 now, QSet& entitiesToDelete); - void updateMovingEntities(quint64 now, QSet& entitiesToDelete); - void updateMortalEntities(quint64 now, QSet& entitiesToDelete); + void updateChangedEntities(quint64 now, QSet& entitiesToDelete); + void updateMovingEntities(quint64 now, QSet& entitiesToDelete); + void updateMortalEntities(quint64 now, QSet& entitiesToDelete); -private: + QSet _changedEntities; // entities that have changed in the last frame QList _movingEntities; // entities that need to be updated QList _mortalEntities; // non-moving entities that need to be checked for expiry - QSet _changedEntities; // entities that have changed in the last frame }; #endif // hifi_SimpleEntitySimulation_h From cb6d9a4312fcad37625c4bce7ed66e9632c42215 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 26 Nov 2014 12:14:17 -0800 Subject: [PATCH 104/502] EntityServer gets a simuation --- assignment-client/src/entities/EntityServer.cpp | 10 +++++++++- assignment-client/src/entities/EntityServer.h | 1 + 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/assignment-client/src/entities/EntityServer.cpp b/assignment-client/src/entities/EntityServer.cpp index 2b7d6873cc..f3c52f5895 100644 --- a/assignment-client/src/entities/EntityServer.cpp +++ b/assignment-client/src/entities/EntityServer.cpp @@ -11,6 +11,7 @@ #include #include +#include #include "EntityServer.h" #include "EntityServerConsts.h" @@ -20,7 +21,8 @@ const char* MODEL_SERVER_NAME = "Entity"; const char* MODEL_SERVER_LOGGING_TARGET_NAME = "entity-server"; const char* LOCAL_MODELS_PERSIST_FILE = "resources/models.svo"; -EntityServer::EntityServer(const QByteArray& packet) : OctreeServer(packet) { +EntityServer::EntityServer(const QByteArray& packet) + : OctreeServer(packet), _entitySimulation(NULL) { // nothing special to do here... } @@ -36,6 +38,12 @@ OctreeQueryNode* EntityServer::createOctreeQueryNode() { Octree* EntityServer::createTree() { EntityTree* tree = new EntityTree(true); tree->addNewlyCreatedHook(this); + if (!_entitySimulation) { + SimpleEntitySimulation* simpleSimulation = new SimpleEntitySimulation(); + simpleSimulation->setEntityTree(tree); + tree->setSimulation(simpleSimulation); + _entitySimulation = simpleSimulation; + } return tree; } diff --git a/assignment-client/src/entities/EntityServer.h b/assignment-client/src/entities/EntityServer.h index 563efed288..14fd26b775 100644 --- a/assignment-client/src/entities/EntityServer.h +++ b/assignment-client/src/entities/EntityServer.h @@ -47,6 +47,7 @@ public slots: void pruneDeletedEntities(); private: + EntitySimulation* _entitySimulation; }; #endif // hifi_EntityServer_h From cda8ac85c108e9fed76a359cebf8c512386e2d42 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 26 Nov 2014 12:15:24 -0800 Subject: [PATCH 105/502] EntityCollisionSystem moves to interface and interface connects EntityCollision system to EntityTree --- interface/src/Application.cpp | 14 ++++-- interface/src/Application.h | 2 +- .../src/entities/EntityCollisionSystem.cpp | 48 +++++++++++-------- .../src/entities/EntityCollisionSystem.h | 17 +++---- 4 files changed, 44 insertions(+), 37 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 58b28fcef9..f2663829e4 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -441,6 +441,7 @@ void Application::aboutToQuit() { } Application::~Application() { + _entities.getTree()->setSimulation(NULL); qInstallMessageHandler(NULL); saveSettings(); @@ -1968,7 +1969,9 @@ void Application::init() { _entities.init(); _entities.setViewFrustum(getViewFrustum()); - _entityCollisionSystem.init(&_entityEditSender, _entities.getTree(), _voxels.getTree(), &_audio, &_avatarManager); + EntityTree* entityTree = _entities.getTree(); + _entityCollisionSystem.init(&_entityEditSender, entityTree, _voxels.getTree(), &_audio, &_avatarManager); + entityTree->setSimulation(&_entityCollisionSystem); // connect the _entityCollisionSystem to our script engine's EntityScriptingInterface connect(&_entityCollisionSystem, &EntityCollisionSystem::entityCollisionWithVoxel, @@ -2319,11 +2322,12 @@ void Application::update(float deltaTime) { if (!_aboutToQuit) { PerformanceTimer perfTimer("entities"); + // NOTE: the _entities.update() call below will wait for lock + // and will simulate entity motion (the EntityTree has been given an EntitySimulation). _entities.update(); // update the models... - { - PerformanceTimer perfTimer("collisions"); - _entityCollisionSystem.update(); // collide the entities... - } + // The _entityCollisionSystem.updateCollisions() call below merely tries for lock, + // and on failure it skips collision detection. + _entityCollisionSystem.updateCollisions(); // collide the entities... } { diff --git a/interface/src/Application.h b/interface/src/Application.h index c75202d96f..1c49e871e7 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -31,7 +31,6 @@ #include #include -#include #include #include #include @@ -60,6 +59,7 @@ #include "devices/SixenseManager.h" #include "devices/Visage.h" #include "devices/DdeFaceTracker.h" +#include "entities/EntityCollisionSystem.h" #include "entities/EntityTreeRenderer.h" #include "renderer/AmbientOcclusionEffect.h" #include "renderer/DeferredLightingEffect.h" diff --git a/interface/src/entities/EntityCollisionSystem.cpp b/interface/src/entities/EntityCollisionSystem.cpp index b080212479..1760d63157 100644 --- a/interface/src/entities/EntityCollisionSystem.cpp +++ b/interface/src/entities/EntityCollisionSystem.cpp @@ -16,27 +16,33 @@ #include #include #include +#include #include -#include "EntityItem.h" +#include +#include +#include +#include + #include "EntityCollisionSystem.h" -#include "EntityEditPacketSender.h" -#include "EntityTree.h" -#include "EntityTreeElement.h" const int MAX_COLLISIONS_PER_Entity = 16; -EntityCollisionSystem::EntityCollisionSystem(EntityEditPacketSender* packetSender, - EntityTree* Entities, VoxelTree* voxels, AbstractAudioInterface* audio, - AvatarHashMap* avatars) : _collisions(MAX_COLLISIONS_PER_Entity) { - init(packetSender, Entities, voxels, audio, avatars); +EntityCollisionSystem::EntityCollisionSystem() + : SimpleEntitySimulation(), + _packetSender(NULL), + _voxels(NULL), + _audio(NULL), + _avatars(NULL), + _collisions(MAX_COLLISIONS_PER_Entity) { } void EntityCollisionSystem::init(EntityEditPacketSender* packetSender, - EntityTree* Entities, VoxelTree* voxels, AbstractAudioInterface* audio, - AvatarHashMap* avatars) { + EntityTree* entities, VoxelTree* voxels, AbstractAudioInterface* audio, + AvatarHashMap* avatars) { + assert(entities); + setEntityTree(entities); _packetSender = packetSender; - _entities = Entities; _voxels = voxels; _audio = audio; _avatars = avatars; @@ -45,14 +51,15 @@ void EntityCollisionSystem::init(EntityEditPacketSender* packetSender, EntityCollisionSystem::~EntityCollisionSystem() { } -void EntityCollisionSystem::update() { +void EntityCollisionSystem::updateCollisions() { + PerformanceTimer perfTimer("collisions"); + assert(_entityTree); // update all Entities - if (_entities->tryLockForRead()) { - QList& movingEntities = _entities->getMovingEntities(); - foreach (EntityItem* entity, movingEntities) { + if (_entityTree->tryLockForRead()) { + foreach (EntityItem* entity, _movingEntities) { checkEntity(entity); } - _entities->unlock(); + _entityTree->unlock(); } } @@ -127,9 +134,8 @@ void EntityCollisionSystem::updateCollisionWithEntities(EntityItem* entityA) { CollisionList collisions(MAX_COLLISIONS_PER_ENTITY); bool shapeCollisionsAccurate = false; - bool shapeCollisions = _entities->findShapeCollisions(&entityA->getCollisionShapeInMeters(), + bool shapeCollisions = _entityTree->findShapeCollisions(&entityA->getCollisionShapeInMeters(), collisions, Octree::NoLock, &shapeCollisionsAccurate); - if (shapeCollisions) { for(int i = 0; i < collisions.size(); i++) { @@ -203,7 +209,7 @@ void EntityCollisionSystem::updateCollisionWithEntities(EntityItem* entityA) { propertiesA.setPosition(newPositionA * (float)TREE_SCALE); propertiesA.setLastEdited(now); - _entities->updateEntity(idA, propertiesA); + _entityTree->updateEntity(idA, propertiesA); _packetSender->queueEditEntityMessage(PacketTypeEntityAddOrEdit, idA, propertiesA); } @@ -220,7 +226,7 @@ void EntityCollisionSystem::updateCollisionWithEntities(EntityItem* entityA) { propertiesB.setPosition(newPositionB * (float)TREE_SCALE); propertiesB.setLastEdited(now); - _entities->updateEntity(idB, propertiesB); + _entityTree->updateEntity(idB, propertiesB); _packetSender->queueEditEntityMessage(PacketTypeEntityAddOrEdit, idB, propertiesB); } } @@ -326,6 +332,6 @@ void EntityCollisionSystem::applyHardCollision(EntityItem* entity, const Collisi properties.setVelocity(velocity * (float)TREE_SCALE); properties.setLastEdited(usecTimestampNow()); - _entities->updateEntity(entityItemID, properties); + _entityTree->updateEntity(entityItemID, properties); _packetSender->queueEditEntityMessage(PacketTypeEntityAddOrEdit, entityItemID, properties); } diff --git a/interface/src/entities/EntityCollisionSystem.h b/interface/src/entities/EntityCollisionSystem.h index 4b483122fe..a1eb174756 100644 --- a/interface/src/entities/EntityCollisionSystem.h +++ b/interface/src/entities/EntityCollisionSystem.h @@ -20,31 +20,29 @@ #include #include -#include +#include #include +#include +#include #include -#include "EntityItem.h" - class AbstractAudioInterface; class AvatarData; class EntityEditPacketSender; class EntityTree; class VoxelTree; -class EntityCollisionSystem : public QObject { +class EntityCollisionSystem : public QObject, public SimpleEntitySimulation { Q_OBJECT public: - EntityCollisionSystem(EntityEditPacketSender* packetSender = NULL, EntityTree* Entitys = NULL, - VoxelTree* voxels = NULL, AbstractAudioInterface* audio = NULL, - AvatarHashMap* avatars = NULL); + EntityCollisionSystem(); - void init(EntityEditPacketSender* packetSender, EntityTree* Entitys, VoxelTree* voxels, + void init(EntityEditPacketSender* packetSender, EntityTree* entities, VoxelTree* voxels, AbstractAudioInterface* audio = NULL, AvatarHashMap* _avatars = NULL); ~EntityCollisionSystem(); - void update(); + void updateCollisions(); void checkEntity(EntityItem* Entity); void updateCollisionWithVoxels(EntityItem* Entity); @@ -65,7 +63,6 @@ private: void emitGlobalEntityCollisionWithEntity(EntityItem* entityA, EntityItem* entityB, const CollisionInfo& penetration); EntityEditPacketSender* _packetSender; - EntityTree* _entities; VoxelTree* _voxels; AbstractAudioInterface* _audio; AvatarHashMap* _avatars; From b543434a1754e21fdceba7578ea60dc490a1c1dc Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 26 Nov 2014 12:16:52 -0800 Subject: [PATCH 106/502] EntityTreeHeadlessViewer gets a simulation --- libraries/entities/src/EntityTreeHeadlessViewer.cpp | 13 ++++++++++--- libraries/entities/src/EntityTreeHeadlessViewer.h | 4 ++++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/libraries/entities/src/EntityTreeHeadlessViewer.cpp b/libraries/entities/src/EntityTreeHeadlessViewer.cpp index df00d302e3..45d21c0987 100644 --- a/libraries/entities/src/EntityTreeHeadlessViewer.cpp +++ b/libraries/entities/src/EntityTreeHeadlessViewer.cpp @@ -10,9 +10,10 @@ // #include "EntityTreeHeadlessViewer.h" +#include "SimpleEntitySimulation.h" -EntityTreeHeadlessViewer::EntityTreeHeadlessViewer() : - OctreeHeadlessViewer() { +EntityTreeHeadlessViewer::EntityTreeHeadlessViewer() + : OctreeHeadlessViewer(), _simulation(NULL) { } EntityTreeHeadlessViewer::~EntityTreeHeadlessViewer() { @@ -20,9 +21,15 @@ EntityTreeHeadlessViewer::~EntityTreeHeadlessViewer() { void EntityTreeHeadlessViewer::init() { OctreeHeadlessViewer::init(); + if (!_simulation) { + SimpleEntitySimulation* simpleSimulation = new SimpleEntitySimulation(); + EntityTree* entityTree = static_cast(_tree); + simpleSimulation->setEntityTree(entityTree); + entityTree->setSimulation(simpleSimulation); + _simulation = simpleSimulation; + } } - void EntityTreeHeadlessViewer::update() { if (_tree) { EntityTree* tree = static_cast(_tree); diff --git a/libraries/entities/src/EntityTreeHeadlessViewer.h b/libraries/entities/src/EntityTreeHeadlessViewer.h index b6cc04fb12..16839f9951 100644 --- a/libraries/entities/src/EntityTreeHeadlessViewer.h +++ b/libraries/entities/src/EntityTreeHeadlessViewer.h @@ -21,6 +21,8 @@ #include "EntityTree.h" +class EntitySimulation; + // Generic client side Octree renderer class. class EntityTreeHeadlessViewer : public OctreeHeadlessViewer { Q_OBJECT @@ -40,6 +42,8 @@ public: void processEraseMessage(const QByteArray& dataByteArray, const SharedNodePointer& sourceNode); virtual void init(); +protected: + EntitySimulation* _simulation; }; #endif // hifi_EntityTreeHeadlessViewer_h From 2fc3fdc7e6c717f36c8ff6e7426fd6f2f1b65702 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 26 Nov 2014 12:26:02 -0800 Subject: [PATCH 107/502] improve how cameras are reset when leaving vr mode --- interface/src/Application.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 1a7ccf21ee..397f883b3e 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -668,8 +668,6 @@ void Application::paintGL() { // Update camera position if (!OculusManager::isConnected()) { - _myCamera.setHmdPosition(glm::vec3()); - _myCamera.setHmdRotation(glm::quat()); _myCamera.update(1.0f / _fps); } @@ -1606,6 +1604,11 @@ void Application::setEnableVRMode(bool enableVRMode) { OculusManager::recalibrate(); } else { OculusManager::abandonCalibration(); + + _mirrorCamera.setHmdPosition(glm::vec3()); + _mirrorCamera.setHmdRotation(glm::quat()); + _myCamera.setHmdPosition(glm::vec3()); + _myCamera.setHmdRotation(glm::quat()); } resizeGL(_glWidget->getDeviceWidth(), _glWidget->getDeviceHeight()); From 711f9f69058ca26e1a47602c959c9a72a49e60df Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 26 Nov 2014 12:34:47 -0800 Subject: [PATCH 108/502] fix bug where audio meter is incorrectly offset when in oculus mode --- interface/src/ui/ApplicationOverlay.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 55d4cf7c8b..1307672ad1 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -984,7 +984,8 @@ void ApplicationOverlay::renderAudioMeter() { const int AUDIO_METER_X = MIRROR_VIEW_LEFT_PADDING + MUTE_ICON_SIZE + AUDIO_METER_INSET + AUDIO_METER_GAP; int audioMeterY; - bool boxed = Menu::getInstance()->isOptionChecked(MenuOption::Mirror) && + bool smallMirrorVisible = Menu::getInstance()->isOptionChecked(MenuOption::Mirror) && !OculusManager::isConnected(); + bool boxed = smallMirrorVisible && !Menu::getInstance()->isOptionChecked(MenuOption::FullscreenMirror); if (boxed) { audioMeterY = MIRROR_VIEW_HEIGHT + AUDIO_METER_GAP + MUTE_ICON_PADDING; From 790b085307ae8db752af6031b661cc0e0586b7fe Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 26 Nov 2014 13:02:11 -0800 Subject: [PATCH 109/502] Rejiggering the heightfield renderer for LOD. --- interface/src/MetavoxelSystem.cpp | 237 ++++++++++++++------------- interface/src/MetavoxelSystem.h | 34 +++- libraries/metavoxels/src/Spanner.cpp | 24 ++- libraries/metavoxels/src/Spanner.h | 3 + 4 files changed, 174 insertions(+), 124 deletions(-) diff --git a/interface/src/MetavoxelSystem.cpp b/interface/src/MetavoxelSystem.cpp index b98fea8eca..b8d1761297 100644 --- a/interface/src/MetavoxelSystem.cpp +++ b/interface/src/MetavoxelSystem.cpp @@ -2073,57 +2073,67 @@ void StaticModelRenderer::applyURL(const QUrl& url) { } HeightfieldRenderer::HeightfieldRenderer() { - glGenTextures(1, &_heightTextureID); - glBindTexture(GL_TEXTURE_2D, _heightTextureID); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - glGenTextures(1, &_colorTextureID); - glBindTexture(GL_TEXTURE_2D, _colorTextureID); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - glGenTextures(1, &_materialTextureID); - glBindTexture(GL_TEXTURE_2D, _materialTextureID); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - glBindTexture(GL_TEXTURE_2D, 0); -} - -HeightfieldRenderer::~HeightfieldRenderer() { - glDeleteTextures(1, &_heightTextureID); - glDeleteTextures(1, &_colorTextureID); - glDeleteTextures(1, &_materialTextureID); } void HeightfieldRenderer::init(Spanner* spanner) { SpannerRenderer::init(spanner); Heightfield* heightfield = static_cast(spanner); - applyHeight(heightfield->getHeight()); - applyColor(heightfield->getColor()); - applyMaterial(heightfield->getMaterial()); - - connect(heightfield, &Heightfield::heightChanged, this, &HeightfieldRenderer::applyHeight); - connect(heightfield, &Heightfield::colorChanged, this, &HeightfieldRenderer::applyColor); - connect(heightfield, &Heightfield::materialChanged, this, &HeightfieldRenderer::applyMaterial); + connect(heightfield, &Heightfield::rootChanged, this, &HeightfieldRenderer::updateRoot); + updateRoot(); } void HeightfieldRenderer::render(bool cursor) { - // create the buffer objects lazily Heightfield* heightfield = static_cast(_spanner); - if (!heightfield->getHeight()) { + _root->render(heightfield->getTranslation(), heightfield->getRotation(), glm::vec3(heightfield->getScale(), + heightfield->getScale() * heightfield->getAspectY(), heightfield->getScale() * heightfield->getAspectZ()), cursor); +} + +void HeightfieldRenderer::updateRoot() { + Heightfield* heightfield = static_cast(_spanner); + _root = new HeightfieldRendererNode(heightfield->getRoot()); +} + +HeightfieldRendererNode::HeightfieldRendererNode(const HeightfieldNodePointer& heightfieldNode) : + _heightfieldNode(heightfieldNode), + _heightTextureID(0), + _colorTextureID(0), + _materialTextureID(0) { + + for (int i = 0; i < CHILD_COUNT; i++) { + HeightfieldNodePointer child = heightfieldNode->getChild(i); + if (child) { + _children[i] = new HeightfieldRendererNode(child); + } + } +} + +HeightfieldRendererNode::~HeightfieldRendererNode() { + glDeleteTextures(1, &_heightTextureID); + glDeleteTextures(1, &_colorTextureID); + glDeleteTextures(1, &_materialTextureID); +} + +const int X_MAXIMUM_FLAG = 1; +const int Y_MAXIMUM_FLAG = 2; + +void HeightfieldRendererNode::render(const glm::vec3& translation, const glm::quat& rotation, + const glm::vec3& scale, bool cursor) { + if (!isLeaf()) { + glm::vec3 nextScale(scale.x * 0.5f, scale.y, scale.z * 0.5f); + glm::vec3 xOffset = rotation * glm::vec3(nextScale.x, 0.0f, 0.0f); + glm::vec3 zOffset = rotation * glm::vec3(0.0f, 0.0f, nextScale.z); + for (int i = 0; i < CHILD_COUNT; i++) { + _children[i]->render(translation + (i & X_MAXIMUM_FLAG ? xOffset : glm::vec3()) + + (i & Y_MAXIMUM_FLAG ? zOffset : glm::vec3()), rotation, nextScale, cursor); + } return; } - int width = heightfield->getHeight()->getWidth(); - int height = heightfield->getHeight()->getContents().size() / width; - + if (!_heightfieldNode->getHeight()) { + return; + } + int width = _heightfieldNode->getHeight()->getWidth(); + int height = _heightfieldNode->getHeight()->getContents().size() / width; int innerWidth = width - 2 * HeightfieldHeight::HEIGHT_BORDER; int innerHeight = height - 2 * HeightfieldHeight::HEIGHT_BORDER; int vertexCount = width * height; @@ -2180,17 +2190,71 @@ void HeightfieldRenderer::render(bool cursor) { bufferPair.second.allocate(indices.constData(), indexCount * sizeof(int)); bufferPair.second.release(); } + if (_heightTextureID == 0) { + glGenTextures(1, &_heightTextureID); + glBindTexture(GL_TEXTURE_2D, _heightTextureID); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + const QVector& heightContents = _heightfieldNode->getHeight()->getContents(); + glTexImage2D(GL_TEXTURE_2D, 0, GL_R16, width, height, 0, + GL_RED, GL_UNSIGNED_SHORT, heightContents.constData()); + + glGenTextures(1, &_colorTextureID); + glBindTexture(GL_TEXTURE_2D, _colorTextureID); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + if (_heightfieldNode->getColor()) { + const QByteArray& contents = _heightfieldNode->getColor()->getContents(); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, _heightfieldNode->getColor()->getWidth(), + contents.size() / (_heightfieldNode->getColor()->getWidth() * DataBlock::COLOR_BYTES), + 0, GL_RGB, GL_UNSIGNED_BYTE, contents.constData()); + + } else { + const quint8 WHITE_COLOR[] = { 255, 255, 255 }; + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, WHITE_COLOR); + } + + glGenTextures(1, &_materialTextureID); + glBindTexture(GL_TEXTURE_2D, _materialTextureID); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + if (_heightfieldNode->getMaterial()) { + const QByteArray& contents = _heightfieldNode->getMaterial()->getContents(); + glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, _heightfieldNode->getMaterial()->getWidth(), + contents.size() / _heightfieldNode->getMaterial()->getWidth(), + 0, GL_RED, GL_UNSIGNED_BYTE, contents.constData()); + + const QVector& materials = _heightfieldNode->getMaterial()->getMaterials(); + _networkTextures.resize(materials.size()); + for (int i = 0; i < materials.size(); i++) { + const SharedObjectPointer& material = materials.at(i); + if (material) { + _networkTextures[i] = Application::getInstance()->getTextureCache()->getTexture( + static_cast(material.data())->getDiffuse(), SPLAT_TEXTURE); + } + } + } else { + const quint8 ZERO_VALUE = 0; + glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, 1, 1, 0, GL_RED, GL_UNSIGNED_BYTE, &ZERO_VALUE); + } + glBindTexture(GL_TEXTURE_2D, 0); + } - float xScale = heightfield->getScale(), zScale = xScale * heightfield->getAspectZ(); if (cursor) { bufferPair.first.bind(); bufferPair.second.bind(); glPushMatrix(); - glTranslatef(heightfield->getTranslation().x, heightfield->getTranslation().y, heightfield->getTranslation().z); - glm::vec3 axis = glm::axis(heightfield->getRotation()); - glRotatef(glm::degrees(glm::angle(heightfield->getRotation())), axis.x, axis.y, axis.z); - glScalef(xScale, xScale * heightfield->getAspectY(), zScale); + glTranslatef(translation.x, translation.y, translation.z); + glm::vec3 axis = glm::axis(rotation); + glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z); + glScalef(scale.x, scale.y, scale.z); HeightfieldPoint* point = 0; glVertexPointer(3, GL_FLOAT, sizeof(HeightfieldPoint), &point->vertex); @@ -2208,13 +2272,12 @@ void HeightfieldRenderer::render(bool cursor) { bufferPair.second.release(); return; } - HeightfieldBaseLayerBatch baseBatch; baseBatch.vertexBuffer = &bufferPair.first; baseBatch.indexBuffer = &bufferPair.second; - baseBatch.translation = heightfield->getTranslation(); - baseBatch.rotation = heightfield->getRotation(); - baseBatch.scale = glm::vec3(xScale, xScale * heightfield->getAspectY(), zScale); + baseBatch.translation = translation; + baseBatch.rotation = rotation; + baseBatch.scale = scale; baseBatch.vertexCount = vertexCount; baseBatch.indexCount = indexCount; baseBatch.heightTextureID = _heightTextureID; @@ -2223,13 +2286,13 @@ void HeightfieldRenderer::render(bool cursor) { baseBatch.colorScale = glm::vec2((float)width / innerWidth, (float)height / innerHeight); Application::getInstance()->getMetavoxels()->addHeightfieldBaseBatch(baseBatch); - if (heightfield->getMaterial() && !_networkTextures.isEmpty()) { + if (!_networkTextures.isEmpty()) { HeightfieldSplatBatch splatBatch; splatBatch.vertexBuffer = &bufferPair.first; splatBatch.indexBuffer = &bufferPair.second; - splatBatch.translation = heightfield->getTranslation(); - splatBatch.rotation = heightfield->getRotation(); - splatBatch.scale = glm::vec3(xScale, xScale * heightfield->getAspectY(), zScale); + splatBatch.translation = translation; + splatBatch.rotation = rotation; + splatBatch.scale = scale; splatBatch.vertexCount = vertexCount; splatBatch.indexCount = indexCount; splatBatch.heightTextureID = _heightTextureID; @@ -2237,10 +2300,10 @@ void HeightfieldRenderer::render(bool cursor) { splatBatch.materialTextureID = _materialTextureID; splatBatch.textureScale = glm::vec2((float)width / innerWidth, (float)height / innerHeight); splatBatch.splatTextureOffset = glm::vec2( - glm::dot(heightfield->getTranslation(), heightfield->getRotation() * glm::vec3(1.0f, 0.0f, 0.0f)) / xScale, - glm::dot(heightfield->getTranslation(), heightfield->getRotation() * glm::vec3(0.0f, 0.0f, 1.0f)) / zScale); + glm::dot(translation, rotation * glm::vec3(1.0f, 0.0f, 0.0f)) / scale.x, + glm::dot(translation, rotation * glm::vec3(0.0f, 0.0f, 1.0f)) / scale.z); - const QVector& materials = heightfield->getMaterial()->getMaterials(); + const QVector& materials = _heightfieldNode->getMaterial()->getMaterials(); for (int i = 0; i < materials.size(); i += SPLAT_COUNT) { for (int j = 0; j < SPLAT_COUNT; j++) { int index = i + j; @@ -2248,8 +2311,8 @@ void HeightfieldRenderer::render(bool cursor) { const NetworkTexturePointer& texture = _networkTextures.at(index); if (texture) { MaterialObject* material = static_cast(materials.at(index).data()); - splatBatch.splatTextureScalesS[j] = xScale / material->getScaleS(); - splatBatch.splatTextureScalesT[j] = zScale / material->getScaleT(); + splatBatch.splatTextureScalesS[j] = scale.x / material->getScaleS(); + splatBatch.splatTextureScalesT[j] = scale.z / material->getScaleT(); splatBatch.splatTextureIDs[j] = texture->getID(); } else { @@ -2265,62 +2328,14 @@ void HeightfieldRenderer::render(bool cursor) { } } -void HeightfieldRenderer::applyHeight(const HeightfieldHeightPointer& height) { - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - glBindTexture(GL_TEXTURE_2D, _heightTextureID); - if (height) { - const QVector& contents = height->getContents(); - glTexImage2D(GL_TEXTURE_2D, 0, GL_R16, height->getWidth(), contents.size() / height->getWidth(), 0, - GL_RED, GL_UNSIGNED_SHORT, contents.constData()); - - } else { - const quint16 ZERO_VALUE = 0; - glTexImage2D(GL_TEXTURE_2D, 0, GL_R16, 1, 1, 0, GL_RED, GL_UNSIGNED_SHORT, &ZERO_VALUE); - } - glBindTexture(GL_TEXTURE_2D, 0); -} - -void HeightfieldRenderer::applyColor(const HeightfieldColorPointer& color) { - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - glBindTexture(GL_TEXTURE_2D, _colorTextureID); - if (color) { - const QByteArray& contents = color->getContents(); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, color->getWidth(), - contents.size() / (color->getWidth() * DataBlock::COLOR_BYTES), 0, GL_RGB, GL_UNSIGNED_BYTE, contents.constData()); - - } else { - const quint8 WHITE_COLOR[] = { 255, 255, 255 }; - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, WHITE_COLOR); - } - glBindTexture(GL_TEXTURE_2D, 0); -} - -void HeightfieldRenderer::applyMaterial(const HeightfieldMaterialPointer& material) { - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - glBindTexture(GL_TEXTURE_2D, _materialTextureID); - if (material) { - const QByteArray& contents = material->getContents(); - glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, material->getWidth(), contents.size() / material->getWidth(), 0, - GL_RED, GL_UNSIGNED_BYTE, contents.constData()); - - const QVector& materials = material->getMaterials(); - _networkTextures.resize(materials.size()); - for (int i = 0; i < materials.size(); i++) { - const SharedObjectPointer& material = materials.at(i); - if (material) { - _networkTextures[i] = Application::getInstance()->getTextureCache()->getTexture( - static_cast(material.data())->getDiffuse(), SPLAT_TEXTURE); - } else { - _networkTextures[i].clear(); - } +bool HeightfieldRendererNode::isLeaf() const { + for (int i = 0; i < CHILD_COUNT; i++) { + if (_children[i]) { + return false; } - } else { - const quint8 ZERO_VALUE = 0; - glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, 1, 1, 0, GL_RED, GL_UNSIGNED_BYTE, &ZERO_VALUE); - _networkTextures.clear(); } - glBindTexture(GL_TEXTURE_2D, 0); + return true; } -QHash HeightfieldRenderer::_bufferPairs; +QHash HeightfieldRendererNode::_bufferPairs; diff --git a/interface/src/MetavoxelSystem.h b/interface/src/MetavoxelSystem.h index c1cdfd3624..d7173e3cf0 100644 --- a/interface/src/MetavoxelSystem.h +++ b/interface/src/MetavoxelSystem.h @@ -24,6 +24,7 @@ #include "renderer/ProgramObject.h" class HeightfieldBaseLayerBatch; +class HeightfieldRendererNode; class HeightfieldSplatBatch; class Model; class VoxelBatch; @@ -419,6 +420,8 @@ private: Model* _model; }; +typedef QExplicitlySharedDataPointer HeightfieldRendererNodePointer; + /// Renders heightfields. class HeightfieldRenderer : public SpannerRenderer { Q_OBJECT @@ -426,26 +429,45 @@ class HeightfieldRenderer : public SpannerRenderer { public: Q_INVOKABLE HeightfieldRenderer(); - virtual ~HeightfieldRenderer(); virtual void init(Spanner* spanner); virtual void render(bool cursor = false); private slots: - void applyHeight(const HeightfieldHeightPointer& height); - void applyColor(const HeightfieldColorPointer& color); - void applyMaterial(const HeightfieldMaterialPointer& material); + void updateRoot(); private: + HeightfieldRendererNodePointer _root; +}; + +/// A node in the heightfield renderer quadtree. +class HeightfieldRendererNode : public QSharedData { +public: + + static const int CHILD_COUNT = 4; + + HeightfieldRendererNode(const HeightfieldNodePointer& heightfieldNode); + virtual ~HeightfieldRendererNode(); + + void render(const glm::vec3& translation, const glm::quat& rotation, const glm::vec3& scale, bool cursor = false); + +private: + + bool isLeaf() const; + + HeightfieldNodePointer _heightfieldNode; + + HeightfieldRendererNodePointer _children[CHILD_COUNT]; + GLuint _heightTextureID; GLuint _colorTextureID; GLuint _materialTextureID; QVector _networkTextures; - typedef QPair IntPair; - typedef QPair BufferPair; + typedef QPair IntPair; + typedef QPair BufferPair; static QHash _bufferPairs; }; diff --git a/libraries/metavoxels/src/Spanner.cpp b/libraries/metavoxels/src/Spanner.cpp index 07eb2d02a3..ce8aa7c928 100644 --- a/libraries/metavoxels/src/Spanner.cpp +++ b/libraries/metavoxels/src/Spanner.cpp @@ -1684,6 +1684,12 @@ void Heightfield::setMaterial(const HeightfieldMaterialPointer& material) { } } +void Heightfield::setRoot(const HeightfieldNodePointer& root) { + if (_root != root) { + emit rootChanged(_root = root); + } +} + bool Heightfield::isHeightfield() const { return true; } @@ -2667,8 +2673,10 @@ void Heightfield::readExtra(Bitstream& in) { } HeightfieldStreamBase base = { in, lod, lod }; HeightfieldStreamState state = { base, glm::vec2(), 1.0f }; - _root = new HeightfieldNode(); - _root->read(state); + + HeightfieldNodePointer root(new HeightfieldNode()); + root->read(state); + setRoot(root); } void Heightfield::writeExtraDelta(Bitstream& out, const SharedObject* reference) const { @@ -2705,11 +2713,12 @@ void Heightfield::readExtraDelta(Bitstream& in, const SharedObject* reference) { bool changed; in >> changed; if (changed) { - _root = new HeightfieldNode(); - _root->readDelta(static_cast(reference)->getRoot(), state); + HeightfieldNodePointer root(new HeightfieldNode()); + root->readDelta(static_cast(reference)->getRoot(), state); + setRoot(root); } else if (state.becameSubdividedOrCollapsed()) { - _root = _root->readSubdivision(state); + setRoot(HeightfieldNodePointer(_root->readSubdivision(state))); } } @@ -2724,10 +2733,11 @@ void Heightfield::updateBounds() { } void Heightfield::updateRoot() { - _root = new HeightfieldNode(); + HeightfieldNodePointer root(new HeightfieldNode()); if (_height) { - _root->setContents(_height, _color, _material); + root->setContents(_height, _color, _material); } + setRoot(root); } MetavoxelLOD Heightfield::transformLOD(const MetavoxelLOD& lod) const { diff --git a/libraries/metavoxels/src/Spanner.h b/libraries/metavoxels/src/Spanner.h index d67c23909d..e9ee43897a 100644 --- a/libraries/metavoxels/src/Spanner.h +++ b/libraries/metavoxels/src/Spanner.h @@ -540,6 +540,7 @@ class Heightfield : public Transformable { Q_PROPERTY(HeightfieldColorPointer color MEMBER _color WRITE setColor NOTIFY colorChanged STORED false) Q_PROPERTY(HeightfieldMaterialPointer material MEMBER _material WRITE setMaterial NOTIFY materialChanged STORED false DESIGNABLE false) + Q_PROPERTY(HeightfieldNodePointer root MEMBER _root WRITE setRoot NOTIFY rootChanged STORED false DESIGNABLE false) public: @@ -560,6 +561,7 @@ public: void setMaterial(const HeightfieldMaterialPointer& material); const HeightfieldMaterialPointer& getMaterial() const { return _material; } + void setRoot(const HeightfieldNodePointer& root); const HeightfieldNodePointer& getRoot() const { return _root; } virtual bool isHeightfield() const; @@ -596,6 +598,7 @@ signals: void heightChanged(const HeightfieldHeightPointer& height); void colorChanged(const HeightfieldColorPointer& color); void materialChanged(const HeightfieldMaterialPointer& material); + void rootChanged(const HeightfieldNodePointer& root); protected: From 0a329bbe3c35c9bb4e151700e5d3ace993a46f86 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 26 Nov 2014 16:18:57 -0800 Subject: [PATCH 110/502] More work on LOD rendering; now rendering in preview. --- interface/src/MetavoxelSystem.cpp | 130 +++++++++++++++------------ interface/src/MetavoxelSystem.h | 11 +-- interface/src/ui/MetavoxelEditor.cpp | 4 +- libraries/metavoxels/src/Spanner.cpp | 24 ++--- libraries/metavoxels/src/Spanner.h | 6 +- 5 files changed, 94 insertions(+), 81 deletions(-) diff --git a/interface/src/MetavoxelSystem.cpp b/interface/src/MetavoxelSystem.cpp index b8d1761297..a4d8c6ff37 100644 --- a/interface/src/MetavoxelSystem.cpp +++ b/interface/src/MetavoxelSystem.cpp @@ -550,10 +550,47 @@ void MetavoxelSystem::setVoxelMaterial(const SharedObjectPointer& spanner, const applyMaterialEdit(edit, true); } -class SpannerCursorRenderVisitor : public SpannerVisitor { +class SpannerRenderVisitor : public SpannerVisitor { public: - SpannerCursorRenderVisitor(const Box& bounds); + SpannerRenderVisitor(const MetavoxelLOD& lod); + + virtual int visit(MetavoxelInfo& info); + virtual bool visit(Spanner* spanner); + +protected: + + int _containmentDepth; +}; + +SpannerRenderVisitor::SpannerRenderVisitor(const MetavoxelLOD& lod) : + SpannerVisitor(QVector() << AttributeRegistry::getInstance()->getSpannersAttribute(), + QVector(), QVector(), lod, + encodeOrder(Application::getInstance()->getDisplayViewFrustum()->getDirection())), + _containmentDepth(INT_MAX) { +} + +int SpannerRenderVisitor::visit(MetavoxelInfo& info) { + if (_containmentDepth >= _depth) { + Frustum::IntersectionType intersection = Application::getInstance()->getMetavoxels()->getFrustum().getIntersectionType( + info.getBounds()); + if (intersection == Frustum::NO_INTERSECTION) { + return STOP_RECURSION; + } + _containmentDepth = (intersection == Frustum::CONTAINS_INTERSECTION) ? _depth : INT_MAX; + } + return SpannerVisitor::visit(info); +} + +bool SpannerRenderVisitor::visit(Spanner* spanner) { + spanner->getRenderer()->render(_lod, _containmentDepth <= _depth); + return true; +} + +class SpannerCursorRenderVisitor : public SpannerRenderVisitor { +public: + + SpannerCursorRenderVisitor(const MetavoxelLOD& lod, const Box& bounds); virtual bool visit(Spanner* spanner); @@ -564,20 +601,20 @@ private: Box _bounds; }; -SpannerCursorRenderVisitor::SpannerCursorRenderVisitor(const Box& bounds) : - SpannerVisitor(QVector() << AttributeRegistry::getInstance()->getSpannersAttribute()), +SpannerCursorRenderVisitor::SpannerCursorRenderVisitor(const MetavoxelLOD& lod, const Box& bounds) : + SpannerRenderVisitor(lod), _bounds(bounds) { } bool SpannerCursorRenderVisitor::visit(Spanner* spanner) { if (spanner->isHeightfield()) { - spanner->getRenderer()->render(true); + spanner->getRenderer()->render(_lod, _containmentDepth <= _depth, true); } return true; } int SpannerCursorRenderVisitor::visit(MetavoxelInfo& info) { - return info.getBounds().intersects(_bounds) ? SpannerVisitor::visit(info) : STOP_RECURSION; + return info.getBounds().intersects(_bounds) ? SpannerRenderVisitor::visit(info) : STOP_RECURSION; } void MetavoxelSystem::renderHeightfieldCursor(const glm::vec3& position, float radius) { @@ -604,7 +641,7 @@ void MetavoxelSystem::renderHeightfieldCursor(const glm::vec3& position, float r glActiveTexture(GL_TEXTURE0); glm::vec3 extents(radius, radius, radius); - SpannerCursorRenderVisitor visitor(Box(position - extents, position + extents)); + SpannerCursorRenderVisitor visitor(getLOD(), Box(position - extents, position + extents)); guide(visitor); _heightfieldCursorProgram.release(); @@ -678,7 +715,7 @@ void MetavoxelSystem::renderVoxelCursor(const glm::vec3& position, float radius) _heightfieldCursorProgram.bind(); - SpannerCursorRenderVisitor spannerVisitor(bounds); + SpannerCursorRenderVisitor spannerVisitor(getLOD(), bounds); guide(spannerVisitor); _heightfieldCursorProgram.release(); @@ -1880,43 +1917,6 @@ void DefaultMetavoxelRendererImplementation::simulate(MetavoxelData& data, float data.guide(spannerSimulateVisitor); } -class SpannerRenderVisitor : public SpannerVisitor { -public: - - SpannerRenderVisitor(const MetavoxelLOD& lod); - - virtual int visit(MetavoxelInfo& info); - virtual bool visit(Spanner* spanner); - -private: - - int _containmentDepth; -}; - -SpannerRenderVisitor::SpannerRenderVisitor(const MetavoxelLOD& lod) : - SpannerVisitor(QVector() << AttributeRegistry::getInstance()->getSpannersAttribute(), - QVector(), QVector(), lod, - encodeOrder(Application::getInstance()->getDisplayViewFrustum()->getDirection())), - _containmentDepth(INT_MAX) { -} - -int SpannerRenderVisitor::visit(MetavoxelInfo& info) { - if (_containmentDepth >= _depth) { - Frustum::IntersectionType intersection = Application::getInstance()->getMetavoxels()->getFrustum().getIntersectionType( - info.getBounds()); - if (intersection == Frustum::NO_INTERSECTION) { - return STOP_RECURSION; - } - _containmentDepth = (intersection == Frustum::CONTAINS_INTERSECTION) ? _depth : INT_MAX; - } - return SpannerVisitor::visit(info); -} - -bool SpannerRenderVisitor::visit(Spanner* spanner) { - spanner->getRenderer()->render(); - return true; -} - class BufferRenderVisitor : public MetavoxelVisitor { public: @@ -1970,7 +1970,7 @@ SphereRenderer::SphereRenderer() { } -void SphereRenderer::render(bool cursor) { +void SphereRenderer::render(const MetavoxelLOD& lod, bool contained, bool cursor) { Sphere* sphere = static_cast(_spanner); const QColor& color = sphere->getColor(); glColor4f(color.redF(), color.greenF(), color.blueF(), color.alphaF()); @@ -1990,7 +1990,7 @@ void SphereRenderer::render(bool cursor) { CuboidRenderer::CuboidRenderer() { } -void CuboidRenderer::render(bool cursor) { +void CuboidRenderer::render(const MetavoxelLOD& lod, bool contained, bool cursor) { Cuboid* cuboid = static_cast(_spanner); const QColor& color = cuboid->getColor(); glColor4f(color.redF(), color.greenF(), color.blueF(), color.alphaF()); @@ -2041,7 +2041,7 @@ void StaticModelRenderer::simulate(float deltaTime) { _model->simulate(deltaTime); } -void StaticModelRenderer::render(bool cursor) { +void StaticModelRenderer::render(const MetavoxelLOD& lod, bool contained, bool cursor) { _model->render(); } @@ -2083,10 +2083,9 @@ void HeightfieldRenderer::init(Spanner* spanner) { updateRoot(); } -void HeightfieldRenderer::render(bool cursor) { +void HeightfieldRenderer::render(const MetavoxelLOD& lod, bool contained, bool cursor) { Heightfield* heightfield = static_cast(_spanner); - _root->render(heightfield->getTranslation(), heightfield->getRotation(), glm::vec3(heightfield->getScale(), - heightfield->getScale() * heightfield->getAspectY(), heightfield->getScale() * heightfield->getAspectZ()), cursor); + _root->render(heightfield, heightfield->transformLOD(lod), glm::vec2(), 1.0f, contained, cursor); } void HeightfieldRenderer::updateRoot() { @@ -2117,15 +2116,28 @@ HeightfieldRendererNode::~HeightfieldRendererNode() { const int X_MAXIMUM_FLAG = 1; const int Y_MAXIMUM_FLAG = 2; -void HeightfieldRendererNode::render(const glm::vec3& translation, const glm::quat& rotation, - const glm::vec3& scale, bool cursor) { - if (!isLeaf()) { - glm::vec3 nextScale(scale.x * 0.5f, scale.y, scale.z * 0.5f); - glm::vec3 xOffset = rotation * glm::vec3(nextScale.x, 0.0f, 0.0f); - glm::vec3 zOffset = rotation * glm::vec3(0.0f, 0.0f, nextScale.z); +void HeightfieldRendererNode::render(Heightfield* heightfield, const MetavoxelLOD& lod, + const glm::vec2& minimum, float size, bool contained, bool cursor) { + const glm::quat& rotation = heightfield->getRotation(); + glm::vec3 scale(heightfield->getScale() * size, heightfield->getScale() * heightfield->getAspectY(), + heightfield->getScale() * heightfield->getAspectZ() * size); + glm::vec3 translation = heightfield->getTranslation() + rotation * glm::vec3(minimum.x * heightfield->getScale(), + 0.0f, minimum.y * heightfield->getScale() * heightfield->getAspectZ()); + if (!contained) { + Frustum::IntersectionType type = Application::getInstance()->getMetavoxels()->getFrustum().getIntersectionType( + glm::translate(translation) * glm::mat4_cast(rotation) * Box(glm::vec3(), scale)); + if (type == Frustum::NO_INTERSECTION) { + return; + } + if (type == Frustum::CONTAINS_INTERSECTION) { + contained = true; + } + } + if (!isLeaf() && lod.shouldSubdivide(minimum, size)) { + float nextSize = size * 0.5f; for (int i = 0; i < CHILD_COUNT; i++) { - _children[i]->render(translation + (i & X_MAXIMUM_FLAG ? xOffset : glm::vec3()) + - (i & Y_MAXIMUM_FLAG ? zOffset : glm::vec3()), rotation, nextScale, cursor); + _children[i]->render(heightfield, lod, minimum + glm::vec2(i & X_MAXIMUM_FLAG ? nextSize : 0.0f, + i & Y_MAXIMUM_FLAG ? nextSize : 0.0f), nextSize, contained, cursor); } return; } diff --git a/interface/src/MetavoxelSystem.h b/interface/src/MetavoxelSystem.h index d7173e3cf0..059ef27de4 100644 --- a/interface/src/MetavoxelSystem.h +++ b/interface/src/MetavoxelSystem.h @@ -381,7 +381,7 @@ public: Q_INVOKABLE SphereRenderer(); - virtual void render(bool cursor = false); + virtual void render(const MetavoxelLOD& lod = MetavoxelLOD(), bool contained = false, bool cursor = false); }; /// Renders cuboids. @@ -392,7 +392,7 @@ public: Q_INVOKABLE CuboidRenderer(); - virtual void render(bool cursor = false); + virtual void render(const MetavoxelLOD& lod = MetavoxelLOD(), bool contained = false, bool cursor = false); }; /// Renders static models. @@ -405,7 +405,7 @@ public: virtual void init(Spanner* spanner); virtual void simulate(float deltaTime); - virtual void render(bool cursor = false); + virtual void render(const MetavoxelLOD& lod = MetavoxelLOD(), bool contained = false, bool cursor = false); virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const; private slots: @@ -431,7 +431,7 @@ public: Q_INVOKABLE HeightfieldRenderer(); virtual void init(Spanner* spanner); - virtual void render(bool cursor = false); + virtual void render(const MetavoxelLOD& lod = MetavoxelLOD(), bool contained = false, bool cursor = false); private slots: @@ -451,7 +451,8 @@ public: HeightfieldRendererNode(const HeightfieldNodePointer& heightfieldNode); virtual ~HeightfieldRendererNode(); - void render(const glm::vec3& translation, const glm::quat& rotation, const glm::vec3& scale, bool cursor = false); + void render(Heightfield* heightfield, const MetavoxelLOD& lod, const glm::vec2& minimum, float size, + bool contained, bool cursor = false); private: diff --git a/interface/src/ui/MetavoxelEditor.cpp b/interface/src/ui/MetavoxelEditor.cpp index 65faa938e2..6d1e181907 100644 --- a/interface/src/ui/MetavoxelEditor.cpp +++ b/interface/src/ui/MetavoxelEditor.cpp @@ -634,7 +634,7 @@ void PlaceSpannerTool::simulate(float deltaTime) { void PlaceSpannerTool::renderPreview() { Spanner* spanner = static_cast(getSpanner().data()); - spanner->getRenderer()->render(); + spanner->getRenderer()->render(Application::getInstance()->getMetavoxels()->getLOD()); } bool PlaceSpannerTool::appliesTo(const AttributePointer& attribute) const { @@ -781,7 +781,7 @@ void ImportHeightfieldTool::simulate(float deltaTime) { } void ImportHeightfieldTool::renderPreview() { - static_cast(_spanner.data())->getRenderer()->render(); + static_cast(_spanner.data())->getRenderer()->render(Application::getInstance()->getMetavoxels()->getLOD()); } void ImportHeightfieldTool::apply() { diff --git a/libraries/metavoxels/src/Spanner.cpp b/libraries/metavoxels/src/Spanner.cpp index ce8aa7c928..608dbc77c2 100644 --- a/libraries/metavoxels/src/Spanner.cpp +++ b/libraries/metavoxels/src/Spanner.cpp @@ -168,7 +168,7 @@ void SpannerRenderer::simulate(float deltaTime) { // nothing by default } -void SpannerRenderer::render(bool cursor) { +void SpannerRenderer::render(const MetavoxelLOD& lod, bool contained, bool cursor) { // nothing by default } @@ -1573,10 +1573,10 @@ void HeightfieldNode::mergeChildren() { int quadrantColorHeight = innerQuadrantColorHeight + HeightfieldData::SHARED_EDGE; char* dest = colorContents.data() + ((i & Y_MAXIMUM_FLAG ? innerQuadrantColorHeight * colorWidth : 0) + (i & X_MAXIMUM_FLAG ? innerQuadrantColorWidth : 0)) * DataBlock::COLOR_BYTES; - const char* src = childColor->getContents().constData(); + const uchar* src = (const uchar*)childColor->getContents().constData(); for (int z = 0; z < quadrantColorHeight; z++, dest += colorWidth * DataBlock::COLOR_BYTES, src += colorWidth * DataBlock::COLOR_BYTES * 2) { - const char* lineSrc = src; + const uchar* lineSrc = src; for (char* lineDest = dest, *end = dest + quadrantColorWidth * DataBlock::COLOR_BYTES; lineDest != end; lineDest += DataBlock::COLOR_BYTES, lineSrc += DataBlock::COLOR_BYTES * 2) { lineDest[0] = lineSrc[0]; @@ -1690,6 +1690,15 @@ void Heightfield::setRoot(const HeightfieldNodePointer& root) { } } +MetavoxelLOD Heightfield::transformLOD(const MetavoxelLOD& lod) const { + // after transforming into unit space, we scale the threshold in proportion to vertical distance + glm::vec3 inverseScale(1.0f / getScale(), 1.0f / (getScale() * _aspectY), 1.0f / (getScale() * _aspectZ)); + glm::vec3 position = glm::inverse(getRotation()) * (lod.position - getTranslation()) * inverseScale; + const float THRESHOLD_MULTIPLIER = 256.0f; + return MetavoxelLOD(glm::vec3(position.x, position.z, 0.0f), lod.threshold * + qMax(0.5f, glm::abs(position.y * _aspectY - 0.5f)) * THRESHOLD_MULTIPLIER); +} + bool Heightfield::isHeightfield() const { return true; } @@ -2739,12 +2748,3 @@ void Heightfield::updateRoot() { } setRoot(root); } - -MetavoxelLOD Heightfield::transformLOD(const MetavoxelLOD& lod) const { - // after transforming into unit space, we scale the threshold in proportion to vertical distance - glm::vec3 inverseScale(1.0f / getScale(), 1.0f / (getScale() * _aspectY), 1.0f / (getScale() * _aspectZ)); - glm::vec3 position = glm::inverse(getRotation()) * (lod.position - getTranslation()) * inverseScale; - const float THRESHOLD_MULTIPLIER = 2.0f; - return MetavoxelLOD(glm::vec3(position.x, position.z, 0.0f), lod.threshold * - qMax(0.5f, glm::abs(position.y - 0.5f)) * THRESHOLD_MULTIPLIER); -} diff --git a/libraries/metavoxels/src/Spanner.h b/libraries/metavoxels/src/Spanner.h index e9ee43897a..0b24c7e318 100644 --- a/libraries/metavoxels/src/Spanner.h +++ b/libraries/metavoxels/src/Spanner.h @@ -134,7 +134,7 @@ public: virtual void init(Spanner* spanner); virtual void simulate(float deltaTime); - virtual void render(bool cursor = false); + virtual void render(const MetavoxelLOD& lod = MetavoxelLOD(), bool contained = false, bool cursor = false); virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const; protected: @@ -564,6 +564,8 @@ public: void setRoot(const HeightfieldNodePointer& root); const HeightfieldNodePointer& getRoot() const { return _root; } + MetavoxelLOD transformLOD(const MetavoxelLOD& lod) const; + virtual bool isHeightfield() const; virtual float getHeight(const glm::vec3& location) const; @@ -611,8 +613,6 @@ private slots: private: - MetavoxelLOD transformLOD(const MetavoxelLOD& lod) const; - float _aspectY; float _aspectZ; From 3781c23480816671f47769b55a5b8184fab2fd1d Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 26 Nov 2014 17:09:53 -0800 Subject: [PATCH 111/502] add entities to simulation after unpacking --- libraries/entities/src/EntityTree.cpp | 31 ++++++-------------- libraries/entities/src/EntityTree.h | 3 +- libraries/entities/src/EntityTreeElement.cpp | 2 +- 3 files changed, 11 insertions(+), 25 deletions(-) diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 5d4c5b0fc4..6ac3c31939 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -76,25 +76,14 @@ EntityItem* EntityTree::getOrCreateEntityItem(const EntityItemID& entityID, cons } /// Adds a new entity item to the tree -void EntityTree::addEntityItem(EntityItem* entityItem) { - // You should not call this on existing entities that are already part of the tree! Call updateEntity() - EntityItemID entityID = entityItem->getEntityItemID(); - EntityTreeElement* containingElement = getContainingElement(entityID); - if (containingElement) { - qDebug() << "UNEXPECTED!!!! don't call addEntityItem() on existing EntityItems. entityID=" << entityID; - return; - } - - // Recurse the tree and store the entity in the correct tree element - AddEntityOperator theOperator(this, entityItem); - recurseTreeWithOperator(&theOperator); - +void EntityTree::postAddEntity(EntityItem* entity) { + assert(entity); // check to see if we need to simulate this entity.. if (_simulation) { - _simulation->addEntity(entityItem); + _simulation->addEntity(entity); } - _isDirty = true; + emit addingEntity(entity->getEntityItemID()); } bool EntityTree::updateEntity(const EntityItemID& entityID, const EntityItemProperties& properties) { @@ -177,9 +166,11 @@ EntityItem* EntityTree::addEntity(const EntityItemID& entityID, const EntityItem result = EntityTypes::constructEntityItem(type, entityID, properties); if (result) { - // this does the actual adding of the entity - addEntityItem(result); - emitAddingEntity(entityID); + // Recurse the tree and store the entity in the correct tree element + AddEntityOperator theOperator(this, result); + recurseTreeWithOperator(&theOperator); + + postAddEntity(result); } return result; } @@ -199,10 +190,6 @@ void EntityTree::trackDeletedEntity(EntityItem* entity) { } } -void EntityTree::emitAddingEntity(const EntityItemID& entityItemID) { - emit addingEntity(entityItemID); -} - void EntityTree::emitEntityScriptChanging(const EntityItemID& entityItemID) { emit entityScriptChanging(entityItemID); } diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index db128e4563..5dccfd7709 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -79,7 +79,7 @@ public: // The newer API... EntityItem* getOrCreateEntityItem(const EntityItemID& entityID, const EntityItemProperties& properties); - void addEntityItem(EntityItem* entityItem); + void postAddEntity(EntityItem* entityItem); EntityItem* addEntity(const EntityItemID& entityID, const EntityItemProperties& properties); bool updateEntity(const EntityItemID& entityID, const EntityItemProperties& properties); @@ -142,7 +142,6 @@ public: void trackDeletedEntity(EntityItem* entity); - void emitAddingEntity(const EntityItemID& entityItemID); void emitEntityScriptChanging(const EntityItemID& entityItemID); void setSimulation(EntitySimulation* simulation); diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index 17f7456670..f0eeb40ede 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -768,7 +768,7 @@ int EntityTreeElement::readElementDataFromBuffer(const unsigned char* data, int addEntityItem(entityItem); // add this new entity to this elements entities entityItemID = entityItem->getEntityItemID(); _myTree->setContainingElement(entityItemID, this); - _myTree->emitAddingEntity(entityItemID); // we just added an entity + _myTree->postAddEntity(entityItem); } } // Move the buffer forward to read more entities From fe9fab68bfd6ea1c94d48a16bb5c29d09af4ff78 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 26 Nov 2014 17:30:59 -0800 Subject: [PATCH 112/502] don't exit app in full screen or hdm mode --- interface/src/Application.cpp | 1 + interface/src/ui/HMDToolsDialog.cpp | 103 ++++++++++++++++++---------- interface/src/ui/HMDToolsDialog.h | 4 ++ 3 files changed, 70 insertions(+), 38 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 397f883b3e..6791ae3d62 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -438,6 +438,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : void Application::aboutToQuit() { _aboutToQuit = true; + setFullscreen(false); // if you exit while in full screen, you'll get bad behavior when you restart. } Application::~Application() { diff --git a/interface/src/ui/HMDToolsDialog.cpp b/interface/src/ui/HMDToolsDialog.cpp index a5e54fa546..f2be62a026 100644 --- a/interface/src/ui/HMDToolsDialog.cpp +++ b/interface/src/ui/HMDToolsDialog.cpp @@ -30,7 +30,8 @@ HMDToolsDialog::HMDToolsDialog(QWidget* parent) : QDialog(parent, Qt::Window | Qt::WindowCloseButtonHint | Qt::WindowStaysOnTopHint) , _previousScreen(NULL), _hmdScreen(NULL), - _previousDialogScreen(NULL) + _previousDialogScreen(NULL), + _inHDMMode(false) { this->setWindowTitle("HMD Tools"); @@ -65,14 +66,18 @@ HMDToolsDialog::HMDToolsDialog(QWidget* parent) : QWindow* mainWindow = Application::getInstance()->getWindow()->windowHandle(); connect(mainWindow, &QWindow::screenChanged, this, &HMDToolsDialog::applicationWindowScreenChanged); - // watch for our dialog window moving screens. If it does we want to enforce our rules about what screens we're - // allowed on + // watch for our dialog window moving screens. If it does we want to enforce our rules about + // what screens we're allowed on QWindow* dialogWindow = windowHandle(); connect(dialogWindow, &QWindow::screenChanged, this, &HMDToolsDialog::dialogWindowScreenChanged); connect(dialogWindow, &QWindow::xChanged, this, &HMDToolsDialog::dialogWindowGeometryChanged); connect(dialogWindow, &QWindow::yChanged, this, &HMDToolsDialog::dialogWindowGeometryChanged); connect(dialogWindow, &QWindow::widthChanged, this, &HMDToolsDialog::dialogWindowGeometryChanged); connect(dialogWindow, &QWindow::heightChanged, this, &HMDToolsDialog::dialogWindowGeometryChanged); + + // when the application is about to quit, leave HDM mode + connect(Application::getInstance(), SIGNAL(aboutToQuit()), this, SLOT(aboutToQuit())); + } HMDToolsDialog::~HMDToolsDialog() { @@ -159,37 +164,45 @@ QString HMDToolsDialog::getDebugDetails() const { } void HMDToolsDialog::enterModeClicked(bool checked) { - _debugDetails->setText(getDebugDetails()); + enterHDMMode(); +} - int hmdScreen = OculusManager::getHMDScreen(); - qDebug() << "enterModeClicked().... hmdScreen:" << hmdScreen; +void HMDToolsDialog::enterHDMMode() { + if (!_inHDMMode) { + _debugDetails->setText(getDebugDetails()); + + int hmdScreen = OculusManager::getHMDScreen(); + qDebug() << "enterModeClicked().... hmdScreen:" << hmdScreen; - if (hmdScreen >= 0) { - QWindow* mainWindow = Application::getInstance()->getWindow()->windowHandle(); - _hmdScreen = QGuiApplication::screens()[hmdScreen]; + if (hmdScreen >= 0) { + QWindow* mainWindow = Application::getInstance()->getWindow()->windowHandle(); + _hmdScreen = QGuiApplication::screens()[hmdScreen]; - _previousRect = Application::getInstance()->getWindow()->rect(); - _previousRect = QRect(mainWindow->mapToGlobal(_previousRect.topLeft()), - mainWindow->mapToGlobal(_previousRect.bottomRight())); - _previousScreen = mainWindow->screen(); - QRect rect = QApplication::desktop()->screenGeometry(hmdScreen); - mainWindow->setScreen(_hmdScreen); - mainWindow->setGeometry(rect); + _previousRect = Application::getInstance()->getWindow()->rect(); + _previousRect = QRect(mainWindow->mapToGlobal(_previousRect.topLeft()), + mainWindow->mapToGlobal(_previousRect.bottomRight())); + _previousScreen = mainWindow->screen(); + QRect rect = QApplication::desktop()->screenGeometry(hmdScreen); + mainWindow->setScreen(_hmdScreen); + mainWindow->setGeometry(rect); - _wasMoved = true; - } + _wasMoved = true; + } - // if we're on a single screen setup, then hide our tools window when entering HMD mode - if (QApplication::desktop()->screenCount() == 1) { - close(); - } + // if we're on a single screen setup, then hide our tools window when entering HMD mode + if (QApplication::desktop()->screenCount() == 1) { + close(); + } - Application::getInstance()->setFullscreen(true); - Application::getInstance()->setEnableVRMode(true); + Application::getInstance()->setFullscreen(true); + Application::getInstance()->setEnableVRMode(true); - const int SLIGHT_DELAY = 500; - QTimer::singleShot(SLIGHT_DELAY, this, SLOT(activateWindowAfterEnterMode())); + const int SLIGHT_DELAY = 500; + QTimer::singleShot(SLIGHT_DELAY, this, SLOT(activateWindowAfterEnterMode())); + + _inHDMMode = true; + } } void HMDToolsDialog::activateWindowAfterEnterMode() { @@ -199,23 +212,30 @@ void HMDToolsDialog::activateWindowAfterEnterMode() { centerCursorOnWidget(Application::getInstance()->getWindow()); } - void HMDToolsDialog::leaveModeClicked(bool checked) { - _debugDetails->setText(getDebugDetails()); + leaveHDMMode(); +} - Application::getInstance()->setFullscreen(false); - Application::getInstance()->setEnableVRMode(false); - Application::getInstance()->getWindow()->activateWindow(); - if (_wasMoved) { - QWindow* mainWindow = Application::getInstance()->getWindow()->windowHandle(); - mainWindow->setScreen(_previousScreen); - mainWindow->setGeometry(_previousRect); +void HMDToolsDialog::leaveHDMMode() { + if (_inHDMMode) { + _debugDetails->setText(getDebugDetails()); + + Application::getInstance()->setFullscreen(false); + Application::getInstance()->setEnableVRMode(false); + Application::getInstance()->getWindow()->activateWindow(); + + if (_wasMoved) { + QWindow* mainWindow = Application::getInstance()->getWindow()->windowHandle(); + mainWindow->setScreen(_previousScreen); + mainWindow->setGeometry(_previousRect); - const int SLIGHT_DELAY = 1500; - QTimer::singleShot(SLIGHT_DELAY, this, SLOT(moveWindowAfterLeaveMode())); + const int SLIGHT_DELAY = 1500; + QTimer::singleShot(SLIGHT_DELAY, this, SLOT(moveWindowAfterLeaveMode())); + } + _wasMoved = false; + _inHDMMode = false; } - _wasMoved = false; } void HMDToolsDialog::moveWindowAfterLeaveMode() { @@ -256,3 +276,10 @@ void HMDToolsDialog::hideEvent(QHideEvent* event) { } +void HMDToolsDialog::aboutToQuit() { + if (_inHDMMode) { + leaveHDMMode(); + } +} + + diff --git a/interface/src/ui/HMDToolsDialog.h b/interface/src/ui/HMDToolsDialog.h index 4fe0dd626f..d2068d9e82 100644 --- a/interface/src/ui/HMDToolsDialog.h +++ b/interface/src/ui/HMDToolsDialog.h @@ -35,6 +35,7 @@ public slots: void applicationWindowScreenChanged(QScreen* screen); void dialogWindowScreenChanged(QScreen* screen); void dialogWindowGeometryChanged(int arg); + void aboutToQuit(); protected: virtual void closeEvent(QCloseEvent*); // Emits a 'closed' signal when this dialog is closed. @@ -43,6 +44,8 @@ protected: private: void centerCursorOnWidget(QWidget* widget); + void enterHDMMode(); + void leaveHDMMode(); bool _wasMoved; QRect _previousRect; @@ -52,6 +55,7 @@ private: QRect _previousDialogRect; QScreen* _previousDialogScreen; + bool _inHDMMode; }; #endif // hifi_HMDToolsDialog_h From 85ca03199ebafcd8f26091d8c87eb8c107d0413b Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 26 Nov 2014 17:53:41 -0800 Subject: [PATCH 113/502] remove Entities developer menu items from C++ menu, make them available through script --- examples/developerMenuItems.js | 37 ++++++++++++++++++++++++++++++++++ interface/src/Menu.cpp | 16 --------------- 2 files changed, 37 insertions(+), 16 deletions(-) create mode 100644 examples/developerMenuItems.js diff --git a/examples/developerMenuItems.js b/examples/developerMenuItems.js new file mode 100644 index 0000000000..221975c9c8 --- /dev/null +++ b/examples/developerMenuItems.js @@ -0,0 +1,37 @@ +// +// developerMenuItems.js +// examples +// +// Created by Brad Hefta-Gaub on 2/24/14 +// Copyright 2013 High Fidelity, Inc. +// +// Adds a bunch of developer and debugging menu items +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + + +function setupMenus() { + if (!Menu.menuExists("Developer")) { + Menu.addMenu("Developer"); + } + if (!Menu.menuExists("Developer > Entities")) { + Menu.addMenu("Developer > Entities"); + Menu.addMenuItem({ menuName: "Developer > Entities", menuItemName: "Display Model Bounds", isCheckable: true, isChecked: false }); + Menu.addMenuItem({ menuName: "Developer > Entities", menuItemName: "Display Model Element Bounds", isCheckable: true, isChecked: false }); + Menu.addMenuItem({ menuName: "Developer > Entities", menuItemName: "Display Model Element Children", isCheckable: true, isChecked: false }); + Menu.addMenuItem({ menuName: "Developer > Entities", menuItemName: "Disable Light Entities", isCheckable: true, isChecked: false }); + Menu.addMenuItem({ menuName: "Developer > Entities", menuItemName: "Don't Attempt to Reduce Material Switches", isCheckable: true, isChecked: false }); + Menu.addMenuItem({ menuName: "Developer > Entities", menuItemName: "Don't Attempt Render Entities as Scene", isCheckable: true, isChecked: false }); + Menu.addMenu("Developer > Entities > Culling"); + Menu.addMenuItem({ menuName: "Developer > Entities > Culling", menuItemName: "Don't Cull Out Of View Mesh Parts", isCheckable: true, isChecked: false }); + Menu.addMenuItem({ menuName: "Developer > Entities > Culling", menuItemName: "Don't Cull Too Small Mesh Parts", isCheckable: true, isChecked: false }); + } +} + +function scriptEnding() { + Menu.removeMenu("Developer > Entities"); +} +setupMenus(); +Script.scriptEnding.connect(scriptEnding); diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 2c7b4a9efd..6cfb3db35a 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -445,23 +445,7 @@ Menu::Menu() : addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::RenderBoundingCollisionShapes); addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::RenderLookAtVectors, 0, false); addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::RenderFocusIndicator, 0, false); - - QMenu* entitiesDebugMenu = developerMenu->addMenu("Entities"); - addCheckableActionToQMenuAndActionHash(entitiesDebugMenu, MenuOption::DisplayModelBounds, 0, false); - addCheckableActionToQMenuAndActionHash(entitiesDebugMenu, MenuOption::DisplayModelElementProxy, 0, false); - addCheckableActionToQMenuAndActionHash(entitiesDebugMenu, MenuOption::DisplayModelElementChildProxies, 0, false); - addCheckableActionToQMenuAndActionHash(entitiesDebugMenu, MenuOption::DisableLightEntities, 0, false); - addCheckableActionToQMenuAndActionHash(entitiesDebugMenu, MenuOption::DontReduceMaterialSwitches, 0, false); - addCheckableActionToQMenuAndActionHash(entitiesDebugMenu, MenuOption::DontRenderEntitiesAsScene, 0, false); - - QMenu* entityCullingMenu = entitiesDebugMenu->addMenu("Culling"); - addCheckableActionToQMenuAndActionHash(entityCullingMenu, MenuOption::DontCullOutOfViewMeshParts, 0, false); - addCheckableActionToQMenuAndActionHash(entityCullingMenu, MenuOption::DontCullTooSmallMeshParts, 0, false); - - - - QMenu* voxelOptionsMenu = developerMenu->addMenu("Voxels"); addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::VoxelTextures); addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::AmbientOcclusion); From 6be18109679874eeb5b0f2a765cca786203c54ba Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 26 Nov 2014 17:57:03 -0800 Subject: [PATCH 114/502] More work on subdivision. --- libraries/metavoxels/src/SharedObject.cpp | 8 ++++++ libraries/metavoxels/src/SharedObject.h | 6 +++++ libraries/metavoxels/src/Spanner.cpp | 31 +++++++++++++++++++++++ libraries/metavoxels/src/Spanner.h | 2 ++ 4 files changed, 47 insertions(+) diff --git a/libraries/metavoxels/src/SharedObject.cpp b/libraries/metavoxels/src/SharedObject.cpp index e57b7d9a8e..8f57c8be34 100644 --- a/libraries/metavoxels/src/SharedObject.cpp +++ b/libraries/metavoxels/src/SharedObject.cpp @@ -147,6 +147,14 @@ void SharedObject::readExtraDelta(Bitstream& in, const SharedObject* reference) // nothing by default } +void SharedObject::writeExtraSubdivision(Bitstream& out) { + // nothing by default +} + +void SharedObject::readExtraSubdivision(Bitstream& in) { + // nothing by default +} + QAtomicInt SharedObject::_nextID(1); WeakSharedObjectHash SharedObject::_weakHash; QReadWriteLock SharedObject::_weakHashLock; diff --git a/libraries/metavoxels/src/SharedObject.h b/libraries/metavoxels/src/SharedObject.h index 7f44ffec82..f35fde802c 100644 --- a/libraries/metavoxels/src/SharedObject.h +++ b/libraries/metavoxels/src/SharedObject.h @@ -92,6 +92,12 @@ public: /// Reads the delta-encoded non-property contents of this object from the specified stream. virtual void readExtraDelta(Bitstream& in, const SharedObject* reference); + /// Writes the subdivision of the non-property contents of this object to the specified stream. + virtual void writeExtraSubdivision(Bitstream& out); + + /// Reads the subdivision of the non-property contents of this object from the specified stream. + virtual void readExtraSubdivision(Bitstream& in); + private: int _id; diff --git a/libraries/metavoxels/src/Spanner.cpp b/libraries/metavoxels/src/Spanner.cpp index 608dbc77c2..bdccb18b7e 100644 --- a/libraries/metavoxels/src/Spanner.cpp +++ b/libraries/metavoxels/src/Spanner.cpp @@ -2731,6 +2731,37 @@ void Heightfield::readExtraDelta(Bitstream& in, const SharedObject* reference) { } } +void Heightfield::writeExtraSubdivision(Bitstream& out) { + MetavoxelLOD lod, referenceLOD; + if (out.getContext()) { + MetavoxelStreamBase* base = static_cast(out.getContext()); + lod = transformLOD(base->lod); + referenceLOD = transformLOD(base->referenceLOD); + } + HeightfieldStreamBase base = { out, lod, referenceLOD }; + HeightfieldStreamState state = { base, glm::vec2(), 1.0f }; + + if (state.becameSubdivided()) { + out << SharedObjectPointer(this); + _root->writeSubdivision(state); + } +} + +void Heightfield::readExtraSubdivision(Bitstream& in) { + MetavoxelLOD lod, referenceLOD; + if (in.getContext()) { + MetavoxelStreamBase* base = static_cast(in.getContext()); + lod = transformLOD(base->lod); + referenceLOD = transformLOD(base->referenceLOD); + } + HeightfieldStreamBase base = { in, lod, referenceLOD }; + HeightfieldStreamState state = { base, glm::vec2(), 1.0f }; + + if (state.becameSubdividedOrCollapsed()) { + setRoot(HeightfieldNodePointer(_root->readSubdivision(state))); + } +} + QByteArray Heightfield::getRendererClassName() const { return "HeightfieldRenderer"; } diff --git a/libraries/metavoxels/src/Spanner.h b/libraries/metavoxels/src/Spanner.h index 0b24c7e318..c832d3fbd5 100644 --- a/libraries/metavoxels/src/Spanner.h +++ b/libraries/metavoxels/src/Spanner.h @@ -592,6 +592,8 @@ public: virtual void readExtra(Bitstream& in); virtual void writeExtraDelta(Bitstream& out, const SharedObject* reference) const; virtual void readExtraDelta(Bitstream& in, const SharedObject* reference); + virtual void writeExtraSubdivision(Bitstream& out); + virtual void readExtraSubdivision(Bitstream& in); signals: From 184acaedefa7e5ff8b7aecb520529ec8f982dc7e Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 26 Nov 2014 19:43:01 -0800 Subject: [PATCH 115/502] switch to single button for mode switching --- interface/src/ui/HMDToolsDialog.cpp | 31 ++++++++++++++--------------- interface/src/ui/HMDToolsDialog.h | 4 ++-- 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/interface/src/ui/HMDToolsDialog.cpp b/interface/src/ui/HMDToolsDialog.cpp index f2be62a026..d7cb5b4756 100644 --- a/interface/src/ui/HMDToolsDialog.cpp +++ b/interface/src/ui/HMDToolsDialog.cpp @@ -28,6 +28,8 @@ HMDToolsDialog::HMDToolsDialog(QWidget* parent) : QDialog(parent, Qt::Window | Qt::WindowCloseButtonHint | Qt::WindowStaysOnTopHint) , + _switchModeButton(NULL), + _debugDetails(NULL), _previousScreen(NULL), _hmdScreen(NULL), _previousDialogScreen(NULL), @@ -37,21 +39,17 @@ HMDToolsDialog::HMDToolsDialog(QWidget* parent) : // Create layouter QFormLayout* form = new QFormLayout(); + const int WIDTH = 350; // Add a button to enter - QPushButton* enterModeButton = new QPushButton("Enter HMD Mode"); - form->addRow("", enterModeButton); - connect(enterModeButton,SIGNAL(clicked(bool)),this,SLOT(enterModeClicked(bool))); - - // Add a button to leave - QPushButton* leaveModeButton = new QPushButton("Leave HMD Mode"); - form->addRow("", leaveModeButton); - connect(leaveModeButton,SIGNAL(clicked(bool)),this,SLOT(leaveModeClicked(bool))); + _switchModeButton = new QPushButton("Enter HMD Mode"); + _switchModeButton->setFixedWidth(WIDTH); + form->addRow("", _switchModeButton); + connect(_switchModeButton,SIGNAL(clicked(bool)),this,SLOT(switchModeClicked(bool))); // Create a label with debug details... _debugDetails = new QLabel(); _debugDetails->setText(getDebugDetails()); - const int WIDTH = 350; const int HEIGHT = 100; _debugDetails->setFixedSize(WIDTH, HEIGHT); form->addRow("", _debugDetails); @@ -163,12 +161,17 @@ QString HMDToolsDialog::getDebugDetails() const { return results; } -void HMDToolsDialog::enterModeClicked(bool checked) { - enterHDMMode(); +void HMDToolsDialog::switchModeClicked(bool checked) { + if (!_inHDMMode) { + enterHDMMode(); + } else { + leaveHDMMode(); + } } void HMDToolsDialog::enterHDMMode() { if (!_inHDMMode) { + _switchModeButton->setText("Leave HMD Mode"); _debugDetails->setText(getDebugDetails()); int hmdScreen = OculusManager::getHMDScreen(); @@ -212,13 +215,9 @@ void HMDToolsDialog::activateWindowAfterEnterMode() { centerCursorOnWidget(Application::getInstance()->getWindow()); } -void HMDToolsDialog::leaveModeClicked(bool checked) { - leaveHDMMode(); -} - - void HMDToolsDialog::leaveHDMMode() { if (_inHDMMode) { + _switchModeButton->setText("Enter HMD Mode"); _debugDetails->setText(getDebugDetails()); Application::getInstance()->setFullscreen(false); diff --git a/interface/src/ui/HMDToolsDialog.h b/interface/src/ui/HMDToolsDialog.h index d2068d9e82..91db300224 100644 --- a/interface/src/ui/HMDToolsDialog.h +++ b/interface/src/ui/HMDToolsDialog.h @@ -28,8 +28,7 @@ signals: public slots: void reject(); - void enterModeClicked(bool checked); - void leaveModeClicked(bool checked); + void switchModeClicked(bool checked); void activateWindowAfterEnterMode(); void moveWindowAfterLeaveMode(); void applicationWindowScreenChanged(QScreen* screen); @@ -51,6 +50,7 @@ private: QRect _previousRect; QScreen* _previousScreen; QScreen* _hmdScreen; + QPushButton* _switchModeButton; QLabel* _debugDetails; QRect _previousDialogRect; From 39042f61cd8a535d0afb7e87e2110230d8824508 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Wed, 26 Nov 2014 19:57:18 -0800 Subject: [PATCH 116/502] 1P mirror can lean fwd/back --- interface/src/Application.cpp | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 58b28fcef9..a1f374c3c6 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -650,20 +650,11 @@ void Application::paintGL() { } } else if (_myCamera.getMode() == CAMERA_MODE_MIRROR) { - //Only behave like a true mirror when in the OR - if (OculusManager::isConnected()) { - _myCamera.setRotation(_myAvatar->getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f))); - _myCamera.setPosition(_myAvatar->getHead()->getEyePosition() + - glm::vec3(0, _raiseMirror * _myAvatar->getScale(), 0) + - (_myAvatar->getOrientation() * glm::quat(glm::vec3(0.0f, _rotateMirror, 0.0f))) * - glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_FULLSCREEN_DISTANCE * _scaleMirror); - } else { - _myCamera.setRotation(_myAvatar->getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f))); - _myCamera.setPosition(_myAvatar->getHead()->getEyePosition() + - glm::vec3(0, _raiseMirror * _myAvatar->getScale(), 0) + - (_myAvatar->getOrientation() * glm::quat(glm::vec3(0.0f, _rotateMirror, 0.0f))) * - glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_FULLSCREEN_DISTANCE * _scaleMirror); - } + _myCamera.setRotation(_myAvatar->getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f))); + _myCamera.setPosition(_myAvatar->getDefaultEyePosition() + + glm::vec3(0, _raiseMirror * _myAvatar->getScale(), 0) + + (_myAvatar->getOrientation() * glm::quat(glm::vec3(0.0f, _rotateMirror, 0.0f))) * + glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_FULLSCREEN_DISTANCE * _scaleMirror); } // Update camera position From fe010b685a6a9ccf71348986ce85e5605ba145c5 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 26 Nov 2014 20:19:23 -0800 Subject: [PATCH 117/502] more HMD Tools improvements, better support for detecting adding/removing screens --- interface/src/ui/HMDToolsDialog.cpp | 47 ++++++++++++++++++++++------- interface/src/ui/HMDToolsDialog.h | 6 ++-- 2 files changed, 40 insertions(+), 13 deletions(-) diff --git a/interface/src/ui/HMDToolsDialog.cpp b/interface/src/ui/HMDToolsDialog.cpp index d7cb5b4756..88924f68d1 100644 --- a/interface/src/ui/HMDToolsDialog.cpp +++ b/interface/src/ui/HMDToolsDialog.cpp @@ -28,10 +28,11 @@ HMDToolsDialog::HMDToolsDialog(QWidget* parent) : QDialog(parent, Qt::Window | Qt::WindowCloseButtonHint | Qt::WindowStaysOnTopHint) , - _switchModeButton(NULL), - _debugDetails(NULL), _previousScreen(NULL), _hmdScreen(NULL), + _hmdScreenNumber(-1), + _switchModeButton(NULL), + _debugDetails(NULL), _previousDialogScreen(NULL), _inHDMMode(false) { @@ -75,6 +76,9 @@ HMDToolsDialog::HMDToolsDialog(QWidget* parent) : // when the application is about to quit, leave HDM mode connect(Application::getInstance(), SIGNAL(aboutToQuit()), this, SLOT(aboutToQuit())); + + // keep track of changes to the number of screens + connect(QApplication::desktop(), &QDesktopWidget::screenCountChanged, this, &HMDToolsDialog::screenCountChanged); } @@ -99,11 +103,11 @@ void HMDToolsDialog::dialogWindowScreenChanged(QScreen* screen) { // if we have more than one screen, and a known hmdScreen then try to // keep our dialog off of the hmdScreen if (QApplication::desktop()->screenCount() > 1) { - int hmdScreenNumber = OculusManager::getHMDScreen(); - - if (hmdScreenNumber >= 0) { - QScreen* hmdScreen = QGuiApplication::screens()[hmdScreenNumber]; + // we want to use a local variable here because we are not necesarily in HMD mode + int hmdScreenNumber = OculusManager::getHMDScreen(); + if (_hmdScreenNumber >= 0) { + QScreen* hmdScreen = QGuiApplication::screens()[hmdScreenNumber]; if (screen == hmdScreen) { qDebug() << "HMD Tools: Whoa! What are you doing? You don't want to move me to the HMD Screen!"; QWindow* dialogWindow = windowHandle(); @@ -157,6 +161,7 @@ QString HMDToolsDialog::getDebugDetails() const { results += "Application Primary Screen: " + QGuiApplication::primaryScreen()->name() + "\n"; QScreen* mainWindowScreen = Application::getInstance()->getWindow()->windowHandle()->screen(); results += "Application Main Window Screen: " + mainWindowScreen->name() + "\n"; + results += "Total Screens: " + QString::number(QApplication::desktop()->screenCount()) + "\n"; return results; } @@ -174,18 +179,17 @@ void HMDToolsDialog::enterHDMMode() { _switchModeButton->setText("Leave HMD Mode"); _debugDetails->setText(getDebugDetails()); - int hmdScreen = OculusManager::getHMDScreen(); - qDebug() << "enterModeClicked().... hmdScreen:" << hmdScreen; + _hmdScreenNumber = OculusManager::getHMDScreen(); - if (hmdScreen >= 0) { + if (_hmdScreenNumber >= 0) { QWindow* mainWindow = Application::getInstance()->getWindow()->windowHandle(); - _hmdScreen = QGuiApplication::screens()[hmdScreen]; + _hmdScreen = QGuiApplication::screens()[_hmdScreenNumber]; _previousRect = Application::getInstance()->getWindow()->rect(); _previousRect = QRect(mainWindow->mapToGlobal(_previousRect.topLeft()), mainWindow->mapToGlobal(_previousRect.bottomRight())); _previousScreen = mainWindow->screen(); - QRect rect = QApplication::desktop()->screenGeometry(hmdScreen); + QRect rect = QApplication::desktop()->screenGeometry(_hmdScreenNumber); mainWindow->setScreen(_hmdScreen); mainWindow->setGeometry(rect); @@ -281,4 +285,25 @@ void HMDToolsDialog::aboutToQuit() { } } +void HMDToolsDialog::screenCountChanged(int newCount) { + if (!OculusManager::isConnected()) { + OculusManager::connect(); + } + int hmdScreenNumber = OculusManager::getHMDScreen(); + + if (_inHDMMode && _hmdScreenNumber != hmdScreenNumber) { + qDebug() << "HMD Display changed WHILE IN HMD MODE"; + leaveHDMMode(); + + // if there is a new best HDM screen then go back into HDM mode after done leaving + if (hmdScreenNumber >= 0) { + qDebug() << "Trying to go back into HDM Mode"; + const int SLIGHT_DELAY = 2000; + QTimer::singleShot(SLIGHT_DELAY, this, SLOT(enterHDMMode())); + } + } + _debugDetails->setText(getDebugDetails()); +} + + diff --git a/interface/src/ui/HMDToolsDialog.h b/interface/src/ui/HMDToolsDialog.h index 91db300224..e3e5573533 100644 --- a/interface/src/ui/HMDToolsDialog.h +++ b/interface/src/ui/HMDToolsDialog.h @@ -34,8 +34,9 @@ public slots: void applicationWindowScreenChanged(QScreen* screen); void dialogWindowScreenChanged(QScreen* screen); void dialogWindowGeometryChanged(int arg); - void aboutToQuit(); - + void aboutToQuit(); + void screenCountChanged(int newCount); + protected: virtual void closeEvent(QCloseEvent*); // Emits a 'closed' signal when this dialog is closed. virtual void showEvent(QShowEvent* event); @@ -50,6 +51,7 @@ private: QRect _previousRect; QScreen* _previousScreen; QScreen* _hmdScreen; + int _hmdScreenNumber; QPushButton* _switchModeButton; QLabel* _debugDetails; From c78af1c982f3f891ca413b7c9f2058ee4e1f8740 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 27 Nov 2014 10:48:36 -0800 Subject: [PATCH 118/502] fixing the bug when lighmaps are diasppearing in the , i don;t understand why --- interface/src/renderer/Model.cpp | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 2e17cc2605..b2570b7c28 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -2381,24 +2381,27 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod GLBATCH(glActiveTexture)(GL_TEXTURE0); } - if (locations->emissiveTextureUnit >= 0) { - // assert(locations->emissiveParams >= 0); // we should have the emissiveParams defined in the shader - float emissiveOffset = part.emissiveParams.x; - float emissiveScale = part.emissiveParams.y; - GLBATCH(glUniform2f)(locations->emissiveParams, emissiveOffset, emissiveScale); - - GLBATCH(glActiveTexture)(GL_TEXTURE0 + locations->emissiveTextureUnit); - Texture* emissiveMap = networkPart.emissiveTexture.data(); - GLBATCH(glBindTexture)(GL_TEXTURE_2D, !emissiveMap ? - Application::getInstance()->getTextureCache()->getWhiteTextureID() : emissiveMap->getID()); - GLBATCH(glActiveTexture)(GL_TEXTURE0); - } - if (args) { args->_materialSwitches++; } } + + // HACK: For unkwon reason (yet!) this code that should be assigned only if the material changes need to be called for every + // drawcall with an emissive, so let's do it for now. + if (locations->emissiveTextureUnit >= 0) { + // assert(locations->emissiveParams >= 0); // we should have the emissiveParams defined in the shader + float emissiveOffset = part.emissiveParams.x; + float emissiveScale = part.emissiveParams.y; + GLBATCH(glUniform2f)(locations->emissiveParams, emissiveOffset, emissiveScale); + + GLBATCH(glActiveTexture)(GL_TEXTURE0 + locations->emissiveTextureUnit); + Texture* emissiveMap = networkPart.emissiveTexture.data(); + GLBATCH(glBindTexture)(GL_TEXTURE_2D, !emissiveMap ? + Application::getInstance()->getTextureCache()->getWhiteTextureID() : emissiveMap->getID()); + GLBATCH(glActiveTexture)(GL_TEXTURE0); + } + lastMaterialID = part.materialID; } From 583e079d3a1f3650e7fb063f308f86848adaa97e Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 28 Nov 2014 10:01:15 -0800 Subject: [PATCH 119/502] Fix Hydra cursors in VR display They weren't being drawn at the correct location an so weren't matching up with location of voxel being added or deleted, for example. --- interface/src/devices/SixenseManager.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/interface/src/devices/SixenseManager.cpp b/interface/src/devices/SixenseManager.cpp index d636f8929c..6d227027ed 100644 --- a/interface/src/devices/SixenseManager.cpp +++ b/interface/src/devices/SixenseManager.cpp @@ -477,7 +477,8 @@ void SixenseManager::emulateMouse(PalmData* palm, int index) { triggerButton = Qt::LeftButton; } - if (Menu::getInstance()->isOptionChecked(MenuOption::SixenseLasers)) { + if (Menu::getInstance()->isOptionChecked(MenuOption::SixenseLasers) + || Menu::getInstance()->isOptionChecked(MenuOption::EnableVRMode)) { pos = application->getApplicationOverlay().getPalmClickLocation(palm); } else { // Get directon relative to avatar orientation From 5c2cc20313e14757e14399051dd814846b543b7f Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 28 Nov 2014 17:36:55 -0800 Subject: [PATCH 120/502] fixes the stutter in animation when observer moves --- interface/src/renderer/AnimationHandle.cpp | 8 +++----- libraries/animation/src/AnimationLoop.cpp | 5 +++-- libraries/animation/src/AnimationLoop.h | 4 ++++ libraries/entities/src/ModelEntityItem.cpp | 4 +++- 4 files changed, 13 insertions(+), 8 deletions(-) diff --git a/interface/src/renderer/AnimationHandle.cpp b/interface/src/renderer/AnimationHandle.cpp index 767f941049..89c265875b 100644 --- a/interface/src/renderer/AnimationHandle.cpp +++ b/interface/src/renderer/AnimationHandle.cpp @@ -138,11 +138,9 @@ void AnimationHandle::simulate(float deltaTime) { return; } - // TODO: When moving the loop/frame calculations to AnimationLoop class, we changed this behavior - // see AnimationLoop class for more details. Do we need to support clamping the endFrameIndex to - // the max number of frames in the geometry??? - // - // float endFrameIndex = qMin(_lastFrame, animationGeometry.animationFrames.size() - (_loop ? 0.0f : 1.0f)); + if (_animationLoop.getMaxFrameIndexHint() != animationGeometry.animationFrames.size()) { + _animationLoop.setMaxFrameIndexHint(animationGeometry.animationFrames.size()); + } // blend between the closest two frames applyFrame(getFrameIndex()); diff --git a/libraries/animation/src/AnimationLoop.cpp b/libraries/animation/src/AnimationLoop.cpp index f81904990f..75a3cdd338 100644 --- a/libraries/animation/src/AnimationLoop.cpp +++ b/libraries/animation/src/AnimationLoop.cpp @@ -20,7 +20,8 @@ AnimationLoop::AnimationLoop() : _firstFrame(0.0f), _lastFrame(FLT_MAX), _running(false), - _frameIndex(0.0f) + _frameIndex(0.0f), + _maxFrameIndexHint(FLT_MAX) { } @@ -55,7 +56,7 @@ void AnimationLoop::simulate(float deltaTime) { // If we knew the number of frames from the animation, we'd consider using it here // animationGeometry.animationFrames.size() - float maxFrame = _lastFrame; + float maxFrame = _maxFrameIndexHint; float endFrameIndex = qMin(_lastFrame, maxFrame - (_loop ? 0.0f : 1.0f)); float startFrameIndex = qMin(_firstFrame, endFrameIndex); if ((!_loop && (_frameIndex < startFrameIndex || _frameIndex > endFrameIndex)) || startFrameIndex == endFrameIndex) { diff --git a/libraries/animation/src/AnimationLoop.h b/libraries/animation/src/AnimationLoop.h index b56f68f23b..aff2cd86ee 100644 --- a/libraries/animation/src/AnimationLoop.h +++ b/libraries/animation/src/AnimationLoop.h @@ -44,6 +44,9 @@ public: void setFrameIndex(float frameIndex) { _frameIndex = glm::clamp(frameIndex, _firstFrame, _lastFrame); } float getFrameIndex() const { return _frameIndex; } + + void setMaxFrameIndexHint(float value) { _maxFrameIndexHint = value; } + float getMaxFrameIndexHint() const { return _maxFrameIndexHint; } void start() { setRunning(true); } void stop() { setRunning(false); } @@ -58,6 +61,7 @@ private: float _lastFrame; bool _running; float _frameIndex; + float _maxFrameIndexHint; }; #endif // hifi_AnimationLoop_h diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index 31a0c57f5b..63fe3daa03 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -344,7 +344,9 @@ QVector ModelEntityItem::getAnimationFrame() { Animation* myAnimation = getAnimation(_animationURL); QVector frames = myAnimation->getFrames(); int frameCount = frames.size(); - + if (_animationLoop.getMaxFrameIndexHint() != frameCount) { + _animationLoop.setMaxFrameIndexHint(frameCount); + } if (frameCount > 0) { int animationFrameIndex = (int)(glm::floor(getAnimationFrameIndex())) % frameCount; if (animationFrameIndex < 0 || animationFrameIndex > frameCount) { From 709a40516d5ffcc2e3fc5b25c152f8ba3e91c970 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Sat, 29 Nov 2014 12:17:38 -0800 Subject: [PATCH 121/502] Add auto-turn of body when head is beyond 45 degrees --- examples/headMove.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/examples/headMove.js b/examples/headMove.js index df5c858b46..4d2e4ded07 100644 --- a/examples/headMove.js +++ b/examples/headMove.js @@ -19,6 +19,7 @@ var warpPosition = { x: 0, y: 0, z: 0 }; var hipsToEyes; var restoreCountdownTimer; +var headTurningTimer = 0.0; // Overlays to show target location @@ -168,6 +169,20 @@ function update(deltaTime) { restoreCountDownTimer = 0.0; } } + var HEAD_TURN_TIME = 0.10; + var HEAD_TURN_DEGREES = 4.0; + var HEAD_TURN_START_ANGLE = 45.0; + var currentYaw = MyAvatar.getHeadFinalYaw(); + if (Math.abs(currentYaw) > HEAD_TURN_START_ANGLE) { + headTurningTimer += deltaTime; + if (headTurningTimer > HEAD_TURN_TIME) { + headTurningTimer = 0.0; + MyAvatar.orientation = Quat.multiply(Quat.fromPitchYawRollDegrees(0, (currentYaw > 0) ? HEAD_TURN_DEGREES: -HEAD_TURN_DEGREES, 0), + MyAvatar.orientation); + } + } else { + headTurningTimer = 0.0; + } } Controller.keyPressEvent.connect(function(event) { From 321d651d77fe0c8927e003c08715020de8928765 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Sun, 30 Nov 2014 12:54:43 -0800 Subject: [PATCH 122/502] Hack for avoiding lightmaps loading in starchamber --- interface/src/renderer/GeometryCache.cpp | 7 ++++++- libraries/fbx/src/FBXReader.cpp | 10 +++++----- libraries/fbx/src/FBXReader.h | 2 +- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/interface/src/renderer/GeometryCache.cpp b/interface/src/renderer/GeometryCache.cpp index 5ef90732ef..04b59e7ea1 100644 --- a/interface/src/renderer/GeometryCache.cpp +++ b/interface/src/renderer/GeometryCache.cpp @@ -834,7 +834,12 @@ void GeometryReader::run() { if (_url.path().toLower().endsWith(".svo")) { fbxgeo = readSVO(_reply->readAll()); } else { - fbxgeo = readFBX(_reply->readAll(), _mapping); + bool grabLightmaps = true; + // HACK: For monday 12/01/2014 we need to kill lighmaps loading in starchamber... + if (_url.path().toLower().endsWith("loungev4_11-18.fbx")) { + grabLightmaps = false; + } + fbxgeo = readFBX(_reply->readAll(), _mapping, grabLightmaps); } QMetaObject::invokeMethod(geometry.data(), "setGeometry", Q_ARG(const FBXGeometry&, fbxgeo)); diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index fd9190f597..d77cbbd0a1 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -1194,7 +1194,7 @@ int matchTextureUVSetToAttributeChannel(const std::string& texUVSetName, const Q } } -FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) { +FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, bool loadLightmaps) { QHash meshes; QHash modelIDsToNames; QHash meshIDsToMeshIndices; @@ -1704,10 +1704,10 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) } else if (type.contains("shininess")) { counter++; - } else if (type.contains("emissive")) { + } else if (loadLightmaps && type.contains("emissive")) { emissiveTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1)); - } else if (type.contains("ambient")) { + } else if (loadLightmaps && type.contains("ambient")) { ambientTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1)); } else { std::string typenam = type.data(); @@ -2372,10 +2372,10 @@ QByteArray writeMapping(const QVariantHash& mapping) { return buffer.data(); } -FBXGeometry readFBX(const QByteArray& model, const QVariantHash& mapping) { +FBXGeometry readFBX(const QByteArray& model, const QVariantHash& mapping, bool loadLightmaps) { QBuffer buffer(const_cast(&model)); buffer.open(QIODevice::ReadOnly); - return extractFBXGeometry(parseFBX(&buffer), mapping); + return extractFBXGeometry(parseFBX(&buffer), mapping, loadLightmaps); } bool addMeshVoxelsOperation(OctreeElement* element, void* extraData) { diff --git a/libraries/fbx/src/FBXReader.h b/libraries/fbx/src/FBXReader.h index d92f787050..3adf5b5ffb 100644 --- a/libraries/fbx/src/FBXReader.h +++ b/libraries/fbx/src/FBXReader.h @@ -253,7 +253,7 @@ QByteArray writeMapping(const QVariantHash& mapping); /// Reads FBX geometry from the supplied model and mapping data. /// \exception QString if an error occurs in parsing -FBXGeometry readFBX(const QByteArray& model, const QVariantHash& mapping); +FBXGeometry readFBX(const QByteArray& model, const QVariantHash& mapping, bool loadLightmaps = true); /// Reads SVO geometry from the supplied model data. FBXGeometry readSVO(const QByteArray& model); From fed7d789f6023eef1670974eb75b558691b16a8d Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Sun, 30 Nov 2014 17:29:18 -0800 Subject: [PATCH 123/502] have the domain-server write its local port into shared memory --- domain-server/src/DomainServer.cpp | 13 +++++++++++++ libraries/networking/src/LimitedNodeList.h | 2 ++ 2 files changed, 15 insertions(+) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 02f17bc502..84948e2406 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -228,6 +229,18 @@ void DomainServer::setupNodeListAndAssignments(const QUuid& sessionUUID) { LimitedNodeList* nodeList = LimitedNodeList::createInstance(domainServerPort, domainServerDTLSPort); + // no matter the local port, save it to shared mem so that local assignment clients can ask what it is + QSharedMemory* sharedPortMem = new QSharedMemory(DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY, this); + quint16 localPort = nodeList->getNodeSocket().localPort(); + + // attempt to create the shared memory segment + if (sharedPortMem->create(sizeof(localPort)) || sharedPortMem->attach()) { + memcpy(sharedPortMem->data(), &localPort, sizeof(localPort)); + qDebug() << "Wrote local listening port to shared memory at key" << DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY; + } else { + qWarning() << "Failed to create and attach to shared memory to share local port with assignment-client children."; + } + // set our LimitedNodeList UUID to match the UUID from our config // nodes will currently use this to add resources to data-web that relate to our domain const QString METAVERSE_DOMAIN_ID_KEY_PATH = "metaverse.id"; diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index 64495fbd34..ad8c1688bb 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -44,6 +44,8 @@ const char DEFAULT_ASSIGNMENT_SERVER_HOSTNAME[] = "localhost"; const char STUN_SERVER_HOSTNAME[] = "stun.highfidelity.io"; const unsigned short STUN_SERVER_PORT = 3478; +const QString DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY = "domain-server.local-port"; + class HifiSockAddr; typedef QSet NodeSet; From 59432e8d2935f2b1937a26b784fc64fdc29640e4 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Sun, 30 Nov 2014 17:54:10 -0800 Subject: [PATCH 124/502] complete sharing of local domain-server port to local AC --- assignment-client/src/AssignmentClient.cpp | 59 +++++++++++++++++----- assignment-client/src/AssignmentClient.h | 4 ++ domain-server/src/DomainServer.cpp | 5 +- 3 files changed, 55 insertions(+), 13 deletions(-) diff --git a/assignment-client/src/AssignmentClient.cpp b/assignment-client/src/AssignmentClient.cpp index ae235eb1ff..9972adfda2 100644 --- a/assignment-client/src/AssignmentClient.cpp +++ b/assignment-client/src/AssignmentClient.cpp @@ -10,6 +10,7 @@ // #include +#include #include #include @@ -38,7 +39,8 @@ int hifiSockAddrMeta = qRegisterMetaType("HifiSockAddr"); AssignmentClient::AssignmentClient(int &argc, char **argv) : QCoreApplication(argc, argv), _shutdownEventListener(this), - _assignmentServerHostname(DEFAULT_ASSIGNMENT_SERVER_HOSTNAME) + _assignmentServerHostname(DEFAULT_ASSIGNMENT_SERVER_HOSTNAME), + _localASPortSharedMem(NULL) { LogUtils::init(); @@ -89,13 +91,7 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) : // create a NodeList as an unassigned client NodeList* nodeList = NodeList::createInstance(NodeType::Unassigned); - unsigned short assignmentServerPort = DEFAULT_DOMAIN_SERVER_PORT; - - // check for an overriden assignment server port - if (argumentVariantMap.contains(CUSTOM_ASSIGNMENT_SERVER_PORT_OPTION)) { - assignmentServerPort = - argumentVariantMap.value(CUSTOM_ASSIGNMENT_SERVER_PORT_OPTION).toString().toUInt(); - } + quint16 assignmentServerPort = DEFAULT_DOMAIN_SERVER_PORT; // check for an overriden assignment server hostname if (argumentVariantMap.contains(CUSTOM_ASSIGNMENT_SERVER_HOSTNAME_OPTION)) { @@ -103,10 +99,16 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) : _assignmentServerHostname = argumentVariantMap.value(CUSTOM_ASSIGNMENT_SERVER_HOSTNAME_OPTION).toString(); } - HifiSockAddr assignmentServerSocket(_assignmentServerHostname, assignmentServerPort, true); - nodeList->setAssignmentServerSocket(assignmentServerSocket); + // check for an overriden assignment server port + if (argumentVariantMap.contains(CUSTOM_ASSIGNMENT_SERVER_PORT_OPTION)) { + assignmentServerPort = + argumentVariantMap.value(CUSTOM_ASSIGNMENT_SERVER_PORT_OPTION).toString().toUInt(); + } + + _assignmentServerSocket = HifiSockAddr(_assignmentServerHostname, assignmentServerPort, true); + nodeList->setAssignmentServerSocket(_assignmentServerSocket); - qDebug() << "Assignment server socket is" << assignmentServerSocket; + qDebug() << "Assignment server socket is" << _assignmentServerSocket; // call a timer function every ASSIGNMENT_REQUEST_INTERVAL_MSECS to ask for assignment, if required qDebug() << "Waiting for assignment -" << _requestAssignment; @@ -129,7 +131,40 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) : void AssignmentClient::sendAssignmentRequest() { if (!_currentAssignment) { - NodeList::getInstance()->sendAssignment(_requestAssignment); + + NodeList* nodeList = NodeList::getInstance(); + + if (_assignmentServerHostname == "localhost") { + // we want to check again for the local domain-server port in case the DS has restarted + if (!_localASPortSharedMem) { + _localASPortSharedMem = new QSharedMemory(DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY, this); + + if (!_localASPortSharedMem->attach(QSharedMemory::ReadOnly)) { + qWarning() << "Could not attach to shared memory at key" << DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY + << "- will attempt to connect to domain-server on" << _assignmentServerSocket.getPort(); + } + } + + if (_localASPortSharedMem->isAttached()) { + _localASPortSharedMem->lock(); + + quint16 localAssignmentServerPort; + memcpy(&localAssignmentServerPort, _localASPortSharedMem->data(), sizeof(localAssignmentServerPort)); + + _localASPortSharedMem->unlock(); + + if (localAssignmentServerPort != _assignmentServerSocket.getPort()) { + qDebug() << "Port for local assignment server read from shared memory is" + << localAssignmentServerPort; + + _assignmentServerSocket.setPort(localAssignmentServerPort); + nodeList->setAssignmentServerSocket(_assignmentServerSocket); + } + } + + } + + nodeList->sendAssignment(_requestAssignment); } } diff --git a/assignment-client/src/AssignmentClient.h b/assignment-client/src/AssignmentClient.h index 7628aa0a3b..566805d67f 100644 --- a/assignment-client/src/AssignmentClient.h +++ b/assignment-client/src/AssignmentClient.h @@ -17,6 +17,8 @@ #include "ShutdownEventListener.h" #include "ThreadedAssignment.h" +class QSharedMemory; + class AssignmentClient : public QCoreApplication { Q_OBJECT public: @@ -34,6 +36,8 @@ private: static SharedAssignmentPointer _currentAssignment; ShutdownEventListener _shutdownEventListener; QString _assignmentServerHostname; + HifiSockAddr _assignmentServerSocket; + QSharedMemory* _localASPortSharedMem; }; #endif // hifi_AssignmentClient_h diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 84948e2406..ddc06c8015 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -235,8 +235,11 @@ void DomainServer::setupNodeListAndAssignments(const QUuid& sessionUUID) { // attempt to create the shared memory segment if (sharedPortMem->create(sizeof(localPort)) || sharedPortMem->attach()) { + sharedPortMem->lock(); memcpy(sharedPortMem->data(), &localPort, sizeof(localPort)); - qDebug() << "Wrote local listening port to shared memory at key" << DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY; + sharedPortMem->unlock(); + + qDebug() << "Wrote local listening port" << localPort << "to shared memory at key" << DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY; } else { qWarning() << "Failed to create and attach to shared memory to share local port with assignment-client children."; } From 8449575fa231cfe504cbfcecc395d2f447f59f16 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 1 Dec 2014 09:25:21 -0800 Subject: [PATCH 125/502] fix for ice-server heartbeat without an access token --- domain-server/src/DomainServer.cpp | 45 ++++++++++++++++-------------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index ddc06c8015..80777ce529 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -337,9 +337,31 @@ bool DomainServer::optionallySetupAssignmentPayment() { void DomainServer::setupAutomaticNetworking() { + LimitedNodeList* nodeList = LimitedNodeList::getInstance(); + + const int STUN_REFLEXIVE_KEEPALIVE_INTERVAL_MSECS = 10 * 1000; + const int STUN_IP_ADDRESS_CHECK_INTERVAL_MSECS = 30 * 1000; + + // setup our timer to check our IP via stun every X seconds + QTimer* dynamicIPTimer = new QTimer(this); + connect(dynamicIPTimer, &QTimer::timeout, this, &DomainServer::requestCurrentPublicSocketViaSTUN); + + if (_automaticNetworkingSetting == FULL_AUTOMATIC_NETWORKING_VALUE) { + dynamicIPTimer->start(STUN_REFLEXIVE_KEEPALIVE_INTERVAL_MSECS); + + // setup a timer to heartbeat with the ice-server every so often + QTimer* iceHeartbeatTimer = new QTimer(this); + connect(iceHeartbeatTimer, &QTimer::timeout, this, &DomainServer::performICEUpdates); + iceHeartbeatTimer->start(ICE_HEARBEAT_INTERVAL_MSECS); + + // call our sendHeartbeaToIceServer immediately anytime a local or public socket changes + connect(nodeList, &LimitedNodeList::localSockAddrChanged, this, &DomainServer::sendHeartbeatToIceServer); + connect(nodeList, &LimitedNodeList::publicSockAddrChanged, this, &DomainServer::sendHeartbeatToIceServer); + } + if (!didSetupAccountManagerWithAccessToken()) { - qDebug() << "Cannot setup domain-server automatic networking without an access token."; - qDebug() << "Please add an access token to your config file or via the web interface."; + qDebug() << "Cannot send heartbeat to data server without an access token."; + qDebug() << "Add an access token to your config file or via the web interface."; return; } @@ -350,37 +372,18 @@ void DomainServer::setupAutomaticNetworking() { if (_automaticNetworkingSetting == IP_ONLY_AUTOMATIC_NETWORKING_VALUE || _automaticNetworkingSetting == FULL_AUTOMATIC_NETWORKING_VALUE) { - LimitedNodeList* nodeList = LimitedNodeList::getInstance(); const QUuid& domainID = nodeList->getSessionUUID(); if (!domainID.isNull()) { qDebug() << "domain-server" << _automaticNetworkingSetting << "automatic networking enabled for ID" << uuidStringWithoutCurlyBraces(domainID) << "via" << _oauthProviderURL.toString(); - const int STUN_IP_ADDRESS_CHECK_INTERVAL_MSECS = 30 * 1000; - const int STUN_REFLEXIVE_KEEPALIVE_INTERVAL_MSECS = 10 * 1000; - - // setup our timer to check our IP via stun every X seconds - QTimer* dynamicIPTimer = new QTimer(this); - connect(dynamicIPTimer, &QTimer::timeout, this, &DomainServer::requestCurrentPublicSocketViaSTUN); - if (_automaticNetworkingSetting == IP_ONLY_AUTOMATIC_NETWORKING_VALUE) { dynamicIPTimer->start(STUN_IP_ADDRESS_CHECK_INTERVAL_MSECS); // send public socket changes to the data server so nodes can find us at our new IP connect(nodeList, &LimitedNodeList::publicSockAddrChanged, this, &DomainServer::performIPAddressUpdate); } else { - dynamicIPTimer->start(STUN_REFLEXIVE_KEEPALIVE_INTERVAL_MSECS); - - // setup a timer to heartbeat with the ice-server every so often - QTimer* iceHeartbeatTimer = new QTimer(this); - connect(iceHeartbeatTimer, &QTimer::timeout, this, &DomainServer::performICEUpdates); - iceHeartbeatTimer->start(ICE_HEARBEAT_INTERVAL_MSECS); - - // call our sendHeartbeaToIceServer immediately anytime a local or public socket changes - connect(nodeList, &LimitedNodeList::localSockAddrChanged, this, &DomainServer::sendHeartbeatToIceServer); - connect(nodeList, &LimitedNodeList::publicSockAddrChanged, this, &DomainServer::sendHeartbeatToIceServer); - // send our heartbeat to data server so it knows what our network settings are sendHeartbeatToDataServer(); } From 40db44e4bd708831694cc283cccb03e5174c23e3 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 1 Dec 2014 09:59:51 -0800 Subject: [PATCH 126/502] fix for custom hifi URL lookup --- interface/src/Application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 20ae07b0c9..31b73274fc 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -842,7 +842,7 @@ bool Application::event(QEvent* event) { QFileOpenEvent* fileEvent = static_cast(event); if (!fileEvent->url().isEmpty()) { - AddressManager::getInstance().handleLookupString(fileEvent->url().toLocalFile()); + AddressManager::getInstance().handleLookupString(fileEvent->url().toString()); } return false; From 6d7f799dbe072a857d9ffdf1a9be66c6578f764f Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 1 Dec 2014 10:32:35 -0800 Subject: [PATCH 127/502] oculus mirror lean hack --- interface/src/avatar/MyAvatar.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 3cbe2ac8ae..3301cf0347 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -367,6 +367,15 @@ void MyAvatar::updateFromTrackers(float deltaTime) { const float TORSO_LENGTH = 0.5f; glm::vec3 relativePosition = estimatedPosition - glm::vec3(0.0f, -TORSO_LENGTH, 0.0f); const float MAX_LEAN = 45.0f; + + // Invert left/right lean when in mirror mode + // NOTE: this is kinda a hack, it's the same hack we use to make the head tilt. But it's not really a mirror + // it just makes you feel like you're looking in a mirror because the body movements of the avatar appear to + // match your body movements. + if (OculusManager::isConnected() && Application::getInstance()->getCamera()->getMode() == CAMERA_MODE_MIRROR) { + relativePosition.x = -relativePosition.x; + } + head->setLeanSideways(glm::clamp(glm::degrees(atanf(relativePosition.x * _leanScale / TORSO_LENGTH)), -MAX_LEAN, MAX_LEAN)); head->setLeanForward(glm::clamp(glm::degrees(atanf(relativePosition.z * _leanScale / TORSO_LENGTH)), From 7f36a11f3539ec07ca807ea097d813d48acd2627 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Mon, 1 Dec 2014 10:40:37 -0800 Subject: [PATCH 128/502] Find Oculus libraries when using Visual Studio 2013 --- cmake/modules/FindLibOVR.cmake | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/cmake/modules/FindLibOVR.cmake b/cmake/modules/FindLibOVR.cmake index a1d75add3f..6ffb3ed309 100644 --- a/cmake/modules/FindLibOVR.cmake +++ b/cmake/modules/FindLibOVR.cmake @@ -48,8 +48,13 @@ elseif (UNIX) select_library_configurations(XINERAMA) elseif (WIN32) - find_library(LIBOVR_LIBRARY_DEBUG NAMES libovrd PATH_SUFFIXES Lib/Win32/VS2010 HINTS ${LIBOVR_SEARCH_DIRS}) - find_library(LIBOVR_LIBRARY_RELEASE NAMES libovr PATH_SUFFIXES Lib/Win32/VS2010 HINTS ${LIBOVR_SEARCH_DIRS}) + if (MSVC10) + find_library(LIBOVR_LIBRARY_DEBUG NAMES libovrd PATH_SUFFIXES Lib/Win32/VS2010 HINTS ${LIBOVR_SEARCH_DIRS}) + find_library(LIBOVR_LIBRARY_RELEASE NAMES libovr PATH_SUFFIXES Lib/Win32/VS2010 HINTS ${LIBOVR_SEARCH_DIRS}) + elseif (MSVC12) + find_library(LIBOVR_LIBRARY_DEBUG NAMES libovrd PATH_SUFFIXES Lib/Win32/VS2013 HINTS ${LIBOVR_SEARCH_DIRS}) + find_library(LIBOVR_LIBRARY_RELEASE NAMES libovr PATH_SUFFIXES Lib/Win32/VS2013 HINTS ${LIBOVR_SEARCH_DIRS}) + endif () find_package(ATL) endif () From 09eb150edc9adb0e06ac9931633ce00115e99240 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Mon, 1 Dec 2014 11:40:35 -0800 Subject: [PATCH 129/502] Update build instructions for VS2013 Community and Professional --- BUILD.md | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/BUILD.md b/BUILD.md index d6e1603f37..e1d920b8df 100644 --- a/BUILD.md +++ b/BUILD.md @@ -96,12 +96,13 @@ Currently building on Windows has been tested using the following compilers: #####Windows SDK 7.1 -Whichever version of Visual Studio you use, you will need [Microsoft Windows SDK for Windows 7 and .NET Framework 4](http://www.microsoft.com/en-us/download/details.aspx?id=8279). +If using Visual Studio 2010, or using Visual Studio 2013 but building as a Visual Studio 2010 project, you need [Microsoft Windows SDK for Windows 7 and .NET Framework 4](http://www.microsoft.com/en-us/download/details.aspx?id=8279). NOTE: If using Visual Studio C++ 2010 Express, you need to follow a specific install order. See below before installing the Windows SDK. -######Windows 8.1 -You may have already downloaded the Windows 8 SDK (e.g. if you have previously installed Visual Studio 2013). If so, change CMAKE_PREFIX_PATH in %HIFI_DIR%\CMakeLists.txt to point to the Windows 8 SDK binaries. The default path is `C:\Program Files (x86)\Windows Kits\8.1\Lib\winv6.3\um\x86` +######Windows SDK 8.1 + +If using Visual Studio 2013 and building as a Visual Studio 2013 project you need the Windows 8 SDK which you should already have as part of installing Visual Studio 2013. You should be able to see it at `C:\Program Files (x86)\Windows Kits\8.1\Lib\winv6.3\um\x86`. #####Visual Studio C++ 2010 Express @@ -123,9 +124,11 @@ Some of the build instructions will ask you to start a Visual Studio Command Pro #####Visual Studio 2013 -This product must be purchased separately. +You can use the Community or Professional editions of Visual Studio 2013. -Visual Studio 2013 doesn't have a shortcut to start a Visual Studio Command Prompt. Instead, start a regular command prompt and then run: +You can start a Visual Studio 2013 command prompt using the shortcut provided in the Visual Studio Tools folder installed as part of Visual Studio 2013. + +Or you can start a regular command prompt and then run: "%VS120COMNTOOLS%\vsvars32.bat" @@ -146,6 +149,8 @@ Once Qt is installed, you need to manually configure the following: * Make sure the Qt runtime DLLs are loadable. You must do this before you attempt to build because some tools for the build depend on Qt. E.g., add to the PATH: `Qt\5.2.0\msvc2010_opengl\bin\`. * Set the QT_CMAKE_PREFIX_PATH environment variable to your `Qt\5.2.0\msvc2010_opengl` directory. +If building as a Visual Studio 2013 project, download and configure the msvc2013 version of Qt instead. + ####External Libraries CMake will need to know where the headers and libraries for required external dependencies are. From 845e687fc579add8016dd593d41f94f9a956dad2 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 1 Dec 2014 11:45:07 -0800 Subject: [PATCH 130/502] Adding a Hack for the apaartment model to boost the lightmaps --- interface/src/renderer/GeometryCache.cpp | 5 ++++- libraries/fbx/src/FBXReader.cpp | 7 ++++--- libraries/fbx/src/FBXReader.h | 2 +- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/interface/src/renderer/GeometryCache.cpp b/interface/src/renderer/GeometryCache.cpp index 04b59e7ea1..e2517613df 100644 --- a/interface/src/renderer/GeometryCache.cpp +++ b/interface/src/renderer/GeometryCache.cpp @@ -835,11 +835,14 @@ void GeometryReader::run() { fbxgeo = readSVO(_reply->readAll()); } else { bool grabLightmaps = true; + float lightmapLevel = 1.0f; // HACK: For monday 12/01/2014 we need to kill lighmaps loading in starchamber... if (_url.path().toLower().endsWith("loungev4_11-18.fbx")) { grabLightmaps = false; + } else if (_url.path().toLower().endsWith("apt8_reboot.fbx")) { + lightmapLevel = 4.0f; } - fbxgeo = readFBX(_reply->readAll(), _mapping, grabLightmaps); + fbxgeo = readFBX(_reply->readAll(), _mapping, grabLightmaps, lightmapLevel); } QMetaObject::invokeMethod(geometry.data(), "setGeometry", Q_ARG(const FBXGeometry&, fbxgeo)); diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index d77cbbd0a1..5f215ac4d0 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -1194,7 +1194,7 @@ int matchTextureUVSetToAttributeChannel(const std::string& texUVSetName, const Q } } -FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, bool loadLightmaps) { +FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, bool loadLightmaps, float lightmapLevel) { QHash meshes; QHash modelIDsToNames; QHash meshIDsToMeshIndices; @@ -1954,6 +1954,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, FBXTexture emissiveTexture; glm::vec2 emissiveParams(0.f, 1.f); + emissiveParams.y = lightmapLevel; QString emissiveTextureID = emissiveTextures.value(childID); QString ambientTextureID = ambientTextures.value(childID); if (!emissiveTextureID.isNull() || !ambientTextureID.isNull()) { @@ -2372,10 +2373,10 @@ QByteArray writeMapping(const QVariantHash& mapping) { return buffer.data(); } -FBXGeometry readFBX(const QByteArray& model, const QVariantHash& mapping, bool loadLightmaps) { +FBXGeometry readFBX(const QByteArray& model, const QVariantHash& mapping, bool loadLightmaps, float lightmapLevel) { QBuffer buffer(const_cast(&model)); buffer.open(QIODevice::ReadOnly); - return extractFBXGeometry(parseFBX(&buffer), mapping, loadLightmaps); + return extractFBXGeometry(parseFBX(&buffer), mapping, loadLightmaps, lightmapLevel); } bool addMeshVoxelsOperation(OctreeElement* element, void* extraData) { diff --git a/libraries/fbx/src/FBXReader.h b/libraries/fbx/src/FBXReader.h index 3adf5b5ffb..a5df7ccc0c 100644 --- a/libraries/fbx/src/FBXReader.h +++ b/libraries/fbx/src/FBXReader.h @@ -253,7 +253,7 @@ QByteArray writeMapping(const QVariantHash& mapping); /// Reads FBX geometry from the supplied model and mapping data. /// \exception QString if an error occurs in parsing -FBXGeometry readFBX(const QByteArray& model, const QVariantHash& mapping, bool loadLightmaps = true); +FBXGeometry readFBX(const QByteArray& model, const QVariantHash& mapping, bool loadLightmaps = true, float lightmapLevel = 1.0f); /// Reads SVO geometry from the supplied model data. FBXGeometry readSVO(const QByteArray& model); From 1950ce5a4b9d1d9d023205300a8a51e3a820d497 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 25 Nov 2014 14:09:32 -0800 Subject: [PATCH 131/502] Add option for white grid color --- examples/html/gridControls.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/html/gridControls.html b/examples/html/gridControls.html index 241fa2406c..d95c9545e4 100644 --- a/examples/html/gridControls.html +++ b/examples/html/gridControls.html @@ -6,7 +6,7 @@ var gridColor = { red: 0, green: 0, blue: 0 }; var gridColors = [ { red: 0, green: 0, blue: 0 }, - { red: 128, green: 128, blue: 128 }, + { red: 255, green: 255, blue: 255 }, { red: 255, green: 0, blue: 0 }, { red: 0, green: 255, blue: 0}, { red: 0, green: 0, blue: 255 }, From 2c524cd70ce3835982092e9b4a40d7563d70b77d Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 25 Nov 2014 14:10:39 -0800 Subject: [PATCH 132/502] Darken colors of selection/highlight boxes --- examples/libraries/entitySelectionTool.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/libraries/entitySelectionTool.js b/examples/libraries/entitySelectionTool.js index 813bf015d1..f1e311246e 100644 --- a/examples/libraries/entitySelectionTool.js +++ b/examples/libraries/entitySelectionTool.js @@ -306,7 +306,7 @@ SelectionDisplay = (function () { var highlightBox = Overlays.addOverlay("cube", { position: { x:0, y: 0, z: 0}, size: 1, - color: { red: 180, green: 180, blue: 180}, + color: { red: 90, green: 90, blue: 90}, alpha: 1, solid: false, visible: false, @@ -318,7 +318,7 @@ SelectionDisplay = (function () { var selectionBox = Overlays.addOverlay("cube", { position: { x:0, y: 0, z: 0}, size: 1, - color: { red: 180, green: 180, blue: 180}, + color: { red: 60, green: 60, blue: 60}, alpha: 1, solid: false, visible: false, From fc5adef501a326300fb3ef42cf29a14188ea3a08 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 25 Nov 2014 14:11:04 -0800 Subject: [PATCH 133/502] Update the tool window to use tabbed windows --- interface/src/ui/ToolWindow.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/interface/src/ui/ToolWindow.cpp b/interface/src/ui/ToolWindow.cpp index de88d75b3d..799402a486 100644 --- a/interface/src/ui/ToolWindow.cpp +++ b/interface/src/ui/ToolWindow.cpp @@ -21,6 +21,7 @@ ToolWindow::ToolWindow(QWidget* parent) : _hasShown(false), _lastGeometry() { + setDockOptions(QMainWindow::ForceTabbedDocks); Application::getInstance()->installEventFilter(this); } From da568c96cea7d7a5bacb43b5f0f1de63f5c70b30 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 1 Dec 2014 12:04:00 -0800 Subject: [PATCH 134/502] Add rotation degrees overlay --- examples/libraries/entitySelectionTool.js | 131 +++++++++++++++++++--- 1 file changed, 113 insertions(+), 18 deletions(-) diff --git a/examples/libraries/entitySelectionTool.js b/examples/libraries/entitySelectionTool.js index f1e311246e..2b3819aff1 100644 --- a/examples/libraries/entitySelectionTool.js +++ b/examples/libraries/entitySelectionTool.js @@ -200,6 +200,12 @@ SelectionManager = (function() { return that; })(); +function normalizeDegrees(degrees) { + while (degrees > 180) degrees -= 360; + while (degrees < -180) degrees += 360; + return degrees; +} + SelectionDisplay = (function () { var that = {}; @@ -207,6 +213,8 @@ SelectionDisplay = (function () { var GRABBER_DISTANCE_TO_SIZE_RATIO = 0.0075; + var ROTATION_DISPLAY_DISTANCE_MULTIPLIER = 1.2; + var showExtendedStretchHandles = false; var spaceMode = SPACE_LOCAL; @@ -223,6 +231,9 @@ SelectionDisplay = (function () { var innerSnapAngle = 22.5; // the angle which we snap to on the inner rotation tool var innerRadius; var outerRadius; + var yawOffset = 0; + var pitchOffset = 0; + var rollOffset = 0; var yawHandleRotation; var pitchHandleRotation; var rollHandleRotation; @@ -326,6 +337,23 @@ SelectionDisplay = (function () { lineWidth: 1.0, }); + var rotationDegreesDisplay = Overlays.addOverlay("text3d", { + position: { x:0, y: 0, z: 0}, + text: "", + color: { red: 0, green: 0, blue: 0}, + backgroundColor: { red: 255, green: 255, blue: 255 }, + alpha: 0.7, + visible: false, + isFacingAvatar: true, + drawInFront: true, + dimensions: { x: 0, y: 0 }, + lineHeight: 0.0, + topMargin: 0, + rightMargin: 0, + bottomMargin: 0, + leftMargin: 0, + }); + var grabberMoveUp = Overlays.addOverlay("billboard", { url: HIFI_PUBLIC_BUCKET + "images/up-arrow.png", position: { x:0, y: 0, z: 0}, @@ -585,6 +613,7 @@ SelectionDisplay = (function () { rotateOverlayCurrent, rotateZeroOverlay, rotateCurrentOverlay, + rotationDegreesDisplay, xRailOverlay, yRailOverlay, zRailOverlay, @@ -757,6 +786,10 @@ SelectionDisplay = (function () { pitchHandleRotation = Quat.fromVec3Degrees({ x: 0, y: 90, z: 0 }); rollHandleRotation = Quat.fromVec3Degrees({ x: 0, y: 0, z: 0 }); + yawOffset = 90; + pitchOffset = 0; + rollOffset = 0; + yawNormal = { x: 0, y: 1, z: 0 }; pitchNormal = { x: 1, y: 0, z: 0 }; rollNormal = { x: 0, y: 0, z: 1 }; @@ -788,6 +821,10 @@ SelectionDisplay = (function () { pitchHandleRotation = Quat.fromVec3Degrees({ x: 180, y: 270, z: 0 }); rollHandleRotation = Quat.fromVec3Degrees({ x: 0, y: 0, z: 90 }); + yawOffset = 0; + pitchOffset = 180; + rollOffset = 90; + yawNormal = { x: 0, y: 1, z: 0 }; pitchNormal = { x: 1, y: 0, z: 0 }; rollNormal = { x: 0, y: 0, z: 1 }; @@ -822,6 +859,10 @@ SelectionDisplay = (function () { pitchHandleRotation = Quat.fromVec3Degrees({ x: 90, y: 0, z: 90 }); rollHandleRotation = Quat.fromVec3Degrees({ x: 0, y: 0, z: 180 }); + yawOffset = 180; + pitchOffset = 90; + rollOffset = 180; + yawNormal = { x: 0, y: 1, z: 0 }; pitchNormal = { x: 1, y: 0, z: 0 }; rollNormal = { x: 0, y: 0, z: 1 }; @@ -848,8 +889,12 @@ SelectionDisplay = (function () { } else { yawHandleRotation = Quat.fromVec3Degrees({ x: 270, y: 270, z: 0 }); - rollHandleRotation = Quat.fromVec3Degrees({ x: 0, y: 0, z: 180 }); pitchHandleRotation = Quat.fromVec3Degrees({ x: 180, y: 270, z: 0 }); + rollHandleRotation = Quat.fromVec3Degrees({ x: 0, y: 0, z: 180 }); + + yawOffset = 270; + pitchOffset = 180; + rollOffset = 180; yawNormal = { x: 0, y: 1, z: 0 }; rollNormal = { x: 0, y: 0, z: 1 }; @@ -1570,11 +1615,17 @@ SelectionDisplay = (function () { endAt: 0, innerRadius: 0.9, }); + + Overlays.editOverlay(rotationDegreesDisplay, { + visible: true, + ignoreRayIntersection: true, + }); }, onEnd: function(event, reason) { Overlays.editOverlay(rotateOverlayInner, { visible: false }); Overlays.editOverlay(rotateOverlayOuter, { visible: false }); Overlays.editOverlay(rotateOverlayCurrent, { visible: false }); + Overlays.editOverlay(rotationDegreesDisplay, { visible: false }); pushCommandForSelections(); }, @@ -1605,12 +1656,9 @@ SelectionDisplay = (function () { var angleFromZero = Vec3.orientedAngle(centerToZero, centerToIntersect, rotationNormal); var distanceFromCenter = Vec3.distance(center, result.intersection); - var snapToInner = false; - // var innerRadius = (Vec3.length(selectionManager.worldDimensions) / 2) * 1.1; - if (distanceFromCenter < innerRadius) { - angleFromZero = Math.floor(angleFromZero/innerSnapAngle) * innerSnapAngle; - snapToInner = true; - } + var snapToInner = distanceFromCenter < innerRadius; + var snapAngle = snapToInner ? innerSnapAngle : 1.0; + angleFromZero = Math.floor(angleFromZero / snapAngle) * snapAngle; // for debugging if (debug) { @@ -1632,7 +1680,20 @@ SelectionDisplay = (function () { rotation: Quat.multiply(yawChange, initialProperties.rotation), }); } - + + var angle = (yawOffset + angleFromZero + 180) * (Math.PI / 180); + var position = Vec3.sum( selectionManager.worldPosition, { + x: -Math.cos(angle) * outerRadius * ROTATION_DISPLAY_DISTANCE_MULTIPLIER, + y: -selectionManager.worldDimensions.y / 2, + z: Math.sin(angle) * outerRadius * ROTATION_DISPLAY_DISTANCE_MULTIPLIER, + }); + Overlays.editOverlay(rotationDegreesDisplay, { + position: position, + dimensions: { x: innerRadius / 2, y: innerRadius / 5.6 }, + lineHeight: innerRadius / 6, + text: normalizeDegrees(angleFromZero), + }); + // update the rotation display accordingly... var startAtCurrent = 0; var endAtCurrent = angleFromZero; @@ -1701,11 +1762,17 @@ SelectionDisplay = (function () { endAt: 0, innerRadius: 0.9, }); + + Overlays.editOverlay(rotationDegreesDisplay, { + visible: true, + ignoreRayIntersection: true, + }); }, onEnd: function(event, reason) { Overlays.editOverlay(rotateOverlayInner, { visible: false }); Overlays.editOverlay(rotateOverlayOuter, { visible: false }); Overlays.editOverlay(rotateOverlayCurrent, { visible: false }); + Overlays.editOverlay(rotationDegreesDisplay, { visible: false }); pushCommandForSelections(); }, @@ -1736,11 +1803,9 @@ SelectionDisplay = (function () { var angleFromZero = Vec3.orientedAngle(centerToZero, centerToIntersect, rotationNormal); var distanceFromCenter = Vec3.distance(center, result.intersection); - var snapToInner = false; - if (distanceFromCenter < innerRadius) { - angleFromZero = Math.floor(angleFromZero/innerSnapAngle) * innerSnapAngle; - snapToInner = true; - } + var snapToInner = distanceFromCenter < innerRadius; + var snapAngle = snapToInner ? innerSnapAngle : 1.0; + angleFromZero = Math.floor(angleFromZero / snapAngle) * snapAngle; // for debugging if (debug) { @@ -1764,6 +1829,19 @@ SelectionDisplay = (function () { }); } + var angle = (rollOffset + angleFromZero - 90) * (Math.PI / 180); + var position = Vec3.sum( selectionManager.worldPosition, { + x: selectionManager.worldDimensions.x / 2, + y: Math.cos(angle) * outerRadius * ROTATION_DISPLAY_DISTANCE_MULTIPLIER, + z: Math.sin(angle) * outerRadius * ROTATION_DISPLAY_DISTANCE_MULTIPLIER, + }); + Overlays.editOverlay(rotationDegreesDisplay, { + position: position, + dimensions: { x: innerRadius / 2, y: innerRadius / 5.6 }, + lineHeight: innerRadius / 6, + text: normalizeDegrees(angleFromZero), + }); + // update the rotation display accordingly... var startAtCurrent = 0; var endAtCurrent = angleFromZero; @@ -1831,11 +1909,17 @@ SelectionDisplay = (function () { endAt: 0, innerRadius: 0.9, }); + + Overlays.editOverlay(rotationDegreesDisplay, { + visible: true, + ignoreRayIntersection: true, + }); }, onEnd: function(event, reason) { Overlays.editOverlay(rotateOverlayInner, { visible: false }); Overlays.editOverlay(rotateOverlayOuter, { visible: false }); Overlays.editOverlay(rotateOverlayCurrent, { visible: false }); + Overlays.editOverlay(rotationDegreesDisplay, { visible: false }); pushCommandForSelections(); }, @@ -1866,11 +1950,9 @@ SelectionDisplay = (function () { var angleFromZero = Vec3.orientedAngle(centerToZero, centerToIntersect, rotationNormal); var distanceFromCenter = Vec3.distance(center, result.intersection); - var snapToInner = false; - if (distanceFromCenter < innerRadius) { - angleFromZero = Math.floor(angleFromZero/innerSnapAngle) * innerSnapAngle; - snapToInner = true; - } + var snapToInner = distanceFromCenter < innerRadius; + var snapAngle = snapToInner ? innerSnapAngle : 1.0; + angleFromZero = Math.floor(angleFromZero / snapAngle) * snapAngle; // for debugging if (debug) { @@ -1893,6 +1975,19 @@ SelectionDisplay = (function () { }); } + var angle = (rollOffset + angleFromZero + 90) * (Math.PI / 180); + var position = Vec3.sum( selectionManager.worldPosition, { + x: Math.sin(angle) * outerRadius * ROTATION_DISPLAY_DISTANCE_MULTIPLIER, + y: -Math.cos(angle) * outerRadius * ROTATION_DISPLAY_DISTANCE_MULTIPLIER, + z: -selectionManager.worldDimensions.z / 2, + }); + Overlays.editOverlay(rotationDegreesDisplay, { + position: position, + dimensions: { x: innerRadius / 2, y: innerRadius / 5.6 }, + lineHeight: innerRadius / 6, + text: normalizeDegrees(angleFromZero), + }); + // update the rotation display accordingly... var startAtCurrent = 0; var endAtCurrent = angleFromZero; From 4f0683dc5ee9f45d02275e52c0540b19462e511c Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 1 Dec 2014 15:07:03 -0800 Subject: [PATCH 135/502] Fix stretch tools not following mouse correctly --- examples/libraries/entitySelectionTool.js | 76 ++++++++++++++--------- 1 file changed, 45 insertions(+), 31 deletions(-) diff --git a/examples/libraries/entitySelectionTool.js b/examples/libraries/entitySelectionTool.js index 2b3819aff1..ead424522a 100644 --- a/examples/libraries/entitySelectionTool.js +++ b/examples/libraries/entitySelectionTool.js @@ -1337,7 +1337,11 @@ SelectionDisplay = (function () { var vec3Mult = function(v1, v2) { return { x: v1.x * v2.x, y: v1.y * v2.y, z: v1.z * v2.z }; } - var makeStretchTool = function(stretchMode, direction, pivot) { + // stretchMode - name of mode + // direction - direction to stretch in + // pivot - point to use as a pivot + // offset - the position of the overlay tool relative to the selections center position + var makeStretchTool = function(stretchMode, direction, pivot, offset) { var signs = { x: direction.x < 0 ? -1 : (direction.x > 0 ? 1 : 0), y: direction.y < 0 ? -1 : (direction.y > 0 ? 1 : 0), @@ -1358,6 +1362,7 @@ SelectionDisplay = (function () { var initialDimensions = null; var initialIntersection = null; var initialProperties = null; + var pickRayPosition = null; var rotation = null; var onBegin = function(event) { @@ -1366,13 +1371,22 @@ SelectionDisplay = (function () { rotation = spaceMode == SPACE_LOCAL ? properties.rotation : Quat.fromPitchYawRollDegrees(0, 0, 0); if (spaceMode == SPACE_LOCAL) { + rotation = SelectionManager.localRotation; initialPosition = SelectionManager.localPosition; initialDimensions = SelectionManager.localDimensions; } else { + rotation = SelectionManager.worldRotation; initialPosition = SelectionManager.worldPosition; initialDimensions = SelectionManager.worldDimensions; } + var scaledOffset = { + x: initialDimensions.x * offset.x * 0.5, + y: initialDimensions.y * offset.y * 0.5, + z: initialDimensions.z * offset.z * 0.5, + }; + pickRayPosition = Vec3.sum(initialPosition, Vec3.multiplyQbyV(rotation, scaledOffset)); + if (numDimensions == 1 && mask.x) { var start = Vec3.multiplyQbyV(rotation, { x: -10000, y: 0, z: 0 }); start = Vec3.sum(start, properties.position); @@ -1426,7 +1440,7 @@ SelectionDisplay = (function () { planeNormal = Vec3.multiplyQbyV(rotation, planeNormal); var pickRay = Camera.computePickRay(event.x, event.y); lastPick = rayPlaneIntersection(pickRay, - initialPosition, + pickRayPosition, planeNormal); // Overlays.editOverlay(normalLine, { @@ -1461,7 +1475,7 @@ SelectionDisplay = (function () { var pickRay = Camera.computePickRay(event.x, event.y); newPick = rayPlaneIntersection(pickRay, - initialPosition, + pickRayPosition, planeNormal); var vector = Vec3.subtract(newPick, lastPick); @@ -1536,44 +1550,44 @@ SelectionDisplay = (function () { }; }; - function addStretchTool(overlay, mode, pivot, direction) { + function addStretchTool(overlay, mode, pivot, direction, offset) { if (!pivot) { pivot = Vec3.multiply(-1, direction); pivot.y = direction.y; } - var tool = makeStretchTool(mode, direction, pivot); + var tool = makeStretchTool(mode, direction, pivot, offset); addGrabberTool(overlay, tool); } - addStretchTool(grabberNEAR, "STRETCH_NEAR", { x: 0, y: 0, z: -1 }, { x: 0, y: 0, z: 1 }); - addStretchTool(grabberFAR, "STRETCH_FAR", { x: 0, y: 0, z: 1 }, { x: 0, y: 0, z: -1 }); - addStretchTool(grabberTOP, "STRETCH_TOP", { x: 0, y: 1, z: 0 }, { x: 0, y: -1, z: 0 }); - addStretchTool(grabberBOTTOM, "STRETCH_BOTTOM", { x: 0, y: -1, z: 0 }, { x: 0, y: 1, z: 0 }); - addStretchTool(grabberRIGHT, "STRETCH_RIGHT", { x: 1, y: 0, z: 0 }, { x: -1, y: 0, z: 0 }); - addStretchTool(grabberLEFT, "STRETCH_LEFT", { x: -1, y: 0, z: 0 }, { x: 1, y: 0, z: 0 }); + addStretchTool(grabberNEAR, "STRETCH_NEAR", { x: 0, y: 0, z: -1 }, { x: 0, y: 0, z: 1 }, { x: 0, y: 0, z: -1 }); + addStretchTool(grabberFAR, "STRETCH_FAR", { x: 0, y: 0, z: 1 }, { x: 0, y: 0, z: -1 }, { x: 0, y: 0, z: 1 }); + addStretchTool(grabberTOP, "STRETCH_TOP", { x: 0, y: 1, z: 0 }, { x: 0, y: -1, z: 0 }, { x: 0, y: 1, z: 0 }); + addStretchTool(grabberBOTTOM, "STRETCH_BOTTOM", { x: 0, y: -1, z: 0 }, { x: 0, y: 1, z: 0 }, { x: 0, y: -1, z: 0 }); + addStretchTool(grabberRIGHT, "STRETCH_RIGHT", { x: 1, y: 0, z: 0 }, { x: -1, y: 0, z: 0 }, { x: 1, y: 0, z: 0 }); + addStretchTool(grabberLEFT, "STRETCH_LEFT", { x: -1, y: 0, z: 0 }, { x: 1, y: 0, z: 0 }, { x: -1, y: 0, z: 0 }); - addStretchTool(grabberLBN, "STRETCH_LBN", null, {x: 1, y: 0, z: 1}); - addStretchTool(grabberRBN, "STRETCH_RBN", null, {x: -1, y: 0, z: 1}); - addStretchTool(grabberLBF, "STRETCH_LBF", null, {x: 1, y: 0, z: -1}); - addStretchTool(grabberRBF, "STRETCH_RBF", null, {x: -1, y: 0, z: -1}); - addStretchTool(grabberLTN, "STRETCH_LTN", null, {x: 1, y: 0, z: 1}); - addStretchTool(grabberRTN, "STRETCH_RTN", null, {x: -1, y: 0, z: 1}); - addStretchTool(grabberLTF, "STRETCH_LTF", null, {x: 1, y: 0, z: -1}); - addStretchTool(grabberRTF, "STRETCH_RTF", null, {x: -1, y: 0, z: -1}); + addStretchTool(grabberLBN, "STRETCH_LBN", null, {x: 1, y: 0, z: 1}, { x: -1, y: -1, z: -1 }); + addStretchTool(grabberRBN, "STRETCH_RBN", null, {x: -1, y: 0, z: 1}, { x: 1, y: -1, z: -1 }); + addStretchTool(grabberLBF, "STRETCH_LBF", null, {x: 1, y: 0, z: -1}, { x: -1, y: -1, z: 1 }); + addStretchTool(grabberRBF, "STRETCH_RBF", null, {x: -1, y: 0, z: -1}, { x: 1, y: -1, z: 1 }); + addStretchTool(grabberLTN, "STRETCH_LTN", null, {x: 1, y: 0, z: 1}, { x: -1, y: 1, z: -1 }); + addStretchTool(grabberRTN, "STRETCH_RTN", null, {x: -1, y: 0, z: 1}, { x: 1, y: 1, z: -1 }); + addStretchTool(grabberLTF, "STRETCH_LTF", null, {x: 1, y: 0, z: -1}, { x: -1, y: 1, z: 1 }); + addStretchTool(grabberRTF, "STRETCH_RTF", null, {x: -1, y: 0, z: -1}, { x: 1, y: 1, z: 1 }); - addStretchTool(grabberEdgeTR, "STRETCH_EdgeTR", null, {x: 1, y: 1, z: 0}); - addStretchTool(grabberEdgeTL, "STRETCH_EdgeTL", null, {x: -1, y: 1, z: 0}); - addStretchTool(grabberEdgeTF, "STRETCH_EdgeTF", null, {x: 0, y: 1, z: -1}); - addStretchTool(grabberEdgeTN, "STRETCH_EdgeTN", null, {x: 0, y: 1, z: 1}); - addStretchTool(grabberEdgeBR, "STRETCH_EdgeBR", null, {x: -1, y: 0, z: 0}); - addStretchTool(grabberEdgeBL, "STRETCH_EdgeBL", null, {x: 1, y: 0, z: 0}); - addStretchTool(grabberEdgeBF, "STRETCH_EdgeBF", null, {x: 0, y: 0, z: -1}); - addStretchTool(grabberEdgeBN, "STRETCH_EdgeBN", null, {x: 0, y: 0, z: 1}); - addStretchTool(grabberEdgeNR, "STRETCH_EdgeNR", null, {x: -1, y: 0, z: 1}); - addStretchTool(grabberEdgeNL, "STRETCH_EdgeNL", null, {x: 1, y: 0, z: 1}); - addStretchTool(grabberEdgeFR, "STRETCH_EdgeFR", null, {x: -1, y: 0, z: -1}); - addStretchTool(grabberEdgeFL, "STRETCH_EdgeFL", null, {x: 1, y: 0, z: -1}); + addStretchTool(grabberEdgeTR, "STRETCH_EdgeTR", null, {x: 1, y: 1, z: 0}, { x: 1, y: 1, z: 0 }); + addStretchTool(grabberEdgeTL, "STRETCH_EdgeTL", null, {x: -1, y: 1, z: 0}, { x: -1, y: 1, z: 0 }); + addStretchTool(grabberEdgeTF, "STRETCH_EdgeTF", null, {x: 0, y: 1, z: -1}, { x: 0, y: 1, z: -1 }); + addStretchTool(grabberEdgeTN, "STRETCH_EdgeTN", null, {x: 0, y: 1, z: 1}, { x: 0, y: 1, z: 1 }); + addStretchTool(grabberEdgeBR, "STRETCH_EdgeBR", null, {x: -1, y: 0, z: 0}, { x: 1, y: -1, z: 0 }); + addStretchTool(grabberEdgeBL, "STRETCH_EdgeBL", null, {x: 1, y: 0, z: 0}, { x: -1, y: -1, z: 0 }); + addStretchTool(grabberEdgeBF, "STRETCH_EdgeBF", null, {x: 0, y: 0, z: -1}, { x: 0, y: -1, z: -1 }); + addStretchTool(grabberEdgeBN, "STRETCH_EdgeBN", null, {x: 0, y: 0, z: 1}, { x: 0, y: -1, z: 1 }); + addStretchTool(grabberEdgeNR, "STRETCH_EdgeNR", null, {x: -1, y: 0, z: 1}, { x: 1, y: 0, z: -1 }); + addStretchTool(grabberEdgeNL, "STRETCH_EdgeNL", null, {x: 1, y: 0, z: 1}, { x: -1, y: 0, z: -1 }); + addStretchTool(grabberEdgeFR, "STRETCH_EdgeFR", null, {x: -1, y: 0, z: -1}, { x: 1, y: 0, z: 1 }); + addStretchTool(grabberEdgeFL, "STRETCH_EdgeFL", null, {x: 1, y: 0, z: -1}, { x: -1, y: 0, z: 1 }); var initialPosition = SelectionManager.worldPosition; addGrabberTool(yawHandle, { From 06ab17987bbd12e58c8457a8a5e4aedd8a12d33f Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 1 Dec 2014 16:08:50 -0800 Subject: [PATCH 136/502] Fix position of rotation degrees display The position of the display was not always correct depending on the camera orientation relative to the selection. --- examples/libraries/entitySelectionTool.js | 69 +++++++++++------------ 1 file changed, 33 insertions(+), 36 deletions(-) diff --git a/examples/libraries/entitySelectionTool.js b/examples/libraries/entitySelectionTool.js index ead424522a..e37171c92a 100644 --- a/examples/libraries/entitySelectionTool.js +++ b/examples/libraries/entitySelectionTool.js @@ -213,7 +213,11 @@ SelectionDisplay = (function () { var GRABBER_DISTANCE_TO_SIZE_RATIO = 0.0075; + // These are multipliers for sizing the rotation degrees display while rotating an entity var ROTATION_DISPLAY_DISTANCE_MULTIPLIER = 1.2; + var ROTATION_DISPLAY_SIZE_X_MULTIPLIER = 0.5; + var ROTATION_DISPLAY_SIZE_Y_MULTIPLIER = 0.18; + var ROTATION_DISPLAY_LINE_HEIGHT_MULTIPLIER = 0.17; var showExtendedStretchHandles = false; @@ -1589,6 +1593,26 @@ SelectionDisplay = (function () { addStretchTool(grabberEdgeFR, "STRETCH_EdgeFR", null, {x: -1, y: 0, z: -1}, { x: 1, y: 0, z: 1 }); addStretchTool(grabberEdgeFL, "STRETCH_EdgeFL", null, {x: 1, y: 0, z: -1}, { x: -1, y: 0, z: 1 }); + function updateRotationDegreesOverlay(angleFromZero, handleRotation, centerPosition) { + var angle = angleFromZero * (Math.PI / 180); + var position = { + x: Math.cos(angle) * outerRadius * ROTATION_DISPLAY_DISTANCE_MULTIPLIER, + y: Math.sin(angle) * outerRadius * ROTATION_DISPLAY_DISTANCE_MULTIPLIER, + z: 0, + }; + position = Vec3.multiplyQbyV(handleRotation, position); + position = Vec3.sum(centerPosition, position); + Overlays.editOverlay(rotationDegreesDisplay, { + position: position, + dimensions: { + x: innerRadius * ROTATION_DISPLAY_SIZE_X_MULTIPLIER, + y: innerRadius * ROTATION_DISPLAY_SIZE_Y_MULTIPLIER + }, + lineHeight: innerRadius * ROTATION_DISPLAY_LINE_HEIGHT_MULTIPLIER, + text: normalizeDegrees(angleFromZero), + }); + } + var initialPosition = SelectionManager.worldPosition; addGrabberTool(yawHandle, { mode: "ROTATE_YAW", @@ -1634,6 +1658,8 @@ SelectionDisplay = (function () { visible: true, ignoreRayIntersection: true, }); + + updateRotationDegreesOverlay(0, yawHandleRotation, yawCenter); }, onEnd: function(event, reason) { Overlays.editOverlay(rotateOverlayInner, { visible: false }); @@ -1695,18 +1721,7 @@ SelectionDisplay = (function () { }); } - var angle = (yawOffset + angleFromZero + 180) * (Math.PI / 180); - var position = Vec3.sum( selectionManager.worldPosition, { - x: -Math.cos(angle) * outerRadius * ROTATION_DISPLAY_DISTANCE_MULTIPLIER, - y: -selectionManager.worldDimensions.y / 2, - z: Math.sin(angle) * outerRadius * ROTATION_DISPLAY_DISTANCE_MULTIPLIER, - }); - Overlays.editOverlay(rotationDegreesDisplay, { - position: position, - dimensions: { x: innerRadius / 2, y: innerRadius / 5.6 }, - lineHeight: innerRadius / 6, - text: normalizeDegrees(angleFromZero), - }); + updateRotationDegreesOverlay(angleFromZero, yawHandleRotation, yawCenter); // update the rotation display accordingly... var startAtCurrent = 0; @@ -1781,6 +1796,8 @@ SelectionDisplay = (function () { visible: true, ignoreRayIntersection: true, }); + + updateRotationDegreesOverlay(0, pitchHandleRotation, pitchCenter); }, onEnd: function(event, reason) { Overlays.editOverlay(rotateOverlayInner, { visible: false }); @@ -1843,18 +1860,7 @@ SelectionDisplay = (function () { }); } - var angle = (rollOffset + angleFromZero - 90) * (Math.PI / 180); - var position = Vec3.sum( selectionManager.worldPosition, { - x: selectionManager.worldDimensions.x / 2, - y: Math.cos(angle) * outerRadius * ROTATION_DISPLAY_DISTANCE_MULTIPLIER, - z: Math.sin(angle) * outerRadius * ROTATION_DISPLAY_DISTANCE_MULTIPLIER, - }); - Overlays.editOverlay(rotationDegreesDisplay, { - position: position, - dimensions: { x: innerRadius / 2, y: innerRadius / 5.6 }, - lineHeight: innerRadius / 6, - text: normalizeDegrees(angleFromZero), - }); + updateRotationDegreesOverlay(angleFromZero, pitchHandleRotation, pitchCenter); // update the rotation display accordingly... var startAtCurrent = 0; @@ -1928,6 +1934,8 @@ SelectionDisplay = (function () { visible: true, ignoreRayIntersection: true, }); + + updateRotationDegreesOverlay(0, rollHandleRotation, rollCenter); }, onEnd: function(event, reason) { Overlays.editOverlay(rotateOverlayInner, { visible: false }); @@ -1989,18 +1997,7 @@ SelectionDisplay = (function () { }); } - var angle = (rollOffset + angleFromZero + 90) * (Math.PI / 180); - var position = Vec3.sum( selectionManager.worldPosition, { - x: Math.sin(angle) * outerRadius * ROTATION_DISPLAY_DISTANCE_MULTIPLIER, - y: -Math.cos(angle) * outerRadius * ROTATION_DISPLAY_DISTANCE_MULTIPLIER, - z: -selectionManager.worldDimensions.z / 2, - }); - Overlays.editOverlay(rotationDegreesDisplay, { - position: position, - dimensions: { x: innerRadius / 2, y: innerRadius / 5.6 }, - lineHeight: innerRadius / 6, - text: normalizeDegrees(angleFromZero), - }); + updateRotationDegreesOverlay(angleFromZero, rollHandleRotation, rollCenter); // update the rotation display accordingly... var startAtCurrent = 0; From ce4d4073789da913e19eefe32f4e1d3ea2b2e027 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 1 Dec 2014 16:12:18 -0800 Subject: [PATCH 137/502] Update normalizeDegrees to be exclusive on the -180 end --- examples/libraries/entitySelectionTool.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/libraries/entitySelectionTool.js b/examples/libraries/entitySelectionTool.js index e37171c92a..478782c6ec 100644 --- a/examples/libraries/entitySelectionTool.js +++ b/examples/libraries/entitySelectionTool.js @@ -200,9 +200,10 @@ SelectionManager = (function() { return that; })(); +// Normalize degrees to be in the range (-180, 180] function normalizeDegrees(degrees) { while (degrees > 180) degrees -= 360; - while (degrees < -180) degrees += 360; + while (degrees <= -180) degrees += 360; return degrees; } From 0b7ddb009dca37a3433def60898fbb9347cbc73a Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 1 Dec 2014 16:33:51 -0800 Subject: [PATCH 138/502] Fix tabification of tool windows --- interface/src/ui/ToolWindow.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/interface/src/ui/ToolWindow.cpp b/interface/src/ui/ToolWindow.cpp index 799402a486..da1d2c68f4 100644 --- a/interface/src/ui/ToolWindow.cpp +++ b/interface/src/ui/ToolWindow.cpp @@ -100,8 +100,17 @@ void ToolWindow::onChildVisibilityUpdated(bool visible) { } void ToolWindow::addDockWidget(Qt::DockWidgetArea area, QDockWidget* dockWidget) { + QList dockWidgets = findChildren(); + QMainWindow::addDockWidget(area, dockWidget); + // We want to force tabbing, so retabify all of our widgets. + QDockWidget* lastDockWidget = dockWidget; + foreach (QDockWidget* nextDockWidget, dockWidgets) { + tabifyDockWidget(lastDockWidget, nextDockWidget); + lastDockWidget = nextDockWidget; + } + connect(dockWidget, &QDockWidget::visibilityChanged, this, &ToolWindow::onChildVisibilityUpdated); } From a8eb49a8226c5ae6a4acf550a5fe37818620369d Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 1 Dec 2014 16:38:40 -0800 Subject: [PATCH 139/502] Remove now-unused *Offset variables --- examples/libraries/entitySelectionTool.js | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/examples/libraries/entitySelectionTool.js b/examples/libraries/entitySelectionTool.js index 478782c6ec..5544fec84d 100644 --- a/examples/libraries/entitySelectionTool.js +++ b/examples/libraries/entitySelectionTool.js @@ -236,9 +236,6 @@ SelectionDisplay = (function () { var innerSnapAngle = 22.5; // the angle which we snap to on the inner rotation tool var innerRadius; var outerRadius; - var yawOffset = 0; - var pitchOffset = 0; - var rollOffset = 0; var yawHandleRotation; var pitchHandleRotation; var rollHandleRotation; @@ -791,10 +788,6 @@ SelectionDisplay = (function () { pitchHandleRotation = Quat.fromVec3Degrees({ x: 0, y: 90, z: 0 }); rollHandleRotation = Quat.fromVec3Degrees({ x: 0, y: 0, z: 0 }); - yawOffset = 90; - pitchOffset = 0; - rollOffset = 0; - yawNormal = { x: 0, y: 1, z: 0 }; pitchNormal = { x: 1, y: 0, z: 0 }; rollNormal = { x: 0, y: 0, z: 1 }; @@ -826,10 +819,6 @@ SelectionDisplay = (function () { pitchHandleRotation = Quat.fromVec3Degrees({ x: 180, y: 270, z: 0 }); rollHandleRotation = Quat.fromVec3Degrees({ x: 0, y: 0, z: 90 }); - yawOffset = 0; - pitchOffset = 180; - rollOffset = 90; - yawNormal = { x: 0, y: 1, z: 0 }; pitchNormal = { x: 1, y: 0, z: 0 }; rollNormal = { x: 0, y: 0, z: 1 }; @@ -864,10 +853,6 @@ SelectionDisplay = (function () { pitchHandleRotation = Quat.fromVec3Degrees({ x: 90, y: 0, z: 90 }); rollHandleRotation = Quat.fromVec3Degrees({ x: 0, y: 0, z: 180 }); - yawOffset = 180; - pitchOffset = 90; - rollOffset = 180; - yawNormal = { x: 0, y: 1, z: 0 }; pitchNormal = { x: 1, y: 0, z: 0 }; rollNormal = { x: 0, y: 0, z: 1 }; @@ -897,10 +882,6 @@ SelectionDisplay = (function () { pitchHandleRotation = Quat.fromVec3Degrees({ x: 180, y: 270, z: 0 }); rollHandleRotation = Quat.fromVec3Degrees({ x: 0, y: 0, z: 180 }); - yawOffset = 270; - pitchOffset = 180; - rollOffset = 180; - yawNormal = { x: 0, y: 1, z: 0 }; rollNormal = { x: 0, y: 0, z: 1 }; pitchNormal = { x: 1, y: 0, z: 0 }; From 9d9a7ead5b8f73dcfe6e306aac220bbb7bfb2a6a Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 1 Dec 2014 16:39:36 -0800 Subject: [PATCH 140/502] Remove unnecessary overlay property updates --- examples/libraries/entitySelectionTool.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/examples/libraries/entitySelectionTool.js b/examples/libraries/entitySelectionTool.js index 5544fec84d..1a43231f6f 100644 --- a/examples/libraries/entitySelectionTool.js +++ b/examples/libraries/entitySelectionTool.js @@ -348,6 +348,7 @@ SelectionDisplay = (function () { visible: false, isFacingAvatar: true, drawInFront: true, + ignoreRayIntersection: true, dimensions: { x: 0, y: 0 }, lineHeight: 0.0, topMargin: 0, @@ -1638,7 +1639,6 @@ SelectionDisplay = (function () { Overlays.editOverlay(rotationDegreesDisplay, { visible: true, - ignoreRayIntersection: true, }); updateRotationDegreesOverlay(0, yawHandleRotation, yawCenter); @@ -1776,7 +1776,6 @@ SelectionDisplay = (function () { Overlays.editOverlay(rotationDegreesDisplay, { visible: true, - ignoreRayIntersection: true, }); updateRotationDegreesOverlay(0, pitchHandleRotation, pitchCenter); @@ -1914,7 +1913,6 @@ SelectionDisplay = (function () { Overlays.editOverlay(rotationDegreesDisplay, { visible: true, - ignoreRayIntersection: true, }); updateRotationDegreesOverlay(0, rollHandleRotation, rollCenter); From 3fbbd6c2dee3c5ed8f759c64dedf7f7109d2eef1 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Mon, 1 Dec 2014 16:43:03 -0800 Subject: [PATCH 141/502] Working on transitioning functions to quadtree equivalents. --- libraries/metavoxels/src/SharedObject.cpp | 4 +- libraries/metavoxels/src/SharedObject.h | 3 +- libraries/metavoxels/src/Spanner.cpp | 441 ++++++++++++---------- libraries/metavoxels/src/Spanner.h | 6 +- 4 files changed, 252 insertions(+), 202 deletions(-) diff --git a/libraries/metavoxels/src/SharedObject.cpp b/libraries/metavoxels/src/SharedObject.cpp index 8f57c8be34..95dc75fec0 100644 --- a/libraries/metavoxels/src/SharedObject.cpp +++ b/libraries/metavoxels/src/SharedObject.cpp @@ -151,8 +151,8 @@ void SharedObject::writeExtraSubdivision(Bitstream& out) { // nothing by default } -void SharedObject::readExtraSubdivision(Bitstream& in) { - // nothing by default +SharedObject* SharedObject::readExtraSubdivision(Bitstream& in) { + return this; } QAtomicInt SharedObject::_nextID(1); diff --git a/libraries/metavoxels/src/SharedObject.h b/libraries/metavoxels/src/SharedObject.h index f35fde802c..cf9bf4e645 100644 --- a/libraries/metavoxels/src/SharedObject.h +++ b/libraries/metavoxels/src/SharedObject.h @@ -96,7 +96,8 @@ public: virtual void writeExtraSubdivision(Bitstream& out); /// Reads the subdivision of the non-property contents of this object from the specified stream. - virtual void readExtraSubdivision(Bitstream& in); + /// \return the modified object, or this if no modification was performed + virtual SharedObject* readExtraSubdivision(Bitstream& in); private: diff --git a/libraries/metavoxels/src/Spanner.cpp b/libraries/metavoxels/src/Spanner.cpp index bdccb18b7e..f8857a36d3 100644 --- a/libraries/metavoxels/src/Spanner.cpp +++ b/libraries/metavoxels/src/Spanner.cpp @@ -1242,6 +1242,235 @@ bool HeightfieldNode::isLeaf() const { return true; } +float HeightfieldNode::getHeight(const glm::vec3& location) const { + if (!isLeaf()) { + if (location.x < 0.5f) { + if (location.z < 0.5f) { + return _children[0]->getHeight(location * 2.0f); + } else { + return _children[Y_MAXIMUM_FLAG]->getHeight(location * 2.0f - glm::vec3(0.0f, 0.0f, 1.0f)); + } + } else { + if (location.z < 0.5f) { + return _children[X_MAXIMUM_FLAG]->getHeight(location * 2.0f - glm::vec3(1.0f, 0.0f, 0.0f)); + } else { + return _children[X_MAXIMUM_FLAG | Y_MAXIMUM_FLAG]->getHeight(location * 2.0f - glm::vec3(1.0f, 0.0f, 1.0f)); + } + } + } + if (!_height) { + return -FLT_MAX; + } + int width = _height->getWidth(); + const QVector& contents = _height->getContents(); + const quint16* src = contents.constData(); + int height = contents.size() / width; + int innerWidth = width - HeightfieldHeight::HEIGHT_EXTENSION; + int innerHeight = height - HeightfieldHeight::HEIGHT_EXTENSION; + + glm::vec3 relative = location; + relative.x = relative.x * innerWidth + HeightfieldHeight::HEIGHT_BORDER; + relative.z = relative.z * innerHeight + HeightfieldHeight::HEIGHT_BORDER; + if (relative.x < 0.0f || relative.z < 0.0f || relative.x > width - 1 || relative.z > height - 1) { + return -FLT_MAX; + } + + // find the bounds of the cell containing the point and the shared vertex heights + glm::vec3 floors = glm::floor(relative); + glm::vec3 ceils = glm::ceil(relative); + glm::vec3 fracts = glm::fract(relative); + int floorX = (int)floors.x; + int floorZ = (int)floors.z; + int ceilX = (int)ceils.x; + int ceilZ = (int)ceils.z; + float upperLeft = src[floorZ * width + floorX]; + float lowerRight = src[ceilZ * width + ceilX]; + float interpolatedHeight = glm::mix(upperLeft, lowerRight, fracts.z); + + // the final vertex (and thus which triangle we check) depends on which half we're on + if (fracts.x >= fracts.z) { + float upperRight = src[floorZ * width + ceilX]; + interpolatedHeight = glm::mix(interpolatedHeight, glm::mix(upperRight, lowerRight, fracts.z), + (fracts.x - fracts.z) / (1.0f - fracts.z)); + + } else { + float lowerLeft = src[ceilZ * width + floorX]; + interpolatedHeight = glm::mix(glm::mix(upperLeft, lowerLeft, fracts.z), interpolatedHeight, fracts.x / fracts.z); + } + if (interpolatedHeight == 0.0f) { + return -FLT_MAX; // ignore zero values + } + return interpolatedHeight / numeric_limits::max(); +} + +bool HeightfieldNode::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const { + if (!isLeaf()) { + float closestDistance = FLT_MAX; + for (int i = 0; i < CHILD_COUNT; i++) { + float childDistance; + if (_children[i]->findRayIntersection(origin * glm::vec3(2.0f, 1.0f, 2.0f) - + glm::vec3(i & X_MAXIMUM_FLAG ? 1.0f : 0.0f, 0.0f, i & Y_MAXIMUM_FLAG ? 1.0f : 0.0f), + direction * glm::vec3(2.0f, 1.0f, 2.0f), childDistance)) { + closestDistance = qMin(closestDistance, childDistance); + } + } + if (closestDistance == FLT_MAX) { + return false; + } + distance = closestDistance; + return true; + } + if (!_height) { + return false; + } + int width = _height->getWidth(); + const QVector& contents = _height->getContents(); + const quint16* src = contents.constData(); + int height = contents.size() / width; + int innerWidth = width - HeightfieldHeight::HEIGHT_EXTENSION; + int innerHeight = height - HeightfieldHeight::HEIGHT_EXTENSION; + int highestX = innerWidth + HeightfieldHeight::HEIGHT_BORDER; + int highestZ = innerHeight + HeightfieldHeight::HEIGHT_BORDER; + + glm::vec3 scale((float)innerWidth, (float)numeric_limits::max(), (float)innerHeight); + glm::vec3 dir = direction * scale; + glm::vec3 entry = origin * scale; + + float boundsDistance; + if (!Box(glm::vec3(), glm::vec3((float)innerWidth, (float)numeric_limits::max(), + (float)innerHeight)).findRayIntersection(entry, dir, boundsDistance)) { + return false; + } + entry += dir * boundsDistance; + + entry.x += HeightfieldHeight::HEIGHT_BORDER; + entry.z += HeightfieldHeight::HEIGHT_BORDER; + glm::vec3 floors = glm::floor(entry); + glm::vec3 ceils = glm::ceil(entry); + if (floors.x == ceils.x) { + if (dir.x > 0.0f) { + ceils.x += 1.0f; + } else { + floors.x -= 1.0f; + } + } + if (floors.z == ceils.z) { + if (dir.z > 0.0f) { + ceils.z += 1.0f; + } else { + floors.z -= 1.0f; + } + } + + bool withinBounds = true; + float accumulatedDistance = 0.0f; + while (withinBounds) { + // find the heights at the corners of the current cell + int floorX = qMin(qMax((int)floors.x, HeightfieldHeight::HEIGHT_BORDER), highestX); + int floorZ = qMin(qMax((int)floors.z, HeightfieldHeight::HEIGHT_BORDER), highestZ); + int ceilX = qMin(qMax((int)ceils.x, HeightfieldHeight::HEIGHT_BORDER), highestX); + int ceilZ = qMin(qMax((int)ceils.z, HeightfieldHeight::HEIGHT_BORDER), highestZ); + float upperLeft = src[floorZ * width + floorX]; + float upperRight = src[floorZ * width + ceilX]; + float lowerLeft = src[ceilZ * width + floorX]; + float lowerRight = src[ceilZ * width + ceilX]; + + // find the distance to the next x coordinate + float xDistance = FLT_MAX; + if (dir.x > 0.0f) { + xDistance = (ceils.x - entry.x) / dir.x; + } else if (dir.x < 0.0f) { + xDistance = (floors.x - entry.x) / dir.x; + } + + // and the distance to the next z coordinate + float zDistance = FLT_MAX; + if (dir.z > 0.0f) { + zDistance = (ceils.z - entry.z) / dir.z; + } else if (dir.z < 0.0f) { + zDistance = (floors.z - entry.z) / dir.z; + } + + // the exit distance is the lower of those two + float exitDistance = qMin(xDistance, zDistance); + glm::vec3 exit, nextFloors = floors, nextCeils = ceils; + if (exitDistance == FLT_MAX) { + if (dir.y > 0.0f) { + return false; // line points upwards; no collisions possible + } + withinBounds = false; // line points downwards; check this cell only + + } else { + // find the exit point and the next cell, and determine whether it's still within the bounds + exit = entry + exitDistance * dir; + withinBounds = (exit.y >= 0.0f && exit.y <= numeric_limits::max()); + if (exitDistance == xDistance) { + if (dir.x > 0.0f) { + nextFloors.x += 1.0f; + withinBounds &= (nextCeils.x += 1.0f) <= highestX; + } else { + withinBounds &= (nextFloors.x -= 1.0f) >= HeightfieldHeight::HEIGHT_BORDER; + nextCeils.x -= 1.0f; + } + } + if (exitDistance == zDistance) { + if (dir.z > 0.0f) { + nextFloors.z += 1.0f; + withinBounds &= (nextCeils.z += 1.0f) <= highestZ; + } else { + withinBounds &= (nextFloors.z -= 1.0f) >= HeightfieldHeight::HEIGHT_BORDER; + nextCeils.z -= 1.0f; + } + } + // check the vertical range of the ray against the ranges of the cell heights + if (qMin(entry.y, exit.y) > qMax(qMax(upperLeft, upperRight), qMax(lowerLeft, lowerRight)) || + qMax(entry.y, exit.y) < qMin(qMin(upperLeft, upperRight), qMin(lowerLeft, lowerRight))) { + entry = exit; + floors = nextFloors; + ceils = nextCeils; + accumulatedDistance += exitDistance; + continue; + } + } + // having passed the bounds check, we must check against the planes + glm::vec3 relativeEntry = entry - glm::vec3(floors.x, upperLeft, floors.z); + + // first check the triangle including the Z+ segment + glm::vec3 lowerNormal(lowerLeft - lowerRight, 1.0f, upperLeft - lowerLeft); + float lowerProduct = glm::dot(lowerNormal, dir); + if (lowerProduct < 0.0f) { + float planeDistance = -glm::dot(lowerNormal, relativeEntry) / lowerProduct; + glm::vec3 intersection = relativeEntry + planeDistance * dir; + if (intersection.x >= 0.0f && intersection.x <= 1.0f && intersection.z >= 0.0f && intersection.z <= 1.0f && + intersection.z >= intersection.x) { + distance = boundsDistance + accumulatedDistance + planeDistance; + return true; + } + } + + // then the one with the X+ segment + glm::vec3 upperNormal(upperLeft - upperRight, 1.0f, upperRight - lowerRight); + float upperProduct = glm::dot(upperNormal, dir); + if (upperProduct < 0.0f) { + float planeDistance = -glm::dot(upperNormal, relativeEntry) / upperProduct; + glm::vec3 intersection = relativeEntry + planeDistance * dir; + if (intersection.x >= 0.0f && intersection.x <= 1.0f && intersection.z >= 0.0f && intersection.z <= 1.0f && + intersection.x >= intersection.z) { + distance = boundsDistance + accumulatedDistance + planeDistance; + return true; + } + } + + // no joy; continue on our way + entry = exit; + floors = nextFloors; + ceils = nextCeils; + accumulatedDistance += exitDistance; + } + + return false; +} + void HeightfieldNode::read(HeightfieldStreamState& state) { clearChildren(); @@ -1704,206 +1933,16 @@ bool Heightfield::isHeightfield() const { } float Heightfield::getHeight(const glm::vec3& location) const { - if (!_height) { - return -FLT_MAX; - } - int width = _height->getWidth(); - const QVector& contents = _height->getContents(); - const quint16* src = contents.constData(); - int height = contents.size() / width; - int innerWidth = width - HeightfieldHeight::HEIGHT_EXTENSION; - int innerHeight = height - HeightfieldHeight::HEIGHT_EXTENSION; - - glm::vec3 relative = glm::inverse(getRotation()) * (location - getTranslation()) * glm::vec3(1.0f / getScale(), - 1.0f, 1.0f / (getScale() * _aspectZ)); - relative.x = relative.x * innerWidth + HeightfieldHeight::HEIGHT_BORDER; - relative.z = relative.z * innerHeight + HeightfieldHeight::HEIGHT_BORDER; - if (relative.x < 0.0f || relative.z < 0.0f || relative.x > width - 1 || relative.z > height - 1) { - return -FLT_MAX; - } - - // find the bounds of the cell containing the point and the shared vertex heights - glm::vec3 floors = glm::floor(relative); - glm::vec3 ceils = glm::ceil(relative); - glm::vec3 fracts = glm::fract(relative); - int floorX = (int)floors.x; - int floorZ = (int)floors.z; - int ceilX = (int)ceils.x; - int ceilZ = (int)ceils.z; - float upperLeft = src[floorZ * width + floorX]; - float lowerRight = src[ceilZ * width + ceilX]; - float interpolatedHeight = glm::mix(upperLeft, lowerRight, fracts.z); - - // the final vertex (and thus which triangle we check) depends on which half we're on - if (fracts.x >= fracts.z) { - float upperRight = src[floorZ * width + ceilX]; - interpolatedHeight = glm::mix(interpolatedHeight, glm::mix(upperRight, lowerRight, fracts.z), - (fracts.x - fracts.z) / (1.0f - fracts.z)); - - } else { - float lowerLeft = src[ceilZ * width + floorX]; - interpolatedHeight = glm::mix(glm::mix(upperLeft, lowerLeft, fracts.z), interpolatedHeight, fracts.x / fracts.z); - } - if (interpolatedHeight == 0.0f) { - return -FLT_MAX; // ignore zero values - } - - // convert the interpolated height into world space - return getTranslation().y + interpolatedHeight * getScale() * _aspectY / numeric_limits::max(); + float result = _root->getHeight(glm::inverse(getRotation()) * (location - getTranslation()) * glm::vec3(1.0f / getScale(), + 0.0f, 1.0f / (getScale() * _aspectZ))); + return (result == -FLT_MAX) ? -FLT_MAX : (getTranslation().y + result * getScale() * _aspectY); } bool Heightfield::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const { - if (!_height) { - return false; - } - int width = _height->getWidth(); - const QVector& contents = _height->getContents(); - const quint16* src = contents.constData(); - int height = contents.size() / width; - int innerWidth = width - HeightfieldHeight::HEIGHT_EXTENSION; - int innerHeight = height - HeightfieldHeight::HEIGHT_EXTENSION; - int highestX = innerWidth + HeightfieldHeight::HEIGHT_BORDER; - int highestZ = innerHeight + HeightfieldHeight::HEIGHT_BORDER; - glm::quat inverseRotation = glm::inverse(getRotation()); - glm::vec3 inverseScale(innerWidth / getScale(), numeric_limits::max() / (getScale() * _aspectY), - innerHeight / (getScale() * _aspectZ)); - glm::vec3 dir = inverseRotation * direction * inverseScale; - glm::vec3 entry = inverseRotation * (origin - getTranslation()) * inverseScale; - - float boundsDistance; - if (!Box(glm::vec3(), glm::vec3((float)innerWidth, (float)numeric_limits::max(), - (float)innerHeight)).findRayIntersection(entry, dir, boundsDistance)) { - return false; - } - entry += dir * boundsDistance; - - entry.x += HeightfieldHeight::HEIGHT_BORDER; - entry.z += HeightfieldHeight::HEIGHT_BORDER; - glm::vec3 floors = glm::floor(entry); - glm::vec3 ceils = glm::ceil(entry); - if (floors.x == ceils.x) { - if (dir.x > 0.0f) { - ceils.x += 1.0f; - } else { - floors.x -= 1.0f; - } - } - if (floors.z == ceils.z) { - if (dir.z > 0.0f) { - ceils.z += 1.0f; - } else { - floors.z -= 1.0f; - } - } - - bool withinBounds = true; - float accumulatedDistance = 0.0f; - while (withinBounds) { - // find the heights at the corners of the current cell - int floorX = qMin(qMax((int)floors.x, HeightfieldHeight::HEIGHT_BORDER), highestX); - int floorZ = qMin(qMax((int)floors.z, HeightfieldHeight::HEIGHT_BORDER), highestZ); - int ceilX = qMin(qMax((int)ceils.x, HeightfieldHeight::HEIGHT_BORDER), highestX); - int ceilZ = qMin(qMax((int)ceils.z, HeightfieldHeight::HEIGHT_BORDER), highestZ); - float upperLeft = src[floorZ * width + floorX]; - float upperRight = src[floorZ * width + ceilX]; - float lowerLeft = src[ceilZ * width + floorX]; - float lowerRight = src[ceilZ * width + ceilX]; - - // find the distance to the next x coordinate - float xDistance = FLT_MAX; - if (dir.x > 0.0f) { - xDistance = (ceils.x - entry.x) / dir.x; - } else if (dir.x < 0.0f) { - xDistance = (floors.x - entry.x) / dir.x; - } - - // and the distance to the next z coordinate - float zDistance = FLT_MAX; - if (dir.z > 0.0f) { - zDistance = (ceils.z - entry.z) / dir.z; - } else if (dir.z < 0.0f) { - zDistance = (floors.z - entry.z) / dir.z; - } - - // the exit distance is the lower of those two - float exitDistance = qMin(xDistance, zDistance); - glm::vec3 exit, nextFloors = floors, nextCeils = ceils; - if (exitDistance == FLT_MAX) { - if (dir.y > 0.0f) { - return false; // line points upwards; no collisions possible - } - withinBounds = false; // line points downwards; check this cell only - - } else { - // find the exit point and the next cell, and determine whether it's still within the bounds - exit = entry + exitDistance * dir; - withinBounds = (exit.y >= 0.0f && exit.y <= numeric_limits::max()); - if (exitDistance == xDistance) { - if (dir.x > 0.0f) { - nextFloors.x += 1.0f; - withinBounds &= (nextCeils.x += 1.0f) <= highestX; - } else { - withinBounds &= (nextFloors.x -= 1.0f) >= HeightfieldHeight::HEIGHT_BORDER; - nextCeils.x -= 1.0f; - } - } - if (exitDistance == zDistance) { - if (dir.z > 0.0f) { - nextFloors.z += 1.0f; - withinBounds &= (nextCeils.z += 1.0f) <= highestZ; - } else { - withinBounds &= (nextFloors.z -= 1.0f) >= HeightfieldHeight::HEIGHT_BORDER; - nextCeils.z -= 1.0f; - } - } - // check the vertical range of the ray against the ranges of the cell heights - if (qMin(entry.y, exit.y) > qMax(qMax(upperLeft, upperRight), qMax(lowerLeft, lowerRight)) || - qMax(entry.y, exit.y) < qMin(qMin(upperLeft, upperRight), qMin(lowerLeft, lowerRight))) { - entry = exit; - floors = nextFloors; - ceils = nextCeils; - accumulatedDistance += exitDistance; - continue; - } - } - // having passed the bounds check, we must check against the planes - glm::vec3 relativeEntry = entry - glm::vec3(floors.x, upperLeft, floors.z); - - // first check the triangle including the Z+ segment - glm::vec3 lowerNormal(lowerLeft - lowerRight, 1.0f, upperLeft - lowerLeft); - float lowerProduct = glm::dot(lowerNormal, dir); - if (lowerProduct < 0.0f) { - float planeDistance = -glm::dot(lowerNormal, relativeEntry) / lowerProduct; - glm::vec3 intersection = relativeEntry + planeDistance * dir; - if (intersection.x >= 0.0f && intersection.x <= 1.0f && intersection.z >= 0.0f && intersection.z <= 1.0f && - intersection.z >= intersection.x) { - distance = boundsDistance + accumulatedDistance + planeDistance; - return true; - } - } - - // then the one with the X+ segment - glm::vec3 upperNormal(upperLeft - upperRight, 1.0f, upperRight - lowerRight); - float upperProduct = glm::dot(upperNormal, dir); - if (upperProduct < 0.0f) { - float planeDistance = -glm::dot(upperNormal, relativeEntry) / upperProduct; - glm::vec3 intersection = relativeEntry + planeDistance * dir; - if (intersection.x >= 0.0f && intersection.x <= 1.0f && intersection.z >= 0.0f && intersection.z <= 1.0f && - intersection.x >= intersection.z) { - distance = boundsDistance + accumulatedDistance + planeDistance; - return true; - } - } - - // no joy; continue on our way - entry = exit; - floors = nextFloors; - ceils = nextCeils; - accumulatedDistance += exitDistance; - } - - return false; + glm::vec3 inverseScale(1.0f / getScale(), 1.0f / (getScale() * _aspectY), 1.0f / (getScale() * _aspectZ)); + return _root->findRayIntersection(inverseRotation * (origin - getTranslation()) * inverseScale, + inverseRotation * direction * inverseScale, distance); } Spanner* Heightfield::paintMaterial(const glm::vec3& position, float radius, @@ -2747,7 +2786,7 @@ void Heightfield::writeExtraSubdivision(Bitstream& out) { } } -void Heightfield::readExtraSubdivision(Bitstream& in) { +SharedObject* Heightfield::readExtraSubdivision(Bitstream& in) { MetavoxelLOD lod, referenceLOD; if (in.getContext()) { MetavoxelStreamBase* base = static_cast(in.getContext()); @@ -2758,8 +2797,14 @@ void Heightfield::readExtraSubdivision(Bitstream& in) { HeightfieldStreamState state = { base, glm::vec2(), 1.0f }; if (state.becameSubdividedOrCollapsed()) { - setRoot(HeightfieldNodePointer(_root->readSubdivision(state))); + HeightfieldNodePointer root(_root->readSubdivision(state)); + if (_root != root) { + Heightfield* newHeightfield = static_cast(clone(true)); + newHeightfield->setRoot(root); + return newHeightfield; + } } + return this; } QByteArray Heightfield::getRendererClassName() const { diff --git a/libraries/metavoxels/src/Spanner.h b/libraries/metavoxels/src/Spanner.h index c832d3fbd5..be8602d3a4 100644 --- a/libraries/metavoxels/src/Spanner.h +++ b/libraries/metavoxels/src/Spanner.h @@ -505,6 +505,10 @@ public: const HeightfieldNodePointer& getChild(int index) const { return _children[index]; } + float getHeight(const glm::vec3& location) const; + + bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const; + void read(HeightfieldStreamState& state); void write(HeightfieldStreamState& state) const; @@ -593,7 +597,7 @@ public: virtual void writeExtraDelta(Bitstream& out, const SharedObject* reference) const; virtual void readExtraDelta(Bitstream& in, const SharedObject* reference); virtual void writeExtraSubdivision(Bitstream& out); - virtual void readExtraSubdivision(Bitstream& in); + virtual SharedObject* readExtraSubdivision(Bitstream& in); signals: From 46f1fc7c0f6ab1c9c27ae0cbccd64a119fbb1cda Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Mon, 1 Dec 2014 18:50:24 -0800 Subject: [PATCH 142/502] More work on spanner heightfield edits. --- libraries/metavoxels/src/Spanner.cpp | 238 +++++++++++++++------------ libraries/metavoxels/src/Spanner.h | 11 +- 2 files changed, 147 insertions(+), 102 deletions(-) diff --git a/libraries/metavoxels/src/Spanner.cpp b/libraries/metavoxels/src/Spanner.cpp index f8857a36d3..9e1248524f 100644 --- a/libraries/metavoxels/src/Spanner.cpp +++ b/libraries/metavoxels/src/Spanner.cpp @@ -1471,6 +1471,132 @@ bool HeightfieldNode::findRayIntersection(const glm::vec3& origin, const glm::ve return false; } +HeightfieldNode* HeightfieldNode::paintMaterial(const glm::vec3& position, const glm::vec3& radius, + const SharedObjectPointer& material, const QColor& color) { + if (!isLeaf()) { + HeightfieldNode* newNode = this; + for (int i = 0; i < CHILD_COUNT; i++) { + HeightfieldNode* newChild = _children[i]->paintMaterial(position * glm::vec3(2.0f, 1.0f, 2.0f) - + glm::vec3(i & X_MAXIMUM_FLAG ? 1.0f : 0.0f, 0.0f, i & Y_MAXIMUM_FLAG ? 1.0f : 0.0f), + radius * glm::vec3(2.0f, 1.0f, 2.0f), material, color); + if (_children[i] != newChild) { + if (newNode == this) { + newNode = new HeightfieldNode(*this); + } + newNode->setChild(i, HeightfieldNodePointer(newChild)); + } + } + if (newNode != this) { + newNode->mergeChildren(false, true); + } + return newNode; + } + if (!_height || position.x + radius.x < 0.0f || position.z + radius.z < 0.0f || + position.x - radius.x > 1.0f || position.z - radius.z > 1.0f) { + return this; + } + int heightWidth = _height->getWidth(); + int heightHeight = _height->getContents().size() / heightWidth; + int baseWidth = heightWidth - HeightfieldHeight::HEIGHT_EXTENSION + HeightfieldData::SHARED_EDGE; + int baseHeight = heightHeight - HeightfieldHeight::HEIGHT_EXTENSION + HeightfieldData::SHARED_EDGE; + HeightfieldNode* newNode = new HeightfieldNode(*this); + + int colorWidth = baseWidth, colorHeight = baseHeight; + QByteArray colorContents; + if (_color) { + colorWidth = _color->getWidth(); + colorHeight = _color->getContents().size() / (colorWidth * DataBlock::COLOR_BYTES); + colorContents = _color->getContents(); + + } else { + colorContents = QByteArray(baseWidth * baseHeight * DataBlock::COLOR_BYTES, 0xFF); + } + + int materialWidth = baseWidth, materialHeight = baseHeight; + QByteArray materialContents; + QVector materials; + if (_material) { + materialWidth = _material->getWidth(); + materialHeight = _material->getContents().size() / materialWidth; + materialContents = _material->getContents(); + materials = _material->getMaterials(); + + } else { + materialContents = QByteArray(baseWidth * baseHeight, 0); + } + + int highestX = colorWidth - 1; + int highestZ = colorHeight - 1; + glm::vec3 scale((float)highestX, 1.0f, (float)highestZ); + glm::vec3 center = position * scale; + + glm::vec3 extents = radius * scale; + glm::vec3 start = glm::floor(center - extents); + glm::vec3 end = glm::ceil(center + extents); + + // paint all points within the radius + float z = qMax(start.z, 0.0f); + float startX = qMax(start.x, 0.0f), endX = qMin(end.x, (float)highestX); + int stride = colorWidth * DataBlock::COLOR_BYTES; + uchar* lineDest = (uchar*)colorContents.data() + (int)z * stride + (int)startX * DataBlock::COLOR_BYTES; + float squaredRadius = extents.x * extents.x; + float multiplierZ = extents.x / extents.z; + char red = color.red(), green = color.green(), blue = color.blue(); + bool changed = false; + for (float endZ = qMin(end.z, (float)highestZ); z <= endZ; z += 1.0f) { + uchar* dest = lineDest; + for (float x = startX; x <= endX; x += 1.0f, dest += DataBlock::COLOR_BYTES) { + float dx = x - center.x, dz = (z - center.z) * multiplierZ; + if (dx * dx + dz * dz <= squaredRadius) { + dest[0] = red; + dest[1] = green; + dest[2] = blue; + changed = true; + } + } + lineDest += stride; + } + if (changed) { + newNode->setColor(HeightfieldColorPointer(new HeightfieldColor(colorWidth, colorContents))); + } + + highestX = materialWidth - 1; + highestZ = materialHeight - 1; + scale = glm::vec3((float)highestX, 1.0f, (float)highestZ); + center = position * scale; + + extents = radius * scale; + start = glm::floor(center - extents); + end = glm::ceil(center + extents); + + // paint all points within the radius + z = qMax(start.z, 0.0f); + startX = qMax(start.x, 0.0f), endX = qMin(end.x, (float)highestX); + lineDest = (uchar*)materialContents.data() + (int)z * materialWidth + (int)startX; + squaredRadius = extents.x * extents.x; + multiplierZ = extents.x / extents.z; + uchar materialIndex = getMaterialIndex(material, materials, materialContents); + changed = false; + for (float endZ = qMin(end.z, (float)highestZ); z <= endZ; z += 1.0f) { + uchar* dest = lineDest; + for (float x = startX; x <= endX; x += 1.0f, dest++) { + float dx = x - center.x, dz = (z - center.z) * multiplierZ; + if (dx * dx + dz * dz <= squaredRadius) { + *dest = materialIndex; + changed = true; + } + } + lineDest += materialWidth; + } + if (changed) { + clearUnusedMaterials(materials, materialContents); + newNode->setMaterial(HeightfieldMaterialPointer(new HeightfieldMaterial(materialWidth, + materialContents, materials))); + } + + return newNode; +} + void HeightfieldNode::read(HeightfieldStreamState& state) { clearChildren(); @@ -1718,7 +1844,7 @@ void HeightfieldNode::clearChildren() { } } -void HeightfieldNode::mergeChildren() { +void HeightfieldNode::mergeChildren(bool height, bool colorMaterial) { if (isLeaf()) { return; } @@ -1751,7 +1877,7 @@ void HeightfieldNode::mergeChildren() { materialHeight = qMax(materialHeight, childMaterialHeight); } } - if (heightWidth > 0) { + if (heightWidth > 0 && height) { QVector heightContents(heightWidth * heightHeight); for (int i = 0; i < CHILD_COUNT; i++) { HeightfieldHeightPointer childHeight = _children[i]->getHeight(); @@ -1780,9 +1906,12 @@ void HeightfieldNode::mergeChildren() { } _height = new HeightfieldHeight(heightWidth, heightContents); - } else { + } else if (height) { _height.reset(); } + if (!colorMaterial) { + return; + } if (colorWidth > 0) { QByteArray colorContents(colorWidth * colorHeight * DataBlock::COLOR_BYTES, 0); for (int i = 0; i < CHILD_COUNT; i++) { @@ -1947,107 +2076,14 @@ bool Heightfield::findRayIntersection(const glm::vec3& origin, const glm::vec3& Spanner* Heightfield::paintMaterial(const glm::vec3& position, float radius, const SharedObjectPointer& material, const QColor& color) { - if (!_height) { + glm::vec3 inverseScale(1.0f / getScale(), 1.0f, 1.0f / getScale() * _aspectZ); + HeightfieldNode* newRoot = _root->paintMaterial(glm::inverse(getRotation()) * (position - getTranslation()) * + inverseScale, radius * inverseScale, material, color); + if (_root == newRoot) { return this; } - int heightWidth = _height->getWidth(); - int heightHeight = _height->getContents().size() / heightWidth; - int baseWidth = heightWidth - HeightfieldHeight::HEIGHT_EXTENSION + HeightfieldData::SHARED_EDGE; - int baseHeight = heightHeight - HeightfieldHeight::HEIGHT_EXTENSION + HeightfieldData::SHARED_EDGE; Heightfield* newHeightfield = static_cast(clone(true)); - - int colorWidth = baseWidth, colorHeight = baseHeight; - QByteArray colorContents; - if (_color) { - colorWidth = _color->getWidth(); - colorHeight = _color->getContents().size() / (colorWidth * DataBlock::COLOR_BYTES); - colorContents = _color->getContents(); - - } else { - colorContents = QByteArray(baseWidth * baseHeight * DataBlock::COLOR_BYTES, 0xFF); - } - - int materialWidth = baseWidth, materialHeight = baseHeight; - QByteArray materialContents; - QVector materials; - if (_material) { - materialWidth = _material->getWidth(); - materialHeight = _material->getContents().size() / materialWidth; - materialContents = _material->getContents(); - materials = _material->getMaterials(); - - } else { - materialContents = QByteArray(baseWidth * baseHeight, 0); - } - - int highestX = colorWidth - 1; - int highestZ = colorHeight - 1; - glm::vec3 inverseScale(highestX / getScale(), 1.0f, highestZ / (getScale() * _aspectZ)); - glm::vec3 center = glm::inverse(getRotation()) * (position - getTranslation()) * inverseScale; - - glm::vec3 extents = glm::vec3(radius, radius, radius) * inverseScale; - glm::vec3 start = glm::floor(center - extents); - glm::vec3 end = glm::ceil(center + extents); - - // paint all points within the radius - float z = qMax(start.z, 0.0f); - float startX = qMax(start.x, 0.0f), endX = qMin(end.x, (float)highestX); - int stride = colorWidth * DataBlock::COLOR_BYTES; - uchar* lineDest = (uchar*)colorContents.data() + (int)z * stride + (int)startX * DataBlock::COLOR_BYTES; - float squaredRadius = extents.x * extents.x; - float multiplierZ = inverseScale.x / inverseScale.z; - char red = color.red(), green = color.green(), blue = color.blue(); - bool changed = false; - for (float endZ = qMin(end.z, (float)highestZ); z <= endZ; z += 1.0f) { - uchar* dest = lineDest; - for (float x = startX; x <= endX; x += 1.0f, dest += DataBlock::COLOR_BYTES) { - float dx = x - center.x, dz = (z - center.z) * multiplierZ; - if (dx * dx + dz * dz <= squaredRadius) { - dest[0] = red; - dest[1] = green; - dest[2] = blue; - changed = true; - } - } - lineDest += stride; - } - if (changed) { - newHeightfield->setColor(HeightfieldColorPointer(new HeightfieldColor(colorWidth, colorContents))); - } - - highestX = materialWidth - 1; - highestZ = materialHeight - 1; - inverseScale = glm::vec3(highestX / getScale(), 1.0f, highestZ / (getScale() * _aspectZ)); - center = glm::inverse(getRotation()) * (position - getTranslation()) * inverseScale; - - extents = glm::vec3(radius, radius, radius) * inverseScale; - start = glm::floor(center - extents); - end = glm::ceil(center + extents); - - // paint all points within the radius - z = qMax(start.z, 0.0f); - startX = qMax(start.x, 0.0f), endX = qMin(end.x, (float)highestX); - lineDest = (uchar*)materialContents.data() + (int)z * materialWidth + (int)startX; - squaredRadius = extents.x * extents.x; - uchar materialIndex = getMaterialIndex(material, materials, materialContents); - changed = false; - for (float endZ = qMin(end.z, (float)highestZ); z <= endZ; z += 1.0f) { - uchar* dest = lineDest; - for (float x = startX; x <= endX; x += 1.0f, dest++) { - float dx = x - center.x, dz = (z - center.z) * multiplierZ; - if (dx * dx + dz * dz <= squaredRadius) { - *dest = materialIndex; - changed = true; - } - } - lineDest += materialWidth; - } - if (changed) { - clearUnusedMaterials(materials, materialContents); - newHeightfield->setMaterial(HeightfieldMaterialPointer(new HeightfieldMaterial(materialWidth, - materialContents, materials))); - } - + newHeightfield->setRoot(HeightfieldNodePointer(newRoot)); return newHeightfield; } diff --git a/libraries/metavoxels/src/Spanner.h b/libraries/metavoxels/src/Spanner.h index be8602d3a4..2173bd67e9 100644 --- a/libraries/metavoxels/src/Spanner.h +++ b/libraries/metavoxels/src/Spanner.h @@ -497,18 +497,27 @@ public: void setContents(const HeightfieldHeightPointer& height, const HeightfieldColorPointer& color, const HeightfieldMaterialPointer& material); + void setHeight(const HeightfieldHeightPointer& height) { _height = height; } const HeightfieldHeightPointer& getHeight() const { return _height; } + + void setColor(const HeightfieldColorPointer& color) { _color = color; } const HeightfieldColorPointer& getColor() const { return _color; } + + void setMaterial(const HeightfieldMaterialPointer& material) { _material = material; } const HeightfieldMaterialPointer& getMaterial() const { return _material; } bool isLeaf() const; + void setChild(int index, const HeightfieldNodePointer& child) { _children[index] = child; } const HeightfieldNodePointer& getChild(int index) const { return _children[index]; } float getHeight(const glm::vec3& location) const; bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const; + HeightfieldNode* paintMaterial(const glm::vec3& position, const glm::vec3& radius, const SharedObjectPointer& material, + const QColor& color); + void read(HeightfieldStreamState& state); void write(HeightfieldStreamState& state) const; @@ -526,7 +535,7 @@ public: private: void clearChildren(); - void mergeChildren(); + void mergeChildren(bool height = true, bool colorMaterial = true); HeightfieldHeightPointer _height; HeightfieldColorPointer _color; From a46b46b5a2b1bfaf453aea440956723a4e481167 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Mon, 1 Dec 2014 19:10:10 -0800 Subject: [PATCH 143/502] Fix for merging. --- libraries/metavoxels/src/Spanner.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libraries/metavoxels/src/Spanner.cpp b/libraries/metavoxels/src/Spanner.cpp index 9e1248524f..301959b16f 100644 --- a/libraries/metavoxels/src/Spanner.cpp +++ b/libraries/metavoxels/src/Spanner.cpp @@ -1913,9 +1913,12 @@ void HeightfieldNode::mergeChildren(bool height, bool colorMaterial) { return; } if (colorWidth > 0) { - QByteArray colorContents(colorWidth * colorHeight * DataBlock::COLOR_BYTES, 0); + QByteArray colorContents(colorWidth * colorHeight * DataBlock::COLOR_BYTES, 0xFF); for (int i = 0; i < CHILD_COUNT; i++) { HeightfieldColorPointer childColor = _children[i]->getColor(); + if (!childColor) { + continue; + } int childColorWidth = childColor->getWidth(); int childColorHeight = childColor->getContents().size() / (childColorWidth * DataBlock::COLOR_BYTES); if (childColorWidth != colorWidth || childColorHeight != colorHeight) { @@ -1953,6 +1956,9 @@ void HeightfieldNode::mergeChildren(bool height, bool colorMaterial) { QVector materials; for (int i = 0; i < CHILD_COUNT; i++) { HeightfieldMaterialPointer childMaterial = _children[i]->getMaterial(); + if (!childMaterial) { + continue; + } int childMaterialWidth = childMaterial->getWidth(); int childMaterialHeight = childMaterial->getContents().size() / childMaterialWidth; if (childMaterialWidth != materialWidth || childMaterialHeight != materialHeight) { From 526664ac57c39113a357f50e5e5e5f52724a8b6d Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 1 Dec 2014 22:11:34 -0800 Subject: [PATCH 144/502] delete old dead code --- interface/src/Application.cpp | 6 ------ interface/src/avatar/Avatar.cpp | 7 ------- interface/src/avatar/Avatar.h | 3 --- interface/src/avatar/AvatarManager.cpp | 1 - interface/src/avatar/MyAvatar.cpp | 1 - interface/src/avatar/MyAvatar.h | 4 ---- 6 files changed, 22 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 20ae07b0c9..ab18c68a10 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2084,12 +2084,6 @@ void Application::updateMouseRay() { _mouseRayDirection -= 2.0f * (_viewFrustum.getDirection() * glm::dot(_viewFrustum.getDirection(), _mouseRayDirection) + _viewFrustum.getRight() * glm::dot(_viewFrustum.getRight(), _mouseRayDirection)); } - - // tell my avatar if the mouse is being pressed... - _myAvatar->setMousePressed(_mousePressed); - - // tell my avatar the posiion and direction of the ray projected ino the world based on the mouse position - _myAvatar->setMouseRay(_mouseRayOrigin, _mouseRayDirection); } void Application::updateFaceshift() { diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 03243c1a83..c680c75056 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -66,8 +66,6 @@ Avatar::Avatar() : _leanScale(0.5f), _scale(1.0f), _worldUpDirection(DEFAULT_UP_DIRECTION), - _mouseRayOrigin(0.0f, 0.0f, 0.0f), - _mouseRayDirection(0.0f, 0.0f, 0.0f), _moving(false), _collisionGroups(0), _initialized(false), @@ -250,11 +248,6 @@ void Avatar::measureMotionDerivatives(float deltaTime) { _lastOrientation = getOrientation(); } -void Avatar::setMouseRay(const glm::vec3 &origin, const glm::vec3 &direction) { - _mouseRayOrigin = origin; - _mouseRayDirection = direction; -} - enum TextRendererType { CHAT, DISPLAYNAME diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index 2d1a44403f..88ab3b12ca 100644 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -85,7 +85,6 @@ public: //setters void setDisplayingLookatVectors(bool displayingLookatVectors) { getHead()->setRenderLookatVectors(displayingLookatVectors); } - void setMouseRay(const glm::vec3 &origin, const glm::vec3 &direction); void setIsLookAtTarget(const bool isLookAtTarget) { _isLookAtTarget = isLookAtTarget; } bool getIsLookAtTarget() const { return _isLookAtTarget; } //getters @@ -213,8 +212,6 @@ protected: float _leanScale; float _scale; glm::vec3 _worldUpDirection; - glm::vec3 _mouseRayOrigin; - glm::vec3 _mouseRayDirection; float _stringLength; bool _moving; ///< set when position is changing diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index ba5ba8141d..25916d761c 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -87,7 +87,6 @@ void AvatarManager::updateOtherAvatars(float deltaTime) { if (!shouldKillAvatar(sharedAvatar)) { // this avatar's mixer is still around, go ahead and simulate it avatar->simulate(deltaTime); - avatar->setMouseRay(mouseOrigin, mouseDirection); ++avatarIterator; } else { // the mixer that owned this avatar is gone, give it to the vector of fades and kill it diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 3301cf0347..880331deb9 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -67,7 +67,6 @@ const int SCRIPTED_MOTOR_WORLD_FRAME = 2; MyAvatar::MyAvatar() : Avatar(), - _mousePressed(false), _bodyPitchDelta(0.0f), _bodyRollDelta(0.0f), _gravity(0.0f, 0.0f, 0.0f), diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index dd1178c7b5..7e05389102 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -55,15 +55,12 @@ public: void renderHeadMouse(int screenWidth, int screenHeight) const; // setters - void setMousePressed(bool mousePressed) { _mousePressed = mousePressed; } void setLeanScale(float scale) { _leanScale = scale; } void setLocalGravity(glm::vec3 gravity); void setShouldRenderLocally(bool shouldRender) { _shouldRender = shouldRender; } // getters float getLeanScale() const { return _leanScale; } - const glm::vec3& getMouseRayOrigin() const { return _mouseRayOrigin; } - const glm::vec3& getMouseRayDirection() const { return _mouseRayDirection; } glm::vec3 getGravity() const { return _gravity; } glm::vec3 getDefaultEyePosition() const; bool getShouldRenderLocally() const { return _shouldRender; } @@ -203,7 +200,6 @@ protected: virtual void renderAttachments(RenderMode renderMode); private: - bool _mousePressed; float _bodyPitchDelta; // degrees float _bodyRollDelta; // degrees glm::vec3 _gravity; From 36f716cd6165e846a4bb475a08c217de20a37001 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 2 Dec 2014 10:13:43 -0800 Subject: [PATCH 145/502] have script loading be separate from ScriptEngine constructor --- libraries/script-engine/src/ScriptEngine.cpp | 114 ++++++++----------- libraries/script-engine/src/ScriptEngine.h | 8 +- 2 files changed, 54 insertions(+), 68 deletions(-) diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index e6002d7c10..fefe8e2103 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -100,71 +100,6 @@ ScriptEngine::ScriptEngine(const QString& scriptContents, const QString& fileNam { } -ScriptEngine::ScriptEngine(const QUrl& scriptURL, - AbstractControllerScriptingInterface* controllerScriptingInterface) : - _scriptContents(), - _isFinished(false), - _isRunning(false), - _isInitialized(false), - _isAvatar(false), - _avatarIdentityTimer(NULL), - _avatarBillboardTimer(NULL), - _timerFunctionMap(), - _isListeningToAudioStream(false), - _avatarSound(NULL), - _numAvatarSoundSentBytes(0), - _controllerScriptingInterface(controllerScriptingInterface), - _avatarData(NULL), - _scriptName(), - _fileNameString(), - _quatLibrary(), - _vec3Library(), - _uuidLibrary(), - _animationCache(this), - _isUserLoaded(false), - _arrayBufferClass(new ArrayBufferClass(this)) -{ - QString scriptURLString = scriptURL.toString(); - _fileNameString = scriptURLString; - - QUrl url(scriptURL); - - // if the scheme length is one or lower, maybe they typed in a file, let's try - const int WINDOWS_DRIVE_LETTER_SIZE = 1; - if (url.scheme().size() <= WINDOWS_DRIVE_LETTER_SIZE) { - url = QUrl::fromLocalFile(scriptURLString); - } - - // ok, let's see if it's valid... and if so, load it - if (url.isValid()) { - if (url.scheme() == "file") { - QString fileName = url.toLocalFile(); - QFile scriptFile(fileName); - if (scriptFile.open(QFile::ReadOnly | QFile::Text)) { - qDebug() << "Loading file:" << fileName; - QTextStream in(&scriptFile); - _scriptContents = in.readAll(); - } else { - qDebug() << "ERROR Loading file:" << fileName; - emit errorMessage("ERROR Loading file:" + fileName); - } - } else { - QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); - QNetworkReply* reply = networkAccessManager.get(QNetworkRequest(url)); - qDebug() << "Downloading script at" << url; - QEventLoop loop; - QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit())); - loop.exec(); - if (reply->error() == QNetworkReply::NoError && reply->attribute(QNetworkRequest::HttpStatusCodeAttribute) == 200) { - _scriptContents = reply->readAll(); - } else { - qDebug() << "ERROR Loading file:" << url.toString(); - emit errorMessage("ERROR Loading file:" + url.toString()); - } - } - } -} - void ScriptEngine::setIsAvatar(bool isAvatar) { _isAvatar = isAvatar; @@ -217,6 +152,55 @@ bool ScriptEngine::setScriptContents(const QString& scriptContents, const QStrin return true; } +void ScriptEngine::loadURL(const QUrl& scriptURL) { + if (_isRunning) { + return; + } + + QString scriptURLString = scriptURL.toString(); + _fileNameString = scriptURLString; + + QUrl url(scriptURL); + + // if the scheme length is one or lower, maybe they typed in a file, let's try + const int WINDOWS_DRIVE_LETTER_SIZE = 1; + if (url.scheme().size() <= WINDOWS_DRIVE_LETTER_SIZE) { + url = QUrl::fromLocalFile(scriptURLString); + } + + // ok, let's see if it's valid... and if so, load it + if (url.isValid()) { + if (url.scheme() == "file") { + QString fileName = url.toLocalFile(); + QFile scriptFile(fileName); + if (scriptFile.open(QFile::ReadOnly | QFile::Text)) { + qDebug() << "Loading file:" << fileName; + QTextStream in(&scriptFile); + _scriptContents = in.readAll(); + emit scriptLoaded(); + } else { + qDebug() << "ERROR Loading file:" << fileName; + emit errorLoadingScript(); + } + } else { + QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); + QNetworkReply* reply = networkAccessManager.get(QNetworkRequest(url)); + connect(reply, &QNetworkReply::finished, this, &ScriptEngine::handleScriptDownload); + } + } +} + +void ScriptEngine::handleScriptDownload() { + QNetworkReply* reply = qobject_cast(sender()); + + if (reply->error() == QNetworkReply::NoError && reply->attribute(QNetworkRequest::HttpStatusCodeAttribute) == 200) { + _scriptContents = reply->readAll(); + } else { + qDebug() << "ERROR Loading file:" << reply->url().toString(); + emit errorLoadingScript(); + } +} + Q_SCRIPT_DECLARE_QMETAOBJECT(LocalVoxels, QString) void ScriptEngine::init() { diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index bb279b8887..ee952d9d35 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -40,9 +40,6 @@ const unsigned int SCRIPT_DATA_CALLBACK_USECS = floor(((1.0 / 60.0f) * 1000 * 10 class ScriptEngine : public QScriptEngine { Q_OBJECT public: - ScriptEngine(const QUrl& scriptURL, - AbstractControllerScriptingInterface* controllerScriptingInterface = NULL); - ScriptEngine(const QString& scriptContents = NO_SCRIPT, const QString& fileNameString = QString(""), AbstractControllerScriptingInterface* controllerScriptingInterface = NULL); @@ -94,6 +91,7 @@ public: bool isUserLoaded() const { return _isUserLoaded; } public slots: + void loadURL(const QUrl& scriptURL); void stop(); QScriptValue evaluate(const QString& program, const QString& fileName = QString(), int lineNumber = 1); @@ -109,6 +107,8 @@ public slots: void nodeKilled(SharedNodePointer node); signals: + void scriptLoaded(); + void errorLoadingScript(); void update(float deltaTime); void scriptEnding(); void finished(const QString& fileNameString); @@ -155,6 +155,8 @@ private: ArrayBufferClass* _arrayBufferClass; QHash _outgoingScriptAudioSequenceNumbers; +private slots: + void handleScriptDownload(); }; #endif // hifi_ScriptEngine_h From d7f168999d1de69951942d02fa4fa6a39a3d65b1 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 2 Dec 2014 10:30:23 -0800 Subject: [PATCH 146/502] don't block main thread for a script load --- interface/src/Application.cpp | 49 +++++++++++++------- interface/src/Application.h | 3 ++ libraries/script-engine/src/ScriptEngine.cpp | 7 +-- libraries/script-engine/src/ScriptEngine.h | 4 +- 4 files changed, 40 insertions(+), 23 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 20ae07b0c9..35b13cbec7 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4013,26 +4013,23 @@ ScriptEngine* Application::loadScript(const QString& scriptFilename, bool isUser return _scriptEnginesHash[scriptURLString]; } - ScriptEngine* scriptEngine; - if (scriptFilename.isNull()) { - scriptEngine = new ScriptEngine(NO_SCRIPT, "", &_controllerScriptingInterface); - } else { - // start the script on a new thread... - scriptEngine = new ScriptEngine(scriptUrl, &_controllerScriptingInterface); - - if (!scriptEngine->hasScript()) { - qDebug() << "Application::loadScript(), script failed to load..."; - QMessageBox::warning(getWindow(), "Error Loading Script", scriptURLString + " failed to load."); - return NULL; - } - - _scriptEnginesHash.insertMulti(scriptURLString, scriptEngine); - _runningScriptsWidget->setRunningScripts(getRunningScripts()); - UserActivityLogger::getInstance().loadedScript(scriptURLString); - } + ScriptEngine* scriptEngine = new ScriptEngine(NO_SCRIPT, "", &_controllerScriptingInterface); scriptEngine->setUserLoaded(isUserLoaded); - registerScriptEngineWithApplicationServices(scriptEngine); + if (scriptFilename.isNull()) { + // this had better be the script editor (we should de-couple so somebody who thinks they are loading a script + // doesn't just get an empty script engine) + + // we can complete setup now since there isn't a script we have to load + registerScriptEngineWithApplicationServices(scriptEngine); + } else { + // connect to the appropriate signals of this script engine + connect(scriptEngine, &ScriptEngine::scriptLoaded, this, &Application::handleScriptEngineLoaded); + connect(scriptEngine, &ScriptEngine::scriptLoaded, this, &Application::handleScriptLoadError); + + // get the script engine object to load the script at the designated script URL + scriptEngine->loadURL(scriptUrl); + } // restore the main window's active state if (activateMainWindow && !loadScriptFromEditor) { @@ -4043,6 +4040,22 @@ ScriptEngine* Application::loadScript(const QString& scriptFilename, bool isUser return scriptEngine; } +void Application::handleScriptEngineLoaded(const QUrl& scriptURL) { + ScriptEngine* scriptEngine = qobject_cast(sender()); + + _scriptEnginesHash.insertMulti(scriptURL.toString(), scriptEngine); + _runningScriptsWidget->setRunningScripts(getRunningScripts()); + UserActivityLogger::getInstance().loadedScript(scriptURL.toString()); + + // register our application services and set it off on its own thread + registerScriptEngineWithApplicationServices(scriptEngine); +} + +void Application::handleScriptLoadError(const QUrl& scriptURL) { + qDebug() << "Application::loadScript(), script failed to load..."; + QMessageBox::warning(getWindow(), "Error Loading Script", scriptURL.toString() + " failed to load."); +} + void Application::scriptFinished(const QString& scriptName) { const QString& scriptURLString = QUrl(scriptName).toString(); QHash::iterator it = _scriptEnginesHash.find(scriptURLString); diff --git a/interface/src/Application.h b/interface/src/Application.h index 9f2cdbd520..caaebea876 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -393,6 +393,9 @@ private slots: void timer(); void idle(); void aboutToQuit(); + + void handleScriptEngineLoaded(const QUrl& scriptURL); + void handleScriptLoadError(const QUrl& scriptURL); void connectedToDomain(const QString& hostname); diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index fefe8e2103..6cef69d23f 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -177,10 +177,10 @@ void ScriptEngine::loadURL(const QUrl& scriptURL) { qDebug() << "Loading file:" << fileName; QTextStream in(&scriptFile); _scriptContents = in.readAll(); - emit scriptLoaded(); + emit scriptLoaded(url); } else { qDebug() << "ERROR Loading file:" << fileName; - emit errorLoadingScript(); + emit errorLoadingScript(url); } } else { QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); @@ -195,9 +195,10 @@ void ScriptEngine::handleScriptDownload() { if (reply->error() == QNetworkReply::NoError && reply->attribute(QNetworkRequest::HttpStatusCodeAttribute) == 200) { _scriptContents = reply->readAll(); + emit scriptLoaded(reply->url()); } else { qDebug() << "ERROR Loading file:" << reply->url().toString(); - emit errorLoadingScript(); + emit errorLoadingScript(reply->url()); } } diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index ee952d9d35..4b6b3e48ab 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -107,8 +107,8 @@ public slots: void nodeKilled(SharedNodePointer node); signals: - void scriptLoaded(); - void errorLoadingScript(); + void scriptLoaded(const QUrl& scriptURL); + void errorLoadingScript(const QUrl& scriptURL); void update(float deltaTime); void scriptEnding(); void finished(const QString& fileNameString); From 0a92374ca6df9172e031999f2f58600ed5d1aec9 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 2 Dec 2014 10:39:20 -0800 Subject: [PATCH 147/502] fix an incorrect connection to script load error --- interface/src/Application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 35b13cbec7..f499d04cfa 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4025,7 +4025,7 @@ ScriptEngine* Application::loadScript(const QString& scriptFilename, bool isUser } else { // connect to the appropriate signals of this script engine connect(scriptEngine, &ScriptEngine::scriptLoaded, this, &Application::handleScriptEngineLoaded); - connect(scriptEngine, &ScriptEngine::scriptLoaded, this, &Application::handleScriptLoadError); + connect(scriptEngine, &ScriptEngine::errorLoadingScript, this, &Application::handleScriptLoadError); // get the script engine object to load the script at the designated script URL scriptEngine->loadURL(scriptUrl); From 0814949e4cd9ec65c43657fa3daad7dc8325370f Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 2 Dec 2014 11:05:17 -0800 Subject: [PATCH 148/502] moving EntityCollisionSystem back to entities lib --- interface/src/Application.h | 2 +- .../entities/src}/EntityCollisionSystem.cpp | 9 ++++----- .../entities/src}/EntityCollisionSystem.h | 5 +++-- 3 files changed, 8 insertions(+), 8 deletions(-) rename {interface/src/entities => libraries/entities/src}/EntityCollisionSystem.cpp (99%) rename {interface/src/entities => libraries/entities/src}/EntityCollisionSystem.h (97%) diff --git a/interface/src/Application.h b/interface/src/Application.h index 1c49e871e7..6980ac7a48 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -30,6 +30,7 @@ #include #include +#include #include #include #include @@ -59,7 +60,6 @@ #include "devices/SixenseManager.h" #include "devices/Visage.h" #include "devices/DdeFaceTracker.h" -#include "entities/EntityCollisionSystem.h" #include "entities/EntityTreeRenderer.h" #include "renderer/AmbientOcclusionEffect.h" #include "renderer/DeferredLightingEffect.h" diff --git a/interface/src/entities/EntityCollisionSystem.cpp b/libraries/entities/src/EntityCollisionSystem.cpp similarity index 99% rename from interface/src/entities/EntityCollisionSystem.cpp rename to libraries/entities/src/EntityCollisionSystem.cpp index 1760d63157..2ac8ea596d 100644 --- a/interface/src/entities/EntityCollisionSystem.cpp +++ b/libraries/entities/src/EntityCollisionSystem.cpp @@ -19,12 +19,11 @@ #include #include -#include -#include -#include -#include - #include "EntityCollisionSystem.h" +#include "EntityEditPacketSender.h" +#include "EntityItem.h" +#include "EntityTreeElement.h" +#include "EntityTree.h" const int MAX_COLLISIONS_PER_Entity = 16; diff --git a/interface/src/entities/EntityCollisionSystem.h b/libraries/entities/src/EntityCollisionSystem.h similarity index 97% rename from interface/src/entities/EntityCollisionSystem.h rename to libraries/entities/src/EntityCollisionSystem.h index a1eb174756..b4421ffc72 100644 --- a/interface/src/entities/EntityCollisionSystem.h +++ b/libraries/entities/src/EntityCollisionSystem.h @@ -20,12 +20,13 @@ #include #include -#include #include #include -#include #include +#include "EntityItem.h" +#include "SimpleEntitySimulation.h" + class AbstractAudioInterface; class AvatarData; class EntityEditPacketSender; From b9944edf66d33a08f857325737d342684fd7550b Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 2 Dec 2014 11:13:37 -0800 Subject: [PATCH 149/502] OctreeServer::createTree() is now protected --- assignment-client/src/entities/EntityServer.h | 4 +++- assignment-client/src/octree/OctreeServer.h | 2 +- assignment-client/src/voxels/VoxelServer.h | 2 +- interface/src/entities/EntityTreeRenderer.h | 4 +++- libraries/entities/src/EntityTreeHeadlessViewer.h | 4 +++- libraries/octree/src/OctreeRenderer.h | 3 ++- libraries/voxels/src/VoxelTreeHeadlessViewer.h | 4 +++- 7 files changed, 16 insertions(+), 7 deletions(-) diff --git a/assignment-client/src/entities/EntityServer.h b/assignment-client/src/entities/EntityServer.h index 14fd26b775..d072d18cdf 100644 --- a/assignment-client/src/entities/EntityServer.h +++ b/assignment-client/src/entities/EntityServer.h @@ -27,7 +27,6 @@ public: // Subclasses must implement these methods virtual OctreeQueryNode* createOctreeQueryNode(); - virtual Octree* createTree(); virtual char getMyNodeType() const { return NodeType::EntityServer; } virtual PacketType getMyQueryMessageType() const { return PacketTypeEntityQuery; } virtual const char* getMyServerName() const { return MODEL_SERVER_NAME; } @@ -46,6 +45,9 @@ public: public slots: void pruneDeletedEntities(); +protected: + virtual Octree* createTree(); + private: EntitySimulation* _entitySimulation; }; diff --git a/assignment-client/src/octree/OctreeServer.h b/assignment-client/src/octree/OctreeServer.h index 27365c1e9d..4999594a98 100644 --- a/assignment-client/src/octree/OctreeServer.h +++ b/assignment-client/src/octree/OctreeServer.h @@ -62,7 +62,6 @@ public: // Subclasses must implement these methods virtual OctreeQueryNode* createOctreeQueryNode() = 0; - virtual Octree* createTree() = 0; virtual char getMyNodeType() const = 0; virtual PacketType getMyQueryMessageType() const = 0; virtual const char* getMyServerName() const = 0; @@ -132,6 +131,7 @@ public slots: void readPendingDatagram(const QByteArray& receivedPacket, const HifiSockAddr& senderSockAddr); protected: + virtual Octree* createTree() = 0; bool readOptionBool(const QString& optionName, const QJsonObject& settingsSectionObject, bool& result); bool readOptionInt(const QString& optionName, const QJsonObject& settingsSectionObject, int& result); bool readOptionString(const QString& optionName, const QJsonObject& settingsSectionObject, QString& result); diff --git a/assignment-client/src/voxels/VoxelServer.h b/assignment-client/src/voxels/VoxelServer.h index f4b6bd3a42..4d21695f33 100644 --- a/assignment-client/src/voxels/VoxelServer.h +++ b/assignment-client/src/voxels/VoxelServer.h @@ -36,7 +36,6 @@ public: // Subclasses must implement these methods virtual OctreeQueryNode* createOctreeQueryNode(); - virtual Octree* createTree(); virtual char getMyNodeType() const { return NodeType::VoxelServer; } virtual PacketType getMyQueryMessageType() const { return PacketTypeVoxelQuery; } virtual const char* getMyServerName() const { return VOXEL_SERVER_NAME; } @@ -50,6 +49,7 @@ public: virtual int sendSpecialPacket(const SharedNodePointer& node, OctreeQueryNode* queryNode, int& packetsSent); protected: + virtual Octree* createTree(); virtual void readAdditionalConfiguration(const QJsonObject& settingsSectionObject); private: diff --git a/interface/src/entities/EntityTreeRenderer.h b/interface/src/entities/EntityTreeRenderer.h index 9f06011d30..0042dd495f 100644 --- a/interface/src/entities/EntityTreeRenderer.h +++ b/interface/src/entities/EntityTreeRenderer.h @@ -40,7 +40,6 @@ public: EntityTreeRenderer(bool wantScripts); virtual ~EntityTreeRenderer(); - virtual Octree* createTree() { return new EntityTree(true); } virtual char getMyNodeType() const { return NodeType::EntityServer; } virtual PacketType getMyQueryMessageType() const { return PacketTypeEntityQuery; } virtual PacketType getExpectedPacketType() const { return PacketTypeEntityData; } @@ -108,6 +107,9 @@ public slots: void changingEntityID(const EntityItemID& oldEntityID, const EntityItemID& newEntityID); void entitySciptChanging(const EntityItemID& entityID); +protected: + virtual Octree* createTree() { return new EntityTree(true); } + private: void checkAndCallPreload(const EntityItemID& entityID); void checkAndCallUnload(const EntityItemID& entityID); diff --git a/libraries/entities/src/EntityTreeHeadlessViewer.h b/libraries/entities/src/EntityTreeHeadlessViewer.h index 16839f9951..3989582c2b 100644 --- a/libraries/entities/src/EntityTreeHeadlessViewer.h +++ b/libraries/entities/src/EntityTreeHeadlessViewer.h @@ -30,7 +30,6 @@ public: EntityTreeHeadlessViewer(); virtual ~EntityTreeHeadlessViewer(); - virtual Octree* createTree() { return new EntityTree(true); } virtual char getMyNodeType() const { return NodeType::EntityServer; } virtual PacketType getMyQueryMessageType() const { return PacketTypeEntityQuery; } virtual PacketType getExpectedPacketType() const { return PacketTypeEntityData; } @@ -42,7 +41,10 @@ public: void processEraseMessage(const QByteArray& dataByteArray, const SharedNodePointer& sourceNode); virtual void init(); + protected: + virtual Octree* createTree() { return new EntityTree(true); } + EntitySimulation* _simulation; }; diff --git a/libraries/octree/src/OctreeRenderer.h b/libraries/octree/src/OctreeRenderer.h index 2999f34fb6..4ee0865243 100644 --- a/libraries/octree/src/OctreeRenderer.h +++ b/libraries/octree/src/OctreeRenderer.h @@ -35,7 +35,6 @@ public: OctreeRenderer(); virtual ~OctreeRenderer(); - virtual Octree* createTree() = 0; virtual char getMyNodeType() const = 0; virtual PacketType getMyQueryMessageType() const = 0; virtual PacketType getExpectedPacketType() const = 0; @@ -81,6 +80,8 @@ public: int getOpaqueMeshPartsRendered() const { return _opaqueMeshPartsRendered; } protected: + virtual Octree* createTree() = 0; + Octree* _tree; bool _managedTree; ViewFrustum* _viewFrustum; diff --git a/libraries/voxels/src/VoxelTreeHeadlessViewer.h b/libraries/voxels/src/VoxelTreeHeadlessViewer.h index 4acd5aa52d..291ad7f813 100644 --- a/libraries/voxels/src/VoxelTreeHeadlessViewer.h +++ b/libraries/voxels/src/VoxelTreeHeadlessViewer.h @@ -27,7 +27,6 @@ public: VoxelTreeHeadlessViewer(); virtual ~VoxelTreeHeadlessViewer(); - virtual Octree* createTree() { return new VoxelTree(true); } virtual char getMyNodeType() const { return NodeType::VoxelServer; } virtual PacketType getMyQueryMessageType() const { return PacketTypeVoxelQuery; } virtual PacketType getExpectedPacketType() const { return PacketTypeVoxelData; } @@ -35,6 +34,9 @@ public: VoxelTree* getTree() { return (VoxelTree*)_tree; } virtual void init(); + +protected: + virtual Octree* createTree() { return new VoxelTree(true); } }; #endif // hifi_VoxelTreeHeadlessViewer_h From 6d385d9a75de786e0d1f583ad8448c30a9df2492 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 2 Dec 2014 11:45:33 -0800 Subject: [PATCH 150/502] get rid of redundant _displayViewFrustum and use _viewFrustum --- interface/src/Application.cpp | 4 ++-- interface/src/Application.h | 2 -- interface/src/MetavoxelSystem.cpp | 6 +++--- interface/src/renderer/DeferredLightingEffect.cpp | 4 ++-- 4 files changed, 7 insertions(+), 9 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index ab18c68a10..6a0ec5afdf 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2903,7 +2903,7 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly, RenderAr // transform by eye offset // load the view frustum - loadViewFrustum(whichCamera, _displayViewFrustum); + loadViewFrustum(whichCamera, _viewFrustum); // flip x if in mirror mode (also requires reversing winding order for backface culling) if (whichCamera.getMode() == CAMERA_MODE_MIRROR) { @@ -3177,7 +3177,7 @@ void Application::computeOffAxisFrustum(float& left, float& right, float& bottom float& farVal, glm::vec4& nearClipPlane, glm::vec4& farClipPlane) const { // allow 3DTV/Oculus to override parameters from camera - _displayViewFrustum.computeOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane); + _viewFrustum.computeOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane); if (OculusManager::isConnected()) { OculusManager::overrideOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane); diff --git a/interface/src/Application.h b/interface/src/Application.h index 9f2cdbd520..46f4cda0a6 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -196,7 +196,6 @@ public: const AudioReflector* getAudioReflector() const { return &_audioReflector; } Camera* getCamera() { return &_myCamera; } ViewFrustum* getViewFrustum() { return &_viewFrustum; } - ViewFrustum* getDisplayViewFrustum() { return &_displayViewFrustum; } ViewFrustum* getShadowViewFrustum() { return &_shadowViewFrustum; } VoxelImporter* getVoxelImporter() { return &_voxelImporter; } VoxelSystem* getVoxels() { return &_voxels; } @@ -515,7 +514,6 @@ private: ViewFrustum _viewFrustum; // current state of view frustum, perspective, orientation, etc. ViewFrustum _lastQueriedViewFrustum; /// last view frustum used to query octree servers (voxels) - ViewFrustum _displayViewFrustum; ViewFrustum _shadowViewFrustum; quint64 _lastQueriedTime; diff --git a/interface/src/MetavoxelSystem.cpp b/interface/src/MetavoxelSystem.cpp index b98fea8eca..996b92e22d 100644 --- a/interface/src/MetavoxelSystem.cpp +++ b/interface/src/MetavoxelSystem.cpp @@ -192,7 +192,7 @@ static const float EIGHT_BIT_MAXIMUM_RECIPROCAL = 1.0f / EIGHT_BIT_MAXIMUM; void MetavoxelSystem::render() { // update the frustum - ViewFrustum* viewFrustum = Application::getInstance()->getDisplayViewFrustum(); + ViewFrustum* viewFrustum = Application::getInstance()->getViewFrustum(); _frustum.set(viewFrustum->getFarTopLeft(), viewFrustum->getFarTopRight(), viewFrustum->getFarBottomLeft(), viewFrustum->getFarBottomRight(), viewFrustum->getNearTopLeft(), viewFrustum->getNearTopRight(), viewFrustum->getNearBottomLeft(), viewFrustum->getNearBottomRight()); @@ -1896,7 +1896,7 @@ private: SpannerRenderVisitor::SpannerRenderVisitor(const MetavoxelLOD& lod) : SpannerVisitor(QVector() << AttributeRegistry::getInstance()->getSpannersAttribute(), QVector(), QVector(), lod, - encodeOrder(Application::getInstance()->getDisplayViewFrustum()->getDirection())), + encodeOrder(Application::getInstance()->getViewFrustum()->getDirection())), _containmentDepth(INT_MAX) { } @@ -1932,7 +1932,7 @@ private: BufferRenderVisitor::BufferRenderVisitor(const AttributePointer& attribute) : MetavoxelVisitor(QVector() << attribute), - _order(encodeOrder(Application::getInstance()->getDisplayViewFrustum()->getDirection())), + _order(encodeOrder(Application::getInstance()->getViewFrustum()->getDirection())), _containmentDepth(INT_MAX) { } diff --git a/interface/src/renderer/DeferredLightingEffect.cpp b/interface/src/renderer/DeferredLightingEffect.cpp index be4e457131..63d874cda7 100644 --- a/interface/src/renderer/DeferredLightingEffect.cpp +++ b/interface/src/renderer/DeferredLightingEffect.cpp @@ -232,8 +232,8 @@ void DeferredLightingEffect::render() { // enlarge the scales slightly to account for tesselation const float SCALE_EXPANSION = 0.05f; - const glm::vec3& eyePoint = Application::getInstance()->getDisplayViewFrustum()->getPosition(); - float nearRadius = glm::distance(eyePoint, Application::getInstance()->getDisplayViewFrustum()->getNearTopLeft()); + const glm::vec3& eyePoint = Application::getInstance()->getViewFrustum()->getPosition(); + float nearRadius = glm::distance(eyePoint, Application::getInstance()->getViewFrustum()->getNearTopLeft()); if (!_pointLights.isEmpty()) { _pointLight.bind(); From 89b3a4d9872c4864af6501f7a56de959bca2bc35 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 2 Dec 2014 12:17:10 -0800 Subject: [PATCH 151/502] Fix selection shadow not updating when grid moves --- examples/libraries/gridTool.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/examples/libraries/gridTool.js b/examples/libraries/gridTool.js index de4fd7b8d4..aa412b1a76 100644 --- a/examples/libraries/gridTool.js +++ b/examples/libraries/gridTool.js @@ -177,6 +177,8 @@ Grid = function(opts) { color: gridColor, alpha: gridAlpha, }); + + that.emitUpdate(); } function cleanup() { @@ -207,6 +209,7 @@ GridTool = function(opts) { horizontalGrid.addListener(function(data) { webView.eventBridge.emitScriptEvent(JSON.stringify(data)); + selectionDisplay.updateHandles(); }); webView.eventBridge.webEventReceived.connect(function(data) { From 3c5f33f0ac06ae0bc86ad49b82146ae36e89be9b Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 2 Dec 2014 12:28:04 -0800 Subject: [PATCH 152/502] Hemisphere vbo refactoring --- interface/src/ui/ApplicationOverlay.cpp | 194 ++++++++++++------------ interface/src/ui/ApplicationOverlay.h | 4 +- 2 files changed, 100 insertions(+), 98 deletions(-) diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 1307672ad1..e479452fec 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -1129,118 +1129,118 @@ void ApplicationOverlay::renderStatsAndLogs() { nodeBoundsDisplay.drawOverlay(); } -//Renders a hemisphere with texture coordinates. -void ApplicationOverlay::renderTexturedHemisphere() { - const int slices = 80; - const int stacks = 80; - - //UV mapping source: http://www.mvps.org/directx/articles/spheremap.htm - static VerticesIndices vbo(0, 0); - int vertices = slices * (stacks - 1) + 1; - int indices = slices * 2 * 3 * (stacks - 2) + slices * 3; - - static float oldTextureFOV = _textureFov; - //We only generate the VBO when the _textureFov changes - if (vbo.first == 0 || oldTextureFOV != _textureFov) { - oldTextureFOV = _textureFov; - TextureVertex* vertexData = new TextureVertex[vertices]; - TextureVertex* vertex = vertexData; - for (int i = 0; i < stacks - 1; i++) { - float phi = PI_OVER_TWO * (float)i / (float)(stacks - 1); - float z = -sinf(phi), radius = cosf(phi); - - for (int j = 0; j < slices; j++) { - float theta = TWO_PI * (float)j / (float)slices; - - vertex->position.x = sinf(theta) * radius; - vertex->position.y = cosf(theta) * radius; - vertex->position.z = z; - vertex->uv.x = asin(vertex->position.x) / (_textureFov) + 0.5f; - vertex->uv.y = asin(vertex->position.y) / (_textureFov) + 0.5f; - vertex++; - } - } - vertex->position.x = 0.0f; - vertex->position.y = 0.0f; - vertex->position.z = -1.0f; - vertex->uv.x = 0.5f; - vertex->uv.y = 0.5f; - vertex++; - - if (vbo.first == 0){ - glGenBuffers(1, &vbo.first); - } - glBindBuffer(GL_ARRAY_BUFFER, vbo.first); - const int BYTES_PER_VERTEX = sizeof(TextureVertex); - glBufferData(GL_ARRAY_BUFFER, vertices * BYTES_PER_VERTEX, vertexData, GL_STATIC_DRAW); - delete[] vertexData; - - GLushort* indexData = new GLushort[indices]; - GLushort* index = indexData; - for (int i = 0; i < stacks - 2; i++) { - GLushort bottom = i * slices; - GLushort top = bottom + slices; - for (int j = 0; j < slices; j++) { - int next = (j + 1) % slices; - - *(index++) = bottom + j; - *(index++) = top + next; - *(index++) = top + j; - - *(index++) = bottom + j; - *(index++) = bottom + next; - *(index++) = top + next; - } - } - GLushort bottom = (stacks - 2) * slices; - GLushort top = bottom + slices; - for (int i = 0; i < slices; i++) { - *(index++) = bottom + i; - *(index++) = bottom + (i + 1) % slices; - *(index++) = top; - } - - glGenBuffers(1, &vbo.second); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo.second); - const int BYTES_PER_INDEX = sizeof(GLushort); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices * BYTES_PER_INDEX, indexData, GL_STATIC_DRAW); - delete[] indexData; - - } else { - glBindBuffer(GL_ARRAY_BUFFER, vbo.first); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo.second); +ApplicationOverlay::VerticesIndices* ApplicationOverlay::makeTexturedHemiphereVBO(float fov, + float aspectRatio, + int slices, + int stacks) { + if (fov >= PI) { + qDebug() << "ApplicationOverlay::makeHemiphereVBO(): FOV greater or equal than Pi will create issues"; } + + //UV mapping source: http://www.mvps.org/directx/articles/spheremap.htm + VerticesIndices* vbo = new VerticesIndices(0, 0); + + // Compute number of vertices needed + int vertices = slices * stacks; + + // Compute vertices positions and texture UV coordinate + TextureVertex* vertexData = new TextureVertex[vertices]; + TextureVertex* vertexPtr = &vertexData[0]; + for (int i = 0; i < stacks; i++) { + float stacksRatio = (float)i / (float)stacks; // First stack is 0.0f, last stack is 1.0f + // abs(phi) <= fov / 2.0f + float phi = fov * (stacksRatio - 0.5f); + + for (int j = 0; j < slices; j++) { + float slicesRatio = (float)j / (float)slices; // First slice is 0.0f, last slice is 1.0f + // abs(theta) <= fov * aspectRatio / 2.0f + float theta = fov * aspectRatio * (slicesRatio - 0.5f); + + vertexPtr->position.x = -sinf(theta); + vertexPtr->position.y = sinf(phi); + vertexPtr->position.z = cosf(theta); + vertexPtr->uv.x = slicesRatio; + vertexPtr->uv.y = 1.0f - stacksRatio; + vertexPtr++; + } + } + // Create and write to buffer + glGenBuffers(1, &vbo->first); + glBindBuffer(GL_ARRAY_BUFFER, vbo->first); + static const int BYTES_PER_VERTEX = sizeof(TextureVertex); + glBufferData(GL_ARRAY_BUFFER, vertices * BYTES_PER_VERTEX, vertexData, GL_STATIC_DRAW); + delete[] vertexData; + + + // Compute number of indices needed + static const int VERTEX_PER_TRANGLE = 3; + static const int TRIANGLE_PER_RECTANGLE = 2; + int numberOfRectangles = (slices - 1) * (stacks - 1); + int indices = numberOfRectangles * TRIANGLE_PER_RECTANGLE * VERTEX_PER_TRANGLE; + + // Compute indices order + GLushort* indexData = new GLushort[indices]; + GLushort* indexPtr = indexData; + for (int i = 0; i < stacks - 1; i++) { + for (int j = 0; j < slices - 1; j++) { + GLushort bottomLeftIndex = i * slices + j; + GLushort bottomRightIndex = bottomLeftIndex + 1; + GLushort topLeftIndex = bottomLeftIndex + slices; + GLushort topRightIndex = topLeftIndex + 1; + + *(indexPtr++) = topLeftIndex; + *(indexPtr++) = bottomLeftIndex; + *(indexPtr++) = topRightIndex; + + *(indexPtr++) = topRightIndex; + *(indexPtr++) = bottomLeftIndex; + *(indexPtr++) = bottomRightIndex; + } + } + // Create and write to buffer + glGenBuffers(1, &vbo->second); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo->second); + static const int BYTES_PER_INDEX = sizeof(GLushort); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices * BYTES_PER_INDEX, indexData, GL_STATIC_DRAW); + delete[] indexData; + + return vbo; +} + +//Renders a hemisphere with texture coordinates. +void ApplicationOverlay::renderTexturedHemisphere(ApplicationOverlay::VerticesIndices* vbo, int vertices, int indices) { + glBindBuffer(GL_ARRAY_BUFFER, vbo->first); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo->second); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glVertexPointer(3, GL_FLOAT, sizeof(TextureVertex), (void*)0); - glTexCoordPointer(2, GL_FLOAT, sizeof(TextureVertex), (void*)12); + static const int STRIDE = sizeof(TextureVertex); + static const void* VERTEX_POINTER = 0; + static const void* TEX_COORD_POINTER = (void*)sizeof(glm::vec3); + glVertexPointer(3, GL_FLOAT, STRIDE, VERTEX_POINTER); + glTexCoordPointer(2, GL_FLOAT, STRIDE, TEX_COORD_POINTER); - glPushMatrix(); - Application* application = Application::getInstance(); - MyAvatar* myAvatar = application->getAvatar(); + + MyAvatar* myAvatar = Application::getInstance()->getAvatar(); const glm::quat& orientation = myAvatar->getOrientation(); const glm::vec3& position = myAvatar->getDefaultEyePosition(); - - glm::mat4 rotation = glm::toMat4(orientation); - - glTranslatef(position.x, position.y, position.z); - glMultMatrixf(&rotation[0][0]); - const float scale = _oculusuiRadius * myAvatar->getScale(); - glScalef(scale, scale, scale); - - glDrawRangeElements(GL_TRIANGLES, 0, vertices - 1, indices, GL_UNSIGNED_SHORT, 0); - - glPopMatrix(); + + glPushMatrix(); { + glTranslatef(position.x, position.y, position.z); + glm::mat4 rotation = glm::toMat4(orientation); + glMultMatrixf(&rotation[0][0]); + glScalef(scale, scale, scale); + + glDrawRangeElements(GL_TRIANGLES, 0, vertices - 1, indices, GL_UNSIGNED_SHORT, 0); + } glPopMatrix(); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - } void ApplicationOverlay::renderDomainConnectionStatusBorder() { diff --git a/interface/src/ui/ApplicationOverlay.h b/interface/src/ui/ApplicationOverlay.h index a493f6cd1b..94100d094c 100644 --- a/interface/src/ui/ApplicationOverlay.h +++ b/interface/src/ui/ApplicationOverlay.h @@ -55,8 +55,10 @@ private: void renderMagnifier(int mouseX, int mouseY, float sizeMult, bool showBorder) const; void renderAudioMeter(); void renderStatsAndLogs(); - void renderTexturedHemisphere(); void renderDomainConnectionStatusBorder(); + + VerticesIndices* makeTexturedHemiphereVBO(float fov, float aspectRatio, int slices, int stacks); + void renderTexturedHemisphere(ApplicationOverlay::VerticesIndices* vbo, int vertices, int indices); QOpenGLFramebufferObject* _framebufferObject; float _trailingAudioLoudness; From cc012aad0012a96eafa5573c709128b1ae70a57f Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 2 Dec 2014 12:54:10 -0800 Subject: [PATCH 153/502] reset view frustum --- interface/src/Application.cpp | 1 + interface/src/Menu.cpp | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 6a0ec5afdf..90f5a0bf96 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -895,6 +895,7 @@ void Application::keyPressEvent(QKeyEvent* event) { case Qt::Key_Greater: case Qt::Key_Comma: case Qt::Key_Period: + case Qt::Key_QuoteDbl: Menu::getInstance()->handleViewFrustumOffsetKeyModifier(event->key()); break; case Qt::Key_L: diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 6cfb3db35a..ae12b5ff26 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -835,6 +835,14 @@ void Menu::handleViewFrustumOffsetKeyModifier(int key) { const float VIEW_FRUSTUM_OFFSET_UP_DELTA = 0.05f; switch (key) { + case Qt::Key_QuoteDbl: + _viewFrustumOffset.yaw = 0.0f; + _viewFrustumOffset.pitch = 0.0f; + _viewFrustumOffset.roll = 0.0f; + _viewFrustumOffset.up = 0.0f; + _viewFrustumOffset.distance = 0.0f; + break; + case Qt::Key_BracketLeft: _viewFrustumOffset.yaw -= VIEW_FRUSTUM_OFFSET_DELTA; break; From a022b7fa172f1f64236b72d4f1c84b6cefe9b82c Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 2 Dec 2014 13:12:45 -0800 Subject: [PATCH 154/502] Fix for successive heightfield placements. --- interface/src/ui/MetavoxelEditor.cpp | 2 +- libraries/metavoxels/src/Spanner.cpp | 6 ++++++ libraries/metavoxels/src/Spanner.h | 2 ++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/interface/src/ui/MetavoxelEditor.cpp b/interface/src/ui/MetavoxelEditor.cpp index 6d1e181907..a88b981d66 100644 --- a/interface/src/ui/MetavoxelEditor.cpp +++ b/interface/src/ui/MetavoxelEditor.cpp @@ -789,7 +789,7 @@ void ImportHeightfieldTool::apply() { if (!(_height->getHeight() && attribute)) { return; } - MetavoxelEditMessage message = { QVariant::fromValue(InsertSpannerEdit(attribute, _spanner)) }; + MetavoxelEditMessage message = { QVariant::fromValue(InsertSpannerEdit(attribute, _spanner->clone())) }; Application::getInstance()->getMetavoxels()->applyEdit(message, true); } diff --git a/libraries/metavoxels/src/Spanner.cpp b/libraries/metavoxels/src/Spanner.cpp index 301959b16f..cb8cdc6260 100644 --- a/libraries/metavoxels/src/Spanner.cpp +++ b/libraries/metavoxels/src/Spanner.cpp @@ -2063,6 +2063,12 @@ MetavoxelLOD Heightfield::transformLOD(const MetavoxelLOD& lod) const { qMax(0.5f, glm::abs(position.y * _aspectY - 0.5f)) * THRESHOLD_MULTIPLIER); } +SharedObject* Heightfield::clone(bool withID, SharedObject* target) const { + Heightfield* newHeightfield = static_cast(Spanner::clone(withID, target)); + newHeightfield->setRoot(_root); + return newHeightfield; +} + bool Heightfield::isHeightfield() const { return true; } diff --git a/libraries/metavoxels/src/Spanner.h b/libraries/metavoxels/src/Spanner.h index 2173bd67e9..6c38dbcb9a 100644 --- a/libraries/metavoxels/src/Spanner.h +++ b/libraries/metavoxels/src/Spanner.h @@ -579,6 +579,8 @@ public: MetavoxelLOD transformLOD(const MetavoxelLOD& lod) const; + virtual SharedObject* clone(bool withID = false, SharedObject* target = NULL) const; + virtual bool isHeightfield() const; virtual float getHeight(const glm::vec3& location) const; From 4d233c09a36003a968bed277dabfad83dfd3559e Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 2 Dec 2014 13:19:39 -0800 Subject: [PATCH 155/502] At least on Linux, fixes an annoying issue where closing the application window causes it to disappear and reappear briefly before exiting. --- interface/src/Application.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 22a221c3a8..9561115478 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1574,7 +1574,9 @@ void Application::setFullscreen(bool fullscreen) { } _window->setWindowState(fullscreen ? (_window->windowState() | Qt::WindowFullScreen) : (_window->windowState() & ~Qt::WindowFullScreen)); - _window->show(); + if (!_aboutToQuit) { + _window->show(); + } } void Application::setEnable3DTVMode(bool enable3DTVMode) { From bf21376c90f66d557f34dda723b7fb7894355ccd Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 2 Dec 2014 13:34:11 -0800 Subject: [PATCH 156/502] TexturedHemisphere class --- interface/src/ui/ApplicationOverlay.cpp | 608 ++++++++++++------------ interface/src/ui/ApplicationOverlay.h | 38 +- 2 files changed, 342 insertions(+), 304 deletions(-) diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index e479452fec..f5396c72f0 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -27,20 +27,16 @@ const float MAG_SPEED = 0.08f; const quint64 MSECS_TO_USECS = 1000ULL; -// Fast helper functions -inline float max(float a, float b) { - return (a > b) ? a : b; -} +const float WHITE_TEXT[] = { 0.93f, 0.93f, 0.93f }; +const float RETICLE_COLOR[] = { 0.0f, 198.0f / 255.0f, 244.0f / 255.0f }; -inline float min(float a, float b) { - return (a < b) ? a : b; -} +const float CONNECTION_STATUS_BORDER_COLOR[] = { 1.0f, 0.0f, 0.0f }; +const float CONNECTION_STATUS_BORDER_LINE_WIDTH = 4.0f; -ApplicationOverlay::ApplicationOverlay() : - _framebufferObject(NULL), - _textureFov(DEFAULT_OCULUS_UI_ANGULAR_SIZE * RADIANS_PER_DEGREE), +ApplicationOverlay::ApplicationOverlay() : + _textureFov(glm::radians(DEFAULT_OCULUS_UI_ANGULAR_SIZE)), _alpha(1.0f), - _oculusuiRadius(1.0f), + _oculusUIRadius(1.0f), _crosshairTexture(0) { memset(_reticleActive, 0, sizeof(_reticleActive)); @@ -49,23 +45,14 @@ ApplicationOverlay::ApplicationOverlay() : } ApplicationOverlay::~ApplicationOverlay() { - if (_framebufferObject != NULL) { - delete _framebufferObject; - } } -const float WHITE_TEXT[] = { 0.93f, 0.93f, 0.93f }; -const float RETICLE_COLOR[] = { 0.0f, 198.0f / 255.0f, 244.0f / 255.0f }; - -const float CONNECTION_STATUS_BORDER_COLOR[] = { 1.0f, 0.0f, 0.0f }; -const float CONNECTION_STATUS_BORDER_LINE_WIDTH = 4.0f; // Renders the overlays either to a texture or to the screen void ApplicationOverlay::renderOverlay(bool renderToTexture) { - PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "ApplicationOverlay::displayOverlay()"); - _textureFov = Menu::getInstance()->getOculusUIAngularSize() * RADIANS_PER_DEGREE; + _textureFov = glm::radians(Menu::getInstance()->getOculusUIAngularSize()); Application* application = Application::getInstance(); @@ -86,42 +73,39 @@ void ApplicationOverlay::renderOverlay(bool renderToTexture) { } } - if (renderToTexture) { - getFramebufferObject()->bind(); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - } - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - // Render 2D overlay glMatrixMode(GL_PROJECTION); - glPushMatrix(); - - glLoadIdentity(); - gluOrtho2D(0, glWidget->width(), glWidget->height(), 0); glDisable(GL_DEPTH_TEST); glDisable(GL_LIGHTING); - - renderAudioMeter(); - - if (Menu::getInstance()->isOptionChecked(MenuOption::HeadMouse)) { - myAvatar->renderHeadMouse(glWidget->width(), glWidget->height()); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + if (renderToTexture) { + _overlays.bind(); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } - - renderStatsAndLogs(); - - // give external parties a change to hook in - emit application->renderingOverlay(); - - overlays.render2D(); - - renderPointers(); - - renderDomainConnectionStatusBorder(); - - glPopMatrix(); - + + glPushMatrix(); { + glLoadIdentity(); + gluOrtho2D(0, glWidget->width(), glWidget->height(), 0); + + renderAudioMeter(); + + if (Menu::getInstance()->isOptionChecked(MenuOption::HeadMouse)) { + myAvatar->renderHeadMouse(glWidget->width(), glWidget->height()); + } + + renderStatsAndLogs(); + + // give external parties a change to hook in + emit application->renderingOverlay(); + + overlays.render2D(); + + renderPointers(); + + renderDomainConnectionStatusBorder(); + } glPopMatrix(); glMatrixMode(GL_MODELVIEW); glEnable(GL_DEPTH_TEST); @@ -129,7 +113,7 @@ void ApplicationOverlay::renderOverlay(bool renderToTexture) { glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE); if (renderToTexture) { - getFramebufferObject()->release(); + _overlays.release(); } } @@ -559,7 +543,6 @@ void ApplicationOverlay::renderPointers() { } glBindTexture(GL_TEXTURE_2D, 0); glDisable(GL_TEXTURE_2D); - } void ApplicationOverlay::renderControllerPointers() { @@ -844,118 +827,6 @@ void ApplicationOverlay::renderPointersOculus(const glm::vec3& eyePos) { glEnable(GL_DEPTH_TEST); } -//Renders a small magnification of the currently bound texture at the coordinates -void ApplicationOverlay::renderMagnifier(int mouseX, int mouseY, float sizeMult, bool showBorder) const -{ - Application* application = Application::getInstance(); - GLCanvas* glWidget = application->getGLWidget(); - - const int widgetWidth = glWidget->width(); - const int widgetHeight = glWidget->height(); - - const float magnifyWidth = MAGNIFY_WIDTH * sizeMult; - const float magnifyHeight = MAGNIFY_HEIGHT * sizeMult; - - mouseX -= magnifyWidth / 2; - mouseY -= magnifyHeight / 2; - - float newWidth = magnifyWidth * MAGNIFY_MULT; - float newHeight = magnifyHeight * MAGNIFY_MULT; - - // Magnification Texture Coordinates - float magnifyULeft = mouseX / (float)widgetWidth; - float magnifyURight = (mouseX + magnifyWidth) / (float)widgetWidth; - float magnifyVBottom = 1.0f - mouseY / (float)widgetHeight; - float magnifyVTop = 1.0f - (mouseY + magnifyHeight) / (float)widgetHeight; - - // Coordinates of magnification overlay - float newMouseX = (mouseX + magnifyWidth / 2) - newWidth / 2.0f; - float newMouseY = (mouseY + magnifyHeight / 2) + newHeight / 2.0f; - - // Get position on hemisphere using angle - - //Get new UV coordinates from our magnification window - float newULeft = newMouseX / widgetWidth; - float newURight = (newMouseX + newWidth) / widgetWidth; - float newVBottom = 1.0 - newMouseY / widgetHeight; - float newVTop = 1.0 - (newMouseY - newHeight) / widgetHeight; - - // Project our position onto the hemisphere using the UV coordinates - float radius = _oculusuiRadius * application->getAvatar()->getScale(); - float radius2 = radius * radius; - - float lX = radius * sin((newULeft - 0.5f) * _textureFov); - float rX = radius * sin((newURight - 0.5f) * _textureFov); - float bY = radius * sin((newVBottom - 0.5f) * _textureFov); - float tY = radius * sin((newVTop - 0.5f) * _textureFov); - - float blZ, tlZ, brZ, trZ; - - float dist; - float discriminant; - - //Bottom Left - dist = sqrt(lX * lX + bY * bY); - discriminant = radius2 - dist * dist; - if (discriminant > 0) { - blZ = sqrt(discriminant); - } else { - blZ = 0; - } - //Top Left - dist = sqrt(lX * lX + tY * tY); - discriminant = radius2 - dist * dist; - if (discriminant > 0) { - tlZ = sqrt(discriminant); - } else { - tlZ = 0; - } - //Bottom Right - dist = sqrt(rX * rX + bY * bY); - discriminant = radius2 - dist * dist; - if (discriminant > 0) { - brZ = sqrt(discriminant); - } else { - brZ = 0; - } - //Top Right - dist = sqrt(rX * rX + tY * tY); - discriminant = radius2 - dist * dist; - if (discriminant > 0) { - trZ = sqrt(discriminant); - } else { - trZ = 0; - } - - if (showBorder) { - glDisable(GL_TEXTURE_2D); - glLineWidth(1.0f); - //Outer Line - glBegin(GL_LINE_STRIP); - glColor4f(1.0f, 0.0f, 0.0f, _alpha); - - glVertex3f(lX, tY, -tlZ); - glVertex3f(rX, tY, -trZ); - glVertex3f(rX, bY, -brZ); - glVertex3f(lX, bY, -blZ); - glVertex3f(lX, tY, -tlZ); - - glEnd(); - glEnable(GL_TEXTURE_2D); - } - glColor4f(1.0f, 1.0f, 1.0f, _alpha); - - glBegin(GL_QUADS); - - glTexCoord2f(magnifyULeft, magnifyVBottom); glVertex3f(lX, tY, -tlZ); - glTexCoord2f(magnifyURight, magnifyVBottom); glVertex3f(rX, tY, -trZ); - glTexCoord2f(magnifyURight, magnifyVTop); glVertex3f(rX, bY, -brZ); - glTexCoord2f(magnifyULeft, magnifyVTop); glVertex3f(lX, bY, -blZ); - - glEnd(); - -} - void ApplicationOverlay::renderAudioMeter() { Application* application = Application::getInstance(); @@ -1129,120 +1000,6 @@ void ApplicationOverlay::renderStatsAndLogs() { nodeBoundsDisplay.drawOverlay(); } -ApplicationOverlay::VerticesIndices* ApplicationOverlay::makeTexturedHemiphereVBO(float fov, - float aspectRatio, - int slices, - int stacks) { - if (fov >= PI) { - qDebug() << "ApplicationOverlay::makeHemiphereVBO(): FOV greater or equal than Pi will create issues"; - } - - //UV mapping source: http://www.mvps.org/directx/articles/spheremap.htm - VerticesIndices* vbo = new VerticesIndices(0, 0); - - // Compute number of vertices needed - int vertices = slices * stacks; - - // Compute vertices positions and texture UV coordinate - TextureVertex* vertexData = new TextureVertex[vertices]; - TextureVertex* vertexPtr = &vertexData[0]; - for (int i = 0; i < stacks; i++) { - float stacksRatio = (float)i / (float)stacks; // First stack is 0.0f, last stack is 1.0f - // abs(phi) <= fov / 2.0f - float phi = fov * (stacksRatio - 0.5f); - - for (int j = 0; j < slices; j++) { - float slicesRatio = (float)j / (float)slices; // First slice is 0.0f, last slice is 1.0f - // abs(theta) <= fov * aspectRatio / 2.0f - float theta = fov * aspectRatio * (slicesRatio - 0.5f); - - vertexPtr->position.x = -sinf(theta); - vertexPtr->position.y = sinf(phi); - vertexPtr->position.z = cosf(theta); - vertexPtr->uv.x = slicesRatio; - vertexPtr->uv.y = 1.0f - stacksRatio; - vertexPtr++; - } - } - // Create and write to buffer - glGenBuffers(1, &vbo->first); - glBindBuffer(GL_ARRAY_BUFFER, vbo->first); - static const int BYTES_PER_VERTEX = sizeof(TextureVertex); - glBufferData(GL_ARRAY_BUFFER, vertices * BYTES_PER_VERTEX, vertexData, GL_STATIC_DRAW); - delete[] vertexData; - - - // Compute number of indices needed - static const int VERTEX_PER_TRANGLE = 3; - static const int TRIANGLE_PER_RECTANGLE = 2; - int numberOfRectangles = (slices - 1) * (stacks - 1); - int indices = numberOfRectangles * TRIANGLE_PER_RECTANGLE * VERTEX_PER_TRANGLE; - - // Compute indices order - GLushort* indexData = new GLushort[indices]; - GLushort* indexPtr = indexData; - for (int i = 0; i < stacks - 1; i++) { - for (int j = 0; j < slices - 1; j++) { - GLushort bottomLeftIndex = i * slices + j; - GLushort bottomRightIndex = bottomLeftIndex + 1; - GLushort topLeftIndex = bottomLeftIndex + slices; - GLushort topRightIndex = topLeftIndex + 1; - - *(indexPtr++) = topLeftIndex; - *(indexPtr++) = bottomLeftIndex; - *(indexPtr++) = topRightIndex; - - *(indexPtr++) = topRightIndex; - *(indexPtr++) = bottomLeftIndex; - *(indexPtr++) = bottomRightIndex; - } - } - // Create and write to buffer - glGenBuffers(1, &vbo->second); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo->second); - static const int BYTES_PER_INDEX = sizeof(GLushort); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices * BYTES_PER_INDEX, indexData, GL_STATIC_DRAW); - delete[] indexData; - - return vbo; -} - -//Renders a hemisphere with texture coordinates. -void ApplicationOverlay::renderTexturedHemisphere(ApplicationOverlay::VerticesIndices* vbo, int vertices, int indices) { - glBindBuffer(GL_ARRAY_BUFFER, vbo->first); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo->second); - - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - - static const int STRIDE = sizeof(TextureVertex); - static const void* VERTEX_POINTER = 0; - static const void* TEX_COORD_POINTER = (void*)sizeof(glm::vec3); - glVertexPointer(3, GL_FLOAT, STRIDE, VERTEX_POINTER); - glTexCoordPointer(2, GL_FLOAT, STRIDE, TEX_COORD_POINTER); - - - MyAvatar* myAvatar = Application::getInstance()->getAvatar(); - const glm::quat& orientation = myAvatar->getOrientation(); - const glm::vec3& position = myAvatar->getDefaultEyePosition(); - const float scale = _oculusuiRadius * myAvatar->getScale(); - - glPushMatrix(); { - glTranslatef(position.x, position.y, position.z); - glm::mat4 rotation = glm::toMat4(orientation); - glMultMatrixf(&rotation[0][0]); - glScalef(scale, scale, scale); - - glDrawRangeElements(GL_TRIANGLES, 0, vertices - 1, indices, GL_UNSIGNED_SHORT, 0); - } glPopMatrix(); - - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); -} - void ApplicationOverlay::renderDomainConnectionStatusBorder() { NodeList* nodeList = NodeList::getInstance(); @@ -1267,22 +1024,281 @@ void ApplicationOverlay::renderDomainConnectionStatusBorder() { } } -QOpenGLFramebufferObject* ApplicationOverlay::getFramebufferObject() { - QSize size = Application::getInstance()->getGLWidget()->getDeviceSize(); - if (!_framebufferObject || _framebufferObject->size() != size) { - - delete _framebufferObject; - - _framebufferObject = new QOpenGLFramebufferObject(size); - glBindTexture(GL_TEXTURE_2D, _framebufferObject->texture()); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - GLfloat borderColor[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); - glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor); - glBindTexture(GL_TEXTURE_2D, 0); +//Renders a small magnification of the currently bound texture at the coordinates +void ApplicationOverlay::renderMagnifier(int mouseX, int mouseY, float sizeMult, bool showBorder) const { + Application* application = Application::getInstance(); + GLCanvas* glWidget = application->getGLWidget(); + + const int widgetWidth = glWidget->width(); + const int widgetHeight = glWidget->height(); + + const float magnifyWidth = MAGNIFY_WIDTH * sizeMult; + const float magnifyHeight = MAGNIFY_HEIGHT * sizeMult; + + mouseX -= magnifyWidth / 2; + mouseY -= magnifyHeight / 2; + + float newWidth = magnifyWidth * MAGNIFY_MULT; + float newHeight = magnifyHeight * MAGNIFY_MULT; + + // Magnification Texture Coordinates + float magnifyULeft = mouseX / (float)widgetWidth; + float magnifyURight = (mouseX + magnifyWidth) / (float)widgetWidth; + float magnifyVBottom = 1.0f - mouseY / (float)widgetHeight; + float magnifyVTop = 1.0f - (mouseY + magnifyHeight) / (float)widgetHeight; + + // Coordinates of magnification overlay + float newMouseX = (mouseX + magnifyWidth / 2) - newWidth / 2.0f; + float newMouseY = (mouseY + magnifyHeight / 2) + newHeight / 2.0f; + + // Get position on hemisphere using angle + + //Get new UV coordinates from our magnification window + float newULeft = newMouseX / widgetWidth; + float newURight = (newMouseX + newWidth) / widgetWidth; + float newVBottom = 1.0 - newMouseY / widgetHeight; + float newVTop = 1.0 - (newMouseY - newHeight) / widgetHeight; + + // Project our position onto the hemisphere using the UV coordinates + float radius = _oculusuiRadius * application->getAvatar()->getScale(); + float radius2 = radius * radius; + + float lX = radius * sin((newULeft - 0.5f) * _textureFov); + float rX = radius * sin((newURight - 0.5f) * _textureFov); + float bY = radius * sin((newVBottom - 0.5f) * _textureFov); + float tY = radius * sin((newVTop - 0.5f) * _textureFov); + + float blZ, tlZ, brZ, trZ; + + float dist; + float discriminant; + + //Bottom Left + dist = sqrt(lX * lX + bY * bY); + discriminant = radius2 - dist * dist; + if (discriminant > 0) { + blZ = sqrt(discriminant); + } else { + blZ = 0; } - return _framebufferObject; + //Top Left + dist = sqrt(lX * lX + tY * tY); + discriminant = radius2 - dist * dist; + if (discriminant > 0) { + tlZ = sqrt(discriminant); + } else { + tlZ = 0; + } + //Bottom Right + dist = sqrt(rX * rX + bY * bY); + discriminant = radius2 - dist * dist; + if (discriminant > 0) { + brZ = sqrt(discriminant); + } else { + brZ = 0; + } + //Top Right + dist = sqrt(rX * rX + tY * tY); + discriminant = radius2 - dist * dist; + if (discriminant > 0) { + trZ = sqrt(discriminant); + } else { + trZ = 0; + } + + if (showBorder) { + glDisable(GL_TEXTURE_2D); + glLineWidth(1.0f); + //Outer Line + glBegin(GL_LINE_STRIP); + glColor4f(1.0f, 0.0f, 0.0f, _alpha); + + glVertex3f(lX, tY, -tlZ); + glVertex3f(rX, tY, -trZ); + glVertex3f(rX, bY, -brZ); + glVertex3f(lX, bY, -blZ); + glVertex3f(lX, tY, -tlZ); + + glEnd(); + glEnable(GL_TEXTURE_2D); + } + glColor4f(1.0f, 1.0f, 1.0f, _alpha); + + glBegin(GL_QUADS); + + glTexCoord2f(magnifyULeft, magnifyVBottom); glVertex3f(lX, tY, -tlZ); + glTexCoord2f(magnifyURight, magnifyVBottom); glVertex3f(rX, tY, -trZ); + glTexCoord2f(magnifyURight, magnifyVTop); glVertex3f(rX, bY, -brZ); + glTexCoord2f(magnifyULeft, magnifyVTop); glVertex3f(lX, bY, -blZ); + + glEnd(); + +} + +ApplicationOverlay::TexturedHemisphere::TexturedHemisphere() : + _vertices(0), + _indices(0), + _framebufferObject(NULL), + _vbo(0, 0) { +} + +ApplicationOverlay::TexturedHemisphere::~TexturedHemisphere() { + cleanupVBO(); + if (_framebufferObject != NULL) { + delete _framebufferObject; + } +} + +void ApplicationOverlay::TexturedHemisphere::bind() { + if (_framebufferObject != NULL) { + _framebufferObject->bind(); + } +} + +void ApplicationOverlay::TexturedHemisphere::release() { + if (_framebufferObject != NULL) { + _framebufferObject->release(); + } +} + +void ApplicationOverlay::TexturedHemisphere::buildVBO(const float fov, + const float aspectRatio, + const int slices, + const int stacks) { + if (fov >= PI) { + qDebug() << "TexturedHemisphere::buildVBO(): FOV greater or equal than Pi will create issues"; + } + // Cleanup old VBO if necessary + cleanupVBO(); + + //UV mapping source: http://www.mvps.org/directx/articles/spheremap.htm + + // Compute number of vertices needed + _vertices = slices * stacks; + + // Compute vertices positions and texture UV coordinate + TextureVertex* vertexData = new TextureVertex[_vertices]; + TextureVertex* vertexPtr = &vertexData[0]; + for (int i = 0; i < stacks; i++) { + float stacksRatio = (float)i / (float)stacks; // First stack is 0.0f, last stack is 1.0f + // abs(phi) <= fov / 2.0f + float phi = fov * (stacksRatio - 0.5f); + + for (int j = 0; j < slices; j++) { + float slicesRatio = (float)j / (float)slices; // First slice is 0.0f, last slice is 1.0f + // abs(theta) <= fov * aspectRatio / 2.0f + float theta = fov * aspectRatio * (slicesRatio - 0.5f); + + vertexPtr->position.x = -sinf(theta); + vertexPtr->position.y = sinf(phi); + vertexPtr->position.z = cosf(theta); + vertexPtr->uv.x = slicesRatio; + vertexPtr->uv.y = 1.0f - stacksRatio; + vertexPtr++; + } + } + // Create and write to buffer + glGenBuffers(1, &_vbo.first); + glBindBuffer(GL_ARRAY_BUFFER, _vbo.first); + static const int BYTES_PER_VERTEX = sizeof(TextureVertex); + glBufferData(GL_ARRAY_BUFFER, _vertices * BYTES_PER_VERTEX, vertexData, GL_STATIC_DRAW); + delete[] vertexData; + + + // Compute number of indices needed + static const int VERTEX_PER_TRANGLE = 3; + static const int TRIANGLE_PER_RECTANGLE = 2; + int numberOfRectangles = (slices - 1) * (stacks - 1); + _indices = numberOfRectangles * TRIANGLE_PER_RECTANGLE * VERTEX_PER_TRANGLE; + + // Compute indices order + GLushort* indexData = new GLushort[_indices]; + GLushort* indexPtr = indexData; + for (int i = 0; i < stacks - 1; i++) { + for (int j = 0; j < slices - 1; j++) { + GLushort bottomLeftIndex = i * slices + j; + GLushort bottomRightIndex = bottomLeftIndex + 1; + GLushort topLeftIndex = bottomLeftIndex + slices; + GLushort topRightIndex = topLeftIndex + 1; + + *(indexPtr++) = topLeftIndex; + *(indexPtr++) = bottomLeftIndex; + *(indexPtr++) = topRightIndex; + + *(indexPtr++) = topRightIndex; + *(indexPtr++) = bottomLeftIndex; + *(indexPtr++) = bottomRightIndex; + } + } + // Create and write to buffer + glGenBuffers(1, &_vbo.second); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vbo.second); + static const int BYTES_PER_INDEX = sizeof(GLushort); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, _indices * BYTES_PER_INDEX, indexData, GL_STATIC_DRAW); + delete[] indexData; +} + +void ApplicationOverlay::TexturedHemisphere::cleanupVBO() { + if (_vbo.first != 0) { + glDeleteBuffers(1, &_vbo.first); + _vbo.first = 0; + } + if (_vbo.second != 0) { + glDeleteBuffers(1, &_vbo.second); + _vbo.second = 0; + } +} + +void ApplicationOverlay::TexturedHemisphere::buildFramebufferObject(const QSize& size) { + if (_framebufferObject != NULL) { + delete _framebufferObject; + } + + _framebufferObject = new QOpenGLFramebufferObject(size); + glBindTexture(GL_TEXTURE_2D, _framebufferObject->texture()); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); + GLfloat borderColor[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor); + glBindTexture(GL_TEXTURE_2D, 0); +} + +//Renders a hemisphere with texture coordinates. +void ApplicationOverlay::TexturedHemisphere::render(const glm::quat& orientation, const glm::vec3& position, const float scale) { + if (_framebufferObject == NULL || _vbo.first == 0 || _vbo.second == 0) { + qDebug() << "TexturedHemisphere::render(): Incorrect initialisation"; + return; + } + + _framebufferObject->bind(); + glBindBuffer(GL_ARRAY_BUFFER, _vbo.first); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vbo.second); + + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + + static const int STRIDE = sizeof(TextureVertex); + static const void* VERTEX_POINTER = 0; + static const void* TEX_COORD_POINTER = (void*)sizeof(glm::vec3); + glVertexPointer(3, GL_FLOAT, STRIDE, VERTEX_POINTER); + glTexCoordPointer(2, GL_FLOAT, STRIDE, TEX_COORD_POINTER); + + glPushMatrix(); { + glTranslatef(position.x, position.y, position.z); + glm::mat4 rotation = glm::toMat4(orientation); + glMultMatrixf(&rotation[0][0]); + glScalef(scale, scale, scale); + + glDrawRangeElements(GL_TRIANGLES, 0, _vertices - 1, _indices, GL_UNSIGNED_SHORT, 0); + } glPopMatrix(); + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + + _framebufferObject->release(); + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); } diff --git a/interface/src/ui/ApplicationOverlay.h b/interface/src/ui/ApplicationOverlay.h index 94100d094c..94fc4e4958 100644 --- a/interface/src/ui/ApplicationOverlay.h +++ b/interface/src/ui/ApplicationOverlay.h @@ -37,7 +37,6 @@ public: // Getters - QOpenGLFramebufferObject* getFramebufferObject(); float getAlpha() const { return _alpha; } private: @@ -48,7 +47,31 @@ private: }; typedef QPair VerticesIndices; - + class TexturedHemisphere { + public: + TexturedHemisphere(); + ~TexturedHemisphere(); + + void bind(); + void release(); + + void buildVBO(const float fov, const float aspectRatio, const int slices, const int stacks); + void buildFramebufferObject(const QSize& size); + void render(const glm::quat& orientation, const glm::vec3& position, const float scale); + + private: + void cleanupVBO(); + + GLuint _vertices; + GLuint _indices; + QOpenGLFramebufferObject* _framebufferObject; + VerticesIndices _vbo; + }; + + VerticesIndices* makeTexturedHemiphereVBO(float fov, float aspectRatio, int slices, int stacks); + void renderTexturedHemisphere(ApplicationOverlay::VerticesIndices* vbo, int vertices, int indices); + QOpenGLFramebufferObject* newFramebufferObject(QSize& size); + void renderPointers(); void renderControllerPointers(); void renderPointersOculus(const glm::vec3& eyePos); @@ -56,15 +79,14 @@ private: void renderAudioMeter(); void renderStatsAndLogs(); void renderDomainConnectionStatusBorder(); - - VerticesIndices* makeTexturedHemiphereVBO(float fov, float aspectRatio, int slices, int stacks); - void renderTexturedHemisphere(ApplicationOverlay::VerticesIndices* vbo, int vertices, int indices); - QOpenGLFramebufferObject* _framebufferObject; + TexturedHemisphere _overlays; + TexturedHemisphere _reticule; + float _trailingAudioLoudness; float _textureFov; - enum MagnifyDevices { MOUSE, LEFT_CONTROLLER, RIGHT_CONTROLLER, NUMBER_OF_MAGNIFIERS = RIGHT_CONTROLLER + 1 }; + enum MagnifyDevices { MOUSE, LEFT_CONTROLLER, RIGHT_CONTROLLER, NUMBER_OF_MAGNIFIERS }; bool _reticleActive[NUMBER_OF_MAGNIFIERS]; int _mouseX[NUMBER_OF_MAGNIFIERS]; int _mouseY[NUMBER_OF_MAGNIFIERS]; @@ -74,7 +96,7 @@ private: float _magSizeMult[NUMBER_OF_MAGNIFIERS]; float _alpha; - float _oculusuiRadius; + float _oculusUIRadius; GLuint _crosshairTexture; }; From 40df4973745655ff5d2af1c42d6705300cd89cc9 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 2 Dec 2014 13:48:59 -0800 Subject: [PATCH 157/502] Hack for the Viking Palace scene before demo for good looking lightmaps --- interface/src/renderer/GeometryCache.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/interface/src/renderer/GeometryCache.cpp b/interface/src/renderer/GeometryCache.cpp index e2517613df..e523d7e608 100644 --- a/interface/src/renderer/GeometryCache.cpp +++ b/interface/src/renderer/GeometryCache.cpp @@ -841,6 +841,8 @@ void GeometryReader::run() { grabLightmaps = false; } else if (_url.path().toLower().endsWith("apt8_reboot.fbx")) { lightmapLevel = 4.0f; + } else if (_url.path().toLower().endsWith("palaceoforinthilian4.fbx")) { + lightmapLevel = 3.5f; } fbxgeo = readFBX(_reply->readAll(), _mapping, grabLightmaps, lightmapLevel); } From 2f11501e5b8f3fa5ff8049e8fbd8948f51fcb3c3 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Tue, 2 Dec 2014 14:28:46 -0800 Subject: [PATCH 158/502] Fix constant movement with hydra by adding null zone for thrust --- examples/hydraMove.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/examples/hydraMove.js b/examples/hydraMove.js index 236cecab18..f469fbbe74 100644 --- a/examples/hydraMove.js +++ b/examples/hydraMove.js @@ -245,10 +245,15 @@ function handleGrabBehavior(deltaTime) { } // Update for joysticks and move button +var THRUST_DEAD_ZONE = 0.1; function flyWithHydra(deltaTime) { var thrustJoystickPosition = Controller.getJoystickPosition(THRUST_CONTROLLER); - if (thrustJoystickPosition.x != 0 || thrustJoystickPosition.y != 0) { + if (debug) { + print("thrust X: " + thrustJoystickPosition.x + " Y: " + thrustJoystickPosition.y); + } + + if (Math.abs(thrustJoystickPosition.x) > THRUST_DEAD_ZONE || Math.abs(thrustJoystickPosition.y) > THRUST_DEAD_ZONE) { if (thrustMultiplier < MAX_THRUST_MULTIPLIER) { thrustMultiplier *= 1 + (deltaTime * THRUST_INCREASE_RATE); } From 1ce201c04f9b93a17dc43ee6464dbbac809997a8 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Tue, 2 Dec 2014 14:33:19 -0800 Subject: [PATCH 159/502] add same for rotation --- examples/hydraMove.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/examples/hydraMove.js b/examples/hydraMove.js index f469fbbe74..46715839c3 100644 --- a/examples/hydraMove.js +++ b/examples/hydraMove.js @@ -246,13 +246,10 @@ function handleGrabBehavior(deltaTime) { // Update for joysticks and move button var THRUST_DEAD_ZONE = 0.1; +var ROTATE_DEAD_ZONE = 0.1; function flyWithHydra(deltaTime) { var thrustJoystickPosition = Controller.getJoystickPosition(THRUST_CONTROLLER); - if (debug) { - print("thrust X: " + thrustJoystickPosition.x + " Y: " + thrustJoystickPosition.y); - } - if (Math.abs(thrustJoystickPosition.x) > THRUST_DEAD_ZONE || Math.abs(thrustJoystickPosition.y) > THRUST_DEAD_ZONE) { if (thrustMultiplier < MAX_THRUST_MULTIPLIER) { thrustMultiplier *= 1 + (deltaTime * THRUST_INCREASE_RATE); @@ -275,7 +272,7 @@ function flyWithHydra(deltaTime) { // View Controller var viewJoystickPosition = Controller.getJoystickPosition(VIEW_CONTROLLER); - if (viewJoystickPosition.x != 0 || viewJoystickPosition.y != 0) { + if (Math.abs(viewJoystickPosition.x) > ROTATE_DEAD_ZONE || Math.abs(viewJoystickPosition.y) > ROTATE_DEAD_ZONE) { // change the body yaw based on our x controller var orientation = MyAvatar.orientation; From 284cd54e28d3d75438cbed70f7e31f18b7e85036 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 2 Dec 2014 14:33:54 -0800 Subject: [PATCH 160/502] More detachment fixes. --- interface/src/ui/MetavoxelEditor.cpp | 25 ++++++------------------- interface/src/ui/MetavoxelEditor.h | 5 ++--- 2 files changed, 8 insertions(+), 22 deletions(-) diff --git a/interface/src/ui/MetavoxelEditor.cpp b/interface/src/ui/MetavoxelEditor.cpp index a88b981d66..6989c47d67 100644 --- a/interface/src/ui/MetavoxelEditor.cpp +++ b/interface/src/ui/MetavoxelEditor.cpp @@ -182,13 +182,6 @@ QVariant MetavoxelEditor::getValue() const { return editor ? editor->metaObject()->userProperty().read(editor) : QVariant(); } -void MetavoxelEditor::detachValue() { - SharedObjectEditor* editor = qobject_cast(_valueArea->widget()); - if (editor) { - editor->detachObject(); - } -} - bool MetavoxelEditor::eventFilter(QObject* watched, QEvent* event) { // pass along to the active tool MetavoxelTool* tool = getActiveTool(); @@ -616,7 +609,7 @@ PlaceSpannerTool::PlaceSpannerTool(MetavoxelEditor* editor, const QString& name, } void PlaceSpannerTool::simulate(float deltaTime) { - Spanner* spanner = static_cast(getSpanner(true).data()); + Spanner* spanner = static_cast(getSpanner().data()); Transformable* transformable = qobject_cast(spanner); if (transformable && _followMouse->isChecked() && !Application::getInstance()->isMouseHidden()) { // find the intersection of the mouse ray with the grid and place the transformable there @@ -649,10 +642,7 @@ bool PlaceSpannerTool::eventFilter(QObject* watched, QEvent* event) { return false; } -SharedObjectPointer PlaceSpannerTool::getSpanner(bool detach) { - if (detach) { - _editor->detachValue(); - } +SharedObjectPointer PlaceSpannerTool::getSpanner() { return _editor->getValue().value(); } @@ -663,7 +653,7 @@ QColor PlaceSpannerTool::getColor() { void PlaceSpannerTool::place() { AttributePointer attribute = AttributeRegistry::getInstance()->getAttribute(_editor->getSelectedAttribute()); if (attribute) { - applyEdit(attribute, getSpanner()); + applyEdit(attribute, getSpanner()->clone()); } } @@ -897,7 +887,8 @@ MaterialControl::MaterialControl(QWidget* widget, QFormLayout* form, bool cleara SharedObjectPointer MaterialControl::getMaterial() { SharedObjectPointer material = _materialEditor->getObject(); if (static_cast(material.data())->getDiffuse().isValid()) { - _materialEditor->detachObject(); + material = material->clone(); + } else { material = SharedObjectPointer(); } @@ -1014,10 +1005,7 @@ bool VoxelMaterialSpannerTool::appliesTo(const AttributePointer& attribute) cons return attribute->inherits("VoxelColorAttribute"); } -SharedObjectPointer VoxelMaterialSpannerTool::getSpanner(bool detach) { - if (detach) { - _spannerEditor->detachObject(); - } +SharedObjectPointer VoxelMaterialSpannerTool::getSpanner() { return _spannerEditor->getObject(); } @@ -1026,7 +1014,6 @@ QColor VoxelMaterialSpannerTool::getColor() { } void VoxelMaterialSpannerTool::applyEdit(const AttributePointer& attribute, const SharedObjectPointer& spanner) { - _spannerEditor->detachObject(); MetavoxelEditMessage message = { QVariant::fromValue(VoxelMaterialSpannerEdit(spanner, _materialControl->getMaterial(), _materialControl->getColor())) }; Application::getInstance()->getMetavoxels()->applyEdit(message, true); diff --git a/interface/src/ui/MetavoxelEditor.h b/interface/src/ui/MetavoxelEditor.h index 4e870a9982..c0433fc3cd 100644 --- a/interface/src/ui/MetavoxelEditor.h +++ b/interface/src/ui/MetavoxelEditor.h @@ -46,7 +46,6 @@ public: glm::quat getGridRotation() const; QVariant getValue() const; - void detachValue(); virtual bool eventFilter(QObject* watched, QEvent* event); @@ -197,7 +196,7 @@ public: protected: virtual QColor getColor(); - virtual SharedObjectPointer getSpanner(bool detach = false); + virtual SharedObjectPointer getSpanner(); virtual void applyEdit(const AttributePointer& attribute, const SharedObjectPointer& spanner) = 0; protected slots: @@ -422,7 +421,7 @@ public: protected: - virtual SharedObjectPointer getSpanner(bool detach = false); + virtual SharedObjectPointer getSpanner(); virtual QColor getColor(); virtual void applyEdit(const AttributePointer& attribute, const SharedObjectPointer& spanner); From 06b22cf6057c54aa326c88ac474780c766c85445 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Tue, 2 Dec 2014 14:50:25 -0800 Subject: [PATCH 161/502] ...and don't turn on/off UI from hydra --- interface/src/ui/ApplicationOverlay.cpp | 26 ------------------------- 1 file changed, 26 deletions(-) diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 1307672ad1..305119a019 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -571,8 +571,6 @@ void ApplicationOverlay::renderControllerPointers() { static quint64 pressedTime[NUMBER_OF_MAGNIFIERS] = { 0ULL, 0ULL, 0ULL }; static bool isPressed[NUMBER_OF_MAGNIFIERS] = { false, false, false }; static bool stateWhenPressed[NUMBER_OF_MAGNIFIERS] = { false, false, false }; - static bool triggerPressed[NUMBER_OF_MAGNIFIERS] = { false, false, false }; - static bool bumperPressed[NUMBER_OF_MAGNIFIERS] = { false, false, false }; const HandData* handData = Application::getInstance()->getAvatar()->getHandData(); @@ -613,30 +611,6 @@ void ApplicationOverlay::renderControllerPointers() { } } - //Check for UI active toggle - if (palmData->getTrigger() == 1.0f) { - if (!triggerPressed[index]) { - if (bumperPressed[index]) { - Menu::getInstance()->setIsOptionChecked(MenuOption::UserInterface, - !Menu::getInstance()->isOptionChecked(MenuOption::UserInterface)); - } - triggerPressed[index] = true; - } - } else { - triggerPressed[index] = false; - } - if ((controllerButtons & BUTTON_FWD)) { - if (!bumperPressed[index]) { - if (triggerPressed[index]) { - Menu::getInstance()->setIsOptionChecked(MenuOption::UserInterface, - !Menu::getInstance()->isOptionChecked(MenuOption::UserInterface)); - } - bumperPressed[index] = true; - } - } else { - bumperPressed[index] = false; - } - //if we have the oculus, we should make the cursor smaller since it will be //magnified if (OculusManager::isConnected()) { From 63d1ac83753a6620c1408660502eacd9c5d80e2e Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 2 Dec 2014 14:56:12 -0800 Subject: [PATCH 162/502] implement support for entity subclasses to implement their own detailed ray intersection, make likes light pickability toggle --- examples/editModels.js | 26 ++++++++++++------- .../entities/RenderableLightEntityItem.cpp | 11 ++++++++ .../src/entities/RenderableLightEntityItem.h | 4 +++ libraries/entities/src/EntityItem.h | 5 ++++ .../entities/src/EntityScriptingInterface.cpp | 13 ++++++++++ .../entities/src/EntityScriptingInterface.h | 2 ++ libraries/entities/src/EntityTree.cpp | 1 + libraries/entities/src/EntityTree.h | 5 ++++ libraries/entities/src/EntityTreeElement.cpp | 21 ++++++++++++--- 9 files changed, 75 insertions(+), 13 deletions(-) diff --git a/examples/editModels.js b/examples/editModels.js index 3f1863fef2..8e3503b9b2 100644 --- a/examples/editModels.js +++ b/examples/editModels.js @@ -2807,6 +2807,7 @@ function mouseReleaseEvent(event) { // exists. If it doesn't they add it. If it does they don't. They also only delete the menu item if they were the one that // added it. var modelMenuAddedDelete = false; +var originalLightsArePickable = Entities.getLightsArePickable(); function setupModelMenus() { print("setupModelMenus()"); // adj our menuitems @@ -2824,15 +2825,18 @@ function setupModelMenus() { Menu.addMenuItem({ menuName: "Edit", menuItemName: "Model List...", afterItem: "Models" }); Menu.addMenuItem({ menuName: "Edit", menuItemName: "Paste Models", shortcutKey: "CTRL+META+V", afterItem: "Edit Properties..." }); - Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Select Large Models", shortcutKey: "CTRL+META+L", + Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Selecting of Large Models", shortcutKey: "CTRL+META+L", afterItem: "Paste Models", isCheckable: true }); - Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Select Small Models", shortcutKey: "CTRL+META+S", - afterItem: "Allow Select Large Models", isCheckable: true }); + Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Selecting of Small Models", shortcutKey: "CTRL+META+S", + afterItem: "Allow Selecting of Large Models", isCheckable: true }); + Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Selecting of Lights", shortcutKey: "CTRL+SHIFT+META+L", + afterItem: "Allow Selecting of Small Models", isCheckable: true }); Menu.addMenuItem({ menuName: "File", menuItemName: "Models", isSeparator: true, beforeItem: "Settings" }); Menu.addMenuItem({ menuName: "File", menuItemName: "Export Models", shortcutKey: "CTRL+META+E", afterItem: "Models" }); Menu.addMenuItem({ menuName: "File", menuItemName: "Import Models", shortcutKey: "CTRL+META+I", afterItem: "Export Models" }); + Entities.setLightsArePickable(false); } @@ -2846,8 +2850,9 @@ function cleanupModelMenus() { Menu.removeMenuItem("Edit", "Model List..."); Menu.removeMenuItem("Edit", "Paste Models"); - Menu.removeMenuItem("Edit", "Allow Select Large Models"); - Menu.removeMenuItem("Edit", "Allow Select Small Models"); + Menu.removeMenuItem("Edit", "Allow Selecting of Large Models"); + Menu.removeMenuItem("Edit", "Allow Selecting of Small Models"); + Menu.removeMenuItem("Edit", "Allow Selecting of Lights"); Menu.removeSeparator("File", "Models"); Menu.removeMenuItem("File", "Export Models"); @@ -2865,6 +2870,7 @@ function scriptEnding() { if (exportMenu) { exportMenu.close(); } + Entities.setLightsArePickable(originalLightsArePickable); } Script.scriptEnding.connect(scriptEnding); @@ -2890,10 +2896,12 @@ function showPropertiesForm(editModelID) { function handeMenuEvent(menuItem) { print("menuItemEvent() in JS... menuItem=" + menuItem); - if (menuItem == "Allow Select Small Models") { - allowSmallModels = Menu.isOptionChecked("Allow Select Small Models"); - } else if (menuItem == "Allow Select Large Models") { - allowLargeModels = Menu.isOptionChecked("Allow Select Large Models"); + if (menuItem == "Allow Selecting of Small Models") { + allowSmallModels = Menu.isOptionChecked("Allow Selecting of Small Models"); + } else if (menuItem == "Allow Selecting of Large Models") { + allowLargeModels = Menu.isOptionChecked("Allow Selecting of Large Models"); + } else if (menuItem == "Allow Selecting of Lights") { + Entities.setLightsArePickable(Menu.isOptionChecked("Allow Selecting of Lights")); } else if (menuItem == "Delete") { if (leftController.grabbing) { print(" Delete Entity.... leftController.entityID="+ leftController.entityID); diff --git a/interface/src/entities/RenderableLightEntityItem.cpp b/interface/src/entities/RenderableLightEntityItem.cpp index e3e8f61e58..91b2d35106 100644 --- a/interface/src/entities/RenderableLightEntityItem.cpp +++ b/interface/src/entities/RenderableLightEntityItem.cpp @@ -90,3 +90,14 @@ void RenderableLightEntityItem::render(RenderArgs* args) { glPopMatrix(); } }; + +bool RenderableLightEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, + bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, + void** intersectedObject) const { + + // TODO: this isn't really correct because we don't know if we actually live in the main tree of the applications's + // EntityTreeRenderer. But we probably do. Technically we could be on the clipboard and someone might be trying to + // use the ray intersection API there. Anyway... if you ever try to do ray intersection testing off of trees other + // than the main tree of the main entity renderer, then you'll need to fix this mechanism. + return Application::getInstance()->getEntities()->getTree()->getLightsArePickable(); +} diff --git a/interface/src/entities/RenderableLightEntityItem.h b/interface/src/entities/RenderableLightEntityItem.h index cecd9b761e..40fa31a4ce 100644 --- a/interface/src/entities/RenderableLightEntityItem.h +++ b/interface/src/entities/RenderableLightEntityItem.h @@ -34,6 +34,10 @@ public: { } virtual void render(RenderArgs* args); + virtual bool supportsDetailedRayIntersection() const { return true; } + virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, + bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, + void** intersectedObject) const; }; diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 3f63c96c4e..2c6eb0fdee 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -134,6 +134,11 @@ public: virtual SimulationState computeSimulationState() const; virtual void debugDump() const; + + virtual bool supportsDetailedRayIntersection() const { return false; } + virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, + bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, + void** intersectedObject) const { return true; } // attributes applicable to all entity types EntityTypes::EntityType getType() const { return _type; } diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 29c4a8b19a..575a6c1a78 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -221,6 +221,19 @@ RayToEntityIntersectionResult EntityScriptingInterface::findRayIntersectionWorke return result; } +void EntityScriptingInterface::setLightsArePickable(bool value) { + if (_entityTree) { + _entityTree->setLightsArePickable(value); + } +} + +bool EntityScriptingInterface::getLightsArePickable() const { + if (_entityTree) { + return _entityTree->getLightsArePickable(); + } + return false; +} + RayToEntityIntersectionResult::RayToEntityIntersectionResult() : intersects(false), diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index 2150fa51da..da0c6c9f1a 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -96,6 +96,8 @@ public slots: /// order to return an accurate result Q_INVOKABLE RayToEntityIntersectionResult findRayIntersectionBlocking(const PickRay& ray); + Q_INVOKABLE void setLightsArePickable(bool value); + Q_INVOKABLE bool getLightsArePickable() const; Q_INVOKABLE void dumpTree() const; diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index bb201b6f86..15d0dbddfb 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -20,6 +20,7 @@ EntityTree::EntityTree(bool shouldReaverage) : Octree(shouldReaverage) { _rootElement = createNewElement(); + _lightsArePickable = true; // assume they are by default } EntityTree::~EntityTree() { diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index 7370ebadc6..7adcc190b4 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -149,6 +149,9 @@ public: QList& getMovingEntities() { return _movingEntities; } + bool getLightsArePickable() const { return _lightsArePickable; } + void setLightsArePickable(bool value) { _lightsArePickable = value; } + signals: void deletingEntity(const EntityItemID& entityID); void addingEntity(const EntityItemID& entityID); @@ -181,6 +184,8 @@ private: QList _mortalEntities; // entities that need to be checked for expiry QSet _changedEntities; // entities that have changed in the last frame + + bool _lightsArePickable; }; #endif // hifi_EntityTree_h diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index 2646cc0dfd..506370a9f0 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -511,10 +511,23 @@ bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, con // and testing intersection there. if (entityFrameBox.findRayIntersection(entityFrameOrigin, entityFrameDirection, localDistance, localFace)) { if (localDistance < distance) { - distance = localDistance; - face = localFace; - *intersectedObject = (void*)entity; - somethingIntersected = true; + // now ask the entity if we actually intersect + if (entity->supportsDetailedRayIntersection()) { + + if (entity->findDetailedRayIntersection(origin, direction, keepSearching, element, localDistance, + localFace, intersectedObject)) { + distance = localDistance; + face = localFace; + *intersectedObject = (void*)entity; + somethingIntersected = true; + } + } else { + // if the entity type doesn't support a detailed intersection, then just return the non-AABox results + distance = localDistance; + face = localFace; + *intersectedObject = (void*)entity; + somethingIntersected = true; + } } } } From 167ab05de4bf6a0fbf4ac104de6b0ab8086e3a8a Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 2 Dec 2014 15:19:51 -0800 Subject: [PATCH 163/502] Default 'Allow Select Large/Small Models' to true --- examples/newEditEntities.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/newEditEntities.js b/examples/newEditEntities.js index bc2d87259e..b013b40bce 100644 --- a/examples/newEditEntities.js +++ b/examples/newEditEntities.js @@ -51,8 +51,8 @@ var toolWidth = 50; var MIN_ANGULAR_SIZE = 2; var MAX_ANGULAR_SIZE = 45; -var allowLargeModels = false; -var allowSmallModels = false; +var allowLargeModels = true; +var allowSmallModels = true; var wantEntityGlow = false; var SPAWN_DISTANCE = 1; @@ -644,9 +644,9 @@ function setupModelMenus() { Menu.addMenuItem({ menuName: "Edit", menuItemName: "Model List...", afterItem: "Models" }); Menu.addMenuItem({ menuName: "Edit", menuItemName: "Paste Models", shortcutKey: "CTRL+META+V", afterItem: "Edit Properties..." }); Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Select Large Models", shortcutKey: "CTRL+META+L", - afterItem: "Paste Models", isCheckable: true }); + afterItem: "Paste Models", isCheckable: true, isChecked: true }); Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Select Small Models", shortcutKey: "CTRL+META+S", - afterItem: "Allow Select Large Models", isCheckable: true }); + afterItem: "Allow Select Large Models", isCheckable: true, isChecked: true }); Menu.addMenuItem({ menuName: "File", menuItemName: "Models", isSeparator: true, beforeItem: "Settings" }); Menu.addMenuItem({ menuName: "File", menuItemName: "Export Models", shortcutKey: "CTRL+META+E", afterItem: "Models" }); From bb6e302d694db9a083b4a188ceaef8e8d4b2c8f9 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 2 Dec 2014 15:23:05 -0800 Subject: [PATCH 164/502] support toggle of light picking in newEditEntities.js --- examples/newEditEntities.js | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/examples/newEditEntities.js b/examples/newEditEntities.js index bc2d87259e..96a8617cd9 100644 --- a/examples/newEditEntities.js +++ b/examples/newEditEntities.js @@ -626,6 +626,7 @@ Controller.mouseReleaseEvent.connect(mouseReleaseEvent); // exists. If it doesn't they add it. If it does they don't. They also only delete the menu item if they were the one that // added it. var modelMenuAddedDelete = false; +var originalLightsArePickable = Entities.getLightsArePickable(); function setupModelMenus() { print("setupModelMenus()"); // adj our menuitems @@ -643,10 +644,12 @@ function setupModelMenus() { Menu.addMenuItem({ menuName: "Edit", menuItemName: "Model List...", afterItem: "Models" }); Menu.addMenuItem({ menuName: "Edit", menuItemName: "Paste Models", shortcutKey: "CTRL+META+V", afterItem: "Edit Properties..." }); - Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Select Large Models", shortcutKey: "CTRL+META+L", + Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Selecting of Large Models", shortcutKey: "CTRL+META+L", afterItem: "Paste Models", isCheckable: true }); - Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Select Small Models", shortcutKey: "CTRL+META+S", - afterItem: "Allow Select Large Models", isCheckable: true }); + Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Selecting of Small Models", shortcutKey: "CTRL+META+S", + afterItem: "Allow Selecting of Large Models", isCheckable: true }); + Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Selecting of Lights", shortcutKey: "CTRL+SHIFT+META+L", + afterItem: "Allow Selecting of Small Models", isCheckable: true }); Menu.addMenuItem({ menuName: "File", menuItemName: "Models", isSeparator: true, beforeItem: "Settings" }); Menu.addMenuItem({ menuName: "File", menuItemName: "Export Models", shortcutKey: "CTRL+META+E", afterItem: "Models" }); @@ -655,6 +658,8 @@ function setupModelMenus() { Menu.addMenuItem({ menuName: "View", menuItemName: MENU_EASE_ON_FOCUS, afterItem: MENU_INSPECT_TOOL_ENABLED, isCheckable: true, isChecked: Settings.getValue(SETTING_EASE_ON_FOCUS) == "true" }); + + Entities.setLightsArePickable(false); } setupModelMenus(); // do this when first running our script. @@ -669,8 +674,9 @@ function cleanupModelMenus() { Menu.removeMenuItem("Edit", "Model List..."); Menu.removeMenuItem("Edit", "Paste Models"); - Menu.removeMenuItem("Edit", "Allow Select Large Models"); - Menu.removeMenuItem("Edit", "Allow Select Small Models"); + Menu.removeMenuItem("Edit", "Allow Selecting of Large Models"); + Menu.removeMenuItem("Edit", "Allow Selecting of Small Models"); + Menu.removeMenuItem("Edit", "Allow Selecting of Lights"); Menu.removeSeparator("File", "Models"); Menu.removeMenuItem("File", "Export Models"); @@ -694,6 +700,7 @@ Script.scriptEnding.connect(function() { if (exportMenu) { exportMenu.close(); } + Entities.setLightsArePickable(originalLightsArePickable); }); // Do some stuff regularly, like check for placement of various overlays @@ -704,10 +711,12 @@ Script.update.connect(function (deltaTime) { }); function handeMenuEvent(menuItem) { - if (menuItem == "Allow Select Small Models") { - allowSmallModels = Menu.isOptionChecked("Allow Select Small Models"); - } else if (menuItem == "Allow Select Large Models") { - allowLargeModels = Menu.isOptionChecked("Allow Select Large Models"); + if (menuItem == "Allow Selecting of Small Models") { + allowSmallModels = Menu.isOptionChecked("Allow Selecting of Small Models"); + } else if (menuItem == "Allow Selecting of Large Models") { + allowLargeModels = Menu.isOptionChecked("Allow Selecting of Large Models"); + } else if (menuItem == "Allow Selecting of Lights") { + Entities.setLightsArePickable(Menu.isOptionChecked("Allow Selecting of Lights")); } else if (menuItem == "Delete") { if (SelectionManager.hasSelection()) { print(" Delete Entities"); From 77365ec2829150819debd02c1acf212708126440 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 2 Dec 2014 15:49:45 -0800 Subject: [PATCH 165/502] Move entity selection to click event and add ability to deselect --- examples/libraries/entitySelectionTool.js | 12 +- examples/newEditEntities.js | 129 ++++++++++++---------- 2 files changed, 80 insertions(+), 61 deletions(-) diff --git a/examples/libraries/entitySelectionTool.js b/examples/libraries/entitySelectionTool.js index 1a43231f6f..8fffcf276f 100644 --- a/examples/libraries/entitySelectionTool.js +++ b/examples/libraries/entitySelectionTool.js @@ -89,11 +89,19 @@ SelectionManager = (function() { } } - that.addEntity = function(entityID) { + that.addEntity = function(entityID, toggleSelection) { if (entityID.isKnownID) { - var idx = that.selections.indexOf(entityID); + var idx = -1; + for (var i = 0; i < that.selections.length; i++) { + if (entityID.id == that.selections[i].id) { + idx = i; + break; + } + } if (idx == -1) { that.selections.push(entityID); + } else if (toggleSelection) { + that.selections.splice(idx, 1); } } else { var idx = that.pendingSelections.indexOf(entityID); diff --git a/examples/newEditEntities.js b/examples/newEditEntities.js index b013b40bce..db59944d57 100644 --- a/examples/newEditEntities.js +++ b/examples/newEditEntities.js @@ -485,74 +485,18 @@ function findClickedEntity(event) { return { pickRay: pickRay, entityID: foundEntity }; } +var mouseHasMovedSincePress = false; function mousePressEvent(event) { + mouseHasMovedSincePress = false; + if (toolBar.mousePressEvent(event) || progressDialog.mousePressEvent(event)) { return; } if (isActive) { - var entitySelected = false; if (cameraManager.mousePressEvent(event) || selectionDisplay.mousePressEvent(event)) { // Event handled; do nothing. return; - } else { - var result = findClickedEntity(event); - if (result === null) { - selectionManager.clearSelections(); - return; - } - var pickRay = result.pickRay; - var foundEntity = result.entityID; - - var properties = Entities.getEntityProperties(foundEntity); - if (isLocked(properties)) { - print("Model locked " + properties.id); - } else { - var halfDiagonal = Vec3.length(properties.dimensions) / 2.0; - - print("Checking properties: " + properties.id + " " + properties.isKnownID + " - Half Diagonal:" + halfDiagonal); - // P P - Model - // /| A - Palm - // / | d B - unit vector toward tip - // / | X - base of the perpendicular line - // A---X----->B d - distance fom axis - // x x - distance from A - // - // |X-A| = (P-A).B - // X == A + ((P-A).B)B - // d = |P-X| - - var A = pickRay.origin; - var B = Vec3.normalize(pickRay.direction); - var P = properties.position; - - var x = Vec3.dot(Vec3.subtract(P, A), B); - var X = Vec3.sum(A, Vec3.multiply(B, x)); - var d = Vec3.length(Vec3.subtract(P, X)); - var halfDiagonal = Vec3.length(properties.dimensions) / 2.0; - - var angularSize = 2 * Math.atan(halfDiagonal / Vec3.distance(Camera.getPosition(), properties.position)) * 180 / 3.14; - - var sizeOK = (allowLargeModels || angularSize < MAX_ANGULAR_SIZE) - && (allowSmallModels || angularSize > MIN_ANGULAR_SIZE); - - if (0 < x && sizeOK) { - entitySelected = true; - selectedEntityID = foundEntity; - orientation = MyAvatar.orientation; - intersection = rayPlaneIntersection(pickRay, P, Quat.getFront(orientation)); - - if (!event.isShifted) { - selectionManager.clearSelections(); - } - selectionManager.addEntity(foundEntity); - - print("Model selected: " + foundEntity.id); - } - } - } - if (entitySelected) { - selectionDisplay.select(selectedEntityID, event); } } else if (Menu.isOptionChecked(MENU_INSPECT_TOOL_ENABLED)) { var result = findClickedEntity(event); @@ -572,6 +516,7 @@ function mousePressEvent(event) { var highlightedEntityID = { isKnownID: false }; function mouseMoveEvent(event) { + mouseHasMovedSincePress = true; if (isActive) { // allow the selectionDisplay and cameraManager to handle the event first, if it doesn't handle it, then do our own thing if (selectionDisplay.mouseMoveEvent(event) || cameraManager.mouseMoveEvent(event)) { @@ -615,6 +560,72 @@ function mouseReleaseEvent(event) { } cameraManager.mouseReleaseEvent(event); + + if (!mouseHasMovedSincePress) { + mouseClickEvent(event); + } +} + +function mouseClickEvent(event) { + var result = findClickedEntity(event); + if (result === null) { + if (!event.isShifted) { + selectionManager.clearSelections(); + } + return; + } + var pickRay = result.pickRay; + var foundEntity = result.entityID; + + var properties = Entities.getEntityProperties(foundEntity); + if (isLocked(properties)) { + print("Model locked " + properties.id); + } else { + var halfDiagonal = Vec3.length(properties.dimensions) / 2.0; + + print("Checking properties: " + properties.id + " " + properties.isKnownID + " - Half Diagonal:" + halfDiagonal); + // P P - Model + // /| A - Palm + // / | d B - unit vector toward tip + // / | X - base of the perpendicular line + // A---X----->B d - distance fom axis + // x x - distance from A + // + // |X-A| = (P-A).B + // X == A + ((P-A).B)B + // d = |P-X| + + var A = pickRay.origin; + var B = Vec3.normalize(pickRay.direction); + var P = properties.position; + + var x = Vec3.dot(Vec3.subtract(P, A), B); + var X = Vec3.sum(A, Vec3.multiply(B, x)); + var d = Vec3.length(Vec3.subtract(P, X)); + var halfDiagonal = Vec3.length(properties.dimensions) / 2.0; + + var angularSize = 2 * Math.atan(halfDiagonal / Vec3.distance(Camera.getPosition(), properties.position)) * 180 / 3.14; + + var sizeOK = (allowLargeModels || angularSize < MAX_ANGULAR_SIZE) + && (allowSmallModels || angularSize > MIN_ANGULAR_SIZE); + + if (0 < x && sizeOK) { + entitySelected = true; + selectedEntityID = foundEntity; + orientation = MyAvatar.orientation; + intersection = rayPlaneIntersection(pickRay, P, Quat.getFront(orientation)); + + if (!event.isShifted) { + selectionManager.clearSelections(); + } + + var toggle = event.isShifted; + selectionManager.addEntity(foundEntity, toggle); + + print("Model selected: " + foundEntity.id); + selectionDisplay.select(selectedEntityID, event); + } + } } Controller.mousePressEvent.connect(mousePressEvent); From 2b5a4e4563249c20584ded8295613df882176fe0 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 2 Dec 2014 15:56:43 -0800 Subject: [PATCH 166/502] Add selection boxes in multi-selection mode --- examples/libraries/entitySelectionTool.js | 36 +++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/examples/libraries/entitySelectionTool.js b/examples/libraries/entitySelectionTool.js index 8fffcf276f..302c612f15 100644 --- a/examples/libraries/entitySelectionTool.js +++ b/examples/libraries/entitySelectionTool.js @@ -347,6 +347,8 @@ SelectionDisplay = (function () { lineWidth: 1.0, }); + var selectionBoxes = []; + var rotationDegreesDisplay = Overlays.addOverlay("text3d", { position: { x:0, y: 0, z: 0}, text: "", @@ -692,6 +694,9 @@ SelectionDisplay = (function () { for (var i = 0; i < allOverlays.length; i++) { Overlays.deleteOverlay(allOverlays[i]); } + for (var i = 0; i < selectionBoxes.length; i++) { + Overlays.deleteOverlay(selectionBoxes[i]); + } }; that.highlightSelectable = function(entityID) { @@ -1134,6 +1139,33 @@ SelectionDisplay = (function () { visible: !(mode == "ROTATE_YAW" || mode == "ROTATE_PITCH" || mode == "ROTATE_ROLL"), }); + // Create more selection box overlays if we don't have enough + var overlaysNeeded = selectionManager.selections.length - selectionBoxes.length; + for (var i = 0; i < overlaysNeeded; i++) { + selectionBoxes.push( + Overlays.addOverlay("cube", { + position: { x: 0, y: 0, z: 0 }, + size: 1, + color: { red: 255, green: 153, blue: 0 }, + alpha: 1, + solid: false, + visible: false, + dashed: false, + lineWidth: 1.0, + ignoreRayIntersection: true, + })); + } + + for (var i = 0; i < selectionManager.selections.length; i++) { + var properties = Entities.getEntityProperties(selectionManager.selections[i]); + Overlays.editOverlay(selectionBoxes[i], { + position: properties.position, + rotation: properties.rotation, + dimensions: properties.dimensions, + visible: true, + }); + } + Overlays.editOverlay(grabberEdgeTR, { visible: extendedStretchHandlesVisible, rotation: rotation, position: EdgeTR }); Overlays.editOverlay(grabberEdgeTL, { visible: extendedStretchHandlesVisible, rotation: rotation, position: EdgeTL }); Overlays.editOverlay(grabberEdgeTF, { visible: extendedStretchHandlesVisible, rotation: rotation, position: EdgeTF }); @@ -1157,6 +1189,10 @@ SelectionDisplay = (function () { for (var i = 0; i < length; i++) { Overlays.editOverlay(allOverlays[i], { visible: isVisible }); } + length = selectionBoxes.length; + for (var i = 0; i < length; i++) { + Overlays.editOverlay(selectionBoxes[i], { visible: isVisible }); + } }; that.unselect = function (entityID) { From 2f1ceb922a5a0a2d4ba92dd732b0a91e4d77842e Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 2 Dec 2014 15:59:56 -0800 Subject: [PATCH 167/502] Increase size of selection boxes --- examples/libraries/entitySelectionTool.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/libraries/entitySelectionTool.js b/examples/libraries/entitySelectionTool.js index 302c612f15..92d432df1e 100644 --- a/examples/libraries/entitySelectionTool.js +++ b/examples/libraries/entitySelectionTool.js @@ -332,7 +332,7 @@ SelectionDisplay = (function () { solid: false, visible: false, dashed: true, - lineWidth: 1.0, + lineWidth: 2.0, ignoreRayIntersection: true // this never ray intersects }); @@ -344,7 +344,7 @@ SelectionDisplay = (function () { solid: false, visible: false, dashed: true, - lineWidth: 1.0, + lineWidth: 2.0, }); var selectionBoxes = []; From 0fb0169ff26266487935783e01f6ae5d8c8cd62c Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 2 Dec 2014 16:00:33 -0800 Subject: [PATCH 168/502] Move baseOfEntityProjectionOverlay update to updateHandles() --- examples/libraries/entitySelectionTool.js | 35 +++++++++++------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/examples/libraries/entitySelectionTool.js b/examples/libraries/entitySelectionTool.js index 92d432df1e..babf658f95 100644 --- a/examples/libraries/entitySelectionTool.js +++ b/examples/libraries/entitySelectionTool.js @@ -946,23 +946,6 @@ SelectionDisplay = (function () { var dimensions = selectionManager.worldDimensions; var position = selectionManager.worldPosition; - Overlays.editOverlay(baseOfEntityProjectionOverlay, - { - visible: mode != "ROTATE_YAW" && mode != "ROTATE_PITCH" && mode != "ROTATE_ROLL", - solid: true, - // lineWidth: 2.0, - position: { - x: position.x, - y: grid.getOrigin().y, - z: position.z - }, - dimensions: { - x: dimensions.x, - y: dimensions.z - }, - rotation: rotation, - }); - Overlays.editOverlay(rotateOverlayTarget, { visible: rotationOverlaysVisible }); Overlays.editOverlay(rotateZeroOverlay, { visible: rotationOverlaysVisible }); @@ -999,7 +982,6 @@ SelectionDisplay = (function () { return; } - that.updateRotationHandles(); that.highlightSelectable(); @@ -1182,6 +1164,23 @@ SelectionDisplay = (function () { var grabberMoveUpOffset = 0.1; grabberMoveUpPosition = { x: position.x, y: position.y + worldTop + grabberMoveUpOffset, z: position.z } Overlays.editOverlay(grabberMoveUp, { visible: activeTool == null || mode == "TRANSLATE_UP_DOWN" }); + + Overlays.editOverlay(baseOfEntityProjectionOverlay, { + visible: mode != "ROTATE_YAW" && mode != "ROTATE_PITCH" && mode != "ROTATE_ROLL", + solid: true, + position: { + x: selectionManager.worldPosition.x, + y: grid.getOrigin().y, + z: selectionManager.worldPosition.z + }, + dimensions: { + x: selectionManager.worldDimensions.x, + y: selectionManager.worldDimensions.z + }, + rotation: Quat.fromPitchYawRollDegrees(0, 0, 0), + }); + + }; that.setOverlaysVisible = function(isVisible) { From 30a7b609586192b3a137003cefbe1f00bd2cfa6f Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 2 Dec 2014 16:01:09 -0800 Subject: [PATCH 169/502] Update checkMove to only update rotation handles instead of all handles --- examples/libraries/entitySelectionTool.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/libraries/entitySelectionTool.js b/examples/libraries/entitySelectionTool.js index babf658f95..f88a5c576f 100644 --- a/examples/libraries/entitySelectionTool.js +++ b/examples/libraries/entitySelectionTool.js @@ -2053,7 +2053,7 @@ SelectionDisplay = (function () { that.checkMove = function() { if (SelectionManager.hasSelection() && (!Vec3.equal(Camera.getPosition(), lastCameraPosition) || !Quat.equal(Camera.getOrientation(), lastCameraOrientation))){ - that.select(selectionManager.selections[0], false, false); + that.updateRotationHandles(); } }; From c4ca7e1b18df38381539da8bbf32b4eb6344bf05 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 2 Dec 2014 16:01:40 -0800 Subject: [PATCH 170/502] Remove clearSelections from findClickedEntity - it shouldn't handle it --- examples/newEditEntities.js | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/newEditEntities.js b/examples/newEditEntities.js index db59944d57..92db9daab5 100644 --- a/examples/newEditEntities.js +++ b/examples/newEditEntities.js @@ -476,7 +476,6 @@ function findClickedEntity(event) { var identify = Entities.identifyEntity(foundEntity); if (!identify.isKnownID) { print("Unknown ID " + identify.id + " (update loop " + foundEntity.id + ")"); - selectionManager.clearSelections(); return null; } foundEntity = identify; From 9753041a1a3c01524dc9f69444a19f8110c7b3af Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 2 Dec 2014 16:11:29 -0800 Subject: [PATCH 171/502] Height brush bits. --- libraries/metavoxels/src/Spanner.cpp | 276 ++++++++++++++++++--------- libraries/metavoxels/src/Spanner.h | 6 + 2 files changed, 187 insertions(+), 95 deletions(-) diff --git a/libraries/metavoxels/src/Spanner.cpp b/libraries/metavoxels/src/Spanner.cpp index cb8cdc6260..ee38ef86e4 100644 --- a/libraries/metavoxels/src/Spanner.cpp +++ b/libraries/metavoxels/src/Spanner.cpp @@ -1243,6 +1243,9 @@ bool HeightfieldNode::isLeaf() const { } float HeightfieldNode::getHeight(const glm::vec3& location) const { + if (location.x < 0.0f || location.z < 0.0f || location.x > 1.0f || location.z > 1.0f) { + return -FLT_MAX; + } if (!isLeaf()) { if (location.x < 0.5f) { if (location.z < 0.5f) { @@ -1271,9 +1274,6 @@ float HeightfieldNode::getHeight(const glm::vec3& location) const { glm::vec3 relative = location; relative.x = relative.x * innerWidth + HeightfieldHeight::HEIGHT_BORDER; relative.z = relative.z * innerHeight + HeightfieldHeight::HEIGHT_BORDER; - if (relative.x < 0.0f || relative.z < 0.0f || relative.x > width - 1 || relative.z > height - 1) { - return -FLT_MAX; - } // find the bounds of the cell containing the point and the shared vertex heights glm::vec3 floors = glm::floor(relative); @@ -1304,6 +1304,10 @@ float HeightfieldNode::getHeight(const glm::vec3& location) const { } bool HeightfieldNode::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const { + float boundsDistance; + if (!Box(glm::vec3(), glm::vec3(1.0f, 1.0f, 1.0f)).findRayIntersection(origin, direction, boundsDistance)) { + return false; + } if (!isLeaf()) { float closestDistance = FLT_MAX; for (int i = 0; i < CHILD_COUNT; i++) { @@ -1334,14 +1338,7 @@ bool HeightfieldNode::findRayIntersection(const glm::vec3& origin, const glm::ve glm::vec3 scale((float)innerWidth, (float)numeric_limits::max(), (float)innerHeight); glm::vec3 dir = direction * scale; - glm::vec3 entry = origin * scale; - - float boundsDistance; - if (!Box(glm::vec3(), glm::vec3((float)innerWidth, (float)numeric_limits::max(), - (float)innerHeight)).findRayIntersection(entry, dir, boundsDistance)) { - return false; - } - entry += dir * boundsDistance; + glm::vec3 entry = origin * scale + dir * boundsDistance; entry.x += HeightfieldHeight::HEIGHT_BORDER; entry.z += HeightfieldHeight::HEIGHT_BORDER; @@ -1473,6 +1470,10 @@ bool HeightfieldNode::findRayIntersection(const glm::vec3& origin, const glm::ve HeightfieldNode* HeightfieldNode::paintMaterial(const glm::vec3& position, const glm::vec3& radius, const SharedObjectPointer& material, const QColor& color) { + if (position.x + radius.x < 0.0f || position.z + radius.z < 0.0f || + position.x - radius.x > 1.0f || position.z - radius.z > 1.0f) { + return this; + } if (!isLeaf()) { HeightfieldNode* newNode = this; for (int i = 0; i < CHILD_COUNT; i++) { @@ -1491,15 +1492,13 @@ HeightfieldNode* HeightfieldNode::paintMaterial(const glm::vec3& position, const } return newNode; } - if (!_height || position.x + radius.x < 0.0f || position.z + radius.z < 0.0f || - position.x - radius.x > 1.0f || position.z - radius.z > 1.0f) { + if (!_height) { return this; } int heightWidth = _height->getWidth(); int heightHeight = _height->getContents().size() / heightWidth; int baseWidth = heightWidth - HeightfieldHeight::HEIGHT_EXTENSION + HeightfieldData::SHARED_EDGE; int baseHeight = heightHeight - HeightfieldHeight::HEIGHT_EXTENSION + HeightfieldData::SHARED_EDGE; - HeightfieldNode* newNode = new HeightfieldNode(*this); int colorWidth = baseWidth, colorHeight = baseHeight; QByteArray colorContents; @@ -1556,7 +1555,9 @@ HeightfieldNode* HeightfieldNode::paintMaterial(const glm::vec3& position, const } lineDest += stride; } + HeightfieldNode* newNode = this; if (changed) { + newNode = new HeightfieldNode(*this); newNode->setColor(HeightfieldColorPointer(new HeightfieldColor(colorWidth, colorContents))); } @@ -1589,6 +1590,9 @@ HeightfieldNode* HeightfieldNode::paintMaterial(const glm::vec3& position, const lineDest += materialWidth; } if (changed) { + if (newNode == this) { + newNode = new HeightfieldNode(*this); + } clearUnusedMaterials(materials, materialContents); newNode->setMaterial(HeightfieldMaterialPointer(new HeightfieldMaterial(materialWidth, materialContents, materials))); @@ -1597,6 +1601,153 @@ HeightfieldNode* HeightfieldNode::paintMaterial(const glm::vec3& position, const return newNode; } +void HeightfieldNode::getRangeAfterHeightPaint(const glm::vec3& position, const glm::vec3& radius, + float height, int& minimum, int& maximum) const { + if (position.x + radius.x < 0.0f || position.z + radius.z < 0.0f || + position.x - radius.x > 1.0f || position.z - radius.z > 1.0f) { + return; + } + if (!isLeaf()) { + for (int i = 0; i < CHILD_COUNT; i++) { + _children[i]->getRangeAfterHeightPaint(position * glm::vec3(2.0f, 1.0f, 2.0f) - + glm::vec3(i & X_MAXIMUM_FLAG ? 1.0f : 0.0f, 0.0f, i & Y_MAXIMUM_FLAG ? 1.0f : 0.0f), + radius * glm::vec3(2.0f, 1.0f, 2.0f), height, minimum, maximum); + } + return; + } + if (!_height) { + return; + } + int heightWidth = _height->getWidth(); + int heightHeight = _height->getContents().size() / heightWidth; + QVector contents = _height->getContents(); + int innerWidth = heightWidth - HeightfieldHeight::HEIGHT_EXTENSION; + int innerHeight = heightHeight - HeightfieldHeight::HEIGHT_EXTENSION; + int highestX = heightWidth - 1; + int highestZ = heightHeight - 1; + + glm::vec3 scale((float)innerWidth, 1.0f, (float)innerHeight); + glm::vec3 center = position * scale; + center.x += 1.0f; + center.z += 1.0f; + + glm::vec3 extents = radius * scale; + glm::vec3 start = glm::floor(center - extents); + glm::vec3 end = glm::ceil(center + extents); + + // first see if we're going to exceed the range limits + float z = qMax(start.z, 0.0f); + float startX = qMax(start.x, 0.0f), endX = qMin(end.x, (float)highestX); + quint16* lineDest = contents.data() + (int)z * heightWidth + (int)startX; + float squaredRadius = extents.x * extents.x; + float squaredRadiusReciprocal = 1.0f / squaredRadius; + float multiplierZ = extents.x / extents.z; + for (float endZ = qMin(end.z, (float)highestZ); z <= endZ; z += 1.0f) { + quint16* dest = lineDest; + for (float x = startX; x <= endX; x += 1.0f, dest++) { + float dx = x - center.x, dz = (z - center.z) * multiplierZ; + float distanceSquared = dx * dx + dz * dz; + if (distanceSquared <= squaredRadius) { + // height falls off towards edges + int value = *dest; + if (value != 0) { + value += height * (squaredRadius - distanceSquared) * squaredRadiusReciprocal; + minimum = qMin(minimum, value); + maximum = qMax(maximum, value); + } + } + } + lineDest += heightWidth; + } +} + +HeightfieldNode* HeightfieldNode::paintHeight(const glm::vec3& position, const glm::vec3& radius, + float height, float normalizeScale, float normalizeOffset) { + if ((position.x + radius.x < 0.0f || position.z + radius.z < 0.0f || position.x - radius.x > 1.0f || + position.z - radius.z > 1.0f) && normalizeScale == 1.0f && normalizeOffset == 0.0f) { + return this; + } + if (!isLeaf()) { + HeightfieldNode* newNode = this; + for (int i = 0; i < CHILD_COUNT; i++) { + HeightfieldNode* newChild = _children[i]->paintHeight(position * glm::vec3(2.0f, 1.0f, 2.0f) - + glm::vec3(i & X_MAXIMUM_FLAG ? 1.0f : 0.0f, 0.0f, i & Y_MAXIMUM_FLAG ? 1.0f : 0.0f), + radius * glm::vec3(2.0f, 1.0f, 2.0f), height, normalizeScale, normalizeOffset); + if (_children[i] != newChild) { + if (newNode == this) { + newNode = new HeightfieldNode(*this); + } + newNode->setChild(i, HeightfieldNodePointer(newChild)); + } + } + if (newNode != this) { + newNode->mergeChildren(true, false); + } + return newNode; + } + if (!_height) { + return this; + } + int heightWidth = _height->getWidth(); + int heightHeight = _height->getContents().size() / heightWidth; + QVector contents = _height->getContents(); + int innerWidth = heightWidth - HeightfieldHeight::HEIGHT_EXTENSION; + int innerHeight = heightHeight - HeightfieldHeight::HEIGHT_EXTENSION; + int highestX = heightWidth - 1; + int highestZ = heightHeight - 1; + + glm::vec3 scale((float)innerWidth, 1.0f, (float)innerHeight); + glm::vec3 center = position * scale; + center.x += 1.0f; + center.z += 1.0f; + + glm::vec3 extents = radius * scale; + glm::vec3 start = glm::floor(center - extents); + glm::vec3 end = glm::ceil(center + extents); + + // renormalize if necessary + bool changed = false; + if (normalizeScale != 1.0f || normalizeOffset != 0.0f) { + changed = true; + for (quint16* dest = contents.data(), *end = contents.data() + contents.size(); dest != end; dest++) { + int value = *dest; + if (value != 0) { + *dest = (value + normalizeOffset) * normalizeScale; + } + } + } + + // now apply the actual change + float z = qMax(start.z, 0.0f); + float startX = qMax(start.x, 0.0f), endX = qMin(end.x, (float)highestX); + quint16* lineDest = contents.data() + (int)z * heightWidth + (int)startX; + float squaredRadius = extents.x * extents.x; + float squaredRadiusReciprocal = 1.0f / squaredRadius; + float multiplierZ = extents.x / extents.z; + for (float endZ = qMin(end.z, (float)highestZ); z <= endZ; z += 1.0f) { + quint16* dest = lineDest; + for (float x = startX; x <= endX; x += 1.0f, dest++) { + float dx = x - center.x, dz = (z - center.z) * multiplierZ; + float distanceSquared = dx * dx + dz * dz; + if (distanceSquared <= squaredRadius) { + // height falls off towards edges + int value = *dest; + if (value != 0) { + *dest = value + height * (squaredRadius - distanceSquared) * squaredRadiusReciprocal; + changed = true; + } + } + } + lineDest += heightWidth; + } + if (!changed) { + return this; + } + HeightfieldNode* newNode = new HeightfieldNode(*this); + newNode->setHeight(HeightfieldHeightPointer(new HeightfieldHeight(heightWidth, contents))); + return newNode; +} + void HeightfieldNode::read(HeightfieldStreamState& state) { clearChildren(); @@ -2088,7 +2239,7 @@ bool Heightfield::findRayIntersection(const glm::vec3& origin, const glm::vec3& Spanner* Heightfield::paintMaterial(const glm::vec3& position, float radius, const SharedObjectPointer& material, const QColor& color) { - glm::vec3 inverseScale(1.0f / getScale(), 1.0f, 1.0f / getScale() * _aspectZ); + glm::vec3 inverseScale(1.0f / getScale(), 1.0f, 1.0f / (getScale() * _aspectZ)); HeightfieldNode* newRoot = _root->paintMaterial(glm::inverse(getRotation()) * (position - getTranslation()) * inverseScale, radius * inverseScale, material, color); if (_root == newRoot) { @@ -2100,94 +2251,29 @@ Spanner* Heightfield::paintMaterial(const glm::vec3& position, float radius, } Spanner* Heightfield::paintHeight(const glm::vec3& position, float radius, float height) { - if (!_height) { - return this; - } - int heightWidth = _height->getWidth(); - int heightHeight = _height->getContents().size() / heightWidth; - QVector contents = _height->getContents(); - int innerWidth = heightWidth - HeightfieldHeight::HEIGHT_EXTENSION; - int innerHeight = heightHeight - HeightfieldHeight::HEIGHT_EXTENSION; - int highestX = heightWidth - 1; - int highestZ = heightHeight - 1; - Heightfield* newHeightfield = static_cast(clone(true)); - - glm::vec3 inverseScale(innerWidth / getScale(), 1.0f, innerHeight / (getScale() * _aspectZ)); - glm::vec3 center = glm::inverse(getRotation()) * (position - getTranslation()) * inverseScale; - center.x += 1.0f; - center.z += 1.0f; - - glm::vec3 extents = glm::vec3(radius, radius, radius) * inverseScale; - glm::vec3 start = glm::floor(center - extents); - glm::vec3 end = glm::ceil(center + extents); - // first see if we're going to exceed the range limits - float z = qMax(start.z, 0.0f); - float startX = qMax(start.x, 0.0f), endX = qMin(end.x, (float)highestX); - quint16* lineDest = contents.data() + (int)z * heightWidth + (int)startX; - float squaredRadius = extents.x * extents.x; - float squaredRadiusReciprocal = 1.0f / squaredRadius; - float scaledHeight = height * numeric_limits::max() / (getScale() * _aspectY); - float multiplierZ = inverseScale.x / inverseScale.z; + glm::vec3 inverseScale(1.0f / getScale(), 1.0f, 1.0f / (getScale() * _aspectZ)); + glm::vec3 relativePosition = glm::inverse(getRotation()) * (position - getTranslation()) * inverseScale; + glm::vec3 relativeRadius = radius * inverseScale; int minimumValue = 1, maximumValue = numeric_limits::max(); - for (float endZ = qMin(end.z, (float)highestZ); z <= endZ; z += 1.0f) { - quint16* dest = lineDest; - for (float x = startX; x <= endX; x += 1.0f, dest++) { - float dx = x - center.x, dz = (z - center.z) * multiplierZ; - float distanceSquared = dx * dx + dz * dz; - if (distanceSquared <= squaredRadius) { - // height falls off towards edges - int value = *dest; - if (value != 0) { - value += scaledHeight * (squaredRadius - distanceSquared) * squaredRadiusReciprocal; - minimumValue = qMin(minimumValue, value); - maximumValue = qMax(maximumValue, value); - } - } - } - lineDest += heightWidth; - } - + _root->getRangeAfterHeightPaint(relativePosition, relativeRadius, + height * numeric_limits::max() / (getScale() * _aspectY), minimumValue, maximumValue); + // renormalize if necessary + Heightfield* newHeightfield = static_cast(clone(true)); + float normalizeScale = 1.0f, normalizeOffset = 0.0f; if (minimumValue < 1 || maximumValue > numeric_limits::max()) { - float scale = (numeric_limits::max() - 1.0f) / (maximumValue - minimumValue); - float offset = 1.0f - minimumValue; - newHeightfield->setAspectY(_aspectY / scale); + normalizeScale = (numeric_limits::max() - 1.0f) / (maximumValue - minimumValue); + normalizeOffset = 1.0f - minimumValue; + newHeightfield->setAspectY(_aspectY / normalizeScale); newHeightfield->setTranslation(getTranslation() - getRotation() * - glm::vec3(0.0f, offset * _aspectY * getScale() / (numeric_limits::max() - 1), 0.0f)); - for (quint16* dest = contents.data(), *end = contents.data() + contents.size(); dest != end; dest++) { - int value = *dest; - if (value != 0) { - *dest = (value + offset) * scale; - } - } + glm::vec3(0.0f, normalizeOffset * _aspectY * getScale() / (numeric_limits::max() - 1), 0.0f)); } // now apply the actual change - z = qMax(start.z, 0.0f); - lineDest = contents.data() + (int)z * heightWidth + (int)startX; - scaledHeight = height * numeric_limits::max() / (getScale() * newHeightfield->getAspectY()); - bool changed = false; - for (float endZ = qMin(end.z, (float)highestZ); z <= endZ; z += 1.0f) { - quint16* dest = lineDest; - for (float x = startX; x <= endX; x += 1.0f, dest++) { - float dx = x - center.x, dz = (z - center.z) * multiplierZ; - float distanceSquared = dx * dx + dz * dz; - if (distanceSquared <= squaredRadius) { - // height falls off towards edges - int value = *dest; - if (value != 0) { - *dest = value + scaledHeight * (squaredRadius - distanceSquared) * squaredRadiusReciprocal; - changed = true; - } - } - } - lineDest += heightWidth; - } - if (changed) { - newHeightfield->setHeight(HeightfieldHeightPointer(new HeightfieldHeight(heightWidth, contents))); - } - + newHeightfield->setRoot(HeightfieldNodePointer(_root->paintHeight(relativePosition, relativeRadius, + height * numeric_limits::max() / (getScale() * newHeightfield->getAspectY()), + normalizeScale, normalizeOffset))); return newHeightfield; } diff --git a/libraries/metavoxels/src/Spanner.h b/libraries/metavoxels/src/Spanner.h index 6c38dbcb9a..f3e7c6bfdb 100644 --- a/libraries/metavoxels/src/Spanner.h +++ b/libraries/metavoxels/src/Spanner.h @@ -517,6 +517,12 @@ public: HeightfieldNode* paintMaterial(const glm::vec3& position, const glm::vec3& radius, const SharedObjectPointer& material, const QColor& color); + + void getRangeAfterHeightPaint(const glm::vec3& position, const glm::vec3& radius, + float height, int& minimum, int& maximum) const; + + HeightfieldNode* paintHeight(const glm::vec3& position, const glm::vec3& radius, float height, + float normalizeScale, float normalizeOffset); void read(HeightfieldStreamState& state); void write(HeightfieldStreamState& state) const; From 1aec214138d48a4681a0472ed7692635f926b871 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 2 Dec 2014 16:23:09 -0800 Subject: [PATCH 172/502] gabbing the AnbientCOlor value, we will use it as the lighmap global level --- libraries/fbx/src/FBXReader.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 5f215ac4d0..0c52a4b55b 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -1276,6 +1276,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, #endif FBXGeometry geometry; float unitScaleFactor = 1.0f; + glm::vec3 ambientColor; foreach (const FBXNode& child, node.children) { if (child.name == "FBXHeaderExtension") { @@ -1302,10 +1303,16 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, } else if (child.name == "GlobalSettings") { foreach (const FBXNode& object, child.children) { if (object.name == "Properties70") { + QString propertyName = "P"; + int index = 4; foreach (const FBXNode& subobject, object.children) { - if (subobject.name == "P" && subobject.properties.size() >= 5 && - subobject.properties.at(0) == "UnitScaleFactor") { - unitScaleFactor = subobject.properties.at(4).toFloat(); + if (subobject.name == propertyName) { + std::string subpropName = subobject.properties.at(0).toString().toStdString(); + if (subpropName == "UnitScaleFactor") { + unitScaleFactor = subobject.properties.at(index).toFloat(); + } else if (subpropName == "AmbientColor") { + ambientColor = getVec3(subobject.properties, index); + } } } } From aa067bc15389c492baf51d279115e9222b3a707c Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 2 Dec 2014 17:49:25 -0800 Subject: [PATCH 173/502] Update UpDown translation to follow the mouse as other tools do --- examples/libraries/entitySelectionTool.js | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/examples/libraries/entitySelectionTool.js b/examples/libraries/entitySelectionTool.js index f88a5c576f..5f2549a85c 100644 --- a/examples/libraries/entitySelectionTool.js +++ b/examples/libraries/entitySelectionTool.js @@ -1297,10 +1297,17 @@ SelectionDisplay = (function () { }; var lastXYPick = null + var upDownPickNormal = null; addGrabberTool(grabberMoveUp, { mode: "TRANSLATE_UP_DOWN", onBegin: function(event) { - lastXYPick = rayPlaneIntersection(pickRay, SelectionManager.worldPosition, Quat.getFront(lastCameraOrientation)); + pickRay = Camera.computePickRay(event.x, event.y); + + upDownPickNormal = Quat.getFront(lastCameraOrientation); + // Remove y component so the y-axis lies along the plane we picking on - this will + // give movements that follow the mouse. + upDownPickNormal.y = 0; + lastXYPick = rayPlaneIntersection(pickRay, SelectionManager.worldPosition, upDownPickNormal); SelectionManager.saveProperties(); @@ -1328,11 +1335,9 @@ SelectionDisplay = (function () { pickRay = Camera.computePickRay(event.x, event.y); // translate mode left/right based on view toward entity - var newIntersection = rayPlaneIntersection(pickRay, - SelectionManager.worldPosition, - Quat.getFront(lastCameraOrientation)); + var newIntersection = rayPlaneIntersection(pickRay, SelectionManager.worldPosition, upDownPickNormal); - var vector = Vec3.subtract(newIntersection, lastPlaneIntersection); + var vector = Vec3.subtract(newIntersection, lastXYPick); vector = grid.snapToGrid(vector); // we only care about the Y axis From f25d509363e0daf52fe83c4901dce70e9455ffef Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 2 Dec 2014 17:50:34 -0800 Subject: [PATCH 174/502] Remove unused lastPlaneIntersection --- examples/libraries/entitySelectionTool.js | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/examples/libraries/entitySelectionTool.js b/examples/libraries/entitySelectionTool.js index 5f2549a85c..077c77f999 100644 --- a/examples/libraries/entitySelectionTool.js +++ b/examples/libraries/entitySelectionTool.js @@ -235,7 +235,6 @@ SelectionDisplay = (function () { var overlayNames = new Array(); var lastCameraPosition = Camera.getPosition(); var lastCameraOrientation = Camera.getOrientation(); - var lastPlaneIntersection; var handleHoverColor = { red: 224, green: 67, blue: 36 }; var handleHoverAlpha = 1.0; @@ -721,13 +720,11 @@ SelectionDisplay = (function () { if (event !== false) { pickRay = Camera.computePickRay(event.x, event.y); - lastPlaneIntersection = rayPlaneIntersection(pickRay, properties.position, Quat.getFront(lastCameraOrientation)); var wantDebug = false; if (wantDebug) { print("select() with EVENT...... "); print(" event.y:" + event.y); - Vec3.print(" lastPlaneIntersection:", lastPlaneIntersection); Vec3.print(" current position:", properties.position); } @@ -1285,7 +1282,6 @@ SelectionDisplay = (function () { if (wantDebug) { print("translateXZ... "); - Vec3.print(" lastPlaneIntersection:", lastPlaneIntersection); Vec3.print(" vector:", vector); Vec3.print(" newPosition:", properties.position); Vec3.print(" newPosition:", newPosition); @@ -1348,7 +1344,6 @@ SelectionDisplay = (function () { if (wantDebug) { print("translateUpDown... "); print(" event.y:" + event.y); - Vec3.print(" lastPlaneIntersection:", lastPlaneIntersection); Vec3.print(" newIntersection:", newIntersection); Vec3.print(" vector:", vector); Vec3.print(" newPosition:", newPosition); @@ -1561,7 +1556,6 @@ SelectionDisplay = (function () { var wantDebug = false; if (wantDebug) { print(stretchMode); - Vec3.print(" lastPlaneIntersection:", lastPlaneIntersection); Vec3.print(" newIntersection:", newIntersection); Vec3.print(" vector:", vector); Vec3.print(" oldPOS:", oldPOS); @@ -2310,11 +2304,8 @@ SelectionDisplay = (function () { if (somethingClicked) { pickRay = Camera.computePickRay(event.x, event.y); - lastPlaneIntersection = rayPlaneIntersection(pickRay, selectionManager.worldPosition, - Quat.getFront(lastCameraOrientation)); if (wantDebug) { - print("mousePressEvent()...... " + overlayNames[result.overlayID]); - Vec3.print(" lastPlaneIntersection:", lastPlaneIntersection); + print("mousePressEvent()...... " + overlayNames[result.overlayID]); } } From 4e78003520504187bcb68b435a08f59b43a9a7ff Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 2 Dec 2014 18:03:00 -0800 Subject: [PATCH 175/502] Fix issue with selection boxes not being hidden --- examples/libraries/entitySelectionTool.js | 24 +++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/examples/libraries/entitySelectionTool.js b/examples/libraries/entitySelectionTool.js index 077c77f999..fff1a54abd 100644 --- a/examples/libraries/entitySelectionTool.js +++ b/examples/libraries/entitySelectionTool.js @@ -1135,14 +1135,22 @@ SelectionDisplay = (function () { })); } - for (var i = 0; i < selectionManager.selections.length; i++) { - var properties = Entities.getEntityProperties(selectionManager.selections[i]); - Overlays.editOverlay(selectionBoxes[i], { - position: properties.position, - rotation: properties.rotation, - dimensions: properties.dimensions, - visible: true, - }); + var i = 0; + // Only show individual selections boxes if there is more than 1 selection + if (selectionManager.selections.length > 1) { + for (; i < selectionManager.selections.length; i++) { + var properties = Entities.getEntityProperties(selectionManager.selections[i]); + Overlays.editOverlay(selectionBoxes[i], { + position: properties.position, + rotation: properties.rotation, + dimensions: properties.dimensions, + visible: true, + }); + } + } + // Hide any remaining selection boxes + for (; i < selectionBoxes.length; i++) { + Overlays.editOverlay(selectionBoxes[i], { visible: false }); } Overlays.editOverlay(grabberEdgeTR, { visible: extendedStretchHandlesVisible, rotation: rotation, position: EdgeTR }); From 86693980489f5088e768b6087e14dbe88d5da661 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 2 Dec 2014 19:14:33 -0800 Subject: [PATCH 176/502] Voxelization bits. --- libraries/metavoxels/src/Spanner.cpp | 579 +++++++++++++++------------ libraries/metavoxels/src/Spanner.h | 6 + 2 files changed, 336 insertions(+), 249 deletions(-) diff --git a/libraries/metavoxels/src/Spanner.cpp b/libraries/metavoxels/src/Spanner.cpp index ee38ef86e4..69bc919e9c 100644 --- a/libraries/metavoxels/src/Spanner.cpp +++ b/libraries/metavoxels/src/Spanner.cpp @@ -1748,6 +1748,279 @@ HeightfieldNode* HeightfieldNode::paintHeight(const glm::vec3& position, const g return newNode; } +HeightfieldNode* HeightfieldNode::clearAndFetchHeight(const glm::vec3& translation, const glm::quat& rotation, + const glm::vec3& scale, const Box& bounds, SharedObjectPointer& heightfield) { + Box nodeBounds = glm::translate(translation) * glm::mat4_cast(rotation) * Box(glm::vec3(), scale); + if (!nodeBounds.intersects(bounds)) { + return this; + } + if (!isLeaf()) { + HeightfieldNode* newNode = this; + for (int i = 0; i < CHILD_COUNT; i++) { + glm::vec3 nextScale = scale * glm::vec3(0.5f, 1.0f, 0.5f); + HeightfieldNode* newChild = _children[i]->clearAndFetchHeight(translation + + rotation * glm::vec3(i & X_MAXIMUM_FLAG ? nextScale.x : 0.0f, 0.0f, + i & Y_MAXIMUM_FLAG ? nextScale.z : 0.0f), rotation, + nextScale, bounds, heightfield); + if (_children[i] != newChild) { + if (newNode == this) { + newNode = new HeightfieldNode(*this); + } + newNode->setChild(i, HeightfieldNodePointer(newChild)); + } + } + if (newNode != this) { + newNode->mergeChildren(); + } + return newNode; + } + if (!_height) { + return this; + } + int heightWidth = _height->getWidth(); + int heightHeight = _height->getContents().size() / heightWidth; + int innerHeightWidth = heightWidth - HeightfieldHeight::HEIGHT_EXTENSION; + int innerHeightHeight = heightHeight - HeightfieldHeight::HEIGHT_EXTENSION; + float heightIncrementX = scale.x / innerHeightWidth; + float heightIncrementZ = scale.z / innerHeightHeight; + + int colorWidth = heightWidth; + int colorHeight = heightHeight; + if (_color) { + colorWidth = _color->getWidth(); + colorHeight = _color->getContents().size() / (colorWidth * DataBlock::COLOR_BYTES); + } + int innerColorWidth = colorWidth - HeightfieldData::SHARED_EDGE; + int innerColorHeight = colorHeight - HeightfieldData::SHARED_EDGE; + float colorIncrementX = scale.x / innerColorWidth; + float colorIncrementZ = scale.z / innerColorHeight; + + int materialWidth = colorWidth; + int materialHeight = colorHeight; + if (_material) { + materialWidth = _material->getWidth(); + materialHeight = _material->getContents().size() / materialWidth; + } + int innerMaterialWidth = materialWidth - HeightfieldData::SHARED_EDGE; + int innerMaterialHeight = materialHeight - HeightfieldData::SHARED_EDGE; + float materialIncrementX = scale.x / innerMaterialWidth; + float materialIncrementZ = scale.z / innerMaterialHeight; + + float largestIncrementX = qMax(heightIncrementX, qMax(colorIncrementX, materialIncrementX)); + float largestIncrementZ = qMax(heightIncrementZ, qMax(colorIncrementZ, materialIncrementZ)); + + glm::vec3 minimum(glm::floor(bounds.minimum.x / largestIncrementX) * largestIncrementX, nodeBounds.minimum.y, + glm::floor(bounds.minimum.z / largestIncrementZ) * largestIncrementZ); + glm::vec3 maximum(glm::ceil(bounds.maximum.x / largestIncrementX) * largestIncrementX, nodeBounds.maximum.y, + glm::ceil(bounds.maximum.z / largestIncrementZ) * largestIncrementZ); + Box largestBounds(minimum, maximum); + + // enlarge the area to fetch + minimum.x -= largestIncrementX; + maximum.x += largestIncrementX; + minimum.z -= largestIncrementZ; + maximum.z += largestIncrementX; + + glm::mat4 baseTransform = glm::mat4_cast(glm::inverse(rotation)) * glm::translate(-translation); + glm::vec3 inverseScale(innerHeightWidth / scale.x, 1.0f, innerHeightHeight / scale.z); + glm::mat4 transform = glm::scale(inverseScale) * baseTransform; + Box transformedBounds = transform * largestBounds; + + // make sure there are values to clear + int startX = glm::clamp((int)glm::ceil(transformedBounds.minimum.x) + HeightfieldHeight::HEIGHT_BORDER, + 0, heightWidth - 1); + int startZ = glm::clamp((int)glm::ceil(transformedBounds.minimum.z) + HeightfieldHeight::HEIGHT_BORDER, + 0, heightHeight - 1); + int endX = glm::clamp((int)glm::floor(transformedBounds.maximum.x) + HeightfieldHeight::HEIGHT_BORDER, 0, heightWidth - 1); + int endZ = glm::clamp((int)glm::floor(transformedBounds.maximum.z) + HeightfieldHeight::HEIGHT_BORDER, + 0, heightHeight - 1); + const quint16* src = _height->getContents().constData() + startZ * heightWidth + startX; + for (int z = startZ; z <= endZ; z++, src += heightWidth) { + const quint16* lineSrc = src; + for (int x = startX; x <= endX; x++) { + if (*lineSrc++ != 0) { + goto clearableBreak; + } + } + } + return this; + clearableBreak: + + int spannerHeightWidth = (int)((maximum.x - minimum.x) / heightIncrementX) + HeightfieldHeight::HEIGHT_EXTENSION; + int spannerHeightHeight = (int)((maximum.z - minimum.z) / heightIncrementZ) + HeightfieldHeight::HEIGHT_EXTENSION; + int spannerColorWidth = (int)((maximum.x - minimum.x) / colorIncrementX) + HeightfieldData::SHARED_EDGE; + int spannerColorHeight = (int)((maximum.z - minimum.z) / colorIncrementZ) + HeightfieldData::SHARED_EDGE; + int spannerMaterialWidth = (int)((maximum.x - minimum.x) / materialIncrementX) + HeightfieldData::SHARED_EDGE; + int spannerMaterialHeight = (int)((maximum.z - minimum.z) / materialIncrementZ) + HeightfieldData::SHARED_EDGE; + + // create heightfield if necessary + Heightfield* spanner = static_cast(heightfield.data()); + if (!spanner) { + heightfield = spanner = new Heightfield(); + spanner->setTranslation(minimum); + spanner->setScale(maximum.x - minimum.x); + spanner->setAspectY((maximum.y - minimum.y) / spanner->getScale()); + spanner->setAspectZ((maximum.z - minimum.z) / spanner->getScale()); + spanner->setHeight(HeightfieldHeightPointer(new HeightfieldHeight(spannerHeightWidth, + QVector(spannerHeightWidth * spannerHeightHeight)))); + spanner->setColor(HeightfieldColorPointer(new HeightfieldColor(spannerColorWidth, + QByteArray(spannerColorWidth * spannerColorHeight * DataBlock::COLOR_BYTES, 0xFF)))); + spanner->setMaterial(HeightfieldMaterialPointer(new HeightfieldMaterial(spannerMaterialWidth, + QByteArray(spannerMaterialWidth * spannerMaterialHeight, 0), QVector()))); + } + + // fetch the height + glm::vec3 spannerInverseScale((spannerHeightWidth - HeightfieldHeight::HEIGHT_EXTENSION) / spanner->getScale(), 1.0f, + (spannerHeightHeight - HeightfieldHeight::HEIGHT_EXTENSION) / (spanner->getScale() * spanner->getAspectZ())); + glm::mat4 spannerBaseTransform = glm::translate(-spanner->getTranslation()); + glm::mat4 spannerTransform = glm::scale(spannerInverseScale) * spannerBaseTransform; + Box spannerTransformedBounds = spannerTransform * nodeBounds; + int spannerStartX = glm::clamp((int)glm::floor(spannerTransformedBounds.minimum.x) + HeightfieldHeight::HEIGHT_BORDER, + 0, spannerHeightWidth - 1); + int spannerStartZ = glm::clamp((int)glm::floor(spannerTransformedBounds.minimum.z) + HeightfieldHeight::HEIGHT_BORDER, + 0, spannerHeightHeight - 1); + int spannerEndX = glm::clamp((int)glm::ceil(spannerTransformedBounds.maximum.x) + HeightfieldHeight::HEIGHT_BORDER, + 0, spannerHeightWidth - 1); + int spannerEndZ = glm::clamp((int)glm::ceil(spannerTransformedBounds.maximum.z) + HeightfieldHeight::HEIGHT_BORDER, + 0, spannerHeightHeight - 1); + quint16* dest = spanner->getHeight()->getContents().data() + spannerStartZ * spannerHeightWidth + spannerStartX; + glm::vec3 step = 1.0f / spannerInverseScale; + glm::vec3 initialPosition = glm::inverse(rotation) * (glm::vec3(spannerStartX - HeightfieldHeight::HEIGHT_BORDER, 0, + spannerStartZ - HeightfieldHeight::HEIGHT_BORDER) * step + spanner->getTranslation() - translation) / scale; + glm::vec3 position = initialPosition; + step = glm::inverse(rotation) * step / scale; + float heightScale = numeric_limits::max(); + for (int z = spannerStartZ; z <= spannerEndZ; z++, dest += spannerHeightWidth, position.z += step.z) { + quint16* lineDest = dest; + position.x = initialPosition.x; + for (int x = spannerStartX; x <= spannerEndX; x++, lineDest++, position.x += step.x) { + float height = getHeight(position) * heightScale; + if (height > *lineDest) { + *lineDest = height; + } + } + } + + // and the color + if (_color) { + spannerInverseScale = glm::vec3((spannerColorWidth - HeightfieldData::SHARED_EDGE) / spanner->getScale(), 1.0f, + (spannerColorHeight - HeightfieldData::SHARED_EDGE) / (spanner->getScale() * spanner->getAspectZ())); + spannerTransform = glm::scale(spannerInverseScale) * spannerBaseTransform; + spannerTransformedBounds = spannerTransform * nodeBounds; + spannerStartX = glm::clamp((int)glm::floor(spannerTransformedBounds.minimum.x), 0, spannerColorWidth - 1); + spannerStartZ = glm::clamp((int)glm::floor(spannerTransformedBounds.minimum.z), 0, spannerColorHeight - 1); + spannerEndX = glm::clamp((int)glm::ceil(spannerTransformedBounds.maximum.x), 0, spannerColorWidth - 1); + spannerEndZ = glm::clamp((int)glm::ceil(spannerTransformedBounds.maximum.z), 0, spannerColorHeight - 1); + + char* dest = spanner->getColor()->getContents().data() + + (spannerStartZ * spannerColorWidth + spannerStartX) * DataBlock::COLOR_BYTES; + step = 1.0f / spannerInverseScale; + initialPosition = glm::inverse(rotation) * (glm::vec3(spannerStartX, 0, spannerStartZ) * step + + spanner->getTranslation() - translation) / scale; + position = initialPosition; + step = glm::inverse(rotation) * step / scale; + for (int z = spannerStartZ; z <= spannerEndZ; z++, dest += spannerColorWidth * DataBlock::COLOR_BYTES, + position.z += step.z) { + char* lineDest = dest; + position.x = initialPosition.x; + for (int x = spannerStartX; x <= spannerEndX; x++, lineDest += DataBlock::COLOR_BYTES, position.x += step.x) { + QRgb color = getColorAt(position); + if (color != 0) { + lineDest[0] = qRed(color); + lineDest[1] = qGreen(color); + lineDest[2] = qBlue(color); + } + } + } + } + + // and the material + if (_material) { + spannerInverseScale = glm::vec3((spannerMaterialWidth - HeightfieldData::SHARED_EDGE) / spanner->getScale(), 1.0f, + (spannerMaterialHeight - HeightfieldData::SHARED_EDGE) / (spanner->getScale() * spanner->getAspectZ())); + spannerTransform = glm::scale(spannerInverseScale) * spannerBaseTransform; + spannerTransformedBounds = spannerTransform * nodeBounds; + spannerStartX = glm::clamp((int)glm::floor(spannerTransformedBounds.minimum.x), 0, spannerMaterialWidth - 1); + spannerStartZ = glm::clamp((int)glm::floor(spannerTransformedBounds.minimum.z), 0, spannerMaterialHeight - 1); + spannerEndX = glm::clamp((int)glm::ceil(spannerTransformedBounds.maximum.x), 0, spannerMaterialWidth - 1); + spannerEndZ = glm::clamp((int)glm::ceil(spannerTransformedBounds.maximum.z), 0, spannerMaterialHeight - 1); + + char* dest = spanner->getMaterial()->getContents().data() + spannerStartZ * spannerMaterialWidth + spannerStartX; + step = 1.0f / spannerInverseScale; + initialPosition = glm::inverse(rotation) * (glm::vec3(spannerStartX, 0, spannerStartZ) * step + + spanner->getTranslation() - translation) / scale; + position = initialPosition; + step = glm::inverse(rotation) * step / scale; + QHash materialMap; + for (int z = spannerStartZ; z <= spannerEndZ; z++, dest += spannerMaterialWidth, position.z += step.z) { + char* lineDest = dest; + position.x = initialPosition.x; + for (int x = spannerStartX; x <= spannerEndX; x++, lineDest++, position.x += step.x) { + int material = getMaterialAt(position); + if (material != -1) { + if (material != 0) { + int& mapping = materialMap[material]; + if (mapping == 0) { + material = mapping = getMaterialIndex(_material->getMaterials().at(material - 1), + spanner->getMaterial()->getMaterials(), spanner->getMaterial()->getContents()); + } + } + *lineDest = material; + } + } + } + } + + // clear the height + QVector newHeightContents = _height->getContents(); + dest = newHeightContents.data() + startZ * heightWidth + startX; + for (int z = startZ; z <= endZ; z++, dest += heightWidth) { + memset(dest, 0, (endX - startX + 1) * sizeof(quint16)); + } + + HeightfieldNode* newNode = new HeightfieldNode(); + newNode->setHeight(HeightfieldHeightPointer(new HeightfieldHeight(heightWidth, newHeightContents))); + + // and the color + if (_color) { + inverseScale = glm::vec3(innerColorWidth / scale.x, 1.0f, innerColorHeight / scale.z); + transform = glm::scale(inverseScale) * baseTransform; + transformedBounds = transform * largestBounds; + startX = glm::clamp((int)glm::ceil(transformedBounds.minimum.x), 0, colorWidth - 1); + startZ = glm::clamp((int)glm::ceil(transformedBounds.minimum.z), 0, colorHeight - 1); + endX = glm::clamp((int)glm::floor(transformedBounds.maximum.x), 0, colorWidth - 1); + endZ = glm::clamp((int)glm::floor(transformedBounds.maximum.z), 0, colorHeight - 1); + QByteArray newColorContents = _color->getContents(); + char* dest = newColorContents.data() + (startZ * colorWidth + startX) * DataBlock::COLOR_BYTES; + for (int z = startZ; z <= endZ; z++, dest += colorWidth * DataBlock::COLOR_BYTES) { + memset(dest, 0, (endX - startX + 1) * DataBlock::COLOR_BYTES); + } + newNode->setColor(HeightfieldColorPointer(new HeightfieldColor(colorWidth, newColorContents))); + } + + // and the material + if (_material) { + inverseScale = glm::vec3(innerMaterialWidth / scale.x, 1.0f, innerMaterialHeight / scale.z); + transform = glm::scale(inverseScale) * baseTransform; + transformedBounds = transform * largestBounds; + startX = glm::clamp((int)glm::ceil(transformedBounds.minimum.x), 0, materialWidth - 1); + startZ = glm::clamp((int)glm::ceil(transformedBounds.minimum.z), 0, materialHeight - 1); + endX = glm::clamp((int)glm::floor(transformedBounds.maximum.x), 0, materialWidth - 1); + endZ = glm::clamp((int)glm::floor(transformedBounds.maximum.z), 0, materialHeight - 1); + QByteArray newMaterialContents = _material->getContents(); + QVector newMaterials = _material->getMaterials(); + char* dest = newMaterialContents.data() + startZ * materialWidth + startX; + for (int z = startZ; z <= endZ; z++, dest += materialWidth) { + memset(dest, 0, endX - startX + 1); + } + clearUnusedMaterials(newMaterials, newMaterialContents); + newNode->setMaterial(HeightfieldMaterialPointer(new HeightfieldMaterial( + materialWidth, newMaterialContents, newMaterials))); + } + + return newNode; +} + void HeightfieldNode::read(HeightfieldStreamState& state) { clearChildren(); @@ -2152,6 +2425,59 @@ void HeightfieldNode::mergeChildren(bool height, bool colorMaterial) { } } +QRgb HeightfieldNode::getColorAt(const glm::vec3& location) const { + if (location.x < 0.0f || location.z < 0.0f || location.x > 1.0f || location.z > 1.0f) { + return 0; + } + int width = _color->getWidth(); + const QByteArray& contents = _color->getContents(); + const uchar* src = (const uchar*)contents.constData(); + int height = contents.size() / (width * DataBlock::COLOR_BYTES); + int innerWidth = width - HeightfieldData::SHARED_EDGE; + int innerHeight = height - HeightfieldData::SHARED_EDGE; + + glm::vec3 relative = location * glm::vec3((float)innerWidth, 1.0f, (float)innerHeight); + glm::vec3 floors = glm::floor(relative); + glm::vec3 ceils = glm::ceil(relative); + glm::vec3 fracts = glm::fract(relative); + int floorX = (int)floors.x; + int floorZ = (int)floors.z; + int ceilX = (int)ceils.x; + int ceilZ = (int)ceils.z; + const uchar* upperLeft = src + (floorZ * width + floorX) * DataBlock::COLOR_BYTES; + const uchar* lowerRight = src + (ceilZ * width + ceilX) * DataBlock::COLOR_BYTES; + glm::vec3 interpolatedColor = glm::mix(glm::vec3(upperLeft[0], upperLeft[1], upperLeft[2]), + glm::vec3(lowerRight[0], lowerRight[1], lowerRight[2]), fracts.z); + + // the final vertex (and thus which triangle we check) depends on which half we're on + if (fracts.x >= fracts.z) { + const uchar* upperRight = src + (floorZ * width + ceilX) * DataBlock::COLOR_BYTES; + interpolatedColor = glm::mix(interpolatedColor, glm::mix(glm::vec3(upperRight[0], upperRight[1], upperRight[2]), + glm::vec3(lowerRight[0], lowerRight[1], lowerRight[2]), fracts.z), (fracts.x - fracts.z) / (1.0f - fracts.z)); + + } else { + const uchar* lowerLeft = src + (ceilZ * width + floorX) * DataBlock::COLOR_BYTES; + interpolatedColor = glm::mix(glm::mix(glm::vec3(upperLeft[0], upperLeft[1], upperLeft[2]), + glm::vec3(lowerLeft[0], lowerLeft[1], lowerLeft[2]), fracts.z), interpolatedColor, fracts.x / fracts.z); + } + return qRgb(interpolatedColor.r, interpolatedColor.g, interpolatedColor.b); +} + +int HeightfieldNode::getMaterialAt(const glm::vec3& location) const { + if (location.x < 0.0f || location.z < 0.0f || location.x > 1.0f || location.z > 1.0f) { + return -1; + } + int width = _material->getWidth(); + const QByteArray& contents = _material->getContents(); + const uchar* src = (const uchar*)contents.constData(); + int height = contents.size() / width; + int innerWidth = width - HeightfieldData::SHARED_EDGE; + int innerHeight = height - HeightfieldData::SHARED_EDGE; + + glm::vec3 relative = location * glm::vec3((float)innerWidth, 1.0f, (float)innerHeight); + return src[(int)glm::round(relative.z) * width + (int)glm::round(relative.x)]; +} + Heightfield::Heightfield() : _aspectY(1.0f), _aspectZ(1.0f) { @@ -2278,258 +2604,13 @@ Spanner* Heightfield::paintHeight(const glm::vec3& position, float radius, float } Spanner* Heightfield::clearAndFetchHeight(const Box& bounds, SharedObjectPointer& heightfield) { - if (!_height) { + HeightfieldNode* newRoot = _root->clearAndFetchHeight(getTranslation(), getRotation(), + glm::vec3(getScale(), getScale() * _aspectY, getScale() * _aspectZ), bounds, heightfield); + if (_root == newRoot) { return this; } - int heightWidth = _height->getWidth(); - int heightHeight = _height->getContents().size() / heightWidth; - int innerHeightWidth = heightWidth - HeightfieldHeight::HEIGHT_EXTENSION; - int innerHeightHeight = heightHeight - HeightfieldHeight::HEIGHT_EXTENSION; - float heightIncrementX = getScale() / innerHeightWidth; - float heightIncrementZ = (getScale() * _aspectZ) / innerHeightHeight; - - int colorWidth = heightWidth; - int colorHeight = heightHeight; - if (_color) { - colorWidth = _color->getWidth(); - colorHeight = _color->getContents().size() / (colorWidth * DataBlock::COLOR_BYTES); - } - int innerColorWidth = colorWidth - HeightfieldData::SHARED_EDGE; - int innerColorHeight = colorHeight - HeightfieldData::SHARED_EDGE; - float colorIncrementX = getScale() / innerColorWidth; - float colorIncrementZ = (getScale() * _aspectZ) / innerColorHeight; - - int materialWidth = colorWidth; - int materialHeight = colorHeight; - if (_material) { - materialWidth = _material->getWidth(); - materialHeight = _material->getContents().size() / materialWidth; - } - int innerMaterialWidth = materialWidth - HeightfieldData::SHARED_EDGE; - int innerMaterialHeight = materialHeight - HeightfieldData::SHARED_EDGE; - float materialIncrementX = getScale() / innerMaterialWidth; - float materialIncrementZ = (getScale() * _aspectZ) / innerMaterialHeight; - - float largestIncrementX = qMax(heightIncrementX, qMax(colorIncrementX, materialIncrementX)); - float largestIncrementZ = qMax(heightIncrementZ, qMax(colorIncrementZ, materialIncrementZ)); - - glm::vec3 minimum(glm::floor(bounds.minimum.x / largestIncrementX) * largestIncrementX, getBounds().minimum.y, - glm::floor(bounds.minimum.z / largestIncrementZ) * largestIncrementZ); - glm::vec3 maximum(glm::ceil(bounds.maximum.x / largestIncrementX) * largestIncrementX, getBounds().maximum.y, - glm::ceil(bounds.maximum.z / largestIncrementZ) * largestIncrementZ); - Box largestBounds(minimum, maximum); - - // enlarge the area to fetch - minimum.x -= largestIncrementX; - maximum.x += largestIncrementX; - minimum.z -= largestIncrementZ; - maximum.z += largestIncrementX; - - glm::mat4 baseTransform = glm::mat4_cast(glm::inverse(getRotation())) * glm::translate(-getTranslation()); - glm::vec3 inverseScale(innerHeightWidth / getScale(), 1.0f, innerHeightHeight / (getScale() * _aspectZ)); - glm::mat4 transform = glm::scale(inverseScale) * baseTransform; - Box transformedBounds = transform * largestBounds; - - // make sure there are values to clear - int startX = glm::clamp((int)glm::ceil(transformedBounds.minimum.x) + HeightfieldHeight::HEIGHT_BORDER, - 0, heightWidth - 1); - int startZ = glm::clamp((int)glm::ceil(transformedBounds.minimum.z) + HeightfieldHeight::HEIGHT_BORDER, - 0, heightHeight - 1); - int endX = glm::clamp((int)glm::floor(transformedBounds.maximum.x) + HeightfieldHeight::HEIGHT_BORDER, 0, heightWidth - 1); - int endZ = glm::clamp((int)glm::floor(transformedBounds.maximum.z) + HeightfieldHeight::HEIGHT_BORDER, - 0, heightHeight - 1); - const quint16* src = _height->getContents().constData() + startZ * heightWidth + startX; - for (int z = startZ; z <= endZ; z++, src += heightWidth) { - const quint16* lineSrc = src; - for (int x = startX; x <= endX; x++) { - if (*lineSrc++ != 0) { - goto clearableBreak; - } - } - } - return this; - clearableBreak: - - int spannerHeightWidth = (int)((maximum.x - minimum.x) / heightIncrementX) + HeightfieldHeight::HEIGHT_EXTENSION; - int spannerHeightHeight = (int)((maximum.z - minimum.z) / heightIncrementZ) + HeightfieldHeight::HEIGHT_EXTENSION; - int spannerColorWidth = (int)((maximum.x - minimum.x) / colorIncrementX) + HeightfieldData::SHARED_EDGE; - int spannerColorHeight = (int)((maximum.z - minimum.z) / colorIncrementZ) + HeightfieldData::SHARED_EDGE; - int spannerMaterialWidth = (int)((maximum.x - minimum.x) / materialIncrementX) + HeightfieldData::SHARED_EDGE; - int spannerMaterialHeight = (int)((maximum.z - minimum.z) / materialIncrementZ) + HeightfieldData::SHARED_EDGE; - - // create heightfield if necessary - Heightfield* spanner = static_cast(heightfield.data()); - if (!spanner) { - heightfield = spanner = new Heightfield(); - spanner->setTranslation(minimum); - spanner->setScale(maximum.x - minimum.x); - spanner->setAspectY((maximum.y - minimum.y) / spanner->getScale()); - spanner->setAspectZ((maximum.z - minimum.z) / spanner->getScale()); - spanner->setHeight(HeightfieldHeightPointer(new HeightfieldHeight(spannerHeightWidth, - QVector(spannerHeightWidth * spannerHeightHeight)))); - spanner->setColor(HeightfieldColorPointer(new HeightfieldColor(spannerColorWidth, - QByteArray(spannerColorWidth * spannerColorHeight * DataBlock::COLOR_BYTES, 0xFF)))); - spanner->setMaterial(HeightfieldMaterialPointer(new HeightfieldMaterial(spannerMaterialWidth, - QByteArray(spannerMaterialWidth * spannerMaterialHeight, 0), QVector()))); - } - - // fetch the height - glm::vec3 spannerInverseScale((spannerHeightWidth - HeightfieldHeight::HEIGHT_EXTENSION) / spanner->getScale(), 1.0f, - (spannerHeightHeight - HeightfieldHeight::HEIGHT_EXTENSION) / (spanner->getScale() * spanner->getAspectZ())); - glm::mat4 spannerBaseTransform = glm::translate(-spanner->getTranslation()); - glm::mat4 spannerTransform = glm::scale(spannerInverseScale) * spannerBaseTransform; - Box spannerTransformedBounds = spannerTransform * getBounds(); - int spannerStartX = glm::clamp((int)glm::floor(spannerTransformedBounds.minimum.x) + HeightfieldHeight::HEIGHT_BORDER, - 0, spannerHeightWidth - 1); - int spannerStartZ = glm::clamp((int)glm::floor(spannerTransformedBounds.minimum.z) + HeightfieldHeight::HEIGHT_BORDER, - 0, spannerHeightHeight - 1); - int spannerEndX = glm::clamp((int)glm::ceil(spannerTransformedBounds.maximum.x) + HeightfieldHeight::HEIGHT_BORDER, - 0, spannerHeightWidth - 1); - int spannerEndZ = glm::clamp((int)glm::ceil(spannerTransformedBounds.maximum.z) + HeightfieldHeight::HEIGHT_BORDER, - 0, spannerHeightHeight - 1); - quint16* dest = spanner->getHeight()->getContents().data() + spannerStartZ * spannerHeightWidth + spannerStartX; - glm::vec3 step = 1.0f / spannerInverseScale; - glm::vec3 initialPosition = glm::vec3(spannerStartX - HeightfieldHeight::HEIGHT_BORDER, 0, - spannerStartZ - HeightfieldHeight::HEIGHT_BORDER) * step + spanner->getTranslation(); - glm::vec3 position = initialPosition; - float heightScale = numeric_limits::max() / (getScale() * _aspectY); - for (int z = spannerStartZ; z <= spannerEndZ; z++, dest += spannerHeightWidth, position.z += step.z) { - quint16* lineDest = dest; - position.x = initialPosition.x; - for (int x = spannerStartX; x <= spannerEndX; x++, lineDest++, position.x += step.x) { - float height = (getHeight(position) - getTranslation().y) * heightScale; - if (height > *lineDest) { - *lineDest = height; - } - } - } - - // and the color - if (_color) { - spannerInverseScale = glm::vec3((spannerColorWidth - HeightfieldData::SHARED_EDGE) / spanner->getScale(), 1.0f, - (spannerColorHeight - HeightfieldData::SHARED_EDGE) / (spanner->getScale() * spanner->getAspectZ())); - spannerTransform = glm::scale(spannerInverseScale) * spannerBaseTransform; - spannerTransformedBounds = spannerTransform * getBounds(); - spannerStartX = glm::clamp((int)glm::floor(spannerTransformedBounds.minimum.x), 0, spannerColorWidth - 1); - spannerStartZ = glm::clamp((int)glm::floor(spannerTransformedBounds.minimum.z), 0, spannerColorHeight - 1); - spannerEndX = glm::clamp((int)glm::ceil(spannerTransformedBounds.maximum.x), 0, spannerColorWidth - 1); - spannerEndZ = glm::clamp((int)glm::ceil(spannerTransformedBounds.maximum.z), 0, spannerColorHeight - 1); - - char* dest = spanner->getColor()->getContents().data() + - (spannerStartZ * spannerColorWidth + spannerStartX) * DataBlock::COLOR_BYTES; - step = 1.0f / spannerInverseScale; - initialPosition = glm::vec3(spannerStartX, 0, spannerStartZ) * step + spanner->getTranslation(); - position = initialPosition; - for (int z = spannerStartZ; z <= spannerEndZ; z++, dest += spannerColorWidth * DataBlock::COLOR_BYTES, - position.z += step.z) { - char* lineDest = dest; - position.x = initialPosition.x; - for (int x = spannerStartX; x <= spannerEndX; x++, lineDest += DataBlock::COLOR_BYTES, position.x += step.x) { - QRgb color = getColorAt(position); - if (color != 0) { - lineDest[0] = qRed(color); - lineDest[1] = qGreen(color); - lineDest[2] = qBlue(color); - } - } - } - } - - // and the material - if (_material) { - spannerInverseScale = glm::vec3((spannerMaterialWidth - HeightfieldData::SHARED_EDGE) / spanner->getScale(), 1.0f, - (spannerMaterialHeight - HeightfieldData::SHARED_EDGE) / (spanner->getScale() * spanner->getAspectZ())); - spannerTransform = glm::scale(spannerInverseScale) * spannerBaseTransform; - spannerTransformedBounds = spannerTransform * getBounds(); - spannerStartX = glm::clamp((int)glm::floor(spannerTransformedBounds.minimum.x), 0, spannerMaterialWidth - 1); - spannerStartZ = glm::clamp((int)glm::floor(spannerTransformedBounds.minimum.z), 0, spannerMaterialHeight - 1); - spannerEndX = glm::clamp((int)glm::ceil(spannerTransformedBounds.maximum.x), 0, spannerMaterialWidth - 1); - spannerEndZ = glm::clamp((int)glm::ceil(spannerTransformedBounds.maximum.z), 0, spannerMaterialHeight - 1); - - char* dest = spanner->getMaterial()->getContents().data() + spannerStartZ * spannerMaterialWidth + spannerStartX; - step = 1.0f / spannerInverseScale; - initialPosition = glm::vec3(spannerStartX, 0, spannerStartZ) * step + spanner->getTranslation(); - position = initialPosition; - QHash materialMap; - for (int z = spannerStartZ; z <= spannerEndZ; z++, dest += spannerMaterialWidth, position.z += step.z) { - char* lineDest = dest; - position.x = initialPosition.x; - for (int x = spannerStartX; x <= spannerEndX; x++, lineDest++, position.x += step.x) { - int material = getMaterialAt(position); - if (material != -1) { - if (material != 0) { - int& mapping = materialMap[material]; - if (mapping == 0) { - material = mapping = getMaterialIndex(_material->getMaterials().at(material - 1), - spanner->getMaterial()->getMaterials(), spanner->getMaterial()->getContents()); - } - } - *lineDest = material; - } - } - } - } - - // clear the height - QVector newHeightContents = _height->getContents(); - dest = newHeightContents.data() + startZ * heightWidth + startX; - for (int z = startZ; z <= endZ; z++, dest += heightWidth) { - memset(dest, 0, (endX - startX + 1) * sizeof(quint16)); - } - - // if we've cleared all the inner height, we can remove the spanner entirely - src = newHeightContents.constData() + heightWidth + HeightfieldHeight::HEIGHT_BORDER; - for (int z = 0; z < innerHeightHeight; z++, src += heightWidth) { - const quint16* lineSrc = src; - for (int x = 0; x < innerHeightWidth; x++) { - if (*lineSrc++ != 0) { - goto nonEmptyBreak; - } - } - } - return NULL; - nonEmptyBreak: - Heightfield* newHeightfield = static_cast(clone(true)); - newHeightfield->setHeight(HeightfieldHeightPointer(new HeightfieldHeight(heightWidth, newHeightContents))); - - // and the color - if (_color) { - inverseScale = glm::vec3(innerColorWidth / getScale(), 1.0f, innerColorHeight / (getScale() * _aspectZ)); - transform = glm::scale(inverseScale) * baseTransform; - transformedBounds = transform * largestBounds; - startX = glm::clamp((int)glm::ceil(transformedBounds.minimum.x), 0, colorWidth - 1); - startZ = glm::clamp((int)glm::ceil(transformedBounds.minimum.z), 0, colorHeight - 1); - endX = glm::clamp((int)glm::floor(transformedBounds.maximum.x), 0, colorWidth - 1); - endZ = glm::clamp((int)glm::floor(transformedBounds.maximum.z), 0, colorHeight - 1); - QByteArray newColorContents = _color->getContents(); - char* dest = newColorContents.data() + (startZ * colorWidth + startX) * DataBlock::COLOR_BYTES; - for (int z = startZ; z <= endZ; z++, dest += colorWidth * DataBlock::COLOR_BYTES) { - memset(dest, 0, (endX - startX + 1) * DataBlock::COLOR_BYTES); - } - newHeightfield->setColor(HeightfieldColorPointer(new HeightfieldColor(colorWidth, newColorContents))); - } - - // and the material - if (_material) { - inverseScale = glm::vec3(innerMaterialWidth / getScale(), 1.0f, innerMaterialHeight / (getScale() * _aspectZ)); - transform = glm::scale(inverseScale) * baseTransform; - transformedBounds = transform * largestBounds; - startX = glm::clamp((int)glm::ceil(transformedBounds.minimum.x), 0, materialWidth - 1); - startZ = glm::clamp((int)glm::ceil(transformedBounds.minimum.z), 0, materialHeight - 1); - endX = glm::clamp((int)glm::floor(transformedBounds.maximum.x), 0, materialWidth - 1); - endZ = glm::clamp((int)glm::floor(transformedBounds.maximum.z), 0, materialHeight - 1); - QByteArray newMaterialContents = _material->getContents(); - QVector newMaterials = _material->getMaterials(); - char* dest = newMaterialContents.data() + startZ * materialWidth + startX; - for (int z = startZ; z <= endZ; z++, dest += materialWidth) { - memset(dest, 0, endX - startX + 1); - } - clearUnusedMaterials(newMaterials, newMaterialContents); - newHeightfield->setMaterial(HeightfieldMaterialPointer(new HeightfieldMaterial( - materialWidth, newMaterialContents, newMaterials))); - } - + newHeightfield->setRoot(HeightfieldNodePointer(newRoot)); return newHeightfield; } diff --git a/libraries/metavoxels/src/Spanner.h b/libraries/metavoxels/src/Spanner.h index f3e7c6bfdb..6742324f85 100644 --- a/libraries/metavoxels/src/Spanner.h +++ b/libraries/metavoxels/src/Spanner.h @@ -524,6 +524,9 @@ public: HeightfieldNode* paintHeight(const glm::vec3& position, const glm::vec3& radius, float height, float normalizeScale, float normalizeOffset); + HeightfieldNode* clearAndFetchHeight(const glm::vec3& translation, const glm::quat& rotation, const glm::vec3& scale, + const Box& bounds, SharedObjectPointer& heightfield); + void read(HeightfieldStreamState& state); void write(HeightfieldStreamState& state) const; @@ -543,6 +546,9 @@ private: void clearChildren(); void mergeChildren(bool height = true, bool colorMaterial = true); + QRgb getColorAt(const glm::vec3& location) const; + int getMaterialAt(const glm::vec3& location) const; + HeightfieldHeightPointer _height; HeightfieldColorPointer _color; HeightfieldMaterialPointer _material; From 1a1b1ca3f3f2cea68117a9aeb89fe6af4d26aadd Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 2 Dec 2014 19:49:27 -0800 Subject: [PATCH 177/502] Fix for voxelizing heightfields. --- interface/src/ui/MetavoxelEditor.cpp | 1 + libraries/metavoxels/src/Spanner.cpp | 14 +++++++++++++- libraries/metavoxels/src/Spanner.h | 5 +++++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/interface/src/ui/MetavoxelEditor.cpp b/interface/src/ui/MetavoxelEditor.cpp index 6989c47d67..26b403e423 100644 --- a/interface/src/ui/MetavoxelEditor.cpp +++ b/interface/src/ui/MetavoxelEditor.cpp @@ -1014,6 +1014,7 @@ QColor VoxelMaterialSpannerTool::getColor() { } void VoxelMaterialSpannerTool::applyEdit(const AttributePointer& attribute, const SharedObjectPointer& spanner) { + static_cast(spanner.data())->setWillBeVoxelized(true); MetavoxelEditMessage message = { QVariant::fromValue(VoxelMaterialSpannerEdit(spanner, _materialControl->getMaterial(), _materialControl->getColor())) }; Application::getInstance()->getMetavoxels()->applyEdit(message, true); diff --git a/libraries/metavoxels/src/Spanner.cpp b/libraries/metavoxels/src/Spanner.cpp index 69bc919e9c..f249ae2912 100644 --- a/libraries/metavoxels/src/Spanner.cpp +++ b/libraries/metavoxels/src/Spanner.cpp @@ -61,7 +61,8 @@ Spanner::Spanner() : _renderer(NULL), _placementGranularity(DEFAULT_PLACEMENT_GRANULARITY), _voxelizationGranularity(DEFAULT_VOXELIZATION_GRANULARITY), - _merged(false) { + _merged(false), + _willBeVoxelized(false) { } void Spanner::setBounds(const Box& bounds) { @@ -2542,6 +2543,9 @@ MetavoxelLOD Heightfield::transformLOD(const MetavoxelLOD& lod) const { SharedObject* Heightfield::clone(bool withID, SharedObject* target) const { Heightfield* newHeightfield = static_cast(Spanner::clone(withID, target)); + newHeightfield->setHeight(_height); + newHeightfield->setColor(_color); + newHeightfield->setMaterial(_material); newHeightfield->setRoot(_root); return newHeightfield; } @@ -2920,6 +2924,10 @@ bool Heightfield::intersects(const glm::vec3& start, const glm::vec3& end, float } void Heightfield::writeExtra(Bitstream& out) const { + if (getWillBeVoxelized()) { + out << _height << _color << _material; + return; + } MetavoxelLOD lod; if (out.getContext()) { lod = transformLOD(static_cast(out.getContext())->lod); @@ -2930,6 +2938,10 @@ void Heightfield::writeExtra(Bitstream& out) const { } void Heightfield::readExtra(Bitstream& in) { + if (getWillBeVoxelized()) { + in >> _height >> _color >> _material; + return; + } MetavoxelLOD lod; if (in.getContext()) { lod = transformLOD(static_cast(in.getContext())->lod); diff --git a/libraries/metavoxels/src/Spanner.h b/libraries/metavoxels/src/Spanner.h index 6742324f85..c4fe185a58 100644 --- a/libraries/metavoxels/src/Spanner.h +++ b/libraries/metavoxels/src/Spanner.h @@ -29,6 +29,7 @@ class Spanner : public SharedObject { Q_PROPERTY(Box bounds MEMBER _bounds WRITE setBounds NOTIFY boundsChanged DESIGNABLE false) Q_PROPERTY(float placementGranularity MEMBER _placementGranularity DESIGNABLE false) Q_PROPERTY(float voxelizationGranularity MEMBER _voxelizationGranularity DESIGNABLE false) + Q_PROPERTY(bool willBeVoxelized MEMBER _willBeVoxelized DESIGNABLE false) public: @@ -49,6 +50,9 @@ public: void setMerged(bool merged) { _merged = merged; } bool isMerged() const { return _merged; } + void setWillBeVoxelized(bool willBeVoxelized) { _willBeVoxelized = willBeVoxelized; } + bool getWillBeVoxelized() const { return _willBeVoxelized; } + /// Checks whether we've visited this object on the current traversal. If we have, returns false. /// If we haven't, sets the last visit identifier and returns true. bool testAndSetVisited(int visit); @@ -118,6 +122,7 @@ private: float _placementGranularity; float _voxelizationGranularity; bool _merged; + bool _willBeVoxelized; QHash _lastVisits; ///< last visit identifiers for each thread QMutex _lastVisitsMutex; From 94d0612804ead5d3c41f42d4afd4870a6b80e3d6 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 2 Dec 2014 20:17:18 -0800 Subject: [PATCH 178/502] Fix for Hermite display. --- interface/src/MetavoxelSystem.cpp | 55 ++++++++++++++++++++----------- interface/src/MetavoxelSystem.h | 11 +++++++ 2 files changed, 46 insertions(+), 20 deletions(-) diff --git a/interface/src/MetavoxelSystem.cpp b/interface/src/MetavoxelSystem.cpp index a4d8c6ff37..6a227614cb 100644 --- a/interface/src/MetavoxelSystem.cpp +++ b/interface/src/MetavoxelSystem.cpp @@ -461,6 +461,34 @@ void MetavoxelSystem::render() { _voxelBaseBatches.clear(); } + if (!_hermiteBatches.isEmpty() && Menu::getInstance()->isOptionChecked(MenuOption::DisplayHermiteData)) { + Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, true); + + glEnableClientState(GL_VERTEX_ARRAY); + + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + glNormal3f(0.0f, 1.0f, 0.0f); + + Application::getInstance()->getDeferredLightingEffect()->bindSimpleProgram(); + + foreach (const HermiteBatch& batch, _hermiteBatches) { + batch.vertexBuffer->bind(); + + glVertexPointer(3, GL_FLOAT, 0, 0); + + glDrawArrays(GL_LINES, 0, batch.vertexCount); + + batch.vertexBuffer->release(); + } + + Application::getInstance()->getDeferredLightingEffect()->releaseSimpleProgram(); + + glDisableClientState(GL_VERTEX_ARRAY); + + Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, false); + } + _hermiteBatches.clear(); + // give external parties a chance to join in emit rendering(); } @@ -1229,31 +1257,18 @@ void VoxelBuffer::render(bool cursor) { } } - if (_hermiteCount > 0 && Menu::getInstance()->isOptionChecked(MenuOption::DisplayHermiteData)) { + if (_hermiteCount > 0) { if (!_hermiteBuffer.isCreated()) { _hermiteBuffer.create(); _hermiteBuffer.bind(); - _hermiteBuffer.allocate(_hermite.constData(), _hermite.size() * sizeof(glm::vec3)); + _hermiteBuffer.allocate(_hermite.constData(), _hermite.size() * sizeof(glm::vec3)); + _hermiteBuffer.release(); _hermite.clear(); - - } else { - _hermiteBuffer.bind(); } - - glVertexPointer(3, GL_FLOAT, 0, 0); - - Application::getInstance()->getDeferredLightingEffect()->getSimpleProgram().bind(); - - glColor4f(1.0f, 1.0f, 1.0f, 1.0f); - glNormal3f(0.0f, 1.0f, 0.0f); - - glLineWidth(1.0f); - - glDrawArrays(GL_LINES, 0, _hermiteCount); - - Application::getInstance()->getDeferredLightingEffect()->getSimpleProgram().release(); - - _hermiteBuffer.release(); + HermiteBatch hermiteBatch; + hermiteBatch.vertexBuffer = &_hermiteBuffer; + hermiteBatch.vertexCount = _hermiteCount; + Application::getInstance()->getMetavoxels()->addHermiteBatch(hermiteBatch); } } diff --git a/interface/src/MetavoxelSystem.h b/interface/src/MetavoxelSystem.h index 059ef27de4..99c55549c7 100644 --- a/interface/src/MetavoxelSystem.h +++ b/interface/src/MetavoxelSystem.h @@ -26,6 +26,7 @@ class HeightfieldBaseLayerBatch; class HeightfieldRendererNode; class HeightfieldSplatBatch; +class HermiteBatch; class Model; class VoxelBatch; class VoxelSplatBatch; @@ -89,6 +90,8 @@ public: void addVoxelBaseBatch(const VoxelBatch& batch) { _voxelBaseBatches.append(batch); } void addVoxelSplatBatch(const VoxelSplatBatch& batch) { _voxelSplatBatches.append(batch); } + void addHermiteBatch(const HermiteBatch& batch) { _hermiteBatches.append(batch); } + signals: void rendering(); @@ -121,6 +124,7 @@ private: QVector _heightfieldSplatBatches; QVector _voxelBaseBatches; QVector _voxelSplatBatches; + QVector _hermiteBatches; ProgramObject _baseHeightfieldProgram; int _baseHeightScaleLocation; @@ -212,6 +216,13 @@ public: int materialIndex; }; +/// A batch containing Hermite data for debugging. +class HermiteBatch { +public: + QOpenGLBuffer* vertexBuffer; + int vertexCount; +}; + /// Generic abstract base class for objects that handle a signal. class SignalHandler : public QObject { Q_OBJECT From 3ca20a7eeef7f44bbb8698e84970fc72f7519a89 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Tue, 2 Dec 2014 23:08:34 -0800 Subject: [PATCH 179/502] Add jump/warp turning when in HMD --- interface/src/avatar/MyAvatar.cpp | 24 ++++++++++++++++++++++-- interface/src/avatar/MyAvatar.h | 1 + 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 3301cf0347..a07a3d9b28 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -68,6 +68,7 @@ const int SCRIPTED_MOTOR_WORLD_FRAME = 2; MyAvatar::MyAvatar() : Avatar(), _mousePressed(false), + _turningKeyPressTime(0.0f), _bodyPitchDelta(0.0f), _bodyRollDelta(0.0f), _gravity(0.0f, 0.0f, 0.0f), @@ -1169,8 +1170,27 @@ bool MyAvatar::shouldRenderHead(const glm::vec3& cameraPosition, RenderMode rend void MyAvatar::updateOrientation(float deltaTime) { // Gather rotation information from keyboard - _bodyYawDelta -= _driveKeys[ROT_RIGHT] * YAW_SPEED * deltaTime; - _bodyYawDelta += _driveKeys[ROT_LEFT] * YAW_SPEED * deltaTime; + const float TIME_BETWEEN_HMD_TURNS = 0.5f; + const float HMD_TURN_DEGREES = 22.5f; + if (!OculusManager::isConnected()) { + // Smoothly rotate body with arrow keys if not in HMD + _bodyYawDelta -= _driveKeys[ROT_RIGHT] * YAW_SPEED * deltaTime; + _bodyYawDelta += _driveKeys[ROT_LEFT] * YAW_SPEED * deltaTime; + } else { + // Jump turns if in HMD + if (_driveKeys[ROT_RIGHT] || _driveKeys[ROT_LEFT]) { + if (_turningKeyPressTime == 0.0f) { + setOrientation(getOrientation() * + glm::quat(glm::radians(glm::vec3(0.f, _driveKeys[ROT_LEFT] ? HMD_TURN_DEGREES : -HMD_TURN_DEGREES, 0.0f)))); + } + _turningKeyPressTime += deltaTime; + if (_turningKeyPressTime > TIME_BETWEEN_HMD_TURNS) { + _turningKeyPressTime = 0.0f; + } + } else { + _turningKeyPressTime = 0.0f; + } + } getHead()->setBasePitch(getHead()->getBasePitch() + (_driveKeys[ROT_UP] - _driveKeys[ROT_DOWN]) * PITCH_SPEED * deltaTime); // update body yaw by body yaw delta diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index dd1178c7b5..6926ac9505 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -204,6 +204,7 @@ protected: private: bool _mousePressed; + float _turningKeyPressTime; float _bodyPitchDelta; // degrees float _bodyRollDelta; // degrees glm::vec3 _gravity; From 57e2f71bb7fd7701e299acbb1038c1da1942aa19 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Tue, 2 Dec 2014 23:24:47 -0800 Subject: [PATCH 180/502] remove unused body delta pitch, roll --- interface/src/avatar/MyAvatar.cpp | 14 +++----------- interface/src/avatar/MyAvatar.h | 2 -- 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index a07a3d9b28..a4fc696bc9 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -69,8 +69,6 @@ MyAvatar::MyAvatar() : Avatar(), _mousePressed(false), _turningKeyPressTime(0.0f), - _bodyPitchDelta(0.0f), - _bodyRollDelta(0.0f), _gravity(0.0f, 0.0f, 0.0f), _distanceToNearestAvatar(std::numeric_limits::max()), _shouldJump(false), @@ -1193,22 +1191,18 @@ void MyAvatar::updateOrientation(float deltaTime) { } getHead()->setBasePitch(getHead()->getBasePitch() + (_driveKeys[ROT_UP] - _driveKeys[ROT_DOWN]) * PITCH_SPEED * deltaTime); - // update body yaw by body yaw delta - glm::quat orientation = getOrientation() * glm::quat(glm::radians( - glm::vec3(_bodyPitchDelta, _bodyYawDelta, _bodyRollDelta) * deltaTime)); + // update body orientation by movement inputs + setOrientation(getOrientation() * + glm::quat(glm::radians(glm::vec3(0.0f, _bodyYawDelta, 0.0f) * deltaTime))); // decay body rotation momentum const float BODY_SPIN_FRICTION = 7.5f; float bodySpinMomentum = 1.0f - BODY_SPIN_FRICTION * deltaTime; if (bodySpinMomentum < 0.0f) { bodySpinMomentum = 0.0f; } - _bodyPitchDelta *= bodySpinMomentum; _bodyYawDelta *= bodySpinMomentum; - _bodyRollDelta *= bodySpinMomentum; float MINIMUM_ROTATION_RATE = 2.0f; if (fabs(_bodyYawDelta) < MINIMUM_ROTATION_RATE) { _bodyYawDelta = 0.0f; } - if (fabs(_bodyRollDelta) < MINIMUM_ROTATION_RATE) { _bodyRollDelta = 0.0f; } - if (fabs(_bodyPitchDelta) < MINIMUM_ROTATION_RATE) { _bodyPitchDelta = 0.0f; } if (OculusManager::isConnected()) { // these angles will be in radians @@ -1237,8 +1231,6 @@ void MyAvatar::updateOrientation(float deltaTime) { } - // update the euler angles - setOrientation(orientation); } glm::vec3 MyAvatar::applyKeyboardMotor(float deltaTime, const glm::vec3& localVelocity, bool hasFloor) { diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 6926ac9505..37b93e2f04 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -205,8 +205,6 @@ protected: private: bool _mousePressed; float _turningKeyPressTime; - float _bodyPitchDelta; // degrees - float _bodyRollDelta; // degrees glm::vec3 _gravity; float _distanceToNearestAvatar; // How close is the nearest avatar? From d63ace9f6108a8fcef1a752d65189ab59b2c7dfd Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Tue, 2 Dec 2014 23:53:46 -0800 Subject: [PATCH 181/502] fix angular velocity from oculus, tweak hair --- interface/src/Hair.cpp | 4 ++-- interface/src/avatar/MyAvatar.cpp | 7 +++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/interface/src/Hair.cpp b/interface/src/Hair.cpp index e14fc519d3..cb664f39ed 100644 --- a/interface/src/Hair.cpp +++ b/interface/src/Hair.cpp @@ -18,8 +18,8 @@ const float HAIR_DAMPING = 0.99f; const float CONSTRAINT_RELAXATION = 10.0f; const float HAIR_ACCELERATION_COUPLING = 0.045f; -const float HAIR_ANGULAR_VELOCITY_COUPLING = 0.020f; -const float HAIR_ANGULAR_ACCELERATION_COUPLING = 0.003f; +const float HAIR_ANGULAR_VELOCITY_COUPLING = 0.001f; +const float HAIR_ANGULAR_ACCELERATION_COUPLING = 0.001f; const float HAIR_MAX_LINEAR_ACCELERATION = 4.0f; const float HAIR_STIFFNESS = 0.00f; const glm::vec3 HAIR_COLOR1(0.98f, 0.76f, 0.075f); diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index a4fc696bc9..9f3309ece2 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1215,8 +1215,11 @@ void MyAvatar::updateOrientation(float deltaTime) { // Record the angular velocity Head* head = getHead(); - glm::vec3 angularVelocity(yaw - head->getBaseYaw(), pitch - head->getBasePitch(), roll - head->getBaseRoll()); - head->setAngularVelocity(angularVelocity); + if (deltaTime > 0.0f) { + glm::vec3 angularVelocity(pitch - head->getBasePitch(), yaw - head->getBaseYaw(), roll - head->getBaseRoll()); + angularVelocity *= 1.0f / deltaTime; + head->setAngularVelocity(angularVelocity); + } //Invert yaw and roll when in mirror mode if (Application::getInstance()->getCamera()->getMode() == CAMERA_MODE_MIRROR) { From 49a087018f0a8d48c14f5634f91fc8f62407ca17 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 3 Dec 2014 08:22:50 -0800 Subject: [PATCH 182/502] fix for delayed heartbeats, late socket lookup --- domain-server/src/DomainServer.cpp | 31 ++++++++++++++-------- domain-server/src/DomainServer.h | 2 ++ libraries/networking/src/HifiSockAddr.cpp | 2 ++ libraries/networking/src/HifiSockAddr.h | 3 +++ libraries/networking/src/LimitedNodeList.h | 1 + 5 files changed, 28 insertions(+), 11 deletions(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 80777ce529..75db0b8022 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -37,6 +37,8 @@ int const DomainServer::EXIT_CODE_REBOOT = 234923; +const QString ICE_SERVER_DEFAULT_HOSTNAME = "ice.highfidelity.io"; + DomainServer::DomainServer(int argc, char* argv[]) : QCoreApplication(argc, argv), _shutdownEventListener(this), @@ -52,7 +54,8 @@ DomainServer::DomainServer(int argc, char* argv[]) : _webAuthenticationStateSet(), _cookieSessionHash(), _automaticNetworkingSetting(), - _settingsManager() + _settingsManager(), + _iceServerSocket(ICE_SERVER_DEFAULT_HOSTNAME, ICE_SERVER_DEFAULT_PORT) { LogUtils::init(); @@ -346,6 +349,9 @@ void DomainServer::setupAutomaticNetworking() { QTimer* dynamicIPTimer = new QTimer(this); connect(dynamicIPTimer, &QTimer::timeout, this, &DomainServer::requestCurrentPublicSocketViaSTUN); + _automaticNetworkingSetting = + _settingsManager.valueOrDefaultValueForKeyPath(METAVERSE_AUTOMATIC_NETWORKING_KEY_PATH).toString(); + if (_automaticNetworkingSetting == FULL_AUTOMATIC_NETWORKING_VALUE) { dynamicIPTimer->start(STUN_REFLEXIVE_KEEPALIVE_INTERVAL_MSECS); @@ -354,9 +360,17 @@ void DomainServer::setupAutomaticNetworking() { connect(iceHeartbeatTimer, &QTimer::timeout, this, &DomainServer::performICEUpdates); iceHeartbeatTimer->start(ICE_HEARBEAT_INTERVAL_MSECS); - // call our sendHeartbeaToIceServer immediately anytime a local or public socket changes + // call our sendHeartbeatToIceServer immediately anytime a local or public socket changes connect(nodeList, &LimitedNodeList::localSockAddrChanged, this, &DomainServer::sendHeartbeatToIceServer); connect(nodeList, &LimitedNodeList::publicSockAddrChanged, this, &DomainServer::sendHeartbeatToIceServer); + + // attempt to update our public socket now, this will send a heartbeat once we get public socket + requestCurrentPublicSocketViaSTUN(); + + // in case the STUN lookup is still happening we should re-request a public socket once we get that address + connect(&nodeList->getSTUNSockAddr(), &HifiSockAddr::lookupCompleted, + this, &DomainServer::requestCurrentPublicSocketViaSTUN); + } if (!didSetupAccountManagerWithAccessToken()) { @@ -366,9 +380,6 @@ void DomainServer::setupAutomaticNetworking() { return; } - _automaticNetworkingSetting = - _settingsManager.valueOrDefaultValueForKeyPath(METAVERSE_AUTOMATIC_NETWORKING_KEY_PATH).toString(); - if (_automaticNetworkingSetting == IP_ONLY_AUTOMATIC_NETWORKING_VALUE || _automaticNetworkingSetting == FULL_AUTOMATIC_NETWORKING_VALUE) { @@ -383,14 +394,13 @@ void DomainServer::setupAutomaticNetworking() { // send public socket changes to the data server so nodes can find us at our new IP connect(nodeList, &LimitedNodeList::publicSockAddrChanged, this, &DomainServer::performIPAddressUpdate); + + // attempt to update our sockets now + requestCurrentPublicSocketViaSTUN(); } else { // send our heartbeat to data server so it knows what our network settings are sendHeartbeatToDataServer(); } - - // attempt to update our sockets now - requestCurrentPublicSocketViaSTUN(); - } else { qDebug() << "Cannot enable domain-server automatic networking without a domain ID." << "Please add an ID to your config file or via the web interface."; @@ -1167,8 +1177,7 @@ void DomainServer::performICEUpdates() { } void DomainServer::sendHeartbeatToIceServer() { - static HifiSockAddr ICE_SERVER_SOCK_ADDR = HifiSockAddr("ice.highfidelity.io", ICE_SERVER_DEFAULT_PORT); - LimitedNodeList::getInstance()->sendHeartbeatToIceServer(ICE_SERVER_SOCK_ADDR); + LimitedNodeList::getInstance()->sendHeartbeatToIceServer(_iceServerSocket); } void DomainServer::sendICEPingPackets() { diff --git a/domain-server/src/DomainServer.h b/domain-server/src/DomainServer.h index de485da5e7..2a92c63923 100644 --- a/domain-server/src/DomainServer.h +++ b/domain-server/src/DomainServer.h @@ -154,6 +154,8 @@ private: QString _automaticNetworkingSetting; DomainServerSettingsManager _settingsManager; + + HifiSockAddr _iceServerSocket; }; diff --git a/libraries/networking/src/HifiSockAddr.cpp b/libraries/networking/src/HifiSockAddr.cpp index f2419f5124..425dffefe9 100644 --- a/libraries/networking/src/HifiSockAddr.cpp +++ b/libraries/networking/src/HifiSockAddr.cpp @@ -86,6 +86,7 @@ bool HifiSockAddr::operator==(const HifiSockAddr& rhsSockAddr) const { void HifiSockAddr::handleLookupResult(const QHostInfo& hostInfo) { if (hostInfo.error() != QHostInfo::NoError) { qDebug() << "Lookup failed for" << hostInfo.lookupId() << ":" << hostInfo.errorString(); + emit lookupFailed(); } foreach(const QHostAddress& address, hostInfo.addresses()) { @@ -94,6 +95,7 @@ void HifiSockAddr::handleLookupResult(const QHostInfo& hostInfo) { _address = address; qDebug() << "QHostInfo lookup result for" << hostInfo.hostName() << "with lookup ID" << hostInfo.lookupId() << "is" << address.toString(); + emit lookupCompleted(); break; } } diff --git a/libraries/networking/src/HifiSockAddr.h b/libraries/networking/src/HifiSockAddr.h index 064f8032ca..4d3944012e 100644 --- a/libraries/networking/src/HifiSockAddr.h +++ b/libraries/networking/src/HifiSockAddr.h @@ -54,6 +54,9 @@ public: friend QDataStream& operator>>(QDataStream& dataStream, HifiSockAddr& sockAddr); private slots: void handleLookupResult(const QHostInfo& hostInfo); +signals: + void lookupCompleted(); + void lookupFailed(); private: QHostAddress _address; quint16 _port; diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index ad8c1688bb..2fc8751e3f 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -105,6 +105,7 @@ public: const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket); const HifiSockAddr& getLocalSockAddr() const { return _localSockAddr; } + const HifiSockAddr& getSTUNSockAddr() const { return _stunSockAddr; } void processNodeData(const HifiSockAddr& senderSockAddr, const QByteArray& packet); void processKillNode(const QByteArray& datagram); From 98f56aaa0c81955a6db55243a3b3d09b3e4a9aef Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 3 Dec 2014 09:55:55 -0800 Subject: [PATCH 183/502] fix URL/filename discrepancy for local scripts --- interface/src/Application.cpp | 10 ++++----- interface/src/Application.h | 4 ++-- libraries/script-engine/src/ScriptEngine.cpp | 23 ++++++++++---------- libraries/script-engine/src/ScriptEngine.h | 4 ++-- 4 files changed, 20 insertions(+), 21 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 9561115478..9c3eb48993 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4042,20 +4042,20 @@ ScriptEngine* Application::loadScript(const QString& scriptFilename, bool isUser return scriptEngine; } -void Application::handleScriptEngineLoaded(const QUrl& scriptURL) { +void Application::handleScriptEngineLoaded(const QString& scriptFilename) { ScriptEngine* scriptEngine = qobject_cast(sender()); - _scriptEnginesHash.insertMulti(scriptURL.toString(), scriptEngine); + _scriptEnginesHash.insertMulti(scriptFilename, scriptEngine); _runningScriptsWidget->setRunningScripts(getRunningScripts()); - UserActivityLogger::getInstance().loadedScript(scriptURL.toString()); + UserActivityLogger::getInstance().loadedScript(scriptFilename); // register our application services and set it off on its own thread registerScriptEngineWithApplicationServices(scriptEngine); } -void Application::handleScriptLoadError(const QUrl& scriptURL) { +void Application::handleScriptLoadError(const QString& scriptFilename) { qDebug() << "Application::loadScript(), script failed to load..."; - QMessageBox::warning(getWindow(), "Error Loading Script", scriptURL.toString() + " failed to load."); + QMessageBox::warning(getWindow(), "Error Loading Script", scriptFilename + " failed to load."); } void Application::scriptFinished(const QString& scriptName) { diff --git a/interface/src/Application.h b/interface/src/Application.h index caaebea876..92ef00e8a5 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -394,8 +394,8 @@ private slots: void idle(); void aboutToQuit(); - void handleScriptEngineLoaded(const QUrl& scriptURL); - void handleScriptLoadError(const QUrl& scriptURL); + void handleScriptEngineLoaded(const QString& scriptFilename); + void handleScriptLoadError(const QString& scriptFilename); void connectedToDomain(const QString& hostname); diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 6cef69d23f..70c536e116 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -156,31 +156,30 @@ void ScriptEngine::loadURL(const QUrl& scriptURL) { if (_isRunning) { return; } - - QString scriptURLString = scriptURL.toString(); - _fileNameString = scriptURLString; + + _fileNameString = scriptURL.toString(); QUrl url(scriptURL); // if the scheme length is one or lower, maybe they typed in a file, let's try const int WINDOWS_DRIVE_LETTER_SIZE = 1; if (url.scheme().size() <= WINDOWS_DRIVE_LETTER_SIZE) { - url = QUrl::fromLocalFile(scriptURLString); + url = QUrl::fromLocalFile(_fileNameString); } // ok, let's see if it's valid... and if so, load it if (url.isValid()) { if (url.scheme() == "file") { - QString fileName = url.toLocalFile(); - QFile scriptFile(fileName); + _fileNameString = url.toLocalFile(); + QFile scriptFile(_fileNameString); if (scriptFile.open(QFile::ReadOnly | QFile::Text)) { - qDebug() << "Loading file:" << fileName; + qDebug() << "ScriptEngine loading file:" << _fileNameString; QTextStream in(&scriptFile); _scriptContents = in.readAll(); - emit scriptLoaded(url); + emit scriptLoaded(_fileNameString); } else { - qDebug() << "ERROR Loading file:" << fileName; - emit errorLoadingScript(url); + qDebug() << "ERROR Loading file:" << _fileNameString; + emit errorLoadingScript(_fileNameString); } } else { QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); @@ -195,10 +194,10 @@ void ScriptEngine::handleScriptDownload() { if (reply->error() == QNetworkReply::NoError && reply->attribute(QNetworkRequest::HttpStatusCodeAttribute) == 200) { _scriptContents = reply->readAll(); - emit scriptLoaded(reply->url()); + emit scriptLoaded(_fileNameString); } else { qDebug() << "ERROR Loading file:" << reply->url().toString(); - emit errorLoadingScript(reply->url()); + emit errorLoadingScript(_fileNameString); } } diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index 4b6b3e48ab..fd28e98cab 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -107,8 +107,8 @@ public slots: void nodeKilled(SharedNodePointer node); signals: - void scriptLoaded(const QUrl& scriptURL); - void errorLoadingScript(const QUrl& scriptURL); + void scriptLoaded(const QString& scriptFilename); + void errorLoadingScript(const QString& scriptFilename); void update(float deltaTime); void scriptEnding(); void finished(const QString& fileNameString); From f0b0c5fe0b546912581468f2c277df7aefed9fe6 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 3 Dec 2014 11:08:41 -0800 Subject: [PATCH 184/502] change warp button to button face right --- examples/gamepad.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/gamepad.js b/examples/gamepad.js index b4c2758edd..a2f1034e26 100644 --- a/examples/gamepad.js +++ b/examples/gamepad.js @@ -20,7 +20,7 @@ var BUTTON_TURN_AROUND = Joysticks.BUTTON_RIGHT_STICK; var BUTTON_FLY_UP = Joysticks.BUTTON_RIGHT_SHOULDER; var BUTTON_FLY_DOWN = Joysticks.BUTTON_LEFT_SHOULDER; -var BUTTON_WARP = Joysticks.BUTTON_FACE_BOTTOM; +var BUTTON_WARP = Joysticks.BUTTON_FACE_RIGHT; var BUTTON_WARP_FORWARD = Joysticks.BUTTON_DPAD_UP; var BUTTON_WARP_BACKWARD = Joysticks.BUTTON_DPAD_DOWN; From 1e93137e6b5195a2219c12c68bffb5503debad7e Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 3 Dec 2014 12:24:58 -0800 Subject: [PATCH 185/502] Fix for overflow when computing metavoxel stats. --- interface/src/ui/Stats.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index f041fb8569..d0a25f4f4a 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -461,10 +461,10 @@ void Stats::display( if (_metavoxelSendTotal > 0 || _metavoxelReceiveTotal > 0) { stringstream reliableStats; if (_metavoxelSendTotal > 0) { - reliableStats << "Upload: " << (_metavoxelSendProgress * 100 / _metavoxelSendTotal) << "% "; + reliableStats << "Upload: " << (_metavoxelSendProgress * 100LL / _metavoxelSendTotal) << "% "; } if (_metavoxelReceiveTotal > 0) { - reliableStats << "Download: " << (_metavoxelReceiveProgress * 100 / _metavoxelReceiveTotal) << "%"; + reliableStats << "Download: " << (_metavoxelReceiveProgress * 100LL / _metavoxelReceiveTotal) << "%"; } verticalOffset += STATS_PELS_PER_LINE; drawText(horizontalOffset, verticalOffset, scale, rotation, font, reliableStats.str().c_str(), color); From d975e3f0ce8b3e6afd4c9cd58aae99dc826df414 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 3 Dec 2014 12:38:10 -0800 Subject: [PATCH 186/502] Fixed signed/unsigned warnign. --- interface/src/Audio.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index 167c44111e..2214bb54cf 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -1438,7 +1438,7 @@ void Audio::renderToolBox(int x, int y, bool boxed) { static const float PULSE_MAX = 1.0f; static const float PULSE_FREQUENCY = 1.0f; // in Hz qint64 now = usecTimestampNow(); - if (now - _iconPulseTimeReference > USECS_PER_SECOND) { + if (now - _iconPulseTimeReference > (qint64)USECS_PER_SECOND) { // Prevents t from getting too big, which would diminish glm::cos precision _iconPulseTimeReference = now - ((now - _iconPulseTimeReference) % USECS_PER_SECOND); } From 88048e8599a83beea1f77a02c4eed5ddf0c605c9 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 3 Dec 2014 12:47:32 -0800 Subject: [PATCH 187/502] Make sure the position of the heightfield/voxel brush is valid before acting. --- interface/src/ui/MetavoxelEditor.cpp | 14 ++++++++++---- interface/src/ui/MetavoxelEditor.h | 2 ++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/interface/src/ui/MetavoxelEditor.cpp b/interface/src/ui/MetavoxelEditor.cpp index b6b43c4baf..349a73b9c7 100644 --- a/interface/src/ui/MetavoxelEditor.cpp +++ b/interface/src/ui/MetavoxelEditor.cpp @@ -884,7 +884,8 @@ void ImportHeightfieldTool::updateSpanner() { } HeightfieldBrushTool::HeightfieldBrushTool(MetavoxelEditor* editor, const QString& name) : - MetavoxelTool(editor, name, false) { + MetavoxelTool(editor, name, false), + _positionValid(false) { QWidget* widget = new QWidget(); widget->setLayout(_form = new QFormLayout()); @@ -911,8 +912,10 @@ void HeightfieldBrushTool::render() { float distance; if (!Application::getInstance()->getMetavoxels()->findFirstRayHeightfieldIntersection(origin, direction, distance)) { + _positionValid = false; return; } + _positionValid = true; Application::getInstance()->getMetavoxels()->renderHeightfieldCursor( _position = origin + distance * direction, _radius->value()); } @@ -924,7 +927,7 @@ bool HeightfieldBrushTool::eventFilter(QObject* watched, QEvent* event) { _radius->setValue(_radius->value() * glm::pow(2.0f, angle * ANGLE_SCALE)); return true; - } else if (event->type() == QEvent::MouseButtonPress) { + } else if (event->type() == QEvent::MouseButtonPress && _positionValid) { MetavoxelEditMessage message = { createEdit(static_cast(event)->button() == Qt::RightButton) }; Application::getInstance()->getMetavoxels()->applyEdit(message, true); return true; @@ -1103,7 +1106,8 @@ void VoxelMaterialSpannerTool::applyEdit(const AttributePointer& attribute, cons } VoxelBrushTool::VoxelBrushTool(MetavoxelEditor* editor, const QString& name) : - MetavoxelTool(editor, name, false, true) { + MetavoxelTool(editor, name, false, true), + _positionValid(false) { QWidget* widget = new QWidget(); widget->setLayout(_form = new QFormLayout()); @@ -1132,8 +1136,10 @@ void VoxelBrushTool::render() { if (!(Application::getInstance()->getMetavoxels()->findFirstRayHeightfieldIntersection( origin, direction, heightfieldDistance) | Application::getInstance()->getMetavoxels()->findFirstRayVoxelIntersection(origin, direction, voxelDistance))) { + _positionValid = false; return; } + _positionValid = true; Application::getInstance()->getMetavoxels()->renderVoxelCursor( _position = origin + qMin(heightfieldDistance, voxelDistance) * direction, _radius->value()); } @@ -1145,7 +1151,7 @@ bool VoxelBrushTool::eventFilter(QObject* watched, QEvent* event) { _radius->setValue(_radius->value() * glm::pow(2.0f, angle * ANGLE_SCALE)); return true; - } else if (event->type() == QEvent::MouseButtonPress) { + } else if (event->type() == QEvent::MouseButtonPress && _positionValid) { MetavoxelEditMessage message = { createEdit(static_cast(event)->button() == Qt::RightButton) }; Application::getInstance()->getMetavoxels()->applyEdit(message, true); return true; diff --git a/interface/src/ui/MetavoxelEditor.h b/interface/src/ui/MetavoxelEditor.h index cccb41ecfc..15e731e2ee 100644 --- a/interface/src/ui/MetavoxelEditor.h +++ b/interface/src/ui/MetavoxelEditor.h @@ -326,6 +326,7 @@ protected: QDoubleSpinBox* _radius; glm::vec3 _position; + bool _positionValid; }; /// Allows raising or lowering parts of the heightfield. @@ -456,6 +457,7 @@ protected: QDoubleSpinBox* _radius; glm::vec3 _position; + bool _positionValid; }; /// Allows texturing parts of the voxel field. From fecb225a0653e5f7fabc4cd3b19035a749757621 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 3 Dec 2014 12:55:58 -0800 Subject: [PATCH 188/502] Prevent erroneous resource download percentages; Qt reports the total bytes as -1 before the actual size is available. --- libraries/networking/src/ResourceCache.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/networking/src/ResourceCache.h b/libraries/networking/src/ResourceCache.h index 496839fdcd..e1b6327652 100644 --- a/libraries/networking/src/ResourceCache.h +++ b/libraries/networking/src/ResourceCache.h @@ -109,11 +109,11 @@ public: /// For loading resources, returns the number of bytes received. qint64 getBytesReceived() const { return _bytesReceived; } - /// For loading resources, returns the number of total bytes (or zero if unknown). + /// For loading resources, returns the number of total bytes (<= zero if unknown). qint64 getBytesTotal() const { return _bytesTotal; } /// For loading resources, returns the load progress. - float getProgress() const { return (_bytesTotal == 0) ? 0.0f : (float)_bytesReceived / _bytesTotal; } + float getProgress() const { return (_bytesTotal <= 0) ? 0.0f : (float)_bytesReceived / _bytesTotal; } /// Refreshes the resource. void refresh(); From d08337326ce9117eef95c8451354ab6f427475a5 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 3 Dec 2014 12:59:51 -0800 Subject: [PATCH 189/502] Update selection box color to red --- examples/libraries/entitySelectionTool.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/libraries/entitySelectionTool.js b/examples/libraries/entitySelectionTool.js index fff1a54abd..40b5b78a31 100644 --- a/examples/libraries/entitySelectionTool.js +++ b/examples/libraries/entitySelectionTool.js @@ -338,12 +338,12 @@ SelectionDisplay = (function () { var selectionBox = Overlays.addOverlay("cube", { position: { x:0, y: 0, z: 0}, size: 1, - color: { red: 60, green: 60, blue: 60}, + color: { red: 255, green: 0, blue: 0}, alpha: 1, solid: false, visible: false, - dashed: true, - lineWidth: 2.0, + dashed: false, + lineWidth: 1.0, }); var selectionBoxes = []; From 913007939ba6bd821f0d2f11d22fd78695b0419d Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Wed, 3 Dec 2014 14:12:50 -0800 Subject: [PATCH 190/502] Trying to read the light attribute --- interface/src/renderer/GeometryCache.cpp | 53 +++++++++++++------ libraries/fbx/src/FBXReader.cpp | 66 +++++++++++++++++++++++- 2 files changed, 101 insertions(+), 18 deletions(-) diff --git a/interface/src/renderer/GeometryCache.cpp b/interface/src/renderer/GeometryCache.cpp index e523d7e608..b64b8f1a90 100644 --- a/interface/src/renderer/GeometryCache.cpp +++ b/interface/src/renderer/GeometryCache.cpp @@ -829,26 +829,45 @@ void GeometryReader::run() { return; } try { - std::string urlname = _url.path().toLower().toStdString(); - FBXGeometry fbxgeo; - if (_url.path().toLower().endsWith(".svo")) { - fbxgeo = readSVO(_reply->readAll()); - } else { - bool grabLightmaps = true; - float lightmapLevel = 1.0f; - // HACK: For monday 12/01/2014 we need to kill lighmaps loading in starchamber... - if (_url.path().toLower().endsWith("loungev4_11-18.fbx")) { - grabLightmaps = false; - } else if (_url.path().toLower().endsWith("apt8_reboot.fbx")) { - lightmapLevel = 4.0f; - } else if (_url.path().toLower().endsWith("palaceoforinthilian4.fbx")) { - lightmapLevel = 3.5f; - } - fbxgeo = readFBX(_reply->readAll(), _mapping, grabLightmaps, lightmapLevel); + if (!_reply) { + throw QString("Reply is NULL ?!"); } - QMetaObject::invokeMethod(geometry.data(), "setGeometry", Q_ARG(const FBXGeometry&, fbxgeo)); + QString urlnameQ = _url.path().toLower(); + std::string urlname = _url.path().toLower().toStdString(); + bool urlValid = true; + urlValid &= !urlname.empty(); + urlValid &= !_url.path().isEmpty(); + urlValid &= _url.path().toLower().endsWith(".fbx") + || _url.path().toLower().endsWith(".svo"); + if (urlValid) { + QString urlnameQ = _url.path().toLower(); + std::string urlnameQstd = urlnameQ.toStdString(); + QByteArray fileBinary = _reply->readAll(); + if (fileBinary.isEmpty() || fileBinary.isNull()) { + throw QString("Read File binary is empty?!"); + } + FBXGeometry fbxgeo; + if (_url.path().toLower().endsWith(".svo")) { + fbxgeo = readSVO(fileBinary); + } else if (_url.path().toLower().endsWith(".fbx")) { + bool grabLightmaps = true; + float lightmapLevel = 1.0f; + // HACK: For monday 12/01/2014 we need to kill lighmaps loading in starchamber... + if (_url.path().toLower().endsWith("loungev4_11-18.fbx")) { + grabLightmaps = false; + } else if (_url.path().toLower().endsWith("apt8_reboot.fbx")) { + lightmapLevel = 4.0f; + } else if (_url.path().toLower().endsWith("palaceoforinthilian4.fbx")) { + lightmapLevel = 3.5f; + } + fbxgeo = readFBX(fileBinary, _mapping, grabLightmaps, lightmapLevel); + } + QMetaObject::invokeMethod(geometry.data(), "setGeometry", Q_ARG(const FBXGeometry&, fbxgeo)); + } else { + throw QString("url is invalid"); + } // _url.path().toLower().endsWith(".svo") ? readSVO(_reply->readAll()) : readFBX(_reply->readAll(), _mapping))); } catch (const QString& error) { diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 0c52a4b55b..8eef6ca738 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -32,7 +32,7 @@ // TOOL: Uncomment the following line to enable the filtering of all the unkwnon fields of a node so we can break point easily while loading a model with problems... -//#define DEBUG_FBXREADER +#define DEBUG_FBXREADER using namespace std; @@ -1194,6 +1194,8 @@ int matchTextureUVSetToAttributeChannel(const std::string& texUVSetName, const Q } } + + FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, bool loadLightmaps, float lightmapLevel) { QHash meshes; QHash modelIDsToNames; @@ -1632,9 +1634,39 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, materials.insert(material.id, material); } else if (object.name == "NodeAttribute") { + std::string attributetype; + const FBXNode* prop70Node = 0; foreach (const FBXNode& subobject, object.children) { + if (subobject.name == "TypeFlags") { typeFlags.insert(getID(object.properties), subobject.properties.at(0).toString()); + attributetype = subobject.properties.at(0).toString().toStdString(); + } else if (subobject.name == "Properties70") { + prop70Node = &subobject; + } + } + + if (!attributetype.empty()) { + if (attributetype == "Light") { + if (prop70Node) { + foreach (const FBXNode& property, prop70Node->children) { + int valIndex = 4; + if (property.name == "P") { + std::string propname = property.properties.at(0).toString().toStdString(); + if (propname == "LightType") { + std::string type = property.properties.at(valIndex).toString().toStdString(); + } else if (propname == "Intensity") { + float intensity = property.properties.at(valIndex).value(); + } +#if defined(DEBUG_FBXREADER) + else { + if (propname == "EmissiveFactor") { + } + } +#endif + } + } + } } } } else if (object.name == "Deformer") { @@ -1674,7 +1706,20 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, } } animationCurves.insert(getID(object.properties), curve); + } +#if defined(DEBUG_FBXREADER) + else { + std::string objectname = object.name.data(); + if ( objectname == "Pose" + || objectname == "AnimationStack" + || objectname == "AnimationLayer" + || objectname == "AnimationCurveNode") { + } else { + unknown++; + } + } +#endif } } else if (child.name == "Connections") { foreach (const FBXNode& connection, child.children) { @@ -1726,6 +1771,25 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, } } } +#if defined(DEBUG_FBXREADER) + else { + std::string objectname = child.name.data(); + if ( objectname == "Pose" + || objectname == "CreationTime" + || objectname == "FileId" + || objectname == "Creator" + || objectname == "Documents" + || objectname == "References" + || objectname == "Definitions" + || objectname == "Takes" + || objectname == "AnimationStack" + || objectname == "AnimationLayer" + || objectname == "AnimationCurveNode") { + } else { + unknown++; + } + } +#endif } // assign the blendshapes to their corresponding meshes From df23a84cc27c916a4a594cc3e8b2842739b4ba02 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 3 Dec 2014 14:18:47 -0800 Subject: [PATCH 191/502] Bump up the glyph texture size so that we don't spill over into another texture. --- interface/src/ui/TextRenderer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/ui/TextRenderer.cpp b/interface/src/ui/TextRenderer.cpp index edc14dabf5..fce4c76c0d 100644 --- a/interface/src/ui/TextRenderer.cpp +++ b/interface/src/ui/TextRenderer.cpp @@ -29,7 +29,7 @@ // the width/height of the cached glyph textures -const int IMAGE_SIZE = 256; +const int IMAGE_SIZE = 512; static uint qHash(const TextRenderer::Properties& key, uint seed = 0) { // can be switched to qHash(key.font, seed) when we require Qt 5.3+ From 73004d1beee351a742cd4ccb30b7b8d06356cd09 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 3 Dec 2014 14:40:47 -0800 Subject: [PATCH 192/502] Decoupled reticules from Overlays view --- interface/src/ui/ApplicationOverlay.cpp | 525 +++++++++++------------- interface/src/ui/ApplicationOverlay.h | 12 +- 2 files changed, 237 insertions(+), 300 deletions(-) diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index f5396c72f0..1050eb5a65 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -33,8 +33,16 @@ const float RETICLE_COLOR[] = { 0.0f, 198.0f / 255.0f, 244.0f / 255.0f }; const float CONNECTION_STATUS_BORDER_COLOR[] = { 1.0f, 0.0f, 0.0f }; const float CONNECTION_STATUS_BORDER_LINE_WIDTH = 4.0f; +// Return a point's coordinates on a sphere from it's polar (theta) and azimutal (phi) angles. +glm::vec3 getPoint(float radius, float theta, float phi) { + return glm::vec3(radius * glm::sin(theta) * glm::sin(phi), + radius * glm::cos(theta), + radius * glm::sin(theta) * (-glm::cos(phi))); +} + ApplicationOverlay::ApplicationOverlay() : _textureFov(glm::radians(DEFAULT_OCULUS_UI_ANGULAR_SIZE)), + _textureAspectRatio(1.0f), _alpha(1.0f), _oculusUIRadius(1.0f), _crosshairTexture(0) { @@ -47,18 +55,16 @@ ApplicationOverlay::ApplicationOverlay() : ApplicationOverlay::~ApplicationOverlay() { } - // Renders the overlays either to a texture or to the screen void ApplicationOverlay::renderOverlay(bool renderToTexture) { PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "ApplicationOverlay::displayOverlay()"); - - _textureFov = glm::radians(Menu::getInstance()->getOculusUIAngularSize()); - Application* application = Application::getInstance(); - Overlays& overlays = application->getOverlays(); GLCanvas* glWidget = application->getGLWidget(); MyAvatar* myAvatar = application->getAvatar(); + + _textureFov = glm::radians(Menu::getInstance()->getOculusUIAngularSize()); + _textureAspectRatio = application->getGLWidget()->getDeviceWidth() / application->getGLWidget()->getDeviceHeight(); //Handle fading and deactivation/activation of UI if (Menu::getInstance()->isOptionChecked(MenuOption::UserInterface)) { @@ -79,8 +85,8 @@ void ApplicationOverlay::renderOverlay(bool renderToTexture) { glDisable(GL_LIGHTING); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - if (renderToTexture) { + _overlays.buildFramebufferObject(); _overlays.bind(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } @@ -130,7 +136,7 @@ void ApplicationOverlay::displayOverlayTexture() { glEnable(GL_TEXTURE_2D); glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, getFramebufferObject()->texture()); + _overlays.bindTexture(); glMatrixMode(GL_PROJECTION); glPushMatrix(); @@ -276,7 +282,7 @@ QPoint ApplicationOverlay::getPalmClickLocation(const PalmData *palm) const { //We back the ray up by dir to ensure that it will not start inside the UI. glm::vec3 adjustedPos = tipPos - dir; //Find intersection of crosshair ray. - if (raySphereIntersect(dir, adjustedPos, _oculusuiRadius * myAvatar->getScale(), &t)){ + if (raySphereIntersect(dir, adjustedPos, _oculusUIRadius * myAvatar->getScale(), &t)){ glm::vec3 collisionPos = adjustedPos + dir * t; //Normalize it in case its not a radius of 1 collisionPos = glm::normalize(collisionPos); @@ -324,7 +330,7 @@ bool ApplicationOverlay::calculateRayUICollisionPoint(const glm::vec3& position, glm::vec3 relativeDirection = orientation * direction; float t; - if (raySphereIntersect(relativeDirection, relativePosition, _oculusuiRadius * myAvatar->getScale(), &t)){ + if (raySphereIntersect(relativeDirection, relativePosition, _oculusUIRadius * myAvatar->getScale(), &t)){ result = position + direction * t; return true; } @@ -351,7 +357,7 @@ void ApplicationOverlay::displayOverlayTextureOculus(Camera& whichCamera) { glDisable(GL_LIGHTING); glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, getFramebufferObject()->texture()); + _overlays.bindTexture(); glMatrixMode(GL_MODELVIEW); @@ -362,58 +368,59 @@ void ApplicationOverlay::displayOverlayTextureOculus(Camera& whichCamera) { //Update and draw the magnifiers - glPushMatrix(); const glm::quat& orientation = myAvatar->getOrientation(); const glm::vec3& position = myAvatar->getDefaultEyePosition(); - - glm::mat4 rotation = glm::toMat4(orientation); - - glTranslatef(position.x, position.y, position.z); - glMultMatrixf(&rotation[0][0]); - for (int i = 0; i < NUMBER_OF_MAGNIFIERS; i++) { - - if (_magActive[i]) { - _magSizeMult[i] += MAG_SPEED; - if (_magSizeMult[i] > 1.0f) { - _magSizeMult[i] = 1.0f; + const float scale = myAvatar->getScale() * _oculusUIRadius; + + + glPushMatrix(); { + glTranslatef(position.x, position.y, position.z); + glm::mat4 rotation = glm::toMat4(orientation); + glMultMatrixf(&rotation[0][0]); + glScalef(scale, scale, scale); + for (int i = 0; i < NUMBER_OF_MAGNIFIERS; i++) { + + if (_magActive[i]) { + _magSizeMult[i] += MAG_SPEED; + if (_magSizeMult[i] > 1.0f) { + _magSizeMult[i] = 1.0f; + } + } else { + _magSizeMult[i] -= MAG_SPEED; + if (_magSizeMult[i] < 0.0f) { + _magSizeMult[i] = 0.0f; + } } - } else { - _magSizeMult[i] -= MAG_SPEED; - if (_magSizeMult[i] < 0.0f) { - _magSizeMult[i] = 0.0f; + + if (_magSizeMult[i] > 0.0f) { + //Render magnifier, but dont show border for mouse magnifier + renderMagnifier(_magX[i], _magY[i], _magSizeMult[i], i != MOUSE); } } - - if (_magSizeMult[i] > 0.0f) { - //Render magnifier, but dont show border for mouse magnifier - renderMagnifier(_magX[i], _magY[i], _magSizeMult[i], i != MOUSE); - } - } - glPopMatrix(); - - glDepthMask(GL_FALSE); - glDisable(GL_ALPHA_TEST); - - glColor4f(1.0f, 1.0f, 1.0f, _alpha); - - renderTexturedHemisphere(); - - renderPointersOculus(myAvatar->getDefaultEyePosition()); - - glDepthMask(GL_TRUE); - glBindTexture(GL_TEXTURE_2D, 0); - glDisable(GL_TEXTURE_2D); - - glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE); - glEnable(GL_LIGHTING); - - glColor4f(1.0f, 1.0f, 1.0f, 1.0f); - + + glDepthMask(GL_FALSE); + glDisable(GL_ALPHA_TEST); + + glColor4f(1.0f, 1.0f, 1.0f, _alpha); + + _overlays.buildVBO(_textureFov, _textureAspectRatio, 80, 80); + _overlays.render(); + + renderPointersOculus(myAvatar->getDefaultEyePosition()); + + glDepthMask(GL_TRUE); + _overlays.releaseTexture(); + glDisable(GL_TEXTURE_2D); + + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE); + glEnable(GL_LIGHTING); + + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + } glPopMatrix(); } // Draws the FBO texture for 3DTV. void ApplicationOverlay::displayOverlayTexture3DTV(Camera& whichCamera, float aspectRatio, float fov) { - if (_alpha == 0.0f) { return; } @@ -427,7 +434,7 @@ void ApplicationOverlay::displayOverlayTexture3DTV(Camera& whichCamera, float as glEnable(GL_BLEND); glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE); - glBindTexture(GL_TEXTURE_2D, getFramebufferObject()->texture()); + _overlays.bindTexture(); glEnable(GL_DEPTH_TEST); glDisable(GL_LIGHTING); glEnable(GL_TEXTURE_2D); @@ -686,143 +693,122 @@ void ApplicationOverlay::renderControllerPointers() { } } + +void renderReticule(glm::quat orientation, float alpha) { + const float reticleSize = TWO_PI / 80.0f; + + glm::vec3 topLeft = getPoint(1.0f, PI_OVER_TWO + reticleSize / 2.0f, - reticleSize / 2.0f); + glm::vec3 topRight = getPoint(1.0f, PI_OVER_TWO + reticleSize / 2.0f, + reticleSize / 2.0f); + glm::vec3 bottomLeft = getPoint(1.0f, PI_OVER_TWO - reticleSize / 2.0f, - reticleSize / 2.0f); + glm::vec3 bottomRight = getPoint(1.0f, PI_OVER_TWO - reticleSize / 2.0f, + reticleSize / 2.0f); + + glPushMatrix(); { + glm::vec3 axis = glm::axis(orientation); + glRotatef(glm::degrees(glm::angle(orientation)), axis.x, axis.y, axis.z); + + glBegin(GL_QUADS); { + glColor4f(RETICLE_COLOR[0], RETICLE_COLOR[1], RETICLE_COLOR[2], alpha); + + glTexCoord2f(0.0f, 0.0f); glVertex3f(topLeft.x, topLeft.y, topLeft.z); + glTexCoord2f(1.0f, 0.0f); glVertex3f(bottomLeft.x, bottomLeft.y, bottomLeft.z); + glTexCoord2f(1.0f, 1.0f); glVertex3f(bottomRight.x, bottomRight.y, bottomRight.z); + glTexCoord2f(0.0f, 1.0f); glVertex3f(topRight.x, topRight.y, topRight.z); + } glEnd(); + } glPopMatrix(); +} + void ApplicationOverlay::renderPointersOculus(const glm::vec3& eyePos) { - - Application* application = Application::getInstance(); - GLCanvas* glWidget = application->getGLWidget(); - glm::vec3 cursorVerts[4]; - + GLCanvas* glWidget = Application::getInstance()->getGLWidget(); const int widgetWidth = glWidget->width(); const int widgetHeight = glWidget->height(); - - const float reticleSize = 50.0f; - + glBindTexture(GL_TEXTURE_2D, _crosshairTexture); glDisable(GL_DEPTH_TEST); glMatrixMode(GL_MODELVIEW); - MyAvatar* myAvatar = application->getAvatar(); - + //Controller Pointers + MyAvatar* myAvatar = Application::getInstance()->getAvatar(); for (int i = 0; i < (int)myAvatar->getHand()->getNumPalms(); i++) { - PalmData& palm = myAvatar->getHand()->getPalms()[i]; - if (palm.isActive()) { - glm::vec3 tip = myAvatar->getLaserPointerTipPosition(&palm); - glm::vec3 tipPos = (tip - eyePos); - - float length = glm::length(eyePos - tip); - float size = 0.03f * length; - - glm::vec3 up = glm::vec3(0.0, 1.0, 0.0) * size; - glm::vec3 right = glm::vec3(1.0, 0.0, 0.0) * size; - - cursorVerts[0] = -right + up; - cursorVerts[1] = right + up; - cursorVerts[2] = right - up; - cursorVerts[3] = -right - up; - - glPushMatrix(); - - // objToCamProj is the vector in world coordinates from the - // local origin to the camera projected in the XZ plane - glm::vec3 cursorToCameraXZ(-tipPos.x, 0, -tipPos.z); - cursorToCameraXZ = glm::normalize(cursorToCameraXZ); - - //Translate the cursor to the tip of the oculus ray - glTranslatef(tip.x, tip.y, tip.z); - - glm::vec3 direction(0, 0, 1); - // easy fix to determine wether the angle is negative or positive - // for positive angles upAux will be a vector pointing in the - // positive y direction, otherwise upAux will point downwards - // effectively reversing the rotation. - glm::vec3 upAux = glm::cross(direction, cursorToCameraXZ); - - // compute the angle - float angleCosine = glm::dot(direction, cursorToCameraXZ); - - //Rotate in XZ direction - glRotatef(acos(angleCosine) * DEGREES_PER_RADIAN, upAux[0], upAux[1], upAux[2]); - - glm::vec3 cursorToCamera = glm::normalize(-tipPos); - - // Compute the angle between cursorToCameraXZ and cursorToCamera, - angleCosine = glm::dot(cursorToCameraXZ, cursorToCamera); - - //Rotate in Y direction - if (cursorToCamera.y < 0) { - glRotatef(acos(angleCosine) * DEGREES_PER_RADIAN, 1, 0, 0); - } else { - glRotatef(acos(angleCosine) * DEGREES_PER_RADIAN, -1, 0, 0); - } - - glBegin(GL_QUADS); - - glColor4f(RETICLE_COLOR[0], RETICLE_COLOR[1], RETICLE_COLOR[2], _alpha); - - glTexCoord2f(0.0f, 0.0f); glVertex3f(cursorVerts[0].x, cursorVerts[0].y, cursorVerts[0].z); - glTexCoord2f(1.0f, 0.0f); glVertex3f(cursorVerts[1].x, cursorVerts[1].y, cursorVerts[1].z); - glTexCoord2f(1.0f, 1.0f); glVertex3f(cursorVerts[2].x, cursorVerts[2].y, cursorVerts[2].z); - glTexCoord2f(0.0f, 1.0f); glVertex3f(cursorVerts[3].x, cursorVerts[3].y, cursorVerts[3].z); - - glEnd(); - - glPopMatrix(); - } +// PalmData& palm = myAvatar->getHand()->getPalms()[i]; +// if (palm.isActive()) { +// glm::vec3 tip = myAvatar->getLaserPointerTipPosition(&palm); +// glm::vec3 tipPos = (tip - eyePos); +// +// float length = glm::length(eyePos - tip); +// float size = 0.03f * length; +// +// glm::vec3 up = glm::vec3(0.0, 1.0, 0.0) * size; +// glm::vec3 right = glm::vec3(1.0, 0.0, 0.0) * size; +// +// cursorVerts[0] = -right + up; +// cursorVerts[1] = right + up; +// cursorVerts[2] = right - up; +// cursorVerts[3] = -right - up; +// +// glPushMatrix(); +// +// // objToCamProj is the vector in world coordinates from the +// // local origin to the camera projected in the XZ plane +// glm::vec3 cursorToCameraXZ(-tipPos.x, 0, -tipPos.z); +// cursorToCameraXZ = glm::normalize(cursorToCameraXZ); +// +// //Translate the cursor to the tip of the oculus ray +// glTranslatef(tip.x, tip.y, tip.z); +// +// glm::vec3 direction(0, 0, 1); +// // easy fix to determine wether the angle is negative or positive +// // for positive angles upAux will be a vector pointing in the +// // positive y direction, otherwise upAux will point downwards +// // effectively reversing the rotation. +// glm::vec3 upAux = glm::cross(direction, cursorToCameraXZ); +// +// // compute the angle +// float angleCosine = glm::dot(direction, cursorToCameraXZ); +// +// //Rotate in XZ direction +// glRotatef(acos(angleCosine) * DEGREES_PER_RADIAN, upAux[0], upAux[1], upAux[2]); +// +// glm::vec3 cursorToCamera = glm::normalize(-tipPos); +// +// // Compute the angle between cursorToCameraXZ and cursorToCamera, +// angleCosine = glm::dot(cursorToCameraXZ, cursorToCamera); +// +// //Rotate in Y direction +// if (cursorToCamera.y < 0) { +// glRotatef(acos(angleCosine) * DEGREES_PER_RADIAN, 1, 0, 0); +// } else { +// glRotatef(acos(angleCosine) * DEGREES_PER_RADIAN, -1, 0, 0); +// } +// +// glBegin(GL_QUADS); +// +// glColor4f(RETICLE_COLOR[0], RETICLE_COLOR[1], RETICLE_COLOR[2], _alpha); +// +// glTexCoord2f(0.0f, 0.0f); glVertex3f(cursorVerts[0].x, cursorVerts[0].y, cursorVerts[0].z); +// glTexCoord2f(1.0f, 0.0f); glVertex3f(cursorVerts[1].x, cursorVerts[1].y, cursorVerts[1].z); +// glTexCoord2f(1.0f, 1.0f); glVertex3f(cursorVerts[2].x, cursorVerts[2].y, cursorVerts[2].z); +// glTexCoord2f(0.0f, 1.0f); glVertex3f(cursorVerts[3].x, cursorVerts[3].y, cursorVerts[3].z); +// +// glEnd(); +// +// glPopMatrix(); +// } } //Mouse Pointer if (_reticleActive[MOUSE]) { - float mouseX = (float)_mouseX[MOUSE]; float mouseY = (float)_mouseY[MOUSE]; - mouseX -= reticleSize / 2; - mouseY += reticleSize / 2; - - //Get new UV coordinates from our magnification window - float newULeft = mouseX / widgetWidth; - float newURight = (mouseX + reticleSize) / widgetWidth; - float newVBottom = 1.0 - mouseY / widgetHeight; - float newVTop = 1.0 - (mouseY - reticleSize) / widgetHeight; - - // Project our position onto the hemisphere using the UV coordinates - float lX = sin((newULeft - 0.5f) * _textureFov); - float rX = sin((newURight - 0.5f) * _textureFov); - float bY = sin((newVBottom - 0.5f) * _textureFov); - float tY = sin((newVTop - 0.5f) * _textureFov); - - float dist; - //Bottom Left - dist = sqrt(lX * lX + bY * bY); - float blZ = sqrt(1.0f - dist * dist); - //Top Left - dist = sqrt(lX * lX + tY * tY); - float tlZ = sqrt(1.0f - dist * dist); - //Bottom Right - dist = sqrt(rX * rX + bY * bY); - float brZ = sqrt(1.0f - dist * dist); - //Top Right - dist = sqrt(rX * rX + tY * tY); - float trZ = sqrt(1.0f - dist * dist); - - glBegin(GL_QUADS); - - glColor4f(RETICLE_COLOR[0], RETICLE_COLOR[1], RETICLE_COLOR[2], _alpha); - - const glm::quat& orientation = myAvatar->getOrientation(); - cursorVerts[0] = orientation * glm::vec3(lX, tY, -tlZ) + eyePos; - cursorVerts[1] = orientation * glm::vec3(rX, tY, -trZ) + eyePos; - cursorVerts[2] = orientation * glm::vec3(rX, bY, -brZ) + eyePos; - cursorVerts[3] = orientation * glm::vec3(lX, bY, -blZ) + eyePos; - - glTexCoord2f(0.0f, 0.0f); glVertex3f(cursorVerts[0].x, cursorVerts[0].y, cursorVerts[0].z); - glTexCoord2f(1.0f, 0.0f); glVertex3f(cursorVerts[1].x, cursorVerts[1].y, cursorVerts[1].z); - glTexCoord2f(1.0f, 1.0f); glVertex3f(cursorVerts[2].x, cursorVerts[2].y, cursorVerts[2].z); - glTexCoord2f(0.0f, 1.0f); glVertex3f(cursorVerts[3].x, cursorVerts[3].y, cursorVerts[3].z); - - glEnd(); - } + static const float MOUSE_PITCH_RANGE = 1.0f * PI; + static const float MOUSE_YAW_RANGE = 0.5f * TWO_PI; + float pitch = -(mouseY / widgetHeight - 0.5f) * MOUSE_PITCH_RANGE; + float yaw = -(mouseX / widgetWidth - 0.5f) * MOUSE_YAW_RANGE; + + glm::quat orientation(glm::vec3(pitch, yaw, 0.0f)); + renderReticule(orientation, _alpha); + } glEnable(GL_DEPTH_TEST); } @@ -1032,107 +1018,61 @@ void ApplicationOverlay::renderMagnifier(int mouseX, int mouseY, float sizeMult, const int widgetWidth = glWidget->width(); const int widgetHeight = glWidget->height(); - const float magnifyWidth = MAGNIFY_WIDTH * sizeMult; - const float magnifyHeight = MAGNIFY_HEIGHT * sizeMult; - - mouseX -= magnifyWidth / 2; - mouseY -= magnifyHeight / 2; - - float newWidth = magnifyWidth * MAGNIFY_MULT; - float newHeight = magnifyHeight * MAGNIFY_MULT; - + const float halfWidth = (MAGNIFY_WIDTH / _textureAspectRatio) * sizeMult / 2.0f; + const float halfHeight = MAGNIFY_HEIGHT * sizeMult / 2.0f; // Magnification Texture Coordinates - float magnifyULeft = mouseX / (float)widgetWidth; - float magnifyURight = (mouseX + magnifyWidth) / (float)widgetWidth; - float magnifyVBottom = 1.0f - mouseY / (float)widgetHeight; - float magnifyVTop = 1.0f - (mouseY + magnifyHeight) / (float)widgetHeight; + float magnifyULeft = (mouseX - halfWidth) / (float)widgetWidth; + float magnifyURight = (mouseX + halfWidth) / (float)widgetWidth; + float magnifyVBottom = 1.0f - (mouseY - halfHeight) / (float)widgetHeight; + float magnifyVTop = 1.0f - (mouseY + halfHeight) / (float)widgetHeight; - // Coordinates of magnification overlay - float newMouseX = (mouseX + magnifyWidth / 2) - newWidth / 2.0f; - float newMouseY = (mouseY + magnifyHeight / 2) + newHeight / 2.0f; - - // Get position on hemisphere using angle + const float newHalfWidth = halfWidth * MAGNIFY_MULT; + const float newHalfHeight = halfHeight * MAGNIFY_MULT; //Get new UV coordinates from our magnification window - float newULeft = newMouseX / widgetWidth; - float newURight = (newMouseX + newWidth) / widgetWidth; - float newVBottom = 1.0 - newMouseY / widgetHeight; - float newVTop = 1.0 - (newMouseY - newHeight) / widgetHeight; + float newULeft = (mouseX - newHalfWidth) / (float)widgetWidth; + float newURight = (mouseX + newHalfWidth) / (float)widgetWidth; + float newVBottom = 1.0f - (mouseY - newHalfHeight) / (float)widgetHeight; + float newVTop = 1.0f - (mouseY + newHalfHeight) / (float)widgetHeight; - // Project our position onto the hemisphere using the UV coordinates - float radius = _oculusuiRadius * application->getAvatar()->getScale(); - float radius2 = radius * radius; + // Find spherical coordinates from newUV, fov and aspect ratio + float radius = _oculusUIRadius * application->getAvatar()->getScale(); + const float leftPhi = (newULeft - 0.5f) * _textureFov * _textureAspectRatio; + const float rightPhi = (newURight - 0.5f) * _textureFov * _textureAspectRatio; + const float bottomTheta = PI_OVER_TWO - (newVBottom - 0.5f) * _textureFov; + const float topTheta = PI_OVER_TWO - (newVTop - 0.5f) * _textureFov; - float lX = radius * sin((newULeft - 0.5f) * _textureFov); - float rX = radius * sin((newURight - 0.5f) * _textureFov); - float bY = radius * sin((newVBottom - 0.5f) * _textureFov); - float tY = radius * sin((newVTop - 0.5f) * _textureFov); + glm::vec3 bottomLeft = getPoint(radius, bottomTheta, leftPhi); + glm::vec3 bottomRight = getPoint(radius, bottomTheta, rightPhi); + glm::vec3 topLeft = getPoint(radius, topTheta, leftPhi); + glm::vec3 topRight = getPoint(radius, topTheta, rightPhi); - float blZ, tlZ, brZ, trZ; - - float dist; - float discriminant; - - //Bottom Left - dist = sqrt(lX * lX + bY * bY); - discriminant = radius2 - dist * dist; - if (discriminant > 0) { - blZ = sqrt(discriminant); - } else { - blZ = 0; - } - //Top Left - dist = sqrt(lX * lX + tY * tY); - discriminant = radius2 - dist * dist; - if (discriminant > 0) { - tlZ = sqrt(discriminant); - } else { - tlZ = 0; - } - //Bottom Right - dist = sqrt(rX * rX + bY * bY); - discriminant = radius2 - dist * dist; - if (discriminant > 0) { - brZ = sqrt(discriminant); - } else { - brZ = 0; - } - //Top Right - dist = sqrt(rX * rX + tY * tY); - discriminant = radius2 - dist * dist; - if (discriminant > 0) { - trZ = sqrt(discriminant); - } else { - trZ = 0; - } - - if (showBorder) { - glDisable(GL_TEXTURE_2D); - glLineWidth(1.0f); - //Outer Line - glBegin(GL_LINE_STRIP); - glColor4f(1.0f, 0.0f, 0.0f, _alpha); + glPushMatrix(); { + if (showBorder) { + glDisable(GL_TEXTURE_2D); + glLineWidth(1.0f); + //Outer Line + glBegin(GL_LINE_STRIP); { + glColor4f(1.0f, 0.0f, 0.0f, _alpha); - glVertex3f(lX, tY, -tlZ); - glVertex3f(rX, tY, -trZ); - glVertex3f(rX, bY, -brZ); - glVertex3f(lX, bY, -blZ); - glVertex3f(lX, tY, -tlZ); + glVertex3f(topLeft.x, topLeft.y, topLeft.z); + glVertex3f(bottomLeft.x, bottomLeft.y, bottomLeft.z); + glVertex3f(bottomRight.x, bottomRight.y, bottomRight.z); + glVertex3f(topRight.x, topRight.y, topRight.z); + glVertex3f(topLeft.x, topLeft.y, topLeft.z); + } glEnd(); + + glEnable(GL_TEXTURE_2D); + } + glColor4f(1.0f, 1.0f, 1.0f, _alpha); - glEnd(); - glEnable(GL_TEXTURE_2D); - } - glColor4f(1.0f, 1.0f, 1.0f, _alpha); - - glBegin(GL_QUADS); - - glTexCoord2f(magnifyULeft, magnifyVBottom); glVertex3f(lX, tY, -tlZ); - glTexCoord2f(magnifyURight, magnifyVBottom); glVertex3f(rX, tY, -trZ); - glTexCoord2f(magnifyURight, magnifyVTop); glVertex3f(rX, bY, -brZ); - glTexCoord2f(magnifyULeft, magnifyVTop); glVertex3f(lX, bY, -blZ); - - glEnd(); - + glBegin(GL_QUADS); { + glTexCoord2f(magnifyULeft, magnifyVBottom); glVertex3f(bottomLeft.x, bottomLeft.y, bottomLeft.z); + glTexCoord2f(magnifyURight, magnifyVBottom); glVertex3f(bottomRight.x, bottomRight.y, bottomRight.z); + glTexCoord2f(magnifyURight, magnifyVTop); glVertex3f(topRight.x, topRight.y, topRight.z); + glTexCoord2f(magnifyULeft, magnifyVTop); glVertex3f(topLeft.x, topLeft.y, topLeft.z); + } glEnd(); + } glPopMatrix(); } ApplicationOverlay::TexturedHemisphere::TexturedHemisphere() : @@ -1150,15 +1090,19 @@ ApplicationOverlay::TexturedHemisphere::~TexturedHemisphere() { } void ApplicationOverlay::TexturedHemisphere::bind() { - if (_framebufferObject != NULL) { - _framebufferObject->bind(); - } + _framebufferObject->bind(); } void ApplicationOverlay::TexturedHemisphere::release() { - if (_framebufferObject != NULL) { - _framebufferObject->release(); - } + _framebufferObject->release(); +} + +void ApplicationOverlay::TexturedHemisphere::bindTexture() { + glBindTexture(GL_TEXTURE_2D, _framebufferObject->texture()); +} + +void ApplicationOverlay::TexturedHemisphere::releaseTexture() { + glBindTexture(GL_TEXTURE_2D, 0); } void ApplicationOverlay::TexturedHemisphere::buildVBO(const float fov, @@ -1182,18 +1126,16 @@ void ApplicationOverlay::TexturedHemisphere::buildVBO(const float fov, for (int i = 0; i < stacks; i++) { float stacksRatio = (float)i / (float)stacks; // First stack is 0.0f, last stack is 1.0f // abs(phi) <= fov / 2.0f - float phi = fov * (stacksRatio - 0.5f); + float theta = PI_OVER_TWO - fov * (stacksRatio - 0.5f); for (int j = 0; j < slices; j++) { float slicesRatio = (float)j / (float)slices; // First slice is 0.0f, last slice is 1.0f // abs(theta) <= fov * aspectRatio / 2.0f - float theta = fov * aspectRatio * (slicesRatio - 0.5f); + float phi = fov * aspectRatio * (slicesRatio - 0.5f); - vertexPtr->position.x = -sinf(theta); - vertexPtr->position.y = sinf(phi); - vertexPtr->position.z = cosf(theta); + vertexPtr->position = getPoint(1.0f, theta, phi); vertexPtr->uv.x = slicesRatio; - vertexPtr->uv.y = 1.0f - stacksRatio; + vertexPtr->uv.y = stacksRatio; vertexPtr++; } } @@ -1249,30 +1191,35 @@ void ApplicationOverlay::TexturedHemisphere::cleanupVBO() { } } -void ApplicationOverlay::TexturedHemisphere::buildFramebufferObject(const QSize& size) { +void ApplicationOverlay::TexturedHemisphere::buildFramebufferObject() { + QSize size = Application::getInstance()->getGLWidget()->getDeviceSize(); + if (_framebufferObject != NULL && size == _framebufferObject->size()) { + // Already build + return; + } + if (_framebufferObject != NULL) { delete _framebufferObject; } _framebufferObject = new QOpenGLFramebufferObject(size); - glBindTexture(GL_TEXTURE_2D, _framebufferObject->texture()); + bindTexture(); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); GLfloat borderColor[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor); - glBindTexture(GL_TEXTURE_2D, 0); + releaseTexture(); } //Renders a hemisphere with texture coordinates. -void ApplicationOverlay::TexturedHemisphere::render(const glm::quat& orientation, const glm::vec3& position, const float scale) { +void ApplicationOverlay::TexturedHemisphere::render() { if (_framebufferObject == NULL || _vbo.first == 0 || _vbo.second == 0) { qDebug() << "TexturedHemisphere::render(): Incorrect initialisation"; return; } - _framebufferObject->bind(); glBindBuffer(GL_ARRAY_BUFFER, _vbo.first); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vbo.second); @@ -1285,19 +1232,11 @@ void ApplicationOverlay::TexturedHemisphere::render(const glm::quat& orientation glVertexPointer(3, GL_FLOAT, STRIDE, VERTEX_POINTER); glTexCoordPointer(2, GL_FLOAT, STRIDE, TEX_COORD_POINTER); - glPushMatrix(); { - glTranslatef(position.x, position.y, position.z); - glm::mat4 rotation = glm::toMat4(orientation); - glMultMatrixf(&rotation[0][0]); - glScalef(scale, scale, scale); - - glDrawRangeElements(GL_TRIANGLES, 0, _vertices - 1, _indices, GL_UNSIGNED_SHORT, 0); - } glPopMatrix(); + glDrawRangeElements(GL_TRIANGLES, 0, _vertices - 1, _indices, GL_UNSIGNED_SHORT, 0); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); - _framebufferObject->release(); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); } diff --git a/interface/src/ui/ApplicationOverlay.h b/interface/src/ui/ApplicationOverlay.h index 94fc4e4958..f3be8a30c8 100644 --- a/interface/src/ui/ApplicationOverlay.h +++ b/interface/src/ui/ApplicationOverlay.h @@ -54,10 +54,12 @@ private: void bind(); void release(); + void bindTexture(); + void releaseTexture(); + void buildFramebufferObject(); void buildVBO(const float fov, const float aspectRatio, const int slices, const int stacks); - void buildFramebufferObject(const QSize& size); - void render(const glm::quat& orientation, const glm::vec3& position, const float scale); + void render(); private: void cleanupVBO(); @@ -68,10 +70,6 @@ private: VerticesIndices _vbo; }; - VerticesIndices* makeTexturedHemiphereVBO(float fov, float aspectRatio, int slices, int stacks); - void renderTexturedHemisphere(ApplicationOverlay::VerticesIndices* vbo, int vertices, int indices); - QOpenGLFramebufferObject* newFramebufferObject(QSize& size); - void renderPointers(); void renderControllerPointers(); void renderPointersOculus(const glm::vec3& eyePos); @@ -81,10 +79,10 @@ private: void renderDomainConnectionStatusBorder(); TexturedHemisphere _overlays; - TexturedHemisphere _reticule; float _trailingAudioLoudness; float _textureFov; + float _textureAspectRatio; enum MagnifyDevices { MOUSE, LEFT_CONTROLLER, RIGHT_CONTROLLER, NUMBER_OF_MAGNIFIERS }; bool _reticleActive[NUMBER_OF_MAGNIFIERS]; From 0624ab7c720b090a971f9539e6e80c1be3095443 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 3 Dec 2014 16:04:23 -0800 Subject: [PATCH 193/502] Fixed aspect ratio and cropped overlay texture --- interface/src/ui/ApplicationOverlay.cpp | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 1050eb5a65..922ad43164 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -64,7 +64,7 @@ void ApplicationOverlay::renderOverlay(bool renderToTexture) { MyAvatar* myAvatar = application->getAvatar(); _textureFov = glm::radians(Menu::getInstance()->getOculusUIAngularSize()); - _textureAspectRatio = application->getGLWidget()->getDeviceWidth() / application->getGLWidget()->getDeviceHeight(); + _textureAspectRatio = (float)application->getGLWidget()->getDeviceWidth() / (float)application->getGLWidget()->getDeviceHeight(); //Handle fading and deactivation/activation of UI if (Menu::getInstance()->isOptionChecked(MenuOption::UserInterface)) { @@ -403,7 +403,18 @@ void ApplicationOverlay::displayOverlayTextureOculus(Camera& whichCamera) { glColor4f(1.0f, 1.0f, 1.0f, _alpha); - _overlays.buildVBO(_textureFov, _textureAspectRatio, 80, 80); + + static float textureFOV = 0.0f, textureAspectRatio = 1.0f; + static QSize size; + if (textureFOV != _textureFov || + textureAspectRatio != _textureAspectRatio || + size != application->getGLWidget()->getDeviceSize()) { + textureFOV = _textureFov; + textureAspectRatio = _textureAspectRatio; + size = application->getGLWidget()->getDeviceSize(); + + _overlays.buildVBO(_textureFov, _textureAspectRatio, 80, 80); + } _overlays.render(); renderPointersOculus(myAvatar->getDefaultEyePosition()); @@ -805,8 +816,8 @@ void ApplicationOverlay::renderPointersOculus(const glm::vec3& eyePos) { static const float MOUSE_YAW_RANGE = 0.5f * TWO_PI; float pitch = -(mouseY / widgetHeight - 0.5f) * MOUSE_PITCH_RANGE; float yaw = -(mouseX / widgetWidth - 0.5f) * MOUSE_YAW_RANGE; - glm::quat orientation(glm::vec3(pitch, yaw, 0.0f)); + renderReticule(orientation, _alpha); } @@ -1124,13 +1135,13 @@ void ApplicationOverlay::TexturedHemisphere::buildVBO(const float fov, TextureVertex* vertexData = new TextureVertex[_vertices]; TextureVertex* vertexPtr = &vertexData[0]; for (int i = 0; i < stacks; i++) { - float stacksRatio = (float)i / (float)stacks; // First stack is 0.0f, last stack is 1.0f - // abs(phi) <= fov / 2.0f + float stacksRatio = (float)i / (float)(stacks - 1); // First stack is 0.0f, last stack is 1.0f + // abs(theta) <= fov / 2.0f float theta = PI_OVER_TWO - fov * (stacksRatio - 0.5f); for (int j = 0; j < slices; j++) { - float slicesRatio = (float)j / (float)slices; // First slice is 0.0f, last slice is 1.0f - // abs(theta) <= fov * aspectRatio / 2.0f + float slicesRatio = (float)j / (float)(slices - 1); // First slice is 0.0f, last slice is 1.0f + // abs(phi) <= fov * aspectRatio / 2.0f float phi = fov * aspectRatio * (slicesRatio - 0.5f); vertexPtr->position = getPoint(1.0f, theta, phi); From 8fb766a5d07b6e172c691641893b8c6ac315b201 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 3 Dec 2014 16:44:13 -0800 Subject: [PATCH 194/502] Only recreate the renderers for nodes that have changed. --- interface/src/MetavoxelSystem.cpp | 116 ++++++++++++--------------- interface/src/MetavoxelSystem.h | 36 +++------ libraries/metavoxels/src/Spanner.cpp | 21 ++++- libraries/metavoxels/src/Spanner.h | 18 +++++ 4 files changed, 97 insertions(+), 94 deletions(-) diff --git a/interface/src/MetavoxelSystem.cpp b/interface/src/MetavoxelSystem.cpp index 6a227614cb..fff91d9052 100644 --- a/interface/src/MetavoxelSystem.cpp +++ b/interface/src/MetavoxelSystem.cpp @@ -578,6 +578,12 @@ void MetavoxelSystem::setVoxelMaterial(const SharedObjectPointer& spanner, const applyMaterialEdit(edit, true); } +void MetavoxelSystem::deleteTextures(int heightTextureID, int colorTextureID, int materialTextureID) const { + glDeleteTextures(1, (const GLuint*)&heightTextureID); + glDeleteTextures(1, (const GLuint*)&colorTextureID); + glDeleteTextures(1, (const GLuint*)&materialTextureID); +} + class SpannerRenderVisitor : public SpannerVisitor { public: @@ -2090,48 +2096,10 @@ void StaticModelRenderer::applyURL(const QUrl& url) { HeightfieldRenderer::HeightfieldRenderer() { } -void HeightfieldRenderer::init(Spanner* spanner) { - SpannerRenderer::init(spanner); - - Heightfield* heightfield = static_cast(spanner); - connect(heightfield, &Heightfield::rootChanged, this, &HeightfieldRenderer::updateRoot); - updateRoot(); -} - -void HeightfieldRenderer::render(const MetavoxelLOD& lod, bool contained, bool cursor) { - Heightfield* heightfield = static_cast(_spanner); - _root->render(heightfield, heightfield->transformLOD(lod), glm::vec2(), 1.0f, contained, cursor); -} - -void HeightfieldRenderer::updateRoot() { - Heightfield* heightfield = static_cast(_spanner); - _root = new HeightfieldRendererNode(heightfield->getRoot()); -} - -HeightfieldRendererNode::HeightfieldRendererNode(const HeightfieldNodePointer& heightfieldNode) : - _heightfieldNode(heightfieldNode), - _heightTextureID(0), - _colorTextureID(0), - _materialTextureID(0) { - - for (int i = 0; i < CHILD_COUNT; i++) { - HeightfieldNodePointer child = heightfieldNode->getChild(i); - if (child) { - _children[i] = new HeightfieldRendererNode(child); - } - } -} - -HeightfieldRendererNode::~HeightfieldRendererNode() { - glDeleteTextures(1, &_heightTextureID); - glDeleteTextures(1, &_colorTextureID); - glDeleteTextures(1, &_materialTextureID); -} - const int X_MAXIMUM_FLAG = 1; const int Y_MAXIMUM_FLAG = 2; -void HeightfieldRendererNode::render(Heightfield* heightfield, const MetavoxelLOD& lod, +static void renderNode(const HeightfieldNodePointer& node, Heightfield* heightfield, const MetavoxelLOD& lod, const glm::vec2& minimum, float size, bool contained, bool cursor) { const glm::quat& rotation = heightfield->getRotation(); glm::vec3 scale(heightfield->getScale() * size, heightfield->getScale() * heightfield->getAspectY(), @@ -2148,19 +2116,44 @@ void HeightfieldRendererNode::render(Heightfield* heightfield, const MetavoxelLO contained = true; } } - if (!isLeaf() && lod.shouldSubdivide(minimum, size)) { + if (!node->isLeaf() && lod.shouldSubdivide(minimum, size)) { float nextSize = size * 0.5f; - for (int i = 0; i < CHILD_COUNT; i++) { - _children[i]->render(heightfield, lod, minimum + glm::vec2(i & X_MAXIMUM_FLAG ? nextSize : 0.0f, + for (int i = 0; i < HeightfieldNode::CHILD_COUNT; i++) { + renderNode(node->getChild(i), heightfield, lod, minimum + glm::vec2(i & X_MAXIMUM_FLAG ? nextSize : 0.0f, i & Y_MAXIMUM_FLAG ? nextSize : 0.0f), nextSize, contained, cursor); } return; } - if (!_heightfieldNode->getHeight()) { + HeightfieldNodeRenderer* renderer = static_cast(node->getRenderer()); + if (!renderer) { + node->setRenderer(renderer = new HeightfieldNodeRenderer()); + } + renderer->render(node, translation, rotation, scale, cursor); +} + +void HeightfieldRenderer::render(const MetavoxelLOD& lod, bool contained, bool cursor) { + Heightfield* heightfield = static_cast(_spanner); + renderNode(heightfield->getRoot(), heightfield, heightfield->transformLOD(lod), glm::vec2(), 1.0f, contained, cursor); +} + +HeightfieldNodeRenderer::HeightfieldNodeRenderer() : + _heightTextureID(0), + _colorTextureID(0), + _materialTextureID(0) { +} + +HeightfieldNodeRenderer::~HeightfieldNodeRenderer() { + QMetaObject::invokeMethod(Application::getInstance()->getMetavoxels(), "deleteTextures", Q_ARG(int, _heightTextureID), + Q_ARG(int, _colorTextureID), Q_ARG(int, _materialTextureID)); +} + +void HeightfieldNodeRenderer::render(const HeightfieldNodePointer& node, const glm::vec3& translation, + const glm::quat& rotation, const glm::vec3& scale, bool cursor) { + if (!node->getHeight()) { return; } - int width = _heightfieldNode->getHeight()->getWidth(); - int height = _heightfieldNode->getHeight()->getContents().size() / width; + int width = node->getHeight()->getWidth(); + int height = node->getHeight()->getContents().size() / width; int innerWidth = width - 2 * HeightfieldHeight::HEIGHT_BORDER; int innerHeight = height - 2 * HeightfieldHeight::HEIGHT_BORDER; int vertexCount = width * height; @@ -2225,7 +2218,7 @@ void HeightfieldRendererNode::render(Heightfield* heightfield, const MetavoxelLO glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - const QVector& heightContents = _heightfieldNode->getHeight()->getContents(); + const QVector& heightContents = node->getHeight()->getContents(); glTexImage2D(GL_TEXTURE_2D, 0, GL_R16, width, height, 0, GL_RED, GL_UNSIGNED_SHORT, heightContents.constData()); @@ -2234,10 +2227,10 @@ void HeightfieldRendererNode::render(Heightfield* heightfield, const MetavoxelLO glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - if (_heightfieldNode->getColor()) { - const QByteArray& contents = _heightfieldNode->getColor()->getContents(); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, _heightfieldNode->getColor()->getWidth(), - contents.size() / (_heightfieldNode->getColor()->getWidth() * DataBlock::COLOR_BYTES), + if (node->getColor()) { + const QByteArray& contents = node->getColor()->getContents(); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, node->getColor()->getWidth(), + contents.size() / (node->getColor()->getWidth() * DataBlock::COLOR_BYTES), 0, GL_RGB, GL_UNSIGNED_BYTE, contents.constData()); } else { @@ -2251,13 +2244,13 @@ void HeightfieldRendererNode::render(Heightfield* heightfield, const MetavoxelLO glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - if (_heightfieldNode->getMaterial()) { - const QByteArray& contents = _heightfieldNode->getMaterial()->getContents(); - glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, _heightfieldNode->getMaterial()->getWidth(), - contents.size() / _heightfieldNode->getMaterial()->getWidth(), + if (node->getMaterial()) { + const QByteArray& contents = node->getMaterial()->getContents(); + glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, node->getMaterial()->getWidth(), + contents.size() / node->getMaterial()->getWidth(), 0, GL_RED, GL_UNSIGNED_BYTE, contents.constData()); - const QVector& materials = _heightfieldNode->getMaterial()->getMaterials(); + const QVector& materials = node->getMaterial()->getMaterials(); _networkTextures.resize(materials.size()); for (int i = 0; i < materials.size(); i++) { const SharedObjectPointer& material = materials.at(i); @@ -2330,7 +2323,7 @@ void HeightfieldRendererNode::render(Heightfield* heightfield, const MetavoxelLO glm::dot(translation, rotation * glm::vec3(1.0f, 0.0f, 0.0f)) / scale.x, glm::dot(translation, rotation * glm::vec3(0.0f, 0.0f, 1.0f)) / scale.z); - const QVector& materials = _heightfieldNode->getMaterial()->getMaterials(); + const QVector& materials = node->getMaterial()->getMaterials(); for (int i = 0; i < materials.size(); i += SPLAT_COUNT) { for (int j = 0; j < SPLAT_COUNT; j++) { int index = i + j; @@ -2355,14 +2348,5 @@ void HeightfieldRendererNode::render(Heightfield* heightfield, const MetavoxelLO } } -bool HeightfieldRendererNode::isLeaf() const { - for (int i = 0; i < CHILD_COUNT; i++) { - if (_children[i]) { - return false; - } - } - return true; -} - -QHash HeightfieldRendererNode::_bufferPairs; +QHash HeightfieldNodeRenderer::_bufferPairs; diff --git a/interface/src/MetavoxelSystem.h b/interface/src/MetavoxelSystem.h index 99c55549c7..26f3bd68a3 100644 --- a/interface/src/MetavoxelSystem.h +++ b/interface/src/MetavoxelSystem.h @@ -24,7 +24,6 @@ #include "renderer/ProgramObject.h" class HeightfieldBaseLayerBatch; -class HeightfieldRendererNode; class HeightfieldSplatBatch; class HermiteBatch; class Model; @@ -91,7 +90,9 @@ public: void addVoxelSplatBatch(const VoxelSplatBatch& batch) { _voxelSplatBatches.append(batch); } void addHermiteBatch(const HermiteBatch& batch) { _hermiteBatches.append(batch); } - + + Q_INVOKABLE void deleteTextures(int heightTextureID, int colorTextureID, int materialTextureID) const; + signals: void rendering(); @@ -431,8 +432,6 @@ private: Model* _model; }; -typedef QExplicitlySharedDataPointer HeightfieldRendererNodePointer; - /// Renders heightfields. class HeightfieldRenderer : public SpannerRenderer { Q_OBJECT @@ -441,38 +440,21 @@ public: Q_INVOKABLE HeightfieldRenderer(); - virtual void init(Spanner* spanner); virtual void render(const MetavoxelLOD& lod = MetavoxelLOD(), bool contained = false, bool cursor = false); - -private slots: - - void updateRoot(); - -private: - - HeightfieldRendererNodePointer _root; }; -/// A node in the heightfield renderer quadtree. -class HeightfieldRendererNode : public QSharedData { +/// Renders a single quadtree node. +class HeightfieldNodeRenderer : public AbstractHeightfieldNodeRenderer { public: - static const int CHILD_COUNT = 4; + HeightfieldNodeRenderer(); + virtual ~HeightfieldNodeRenderer(); - HeightfieldRendererNode(const HeightfieldNodePointer& heightfieldNode); - virtual ~HeightfieldRendererNode(); - - void render(Heightfield* heightfield, const MetavoxelLOD& lod, const glm::vec2& minimum, float size, - bool contained, bool cursor = false); + void render(const HeightfieldNodePointer& node, const glm::vec3& translation, + const glm::quat& rotation, const glm::vec3& scale, bool cursor); private: - bool isLeaf() const; - - HeightfieldNodePointer _heightfieldNode; - - HeightfieldRendererNodePointer _children[CHILD_COUNT]; - GLuint _heightTextureID; GLuint _colorTextureID; GLuint _materialTextureID; diff --git a/libraries/metavoxels/src/Spanner.cpp b/libraries/metavoxels/src/Spanner.cpp index f249ae2912..f2a1ebb27f 100644 --- a/libraries/metavoxels/src/Spanner.cpp +++ b/libraries/metavoxels/src/Spanner.cpp @@ -1143,7 +1143,23 @@ HeightfieldNode::HeightfieldNode(const HeightfieldHeightPointer& height, const H const HeightfieldMaterialPointer& material) : _height(height), _color(color), - _material(material) { + _material(material), + _renderer(NULL) { +} + +HeightfieldNode::HeightfieldNode(const HeightfieldNode& other) : + _height(other.getHeight()), + _color(other.getColor()), + _material(other.getMaterial()), + _renderer(NULL) { + + for (int i = 0; i < CHILD_COUNT; i++) { + _children[i] = other.getChild(i); + } +} + +HeightfieldNode::~HeightfieldNode() { + delete _renderer; } const int HEIGHT_LEAF_SIZE = 256 + HeightfieldHeight::HEIGHT_EXTENSION; @@ -2479,6 +2495,9 @@ int HeightfieldNode::getMaterialAt(const glm::vec3& location) const { return src[(int)glm::round(relative.z) * width + (int)glm::round(relative.x)]; } +AbstractHeightfieldNodeRenderer::~AbstractHeightfieldNodeRenderer() { +} + Heightfield::Heightfield() : _aspectY(1.0f), _aspectZ(1.0f) { diff --git a/libraries/metavoxels/src/Spanner.h b/libraries/metavoxels/src/Spanner.h index c4fe185a58..bbfcbff1ff 100644 --- a/libraries/metavoxels/src/Spanner.h +++ b/libraries/metavoxels/src/Spanner.h @@ -17,6 +17,8 @@ #include "AttributeRegistry.h" #include "MetavoxelUtil.h" +class AbstractHeightfieldNodeRenderer; +class Heightfield; class HeightfieldColor; class HeightfieldHeight; class HeightfieldMaterial; @@ -499,6 +501,10 @@ public: const HeightfieldColorPointer& color = HeightfieldColorPointer(), const HeightfieldMaterialPointer& material = HeightfieldMaterialPointer()); + HeightfieldNode(const HeightfieldNode& other); + + ~HeightfieldNode(); + void setContents(const HeightfieldHeightPointer& height, const HeightfieldColorPointer& color, const HeightfieldMaterialPointer& material); @@ -511,6 +517,9 @@ public: void setMaterial(const HeightfieldMaterialPointer& material) { _material = material; } const HeightfieldMaterialPointer& getMaterial() const { return _material; } + void setRenderer(AbstractHeightfieldNodeRenderer* renderer) { _renderer = renderer; } + AbstractHeightfieldNodeRenderer* getRenderer() const { return _renderer; } + bool isLeaf() const; void setChild(int index, const HeightfieldNodePointer& child) { _children[index] = child; } @@ -559,6 +568,15 @@ private: HeightfieldMaterialPointer _material; HeightfieldNodePointer _children[CHILD_COUNT]; + + AbstractHeightfieldNodeRenderer* _renderer; +}; + +/// Base class for heightfield node rendering. +class AbstractHeightfieldNodeRenderer { +public: + + virtual ~AbstractHeightfieldNodeRenderer(); }; /// A heightfield represented as a spanner. From ab011d5b30409aca9c0ab52dcd1a65f08ad16d0a Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 3 Dec 2014 16:49:49 -0800 Subject: [PATCH 195/502] fix for non-animating models --- libraries/entities/src/ModelEntityItem.cpp | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index 63fe3daa03..0de2035dec 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -374,17 +374,9 @@ bool ModelEntityItem::isAnimatingSomething() const { } EntityItem::SimulationState ModelEntityItem::computeSimulationState() const { - EntityItem::SimulationState baseClassState = EntityItem::computeSimulationState(); - - // if the base class is static, then consider our animation state, and upgrade to changing if - // we are animating. If the base class has a higher simulation state than static, then - // use the base class state. - if (baseClassState == EntityItem::Static) { - if (isAnimatingSomething()) { - return EntityItem::Moving; - } - } - return baseClassState; + // if we're animating then we need to have update() periodically called on this entity + // which means we need to categorized as Moving + return isAnimatingSomething() ? EntityItem::Moving : EntityItem::computeSimulationState(); } void ModelEntityItem::update(const quint64& updateTime) { From bd39688c624244f70ab3768aa157bc20deef60c1 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 3 Dec 2014 17:04:26 -0800 Subject: [PATCH 196/502] Magnifiy window tweaks --- interface/src/ui/ApplicationOverlay.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/interface/src/ui/ApplicationOverlay.h b/interface/src/ui/ApplicationOverlay.h index f3be8a30c8..5fa93f6521 100644 --- a/interface/src/ui/ApplicationOverlay.h +++ b/interface/src/ui/ApplicationOverlay.h @@ -15,9 +15,9 @@ class Overlays; class QOpenGLFramebufferObject; -const float MAGNIFY_WIDTH = 160.0f; -const float MAGNIFY_HEIGHT = 80.0f; -const float MAGNIFY_MULT = 4.0f; +const float MAGNIFY_WIDTH = 220.0f; +const float MAGNIFY_HEIGHT = 100.0f; +const float MAGNIFY_MULT = 2.0f; // Handles the drawing of the overlays to the screen class ApplicationOverlay { From 8d814ab07b11a9ad72051a22c7c38ed749fb6562 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 3 Dec 2014 17:05:42 -0800 Subject: [PATCH 197/502] Updated Oculus pickray --- interface/src/ui/ApplicationOverlay.cpp | 26 ++++++++++++------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 922ad43164..af03147ff9 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -161,23 +161,21 @@ void ApplicationOverlay::displayOverlayTexture() { } void ApplicationOverlay::computeOculusPickRay(float x, float y, glm::vec3& direction) const { - MyAvatar* myAvatar = Application::getInstance()->getAvatar(); + static const float MOUSE_PITCH_RANGE = 1.0f * PI; + static const float MOUSE_YAW_RANGE = 0.5f * TWO_PI; - //invert y direction - y = 1.0 - y; - - //Get position on hemisphere UI - x = sin((x - 0.5f) * _textureFov); - y = sin((y - 0.5f) * _textureFov); - - float dist = sqrt(x * x + y * y); - float z = -sqrt(1.0f - dist * dist); - - glm::vec3 relativePosition = myAvatar->getDefaultEyePosition() + - glm::normalize(myAvatar->getOrientation() * glm::vec3(x, y, z)); + const MyAvatar* myAvatar = Application::getInstance()->getAvatar(); + const GLCanvas* glWidget = Application::getInstance()->getGLWidget(); + const int widgetWidth = glWidget->width(); + const int widgetHeight = glWidget->height(); + + const float pitch = -(y / widgetHeight - 0.5f) * MOUSE_PITCH_RANGE; + const float yaw = -(x / widgetWidth - 0.5f) * MOUSE_YAW_RANGE; + const glm::quat orientation(glm::vec3(pitch, yaw, 0.0f)); + const glm::vec3 localDirection = orientation * IDENTITY_FRONT; //Rotate the UI pick ray by the avatar orientation - direction = glm::normalize(relativePosition - Application::getInstance()->getCamera()->getPosition()); + direction = myAvatar->getOrientation() * localDirection; } // Calculates the click location on the screen by taking into account any From dd8deeea59c74c6b9b495e15cb1b348838670e9c Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Wed, 3 Dec 2014 22:39:11 -0800 Subject: [PATCH 198/502] simpler butterflies script that doesn't put as much traffic on entity server --- examples/butterflies.js | 192 +++++++++------------------------------- 1 file changed, 44 insertions(+), 148 deletions(-) diff --git a/examples/butterflies.js b/examples/butterflies.js index 8055e5b7d9..9bd568d011 100644 --- a/examples/butterflies.js +++ b/examples/butterflies.js @@ -13,18 +13,13 @@ // -var numButterflies = 20; +var numButterflies = 25; function getRandomFloat(min, max) { return Math.random() * (max - min) + min; } -// Multiply vector by scalar -function vScalarMult(v, s) { - var rval = { x: v.x * s, y: v.y * s, z: v.z * s }; - return rval; -} // Create a random vector with individual lengths between a,b function randVector(a, b) { @@ -32,50 +27,36 @@ function randVector(a, b) { return rval; } -// Returns a vector which is fraction of the way between a and b -function vInterpolate(a, b, fraction) { - var rval = { x: a.x + (b.x - a.x) * fraction, y: a.y + (b.y - a.y) * fraction, z: a.z + (b.z - a.z) * fraction }; - return rval; -} - var startTimeInSeconds = new Date().getTime() / 1000; -var NATURAL_SIZE_OF_BUTTERFLY = { x: 1.76, y: 0.825, z: 0.20 }; -var lifeTime = 600; // lifetime of the butterflies in seconds -var range = 3.0; // Over what distance in meters do you want the flock to fly around +var NATURAL_SIZE_OF_BUTTERFLY = { x: 1.0, y: 0.4, z: 0.2 }; + +var lifeTime = 3600; // One hour lifespan +var range = 5.0; // Over what distance in meters do you want the flock to fly around var frame = 0; -var CHANCE_OF_MOVING = 0.9; -var BUTTERFLY_GRAVITY = 0; -var BUTTERFLY_FLAP_SPEED = 0.5; -var BUTTERFLY_VELOCITY = 0.55; var DISTANCE_IN_FRONT_OF_ME = 1.5; var DISTANCE_ABOVE_ME = 1.5; -var flockPosition = Vec3.sum(MyAvatar.position,Vec3.sum( +var FIXED_LOCATION = false; + +if (!FIXED_LOCATION) { + var flockPosition = Vec3.sum(MyAvatar.position,Vec3.sum( Vec3.multiply(Quat.getFront(MyAvatar.orientation), DISTANCE_ABOVE_ME), Vec3.multiply(Quat.getFront(MyAvatar.orientation), DISTANCE_IN_FRONT_OF_ME))); - +} else { + var flockPosition = { x: 4999.6, y: 4986.5, z: 5003.5 }; +} -// set these pitch, yaw, roll to the needed values to orient the model as you want it -var pitchInDegrees = 270.0; -var yawInDegrees = 0.0; -var rollInDegrees = 0.0; -var pitchInRadians = pitchInDegrees / 180.0 * Math.PI; -var yawInRadians = yawInDegrees / 180.0 * Math.PI; -var rollInRadians = rollInDegrees / 180.0 * Math.PI; - -var rotation = Quat.fromPitchYawRollDegrees(pitchInDegrees, yawInDegrees, rollInDegrees);//experimental // This is our butterfly object function defineButterfly(entityID, targetPosition) { this.entityID = entityID; - this.previousFlapOffset = 0; this.targetPosition = targetPosition; - this.moving = false; } // Array of butterflies var butterflies = []; + function addButterfly() { // Decide the size of butterfly var color = { red: 100, green: 100, blue: 100 }; @@ -88,26 +69,24 @@ function addButterfly() { size = MINSIZE + Math.random() * RANGESIZE; var dimensions = Vec3.multiply(NATURAL_SIZE_OF_BUTTERFLY, (size / maxSize)); - - flockPosition = Vec3.sum(MyAvatar.position,Vec3.sum( - Vec3.multiply(Quat.getFront(MyAvatar.orientation), DISTANCE_ABOVE_ME), - Vec3.multiply(Quat.getFront(MyAvatar.orientation), DISTANCE_IN_FRONT_OF_ME))); - + + var GRAVITY = -0.2; + var newFrameRate = 20 + Math.random() * 30; var properties = { type: "Model", lifetime: lifeTime, position: Vec3.sum(randVector(-range, range), flockPosition), - velocity: { x: 0, y: 0.0, z: 0 }, - gravity: { x: 0, y: 1.0, z: 0 }, - damping: 0.1, + rotation: Quat.fromPitchYawRollDegrees(-80 + Math.random() * 20, Math.random() * 360.0, 0.0), + velocity: { x: 0, y: 0, z: 0 }, + gravity: { x: 0, y: GRAVITY, z: 0 }, + damping: 0.9999, dimensions: dimensions, color: color, - rotation: rotation, animationURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/models/content/butterfly/butterfly.fbx", - animationIsPlaying: true, + animationSettings: "{\"firstFrame\":0,\"fps\":" + newFrameRate + ",\"frameIndex\":0,\"hold\":false,\"lastFrame\":10000,\"loop\":true,\"running\":true,\"startAutomatically\":false}", modelURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/models/content/butterfly/butterfly.fbx" }; - butterflies.push(new defineButterfly(Entities.addEntity(properties), properties.position)); + butterflies.push(Entities.addEntity(properties)); } // Generate the butterflies @@ -116,117 +95,34 @@ for (var i = 0; i < numButterflies; i++) { } // Main update function -function updateButterflies(deltaTime) { - // Check to see if we've been running long enough that our butterflies are dead - var nowTimeInSeconds = new Date().getTime() / 1000; - if ((nowTimeInSeconds - startTimeInSeconds) >= lifeTime) { - Script.stop(); - return; - } - +function updateButterflies(deltaTime) { frame++; // Only update every third frame because we don't need to do it too quickly if ((frame % 3) == 0) { - flockPosition = Vec3.sum(MyAvatar.position,Vec3.sum(Vec3.multiply(Quat.getFront(MyAvatar.orientation), DISTANCE_ABOVE_ME), - Vec3.multiply(Quat.getFront(MyAvatar.orientation), DISTANCE_IN_FRONT_OF_ME))); - // Update all the butterflies + var CHANCE_OF_IMPULSE = 0.04; for (var i = 0; i < numButterflies; i++) { - entityID = Entities.identifyEntity(butterflies[i].entityID); - butterflies[i].entityID = entityID; - var properties = Entities.getEntityProperties(entityID); - - if (properties.position.y > flockPosition.y + getRandomFloat(0.0,0.3)){ //0.3 //ceiling - properties.gravity.y = - 3.0; - properties.damping.y = 1.0; - properties.velocity.y = 0; - properties.velocity.x = properties.velocity.x; - properties.velocity.z = properties.velocity.z; - if (properties.velocity.x < 0.5){ - butterflies[i].moving = false; - } - if (properties.velocity.z < 0.5){ - butterflies[i].moving = false; - } - } - - if (properties.velocity.y <= -0.2) { - properties.velocity.y = 0.22; - properties.velocity.x = properties.velocity.x; - properties.velocity.z = properties.velocity.z; - } - - if (properties.position.y < flockPosition.y - getRandomFloat(0.0,0.3)) { //-0.3 // floor - properties.velocity.y = 0.9; - properties.gravity.y = - 4.0; - properties.velocity.x = properties.velocity.x; - properties.velocity.z = properties.velocity.z; - if (properties.velocity.x < 0.5){ - butterflies[i].moving = false; - } - if (properties.velocity.z < 0.5){ - butterflies[i].moving = false; - } - } - - - // Begin movement by getting a target - if (butterflies[i].moving == false) { - if (Math.random() < CHANCE_OF_MOVING) { - var targetPosition = Vec3.sum(randVector(-range, range), flockPosition); - if (targetPosition.x < 0) { - targetPosition.x = 0; - } - if (targetPosition.y < 0) { - targetPosition.y = 0; - } - if (targetPosition.z < 0) { - targetPosition.z = 0; - } - if (targetPosition.x > TREE_SCALE) { - targetPosition.x = TREE_SCALE; - } - if (targetPosition.y > TREE_SCALE) { - targetPosition.y = TREE_SCALE; - } - if (targetPosition.z > TREE_SCALE) { - targetPosition.z = TREE_SCALE; - } - butterflies[i].targetPosition = targetPosition; - butterflies[i].moving = true; + if (Math.random() < CHANCE_OF_IMPULSE) { + var properties = Entities.getEntityProperties(butterflies[i]); + if (Vec3.length(Vec3.subtract(properties.position, flockPosition)) > range) { + Entities.editEntity(butterflies[i], { position: flockPosition } ); + } else if (properties.velocity.y < 0.0) { + // If falling, Create a new direction and impulse + var HORIZ_SCALE = 0.50; + var VERT_SCALE = 0.50; + var newHeading = Math.random() * 360.0; + var newVelocity = Vec3.multiply(HORIZ_SCALE, Quat.getFront(Quat.fromPitchYawRollDegrees(0.0, newHeading, 0.0))); + newVelocity.y = (Math.random() + 0.5) * VERT_SCALE; + Entities.editEntity(butterflies[i], { rotation: Quat.fromPitchYawRollDegrees(-80 + Math.random() * 20, newHeading, (Math.random() - 0.5) * 10), + velocity: newVelocity } ); } } - - // If we are moving, move towards the target - if (butterflies[i].moving) { - - var holding = properties.velocity.y; - - var desiredVelocity = Vec3.subtract(butterflies[i].targetPosition, properties.position); - desiredVelocity = vScalarMult(Vec3.normalize(desiredVelocity), BUTTERFLY_VELOCITY); - - properties.velocity = vInterpolate(properties.velocity, desiredVelocity, 0.5); - properties.velocity.y = holding ; - - - // If we are near the target, we should get a new target - var halfLargestDimension = Vec3.length(properties.dimensions) / 2.0; - if (Vec3.length(Vec3.subtract(properties.position, butterflies[i].targetPosition)) < (halfLargestDimension)) { - butterflies[i].moving = false; - } - - var yawRads = Math.atan2(properties.velocity.z, properties.velocity.x); - yawRads = yawRads + Math.PI / 2.0; - var newOrientation = Quat.fromPitchYawRollRadians(pitchInRadians, yawRads, rollInRadians); - properties.rotation = newOrientation; - } - - // Use a cosine wave offset to make it look like its flapping. - var offset = Math.cos(nowTimeInSeconds * BUTTERFLY_FLAP_SPEED) * (halfLargestDimension); - properties.position.y = properties.position.y + (offset - butterflies[i].previousFlapOffset); - // Change position relative to previous offset. - butterflies[i].previousFlapOffset = offset; - Entities.editEntity(entityID, properties); + } + // Check to see if we've been running long enough that our butterflies are dead + var nowTimeInSeconds = new Date().getTime() / 1000; + if ((nowTimeInSeconds - startTimeInSeconds) >= lifeTime) { + Script.stop(); + return; } } } @@ -237,6 +133,6 @@ Script.update.connect(updateButterflies); // Delete our little friends if script is stopped Script.scriptEnding.connect(function() { for (var i = 0; i < numButterflies; i++) { - Entities.deleteEntity(butterflies[i].entityID); + Entities.deleteEntity(butterflies[i]); } }); \ No newline at end of file From 30d87ee026a3e7e1311160a47515f8ccedeca683 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 4 Dec 2014 00:24:08 -0800 Subject: [PATCH 199/502] Trying to capture light information in order to get the one GLobal Light object containg the intensity value --- libraries/fbx/src/FBXReader.cpp | 114 +++++++++++++++++++++++++------- libraries/fbx/src/FBXReader.h | 9 +++ 2 files changed, 99 insertions(+), 24 deletions(-) diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 8eef6ca738..80d8660b9f 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -32,7 +32,7 @@ // TOOL: Uncomment the following line to enable the filtering of all the unkwnon fields of a node so we can break point easily while loading a model with problems... -#define DEBUG_FBXREADER +//#define DEBUG_FBXREADER using namespace std; @@ -1046,6 +1046,7 @@ FBXBlendshape extractBlendshape(const FBXNode& object) { return blendshape; } + void setTangents(FBXMesh& mesh, int firstIndex, int secondIndex) { const glm::vec3& normal = mesh.normals.at(firstIndex); glm::vec3 bitangent = glm::cross(normal, mesh.vertices.at(secondIndex) - mesh.vertices.at(firstIndex)); @@ -1195,6 +1196,42 @@ int matchTextureUVSetToAttributeChannel(const std::string& texUVSetName, const Q } +FBXLight extractLight(const FBXNode& object) { + FBXLight light; + + foreach (const FBXNode& subobject, object.children) { + std::string childname = subobject.name; + if (subobject.name == "Properties70") { + foreach (const FBXNode& property, subobject.children) { + int valIndex = 4; + std::string propName = property.name; + if (property.name == "P") { + std::string propname = property.properties.at(0).toString().toStdString(); + if (propname == "Intensity") { + light.intensity = 0.01f * property.properties.at(valIndex).value(); + } + } + } + } else if ( subobject.name == "GeometryVersion" + || subobject.name == "TypeFlags") { + } + } +#if defined(DEBUG_FBXREADER) + + std::string type = object.properties.at(0).toString().toStdString(); + type = object.properties.at(1).toString().toStdString(); + type = object.properties.at(2).toString().toStdString(); + + foreach (const QVariant& prop, object.properties) { + std::string proptype = prop.typeName(); + std::string propval = prop.toString().toStdString(); + if (proptype == "Properties70") { + } + } +#endif + + return light; +} FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, bool loadLightmaps, float lightmapLevel) { QHash meshes; @@ -1224,6 +1261,8 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, QHash yComponents; QHash zComponents; + std::map lights; + QVariantHash joints = mapping.value("joint").toHash(); QString jointEyeLeftName = processID(getString(joints.value("jointEyeLeft", "jointEyeLeft"))); QString jointEyeRightName = processID(getString(joints.value("jointEyeRight", "jointEyeRight"))); @@ -1279,6 +1318,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, FBXGeometry geometry; float unitScaleFactor = 1.0f; glm::vec3 ambientColor; + QString hifiGlobalNodeID; foreach (const FBXNode& child, node.children) { if (child.name == "FBXHeaderExtension") { @@ -1333,6 +1373,11 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, QString id = getID(object.properties); modelIDsToNames.insert(id, name); + std::string modelname = name.toLower().toStdString(); + if (modelname.find("hifi") == 0) { + hifiGlobalNodeID = id; + } + if (name == jointEyeLeftName || name == "EyeL" || name == "joint_Leye") { jointEyeLeftID = getID(object.properties); @@ -1363,6 +1408,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, } else if (name == "RightToe" || name == "joint_R_toe" || name == "RightToe_End") { jointRightToeID = getID(object.properties); } + int humanIKJointIndex = humanIKJointNames.indexOf(name); if (humanIKJointIndex != -1) { humanIKJointIDs[humanIKJointIndex] = getID(object.properties); @@ -1459,6 +1505,25 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, extractBlendshape(subobject) }; blendshapes.append(blendshape); } +#if defined(DEBUG_FBXREADER) + else if (subobject.name == "TypeFlags") { + std::string attributetype = subobject.properties.at(0).toString().toStdString(); + if (!attributetype.empty()) { + if (attributetype == "Light") { + std::string lightprop; + foreach (const QVariant& vprop, subobject.properties) { + lightprop = vprop.toString().toStdString(); + } + + FBXLight light = extractLight(object); + } + } + } else { + std::string whatisthat = subobject.name; + if (whatisthat == "WTF") { + } + } +#endif } // add the blendshapes included in the model, if any @@ -1634,41 +1699,28 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, materials.insert(material.id, material); } else if (object.name == "NodeAttribute") { +#if defined(DEBUG_FBXREADER) + std::vector properties; + foreach(const QVariant& v, object.properties) { + properties.push_back(v.toString().toStdString()); + } +#endif + std::string attribID = getID(object.properties).toStdString(); std::string attributetype; - const FBXNode* prop70Node = 0; foreach (const FBXNode& subobject, object.children) { - if (subobject.name == "TypeFlags") { typeFlags.insert(getID(object.properties), subobject.properties.at(0).toString()); attributetype = subobject.properties.at(0).toString().toStdString(); - } else if (subobject.name == "Properties70") { - prop70Node = &subobject; } } if (!attributetype.empty()) { if (attributetype == "Light") { - if (prop70Node) { - foreach (const FBXNode& property, prop70Node->children) { - int valIndex = 4; - if (property.name == "P") { - std::string propname = property.properties.at(0).toString().toStdString(); - if (propname == "LightType") { - std::string type = property.properties.at(valIndex).toString().toStdString(); - } else if (propname == "Intensity") { - float intensity = property.properties.at(valIndex).value(); - } -#if defined(DEBUG_FBXREADER) - else { - if (propname == "EmissiveFactor") { - } - } -#endif - } - } - } + FBXLight light = extractLight(object); + lights[attribID] = light; } } + } else if (object.name == "Deformer") { if (object.properties.last() == "Cluster") { Cluster cluster; @@ -1728,6 +1780,12 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, QString childID = getID(connection.properties, 1); QString parentID = getID(connection.properties, 2); ooChildToParent.insert(childID, parentID); + if (!hifiGlobalNodeID.isEmpty() && (parentID == hifiGlobalNodeID)) { + auto lit = lights.find(childID.toStdString()); + if (lit != lights.end()) { + lightmapLevel = (*lit).second.intensity; + } + } } if (connection.properties.at(0) == "OP") { int counter = 0; @@ -1792,6 +1850,14 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, #endif } + // TODO: check if is code is needed + if (!lights.empty()) { + if (hifiGlobalNodeID.isEmpty()) { + auto l = (*lights.begin()); + lightmapLevel = (l.second).intensity; + } + } + // assign the blendshapes to their corresponding meshes foreach (const ExtractedBlendshape& extracted, blendshapes) { QString blendshapeChannelID = parentMap.value(extracted.id); diff --git a/libraries/fbx/src/FBXReader.h b/libraries/fbx/src/FBXReader.h index a5df7ccc0c..aacfbc0a98 100644 --- a/libraries/fbx/src/FBXReader.h +++ b/libraries/fbx/src/FBXReader.h @@ -165,6 +165,15 @@ public: QVector rotations; }; +/// A light in an FBX document. +class FBXLight { +public: + QString name; + Transform transform; + float intensity; + glm::vec3 color; +}; + Q_DECLARE_METATYPE(FBXAnimationFrame) Q_DECLARE_METATYPE(QVector) From 74acf9513bd8863f825b14291217ba2c1eee1562 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 4 Dec 2014 08:47:18 -0800 Subject: [PATCH 200/502] Fix entity tool selection when inactive --- examples/newEditEntities.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/examples/newEditEntities.js b/examples/newEditEntities.js index 92db9daab5..a95c542311 100644 --- a/examples/newEditEntities.js +++ b/examples/newEditEntities.js @@ -566,6 +566,10 @@ function mouseReleaseEvent(event) { } function mouseClickEvent(event) { + if (!isActive) { + return; + } + var result = findClickedEntity(event); if (result === null) { if (!event.isShifted) { From f48d304df02f21ae7e2bd0d56cd7e45512dc2f16 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 4 Dec 2014 10:03:54 -0800 Subject: [PATCH 201/502] Add registrationPoint to SelectionManager --- examples/libraries/entitySelectionTool.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/examples/libraries/entitySelectionTool.js b/examples/libraries/entitySelectionTool.js index 40b5b78a31..0622e4c72c 100644 --- a/examples/libraries/entitySelectionTool.js +++ b/examples/libraries/entitySelectionTool.js @@ -33,10 +33,12 @@ SelectionManager = (function() { that.localRotation = Quat.fromPitchYawRollDegrees(0, 0, 0); that.localPosition = { x: 0, y: 0, z: 0 }; that.localDimensions = { x: 0, y: 0, z: 0 }; + that.localRegistrationPoint = { x: 0.5, y: 0.5, z: 0.5 }; that.worldRotation = Quat.fromPitchYawRollDegrees(0, 0, 0); that.worldPosition = { x: 0, y: 0, z: 0 }; that.worldDimensions = { x: 0, y: 0, z: 0 }; + that.worldRegistrationPoint = { x: 0.5, y: 0.5, z: 0.5 }; that.centerPosition = { x: 0, y: 0, z: 0 }; that.saveProperties = function() { @@ -153,6 +155,7 @@ SelectionManager = (function() { that.localDimensions = properties.dimensions; that.localPosition = properties.position; that.localRotation = properties.rotation; + that.localRegistrationPoint = properties.registrationPoint; that.worldDimensions = properties.boundingBox.dimensions; that.worldPosition = properties.boundingBox.center; From 53f195eec413c54edb01ca3afb2e6b0c39bf924a Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 4 Dec 2014 10:05:34 -0800 Subject: [PATCH 202/502] Fix position of overlays when registrationPoint is not centered --- examples/libraries/entitySelectionTool.js | 81 +++++++++++++++-------- 1 file changed, 53 insertions(+), 28 deletions(-) diff --git a/examples/libraries/entitySelectionTool.js b/examples/libraries/entitySelectionTool.js index 0622e4c72c..3e50bff8f7 100644 --- a/examples/libraries/entitySelectionTool.js +++ b/examples/libraries/entitySelectionTool.js @@ -985,26 +985,40 @@ SelectionDisplay = (function () { that.updateRotationHandles(); that.highlightSelectable(); - var rotation, dimensions, position; + var rotation, dimensions, position, registrationPoint; if (spaceMode == SPACE_LOCAL) { rotation = SelectionManager.localRotation; dimensions = SelectionManager.localDimensions; position = SelectionManager.localPosition; + registrationPoint = SelectionManager.localRegistrationPoint; } else { rotation = Quat.fromPitchYawRollDegrees(0, 0, 0); dimensions = SelectionManager.worldDimensions; position = SelectionManager.worldPosition; + registrationPoint = SelectionManager.worldRegistrationPoint; } - var halfDimensions = Vec3.multiply(0.5, dimensions); + var registrationPointDimensions = { + x: dimensions.x * registrationPoint.x, + y: dimensions.y * registrationPoint.y, + z: dimensions.z * registrationPoint.z, + }; - var left = -halfDimensions.x; - var right = halfDimensions.x; - var top = halfDimensions.y; - var bottom = -halfDimensions.y; - var front = far = halfDimensions.z; - var near = -halfDimensions.z; + // Center of entity, relative to registration point + var center = { + x: dimensions.x / 2 - registrationPointDimensions.x, + y: dimensions.y / 2 - registrationPointDimensions.y, + z: dimensions.z / 2 - registrationPointDimensions.z, + }; + + // Distances in world coordinates relative to the registration point + var left = -registrationPointDimensions.x; + var right = dimensions.x - registrationPointDimensions.x; + var bottom = -registrationPointDimensions.y; + var top = dimensions.y - registrationPointDimensions.y; + var near = -registrationPointDimensions.z; + var front = far = dimensions.z - registrationPointDimensions.z; var worldTop = SelectionManager.worldDimensions.y / 2; @@ -1017,25 +1031,25 @@ SelectionDisplay = (function () { var LTF = { x: left, y: top, z: far }; var RTF = { x: right, y: top, z: far }; - var TOP = { x: 0, y: top, z: 0 }; - var BOTTOM = { x: 0, y: bottom, z: 0 }; - var LEFT = { x: left, y: 0, z: 0 }; - var RIGHT = { x: right, y: 0, z: 0 }; - var NEAR = { x: 0, y: 0, z: near }; - var FAR = { x: 0, y: 0, z: far }; + var TOP = { x: center.x, y: top, z: center.z }; + var BOTTOM = { x: center.x, y: bottom, z: center.z }; + var LEFT = { x: left, y: center.y, z: center.z }; + var RIGHT = { x: right, y: center.y, z: center.z }; + var NEAR = { x: center.x, y: center.y, z: near }; + var FAR = { x: center.x, y: center.y, z: far }; - var EdgeTR = { x: right, y: top, z: 0 }; - var EdgeTL = { x: left, y: top, z: 0 }; - var EdgeTF = { x: 0, y: top, z: front }; - var EdgeTN = { x: 0, y: top, z: near }; - var EdgeBR = { x: right, y: bottom, z: 0 }; - var EdgeBL = { x: left, y: bottom, z: 0 }; - var EdgeBF = { x: 0, y: bottom, z: front }; - var EdgeBN = { x: 0, y: bottom, z: near }; - var EdgeNR = { x: right, y: 0, z: near }; - var EdgeNL = { x: left, y: 0, z: near }; - var EdgeFR = { x: right, y: 0, z: front }; - var EdgeFL = { x: left, y: 0, z: front }; + var EdgeTR = { x: right, y: top, z: center.z }; + var EdgeTL = { x: left, y: top, z: center.z }; + var EdgeTF = { x: center.x, y: top, z: front }; + var EdgeTN = { x: center.x, y: top, z: near }; + var EdgeBR = { x: right, y: bottom, z: center.z }; + var EdgeBL = { x: left, y: bottom, z: center.z }; + var EdgeBF = { x: center.x, y: bottom, z: front }; + var EdgeBN = { x: center.x, y: bottom, z: near }; + var EdgeNR = { x: right, y: center.y, z: near }; + var EdgeNL = { x: left, y: center.y, z: near }; + var EdgeFR = { x: right, y: center.y, z: front }; + var EdgeFL = { x: left, y: center.y, z: front }; LBN = Vec3.multiplyQbyV(rotation, LBN); RBN = Vec3.multiplyQbyV(rotation, RBN); @@ -1114,8 +1128,10 @@ SelectionDisplay = (function () { Overlays.editOverlay(grabberNEAR, { visible: extendedStretchHandlesVisible, rotation: rotation, position: NEAR }); Overlays.editOverlay(grabberFAR, { visible: extendedStretchHandlesVisible, rotation: rotation, position: FAR }); + var boxPosition = Vec3.multiplyQbyV(rotation, center); + boxPosition = Vec3.sum(position, boxPosition); Overlays.editOverlay(selectionBox, { - position: position, + position: boxPosition, dimensions: dimensions, rotation: rotation, visible: !(mode == "ROTATE_YAW" || mode == "ROTATE_PITCH" || mode == "ROTATE_ROLL"), @@ -1143,8 +1159,17 @@ SelectionDisplay = (function () { if (selectionManager.selections.length > 1) { for (; i < selectionManager.selections.length; i++) { var properties = Entities.getEntityProperties(selectionManager.selections[i]); + + // Adjust overlay position to take registrationPoint into account + // centeredRP = registrationPoint with range [-0.5, 0.5] + var centeredRP = Vec3.subtract(properties.registrationPoint, { x: 0.5, y: 0.5, z: 0.5 }); + var offset = vec3Mult(properties.dimensions, centeredRP); + offset = Vec3.multiply(-1, offset); + offset = Vec3.multiplyQbyV(properties.rotation, offset); + var boxPosition = Vec3.sum(properties.position, offset); + Overlays.editOverlay(selectionBoxes[i], { - position: properties.position, + position: boxPosition, rotation: properties.rotation, dimensions: properties.dimensions, visible: true, From f223f51fa6b06afa2bb5ad96a906970988885448 Mon Sep 17 00:00:00 2001 From: DaveDubUK Date: Thu, 4 Dec 2014 18:15:25 +0000 Subject: [PATCH 203/502] Version 1.12 of the walk.js script --- examples/libraries/walkApi.js | 1016 ++++---- examples/libraries/walkFilters.js | 500 ++-- examples/libraries/walkInterface.js | 3028 +++-------------------- examples/walk.js | 3465 +++++++-------------------- 4 files changed, 2072 insertions(+), 5937 deletions(-) diff --git a/examples/libraries/walkApi.js b/examples/libraries/walkApi.js index e61335f6f0..d2622d5833 100644 --- a/examples/libraries/walkApi.js +++ b/examples/libraries/walkApi.js @@ -1,412 +1,606 @@ -// -// walkObjects.js -// -// version 1.001 -// -// Created by David Wooldridge, Autumn 2014 -// -// Motion, state and Transition objects for use by the walk.js script v1.1 -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -// constructor for the Motion object -Motion = function() { - - this.setGender = function(gender) { - - this.avatarGender = gender; - - switch(this.avatarGender) { - - case MALE: - - this.selWalk = walkAssets.maleStandardWalk; - this.selStand = walkAssets.maleStandOne; - this.selFlyUp = walkAssets.maleFlyingUp; - this.selFly = walkAssets.maleFlying; - this.selFlyDown = walkAssets.maleFlyingDown; - this.selSideStepLeft = walkAssets.maleSideStepLeft; - this.selSideStepRight = walkAssets.maleSideStepRight; - this.curAnim = this.selStand; - return; - - case FEMALE: - - this.selWalk = walkAssets.femaleStandardWalk; - this.selStand = walkAssets.femaleStandOne; - this.selFlyUp = walkAssets.femaleFlyingUp; - this.selFly = walkAssets.femaleFlying; - this.selFlyDown = walkAssets.femaleFlyingDown; - this.selSideStepLeft = walkAssets.femaleSideStepLeft; - this.selSideStepRight = walkAssets.femaleSideStepRight; - this.curAnim = this.selStand; - return; - } - } - - this.hydraCheck = function() { - - // function courtesy of Thijs Wenker, frisbee.js - var numberOfButtons = Controller.getNumberOfButtons(); - var numberOfTriggers = Controller.getNumberOfTriggers(); - var numberOfSpatialControls = Controller.getNumberOfSpatialControls(); - var controllersPerTrigger = numberOfSpatialControls / numberOfTriggers; - hydrasConnected = (numberOfButtons == 12 && numberOfTriggers == 2 && controllersPerTrigger == 2); - return hydrasConnected; - } - - // settings - this.armsFree = this.hydraCheck(); // automatically sets true for Hydra support - temporary fix - this.makesFootStepSounds = true; - this.avatarGender = MALE; - this.motionPitchMax = 60; - this.motionRollMax = 40; - - // timing - this.frameStartTime = 0; // used for measuring frame execution times - this.frameExecutionTimeMax = 0; // keep track of the longest frame execution time - this.cumulativeTime = 0.0; - this.lastWalkStartTime = 0; - - // selected animations - this.selWalk = walkAssets.maleStandardWalk; - this.selStand = walkAssets.maleStandOne; - this.selFlyUp = walkAssets.maleFlyingUp; - this.selFly = walkAssets.maleFlying; - this.selFlyDown = walkAssets.maleFlyingDown; - this.selSideStepLeft = walkAssets.maleSideStepLeft; - this.selSideStepRight = walkAssets.maleSideStepRight; - - // the currently selected animation, joint and transition - this.curAnim = this.selStand; - this.curJointIndex = 0; - this.curTransition = null; - - // zero out avi's joints, curl the fingers nicely then take some measurements - this.avatarJointNames = MyAvatar.getJointNames(); - if (!this.armsFree) { - - for (var i = 0; i < this.avatarJointNames.length; i++) { - - if (i > 17 || i < 34) { - // left hand fingers - MyAvatar.setJointData(this.avatarJointNames[i], Quat.fromPitchYawRollDegrees(16, 0, 0)); - } else if (i > 33 || i < 38) { - // left hand thumb - MyAvatar.setJointData(this.avatarJointNames[i], Quat.fromPitchYawRollDegrees(4, 0, 0)); - } else if (i > 41 || i < 58) { - // right hand fingers - MyAvatar.setJointData(this.avatarJointNames[i], Quat.fromPitchYawRollDegrees(16, 0, 0)); - } else if (i > 57 || i < 62) { - // right hand thumb - MyAvatar.setJointData(this.avatarJointNames[i], Quat.fromPitchYawRollDegrees(4, 0, 0)); - } else { - // zero out the remaining joints - MyAvatar.clearJointData(this.avatarJointNames[i]); - } - } - } - - this.footRPos = MyAvatar.getJointPosition("RightFoot"); - this.hipsToFeet = MyAvatar.getJointPosition("Hips").y - this.footRPos.y; - - // walkwheel (foot / ground speed matching) - this.direction = FORWARDS; - this.nextStep = RIGHT; - this.nFrames = 0; - this.strideLength = this.selWalk.calibration.strideLengthForwards; - this.walkWheelPos = 0; - - this.advanceWalkWheel = function(angle){ - this.walkWheelPos += angle; - if (motion.walkWheelPos >= 360) { - this.walkWheelPos = this.walkWheelPos % 360; - } - } - - // last frame history - this.lastDirection = 0; - this.lastVelocity = 0; - this.lastStrideLength = 0; // kept for use during transitions - -}; // end Motion constructor - -// finite state machine -state = (function () { - - return { - - // the finite list of states - STANDING: 1, - WALKING: 2, - SIDE_STEP: 3, - FLYING: 4, - EDIT_WALK_STYLES: 5, - EDIT_WALK_TWEAKS: 6, - EDIT_WALK_JOINTS: 7, - EDIT_STANDING: 8, - EDIT_FLYING: 9, - EDIT_FLYING_UP: 10, - EDIT_FLYING_DOWN: 11, - EDIT_SIDESTEP_LEFT: 12, - EDIT_SIDESTEP_RIGHT: 14, - currentState: this.STANDING, - - // status vars - powerOn: true, - minimised: true, - editing: false, - editingTranslation: false, - - setInternalState: function(newInternalState) { - - switch (newInternalState) { - - case this.WALKING: - - this.currentState = this.WALKING; - this.editing = false; - motion.lastWalkStartTime = new Date().getTime(); - walkInterface.updateMenu(); - return; - - case this.FLYING: - - this.currentState = this.FLYING; - this.editing = false; - motion.lastWalkStartTime = 0; - walkInterface.updateMenu(); - return; - - case this.SIDE_STEP: - - this.currentState = this.SIDE_STEP; - this.editing = false; - motion.lastWalkStartTime = new Date().getTime(); - walkInterface.updateMenu(); - return; - - case this.EDIT_WALK_STYLES: - - this.currentState = this.EDIT_WALK_STYLES; - this.editing = true; - motion.lastWalkStartTime = new Date().getTime(); - motion.curAnim = motion.selWalk; - walkInterface.updateMenu(); - return; - - case this.EDIT_WALK_TWEAKS: - - this.currentState = this.EDIT_WALK_TWEAKS; - this.editing = true; - motion.lastWalkStartTime = new Date().getTime(); - motion.curAnim = motion.selWalk; - walkInterface.updateMenu(); - return; - - case this.EDIT_WALK_JOINTS: - - this.currentState = this.EDIT_WALK_JOINTS; - this.editing = true; - motion.lastWalkStartTime = new Date().getTime(); - motion.curAnim = motion.selWalk; - walkInterface.updateMenu(); - return; - - case this.EDIT_STANDING: - - this.currentState = this.EDIT_STANDING; - this.editing = true; - motion.lastWalkStartTime = 0; - motion.curAnim = motion.selStand; - walkInterface.updateMenu(); - return; - - case this.EDIT_SIDESTEP_LEFT: - - this.currentState = this.EDIT_SIDESTEP_LEFT; - this.editing = true; - motion.lastWalkStartTime = new Date().getTime(); - motion.curAnim = motion.selSideStepLeft; - walkInterface.updateMenu(); - return; - - case this.EDIT_SIDESTEP_RIGHT: - - this.currentState = this.EDIT_SIDESTEP_RIGHT; - this.editing = true; - motion.lastWalkStartTime = new Date().getTime(); - motion.curAnim = motion.selSideStepRight; - walkInterface.updateMenu(); - return; - - case this.EDIT_FLYING: - - this.currentState = this.EDIT_FLYING; - this.editing = true; - motion.lastWalkStartTime = 0; - motion.curAnim = motion.selFly; - walkInterface.updateMenu(); - return; - - case this.EDIT_FLYING_UP: - - this.currentState = this.EDIT_FLYING_UP; - this.editing = true; - motion.lastWalkStartTime = 0; - motion.curAnim = motion.selFlyUp; - walkInterface.updateMenu(); - return; - - case this.EDIT_FLYING_DOWN: - - this.currentState = this.EDIT_FLYING_DOWN; - this.editing = true; - motion.lastWalkStartTime = 0; - motion.curAnim = motion.selFlyDown; - walkInterface.updateMenu(); - return; - - case this.STANDING: - default: - - this.currentState = this.STANDING; - this.editing = false; - motion.lastWalkStartTime = 0; - motion.curAnim = motion.selStand; - walkInterface.updateMenu(); - - // initialisation - runs at script startup only - if (motion.strideLength === 0) { - - motion.setGender(MALE); - if (motion.direction === BACKWARDS) { - motion.strideLength = motion.selWalk.calibration.strideLengthBackwards; - } else { - motion.strideLength = motion.selWalk.calibration.strideLengthForwards; - } - } - return; - } - } - } -})(); // end state object literal - -// constructor for animation Transition -Transition = function(lastAnimation, nextAnimation, reachPoses, transitionDuration, easingLower, easingUpper) { - - this.lastAnim = lastAnimation; // name of last animation - this.nextAnimation = nextAnimation; // name of next animation - if (lastAnimation === motion.selWalk || - nextAnimation === motion.selSideStepLeft || - nextAnimation === motion.selSideStepRight) { - // boolean - is the last animation a walking animation? - this.walkingAtStart = true; - } else { - this.walkingAtStart = false; - } - if (nextAnimation === motion.selWalk || - nextAnimation === motion.selSideStepLeft || - nextAnimation === motion.selSideStepRight) { - // boolean - is the next animation a walking animation? - this.walkingAtEnd = true; - } else { - this.walkingAtEnd = false; - } - this.reachPoses = reachPoses; // placeholder / stub: array of reach poses for squash and stretch techniques - this.transitionDuration = transitionDuration; // length of transition (seconds) - this.easingLower = easingLower; // Bezier curve handle (normalised) - this.easingUpper = easingUpper; // Bezier curve handle (normalised) - this.startTime = new Date().getTime(); // Starting timestamp (seconds) - this.progress = 0; // how far are we through the transition? - this.walkWheelIncrement = 3; // how much to turn the walkwheel each frame when transitioning to / from walking - this.walkWheelAdvance = 0; // how many degrees the walk wheel has been advanced during the transition - this.walkStopAngle = 0; // what angle should we stop the walk cycle? - -}; // end Transition constructor - - -walkAssets = (function () { - - // path to the sounds used for the footsteps - var _pathToSounds = 'https://s3.amazonaws.com/hifi-public/sounds/Footsteps/'; - - // read in the sounds - var _footsteps = []; - _footsteps.push(SoundCache.getSound(_pathToSounds+"FootstepW2Left-12db.wav")); - _footsteps.push(SoundCache.getSound(_pathToSounds+"FootstepW2Right-12db.wav")); - _footsteps.push(SoundCache.getSound(_pathToSounds+"FootstepW3Left-12db.wav")); - _footsteps.push(SoundCache.getSound(_pathToSounds+"FootstepW3Right-12db.wav")); - _footsteps.push(SoundCache.getSound(_pathToSounds+"FootstepW5Left-12db.wav")); - _footsteps.push(SoundCache.getSound(_pathToSounds+"FootstepW5Right-12db.wav")); - - // load the animation datafiles - Script.include(pathToAssets+"animations/dd-female-standard-walk-animation.js"); - Script.include(pathToAssets+"animations/dd-female-flying-up-animation.js"); - Script.include(pathToAssets+"animations/dd-female-flying-animation.js"); - Script.include(pathToAssets+"animations/dd-female-flying-down-animation.js"); - Script.include(pathToAssets+"animations/dd-female-standing-one-animation.js"); - Script.include(pathToAssets+"animations/dd-female-sidestep-left-animation.js"); - Script.include(pathToAssets+"animations/dd-female-sidestep-right-animation.js"); - Script.include(pathToAssets+"animations/dd-male-standard-walk-animation.js"); - Script.include(pathToAssets+"animations/dd-male-flying-up-animation.js"); - Script.include(pathToAssets+"animations/dd-male-flying-animation.js"); - Script.include(pathToAssets+"animations/dd-male-flying-down-animation.js"); - Script.include(pathToAssets+"animations/dd-male-standing-one-animation.js"); - Script.include(pathToAssets+"animations/dd-male-sidestep-left-animation.js"); - Script.include(pathToAssets+"animations/dd-male-sidestep-right-animation.js"); - - // read in the animation files - var _FemaleStandardWalkFile = new FemaleStandardWalk(); - var _femaleStandardWalk = _FemaleStandardWalkFile.loadAnimation(); - var _FemaleFlyingUpFile = new FemaleFlyingUp(); - var _femaleFlyingUp = _FemaleFlyingUpFile.loadAnimation(); - var _FemaleFlyingFile = new FemaleFlying(); - var _femaleFlying = _FemaleFlyingFile.loadAnimation(); - var _FemaleFlyingDownFile = new FemaleFlyingDown(); - var _femaleFlyingDown = _FemaleFlyingDownFile.loadAnimation(); - var _FemaleStandOneFile = new FemaleStandingOne(); - var _femaleStandOne = _FemaleStandOneFile.loadAnimation(); - var _FemaleSideStepLeftFile = new FemaleSideStepLeft(); - var _femaleSideStepLeft = _FemaleSideStepLeftFile.loadAnimation(); - var _FemaleSideStepRightFile = new FemaleSideStepRight(); - var _femaleSideStepRight = _FemaleSideStepRightFile.loadAnimation(); - var _MaleStandardWalkFile = new MaleStandardWalk(filter); - var _maleStandardWalk = _MaleStandardWalkFile.loadAnimation(); - var _MaleFlyingUpFile = new MaleFlyingUp(); - var _maleFlyingUp = _MaleFlyingUpFile.loadAnimation(); - var _MaleFlyingFile = new MaleFlying(); - var _maleFlying = _MaleFlyingFile.loadAnimation(); - var _MaleFlyingDownFile = new MaleFlyingDown(); - var _maleFlyingDown = _MaleFlyingDownFile.loadAnimation(); - var _MaleStandOneFile = new MaleStandingOne(); - var _maleStandOne = _MaleStandOneFile.loadAnimation(); - var _MaleSideStepLeftFile = new MaleSideStepLeft(); - var _maleSideStepLeft = _MaleSideStepLeftFile.loadAnimation(); - var _MaleSideStepRightFile = new MaleSideStepRight(); - var _maleSideStepRight = _MaleSideStepRightFile.loadAnimation(); - - return { - - // expose the sound assets - footsteps: _footsteps, - - // expose the animation assets - femaleStandardWalk: _femaleStandardWalk, - femaleFlyingUp: _femaleFlyingUp, - femaleFlying: _femaleFlying, - femaleFlyingDown: _femaleFlyingDown, - femaleStandOne: _femaleStandOne, - femaleSideStepLeft: _femaleSideStepLeft, - femaleSideStepRight: _femaleSideStepRight, - maleStandardWalk: _maleStandardWalk, - maleFlyingUp: _maleFlyingUp, - maleFlying: _maleFlying, - maleFlyingDown: _maleFlyingDown, - maleStandOne: _maleStandOne, - maleSideStepLeft: _maleSideStepLeft, - maleSideStepRight: _maleSideStepRight, - } +// +// walkObjects.js +// +// version 1.003 +// +// Created by David Wooldridge, Autumn 2014 +// +// Motion, state and Transition objects for use by the walk.js script v1.12 +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +// constructor for the Motion object +Motion = function() { + + // selected animations + this.selectedWalk = undefined; + this.selectedStand = undefined; + this.selectedFly = undefined; + this.selectedFlyUp = undefined; + this.selectedFlyDown = undefined; + this.selectedFlyBlend = undefined; + this.selectedHovering = undefined; + this.selectedSideStepLeft = undefined; + this.selectedSideStepRight = undefined; + + // if Hydras are connected, the only way to enable use is by never setting any rotations on the arm joints + this.hydraCheck = function() { + + // function courtesy of Thijs Wenker (frisbee.js) + var numberOfButtons = Controller.getNumberOfButtons(); + var numberOfTriggers = Controller.getNumberOfTriggers(); + var numberOfSpatialControls = Controller.getNumberOfSpatialControls(); + var controllersPerTrigger = numberOfSpatialControls / numberOfTriggers; + hydrasConnected = (numberOfButtons == 12 && numberOfTriggers == 2 && controllersPerTrigger == 2); + return hydrasConnected; + } + + // settings + this.armsFree = this.hydraCheck(); // automatically sets true for Hydra support - temporary fix + this.makesFootStepSounds = true; + this.avatarGender = undefined; + this.setGender = function(gender) { + + this.avatarGender = gender; + + switch(this.avatarGender) { + + case MALE: + + this.selectedWalk = walkAssets.maleStandardWalk; + this.selectedStand = walkAssets.maleStandOne; + this.selectedFlyUp = walkAssets.maleFlyingUp; + this.selectedFly = walkAssets.maleFlying; + this.selectedFlyDown = walkAssets.maleFlyingDown; + this.selectedFlyBlend = walkAssets.maleFlyingBlend; + this.selectedHovering = walkAssets.maleHovering; + this.selectedSideStepLeft = walkAssets.maleSideStepLeft; + this.selectedSideStepRight = walkAssets.maleSideStepRight; + this.currentAnimation = this.selectedStand; + return; + + case FEMALE: + + this.selectedWalk = walkAssets.femaleStandardWalk; + this.selectedStand = walkAssets.femaleStandOne; + this.selectedFlyUp = walkAssets.femaleFlyingUp; + this.selectedFly = walkAssets.femaleFlying; + this.selectedFlyDown = walkAssets.femaleFlyingDown; + this.selectedFlyBlend = walkAssets.femaleFlyingBlend; + this.selectedHovering = walkAssets.femaleHovering; + this.selectedSideStepLeft = walkAssets.femaleSideStepLeft; + this.selectedSideStepRight = walkAssets.femaleSideStepRight; + this.currentAnimation = this.selectedStand; + return; + } + } + this.setGender(MALE); + + // calibration + this.calibration = { + + pitchMax: 8, + maxWalkAcceleration: 5, + maxWalkDeceleration: 25, + rollMax: 80, + angularVelocityMax: 70, + hipsToFeet: MyAvatar.getJointPosition("Hips").y - MyAvatar.getJointPosition("RightFoot").y, + } + + // used to make sure at least one step has been taken when transitioning from a walk cycle + this.elapsedFTDegrees = 0; + + // the current animation and transition + this.currentAnimation = this.selectedStand; + this.currentTransition = null; + + // zero out avi's joints and pose the fingers + this.avatarJointNames = MyAvatar.getJointNames(); + this.poseFingers = function() { + + for (var i = 0; i < this.avatarJointNames.length; i++) { + + if (i > 17 || i < 34) { + // left hand fingers + MyAvatar.setJointData(this.avatarJointNames[i], Quat.fromPitchYawRollDegrees(16, 0, 0)); + } else if (i > 33 || i < 38) { + // left hand thumb + MyAvatar.setJointData(this.avatarJointNames[i], Quat.fromPitchYawRollDegrees(4, 0, 0)); + } else if (i > 41 || i < 58) { + // right hand fingers + MyAvatar.setJointData(this.avatarJointNames[i], Quat.fromPitchYawRollDegrees(16, 0, 0)); + } else if (i > 57 || i < 62) { + // right hand thumb + MyAvatar.setJointData(this.avatarJointNames[i], Quat.fromPitchYawRollDegrees(4, 0, 0)); + } + } + }; + if (!this.armsFree) { + this.poseFingers(); + } + + // frequency time wheel (foot / ground speed matching) + this.direction = FORWARDS; + this.strideLength = this.selectedWalk.calibration.strideLengthForwards; + this.frequencyTimeWheelPos = 0; + this.frequencyTimeWheelRadius = 0.5; + this.recentFrequencyTimeIncrements = []; + for(var i = 0; i < 8; i++) { + + this.recentFrequencyTimeIncrements.push(0); + } + this.averageFrequencyTimeIncrement = 0; + + this.advanceFrequencyTimeWheel = function(angle){ + + this.elapsedFTDegrees += angle; + + this.recentFrequencyTimeIncrements.push(angle); + this.recentFrequencyTimeIncrements.shift(); + for(increment in this.recentFrequencyTimeIncrements) { + this.averageFrequencyTimeIncrement += this.recentFrequencyTimeIncrements[increment]; + } + this.averageFrequencyTimeIncrement /= this.recentFrequencyTimeIncrements.length; + + this.frequencyTimeWheelPos += angle; + if (this.frequencyTimeWheelPos >= 360) { + this.frequencyTimeWheelPos = this.frequencyTimeWheelPos % 360; + } + } + + // currently disabled due to breaking changes in js audio native objects + this.playFootStepSound = function(side) { + + //var options = new AudioInjectionOptions(); + //options.position = Camera.getPosition(); + //options.volume = 0.3; + //var soundNumber = 2; // 0 to 2 + //if (side === RIGHT && motion.makesFootStepSounds) { + // Audio.playS ound(walkAssets.footsteps[soundNumber + 1], options); + //} else if (side === LEFT && motion.makesFootStepSounds) { + // Audio.playSound(walkAssets.footsteps[soundNumber], options); + //} + } + + // history + this.lastDirection = 0; + this.lastSpeed = 0; + this.transitionCount = 0; + this.lastDistanceToVoxels = 0; + +}; // end Motion constructor + + +spatialInformation = (function() { + + return { + + distanceToVoxels: function() { + + // use the blocking version of findRayIntersection to avoid errors + var pickRay = {origin: MyAvatar.position, direction: {x:0, y:-1, z:0}}; + return Voxels.findRayIntersectionBlocking(pickRay).distance - motion.calibration.hipsToFeet;; + } + } + +})(); // end spatialInformation object literal + + +// animation file manipulation +animation = (function() { + + return { + + zeroAnimation: function(animation) { + + for (i in animation.joints) { + + animation.joints[i].pitch = 0; + animation.joints[i].yaw = 0; + animation.joints[i].roll = 0; + animation.joints[i].pitchPhase = 0; + animation.joints[i].yawPhase = 0; + animation.joints[i].rollPhase = 0; + animation.joints[i].pitchOffset = 0; + animation.joints[i].yawOffset = 0; + animation.joints[i].rollOffset = 0; + if (i === 0) { + // Hips only + animation.joints[i].thrust = 0; + animation.joints[i].sway = 0; + animation.joints[i].bob = 0; + animation.joints[i].thrustPhase = 0; + animation.joints[i].swayPhase = 0; + animation.joints[i].bobPhase = 0; + } + } + }, + + blendAnimation: function(sourceAnimation, targetAnimation, percent) { + + for (i in targetAnimation.joints) { + + targetAnimation.joints[i].pitch += percent * sourceAnimation.joints[i].pitch; + targetAnimation.joints[i].yaw += percent * sourceAnimation.joints[i].yaw; + targetAnimation.joints[i].roll += percent * sourceAnimation.joints[i].roll; + targetAnimation.joints[i].pitchPhase += percent * sourceAnimation.joints[i].pitchPhase; + targetAnimation.joints[i].yawPhase += percent * sourceAnimation.joints[i].yawPhase; + targetAnimation.joints[i].rollPhase += percent * sourceAnimation.joints[i].rollPhase; + targetAnimation.joints[i].pitchOffset += percent * sourceAnimation.joints[i].pitchOffset; + targetAnimation.joints[i].yawOffset += percent * sourceAnimation.joints[i].yawOffset; + targetAnimation.joints[i].rollOffset += percent * sourceAnimation.joints[i].rollOffset; + if (i === 0) { + // Hips only + targetAnimation.joints[i].thrust += percent * sourceAnimation.joints[i].thrust; + targetAnimation.joints[i].sway += percent * sourceAnimation.joints[i].sway; + targetAnimation.joints[i].bob += percent * sourceAnimation.joints[i].bob; + targetAnimation.joints[i].thrustPhase += percent * sourceAnimation.joints[i].thrustPhase; + targetAnimation.joints[i].swayPhase += percent * sourceAnimation.joints[i].swayPhase; + targetAnimation.joints[i].bobPhase += percent * sourceAnimation.joints[i].bobPhase; + } + } + } + } +})(); // end animation object literal + +// finite state machine. Avatar locomotion modes represent states in the FSM +state = (function () { + + return { + + // the finite list of states + STANDING: 1, + WALKING: 2, + SIDE_STEP: 3, + FLYING: 4, + currentState: this.STANDING, + + // status vars + powerOn: true, + + setInternalState: function(newInternalState) { + + motion.elapsedFTDegrees = 0; + + switch (newInternalState) { + + case this.WALKING: + + this.currentState = this.WALKING; + return; + + case this.FLYING: + + this.currentState = this.FLYING; + return; + + case this.SIDE_STEP: + + this.currentState = this.SIDE_STEP; + return; + + case this.STANDING: + default: + + this.currentState = this.STANDING; + return; + } + } + } +})(); // end state object literal + +// constructor for animation Transition +Transition = function(nextAnimation, lastAnimation, lastTransition) { + + // record the current state of animation + this.nextAnimation = nextAnimation; + this.lastAnimation = lastAnimation; + this.lastTransition = lastTransition; + + // deal with transition recursion (overlapping transitions) + this.id = motion.transitionCount++; // serial number for this transition + this.recursionDepth = 0; + this.incrementRecursion = function() { + + this.recursionDepth += 1; + + if(this.lastTransition !== nullTransition) { + + this.lastTransition.incrementRecursion(); + if(this.lastTransition.recursionDepth > 5) { + + delete this.lastTransition; + this.lastTransition = nullTransition; + } + } + } + if(lastTransition !== nullTransition) { + + this.lastTransition.incrementRecursion(); + } + + this.reachPoses = []; // placeholder / stub: work in progress - array of reach poses for squash and stretch techniques + this.transitionDuration = 0.5; // length of transition (seconds) + this.easingLower = {x:0.60, y:0.03}; // Bezier curve handle + this.easingUpper = {x:0.87, y:1.35}; // Bezier curve handle + this.startTime = new Date().getTime(); // Starting timestamp (seconds) + this.progress = 0; // how far are we through the transition? + this.lastDirection = motion.lastDirection; + + // collect information about the currently playing animation + this.lastDirection = motion.lastDirection; + this.lastFrequencyTimeWheelPos = motion.frequencyTimeWheelPos; + this.lastFrequencyTimeIncrement = motion.averageFrequencyTimeIncrement; + this.lastFrequencyTimeWheelRadius = motion.frequencyTimeWheelRadius; + this.stopAngle = 0; // what angle should we stop turning this frequency time wheel? + this.percentToMove = 0; // if we need to keep moving to complete a step, this will be set to 100 + this.lastElapsedFTDegrees = motion.elapsedFTDegrees; + this.advancePreviousFrequencyTimeWheel = function() { + + this.lastFrequencyTimeWheelPos += this.lastFrequencyTimeIncrement; + + if (this.lastFrequencyTimeWheelPos >= 360) { + + this.lastFrequencyTimeWheelPos = this.lastFrequencyTimeWheelPos % 360; + } + + if(this.lastTransition !== nullTransition) { + + this.lastTransition.advancePreviousFrequencyTimeWheel(); + } + }; + + this.updateProgress = function() { + + var elapasedTime = (new Date().getTime() - this.startTime) / 1000; + this.progress = elapasedTime / this.transitionDuration; + + this.progress = filter.bezier((1 - this.progress), + {x: 0, y: 0}, + this.easingLower, + this.easingUpper, + {x: 1, y: 1}).y; + + // ensure there is at least some progress + if(this.progress <= 0) { + + this.progress = VERY_SHORT_TIME; + } + if(this.lastTransition !== nullTransition) { + + if(this.lastTransition.updateProgress() >= 1) { + + // the previous transition is now complete + delete this.lastTransition; + this.lastTransition = nullTransition; + } + } + return this.progress; + }; + + this.blendTranslations = function(frequencyTimeWheelPos, direction) { + + var lastTranslations = {x:0, y:0, z:0}; + if(!isDefined(this.nextAnimation)) { + + return lastTranslations; + } + var nextTranslations = calculateTranslations(this.nextAnimation, + frequencyTimeWheelPos, + direction); + + // are we blending with a previous, still live transition? + if(this.lastTransition !== nullTransition) { + + lastTranslations = this.lastTransition.blendTranslations(this.lastFrequencyTimeWheelPos, + this.lastDirection); + + } else { + + lastTranslations = calculateTranslations(this.lastAnimation, + this.lastFrequencyTimeWheelPos, + this.lastDirection); + } + + nextTranslations.x = this.progress * nextTranslations.x + + (1 - this.progress) * lastTranslations.x; + + nextTranslations.y = this.progress * nextTranslations.y + + (1 - this.progress) * lastTranslations.y; + + nextTranslations.z = this.progress * nextTranslations.z + + (1 - this.progress) * lastTranslations.z; + + return nextTranslations; + }; + + this.blendRotations = function(jointName, frequencyTimeWheelPos, direction) { + + var lastRotations = {x:0, y:0, z:0}; + var nextRotations = calculateRotations(jointName, + this.nextAnimation, + frequencyTimeWheelPos, + direction); + + // are we blending with a previous, still live transition? + if(this.lastTransition !== nullTransition) { + + lastRotations = this.lastTransition.blendRotations(jointName, + this.lastFrequencyTimeWheelPos, + this.lastDirection); + } else { + + lastRotations = calculateRotations(jointName, + this.lastAnimation, + this.lastFrequencyTimeWheelPos, + this.lastDirection); + } + + nextRotations.x = this.progress * nextRotations.x + + (1 - this.progress) * lastRotations.x; + + nextRotations.y = this.progress * nextRotations.y + + (1 - this.progress) * lastRotations.y; + + nextRotations.z = this.progress * nextRotations.z + + (1 - this.progress) * lastRotations.z; + + return nextRotations; + }; + +}; // end Transition constructor + + +// individual joint modiers (mostly used to provide symmetry between left and right limbs) +JointModifiers = function(joint, direction) { + + // gather modifiers and multipliers + this.pitchFrequencyMultiplier = 1; + this.pitchPhaseModifier = 0; + this.pitchReverseModifier = 0; + this.yawReverseModifier = 0; + this.rollReverseModifier = 0; + this.pitchSign = 1; // for sidestepping and incorrectly rigged Ron ToeBases + this.yawSign = 1; + this.rollSign = 1; + this.pitchReverseInvert = 1; + this.pitchOffsetSign = 1; + this.yawOffsetSign = 1; + this.rollOffsetSign = 1; + this.bobReverseModifier = 0; + this.bobFrequencyMultiplier = 1; + this.thrustFrequencyMultiplier = 1; + + if (isDefined(joint.pitchFrequencyMultiplier)) { + this.pitchFrequencyMultiplier = joint.pitchFrequencyMultiplier; + } + if (isDefined(joint.pitchPhaseModifier)) { + this.pitchPhaseModifier = joint.pitchPhaseModifier; + } + if (isDefined(joint.pitchSign)) { + this.pitchSign = joint.pitchSign; + } + if (isDefined(joint.yawSign)) { + this.yawSign = joint.yawSign; + } + if (isDefined(joint.rollSign)) { + this.rollSign = joint.rollSign; + } + if (isDefined(joint.pitchReverseInvert) && direction === BACKWARDS) { + this.pitchReverseInvert = joint.pitchReverseInvert; + } + if (isDefined(joint.pitchReverseModifier) && direction === BACKWARDS) { + this.pitchReverseModifier = joint.pitchReverseModifier; + } + if (isDefined(joint.yawReverseModifier) && direction === BACKWARDS) { + this.yawReverseModifier = joint.yawReverseModifier; + } + if (isDefined(joint.rollReverseModifier) && direction === BACKWARDS) { + this.rollReverseModifier = joint.rollReverseModifier; + } + if (isDefined(joint.pitchOffsetSign)) { + this.pitchOffsetSign = joint.pitchOffsetSign; + } + if (isDefined(joint.yawOffsetSign)) { + this.yawOffsetSign = joint.yawOffsetSign; + } + if (isDefined(joint.rollOffsetSign)) { + this.rollOffsetSign = joint.rollOffsetSign; + } + if (isDefined(joint.bobReverseModifier) && direction === BACKWARDS) { + this.bobReverseModifier = joint.bobReverseModifier; + } + if (isDefined(joint.bobFrequencyMultiplier)) { + this.bobFrequencyMultiplier = joint.bobFrequencyMultiplier; + } + if (isDefined(joint.thrustFrequencyMultiplier)) { + this.thrustFrequencyMultiplier = joint.thrustFrequencyMultiplier; + } +}; + +walkAssets = (function () { + + // load the sounds - currently disabled due to breaking changes in js audio native objects + //var _pathToSounds = 'https://s3.amazonaws.com/hifi-public/sounds/Footsteps/'; + + //var _footsteps = []; + //_footsteps.push(new Sound(_pathToSounds+"FootstepW2Left-12db.wav")); + //_footsteps.push(new Sound(_pathToSounds+"FootstepW2Right-12db.wav")); + //_footsteps.push(new Sound(_pathToSounds+"FootstepW3Left-12db.wav")); + //_footsteps.push(new Sound(_pathToSounds+"FootstepW3Right-12db.wav")); + //_footsteps.push(new Sound(_pathToSounds+"FootstepW5Left-12db.wav")); + //_footsteps.push(new Sound(_pathToSounds+"FootstepW5Right-12db.wav")); + + // load the animation datafiles + Script.include(pathToAssets+"animations/dd-female-standard-walk-animation.js"); + Script.include(pathToAssets+"animations/dd-female-standing-one-animation.js"); + Script.include(pathToAssets+"animations/dd-female-flying-up-animation.js"); + Script.include(pathToAssets+"animations/dd-female-flying-animation.js"); + Script.include(pathToAssets+"animations/dd-female-flying-down-animation.js"); + Script.include(pathToAssets+"animations/dd-female-flying-blend-animation.js"); + Script.include(pathToAssets+"animations/dd-female-hovering-animation.js"); + Script.include(pathToAssets+"animations/dd-female-sidestep-left-animation.js"); + Script.include(pathToAssets+"animations/dd-female-sidestep-right-animation.js"); + Script.include(pathToAssets+"animations/dd-male-standard-walk-animation.js"); + Script.include(pathToAssets+"animations/dd-male-standing-one-animation.js"); + Script.include(pathToAssets+"animations/dd-male-flying-up-animation.js"); + Script.include(pathToAssets+"animations/dd-male-flying-animation.js"); + Script.include(pathToAssets+"animations/dd-male-flying-down-animation.js"); + Script.include(pathToAssets+"animations/dd-male-flying-blend-animation.js"); + Script.include(pathToAssets+"animations/dd-male-hovering-animation.js"); + Script.include(pathToAssets+"animations/dd-male-sidestep-left-animation.js"); + Script.include(pathToAssets+"animations/dd-male-sidestep-right-animation.js"); + Script.include(pathToAssets+"animations/dd-animation-reference.js"); + + var _femaleStandardWalk = new FemaleStandardWalk(); + var _femaleFlyingUp = new FemaleFlyingUp(); + var _femaleFlying = new FemaleFlying(); + var _femaleFlyingDown = new FemaleFlyingDown(); + var _femaleStandOne = new FemaleStandingOne(); + var _femaleSideStepLeft = new FemaleSideStepLeft(); + var _femaleSideStepRight = new FemaleSideStepRight(); + var _femaleFlyingBlend = new FemaleFlyingBlend(); + var _femaleHovering = new FemaleHovering(); + + var _maleStandardWalk = new MaleStandardWalk(filter); + var _maleStandOne = new MaleStandingOne(); + var _maleSideStepLeft = new MaleSideStepLeft(); + var _maleSideStepRight = new MaleSideStepRight(); + var _maleFlying = new MaleFlying(); + var _maleFlyingDown = new MaleFlyingDown(); + var _maleFlyingUp = new MaleFlyingUp(); + var _maleFlyingBlend = new MaleFlyingBlend(); + var _maleHovering = new MaleHovering(); + + var _animationReference = new AnimationReference(); + + return { + + // expose the sound assets + //footsteps: _footsteps, + + // expose the animation assets + femaleStandardWalk: _femaleStandardWalk, + femaleFlyingUp: _femaleFlyingUp, + femaleFlying: _femaleFlying, + femaleFlyingDown: _femaleFlyingDown, + femaleFlyingBlend: _femaleFlyingBlend, + femaleHovering: _femaleHovering, + femaleStandOne: _femaleStandOne, + femaleSideStepLeft: _femaleSideStepLeft, + femaleSideStepRight: _femaleSideStepRight, + maleStandardWalk: _maleStandardWalk, + maleFlyingUp: _maleFlyingUp, + maleFlying: _maleFlying, + maleFlyingDown: _maleFlyingDown, + maleFlyingBlend: _maleFlyingBlend, + maleHovering: _maleHovering, + maleStandOne: _maleStandOne, + maleSideStepLeft: _maleSideStepLeft, + maleSideStepRight: _maleSideStepRight, + animationReference: _animationReference, + } + })(); \ No newline at end of file diff --git a/examples/libraries/walkFilters.js b/examples/libraries/walkFilters.js index 98a7562bb4..4e77fe6ec7 100644 --- a/examples/libraries/walkFilters.js +++ b/examples/libraries/walkFilters.js @@ -1,225 +1,277 @@ -// -// walkFilters.js -// -// version 1.001 -// -// Created by David Wooldridge, Autumn 2014 -// -// Provides a variety of filters for use by the walk.js script v1.1 -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -AveragingFilter = function(length) { - - //this.name = name; - this.pastValues = []; - - for(var i = 0; i < length; i++) { - this.pastValues.push(0); - } - - // single arg is the nextInputValue - this.process = function() { - - if (this.pastValues.length === 0 && arguments[0]) { - return arguments[0]; - } else if (arguments[0]) { - // apply quick and simple LP filtering - this.pastValues.push(arguments[0]); - this.pastValues.shift(); - var nextOutputValue = 0; - for (var ea in this.pastValues) nextOutputValue += this.pastValues[ea]; - return nextOutputValue / this.pastValues.length; - } else { - return 0; - } - }; -}; - -// 2nd order Butterworth LP filter - calculate coeffs here: http://www-users.cs.york.ac.uk/~fisher/mkfilter/trad.html -// provides LP filtering with a more stable frequency / phase response -ButterworthFilter = function(cutOff) { - - // cut off frequency = 5Hz - this.gain = 20.20612010; - this.coeffOne = -0.4775922501; - this.coeffTwo = 1.2796324250; - - // initialise the arrays - this.xv = []; - this.yv = []; - for(var i = 0; i < 3; i++) { - this.xv.push(0); - this.yv.push(0); - } - - // process values - this.process = function(nextInputValue) { - - this.xv[0] = this.xv[1]; - this.xv[1] = this.xv[2]; - this.xv[2] = nextInputValue / this.gain; - - this.yv[0] = this.yv[1]; - this.yv[1] = this.yv[2]; - this.yv[2] = (this.xv[0] + this.xv[2]) + - 2 * this.xv[1] + - (this.coeffOne * this.yv[0]) + - (this.coeffTwo * this.yv[1]); - - return this.yv[2]; - }; -}; // end Butterworth filter contructor - -// Add harmonics to a given sine wave to form square, sawtooth or triangle waves -// Geometric wave synthesis fundamentals taken from: http://hyperphysics.phy-astr.gsu.edu/hbase/audio/geowv.html -WaveSynth = function(waveShape, numHarmonics, smoothing) { - - this.numHarmonics = numHarmonics; - this.waveShape = waveShape; - this.averagingFilter = new AveragingFilter(smoothing); - - // NB: frequency in radians - this.shapeWave = function(frequency) { - - // make some shapes - var harmonics = 0; - var multiplier = 0; - var iterations = this.numHarmonics * 2 + 2; - if (this.waveShape === TRIANGLE) { - iterations++; - } - - for(var n = 2; n < iterations; n++) { - - switch(this.waveShape) { - - case SAWTOOTH: { - - multiplier = 1 / n; - harmonics += multiplier * Math.sin(n * frequency); - break; - } - - case TRIANGLE: { - - if (n % 2 === 1) { - var mulitplier = 1 / (n * n); - // multiply (4n-1)th harmonics by -1 - if (n === 3 || n === 7 || n === 11 || n === 15) { - mulitplier *= -1; - } - harmonics += mulitplier * Math.sin(n * frequency); - } - break; - } - - case SQUARE: { - - if (n % 2 === 1) { - multiplier = 1 / n; - harmonics += multiplier * Math.sin(n * frequency); - } - break; - } - } - } - - // smooth the result and return - return this.averagingFilter.process(harmonics); - }; -}; - -// Create a wave shape by summing pre-calcualted sinusoidal harmonics -HarmonicsFilter = function(magnitudes, phaseAngles) { - - this.magnitudes = magnitudes; - this.phaseAngles = phaseAngles; - - this.calculate = function(twoPiFT) { - - var harmonics = 0; - var numHarmonics = magnitudes.length; - - for(var n = 0; n < numHarmonics; n++) { - harmonics += this.magnitudes[n] * Math.cos(n * twoPiFT - this.phaseAngles[n]); - } - return harmonics; - }; -}; - -// the main filter object literal -filter = (function() { - - // Bezier private functions - function _B1(t) { return t * t * t }; - function _B2(t) { return 3 * t * t * (1 - t) }; - function _B3(t) { return 3 * t * (1 - t) * (1 - t) }; - function _B4(t) { return (1 - t) * (1 - t) * (1 - t) }; - - return { - - // helper methods - degToRad: function(degrees) { - - var convertedValue = degrees * Math.PI / 180; - return convertedValue; - }, - - radToDeg: function(radians) { - - var convertedValue = radians * 180 / Math.PI; - return convertedValue; - }, - - // these filters need instantiating, as they hold arrays of previous values - createAveragingFilter: function(length) { - - var newAveragingFilter = new AveragingFilter(length); - return newAveragingFilter; - }, - - createButterworthFilter: function(cutoff) { - - var newButterworthFilter = new ButterworthFilter(cutoff); - return newButterworthFilter; - }, - - createWaveSynth: function(waveShape, numHarmonics, smoothing) { - - var newWaveSynth = new WaveSynth(waveShape, numHarmonics, smoothing); - return newWaveSynth; - }, - - createHarmonicsFilter: function(magnitudes, phaseAngles) { - - var newHarmonicsFilter = new HarmonicsFilter(magnitudes, phaseAngles); - return newHarmonicsFilter; - }, - - - // the following filters do not need separate instances, as they hold no previous values - bezier: function(percent, C1, C2, C3, C4) { - - // Bezier functions for more natural transitions - // based on script by Dan Pupius (www.pupius.net) http://13thparallel.com/archive/bezier-curves/ - var pos = {x: 0, y: 0}; - pos.x = C1.x * _B1(percent) + C2.x * _B2(percent) + C3.x * _B3(percent) + C4.x * _B4(percent); - pos.y = C1.y * _B1(percent) + C2.y * _B2(percent) + C3.y * _B3(percent) + C4.y * _B4(percent); - return pos; - }, - - // simple clipping filter (clips bottom of wave only, special case for hips y-axis skeleton offset) - clipTrough: function(inputValue, peak, strength) { - - var outputValue = inputValue * strength; - if (outputValue < -peak) { - outputValue = -peak; - } - return outputValue; - } - } - +// +// walkFilters.js +// +// version 1.002 +// +// Created by David Wooldridge, Autumn 2014 +// +// Provides a variety of filters for use by the walk.js script v1.12 +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +AveragingFilter = function(length) { + + //this.name = name; + this.pastValues = []; + + for(var i = 0; i < length; i++) { + this.pastValues.push(0); + } + + // single arg is the nextInputValue + this.process = function() { + + if (this.pastValues.length === 0 && arguments[0]) { + + return arguments[0]; + + } else if (arguments[0] !== null) { + + // apply quick and simple LP filtering + this.pastValues.push(arguments[0]); + this.pastValues.shift(); + var nextOutputValue = 0; + for (var ea in this.pastValues) nextOutputValue += this.pastValues[ea]; + return nextOutputValue / this.pastValues.length; + + } else { + + return 0; + } + }; +}; + + +// 1st order Butterworth filter - calculate coeffs here: http://www-users.cs.york.ac.uk/~fisher/mkfilter/trad.html +// provides LP filtering with a more stable frequency / phase response (-3 dB @ 3 Hz) +ButterworthFilter1 = function() { + + this.gain = 7.313751515; + this.coeff = 0.7265425280; + + // initialise the arrays + this.xv = []; + this.yv = []; + + for(var i = 0; i < 2; i++) { + + this.xv.push(0); + this.yv.push(0); + } + + // process values + this.process = function(nextInputValue) { + + this.xv[0] = this.xv[1]; + this.xv[1] = nextInputValue / this.gain; + + this.yv[0] = this.yv[1]; + this.yv[1] = this.xv[0] + this.xv[1] + this.coeff * this.yv[0]; + + return this.yv[1]; + }; + +}; // end Butterworth filter constructor + +// 2nd order Butterworth LP filter - calculate coeffs here: http://www-users.cs.york.ac.uk/~fisher/mkfilter/trad.html +// provides LP filtering with a more stable frequency / phase response +ButterworthFilter2 = function(cutOff) { + + switch(cutOff) { + + case 5: + default: + + this.gain = 20.20612010; + this.coeffOne = -0.4775922501; + this.coeffTwo = 1.2796324250; + break; + } + + // initialise the arrays + this.xv = []; + this.yv = []; + for(var i = 0; i < 3; i++) { + + this.xv.push(0); + this.yv.push(0); + } + + // process values + this.process = function(nextInputValue) { + + this.xv[0] = this.xv[1]; + this.xv[1] = this.xv[2]; + this.xv[2] = nextInputValue / this.gain; + + this.yv[0] = this.yv[1]; + this.yv[1] = this.yv[2]; + this.yv[2] = (this.xv[0] + this.xv[2]) + + 2 * this.xv[1] + + (this.coeffOne * this.yv[0]) + + (this.coeffTwo * this.yv[1]); + + return this.yv[2]; + }; +}; // end Butterworth filter constructor + + +// Add harmonics to a given sine wave to form square, sawtooth or triangle waves +// Geometric wave synthesis fundamentals taken from: http://hyperphysics.phy-astr.gsu.edu/hbase/audio/geowv.html +WaveSynth = function(waveShape, numHarmonics, smoothing) { + + this.numHarmonics = numHarmonics; + this.waveShape = waveShape; + this.smoothingFilter = new AveragingFilter(smoothing); + + // NB: frequency in radians + this.calculate = function(frequency) { + + // make some shapes + var harmonics = 0; + var multiplier = 0; + var iterations = this.numHarmonics * 2 + 2; + if (this.waveShape === TRIANGLE) { + iterations++; + } + + for(var n = 1; n < iterations; n++) { + + switch(this.waveShape) { + + case SAWTOOTH: { + + multiplier = 1 / n; + harmonics += multiplier * Math.sin(n * frequency); + break; + } + + case TRIANGLE: { + + if (n % 2 === 1) { + var mulitplier = 1 / (n * n); + // multiply (4n-1)th harmonics by -1 + if (n === 3 || n === 7 || n === 11 || n === 15) { + mulitplier *= -1; + } + harmonics += mulitplier * Math.sin(n * frequency); + } + break; + } + + case SQUARE: { + + if (n % 2 === 1) { + multiplier = 1 / n; + harmonics += multiplier * Math.sin(n * frequency); + } + break; + } + } + } + + // smooth the result and return + return this.smoothingFilter.process(harmonics); + }; +}; + +// Create a motion wave by summing pre-calcualted sinusoidal harmonics +HarmonicsFilter = function(magnitudes, phaseAngles) { + + this.magnitudes = magnitudes; + this.phaseAngles = phaseAngles; + + this.calculate = function(twoPiFT) { + + var harmonics = 0; + var numHarmonics = magnitudes.length; + + for(var n = 0; n < numHarmonics; n++) { + harmonics += this.magnitudes[n] * Math.cos(n * twoPiFT - this.phaseAngles[n]); + } + return harmonics; + }; +}; + + +// the main filter object +filter = (function() { + + // Bezier private functions + function _B1(t) { return t * t * t }; + function _B2(t) { return 3 * t * t * (1 - t) }; + function _B3(t) { return 3 * t * (1 - t) * (1 - t) }; + function _B4(t) { return (1 - t) * (1 - t) * (1 - t) }; + + return { + + // helper methods + degToRad: function(degrees) { + + var convertedValue = degrees * Math.PI / 180; + return convertedValue; + }, + + radToDeg: function(radians) { + + var convertedValue = radians * 180 / Math.PI; + return convertedValue; + }, + + // these filters need instantiating, as they hold arrays of previous values + createAveragingFilter: function(length) { + + var newAveragingFilter = new AveragingFilter(length); + return newAveragingFilter; + }, + + createButterworthFilter1: function() { + + var newButterworthFilter = new ButterworthFilter1(); + return newButterworthFilter; + }, + + createButterworthFilter2: function(cutoff) { + + var newButterworthFilter = new ButterworthFilter2(cutoff); + return newButterworthFilter; + }, + + createWaveSynth: function(waveShape, numHarmonics, smoothing) { + + var newWaveSynth = new WaveSynth(waveShape, numHarmonics, smoothing); + return newWaveSynth; + }, + + createHarmonicsFilter: function(magnitudes, phaseAngles) { + + var newHarmonicsFilter = new HarmonicsFilter(magnitudes, phaseAngles); + return newHarmonicsFilter; + }, + + + // the following filters do not need separate instances, as they hold no previous values + bezier: function(percent, C1, C2, C3, C4) { + + // Bezier functions for more natural transitions + // based on script by Dan Pupius (www.pupius.net) http://13thparallel.com/archive/bezier-curves/ + var pos = {x: 0, y: 0}; + pos.x = C1.x * _B1(percent) + C2.x * _B2(percent) + C3.x * _B3(percent) + C4.x * _B4(percent); + pos.y = C1.y * _B1(percent) + C2.y * _B2(percent) + C3.y * _B3(percent) + C4.y * _B4(percent); + return pos; + }, + + // simple clipping filter (clips bottom of wave only) + clipTrough: function(inputValue, peak, strength) { + + var outputValue = inputValue * strength; + if (outputValue < -peak) { + outputValue = -peak; + } + return outputValue; + } + } + })(); \ No newline at end of file diff --git a/examples/libraries/walkInterface.js b/examples/libraries/walkInterface.js index aa0b533101..0375fb7bea 100644 --- a/examples/libraries/walkInterface.js +++ b/examples/libraries/walkInterface.js @@ -1,2690 +1,340 @@ -// -// walkInterface.js -// -// version 1.001 -// -// Created by David Wooldridge, Autumn 2014 -// -// Presents the UI for the walk.js script v1.1 -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -walkInterface = (function() { - - // controller element positions and dimensions - var _backgroundWidth = 350; - var _backgroundHeight = 700; - var _backgroundX = Window.innerWidth - _backgroundWidth - 58; - var _backgroundY = Window.innerHeight / 2 - _backgroundHeight / 2; - var _minSliderX = _backgroundX + 30; - var _sliderRangeX = 295 - 30; - var _jointsControlWidth = 200; - var _jointsControlHeight = 300; - var _jointsControlX = _backgroundX + _backgroundWidth / 2 - _jointsControlWidth / 2; - var _jointsControlY = _backgroundY + 242 - _jointsControlHeight / 2; - var _buttonsY = 20; // distance from top of panel to menu buttons - var _bigButtonsY = 408; // distance from top of panel to top of first big button - - // arrays of overlay names - var _sliderThumbOverlays = []; - var _backgroundOverlays = []; - var _buttonOverlays = []; - var _jointsControlOverlays = []; - var _bigbuttonOverlays = []; - - // reference to the internal state - var _state = { - editingTranslation: false - }; - - // reference to the Motion object - var _motion = null; - - var _walkAssets = null; - - // constants - var MAX_WALK_SPEED = 1257; - - // look and feel - var momentaryButtonTimer = null; - - // all slider controls have a range (with the exception of phase controls that are always +-180) - var _sliderRanges = { - "joints": [{ - "name": "hips", - "pitchRange": 12, - "yawRange": 18, - "rollRange": 12, - "pitchOffsetRange": 25, - "yawOffsetRange": 25, - "rollOffsetRange": 25, - "swayRange": 0.12, - "bobRange": 0.05, - "thrustRange": 0.05, - "swayOffsetRange": 0.25, - "bobOffsetRange": 0.25, - "thrustOffsetRange": 0.25 - }, { - "name": "upperLegs", - "pitchRange": 30, - "yawRange": 35, - "rollRange": 35, - "pitchOffsetRange": 20, - "yawOffsetRange": 20, - "rollOffsetRange": 20 - }, { - "name": "lowerLegs", - "pitchRange": 10, - "yawRange": 20, - "rollRange": 20, - "pitchOffsetRange": 180, - "yawOffsetRange": 20, - "rollOffsetRange": 20 - }, { - "name": "feet", - "pitchRange": 10, - "yawRange": 20, - "rollRange": 20, - "pitchOffsetRange": 180, - "yawOffsetRange": 50, - "rollOffsetRange": 50 - }, { - "name": "toes", - "pitchRange": 90, - "yawRange": 20, - "rollRange": 20, - "pitchOffsetRange": 90, - "yawOffsetRange": 20, - "rollOffsetRange": 20 - }, { - "name": "spine", - "pitchRange": 40, - "yawRange": 40, - "rollRange": 40, - "pitchOffsetRange": 90, - "yawOffsetRange": 50, - "rollOffsetRange": 50 - }, { - "name": "spine1", - "pitchRange": 20, - "yawRange": 40, - "rollRange": 20, - "pitchOffsetRange": 90, - "yawOffsetRange": 50, - "rollOffsetRange": 50 - }, { - "name": "spine2", - "pitchRange": 20, - "yawRange": 40, - "rollRange": 20, - "pitchOffsetRange": 90, - "yawOffsetRange": 50, - "rollOffsetRange": 50 - }, { - "name": "shoulders", - "pitchRange": 35, - "yawRange": 40, - "rollRange": 20, - "pitchOffsetRange": 180, - "yawOffsetRange": 180, - "rollOffsetRange": 180 - }, { - "name": "upperArms", - "pitchRange": 90, - "yawRange": 90, - "rollRange": 90, - "pitchOffsetRange": 180, - "yawOffsetRange": 180, - "rollOffsetRange": 180 - }, { - "name": "lowerArms", - "pitchRange": 90, - "yawRange": 90, - "rollRange": 120, - "pitchOffsetRange": 180, - "yawOffsetRange": 180, - "rollOffsetRange": 180 - }, { - "name": "hands", - "pitchRange": 90, - "yawRange": 180, - "rollRange": 90, - "pitchOffsetRange": 180, - "yawOffsetRange": 180, - "rollOffsetRange": 180 - }, { - "name": "head", - "pitchRange": 20, - "yawRange": 20, - "rollRange": 20, - "pitchOffsetRange": 90, - "yawOffsetRange": 90, - "rollOffsetRange": 90 - }] - }; - - // load overlay images - var _controlsMinimisedTab = Overlays.addOverlay("image", { - x: Window.innerWidth - 58, - y: Window.innerHeight - 145, - width: 50, - height: 50, - imageURL: pathToAssets + 'overlay-images/ddao-minimise-tab.png', - visible: true, - alpha: 0.9 - }); - - var _controlsBackground = Overlays.addOverlay("image", { - bounds: { - x: _backgroundX, - y: _backgroundY, - width: _backgroundWidth, - height: _backgroundHeight - }, - imageURL: pathToAssets + "overlay-images/ddao-background.png", - color: { - red: 255, - green: 255, - blue: 255 - }, - alpha: 1, - visible: false - }); - _backgroundOverlays.push(_controlsBackground); - - var _controlsBackgroundWalkEditStyles = Overlays.addOverlay("image", { - bounds: { - x: _backgroundX, - y: _backgroundY, - width: _backgroundWidth, - height: _backgroundHeight - }, - imageURL: pathToAssets + "overlay-images/ddao-background-edit-styles.png", - color: { - red: 255, - green: 255, - blue: 255 - }, - alpha: 1, - visible: false - }); - _backgroundOverlays.push(_controlsBackgroundWalkEditStyles); - - var _controlsBackgroundWalkEditTweaks = Overlays.addOverlay("image", { - bounds: { - x: _backgroundX, - y: _backgroundY, - width: _backgroundWidth, - height: _backgroundHeight - }, - imageURL: pathToAssets + "overlay-images/ddao-background-edit-tweaks.png", - color: { - red: 255, - green: 255, - blue: 255 - }, - alpha: 1, - visible: false - }); - _backgroundOverlays.push(_controlsBackgroundWalkEditTweaks); - - var _controlsBackgroundWalkEditHipTrans = Overlays.addOverlay("image", { - bounds: { - x: _backgroundX, - y: _backgroundY, - width: _backgroundWidth, - height: _backgroundHeight - }, - imageURL: pathToAssets + "overlay-images/ddao-background-edit-translation.png", - color: { - red: 255, - green: 255, - blue: 255 - }, - alpha: 1, - visible: false - }); - _backgroundOverlays.push(_controlsBackgroundWalkEditHipTrans); - - var _controlsBackgroundWalkEditJoints = Overlays.addOverlay("image", { - bounds: { - x: _backgroundX, - y: _backgroundY, - width: _backgroundWidth, - height: _backgroundHeight - }, - imageURL: pathToAssets + "overlay-images/ddao-background-edit-joints.png", - color: { - red: 255, - green: 255, - blue: 255 - }, - alpha: 1, - visible: false - }); - _backgroundOverlays.push(_controlsBackgroundWalkEditJoints); - - // load character joint selection control images - var _hipsJointsTranslation = Overlays.addOverlay("image", { - bounds: { - x: _jointsControlX, - y: _jointsControlY, - width: 200, - height: 300 - }, - imageURL: pathToAssets + "overlay-images/ddao-background-edit-hips-translation.png", - color: { - red: 255, - green: 255, - blue: 255 - }, - alpha: 1, - visible: false - }); - _jointsControlOverlays.push(_hipsJointsTranslation); - - var _hipsJointControl = Overlays.addOverlay("image", { - bounds: { - x: _jointsControlX, - y: _jointsControlY, - width: 200, - height: 300 - }, - imageURL: pathToAssets + "overlay-images/ddao-background-edit-hips.png", - color: { - red: 255, - green: 255, - blue: 255 - }, - alpha: 1, - visible: false - }); - _jointsControlOverlays.push(_hipsJointControl); - - var _upperLegsJointControl = Overlays.addOverlay("image", { - bounds: { - x: _jointsControlX, - y: _jointsControlY, - width: 200, - height: 300 - }, - imageURL: pathToAssets + "overlay-images/ddao-background-edit-upper-legs.png", - color: { - red: 255, - green: 255, - blue: 255 - }, - alpha: 1, - visible: false - }); - _jointsControlOverlays.push(_upperLegsJointControl); - - var _lowerLegsJointControl = Overlays.addOverlay("image", { - bounds: { - x: _jointsControlX, - y: _jointsControlY, - width: 200, - height: 300 - }, - imageURL: pathToAssets + "overlay-images/ddao-background-edit-lower-legs.png", - color: { - red: 255, - green: 255, - blue: 255 - }, - alpha: 1, - visible: false - }); - _jointsControlOverlays.push(_lowerLegsJointControl); - - var _feetJointControl = Overlays.addOverlay("image", { - bounds: { - x: _jointsControlX, - y: _jointsControlY, - width: 200, - height: 300 - }, - imageURL: pathToAssets + "overlay-images/ddao-background-edit-feet.png", - color: { - red: 255, - green: 255, - blue: 255 - }, - alpha: 1, - visible: false - }); - _jointsControlOverlays.push(_feetJointControl); - - var _toesJointControl = Overlays.addOverlay("image", { - bounds: { - x: _jointsControlX, - y: _jointsControlY, - width: 200, - height: 300 - }, - imageURL: pathToAssets + "overlay-images/ddao-background-edit-toes.png", - color: { - red: 255, - green: 255, - blue: 255 - }, - alpha: 1, - visible: false - }); - _jointsControlOverlays.push(_toesJointControl); - - var _spineJointControl = Overlays.addOverlay("image", { - bounds: { - x: _jointsControlX, - y: _jointsControlY, - width: 200, - height: 300 - }, - imageURL: pathToAssets + "overlay-images/ddao-background-edit-spine.png", - color: { - red: 255, - green: 255, - blue: 255 - }, - alpha: 1, - visible: false - }); - _jointsControlOverlays.push(_spineJointControl); - - var _spine1JointControl = Overlays.addOverlay("image", { - bounds: { - x: _jointsControlX, - y: _jointsControlY, - width: 200, - height: 300 - }, - imageURL: pathToAssets + "overlay-images/ddao-background-edit-spine1.png", - color: { - red: 255, - green: 255, - blue: 255 - }, - alpha: 1, - visible: false - }); - _jointsControlOverlays.push(_spine1JointControl); - - var _spine2JointControl = Overlays.addOverlay("image", { - bounds: { - x: _jointsControlX, - y: _jointsControlY, - width: 200, - height: 300 - }, - imageURL: pathToAssets + "overlay-images/ddao-background-edit-spine2.png", - color: { - red: 255, - green: 255, - blue: 255 - }, - alpha: 1, - visible: false - }); - _jointsControlOverlays.push(_spine2JointControl); - - var _shouldersJointControl = Overlays.addOverlay("image", { - bounds: { - x: _jointsControlX, - y: _jointsControlY, - width: 200, - height: 300 - }, - imageURL: pathToAssets + "overlay-images/ddao-background-edit-shoulders.png", - color: { - red: 255, - green: 255, - blue: 255 - }, - alpha: 1, - visible: false - }); - _jointsControlOverlays.push(_shouldersJointControl); - - var _upperArmsJointControl = Overlays.addOverlay("image", { - bounds: { - x: _jointsControlX, - y: _jointsControlY, - width: 200, - height: 300 - }, - imageURL: pathToAssets + "overlay-images/ddao-background-edit-upper-arms.png", - color: { - red: 255, - green: 255, - blue: 255 - }, - alpha: 1, - visible: false - }); - _jointsControlOverlays.push(_upperArmsJointControl); - - var _forearmsJointControl = Overlays.addOverlay("image", { - bounds: { - x: _jointsControlX, - y: _jointsControlY, - width: 200, - height: 300 - }, - imageURL: pathToAssets + "overlay-images/ddao-background-edit-forearms.png", - color: { - red: 255, - green: 255, - blue: 255 - }, - alpha: 1, - visible: false - }); - _jointsControlOverlays.push(_forearmsJointControl); - - var _handsJointControl = Overlays.addOverlay("image", { - bounds: { - x: _jointsControlX, - y: _jointsControlY, - width: 200, - height: 300 - }, - imageURL: pathToAssets + "overlay-images/ddao-background-edit-hands.png", - color: { - red: 255, - green: 255, - blue: 255 - }, - alpha: 1, - visible: false - }); - _jointsControlOverlays.push(_handsJointControl); - - var _headJointControl = Overlays.addOverlay("image", { - bounds: { - x: _jointsControlX, - y: _jointsControlY, - width: 200, - height: 300 - }, - imageURL: pathToAssets + "overlay-images/ddao-background-edit-head.png", - color: { - red: 255, - green: 255, - blue: 255 - }, - alpha: 1, - visible: false - }); - _jointsControlOverlays.push(_headJointControl); - - - // slider thumb overlays - var _sliderOne = Overlays.addOverlay("image", { - bounds: { - x: 0, - y: 0, - width: 25, - height: 25 - }, - imageURL: pathToAssets + "overlay-images/ddao-slider-handle.png", - color: { - red: 255, - green: 255, - blue: 255 - }, - alpha: 1, - visible: false - }); - _sliderThumbOverlays.push(_sliderOne); - - var _sliderTwo = Overlays.addOverlay("image", { - bounds: { - x: 0, - y: 0, - width: 25, - height: 25 - }, - imageURL: pathToAssets + "overlay-images/ddao-slider-handle.png", - color: { - red: 255, - green: 255, - blue: 255 - }, - alpha: 1, - visible: false - }); - _sliderThumbOverlays.push(_sliderTwo); - - var _sliderThree = Overlays.addOverlay("image", { - bounds: { - x: 0, - y: 0, - width: 25, - height: 25 - }, - imageURL: pathToAssets + "overlay-images/ddao-slider-handle.png", - color: { - red: 255, - green: 255, - blue: 255 - }, - alpha: 1, - visible: false - }); - _sliderThumbOverlays.push(_sliderThree); - - var _sliderFour = Overlays.addOverlay("image", { - bounds: { - x: 0, - y: 0, - width: 25, - height: 25 - }, - imageURL: pathToAssets + "overlay-images/ddao-slider-handle.png", - color: { - red: 255, - green: 255, - blue: 255 - }, - alpha: 1, - visible: false - }); - _sliderThumbOverlays.push(_sliderFour); - - var _sliderFive = Overlays.addOverlay("image", { - bounds: { - x: 0, - y: 0, - width: 25, - height: 25 - }, - imageURL: pathToAssets + "overlay-images/ddao-slider-handle.png", - color: { - red: 255, - green: 255, - blue: 255 - }, - alpha: 1, - visible: false - }); - _sliderThumbOverlays.push(_sliderFive); - - var _sliderSix = Overlays.addOverlay("image", { - bounds: { - x: 0, - y: 0, - width: 25, - height: 25 - }, - imageURL: pathToAssets + "overlay-images/ddao-slider-handle.png", - color: { - red: 255, - green: 255, - blue: 255 - }, - alpha: 1, - visible: false - }); - _sliderThumbOverlays.push(_sliderSix); - - var _sliderSeven = Overlays.addOverlay("image", { - bounds: { - x: 0, - y: 0, - width: 25, - height: 25 - }, - imageURL: pathToAssets + "overlay-images/ddao-slider-handle.png", - color: { - red: 255, - green: 255, - blue: 255 - }, - alpha: 1, - visible: false - }); - _sliderThumbOverlays.push(_sliderSeven); - - var _sliderEight = Overlays.addOverlay("image", { - bounds: { - x: 0, - y: 0, - width: 25, - height: 25 - }, - imageURL: pathToAssets + "overlay-images/ddao-slider-handle.png", - color: { - red: 255, - green: 255, - blue: 255 - }, - alpha: 1, - visible: false - }); - _sliderThumbOverlays.push(_sliderEight); - - var _sliderNine = Overlays.addOverlay("image", { - bounds: { - x: 0, - y: 0, - width: 25, - height: 25 - }, - imageURL: pathToAssets + "overlay-images/ddao-slider-handle.png", - color: { - red: 255, - green: 255, - blue: 255 - }, - alpha: 1, - visible: false - }); - _sliderThumbOverlays.push(_sliderNine); - - - // button overlays - var _onButton = Overlays.addOverlay("image", { - bounds: { - x: _backgroundX + 20, - y: _backgroundY + _buttonsY, - width: 60, - height: 47 - }, - imageURL: pathToAssets + "overlay-images/ddao-on-button.png", - color: { - red: 255, - green: 255, - blue: 255 - }, - alpha: 1, - visible: false - }); - _buttonOverlays.push(_onButton); - - var _offButton = Overlays.addOverlay("image", { - bounds: { - x: _backgroundX + 20, - y: _backgroundY + _buttonsY, - width: 60, - height: 47 - }, - imageURL: pathToAssets + "overlay-images/ddao-off-button.png", - color: { - red: 255, - green: 255, - blue: 255 - }, - alpha: 1, - visible: false - }); - _buttonOverlays.push(_offButton); - - var _configWalkButton = Overlays.addOverlay("image", { - bounds: { - x: _backgroundX + 83, - y: _backgroundY + _buttonsY, - width: 60, - height: 47 - }, - imageURL: pathToAssets + "overlay-images/ddao-edit-walk-button.png", - color: { - red: 255, - green: 255, - blue: 255 - }, - alpha: 1, - visible: false - }); - _buttonOverlays.push(_configWalkButton); - - var _configWalkButtonSelected = Overlays.addOverlay("image", { - bounds: { - x: _backgroundX + 83, - y: _backgroundY + _buttonsY, - width: 60, - height: 47 - }, - imageURL: pathToAssets + "overlay-images/ddao-edit-walk-button-selected.png", - color: { - red: 255, - green: 255, - blue: 255 - }, - alpha: 1, - visible: false - }); - _buttonOverlays.push(_configWalkButtonSelected); - - var _configStandButton = Overlays.addOverlay("image", { - bounds: { - x: _backgroundX + 146, - y: _backgroundY + _buttonsY, - width: 60, - height: 47 - }, - imageURL: pathToAssets + "overlay-images/ddao-edit-stand-button.png", - color: { - red: 255, - green: 255, - blue: 255 - }, - alpha: 1, - visible: false - }); - _buttonOverlays.push(_configStandButton); - - var _configStandButtonSelected = Overlays.addOverlay("image", { - bounds: { - x: _backgroundX + 146, - y: _backgroundY + _buttonsY, - width: 60, - height: 47 - }, - imageURL: pathToAssets + "overlay-images/ddao-edit-stand-button-selected.png", - color: { - red: 255, - green: 255, - blue: 255 - }, - alpha: 1, - visible: false - }); - _buttonOverlays.push(_configStandButtonSelected); - - var _configFlyingButton = Overlays.addOverlay("image", { - bounds: { - x: _backgroundX + 209, - y: _backgroundY + _buttonsY, - width: 60, - height: 47 - }, - imageURL: pathToAssets + "overlay-images/ddao-edit-fly-button.png", - color: { - red: 255, - green: 255, - blue: 255 - }, - alpha: 1, - visible: false - }); - _buttonOverlays.push(_configFlyingButton); - - var _configFlyingButtonSelected = Overlays.addOverlay("image", { - bounds: { - x: _backgroundX + 209, - y: _backgroundY + _buttonsY, - width: 60, - height: 47 - }, - imageURL: pathToAssets + "overlay-images/ddao-edit-fly-button-selected.png", - color: { - red: 255, - green: 255, - blue: 255 - }, - alpha: 1, - visible: false - }); - _buttonOverlays.push(_configFlyingButtonSelected); - - var _configFlyingUpButton = Overlays.addOverlay("image", { - bounds: { - x: _backgroundX + 83, - y: _backgroundY + _buttonsY, - width: 60, - height: 47 - }, - imageURL: pathToAssets + "overlay-images/ddao-edit-fly-up-button.png", - color: { - red: 255, - green: 255, - blue: 255 - }, - alpha: 1, - visible: false - }); - _buttonOverlays.push(_configFlyingUpButton); - - var _configFlyingUpButtonSelected = Overlays.addOverlay("image", { - bounds: { - x: _backgroundX + 83, - y: _backgroundY + _buttonsY, - width: 60, - height: 47 - }, - imageURL: pathToAssets + "overlay-images/ddao-edit-fly-up-button-selected.png", - color: { - red: 255, - green: 255, - blue: 255 - }, - alpha: 1, - visible: false - }); - _buttonOverlays.push(_configFlyingUpButtonSelected); - - var _configFlyingDownButton = Overlays.addOverlay("image", { - bounds: { - x: _backgroundX + 146, - y: _backgroundY + _buttonsY, - width: 60, - height: 47 - }, - imageURL: pathToAssets + "overlay-images/ddao-edit-fly-down-button.png", - color: { - red: 255, - green: 255, - blue: 255 - }, - alpha: 1, - visible: false - }); - _buttonOverlays.push(_configFlyingDownButton); - - var _configFlyingDownButtonSelected = Overlays.addOverlay("image", { - bounds: { - x: _backgroundX + 146, - y: _backgroundY + _buttonsY, - width: 60, - height: 47 - }, - imageURL: pathToAssets + "overlay-images/ddao-edit-fly-down-button-selected.png", - color: { - red: 255, - green: 255, - blue: 255 - }, - alpha: 1, - visible: false - }); - _buttonOverlays.push(_configFlyingDownButtonSelected); - - var _hideButton = Overlays.addOverlay("image", { - bounds: { - x: _backgroundX + 272, - y: _backgroundY + _buttonsY, - width: 60, - height: 47 - }, - imageURL: pathToAssets + "overlay-images/ddao-hide-button.png", - color: { - red: 255, - green: 255, - blue: 255 - }, - alpha: 1, - visible: false - }); - _buttonOverlays.push(_hideButton); - - var _hideButtonSelected = Overlays.addOverlay("image", { - bounds: { - x: _backgroundX + 272, - y: _backgroundY + _buttonsY, - width: 60, - height: 47 - }, - imageURL: pathToAssets + "overlay-images/ddao-hide-button-selected.png", - color: { - red: 255, - green: 255, - blue: 255 - }, - alpha: 1, - visible: false - }); - _buttonOverlays.push(_hideButtonSelected); - - var _configWalkStylesButton = Overlays.addOverlay("image", { - bounds: { - x: _backgroundX + 83, - y: _backgroundY + _buttonsY, - width: 60, - height: 47 - }, - imageURL: pathToAssets + "overlay-images/ddao-walk-styles-button.png", - color: { - red: 255, - green: 255, - blue: 255 - }, - alpha: 1, - visible: false - }); - _buttonOverlays.push(_configWalkStylesButton); - - var _configWalkStylesButtonSelected = Overlays.addOverlay("image", { - bounds: { - x: _backgroundX + 83, - y: _backgroundY + _buttonsY, - width: 60, - height: 47 - }, - imageURL: pathToAssets + "overlay-images/ddao-walk-styles-button-selected.png", - color: { - red: 255, - green: 255, - blue: 255 - }, - alpha: 1, - visible: false - }); - _buttonOverlays.push(_configWalkStylesButtonSelected); - - var _configWalkTweaksButton = Overlays.addOverlay("image", { - bounds: { - x: _backgroundX + 146, - y: _backgroundY + _buttonsY, - width: 60, - height: 47 - }, - imageURL: pathToAssets + "overlay-images/ddao-walk-tweaks-button.png", - color: { - red: 255, - green: 255, - blue: 255 - }, - alpha: 1, - visible: false - }); - _buttonOverlays.push(_configWalkTweaksButton); - - var _configWalkTweaksButtonSelected = Overlays.addOverlay("image", { - bounds: { - x: _backgroundX + 146, - y: _backgroundY + _buttonsY, - width: 60, - height: 47 - }, - imageURL: pathToAssets + "overlay-images/ddao-walk-tweaks-button-selected.png", - color: { - red: 255, - green: 255, - blue: 255 - }, - alpha: 1, - visible: false - }); - _buttonOverlays.push(_configWalkTweaksButtonSelected); - - var _configSideStepLeftButton = Overlays.addOverlay("image", { - bounds: { - x: _backgroundX + 83, - y: _backgroundY + _buttonsY, - width: 60, - height: 47 - }, - imageURL: pathToAssets + "overlay-images/ddao-edit-sidestep-left-button.png", - color: { - red: 255, - green: 255, - blue: 255 - }, - alpha: 1, - visible: false - }); - _buttonOverlays.push(_configSideStepLeftButton); - - var _configSideStepLeftButtonSelected = Overlays.addOverlay("image", { - bounds: { - x: _backgroundX + 83, - y: _backgroundY + _buttonsY, - width: 60, - height: 47 - }, - imageURL: pathToAssets + "overlay-images/ddao-edit-sidestep-left-button-selected.png", - color: { - red: 255, - green: 255, - blue: 255 - }, - alpha: 1, - visible: false - }); - _buttonOverlays.push(_configSideStepLeftButtonSelected); - - var _configSideStepRightButton = Overlays.addOverlay("image", { - bounds: { - x: _backgroundX + 209, - y: _backgroundY + _buttonsY, - width: 60, - height: 47 - }, - imageURL: pathToAssets + "overlay-images/ddao-edit-sidestep-right-button.png", - color: { - red: 255, - green: 255, - blue: 255 - }, - alpha: 1, - visible: false - }); - _buttonOverlays.push(_configSideStepRightButton); - - var _configSideStepRightButtonSelected = Overlays.addOverlay("image", { - bounds: { - x: _backgroundX + 209, - y: _backgroundY + _buttonsY, - width: 60, - height: 47 - }, - imageURL: pathToAssets + "overlay-images/ddao-edit-sidestep-right-button-selected.png", - color: { - red: 255, - green: 255, - blue: 255 - }, - alpha: 1, - visible: false - }); - _buttonOverlays.push(_configSideStepRightButtonSelected); - - var _configWalkJointsButton = Overlays.addOverlay("image", { - bounds: { - x: _backgroundX + 209, - y: _backgroundY + _buttonsY, - width: 60, - height: 47 - }, - imageURL: pathToAssets + "overlay-images/ddao-joints-button.png", - color: { - red: 255, - green: 255, - blue: 255 - }, - alpha: 1, - visible: false - }); - _buttonOverlays.push(_configWalkJointsButton); - - var _configWalkJointsButtonSelected = Overlays.addOverlay("image", { - bounds: { - x: _backgroundX + 209, - y: _backgroundY + _buttonsY, - width: 60, - height: 47 - }, - imageURL: pathToAssets + "overlay-images/ddao-joints-button-selected.png", - color: { - red: 255, - green: 255, - blue: 255 - }, - alpha: 1, - visible: false - }); - _buttonOverlays.push(_configWalkJointsButtonSelected); - - var _backButton = Overlays.addOverlay("image", { - bounds: { - x: _backgroundX + 272, - y: _backgroundY + _buttonsY, - width: 60, - height: 47 - }, - imageURL: pathToAssets + "overlay-images/ddao-back-button.png", - color: { - red: 255, - green: 255, - blue: 255 - }, - alpha: 1, - visible: false - }); - _buttonOverlays.push(_backButton); - - var _backButtonSelected = Overlays.addOverlay("image", { - bounds: { - x: _backgroundX + 272, - y: _backgroundY + _buttonsY, - width: 60, - height: 47 - }, - imageURL: pathToAssets + "overlay-images/ddao-back-button-selected.png", - color: { - red: 255, - green: 255, - blue: 255 - }, - alpha: 1, - visible: false - }); - _buttonOverlays.push(_backButtonSelected); - - // big button overlays - front panel - var _femaleBigButton = Overlays.addOverlay("image", { - bounds: { - x: _backgroundX + _backgroundWidth / 2 - 115, - y: _backgroundY + _bigButtonsY, - width: 230, - height: 36 - }, - imageURL: pathToAssets + "overlay-images/ddao-female-big-button.png", - color: { - red: 255, - green: 255, - blue: 255 - }, - alpha: 1, - visible: false - }); - _bigbuttonOverlays.push(_femaleBigButton); - - var _femaleBigButtonSelected = Overlays.addOverlay("image", { - bounds: { - x: _backgroundX + _backgroundWidth / 2 - 115, - y: _backgroundY + _bigButtonsY, - width: 230, - height: 36 - }, - imageURL: pathToAssets + "overlay-images/ddao-female-big-button-selected.png", - color: { - red: 255, - green: 255, - blue: 255 - }, - alpha: 1, - visible: false - }); - _bigbuttonOverlays.push(_femaleBigButtonSelected); - - var _maleBigButton = Overlays.addOverlay("image", { - bounds: { - x: _backgroundX + _backgroundWidth / 2 - 115, - y: _backgroundY + _bigButtonsY + 60, - width: 230, - height: 36 - }, - imageURL: pathToAssets + "overlay-images/ddao-male-big-button.png", - color: { - red: 255, - green: 255, - blue: 255 - }, - alpha: 1, - visible: false - }); - _bigbuttonOverlays.push(_maleBigButton); - - var _maleBigButtonSelected = Overlays.addOverlay("image", { - bounds: { - x: _backgroundX + _backgroundWidth / 2 - 115, - y: _backgroundY + _bigButtonsY + 60, - width: 230, - height: 36 - }, - imageURL: pathToAssets + "overlay-images/ddao-male-big-button-selected.png", - color: { - red: 255, - green: 255, - blue: 255 - }, - alpha: 1, - visible: false - }); - _bigbuttonOverlays.push(_maleBigButtonSelected); - - var _armsFreeBigButton = Overlays.addOverlay("image", { - bounds: { - x: _backgroundX + _backgroundWidth / 2 - 115, - y: _backgroundY + _bigButtonsY + 120, - width: 230, - height: 36 - }, - imageURL: pathToAssets + "overlay-images/ddao-arms-free-button.png", - color: { - red: 255, - green: 255, - blue: 255 - }, - alpha: 1, - visible: false - }); - _bigbuttonOverlays.push(_armsFreeBigButton); - - var _armsFreeBigButtonSelected = Overlays.addOverlay("image", { - bounds: { - x: _backgroundX + _backgroundWidth / 2 - 115, - y: _backgroundY + _bigButtonsY + 120, - width: 230, - height: 36 - }, - imageURL: pathToAssets + "overlay-images/ddao-arms-free-button-selected.png", - color: { - red: 255, - green: 255, - blue: 255 - }, - alpha: 1, - visible: false - }); - _bigbuttonOverlays.push(_armsFreeBigButtonSelected); - - var _footstepsBigButton = Overlays.addOverlay("image", { - bounds: { - x: _backgroundX + _backgroundWidth / 2 - 115, - y: _backgroundY + _bigButtonsY + 180, - width: 230, - height: 36 - }, - imageURL: pathToAssets + "overlay-images/ddao-footsteps-big-button.png", - color: { - red: 255, - green: 255, - blue: 255 - }, - alpha: 1, - visible: false - }); - _bigbuttonOverlays.push(_footstepsBigButton); - - var _footstepsBigButtonSelected = Overlays.addOverlay("image", { - bounds: { - x: _backgroundX + _backgroundWidth / 2 - 115, - y: _backgroundY + _bigButtonsY + 180, - width: 230, - height: 36 - }, - imageURL: pathToAssets + "overlay-images/ddao-footsteps-big-button-selected.png", - color: { - red: 255, - green: 255, - blue: 255 - }, - alpha: 1, - visible: false - }); - _bigbuttonOverlays.push(_footstepsBigButtonSelected); - - - // walk styles - _bigButtonsY = 121; - var _standardWalkBigButton = Overlays.addOverlay("image", { - bounds: { - x: _backgroundX + _backgroundWidth / 2 - 115, - y: _backgroundY + _bigButtonsY, - width: 230, - height: 36 - }, - imageURL: pathToAssets + "overlay-images/ddao-walk-select-button-standard.png", - color: { - red: 255, - green: 255, - blue: 255 - }, - alpha: 1, - visible: false - }); - _bigbuttonOverlays.push(_standardWalkBigButton); - - var _standardWalkBigButtonSelected = Overlays.addOverlay("image", { - bounds: { - x: _backgroundX + _backgroundWidth / 2 - 115, - y: _backgroundY + _bigButtonsY, - width: 230, - height: 36 - }, - imageURL: pathToAssets + "overlay-images/ddao-walk-select-button-standard-selected.png", - color: { - red: 255, - green: 255, - blue: 255 - }, - alpha: 1, - visible: false - }); - _bigbuttonOverlays.push(_standardWalkBigButtonSelected); - - // various show / hide GUI element functions - function minimiseDialog(minimise) { - - if (momentaryButtonTimer) { - Script.clearInterval(momentaryButtonTimer); - momentaryButtonTimer = null; - } - - if (minimise) { - setBackground(); - hideMenuButtons(); - setSliderThumbsVisible(false); - hideJointSelectors(); - initialiseFrontPanel(false); - Overlays.editOverlay(_controlsMinimisedTab, { - visible: true - }); - } else { - Overlays.editOverlay(_controlsMinimisedTab, { - visible: false - }); - } - }; - - function setBackground(backgroundID) { - for (var i in _backgroundOverlays) { - if (_backgroundOverlays[i] === backgroundID) { - Overlays.editOverlay(_backgroundOverlays[i], { - visible: true - }); - } else { - Overlays.editOverlay(_backgroundOverlays[i], { visible: false }); - } - } - }; - - // top row menu type buttons (on | walk | stand | fly | hide) - function hideMenuButtons() { - for (var i in _buttonOverlays) { - Overlays.editOverlay(_buttonOverlays[i], { visible: false }); - } - }; - - function hideJointSelectors() { - for (var i in _jointsControlOverlays) { - Overlays.editOverlay(_jointsControlOverlays[i], { - visible: false - }); - } - }; - - function setSliderThumbsVisible(thumbsVisible) { - for (var i = 0; i < _sliderThumbOverlays.length; i++) { - Overlays.editOverlay(_sliderThumbOverlays[i], { - visible: thumbsVisible - }); - } - }; - - function setButtonOverlayVisible(buttonOverlayName) { - for (var i in _buttonOverlays) { - if (_buttonOverlays[i] === buttonOverlayName) { - Overlays.editOverlay(buttonOverlayName, { visible: true }); - } - } - }; - - function initialiseFrontPanel(showButtons) { - - if (_motion.avatarGender === FEMALE) { - Overlays.editOverlay(_femaleBigButtonSelected, { - visible: showButtons - }); - Overlays.editOverlay(_femaleBigButton, { - visible: false - }); - Overlays.editOverlay(_maleBigButtonSelected, { - visible: false - }); - Overlays.editOverlay(_maleBigButton, { - visible: showButtons - }); - - } else { - - Overlays.editOverlay(_femaleBigButtonSelected, { - visible: false - }); - Overlays.editOverlay(_femaleBigButton, { - visible: showButtons - }); - Overlays.editOverlay(_maleBigButtonSelected, { - visible: showButtons - }); - Overlays.editOverlay(_maleBigButton, { - visible: false - }); - } - if (_motion.armsFree) { - Overlays.editOverlay(_armsFreeBigButtonSelected, { - visible: showButtons - }); - Overlays.editOverlay(_armsFreeBigButton, { - visible: false - }); - - } else { - - Overlays.editOverlay(_armsFreeBigButtonSelected, { - visible: false - }); - Overlays.editOverlay(_armsFreeBigButton, { - visible: showButtons - }); - } - if (_motion.makesFootStepSounds) { - Overlays.editOverlay(_footstepsBigButtonSelected, { - visible: showButtons - }); - Overlays.editOverlay(_footstepsBigButton, { - visible: false - }); - - } else { - - Overlays.editOverlay(_footstepsBigButtonSelected, { - visible: false - }); - Overlays.editOverlay(_footstepsBigButton, { - visible: showButtons - }); - } - }; - - function initialiseWalkStylesPanel(showButtons) { - - // set all big buttons to hidden, but skip the first 8, as are used by the front panel - for (var i = 8; i < _bigbuttonOverlays.length; i++) { - Overlays.editOverlay(_bigbuttonOverlays[i], { - visible: false - }); - } - - if (!showButtons) { - return; - } - - // set all the non-selected ones to showing - for (var i = 8; i < _bigbuttonOverlays.length; i += 2) { - Overlays.editOverlay(_bigbuttonOverlays[i], { visible: true }); - } - - // set the currently selected one - if (_motion.selWalk === _walkAssets.femaleStandardWalk || - _motion.selWalk === _walkAssets.maleStandardWalk) { - - Overlays.editOverlay(_standardWalkBigButtonSelected, { - visible: true - }); - Overlays.editOverlay(_standardWalkBigButton, { - visible: false - }); - } - }; - - function initialiseWalkTweaksPanel() { - - // sliders for commonly required walk adjustments - var i = 0; - var yLocation = _backgroundY + 71; - - // walk speed - var sliderXPos = _motion.curAnim.calibration.frequency / MAX_WALK_SPEED * _sliderRangeX; - Overlays.editOverlay(_sliderThumbOverlays[i], { - x: _minSliderX + sliderXPos, - y: yLocation += 60, - visible: true - }); - - // lean (hips pitch offset) - sliderXPos = (((_sliderRanges.joints[0].pitchOffsetRange + _motion.curAnim.joints[0].pitchOffset) / 2) / - _sliderRanges.joints[0].pitchOffsetRange) * _sliderRangeX; - Overlays.editOverlay(_sliderThumbOverlays[++i], { - x: _minSliderX + sliderXPos, - y: yLocation += 60, - visible: true - }); - - // stride (upper legs pitch) - sliderXPos = _motion.curAnim.joints[1].pitch / _sliderRanges.joints[1].pitchRange * _sliderRangeX; - Overlays.editOverlay(_sliderThumbOverlays[++i], { - x: _minSliderX + sliderXPos, - y: yLocation += 60, - visible: true - }); - - // Legs separation (upper legs roll offset) - sliderXPos = (((_sliderRanges.joints[1].rollOffsetRange + _motion.curAnim.joints[1].rollOffset) / 2) / - _sliderRanges.joints[1].rollOffsetRange) * _sliderRangeX; - Overlays.editOverlay(_sliderThumbOverlays[++i], { - x: _minSliderX + sliderXPos, - y: yLocation += 60, - visible: true - }); - - // Legs forward (upper legs pitch offset) - sliderXPos = (((_sliderRanges.joints[1].pitchOffsetRange + _motion.curAnim.joints[1].pitchOffset) / 2) / - _sliderRanges.joints[1].pitchOffsetRange) * _sliderRangeX; - Overlays.editOverlay(_sliderThumbOverlays[++i], { - x: _minSliderX + sliderXPos, - y: yLocation += 60, - visible: true - }); - - // Lower legs splay (lower legs roll offset) - sliderXPos = (((_sliderRanges.joints[2].rollOffsetRange + _motion.curAnim.joints[2].rollOffset) / 2) / - _sliderRanges.joints[2].rollOffsetRange) * _sliderRangeX; - Overlays.editOverlay(_sliderThumbOverlays[++i], { - x: _minSliderX + sliderXPos, - y: yLocation += 60, - visible: true - }); - - // Arms forward (upper arms yaw offset) - sliderXPos = (((_sliderRanges.joints[9].yawOffsetRange + _motion.curAnim.joints[9].yawOffset) / 2) / - _sliderRanges.joints[9].yawOffsetRange) * _sliderRangeX; - Overlays.editOverlay(_sliderThumbOverlays[++i], { - x: _minSliderX + sliderXPos, - y: yLocation += 60, - visible: true - }); - - // Arms out (upper arm pitch offset) - sliderXPos = (((_sliderRanges.joints[9].pitchOffsetRange - _motion.curAnim.joints[9].pitchOffset) / 2) / - _sliderRanges.joints[9].pitchOffsetRange) * _sliderRangeX; - Overlays.editOverlay(_sliderThumbOverlays[++i], { - x: _minSliderX + sliderXPos, - y: yLocation += 60, - visible: true - }); - - // Lower arms splay (lower arm pitch offset) - sliderXPos = (((_sliderRanges.joints[10].pitchOffsetRange - _motion.curAnim.joints[10].pitchOffset) / 2) / - _sliderRanges.joints[10].pitchOffsetRange) * _sliderRangeX; - Overlays.editOverlay(_sliderThumbOverlays[++i], { - x: _minSliderX + sliderXPos, - y: yLocation += 60, - visible: true - }); - }; - - function initialiseJointsEditingPanel() { - - var i = 0; - var yLocation = _backgroundY + 359; - hideJointSelectors(); - - if (_state.editingTranslation) { - - // display the joint control selector for hips translations - Overlays.editOverlay(_hipsJointsTranslation, {visible: true}); - - // Hips sway - var sliderXPos = _motion.curAnim.joints[0].sway / _sliderRanges.joints[0].swayRange * _sliderRangeX; - Overlays.editOverlay(_sliderThumbOverlays[i], { - x: _minSliderX + sliderXPos, - y: yLocation += 30, - visible: true - }); - - // Hips bob - sliderXPos = _motion.curAnim.joints[0].bob / _sliderRanges.joints[0].bobRange * _sliderRangeX; - Overlays.editOverlay(_sliderThumbOverlays[++i], { - x: _minSliderX + sliderXPos, - y: yLocation += 30, - visible: true - }); - - // Hips thrust - sliderXPos = _motion.curAnim.joints[0].thrust / _sliderRanges.joints[0].thrustRange * _sliderRangeX; - Overlays.editOverlay(_sliderThumbOverlays[++i], { - x: _minSliderX + sliderXPos, - y: yLocation += 30, - visible: true - }); - - // Sway Phase - sliderXPos = (90 + _motion.curAnim.joints[0].swayPhase / 2) / 180 * _sliderRangeX; - Overlays.editOverlay(_sliderThumbOverlays[++i], { - x: _minSliderX + sliderXPos, - y: yLocation += 30, - visible: true - }); - - // Bob Phase - sliderXPos = (90 + _motion.curAnim.joints[0].bobPhase / 2) / 180 * _sliderRangeX; - Overlays.editOverlay(_sliderThumbOverlays[++i], { - x: _minSliderX + sliderXPos, - y: yLocation += 30, - visible: true - }); - - // Thrust Phase - sliderXPos = (90 + _motion.curAnim.joints[0].thrustPhase / 2) / 180 * _sliderRangeX; - Overlays.editOverlay(_sliderThumbOverlays[++i], { - x: _minSliderX + sliderXPos, - y: yLocation += 30, - visible: true - }); - - // offset ranges are also -ve thr' zero to +ve, so we centre them - sliderXPos = (((_sliderRanges.joints[0].swayOffsetRange + _motion.curAnim.joints[0] - .swayOffset) / 2) / _sliderRanges.joints[0].swayOffsetRange) * _sliderRangeX; - Overlays.editOverlay(_sliderThumbOverlays[++i], { - x: _minSliderX + sliderXPos, - y: yLocation += 30, - visible: true - }); - - sliderXPos = (((_sliderRanges.joints[0].bobOffsetRange + _motion.curAnim.joints[0] - .bobOffset) / 2) / _sliderRanges.joints[0].bobOffsetRange) * _sliderRangeX; - Overlays.editOverlay(_sliderThumbOverlays[++i], { - x: _minSliderX + sliderXPos, - y: yLocation += 30, - visible: true - }); - - sliderXPos = (((_sliderRanges.joints[0].thrustOffsetRange + _motion.curAnim.joints[0] - .thrustOffset) / 2) / _sliderRanges.joints[0].thrustOffsetRange) * _sliderRangeX; - Overlays.editOverlay(_sliderThumbOverlays[++i], { - x: _minSliderX + sliderXPos, - y: yLocation += 30, - visible: true - }); - - } else { - - switch (_motion.curJointIndex) { - - case 0: - Overlays.editOverlay(_hipsJointControl, { - visible: true - }); - break; - case 1: - Overlays.editOverlay(_upperLegsJointControl, { - visible: true - }); - break; - case 2: - Overlays.editOverlay(_lowerLegsJointControl, { - visible: true - }); - break; - case 3: - Overlays.editOverlay(_feetJointControl, { - visible: true - }); - break; - case 4: - Overlays.editOverlay(_toesJointControl, { - visible: true - }); - break; - case 5: - Overlays.editOverlay(_spineJointControl, { - visible: true - }); - break; - case 6: - Overlays.editOverlay(_spine1JointControl, { - visible: true - }); - break; - case 7: - Overlays.editOverlay(_spine2JointControl, { - visible: true - }); - break; - case 8: - Overlays.editOverlay(_shouldersJointControl, { - visible: true - }); - break; - case 9: - Overlays.editOverlay(_upperArmsJointControl, { - visible: true - }); - break; - case 10: - Overlays.editOverlay(_forearmsJointControl, { - visible: true - }); - break; - case 11: - Overlays.editOverlay(_handsJointControl, { - visible: true - }); - break; - case 12: - Overlays.editOverlay(_headJointControl, { - visible: true - }); - break; - } - - var sliderXPos = _motion.curAnim.joints[_motion.curJointIndex].pitch / - _sliderRanges.joints[_motion.curJointIndex].pitchRange * _sliderRangeX; - Overlays.editOverlay(_sliderThumbOverlays[i], { - x: _minSliderX + sliderXPos, - y: yLocation += 30, - visible: true - }); - - sliderXPos = _motion.curAnim.joints[_motion.curJointIndex].yaw / - _sliderRanges.joints[_motion.curJointIndex].yawRange * _sliderRangeX; - Overlays.editOverlay(_sliderThumbOverlays[++i], { - x: _minSliderX + sliderXPos, - y: yLocation += 30, - visible: true - }); - - sliderXPos = _motion.curAnim.joints[_motion.curJointIndex].roll / - _sliderRanges.joints[_motion.curJointIndex].rollRange * _sliderRangeX; - Overlays.editOverlay(_sliderThumbOverlays[++i], { - x: _minSliderX + sliderXPos, - y: yLocation += 30, - visible: true - }); - - // set phases (full range, -180 to 180) - sliderXPos = (90 + _motion.curAnim.joints[_motion.curJointIndex].pitchPhase / 2) / 180 * _sliderRangeX; - Overlays.editOverlay(_sliderThumbOverlays[++i], { - x: _minSliderX + sliderXPos, - y: yLocation += 30, - visible: true - }); - - sliderXPos = (90 + _motion.curAnim.joints[_motion.curJointIndex].yawPhase / 2) / 180 * _sliderRangeX; - Overlays.editOverlay(_sliderThumbOverlays[++i], { - x: _minSliderX + sliderXPos, - y: yLocation += 30, - visible: true - }); - - sliderXPos = (90 + _motion.curAnim.joints[_motion.curJointIndex].rollPhase / 2) / 180 * _sliderRangeX; - Overlays.editOverlay(_sliderThumbOverlays[++i], { - x: _minSliderX + sliderXPos, - y: yLocation += 30, - visible: true - }); - - // offset ranges are also -ve thr' zero to +ve, so we offset - sliderXPos = (((_sliderRanges.joints[_motion.curJointIndex].pitchOffsetRange + - _motion.curAnim.joints[_motion.curJointIndex].pitchOffset) / 2) / - _sliderRanges.joints[_motion.curJointIndex].pitchOffsetRange) * _sliderRangeX; - Overlays.editOverlay(_sliderThumbOverlays[++i], { - x: _minSliderX + sliderXPos, - y: yLocation += 30, - visible: true - }); - - sliderXPos = (((_sliderRanges.joints[_motion.curJointIndex].yawOffsetRange + - _motion.curAnim.joints[_motion.curJointIndex].yawOffset) / 2) / - _sliderRanges.joints[_motion.curJointIndex].yawOffsetRange) * _sliderRangeX; - Overlays.editOverlay(_sliderThumbOverlays[++i], { - x: _minSliderX + sliderXPos, - y: yLocation += 30, - visible: true - }); - - sliderXPos = (((_sliderRanges.joints[_motion.curJointIndex].rollOffsetRange + - _motion.curAnim.joints[_motion.curJointIndex].rollOffset) / 2) / - _sliderRanges.joints[_motion.curJointIndex].rollOffsetRange) * _sliderRangeX; - Overlays.editOverlay(_sliderThumbOverlays[++i], { - x: _minSliderX + sliderXPos, - y: yLocation += 30, - visible: true - }); - } - }; - - // mouse event handlers - var _movingSliderOne = false; - var _movingSliderTwo = false; - var _movingSliderThree = false; - var _movingSliderFour = false; - var _movingSliderFive = false; - var _movingSliderSix = false; - var _movingSliderSeven = false; - var _movingSliderEight = false; - var _movingSliderNine = false; - - function mousePressEvent(event) { - - var clickedOverlay = Overlays.getOverlayAtPoint({ - x: event.x, - y: event.y - }); - - if (_state.currentState === _state.EDIT_WALK_JOINTS || - _state.currentState === _state.EDIT_STANDING || - _state.currentState === _state.EDIT_FLYING || - _state.currentState === _state.EDIT_FLYING_UP || - _state.currentState === _state.EDIT_FLYING_DOWN || - _state.currentState === _state.EDIT_SIDESTEP_LEFT || - _state.currentState === _state.EDIT_SIDESTEP_RIGHT) { - - // check for new joint selection and update display accordingly - var clickX = event.x - _backgroundX - 75; - var clickY = event.y - _backgroundY - 92; - - if (clickX > 60 && clickX < 120 && clickY > 123 && clickY < 155) { - _motion.curJointIndex = 0; - initialiseJointsEditingPanel(); - return; - - } else if (clickX > 63 && clickX < 132 && clickY > 156 && clickY < 202) { - _motion.curJointIndex = 1; - initialiseJointsEditingPanel(); - return; - - } else if (clickX > 58 && clickX < 137 && clickY > 203 && clickY < 250) { - _motion.curJointIndex = 2; - initialiseJointsEditingPanel(); - return; - - } else if (clickX > 58 && clickX < 137 && clickY > 250 && clickY < 265) { - _motion.curJointIndex = 3; - initialiseJointsEditingPanel(); - return; - - } else if (clickX > 58 && clickX < 137 && clickY > 265 && clickY < 280) { - _motion.curJointIndex = 4; - initialiseJointsEditingPanel(); - return; - - } else if (clickX > 78 && clickX < 121 && clickY > 111 && clickY < 128) { - _motion.curJointIndex = 5; - initialiseJointsEditingPanel(); - return; - - } else if (clickX > 78 && clickX < 128 && clickY > 89 && clickY < 111) { - _motion.curJointIndex = 6; - initialiseJointsEditingPanel(); - return; - - } else if (clickX > 85 && clickX < 118 && clickY > 77 && clickY < 94) { - _motion.curJointIndex = 7; - initialiseJointsEditingPanel(); - return; - - } else if (clickX > 64 && clickX < 125 && clickY > 55 && clickY < 77) { - _motion.curJointIndex = 8; - initialiseJointsEditingPanel(); - return; - - } else if ((clickX > 44 && clickX < 73 && clickY > 71 && clickY < 94) || - (clickX > 125 && clickX < 144 && clickY > 71 && clickY < 94)) { - _motion.curJointIndex = 9; - initialiseJointsEditingPanel(); - return; - - } else if ((clickX > 28 && clickX < 57 && clickY > 94 && clickY < 119) || - (clickX > 137 && clickX < 170 && clickY > 97 && clickY < 114)) { - _motion.curJointIndex = 10; - initialiseJointsEditingPanel(); - return; - - } else if ((clickX > 18 && clickX < 37 && clickY > 115 && clickY < 136) || - (clickX > 157 && clickX < 182 && clickY > 115 && clickY < 136)) { - _motion.curJointIndex = 11; - initialiseJointsEditingPanel(); - return; - - } else if (clickX > 81 && clickX < 116 && clickY > 12 && clickY < 53) { - _motion.curJointIndex = 12; - initialiseJointsEditingPanel(); - return; - - } else if (clickX > 188 && clickX < 233 && clickY > 6 && clickY < 34) { - - // translation editing radio selection - if (_state.editingTranslation) { - - hideJointSelectors(); - setBackground(_controlsBackgroundWalkEditJoints); - _state.editingTranslation = false; - - } else { - - hideJointSelectors(); - setBackground(_controlsBackgroundWalkEditHipTrans); - _state.editingTranslation = true; - } - initialiseJointsEditingPanel(); - return; - } - } - - switch (clickedOverlay) { - - case _offButton: - - _state.powerOn = true; - Overlays.editOverlay(_offButton, { - visible: false - }); - Overlays.editOverlay(_onButton, { - visible: true - }); - _state.setInternalState(state.STANDING); - return; - - case _controlsMinimisedTab: - - _state.minimised = false; - minimiseDialog(_state.minimised); - _state.setInternalState(_state.STANDING); - return; - - case _hideButton: - case _hideButtonSelected: - - Overlays.editOverlay(_hideButton, {visible: false}); - Overlays.editOverlay(_hideButtonSelected, {visible: true}); - _state.minimised = true; - momentaryButtonTimer = Script.setInterval(function() { - minimiseDialog(_state.minimised); - }, 80); - return; - - case _backButton: - - Overlays.editOverlay(_backButton, { - visible: false - }); - Overlays.editOverlay(_backButtonSelected, { - visible: true - }); - momentaryButtonTimer = Script.setInterval(function() { - - _state.setInternalState(_state.STANDING); - Overlays.editOverlay(_backButton, { - visible: false - }); - Overlays.editOverlay(_backButtonSelected, { - visible: false - }); - Script.clearInterval(momentaryButtonTimer); - momentaryButtonTimer = null; - }, 80); - return; - - case _footstepsBigButton: - - _motion.makesFootStepSounds = true; - Overlays.editOverlay(_footstepsBigButtonSelected, { - visible: true - }); - Overlays.editOverlay(_footstepsBigButton, { - visible: false - }); - return; - - case _footstepsBigButtonSelected: - - _motion.makesFootStepSounds = false; - Overlays.editOverlay(_footstepsBigButton, { - visible: true - }); - Overlays.editOverlay(_footstepsBigButtonSelected, { - visible: false - }); - return; - - case _femaleBigButton: - case _maleBigButtonSelected: - - _motion.setGender(FEMALE); - - Overlays.editOverlay(_femaleBigButtonSelected, { - visible: true - }); - Overlays.editOverlay(_femaleBigButton, { - visible: false - }); - Overlays.editOverlay(_maleBigButton, { - visible: true - }); - Overlays.editOverlay(_maleBigButtonSelected, { - visible: false - }); - return; - - case _maleBigButton: - case _femaleBigButtonSelected: - - _motion.setGender(MALE); - - Overlays.editOverlay(_femaleBigButton, { - visible: true - }); - Overlays.editOverlay(_femaleBigButtonSelected, { - visible: false - }); - Overlays.editOverlay(_maleBigButtonSelected, { - visible: true - }); - Overlays.editOverlay(_maleBigButton, { - visible: false - }); - return; - - case _armsFreeBigButton: - - _motion.armsFree = true; - - Overlays.editOverlay(_armsFreeBigButtonSelected, { - visible: true - }); - Overlays.editOverlay(_armsFreeBigButton, { - visible: false - }); - return; - - case _armsFreeBigButtonSelected: - - _motion.armsFree = false; - - Overlays.editOverlay(_armsFreeBigButtonSelected, { - visible: false - }); - Overlays.editOverlay(_armsFreeBigButton, { - visible: true - }); - return; - - case _standardWalkBigButton: - - if (_motion.avatarGender === FEMALE) { - _motion.selWalk = _motion.femaleStandardWalk; - } else { - _motion.selWalk = _motion.maleStandardWalk; - } - _motion.curAnim = _motion.selWalk; - initialiseWalkStylesPanel(true); - return; - - case _standardWalkBigButtonSelected: - - // toggle forwards / backwards walk display - if (_motion.direction === FORWARDS) { - _motion.direction = BACKWARDS; - } else { - _motion.direction = FORWARDS; - } - return; - - case _sliderOne: - - _movingSliderOne = true; - return; - - case _sliderTwo: - - _movingSliderTwo = true; - return; - - case _sliderThree: - - _movingSliderThree = true; - return; - - case _sliderFour: - - _movingSliderFour = true; - return; - - case _sliderFive: - - _movingSliderFive = true; - return; - - case _sliderSix: - - _movingSliderSix = true; - return; - - case _sliderSeven: - - _movingSliderSeven = true; - return; - - case _sliderEight: - - _movingSliderEight = true; - return; - - case _sliderNine: - - _movingSliderNine = true; - return; - - case _configWalkButtonSelected: - case _configStandButtonSelected: - case _configSideStepLeftButtonSelected: - case _configSideStepRightButtonSelected: - case _configFlyingButtonSelected: - case _configFlyingUpButtonSelected: - case _configFlyingDownButtonSelected: - case _configWalkStylesButtonSelected: - case _configWalkTweaksButtonSelected: - case _configWalkJointsButtonSelected: - - // exit edit modes - _motion.curAnim = _motion.selStand; - _state.setInternalState(_state.STANDING); - return; - - case _onButton: - - _state.powerOn = false; - _state.setInternalState(state.STANDING); - Overlays.editOverlay(_offButton, { - visible: true - }); - Overlays.editOverlay(_onButton, { - visible: false - }); - return; - - case _backButton: - case _backButtonSelected: - - Overlays.editOverlay(_backButton, { - visible: false - }); - Overlays.editOverlay(_backButtonSelected, { - visible: false - }); - _state.setInternalState(_state.STANDING); - return; - - case _configWalkStylesButton: - - _state.setInternalState(_state.EDIT_WALK_STYLES); - return; - - case _configWalkTweaksButton: - - _state.setInternalState(_state.EDIT_WALK_TWEAKS); - return; - - case _configWalkJointsButton: - - _state.setInternalState(_state.EDIT_WALK_JOINTS); - return; - - case _configWalkButton: - - _state.setInternalState(_state.EDIT_WALK_STYLES); - return; - - case _configStandButton: - - _state.setInternalState(_state.EDIT_STANDING); - return; - - case _configSideStepLeftButton: - - _state.setInternalState(_state.EDIT_SIDESTEP_LEFT); - return; - - case _configSideStepRightButton: - - _state.setInternalState(_state.EDIT_SIDESTEP_RIGHT); - return; - - case _configFlyingButton: - - _state.setInternalState(_state.EDIT_FLYING); - return; - - case _configFlyingUpButton: - - _state.setInternalState(_state.EDIT_FLYING_UP); - return; - - case _configFlyingDownButton: - - _state.setInternalState(_state.EDIT_FLYING_DOWN); - return; - } - }; - - function mouseMoveEvent(event) { - - // workaround for bug (https://worklist.net/20160) - if ((event.x > 310 && event.x < 318 && event.y > 1350 && event.y < 1355) || - (event.x > 423 && event.x < 428 && event.y > 1505 && event.y < 1508 )) { - return; - } - - if (_state.currentState === _state.EDIT_WALK_JOINTS || - _state.currentState === _state.EDIT_STANDING || - _state.currentState === _state.EDIT_FLYING || - _state.currentState === _state.EDIT_FLYING_UP || - _state.currentState === _state.EDIT_FLYING_DOWN || - _state.currentState === _state.EDIT_SIDESTEP_LEFT || - _state.currentState === _state.EDIT_SIDESTEP_RIGHT) { - - var thumbClickOffsetX = event.x - _minSliderX; - var thumbPositionNormalised = thumbClickOffsetX / _sliderRangeX; - if (thumbPositionNormalised < 0) { - thumbPositionNormalised = 0; - } else if (thumbPositionNormalised > 1) { - thumbPositionNormalised = 1; - } - var sliderX = thumbPositionNormalised * _sliderRangeX; // sets range - - if (_movingSliderOne) { - - // currently selected joint pitch or sway - Overlays.editOverlay(_sliderOne, { - x: sliderX + _minSliderX - }); - if (_state.editingTranslation) { - _motion.curAnim.joints[0].sway = - thumbPositionNormalised * _sliderRanges.joints[0].swayRange; - } else { - _motion.curAnim.joints[_motion.curJointIndex].pitch = - thumbPositionNormalised * _sliderRanges.joints[_motion.curJointIndex].pitchRange; - } - - } else if (_movingSliderTwo) { - - // currently selected joint yaw or bob - Overlays.editOverlay(_sliderTwo, { - x: sliderX + _minSliderX - }); - if (_state.editingTranslation) { - _motion.curAnim.joints[0].bob = - thumbPositionNormalised * _sliderRanges.joints[0].bobRange; - } else { - _motion.curAnim.joints[_motion.curJointIndex].yaw = - thumbPositionNormalised * _sliderRanges.joints[_motion.curJointIndex].yawRange; - } - - } else if (_movingSliderThree) { - - // currently selected joint roll or thrust - Overlays.editOverlay(_sliderThree, { - x: sliderX + _minSliderX - }); - if (_state.editingTranslation) { - _motion.curAnim.joints[0].thrust = - thumbPositionNormalised * _sliderRanges.joints[0].thrustRange; - } else { - _motion.curAnim.joints[_motion.curJointIndex].roll = - thumbPositionNormalised * _sliderRanges.joints[_motion.curJointIndex].rollRange; - } - - } else if (_movingSliderFour) { - - // currently selected joint pitch phase - Overlays.editOverlay(_sliderFour, { - x: sliderX + _minSliderX - }); - - var newPhase = 360 * thumbPositionNormalised - 180; - - if (_state.editingTranslation) { - _motion.curAnim.joints[0].swayPhase = newPhase; - } else { - _motion.curAnim.joints[_motion.curJointIndex].pitchPhase = newPhase; - } - - } else if (_movingSliderFive) { - - // currently selected joint yaw phase; - Overlays.editOverlay(_sliderFive, { - x: sliderX + _minSliderX - }); - - var newPhase = 360 * thumbPositionNormalised - 180; - - if (_state.editingTranslation) { - _motion.curAnim.joints[0].bobPhase = newPhase; - } else { - _motion.curAnim.joints[_motion.curJointIndex].yawPhase = newPhase; - } - - } else if (_movingSliderSix) { - - // currently selected joint roll phase - Overlays.editOverlay(_sliderSix, { - x: sliderX + _minSliderX - }); - - var newPhase = 360 * thumbPositionNormalised - 180; - - if (_state.editingTranslation) { - _motion.curAnim.joints[0].thrustPhase = newPhase; - } else { - _motion.curAnim.joints[_motion.curJointIndex].rollPhase = newPhase; - } - - } else if (_movingSliderSeven) { - - // currently selected joint pitch offset - Overlays.editOverlay(_sliderSeven, { - x: sliderX + _minSliderX - }); - if (_state.editingTranslation) { - var newOffset = (thumbPositionNormalised - 0.5) * - 2 * _sliderRanges.joints[0].swayOffsetRange; - _motion.curAnim.joints[0].swayOffset = newOffset; - } else { - var newOffset = (thumbPositionNormalised - 0.5) * - 2 * _sliderRanges.joints[_motion.curJointIndex].pitchOffsetRange; - _motion.curAnim.joints[_motion.curJointIndex].pitchOffset = newOffset; - } - - } else if (_movingSliderEight) { - - // currently selected joint yaw offset - Overlays.editOverlay(_sliderEight, { - x: sliderX + _minSliderX - }); - if (_state.editingTranslation) { - var newOffset = (thumbPositionNormalised - 0.5) * - 2 *_sliderRanges.joints[0].bobOffsetRange; - _motion.curAnim.joints[0].bobOffset = newOffset; - } else { - var newOffset = (thumbPositionNormalised - 0.5) * - 2 * _sliderRanges.joints[_motion.curJointIndex].yawOffsetRange; - _motion.curAnim.joints[_motion.curJointIndex].yawOffset = newOffset; - } - - } else if (_movingSliderNine) { - - // currently selected joint roll offset - Overlays.editOverlay(_sliderNine, { - x: sliderX + _minSliderX - }); - if (_state.editingTranslation) { - var newOffset = (thumbPositionNormalised - 0.5) * - 2 * _sliderRanges.joints[0].thrustOffsetRange; - _motion.curAnim.joints[0].thrustOffset = newOffset; - } else { - var newOffset = (thumbPositionNormalised - 0.5) * - 2 * _sliderRanges.joints[_motion.curJointIndex].rollOffsetRange; - _motion.curAnim.joints[_motion.curJointIndex].rollOffset = newOffset; - } - } - - // end if editing joints - - } else if (_state.currentState === _state.EDIT_WALK_TWEAKS) { - - // sliders for commonly required walk adjustments - var thumbClickOffsetX = event.x - _minSliderX; - var thumbPositionNormalised = thumbClickOffsetX / _sliderRangeX; - if (thumbPositionNormalised < 0) thumbPositionNormalised = 0; - if (thumbPositionNormalised > 1) thumbPositionNormalised = 1; - var sliderX = thumbPositionNormalised * _sliderRangeX; // sets range - - if (_movingSliderOne) { - // walk speed - Overlays.editOverlay(_sliderOne, { - x: sliderX + _minSliderX - }); - _motion.curAnim.calibration.frequency = thumbPositionNormalised * MAX_WALK_SPEED; - } else if (_movingSliderTwo) { - // lean (hips pitch offset) - Overlays.editOverlay(_sliderTwo, { - x: sliderX + _minSliderX - }); - var newOffset = (thumbPositionNormalised - 0.5) * 2 * _sliderRanges.joints[0].pitchOffsetRange; - _motion.curAnim.joints[0].pitchOffset = newOffset; - } else if (_movingSliderThree) { - // stride (upper legs pitch) - Overlays.editOverlay(_sliderThree, { - x: sliderX + _minSliderX - }); - _motion.curAnim.joints[1].pitch = thumbPositionNormalised * _sliderRanges.joints[1].pitchRange; - } else if (_movingSliderFour) { - // legs separation (upper legs roll) - Overlays.editOverlay(_sliderFour, { - x: sliderX + _minSliderX - }); - _motion.curAnim.joints[1].rollOffset = (thumbPositionNormalised - 0.5) * - 2 * _sliderRanges.joints[1].rollOffsetRange; - } else if (_movingSliderFive) { - // legs forward (lower legs pitch offset) - Overlays.editOverlay(_sliderFive, { - x: sliderX + _minSliderX - }); - _motion.curAnim.joints[1].pitchOffset = (thumbPositionNormalised - 0.5) * - 2 * _sliderRanges.joints[1].pitchOffsetRange; - } else if (_movingSliderSix) { - // lower legs splay (lower legs roll offset) - Overlays.editOverlay(_sliderSix, { - x: sliderX + _minSliderX - }); - _motion.curAnim.joints[2].rollOffset = (thumbPositionNormalised - 0.5) * - 2 * _sliderRanges.joints[2].rollOffsetRange; - - } else if (_movingSliderSeven) { - // arms forward (upper arms yaw offset) - Overlays.editOverlay(_sliderSeven, { - x: sliderX + _minSliderX - }); - _motion.curAnim.joints[9].yawOffset = (thumbPositionNormalised - 0.5) * - 2 * _sliderRanges.joints[9].yawOffsetRange; - } else if (_movingSliderEight) { - // arms out (upper arm pitch offset) - Overlays.editOverlay(_sliderEight, { - x: sliderX + _minSliderX - }); - _motion.curAnim.joints[9].pitchOffset = (thumbPositionNormalised - 0.5) * - -2 * _sliderRanges.joints[9].pitchOffsetRange; - } else if (_movingSliderNine) { - // lower arms splay (lower arm pitch offset) - Overlays.editOverlay(_sliderNine, { - x: sliderX + _minSliderX - }); - _motion.curAnim.joints[10].pitchOffset = (thumbPositionNormalised - 0.5) * - -2 * _sliderRanges.joints[10].pitchOffsetRange; - } - } // if tweaking - }; - - function mouseReleaseEvent(event) { - - if (_movingSliderOne) { - _movingSliderOne = false; - } else if (_movingSliderTwo) { - _movingSliderTwo = false; - } else if (_movingSliderThree) { - _movingSliderThree = false; - } else if (_movingSliderFour) { - _movingSliderFour = false; - } else if (_movingSliderFive) { - _movingSliderFive = false; - } else if (_movingSliderSix) { - _movingSliderSix = false; - } else if (_movingSliderSeven) { - _movingSliderSeven = false; - } else if (_movingSliderEight) { - _movingSliderEight = false; - } else if (_movingSliderNine) { - _movingSliderNine = false; - } - }; - - Controller.mousePressEvent.connect(mousePressEvent); - Controller.mouseMoveEvent.connect(mouseMoveEvent); - Controller.mouseReleaseEvent.connect(mouseReleaseEvent); - - // Script ending - Script.scriptEnding.connect(function() { - - // delete the background overlays - for (var i in _backgroundOverlays) { - Overlays.deleteOverlay(_backgroundOverlays[i]); - } - // delete the button overlays - for (var i in _buttonOverlays) { - Overlays.deleteOverlay(_buttonOverlays[i]); - } - // delete the slider thumb overlays - for (var i in _sliderThumbOverlays) { - Overlays.deleteOverlay(_sliderThumbOverlays[i]); - } - // delete the character joint control overlays - for (var i in _jointsControlOverlays) { - Overlays.deleteOverlay(_jointsControlOverlays[i]); - } - // delete the big button overlays - for (var i in _bigbuttonOverlays) { - Overlays.deleteOverlay(_bigbuttonOverlays[i]); - } - // delete the mimimised tab - Overlays.deleteOverlay(_controlsMinimisedTab); - }); - - // public methods - return { - - // gather references to objects from the walk.js script - initialise: function(state, motion, walkAssets) { - - _state = state; - _motion = motion; - _walkAssets = walkAssets; - }, - - updateMenu: function() { - - if (!_state.minimised) { - - switch (_state.currentState) { - - case _state.EDIT_WALK_STYLES: - case _state.EDIT_WALK_TWEAKS: - case _state.EDIT_WALK_JOINTS: { - - hideMenuButtons(); - initialiseFrontPanel(false); - hideJointSelectors(); - - if (_state.currentState === _state.EDIT_WALK_STYLES) { - - setBackground(_controlsBackgroundWalkEditStyles); - initialiseWalkStylesPanel(true); - setSliderThumbsVisible(false); - hideJointSelectors(); - setButtonOverlayVisible(_configWalkStylesButtonSelected); - setButtonOverlayVisible(_configWalkTweaksButton); - setButtonOverlayVisible(_configWalkJointsButton); - - } else if (_state.currentState === _state.EDIT_WALK_TWEAKS) { - - setBackground(_controlsBackgroundWalkEditTweaks); - initialiseWalkStylesPanel(false); - setSliderThumbsVisible(true); - hideJointSelectors(); - initialiseWalkTweaksPanel(); - setButtonOverlayVisible(_configWalkStylesButton); - setButtonOverlayVisible(_configWalkTweaksButtonSelected); - setButtonOverlayVisible(_configWalkJointsButton); - - } else if (_state.currentState === _state.EDIT_WALK_JOINTS) { - - if (_state.editingTranslation) { - setBackground(_controlsBackgroundWalkEditHipTrans); - } else { - setBackground(_controlsBackgroundWalkEditJoints); - } - - initialiseWalkStylesPanel(false); - setSliderThumbsVisible(true); - setButtonOverlayVisible(_configWalkStylesButton); - setButtonOverlayVisible(_configWalkTweaksButton); - setButtonOverlayVisible(_configWalkJointsButtonSelected); - initialiseJointsEditingPanel(); - } - setButtonOverlayVisible(_onButton); - setButtonOverlayVisible(_backButton); - return; - } - - case _state.EDIT_STANDING: - case _state.EDIT_SIDESTEP_LEFT: - case _state.EDIT_SIDESTEP_RIGHT: { - - if (_state.editingTranslation) { - setBackground(_controlsBackgroundWalkEditHipTrans); - } else { - setBackground(_controlsBackgroundWalkEditJoints); - } - hideMenuButtons(); - initialiseWalkStylesPanel(false); - initialiseFrontPanel(false); - - if (_state.currentState === _state.EDIT_SIDESTEP_LEFT) { - - setButtonOverlayVisible(_configSideStepRightButton); - setButtonOverlayVisible(_configSideStepLeftButtonSelected); - setButtonOverlayVisible(_configStandButton); - - } else if (_state.currentState === _state.EDIT_SIDESTEP_RIGHT) { - - setButtonOverlayVisible(_configSideStepRightButtonSelected); - setButtonOverlayVisible(_configSideStepLeftButton); - setButtonOverlayVisible(_configStandButton); - - } else if (_state.currentState === _state.EDIT_STANDING) { - - setButtonOverlayVisible(_configSideStepRightButton); - setButtonOverlayVisible(_configSideStepLeftButton); - setButtonOverlayVisible(_configStandButtonSelected); - } - initialiseJointsEditingPanel(); - setButtonOverlayVisible(_onButton); - setButtonOverlayVisible(_backButton); - return; - } - - case _state.EDIT_FLYING: - case _state.EDIT_FLYING_UP: - case _state.EDIT_FLYING_DOWN: { - - setBackground(_controlsBackgroundWalkEditJoints); - hideMenuButtons(); - initialiseWalkStylesPanel(false); - initialiseFrontPanel(false); - if (_state.currentState === _state.EDIT_FLYING) { - - setButtonOverlayVisible(_configFlyingUpButton); - setButtonOverlayVisible(_configFlyingDownButton); - setButtonOverlayVisible(_configFlyingButtonSelected); - - } else if (_state.currentState === _state.EDIT_FLYING_UP) { - - setButtonOverlayVisible(_configFlyingUpButtonSelected); - setButtonOverlayVisible(_configFlyingDownButton); - setButtonOverlayVisible(_configFlyingButton); - - } else if (_state.currentState === _state.EDIT_FLYING_DOWN) { - - setButtonOverlayVisible(_configFlyingUpButton); - setButtonOverlayVisible(_configFlyingDownButtonSelected); - setButtonOverlayVisible(_configFlyingButton); - } - initialiseJointsEditingPanel(); - setButtonOverlayVisible(_onButton); - setButtonOverlayVisible(_backButton); - return; - } - - case _state.STANDING: - case _state.WALKING: - case _state.FLYING: - case _state.SIDE_STEP: - default: { - - hideMenuButtons(); - hideJointSelectors(); - setBackground(_controlsBackground); - if (_state.powerOn) { - setButtonOverlayVisible(_onButton); - } else { - setButtonOverlayVisible(_offButton); - } - setButtonOverlayVisible(_configWalkButton); - setButtonOverlayVisible(_configStandButton); - setButtonOverlayVisible(_configFlyingButton); - setButtonOverlayVisible(_hideButton); - setSliderThumbsVisible(false); - initialiseFrontPanel(true); - initialiseWalkStylesPanel(false); - return; - } - } - } - } - }; // end public methods (return) +// +// walkInterface.js +// +// version 2.0 +// +// Created by David Wooldridge, Autumn 2014 +// +// Presents the UI for the walk.js script v1.12 +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +walkInterface = (function() { + + // references to walk.js objects + var _motion = null; + var _walkAssets = null; + + // controller UI element positions and dimensions + var _backgroundWidth = 350; + var _backgroundHeight = 700; + var _backgroundX = Window.innerWidth - _backgroundWidth - 58; + var _backgroundY = Window.innerHeight / 2 - _backgroundHeight / 2; + var _bigButtonsY = 348; + + // Load up the overlays + var _buttonOverlays = []; + + // ui minimised tab + var _controlsMinimisedTab = Overlays.addOverlay("image", { + x: Window.innerWidth - 58, + y: Window.innerHeight - 145, + width: 50, height: 50, + imageURL: pathToAssets + 'overlay-images/minimised-tab.png', + visible: true, alpha: 0.9 + }); + + // ui background + var _controlsBackground = Overlays.addOverlay("image", { + bounds: { + x: _backgroundX, + y: _backgroundY, + width: _backgroundWidth, + height: _backgroundHeight + }, + imageURL: pathToAssets + "overlay-images/background.png", + alpha: 1, visible: false + }); + + // button overlays + var _controlsMinimiseButton = Overlays.addOverlay("image", { + bounds: { + x: _backgroundX + _backgroundWidth - 62, + y: _backgroundY + 40, + width: 25, height: 25 + }, + imageURL: pathToAssets + "overlay-images/minimise-button.png", + alpha: 1, visible: false + }); + _buttonOverlays.push(_controlsMinimiseButton); + + var _onButton = Overlays.addOverlay("image", { + bounds: { + x: _backgroundX + _backgroundWidth / 2 - 115, + y: _backgroundY + _bigButtonsY, + width: 230, height: 36 + }, + imageURL: pathToAssets + "overlay-images/power-button-selected.png", + alpha: 1, visible: false + }); + _buttonOverlays.push(_onButton); + + var _offButton = Overlays.addOverlay("image", { + bounds: { + x: _backgroundX + _backgroundWidth / 2 - 115, + y: _backgroundY + _bigButtonsY, + width: 230, height: 36 + }, + imageURL: pathToAssets + "overlay-images/power-button.png", + alpha: 1, visible: false + }); + _buttonOverlays.push(_offButton); + + var _femaleButton = Overlays.addOverlay("image", { + bounds: { + x: _backgroundX + _backgroundWidth / 2 - 115, + y: _backgroundY + _bigButtonsY + 60, + width: 230, height: 36 + }, + imageURL: pathToAssets + "overlay-images/female-button.png", + alpha: 1, visible: false + }); + _buttonOverlays.push(_femaleButton); + + var _femaleButtonSelected = Overlays.addOverlay("image", { + bounds: { + x: _backgroundX + _backgroundWidth / 2 - 115, + y: _backgroundY + _bigButtonsY + 60, + width: 230, height: 36 + }, + imageURL: pathToAssets + "overlay-images/female-button-selected.png", + alpha: 1, visible: false + }); + _buttonOverlays.push(_femaleButtonSelected); + + var _maleButton = Overlays.addOverlay("image", { + bounds: { + x: _backgroundX + _backgroundWidth / 2 - 115, + y: _backgroundY + _bigButtonsY + 120, + width: 230, height: 36 + }, + imageURL: pathToAssets + "overlay-images/male-button.png", + alpha: 1, visible: false + }); + _buttonOverlays.push(_maleButton); + + var _maleButtonSelected = Overlays.addOverlay("image", { + bounds: { + x: _backgroundX + _backgroundWidth / 2 - 115, + y: _backgroundY + _bigButtonsY + 120, + width: 230, height: 36 + }, + imageURL: pathToAssets + "overlay-images/male-button-selected.png", + alpha: 1, visible: false + }); + _buttonOverlays.push(_maleButtonSelected); + + var _armsFreeButton = Overlays.addOverlay("image", { + bounds: { + x: _backgroundX + _backgroundWidth / 2 - 115, + y: _backgroundY + _bigButtonsY + 180, + width: 230, height: 36 + }, + imageURL: pathToAssets + "overlay-images/arms-free-button.png", + alpha: 1, visible: false + }); + _buttonOverlays.push(_armsFreeButton); + + var _armsFreeButtonSelected = Overlays.addOverlay("image", { + bounds: { + x: _backgroundX + _backgroundWidth / 2 - 115, + y: _backgroundY + _bigButtonsY + 180, + width: 230, height: 36 + }, + imageURL: pathToAssets + "overlay-images/arms-free-button-selected.png", + alpha: 1, visible: false + }); + _buttonOverlays.push(_armsFreeButtonSelected); + + var _footstepsButton = Overlays.addOverlay("image", { + bounds: { + x: _backgroundX + _backgroundWidth / 2 - 115, + y: _backgroundY + _bigButtonsY + 240, + width: 230, height: 36 + }, + imageURL: pathToAssets + "overlay-images/footstep-sounds-button.png", + alpha: 1, visible: false + }); + _buttonOverlays.push(_footstepsButton); + + var _footstepsButtonSelected = Overlays.addOverlay("image", { + bounds: { + x: _backgroundX + _backgroundWidth / 2 - 115, + y: _backgroundY + _bigButtonsY + 240, + width: 230, height: 36 + }, + imageURL: pathToAssets + "overlay-images/footstep-sounds-button-selected.png", + alpha: 1, visible: false + }); + _buttonOverlays.push(_footstepsButtonSelected); + + + function minimiseDialog(minimise) { + + Overlays.editOverlay(_controlsBackground, {visible: !minimise}); + Overlays.editOverlay(_controlsMinimisedTab, {visible: minimise}); + Overlays.editOverlay(_controlsMinimiseButton, {visible: !minimise}); + + if(_state.powerOn) { + + Overlays.editOverlay(_onButton, {visible: !minimise}); + Overlays.editOverlay(_offButton, {visible: false}); + + } else { + + Overlays.editOverlay(_onButton, {visible: false}); + Overlays.editOverlay(_offButton, {visible: !minimise}); + + } + if (_motion.avatarGender === FEMALE) { + + Overlays.editOverlay(_femaleButtonSelected, {visible: !minimise}); + Overlays.editOverlay(_femaleButton, {visible: false}); + Overlays.editOverlay(_maleButtonSelected, {visible: false}); + Overlays.editOverlay(_maleButton, {visible: !minimise}); + + } else { + + Overlays.editOverlay(_femaleButtonSelected, {visible: false}); + Overlays.editOverlay(_femaleButton, {visible: !minimise}); + Overlays.editOverlay(_maleButtonSelected, {visible: !minimise}); + Overlays.editOverlay(_maleButton, {visible: false}); + } + if (_motion.armsFree) { + + Overlays.editOverlay(_armsFreeButtonSelected, {visible: !minimise}); + Overlays.editOverlay(_armsFreeButton, {visible: false}); + + } else { + + Overlays.editOverlay(_armsFreeButtonSelected, {visible: false}); + Overlays.editOverlay(_armsFreeButton, {visible: !minimise}); + } + if (_motion.makesFootStepSounds) { + + Overlays.editOverlay(_footstepsButtonSelected, {visible: !minimise}); + Overlays.editOverlay(_footstepsButton, {visible: false}); + + } else { + + Overlays.editOverlay(_footstepsButtonSelected, {visible: false}); + Overlays.editOverlay(_footstepsButton, {visible: !minimise}); + } + }; + + // mouse event handler + function mousePressEvent(event) { + + var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y}); + + switch (clickedOverlay) { + + case _controlsMinimiseButton: + + minimiseDialog(true); + _state.setInternalState(_state.STANDING); + return; + + case _controlsMinimisedTab: + + minimiseDialog(false); + _state.setInternalState(_state.STANDING); + return; + + case _onButton: + + _state.powerOn = false; + Overlays.editOverlay(_offButton, {visible: true}); + Overlays.editOverlay(_onButton, {visible: false}); + _state.setInternalState(state.STANDING); + return; + + case _offButton: + + _state.powerOn = true; + Overlays.editOverlay(_offButton, {visible: false}); + Overlays.editOverlay(_onButton, {visible: true}); + _state.setInternalState(state.STANDING); + return; + + + case _footstepsButton: + + _motion.makesFootStepSounds = true; + Overlays.editOverlay(_footstepsButtonSelected, {visible: true}); + Overlays.editOverlay(_footstepsButton, {visible: false}); + return; + + case _footstepsButtonSelected: + + _motion.makesFootStepSounds = false; + Overlays.editOverlay(_footstepsButton, {visible: true}); + Overlays.editOverlay(_footstepsButtonSelected, {visible: false}); + return; + + case _femaleButton: + case _maleButtonSelected: + + _motion.setGender(FEMALE); + Overlays.editOverlay(_femaleButtonSelected, {visible: true}); + Overlays.editOverlay(_femaleButton, {visible: false}); + Overlays.editOverlay(_maleButton, {visible: true}); + Overlays.editOverlay(_maleButtonSelected, {visible: false}); + return; + + case _maleButton: + case _femaleButtonSelected: + + _motion.setGender(MALE); + Overlays.editOverlay(_femaleButton, {visible: true}); + Overlays.editOverlay(_femaleButtonSelected, {visible: false}); + Overlays.editOverlay(_maleButtonSelected, {visible: true}); + Overlays.editOverlay(_maleButton, {visible: false}); + return; + + case _armsFreeButton: + + _motion.armsFree = true; + Overlays.editOverlay(_armsFreeButtonSelected, {visible: true}); + Overlays.editOverlay(_armsFreeButton, {visible: false}); + return; + + case _armsFreeButtonSelected: + + _motion.armsFree = false; + _motion.poseFingers(); + Overlays.editOverlay(_armsFreeButtonSelected, {visible: false}); + Overlays.editOverlay(_armsFreeButton, {visible: true}); + return; + } + }; + + Controller.mousePressEvent.connect(mousePressEvent); + + // delete overlays on script ending + Script.scriptEnding.connect(function() { + + // delete overlays + Overlays.deleteOverlay(_controlsBackground); + Overlays.deleteOverlay(_controlsMinimisedTab); + for (var i in _buttonOverlays) { + Overlays.deleteOverlay(_buttonOverlays[i]); + } + }); + + // public method + return { + + // gather references to objects from the walk.js script + initialise: function(state, motion, walkAssets) { + + _state = state; + _motion = motion; + _walkAssets = walkAssets; + } + + }; // end public methods (return) + })(); \ No newline at end of file diff --git a/examples/walk.js b/examples/walk.js index 5a0df72f26..be2a1584d4 100644 --- a/examples/walk.js +++ b/examples/walk.js @@ -1,2613 +1,852 @@ -// -// walk.js -// -// version 1.1 -// -// Created by David Wooldridge, Autumn 2014 -// -// Animates an avatar using procedural animation techniques -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -// constants -var MALE = 1; -var FEMALE = 2; -var MAX_WALK_SPEED = 2.5;//3.919; -var TAKE_FLIGHT_SPEED = 4.55; -var TOP_SPEED = 300; -var UP = 1; -var DOWN = 2; -var LEFT = 4; -var RIGHT = 8; -var FORWARDS = 16; -var BACKWARDS = 32; - -// location of animation files and overlay images -var pathToAssets = 'http://s3.amazonaws.com/hifi-public/WalkScript/'; - -// load the UI -Script.include("./libraries/walkInterface.js"); - -// load filters (Bezier, Butterworth, add harmonics, averaging) -Script.include("./libraries/walkFilters.js"); - -// load objects, constructors and assets (state, Motion, Transition, walkAssets) -Script.include("./libraries/walkApi.js"); - -// initialise the motion state / history object -var motion = new Motion(); - -// initialise Transitions -var nullTransition = new Transition(); -motion.curTransition = nullTransition; - -// initialise the UI -walkInterface.initialise(state, motion, walkAssets); - -// wave shapes -var SAWTOOTH = 1; -var TRIANGLE = 2; -var SQUARE = 4; - -// various filters for synthesising more complex, natural waveforms -var leanPitchFilter = filter.createAveragingFilter(15); -var leanRollFilter = filter.createAveragingFilter(15); -var hipsYawShaper = filter.createWaveSynth(TRIANGLE, 3, 2); -var hipsBobLPFilter = filter.createButterworthFilter(5); - - -// Main loop -Script.update.connect(function(deltaTime) { - - if (state.powerOn) { - - motion.frameStartTime = new Date().getTime(); - motion.cumulativeTime += deltaTime; - motion.nFrames++; - var speed = 0; - - // check for editing modes first, as these require no positioning calculations - switch (state.currentState) { - - case state.EDIT_WALK_STYLES: { - motion.curAnim = motion.selWalk; - animateAvatar(deltaTime, speed); - break; - } - - case state.EDIT_WALK_TWEAKS: { - motion.curAnim = motion.selWalk; - animateAvatar(deltaTime, speed); - break; - } - - case state.EDIT_WALK_JOINTS: { - motion.curAnim = motion.selWalk; - animateAvatar(deltaTime, speed); - break; - } - case state.EDIT_STANDING: { - motion.curAnim = motion.selStand; - motion.direction = FORWARDS; - animateAvatar(deltaTime, speed); - break; - } - - case state.EDIT_SIDESTEP_LEFT: { - motion.curAnim = motion.selSideStepLeft; - motion.direction = LEFT; - animateAvatar(deltaTime, speed); - break; - } - - case state.EDIT_SIDESTEP_RIGHT: { - motion.curAnim = motion.selSideStepRight; - motion.direction = RIGHT; - animateAvatar(deltaTime, speed); - break; - } - - case state.EDIT_FLYING: { - motion.curAnim = motion.selFly; - motion.direction = FORWARDS; - animateAvatar(deltaTime, speed); - break; - } - - case state.EDIT_FLYING_UP: { - motion.curAnim = motion.selFlyUp; - motion.direction = UP; - animateAvatar(deltaTime, speed); - break; - } - - case state.EDIT_FLYING_DOWN: { - motion.curAnim = motion.selFlyDown; - motion.direction = DOWN; - animateAvatar(deltaTime, speed); - break; - } - - default: - break; - } - - // calcualte velocity and speed - var velocity = MyAvatar.getVelocity(); - speed = Vec3.length(velocity); - - if (motion.curTransition !== nullTransition) { - - // finish any live transition before changing state - animateAvatar(deltaTime, speed); - return; - } - var localVelocity = {x: 0, y: 0, z: 0}; - if (speed > 0) { - localVelocity = Vec3.multiplyQbyV(Quat.inverse(MyAvatar.orientation), velocity); - } - - if (!state.editing) { - - // determine the candidate animation state - var actionToTake = undefined; - if (speed < 0.05) { - actionToTake = state.STANDING; - } else if (speed < TAKE_FLIGHT_SPEED) { - actionToTake = state.WALKING; - } else if (speed >= TAKE_FLIGHT_SPEED) { - actionToTake = state.FLYING; - } - - // determine the principle direction - if (Math.abs(localVelocity.x) > Math.abs(localVelocity.y) && - Math.abs(localVelocity.x) > Math.abs(localVelocity.z)) { - - if (localVelocity.x < 0) { - motion.direction = LEFT; - } else { - motion.direction = RIGHT; - } - - } else if (Math.abs(localVelocity.y) > Math.abs(localVelocity.x) && - Math.abs(localVelocity.y) > Math.abs(localVelocity.z)) { - - if (localVelocity.y > 0) { - motion.direction = UP; - } else { - motion.direction = DOWN; - } - - } else if (Math.abs(localVelocity.z) > Math.abs(localVelocity.x) && - Math.abs(localVelocity.z) > Math.abs(localVelocity.y)) { - - if (localVelocity.z < 0) { - motion.direction = FORWARDS; - } else { - motion.direction = BACKWARDS; - } - } - - // maybe at walking speed, but sideways? - if (actionToTake === state.WALKING && - (motion.direction === LEFT || - motion.direction === RIGHT)) { - actionToTake = state.SIDE_STEP; - } - - // maybe at walking speed, but flying up or down? - if (actionToTake === state.WALKING && - (motion.direction === UP || - motion.direction === DOWN)) { - actionToTake = state.FLYING; - } - - // select appropriate animation and initiate Transition if required - // note: The transitions are not compete, and are the most likely - // candidate for the next worklist item - switch (actionToTake) { - - case state.STANDING: { - - // do we need to change state? - if (state.currentState !== state.STANDING) { - - switch (motion.curAnim) { - - case motion.selWalk: { - - // Walking to standing - motion.curTransition = new Transition( - motion.curAnim, - motion.selWalk, - [], 0.25, - {x: 0.1, y: 0.5}, - {x: -0.25, y: 1.22}); - break; - } - - case motion.selFly: - case motion.selFlyUp: - case motion.selFlyDown: { - - // Flying to Standing - motion.curTransition = new Transition( - motion.curAnim, - motion.selStand, - [], 0.5, - {x: 0.5, y: 0.08}, - {x: 0.28, y: 1}); - break; - } - - default: - - break; - } - state.setInternalState(state.STANDING); - motion.curAnim = motion.selStand; - } - animateAvatar(deltaTime, speed); - break; - } - - case state.WALKING: { - - if (state.currentState !== state.WALKING) { - - if (motion.direction === BACKWARDS) { - motion.walkWheelPos = motion.selWalk.calibration.startAngleBackwards; - } else { - motion.walkWheelPos = motion.selWalk.calibration.startAngleForwards; - } - - switch (motion.curAnim) { - - case motion.selStand: { - - // Standing to Walking - motion.curTransition = new Transition( - motion.curAnim, - motion.selWalk, - [], 0.25, - {x: 0.5, y: 0.5}, - {x: 0.5, y: 0.5}); - break; - } - - case motion.selFly: - case motion.selFlyUp: - case motion.selFlyDown: { - - // Flying to Walking - motion.curTransition = new Transition( - motion.curAnim, - motion.selWalk, - [], 0.1, - {x: 0.24, y: 0.03}, - {x: 0.42, y: 1.0}); - break; - } - - default: - - break; - } - state.setInternalState(state.WALKING); - } - motion.curAnim = motion.selWalk; - animateAvatar(deltaTime, speed); - break; - } - - case state.SIDE_STEP: { - - var selSideStep = 0; - if (motion.direction === LEFT) { - - if (motion.lastDirection !== LEFT) { - motion.walkWheelPos = motion.selSideStepLeft.calibration.cycleStart; - } - selSideStep = motion.selSideStepLeft; - - } else { - - if (motion.lastDirection !== RIGHT) { - motion.walkWheelPos = motion.selSideStepRight.calibration.cycleStart; - } - selSideStep = motion.selSideStepRight; - } - - if (state.currentState !== state.SIDE_STEP) { - - if (motion.direction === LEFT) { - motion.walkWheelPos = motion.selSideStepLeft.calibration.cycleStart; - } else { - motion.walkWheelPos = motion.selSideStepRight.calibration.cycleStart; - } - state.setInternalState(state.SIDE_STEP); - } - motion.curAnim = selSideStep; - animateAvatar(deltaTime, speed); - break; - } - - case state.FLYING: { - - if (state.currentState !== state.FLYING) { - state.setInternalState(state.FLYING); - } - - // change animation for flying directly up or down - if (motion.direction === UP) { - - if (motion.curAnim !== motion.selFlyUp) { - - switch (motion.curAnim) { - - case motion.selStand: - case motion.selWalk: { - - // standing | walking to flying up - motion.curTransition = new Transition( - motion.curAnim, - motion.selFlyUp, - [], 0.35, - {x: 0.5, y: 0.08}, - {x: 0.28, y: 1}); - break; - } - - case motion.selFly: - case motion.selFlyUp: - case motion.selFlyDown: { - - motion.curTransition = new Transition( - motion.curAnim, - motion.selFlyUp, - [], 0.35, - {x: 0.5, y: 0.08}, - {x: 0.28, y: 1}); - break; - } - - default: - - break; - } - motion.curAnim = motion.selFlyUp; - } - - } else if (motion.direction == DOWN) { - - if (motion.curAnim !== motion.selFlyDown) { - - switch (motion.curAnim) { - - case motion.selStand: - case motion.selWalk: { - - motion.curTransition = new Transition( - motion.curAnim, - motion.selFlyDown, - [], 0.35, - {x: 0.5, y: 0.08}, - {x: 0.28, y: 1}); - break; - } - - case motion.selFly: - case motion.selFlyUp: - case motion.selFlyDown: { - - motion.curTransition = new Transition( - motion.curAnim, - motion.selFlyDown, - [], 0.45, - {x: 0.5, y: 0.08}, - {x: 0.28, y: 1}); - break; - } - - default: - - break; - } - motion.curAnim = motion.selFlyDown; - } - - } else { - - if (motion.curAnim !== motion.selFly) { - - switch (motion.curAnim) { - - case motion.selStand: - case motion.selWalk: { - - motion.curTransition = new Transition( - motion.curAnim, - motion.selFly, - [], 0.35, - {x: 1.44, y:0.24}, - {x: 0.61, y:0.92}); - break; - } - - case motion.selFly: - case motion.selFlyUp: - case motion.selFlyDown: { - - motion.curTransition = new Transition( - motion.curAnim, - motion.selFly, - [], 0.75, - {x: 0.5, y: 0.08}, - {x: 0.28, y: 1}); - break; - } - - default: - - break; - } - motion.curAnim = motion.selFly; - } - } - animateAvatar(deltaTime, speed); - break; - }// end case state.FLYING - - } // end switch(actionToTake) - - } // end if (!state.editing) - - // record the frame's direction and local avatar's local velocity for future reference - motion.lastDirection = motion.direction; - motion.lastVelocity = localVelocity; - } -}); - -// the faster we go, the further we lean forward. the angle is calcualted here -function getLeanPitch(speed) { - - if (speed > TOP_SPEED) { - speed = TOP_SPEED; - } - var leanProgress = speed / TOP_SPEED; - - if (motion.direction === LEFT || - motion.direction === RIGHT) { - leanProgress = 0; - } else { - - var responseSharpness = 1.5; - if (motion.direction == BACKWARDS) { - responseSharpness = 3.0; - } - - leanProgress = filter.bezier((1 - leanProgress), - {x: 0, y: 0.0}, - {x: 0, y: responseSharpness}, - {x: 0, y: 1.5}, - {x: 1, y: 1}).y; - - // determine final pitch and adjust for direction of momentum - if (motion.direction === BACKWARDS) { - leanProgress = -motion.motionPitchMax * leanProgress; - } else { - leanProgress = motion.motionPitchMax * leanProgress; - } - } - - // return the smoothed response - return leanPitchFilter.process(leanProgress); -} - -// calculate the angle at which to bank into corners when turning -function getLeanRoll(deltaTime, speed) { - - var leanRollProgress = 0; - if (speed > TOP_SPEED) { - speed = TOP_SPEED; - } - - // what's our our anglular velocity? - var angularVelocityMax = 70; // from observation - var angularVelocity = filter.radToDeg(MyAvatar.getAngularVelocity().y); - if (angularVelocity > angularVelocityMax) { - angularVelocity = angularVelocityMax; - } - if (angularVelocity < -angularVelocityMax) { - angularVelocity = -angularVelocityMax; - } - - leanRollProgress = speed / TOP_SPEED; - - if (motion.direction !== LEFT && - motion.direction !== RIGHT) { - leanRollProgress *= (Math.abs(angularVelocity) / angularVelocityMax); - } - - // apply our response curve - leanRollProgress = filter.bezier((1 - leanRollProgress), - {x: 0, y: 0}, - {x: 0, y: 1}, - {x: 0, y: 1}, - {x: 1, y: 1}).y; - // which way to lean? - var turnSign = -1; - if (angularVelocity < 0.001) { - turnSign = 1; - } - if (motion.direction === BACKWARDS || - motion.direction === LEFT) { - turnSign *= -1; - } - if (motion.direction === LEFT || - motion.direction === RIGHT) { - leanRollProgress *= 2; - } - - // add damping with simple averaging filter - leanRollProgress = leanRollFilter.process(turnSign * leanRollProgress); - return motion.motionRollMax * leanRollProgress; -} - -function playFootstep(side) { - - options = { - position: Camera.getPosition(), - volume: 0.3 - } - - var soundNumber = 2; // 0 to 2 - if (side === RIGHT && motion.makesFootStepSounds) { - Audio.playSound(walkAssets.footsteps[soundNumber + 1], options); - } else if (side === LEFT && motion.makesFootStepSounds) { - Audio.playSound(walkAssets.footsteps[soundNumber], options); - } -} - -// animate the avatar using sine wave generators. inspired by Victorian clockwork dolls -function animateAvatar(deltaTime, speed) { - - var cycle = motion.cumulativeTime; - var transProgress = 1; - var adjFreq = motion.curAnim.calibration.frequency; - - // legs phase and cycle reversal for walking backwards - var reverseModifier = 0; - var reverseSignModifier = 1; - if (motion.direction === BACKWARDS) { - reverseModifier = -180; - reverseSignModifier = -1; - } - - // don't lean into the direction of travel if going up - var leanMod = 1; - if (motion.direction === UP) { - leanMod = 0; - } - - // adjust leaning direction for flying - var flyingModifier = 1; - if (state.currentState.FLYING) { - flyingModifier = -1; - } - - if (motion.curTransition !== nullTransition) { - - // new transiton? - if (motion.curTransition.progress === 0 && - motion.curTransition.walkingAtStart) { - - if (state.currentState !== state.SIDE_STEP) { - - // work out where we want the walk cycle to stop - var leftStop = motion.selWalk.calibration.stopAngleForwards + 180; - var rightStop = motion.selWalk.calibration.stopAngleForwards; - - if (motion.direction === BACKWARDS) { - leftStop = motion.selWalk.calibration.stopAngleBackwards + 180; - rightStop = motion.selWalk.calibration.stopAngleBackwards; - } - - // find the closest stop point from the walk wheel's angle - var angleToLeftStop = 180 - Math.abs(Math.abs(motion.walkWheelPos - leftStop) - 180); - var angleToRightStop = 180 - Math.abs(Math.abs(motion.walkWheelPos - rightStop) - 180); - if (motion.walkWheelPos > angleToLeftStop) { - angleToLeftStop = 360 - angleToLeftStop; - } - if (motion.walkWheelPos > angleToRightStop) { - angleToRightStop = 360 - angleToRightStop; - } - - motion.curTransition.walkWheelIncrement = 3; - - // keep the walkwheel turning by setting the walkWheelIncrement - // until our feet are tucked nicely underneath us. - if (angleToLeftStop < angleToRightStop) { - motion.curTransition.walkStopAngle = leftStop; - } else { - motion.curTransition.walkStopAngle = rightStop; - } - - } else { - - // freeze wheel for sidestepping transitions (for now) - motion.curTransition.walkWheelIncrement = 0; - } - } // end if (new transition and curTransition.walkingAtStart) - - // update the Transition progress - var elapasedTime = (new Date().getTime() - motion.curTransition.startTime) / 1000; - motion.curTransition.progress = elapasedTime / motion.curTransition.transitionDuration; - transProgress = filter.bezier((1 - motion.curTransition.progress), {x: 0, y: 0}, - motion.curTransition.easingLower, - motion.curTransition.easingUpper, {x: 1, y: 1}).y; - - if (motion.curTransition.progress >= 1) { - - // time to kill off the transition - delete motion.curTransition; - motion.curTransition = nullTransition; - - } else { - - if (motion.curTransition.walkingAtStart) { - - if (state.currentState !== state.SIDE_STEP) { - - // if at a stop angle, hold the walk wheel position for remainder of transition - var tolerance = 7; // must be greater than the walkWheel increment - if ((motion.walkWheelPos > (motion.curTransition.walkStopAngle - tolerance)) && - (motion.walkWheelPos < (motion.curTransition.walkStopAngle + tolerance))) { - - motion.curTransition.walkWheelIncrement = 0; - } - // keep turning walk wheel until both feet are below the avi - motion.advanceWalkWheel(motion.curTransition.walkWheelIncrement); - - } else motion.curTransition.walkWheelIncrement = 0; // sidestep - } - } } // end motion.curTransition !== nullTransition - - - // walking? then get the stride length - if (motion.curAnim === motion.selWalk) { - - // if the timing's right, take a snapshot of the stride max and recalibrate - var strideMaxAt = motion.curAnim.calibration.forwardStrideMaxAt; - if (motion.direction === BACKWARDS) { - strideMaxAt = motion.curAnim.calibration.backwardsStrideMaxAt; - } - - var tolerance = 1.0; - if (motion.walkWheelPos < (strideMaxAt + tolerance) && - motion.walkWheelPos > (strideMaxAt - tolerance)) { - - // measure and save stride length - var footRPos = MyAvatar.getJointPosition("RightFoot"); - var footLPos = MyAvatar.getJointPosition("LeftFoot"); - motion.strideLength = Vec3.distance(footRPos, footLPos); - - if (motion.direction === FORWARDS) { - motion.curAnim.calibration.strideLengthForwards = motion.strideLength; - } else if (motion.direction === BACKWARDS) { - motion.curAnim.calibration.strideLengthBackwards = motion.strideLength; - } - - } else { - - // use the saved value for stride length - if (motion.direction === FORWARDS) { - motion.strideLength = motion.curAnim.calibration.strideLengthForwards; - } else if (motion.direction === BACKWARDS) { - motion.strideLength = motion.curAnim.calibration.strideLengthBackwards; - } - } - } // end get walk stride length - - // sidestepping? get the stride length - if (motion.curAnim === motion.selSideStepLeft || - motion.curAnim === motion.selSideStepRight) { - - // if the timing's right, take a snapshot of the stride max and recalibrate the stride length - var tolerance = 1.0; - if (motion.direction === LEFT) { - - if (motion.walkWheelPos < motion.curAnim.calibration.strideMaxAt + tolerance && - motion.walkWheelPos > motion.curAnim.calibration.strideMaxAt - tolerance) { - - var footRPos = MyAvatar.getJointPosition("RightFoot"); - var footLPos = MyAvatar.getJointPosition("LeftFoot"); - motion.strideLength = Vec3.distance(footRPos, footLPos); - motion.curAnim.calibration.strideLength = motion.strideLength; - - } else motion.strideLength = motion.selSideStepLeft.calibration.strideLength; - - } else if (motion.direction === RIGHT) { - - if (motion.walkWheelPos < motion.curAnim.calibration.strideMaxAt + tolerance && - motion.walkWheelPos > motion.curAnim.calibration.strideMaxAt - tolerance) { - - var footRPos = MyAvatar.getJointPosition("RightFoot"); - var footLPos = MyAvatar.getJointPosition("LeftFoot"); - motion.strideLength = Vec3.distance(footRPos, footLPos); - motion.curAnim.calibration.strideLength = motion.strideLength; - - } else motion.strideLength = motion.selSideStepRight.calibration.strideLength; - } - } // end get sidestep stride length - - // turn the walk wheel - if (motion.curAnim === motion.selWalk || - motion.curAnim === motion.selSideStepLeft || - motion.curAnim === motion.selSideStepRight || - motion.curTransition.walkingAtStart) { - - // wrap the stride length around a 'surveyor's wheel' twice and calculate - // the angular speed at the given (linear) speed: - // omega = v / r , where r = circumference / 2 PI , where circumference = 2 * stride length - var strideLength = motion.strideLength; - var wheelRadius = strideLength / Math.PI; - var angularVelocity = speed / wheelRadius; - - // calculate the degrees turned (at this angular speed) since last frame - var radiansTurnedSinceLastFrame = deltaTime * angularVelocity; - var degreesTurnedSinceLastFrame = filter.radToDeg(radiansTurnedSinceLastFrame); - - // if we are in an edit mode, we will need fake time to turn the wheel - if (state.currentState !== state.WALKING && - state.currentState !== state.SIDE_STEP) { - degreesTurnedSinceLastFrame = motion.curAnim.calibration.frequency / 70; - } - - // advance the walk wheel the appropriate amount - motion.advanceWalkWheel(degreesTurnedSinceLastFrame); - - // set the new values for the exact correct walk cycle speed - adjFreq = 1; - cycle = motion.walkWheelPos; - - } // end of walk wheel and stride length calculation - - // motion vars - var pitchOsc = 0; - var pitchOscLeft = 0; - var pitchOscRight = 0; - var yawOsc = 0; - var yawOscLeft = 0; - var yawOscRight = 0; - var rollOsc = 0; - var pitchOffset = 0; - var yawOffset = 0; - var rollOffset = 0; - var swayOsc = 0; - var bobOsc = 0; - var thrustOsc = 0; - var swayOscLast = 0; - var bobOscLast = 0; - var thrustOscLast = 0; - - // historical (for transitions) - var pitchOscLast = 0; - var pitchOscLeftLast = 0; - var pitchOscRightLast = 0; - var yawOscLast = 0; - var rollOscLast = 0; - var pitchOffsetLast = 0; - var yawOffsetLast = 0; - var rollOffsetLast = 0; - - // feet - var sideStepFootPitchModifier = 1; - var sideStepHandPitchSign = 1; - - // calculate hips translation - if (motion.curTransition !== nullTransition) { - - if (motion.curTransition.walkingAtStart) { - - swayOsc = motion.curAnim.joints[0].sway * - Math.sin(filter.degToRad(motion.cumulativeTime * motion.curAnim.calibration.frequency + - motion.curAnim.joints[0].swayPhase)) + motion.curAnim.joints[0].swayOffset; - - var bobPhase = motion.curAnim.joints[0].bobPhase; - if (motion.direction === motion.BACKWARDS) { - bobPhase += 90; - } - bobOsc = motion.curAnim.joints[0].bob * - Math.sin(filter.degToRad(motion.cumulativeTime * - motion.curAnim.calibration.frequency + bobPhase)) + - motion.curAnim.joints[0].bobOffset; - - thrustOsc = motion.curAnim.joints[0].thrust * - Math.sin(filter.degToRad(motion.cumulativeTime * - motion.curAnim.calibration.frequency * 2 + - motion.curAnim.joints[0].thrustPhase)) + - motion.curAnim.joints[0].thrustOffset; - - swayOscLast = motion.curTransition.lastAnim.joints[0].sway * - Math.sin(filter.degToRad(motion.walkWheelPos + - motion.curTransition.lastAnim.joints[0].swayPhase)) + - motion.curTransition.lastAnim.joints[0].swayOffset; - - var bobPhaseLast = motion.curTransition.lastAnim.joints[0].bobPhase; - if (motion.direction === motion.BACKWARDS) { - bobPhaseLast +=90; - } - bobOscLast = motion.curTransition.lastAnim.joints[0].bob * - Math.sin(filter.degToRad(motion.walkWheelPos + bobPhaseLast)); - bobOscLast = filter.clipTrough(bobOscLast, motion.curTransition.lastAnim.joints[0].bob , 2); - bobOscLast = hipsBobLPFilter.process(bobOscLast); - bobOscLast += motion.curTransition.lastAnim.joints[0].bobOffset; - - thrustOscLast = motion.curTransition.lastAnim.joints[0].thrust * - Math.sin(filter.degToRad(motion.walkWheelPos * 2 + - motion.curTransition.lastAnim.joints[0].thrustPhase)) + - motion.curTransition.lastAnim.joints[0].thrustOffset; - - // end if walking at start of transition - - } else { - - swayOsc = motion.curAnim.joints[0].sway * - Math.sin(filter.degToRad(cycle * adjFreq + motion.curAnim.joints[0].swayPhase)) + - motion.curAnim.joints[0].swayOffset; - - var bobPhase = motion.curAnim.joints[0].bobPhase; - if (motion.direction === motion.BACKWARDS) { - bobPhase += 90; - } - bobOsc = motion.curAnim.joints[0].bob * - Math.sin(filter.degToRad(cycle * adjFreq * 2 + bobPhase)); - if (state.currentState === state.WALKING || - state.currentState === state.EDIT_WALK_STYLES || - state.currentState === state.EDIT_WALK_TWEAKS || - state.currentState === state.EDIT_WALK_JOINTS) { - - // apply clipping filter to flatten the curve's peaks (inputValue, peak, strength) - bobOsc = filter.clipTrough(bobOsc, motion.curAnim.joints[0].bob , 2); - bobOsc = hipsBobLPFilter.process(bobOsc); - } - bobOsc += motion.curAnim.joints[0].bobOffset; - - thrustOsc = motion.curAnim.joints[0].thrust * - Math.sin(filter.degToRad(cycle * adjFreq * 2 + - motion.curAnim.joints[0].thrustPhase)) + - motion.curAnim.joints[0].thrustOffset; - - swayOscLast = motion.curTransition.lastAnim.joints[0].sway * - Math.sin(filter.degToRad(motion.cumulativeTime * - motion.curTransition.lastAnim.calibration.frequency + - motion.curTransition.lastAnim.joints[0].swayPhase)) + - motion.curTransition.lastAnim.joints[0].swayOffset; - - bobOscLast = motion.curTransition.lastAnim.joints[0].bob * - Math.sin(filter.degToRad(motion.cumulativeTime * - motion.curTransition.lastAnim.calibration.frequency * 2 + - motion.curTransition.lastAnim.joints[0].bobPhase)) + - motion.curTransition.lastAnim.joints[0].bobOffset; - - thrustOscLast = motion.curTransition.lastAnim.joints[0].thrust * - Math.sin(filter.degToRad(motion.cumulativeTime * - motion.curTransition.lastAnim.calibration.frequency * 2 + - motion.curTransition.lastAnim.joints[0].thrustPhase)) + - motion.curTransition.lastAnim.joints[0].thrustOffset; - } - - swayOsc = (transProgress * swayOsc) + ((1 - transProgress) * swayOscLast); - bobOsc = (transProgress * bobOsc) + ((1 - transProgress) * bobOscLast); - thrustOsc = (transProgress * thrustOsc) + ((1 - transProgress) * thrustOscLast); - - // end if walking at start of transition - - } else { - - swayOsc = motion.curAnim.joints[0].sway * - Math.sin(filter.degToRad(cycle * adjFreq + motion.curAnim.joints[0].swayPhase)) + - motion.curAnim.joints[0].swayOffset; - - bobPhase = motion.curAnim.joints[0].bobPhase; - if (motion.direction === motion.BACKWARDS) bobPhase += 90; - bobOsc = motion.curAnim.joints[0].bob * Math.sin(filter.degToRad(cycle * adjFreq * 2 + bobPhase)); - if (state.currentState === state.WALKING || - state.currentState === state.EDIT_WALK_STYLES || - state.currentState === state.EDIT_WALK_TWEAKS || - state.currentState === state.EDIT_WALK_JOINTS) { - - // apply clipping filter to flatten the curve's peaks (inputValue, peak, strength) - bobOsc = filter.clipTrough(bobOsc, motion.curAnim.joints[0].bob , 2); - bobOsc = hipsBobLPFilter.process(bobOsc); - } - bobOsc += motion.curAnim.joints[0].bobOffset; - - thrustOsc = motion.curAnim.joints[0].thrust * - Math.sin(filter.degToRad(cycle * adjFreq * 2 + - motion.curAnim.joints[0].thrustPhase)) + - motion.curAnim.joints[0].thrustOffset; - } - - // convert local hips translations to global and apply - var aviOrientation = MyAvatar.orientation; - var front = Quat.getFront(aviOrientation); - var right = Quat.getRight(aviOrientation); - var up = Quat.getUp(aviOrientation); - var aviFront = Vec3.multiply(front, thrustOsc); - var aviRight = Vec3.multiply(right, swayOsc); - var aviUp = Vec3.multiply(up, bobOsc); - var aviTranslationOffset = {x: 0, y: 0, z: 0}; - - aviTranslationOffset = Vec3.sum(aviTranslationOffset, aviFront); - aviTranslationOffset = Vec3.sum(aviTranslationOffset, aviRight); - aviTranslationOffset = Vec3.sum(aviTranslationOffset, aviUp); - - MyAvatar.setSkeletonOffset({ - x: aviTranslationOffset.x, - y: aviTranslationOffset.y, - z: aviTranslationOffset.z - }); - - // hips rotation - if (motion.curTransition !== nullTransition) { - - if (motion.curTransition.walkingAtStart) { - - pitchOsc = motion.curAnim.joints[0].pitch * - Math.sin(filter.degToRad(motion.cumulativeTime * motion.curAnim.calibration.frequency * 2 + - motion.curAnim.joints[0].pitchPhase)) + motion.curAnim.joints[0].pitchOffset; - - yawOsc = motion.curAnim.joints[0].yaw * - Math.sin(filter.degToRad(motion.cumulativeTime * motion.curAnim.calibration.frequency + - motion.curAnim.joints[0].yawPhase - reverseModifier)) + motion.curAnim.joints[0].yawOffset; - - rollOsc = motion.curAnim.joints[0].roll * - Math.sin(filter.degToRad(motion.cumulativeTime * motion.curAnim.calibration.frequency + - motion.curAnim.joints[0].rollPhase)) + motion.curAnim.joints[0].rollOffset; - - pitchOscLast = motion.curTransition.lastAnim.joints[0].pitch * - Math.sin(filter.degToRad(motion.walkWheelPos * 2 + - motion.curTransition.lastAnim.joints[0].pitchPhase)) + - motion.curTransition.lastAnim.joints[0].pitchOffset; - - yawOscLast = motion.curTransition.lastAnim.joints[0].yaw * - Math.sin(filter.degToRad(motion.walkWheelPos + - motion.curTransition.lastAnim.joints[0].yawPhase)); - - yawOscLast += motion.curTransition.lastAnim.joints[0].yaw * - hipsYawShaper.shapeWave(filter.degToRad(motion.walkWheelPos + - motion.curTransition.lastAnim.joints[0].yawPhase - reverseModifier)) + - motion.curTransition.lastAnim.joints[0].yawOffset; - - rollOscLast = (motion.curTransition.lastAnim.joints[0].roll * - Math.sin(filter.degToRad(motion.walkWheelPos + - motion.curTransition.lastAnim.joints[0].rollPhase)) + - motion.curTransition.lastAnim.joints[0].rollOffset); - - } else { - - pitchOsc = motion.curAnim.joints[0].pitch * - Math.sin(filter.degToRad(cycle * adjFreq * 2 + - motion.curAnim.joints[0].pitchPhase)) + - motion.curAnim.joints[0].pitchOffset; - - yawOsc = motion.curAnim.joints[0].yaw * - Math.sin(filter.degToRad(cycle * adjFreq + - motion.curAnim.joints[0].yawPhase - reverseModifier)) + - motion.curAnim.joints[0].yawOffset; - - rollOsc = motion.curAnim.joints[0].roll * - Math.sin(filter.degToRad(cycle * adjFreq + - motion.curAnim.joints[0].rollPhase)) + - motion.curAnim.joints[0].rollOffset; - - pitchOscLast = motion.curTransition.lastAnim.joints[0].pitch * - Math.sin(filter.degToRad(motion.cumulativeTime * - motion.curTransition.lastAnim.calibration.frequency * 2 + - motion.curTransition.lastAnim.joints[0].pitchPhase)) + - motion.curTransition.lastAnim.joints[0].pitchOffset; - - yawOscLast = motion.curTransition.lastAnim.joints[0].yaw * - Math.sin(filter.degToRad(motion.cumulativeTime * - motion.curTransition.lastAnim.calibration.frequency + - motion.curTransition.lastAnim.joints[0].yawPhase - reverseModifier)) + - motion.curTransition.lastAnim.joints[0].yawOffset; - - rollOscLast = motion.curTransition.lastAnim.joints[0].roll * - Math.sin(filter.degToRad(motion.cumulativeTime * - motion.curTransition.lastAnim.calibration.frequency + - motion.curTransition.lastAnim.joints[0].rollPhase)) + - motion.curTransition.lastAnim.joints[0].rollOffset; - } - - pitchOsc = (transProgress * pitchOsc) + ((1 - transProgress) * pitchOscLast); - yawOsc = (transProgress * yawOsc) + ((1 - transProgress) * yawOscLast); - rollOsc = (transProgress * rollOsc) + ((1 - transProgress) * rollOscLast); - - } else { - - pitchOsc = motion.curAnim.joints[0].pitch * - Math.sin(filter.degToRad((cycle * adjFreq * 2) + - motion.curAnim.joints[0].pitchPhase)) + - motion.curAnim.joints[0].pitchOffset; - - yawOsc = motion.curAnim.joints[0].yaw * - Math.sin(filter.degToRad((cycle * adjFreq) + - motion.curAnim.joints[0].yawPhase)); - - yawOsc += motion.curAnim.joints[0].yaw * - hipsYawShaper.shapeWave(filter.degToRad(cycle * adjFreq) + - motion.curAnim.joints[0].yawPhase - reverseModifier)+ - motion.curAnim.joints[0].yawOffset; - - rollOsc = (motion.curAnim.joints[0].roll * - Math.sin(filter.degToRad((cycle * adjFreq) + - motion.curAnim.joints[0].rollPhase)) + - motion.curAnim.joints[0].rollOffset); - } - - // apply hips rotation - MyAvatar.setJointData("Hips", Quat.fromPitchYawRollDegrees( - pitchOsc + (leanMod * getLeanPitch(speed)), - yawOsc, - rollOsc + getLeanRoll(deltaTime, speed))); - - // upper legs - if (state.currentState !== state.SIDE_STEP && - state.currentState !== state.EDIT_SIDESTEP_LEFT && - state.currentState !== state.EDIT_SIDESTEP_RIGHT) { - - if (motion.curTransition !== nullTransition) { - - if (motion.curTransition.walkingAtStart) { - - pitchOscLeft = motion.curAnim.joints[1].pitch * - Math.sin(filter.degToRad(motion.cumulativeTime * - motion.curAnim.calibration.frequency + - reverseModifier * motion.curAnim.joints[1].pitchPhase)); - - pitchOscRight = motion.curAnim.joints[1].pitch * - Math.sin(filter.degToRad(motion.cumulativeTime * - motion.curAnim.calibration.frequency + - reverseModifier * motion.curAnim.joints[1].pitchPhase)); - - yawOsc = motion.curAnim.joints[1].yaw * - Math.sin(filter.degToRad(motion.cumulativeTime * - motion.curAnim.calibration.frequency + - motion.curAnim.joints[1].yawPhase)); - - rollOsc = motion.curAnim.joints[1].roll * - Math.sin(filter.degToRad(motion.cumulativeTime * - motion.curAnim.calibration.frequency + - motion.curAnim.joints[1].rollPhase)); - - pitchOffset = motion.curAnim.joints[1].pitchOffset; - yawOffset = motion.curAnim.joints[1].yawOffset; - rollOffset = motion.curAnim.joints[1].rollOffset; - - pitchOscLeftLast = motion.curTransition.lastAnim.joints[1].pitch * - motion.curTransition.lastAnim.harmonics.leftUpperLeg.calculate( - filter.degToRad(motion.walkWheelPos + - motion.curTransition.lastAnim.joints[1].pitchPhase + 180 + reverseModifier)); - - pitchOscRightLast = motion.curTransition.lastAnim.joints[1].pitch * - motion.curTransition.lastAnim.harmonics.rightUpperLeg.calculate( - filter.degToRad(motion.walkWheelPos + - motion.curTransition.lastAnim.joints[1].pitchPhase + reverseModifier)); - - yawOscLast = motion.curTransition.lastAnim.joints[1].yaw * - Math.sin(filter.degToRad(motion.walkWheelPos + - motion.curTransition.lastAnim.joints[1].yawPhase)); - - rollOscLast = motion.curTransition.lastAnim.joints[1].roll * - Math.sin(filter.degToRad(motion.walkWheelPos + - motion.curTransition.lastAnim.joints[1].rollPhase)); - - pitchOffsetLast = motion.curTransition.lastAnim.joints[1].pitchOffset; - yawOffsetLast = motion.curTransition.lastAnim.joints[1].yawOffset; - rollOffsetLast = motion.curTransition.lastAnim.joints[1].rollOffset; - - } else { - - if (state.currentState === state.WALKING || - state.currentState === state.EDIT_WALK_STYLES || - state.currentState === state.EDIT_WALK_TWEAKS || - state.currentState === state.EDIT_WALK_JOINTS) { - - pitchOscLeft = motion.curAnim.joints[1].pitch * - motion.curAnim.harmonics.leftUpperLeg.calculate(filter.degToRad(cycle * adjFreq + - motion.curAnim.joints[1].pitchPhase + 180 + reverseModifier)); - pitchOscRight = motion.curAnim.joints[1].pitch * - motion.curAnim.harmonics.rightUpperLeg.calculate(filter.degToRad(cycle * adjFreq + - motion.curAnim.joints[1].pitchPhase + reverseModifier)); - } else { - - pitchOscLeft = motion.curAnim.joints[1].pitch * Math.sin(filter.degToRad(cycle * adjFreq - + motion.curAnim.joints[1].pitchPhase)); - pitchOscRight = motion.curAnim.joints[1].pitch * Math.sin(filter.degToRad(cycle * adjFreq - + motion.curAnim.joints[1].pitchPhase)); - } - - yawOsc = motion.curAnim.joints[1].yaw * - Math.sin(filter.degToRad(cycle * adjFreq + - motion.curAnim.joints[1].yawPhase)); - - rollOsc = motion.curAnim.joints[1].roll * - Math.sin(filter.degToRad(cycle * adjFreq + - motion.curAnim.joints[1].rollPhase)); - - pitchOffset = motion.curAnim.joints[1].pitchOffset; - yawOffset = motion.curAnim.joints[1].yawOffset; - rollOffset = motion.curAnim.joints[1].rollOffset; - - pitchOscLeftLast = motion.curTransition.lastAnim.joints[1].pitch * - Math.sin(filter.degToRad(motion.cumulativeTime * - motion.curTransition.lastAnim.calibration.frequency + - reverseModifier * motion.curTransition.lastAnim.joints[1].pitchPhase)); - - pitchOscRightLast = motion.curTransition.lastAnim.joints[1].pitch * - Math.sin(filter.degToRad(motion.cumulativeTime * - motion.curTransition.lastAnim.calibration.frequency + - reverseModifier * motion.curTransition.lastAnim.joints[1].pitchPhase)); - - yawOscLast = motion.curTransition.lastAnim.joints[1].yaw * - Math.sin(filter.degToRad(motion.cumulativeTime * - motion.curTransition.lastAnim.calibration.frequency + - motion.curTransition.lastAnim.joints[1].yawPhase)); - - rollOscLast = motion.curTransition.lastAnim.joints[1].roll * - Math.sin(filter.degToRad(motion.cumulativeTime * - motion.curTransition.lastAnim.calibration.frequency + - motion.curTransition.lastAnim.joints[1].rollPhase)); - - pitchOffsetLast = motion.curTransition.lastAnim.joints[1].pitchOffset; - yawOffsetLast = motion.curTransition.lastAnim.joints[1].yawOffset; - rollOffsetLast = motion.curTransition.lastAnim.joints[1].rollOffset; - } - pitchOscLeft = (transProgress * pitchOscLeft) + ((1 - transProgress) * pitchOscLeftLast); - pitchOscRight = (transProgress * pitchOscRight) + ((1 - transProgress) * pitchOscRightLast); - yawOsc = (transProgress * yawOsc) + ((1 - transProgress) * yawOscLast); - rollOsc = (transProgress * rollOsc) + ((1 - transProgress) * rollOscLast); - - pitchOffset = (transProgress * pitchOffset) + ((1 - transProgress) * pitchOffsetLast); - yawOffset = (transProgress * yawOffset) + ((1 - transProgress) * yawOffsetLast); - rollOffset = (transProgress * rollOffset) + ((1 - transProgress) * rollOffsetLast); - - } else { - - if (state.currentState === state.WALKING || - state.currentState === state.EDIT_WALK_STYLES || - state.currentState === state.EDIT_WALK_TWEAKS || - state.currentState === state.EDIT_WALK_JOINTS) { - - pitchOscLeft = motion.curAnim.joints[1].pitch * - motion.curAnim.harmonics.leftUpperLeg.calculate(filter.degToRad(cycle * adjFreq + - motion.curAnim.joints[1].pitchPhase + 180 + reverseModifier)); - pitchOscRight = motion.curAnim.joints[1].pitch * - motion.curAnim.harmonics.rightUpperLeg.calculate(filter.degToRad(cycle * adjFreq + - motion.curAnim.joints[1].pitchPhase + reverseModifier)); - } else { - - pitchOscLeft = motion.curAnim.joints[1].pitch * Math.sin(filter.degToRad(cycle * adjFreq - + motion.curAnim.joints[1].pitchPhase)); - pitchOscRight = motion.curAnim.joints[1].pitch * Math.sin(filter.degToRad(cycle * adjFreq - + motion.curAnim.joints[1].pitchPhase)); - } - - yawOsc = motion.curAnim.joints[1].yaw * - Math.sin(filter.degToRad((cycle * adjFreq) + - motion.curAnim.joints[1].yawPhase)); - - rollOsc = motion.curAnim.joints[1].roll * - Math.sin(filter.degToRad((cycle * adjFreq) + - motion.curAnim.joints[1].rollPhase)); - - pitchOffset = motion.curAnim.joints[1].pitchOffset; - yawOffset = motion.curAnim.joints[1].yawOffset; - rollOffset = motion.curAnim.joints[1].rollOffset; - } - - // apply the upper leg rotations - MyAvatar.setJointData("LeftUpLeg", Quat.fromPitchYawRollDegrees( - pitchOscLeft + pitchOffset, - yawOsc - yawOffset, - -rollOsc + rollOffset)); - - MyAvatar.setJointData("RightUpLeg", Quat.fromPitchYawRollDegrees( - pitchOscRight + pitchOffset, - yawOsc + yawOffset, - -rollOsc - rollOffset)); - - // lower leg - if (motion.curTransition !== nullTransition) { - - if (motion.curTransition.walkingAtStart) { - - pitchOscLeft = motion.curAnim.joints[2].pitch * - Math.sin(filter.degToRad(motion.cumulativeTime * - motion.curAnim.calibration.frequency + - motion.curAnim.joints[2].pitchPhase + 180)); - - pitchOscRight = motion.curAnim.joints[2].pitch * - Math.sin(filter.degToRad(motion.cumulativeTime * - motion.curAnim.calibration.frequency + - motion.curAnim.joints[2].pitchPhase)); - - yawOsc = motion.curAnim.joints[2].yaw * - Math.sin(filter.degToRad(motion.cumulativeTime * - motion.curAnim.calibration.frequency + - motion.curAnim.joints[2].yawPhase)); - - rollOsc = motion.curAnim.joints[2].roll * - Math.sin(filter.degToRad(motion.cumulativeTime * - motion.curAnim.calibration.frequency + - motion.curAnim.joints[2].rollPhase)); - - pitchOffset = motion.curAnim.joints[2].pitchOffset; - yawOffset = motion.curAnim.joints[2].yawOffset; - rollOffset = motion.curAnim.joints[2].rollOffset; - - pitchOscLeftLast = motion.curTransition.lastAnim.joints[2].pitch * - motion.curTransition.lastAnim.harmonics.leftLowerLeg.calculate(filter.degToRad(motion.walkWheelPos + - motion.curTransition.lastAnim.joints[2].pitchPhase + 180)); - - pitchOscRightLast = motion.curTransition.lastAnim.joints[2].pitch * - motion.curTransition.lastAnim.harmonics.leftLowerLeg.calculate(filter.degToRad(motion.walkWheelPos + - motion.curTransition.lastAnim.joints[2].pitchPhase)); - - yawOscLast = motion.curTransition.lastAnim.joints[2].yaw * - Math.sin(filter.degToRad(motion.walkWheelPos + - motion.curTransition.lastAnim.joints[2].yawPhase)); - - rollOscLast = motion.curTransition.lastAnim.joints[2].roll * - Math.sin(filter.degToRad(motion.walkWheelPos + - motion.curTransition.lastAnim.joints[2].rollPhase)); - - pitchOffsetLast = motion.curTransition.lastAnim.joints[2].pitchOffset; - yawOffsetLast = motion.curTransition.lastAnim.joints[2].yawOffset; - rollOffsetLast = motion.curTransition.lastAnim.joints[2].rollOffset; - - } else { - - if (state.currentState === state.WALKING || - state.currentState === state.EDIT_WALK_STYLES || - state.currentState === state.EDIT_WALK_TWEAKS || - state.currentState === state.EDIT_WALK_JOINTS) { - - pitchOscLeft = motion.curAnim.harmonics.leftLowerLeg.calculate(filter.degToRad(reverseSignModifier * cycle * adjFreq + - motion.curAnim.joints[2].pitchPhase + 180)); - pitchOscRight = motion.curAnim.harmonics.rightLowerLeg.calculate(filter.degToRad(reverseSignModifier * cycle * adjFreq + - motion.curAnim.joints[2].pitchPhase)); - - } else { - - pitchOscLeft = Math.sin(filter.degToRad((cycle * adjFreq) + - motion.curAnim.joints[2].pitchPhase + 180)); - - pitchOscRight = Math.sin(filter.degToRad((cycle * adjFreq) + - motion.curAnim.joints[2].pitchPhase)); - } - pitchOscLeft *= motion.curAnim.joints[2].pitch; - pitchOscRight *= motion.curAnim.joints[2].pitch; - - yawOsc = motion.curAnim.joints[2].yaw * - Math.sin(filter.degToRad(cycle * adjFreq + - motion.curAnim.joints[2].yawPhase)); - - rollOsc = motion.curAnim.joints[2].roll * - Math.sin(filter.degToRad(cycle * adjFreq + - motion.curAnim.joints[2].rollPhase)); - - pitchOffset = motion.curAnim.joints[2].pitchOffset; - yawOffset = motion.curAnim.joints[2].yawOffset; - rollOffset = motion.curAnim.joints[2].rollOffset; - - pitchOscLeftLast = motion.curTransition.lastAnim.joints[2].pitch * - Math.sin(filter.degToRad(motion.cumulativeTime * - motion.curTransition.lastAnim.calibration.frequency + - motion.curTransition.lastAnim.joints[2].pitchPhase + 180)); - - pitchOscRightLast = motion.curTransition.lastAnim.joints[2].pitch * - Math.sin(filter.degToRad(motion.cumulativeTime * - motion.curTransition.lastAnim.calibration.frequency + - motion.curTransition.lastAnim.joints[2].pitchPhase)); - - yawOscLast = motion.curTransition.lastAnim.joints[2].yaw * - Math.sin(filter.degToRad(motion.cumulativeTime * - motion.curTransition.lastAnim.calibration.frequency + - motion.curTransition.lastAnim.joints[2].yawPhase)); - - rollOscLast = motion.curTransition.lastAnim.joints[2].roll * - Math.sin(filter.degToRad(motion.cumulativeTime * - motion.curTransition.lastAnim.calibration.frequency + - motion.curTransition.lastAnim.joints[2].rollPhase)); - - pitchOffsetLast = motion.curTransition.lastAnim.joints[2].pitchOffset; - yawOffsetLast = motion.curTransition.lastAnim.joints[2].yawOffset; - rollOffsetLast = motion.curTransition.lastAnim.joints[2].rollOffset; - } - - pitchOscLeft = (transProgress * pitchOscLeft) + ((1 - transProgress) * pitchOscLeftLast); - pitchOscRight = (transProgress * pitchOscRight) + ((1 - transProgress) * pitchOscRightLast); - yawOsc = (transProgress * yawOsc) + ((1 - transProgress) * yawOscLast); - rollOsc = (transProgress * rollOsc) + ((1 - transProgress) * rollOscLast); - - pitchOffset = (transProgress * pitchOffset) + ((1 - transProgress) * pitchOffsetLast); - yawOffset = (transProgress * yawOffset) + ((1 - transProgress) * yawOffsetLast); - rollOffset = (transProgress * rollOffset) + ((1 - transProgress) * rollOffsetLast); - - rollOscLeft = rollOsc; - rollOscRight = rollOsc; - - } else { // end if transitioning - - if (state.currentState === state.WALKING || - state.currentState === state.EDIT_WALK_STYLES || - state.currentState === state.EDIT_WALK_TWEAKS || - state.currentState === state.EDIT_WALK_JOINTS) { - - pitchOscLeft = motion.curAnim.harmonics.leftLowerLeg.calculate(filter.degToRad(reverseSignModifier * cycle * adjFreq + - motion.curAnim.joints[2].pitchPhase + 180)); - pitchOscRight = motion.curAnim.harmonics.rightLowerLeg.calculate(filter.degToRad(reverseSignModifier * cycle * adjFreq + - motion.curAnim.joints[2].pitchPhase)); - - } else { - - pitchOscLeft = Math.sin(filter.degToRad((cycle * adjFreq) + - motion.curAnim.joints[2].pitchPhase + 180)); - - pitchOscRight = Math.sin(filter.degToRad((cycle * adjFreq) + - motion.curAnim.joints[2].pitchPhase)); - } - - pitchOscLeft *= motion.curAnim.joints[2].pitch; - pitchOscRight *= motion.curAnim.joints[2].pitch; - - yawOsc = motion.curAnim.joints[2].yaw * - Math.sin(filter.degToRad((cycle * adjFreq) + - motion.curAnim.joints[2].yawPhase)); - - rollOsc = Math.sin(filter.degToRad((cycle * adjFreq) + - motion.curAnim.joints[2].rollPhase)); - - rollOsc = motion.curAnim.joints[2].roll; - - pitchOffset = motion.curAnim.joints[2].pitchOffset; - yawOffset = motion.curAnim.joints[2].yawOffset; - rollOffset = motion.curAnim.joints[2].rollOffset; - } - - pitchOscLeft += pitchOffset; - pitchOscRight += pitchOffset; - - // apply lower leg joint rotations - MyAvatar.setJointData("LeftLeg", Quat.fromPitchYawRollDegrees( - pitchOscLeft, - yawOsc + yawOffset, - rollOsc + rollOffset)); - MyAvatar.setJointData("RightLeg", Quat.fromPitchYawRollDegrees( - pitchOscRight, - yawOsc - yawOffset, - rollOsc - rollOffset)); - - } // end if !state.SIDE_STEP - - else if (state.currentState === state.SIDE_STEP || - state.currentState === state.EDIT_SIDESTEP_LEFT || - state.currentState === state.EDIT_SIDESTEP_RIGHT) { - - // sidestepping uses the sinewave generators slightly differently for the legs - pitchOsc = motion.curAnim.joints[1].pitch * - Math.sin(filter.degToRad((cycle * adjFreq) + - motion.curAnim.joints[1].pitchPhase)); - - yawOsc = motion.curAnim.joints[1].yaw * - Math.sin(filter.degToRad((cycle * adjFreq) + - motion.curAnim.joints[1].yawPhase)); - - rollOsc = motion.curAnim.joints[1].roll * - Math.sin(filter.degToRad((cycle * adjFreq) + - motion.curAnim.joints[1].rollPhase)); - - // apply upper leg rotations for sidestepping - MyAvatar.setJointData("RightUpLeg", Quat.fromPitchYawRollDegrees( - -pitchOsc + motion.curAnim.joints[1].pitchOffset, - yawOsc + motion.curAnim.joints[1].yawOffset, - rollOsc + motion.curAnim.joints[1].rollOffset)); - - MyAvatar.setJointData("LeftUpLeg", Quat.fromPitchYawRollDegrees( - pitchOsc + motion.curAnim.joints[1].pitchOffset, - yawOsc - motion.curAnim.joints[1].yawOffset, - -rollOsc - motion.curAnim.joints[1].rollOffset)); - - // calculate lower leg joint rotations for sidestepping - pitchOsc = motion.curAnim.joints[2].pitch * - Math.sin(filter.degToRad((cycle * adjFreq) + - motion.curAnim.joints[2].pitchPhase)); - - yawOsc = motion.curAnim.joints[2].yaw * - Math.sin(filter.degToRad((cycle * adjFreq) + - motion.curAnim.joints[2].yawPhase)); - - rollOsc = motion.curAnim.joints[2].roll * - Math.sin(filter.degToRad((cycle * adjFreq) + - motion.curAnim.joints[2].rollPhase)); - - // apply lower leg joint rotations - MyAvatar.setJointData("RightLeg", Quat.fromPitchYawRollDegrees( - -pitchOsc + motion.curAnim.joints[2].pitchOffset, - yawOsc - motion.curAnim.joints[2].yawOffset, - rollOsc - motion.curAnim.joints[2].rollOffset)); - - MyAvatar.setJointData("LeftLeg", Quat.fromPitchYawRollDegrees( - pitchOsc + motion.curAnim.joints[2].pitchOffset, - yawOsc + motion.curAnim.joints[2].yawOffset, - rollOsc + motion.curAnim.joints[2].rollOffset)); - } - - // feet - if (motion.curAnim === motion.selSideStepLeft || - motion.curAnim === motion.selSideStepRight ) { - - sideStepHandPitchSign = -1; - sideStepFootPitchModifier = 0.5; - } - if (motion.curTransition !== nullTransition) { - - if (motion.curTransition.walkingAtStart) { - - pitchOscLeft = motion.curAnim.joints[3].pitch * - Math.sin(filter.degToRad((motion.cumulativeTime * - motion.curAnim.calibration.frequency) + - motion.curAnim.joints[3].pitchPhase) + 180); - - pitchOscRight = motion.curAnim.joints[3].pitch * - Math.sin(filter.degToRad((motion.cumulativeTime * - motion.curAnim.calibration.frequency) + - motion.curAnim.joints[3].pitchPhase)); - - yawOsc = motion.curAnim.joints[3].yaw * - Math.sin(filter.degToRad((motion.cumulativeTime * - motion.curAnim.calibration.frequency) + - motion.curAnim.joints[3].yawPhase)); - - rollOsc = motion.curAnim.joints[3].roll * - Math.sin(filter.degToRad((motion.cumulativeTime * - motion.curAnim.calibration.frequency) + - motion.curAnim.joints[3].rollPhase)); - - pitchOffset = motion.curAnim.joints[3].pitchOffset; - yawOffset = motion.curAnim.joints[3].yawOffset; - rollOffset = motion.curAnim.joints[3].rollOffset; - - pitchOscLeftLast = motion.curTransition.lastAnim.joints[3].pitch * - motion.curTransition.lastAnim.harmonics.leftFoot.calculate(filter.degToRad(reverseSignModifier * motion.walkWheelPos + - motion.curTransition.lastAnim.joints[3].pitchPhase + reverseModifier)); - - pitchOscRightLast = motion.curTransition.lastAnim.joints[3].pitch * - motion.curTransition.lastAnim.harmonics.rightFoot.calculate(filter.degToRad(reverseSignModifier * motion.walkWheelPos + - motion.curTransition.lastAnim.joints[3].pitchPhase + 180 + reverseModifier)); - - yawOscLast = motion.curTransition.lastAnim.joints[3].yaw * - Math.sin(filter.degToRad((motion.walkWheelPos) + - motion.curTransition.lastAnim.joints[3].yawPhase)); - - rollOscLast = motion.curTransition.lastAnim.joints[3].roll * - Math.sin(filter.degToRad((motion.walkWheelPos) + - motion.curTransition.lastAnim.joints[3].rollPhase)); - - pitchOffsetLast = motion.curTransition.lastAnim.joints[3].pitchOffset; - yawOffsetLast = motion.curTransition.lastAnim.joints[3].yawOffset; - rollOffsetLast = motion.curTransition.lastAnim.joints[3].rollOffset; - - } else { - - if (state.currentState === state.WALKING || - state.currentState === state.EDIT_WALK_STYLES || - state.currentState === state.EDIT_WALK_TWEAKS || - state.currentState === state.EDIT_WALK_JOINTS) { - - pitchOscLeft = motion.curAnim.harmonics.leftFoot.calculate(filter.degToRad(reverseSignModifier * cycle * adjFreq + - motion.curAnim.joints[3].pitchPhase + reverseModifier)); - - pitchOscRight = motion.curAnim.harmonics.rightFoot.calculate(filter.degToRad(reverseSignModifier * cycle * adjFreq + - motion.curAnim.joints[3].pitchPhase + 180 + reverseModifier)); - - } else { - - pitchOscLeft = Math.sin(filter.degToRad(cycle * adjFreq * sideStepFootPitchModifier + - motion.curAnim.joints[3].pitchPhase)); - - pitchOscRight = Math.sin(filter.degToRad(cycle * adjFreq * sideStepFootPitchModifier + - motion.curAnim.joints[3].pitchPhase + 180)); - } - - yawOsc = motion.curAnim.joints[3].yaw * - Math.sin(filter.degToRad((cycle * adjFreq) + - motion.curAnim.joints[3].yawPhase)); - - rollOsc = motion.curAnim.joints[3].roll * - Math.sin(filter.degToRad((cycle * adjFreq) + - motion.curAnim.joints[3].rollPhase)); - - pitchOffset = motion.curAnim.joints[3].pitchOffset; - yawOffset = motion.curAnim.joints[3].yawOffset; - rollOffset = motion.curAnim.joints[3].rollOffset; - - pitchOscLeftLast = motion.curTransition.lastAnim.joints[3].pitch * - Math.sin(filter.degToRad((motion.cumulativeTime * - motion.curTransition.lastAnim.calibration.frequency) + - motion.curTransition.lastAnim.joints[3].pitchPhase + 180)); - - pitchOscRightLast = motion.curTransition.lastAnim.joints[3].pitch * - Math.sin(filter.degToRad((motion.cumulativeTime * - motion.curTransition.lastAnim.calibration.frequency) + - motion.curTransition.lastAnim.joints[3].pitchPhase)); - - yawOscLast = motion.curTransition.lastAnim.joints[3].yaw * - Math.sin(filter.degToRad((motion.cumulativeTime * - motion.curTransition.lastAnim.calibration.frequency) + - motion.curTransition.lastAnim.joints[3].yawPhase)); - - rollOscLast = motion.curTransition.lastAnim.joints[3].roll * - Math.sin(filter.degToRad((motion.cumulativeTime * - motion.curTransition.lastAnim.calibration.frequency) + - motion.curTransition.lastAnim.joints[3].rollPhase)); - - pitchOffsetLast = motion.curTransition.lastAnim.joints[3].pitchOffset; - yawOffsetLast = motion.curTransition.lastAnim.joints[3].yawOffset; - rollOffsetLast = motion.curTransition.lastAnim.joints[3].rollOffset; - } - - pitchOscLeft = (transProgress * pitchOscLeft) + ((1 - transProgress) * pitchOscLeftLast); - pitchOscRight = (transProgress * pitchOscRight) + ((1 - transProgress) * pitchOscRightLast); - yawOsc = (transProgress * yawOsc) + ((1 - transProgress) * yawOscLast); - rollOsc = (transProgress * rollOsc) + ((1 - transProgress) * rollOscLast); - - pitchOffset = (transProgress * pitchOffset) + ((1 - transProgress) * pitchOffsetLast); - yawOffset = (transProgress * yawOffset) + ((1 - transProgress) * yawOffsetLast); - rollOffset = (transProgress * rollOffset) + ((1 - transProgress) * rollOffsetLast); - - } else { - - if (state.currentState === state.WALKING || - state.currentState === state.EDIT_WALK_STYLES || - state.currentState === state.EDIT_WALK_TWEAKS || - state.currentState === state.EDIT_WALK_JOINTS) { - - pitchOscLeft = motion.curAnim.harmonics.leftFoot.calculate(filter.degToRad(reverseSignModifier * cycle * adjFreq + - motion.curAnim.joints[3].pitchPhase + reverseModifier)); - - pitchOscRight = motion.curAnim.harmonics.rightFoot.calculate(filter.degToRad(reverseSignModifier * cycle * adjFreq + - motion.curAnim.joints[3].pitchPhase + 180 + reverseModifier)); - - } else { - - pitchOscLeft = Math.sin(filter.degToRad(cycle * adjFreq * sideStepFootPitchModifier + - motion.curAnim.joints[3].pitchPhase)); - - pitchOscRight = Math.sin(filter.degToRad(cycle * adjFreq * sideStepFootPitchModifier + - motion.curAnim.joints[3].pitchPhase + 180)); - } - - yawOsc = Math.sin(filter.degToRad((cycle * adjFreq) + - motion.curAnim.joints[3].yawPhase)); - - pitchOscLeft *= motion.curAnim.joints[3].pitch; - pitchOscRight *= motion.curAnim.joints[3].pitch; - - yawOsc *= motion.curAnim.joints[3].yaw; - - rollOsc = motion.curAnim.joints[3].roll * - Math.sin(filter.degToRad((cycle * adjFreq) + - motion.curAnim.joints[3].rollPhase)); - - pitchOffset = motion.curAnim.joints[3].pitchOffset; - yawOffset = motion.curAnim.joints[3].yawOffset; - rollOffset = motion.curAnim.joints[3].rollOffset; - } - - // apply foot rotations - MyAvatar.setJointData("LeftFoot", Quat.fromPitchYawRollDegrees( - pitchOscLeft + pitchOffset, - yawOsc - yawOffset, - rollOsc - rollOffset)); - - MyAvatar.setJointData("RightFoot", Quat.fromPitchYawRollDegrees( - pitchOscRight + pitchOffset, - yawOsc + yawOffset, - rollOsc + rollOffset)); - - // play footfall sound yet? To determine this, we take the differential of the - // foot's pitch curve to decide when the foot hits the ground. - if (state.currentState === state.WALKING || - state.currentState === state.SIDE_STEP || - state.currentState === state.EDIT_WALK_STYLES || - state.currentState === state.EDIT_WALK_TWEAKS || - state.currentState === state.EDIT_WALK_JOINTS || - state.currentState === state.EDIT_SIDESTEP_LEFT || - state.currentState === state.EDIT_SIDESTEP_RIGHT) { - - // find dy/dx by determining the cosine wave for the foot's pitch function. - var feetPitchDifferential = Math.cos(filter.degToRad((cycle * adjFreq) + motion.curAnim.joints[3].pitchPhase)); - var threshHold = 0.9; // sets the audio trigger point. with accuracy. - if (feetPitchDifferential < -threshHold && - motion.nextStep === LEFT && - motion.direction !== UP && - motion.direction !== DOWN) { - - playFootstep(LEFT); - motion.nextStep = RIGHT; - } else if (feetPitchDifferential > threshHold && - motion.nextStep === RIGHT && - motion.direction !== UP && - motion.direction !== DOWN) { - - playFootstep(RIGHT); - motion.nextStep = LEFT; - } - } - - // toes - if (motion.curTransition !== nullTransition) { - - if (motion.curTransition.walkingAtStart) { - - pitchOsc = motion.curAnim.joints[4].pitch * - Math.sin(filter.degToRad((2 * motion.cumulativeTime * - motion.curAnim.calibration.frequency) + - motion.curAnim.joints[4].pitchPhase)); - - yawOsc = motion.curAnim.joints[4].yaw * - Math.sin(filter.degToRad((motion.cumulativeTime * - motion.curAnim.calibration.frequency) + - motion.curAnim.joints[4].yawPhase)); - - rollOsc = motion.curAnim.joints[4].roll * - Math.sin(filter.degToRad((motion.cumulativeTime * - motion.curAnim.calibration.frequency) + - motion.curAnim.joints[4].rollPhase)); - - pitchOffset = motion.curAnim.joints[4].pitchOffset; - yawOffset = motion.curAnim.joints[4].yawOffset; - rollOffset = motion.curAnim.joints[4].rollOffset; - - pitchOscLast = motion.curTransition.lastAnim.joints[4].pitch * - Math.sin(filter.degToRad((2 * motion.walkWheelPos) + - motion.curTransition.lastAnim.joints[4].pitchPhase)); - - yawOscLast = motion.curTransition.lastAnim.joints[4].yaw * - Math.sin(filter.degToRad((motion.walkWheelPos) + - motion.curTransition.lastAnim.joints[4].yawPhase)); - - rollOscLast = motion.curTransition.lastAnim.joints[4].roll * - Math.sin(filter.degToRad((motion.walkWheelPos) + - motion.curTransition.lastAnim.joints[4].rollPhase)); - - pitchOffsetLast = motion.curTransition.lastAnim.joints[4].pitchOffset; - yawOffsetLast = motion.curTransition.lastAnim.joints[4].yawOffset; - rollOffsetLast = motion.curTransition.lastAnim.joints[4].rollOffset; - - } else { - - pitchOsc = motion.curAnim.joints[4].pitch * - Math.sin(filter.degToRad((2 * cycle * adjFreq) + - motion.curAnim.joints[4].pitchPhase)); - - yawOsc = motion.curAnim.joints[4].yaw * - Math.sin(filter.degToRad((cycle * adjFreq) + - motion.curAnim.joints[4].yawPhase)); - - rollOsc = motion.curAnim.joints[4].roll * - Math.sin(filter.degToRad((cycle * adjFreq) + - motion.curAnim.joints[4].rollPhase)); - - pitchOffset = motion.curAnim.joints[4].pitchOffset; - yawOffset = motion.curAnim.joints[4].yawOffset; - rollOffset = motion.curAnim.joints[4].rollOffset; - - pitchOscLast = motion.curTransition.lastAnim.joints[4].pitch * - Math.sin(filter.degToRad((2 * motion.cumulativeTime * - motion.curTransition.lastAnim.calibration.frequency) + - motion.curTransition.lastAnim.joints[4].pitchPhase)); - - yawOscLast = motion.curTransition.lastAnim.joints[4].yaw * - Math.sin(filter.degToRad((motion.cumulativeTime * - motion.curTransition.lastAnim.calibration.frequency) + - motion.curTransition.lastAnim.joints[4].yawPhase)); - - rollOscLast = motion.curTransition.lastAnim.joints[4].roll * - Math.sin(filter.degToRad((motion.cumulativeTime * - motion.curTransition.lastAnim.calibration.frequency) + - motion.curTransition.lastAnim.joints[4].rollPhase)); - - pitchOffsetLast = motion.curTransition.lastAnim.joints[4].pitchOffset; - yawOffsetLast = motion.curTransition.lastAnim.joints[4].yawOffset; - rollOffsetLast = motion.curTransition.lastAnim.joints[4].rollOffset; - } - - pitchOsc = (transProgress * pitchOsc) + ((1 - transProgress) * pitchOscLast); - yawOsc = (transProgress * yawOsc) + ((1 - transProgress) * yawOscLast); - rollOsc = (transProgress * rollOsc) + ((1 - transProgress) * rollOscLast); - - pitchOffset = (transProgress * pitchOffset) + ((1 - transProgress) * pitchOffsetLast); - yawOffset = (transProgress * yawOffset) + ((1 - transProgress) * yawOffsetLast); - rollOffset = (transProgress * rollOffset) + ((1 - transProgress) * rollOffsetLast); - - } else { - - pitchOsc = motion.curAnim.joints[4].pitch * - Math.sin(filter.degToRad((2 * cycle * adjFreq) + - motion.curAnim.joints[4].pitchPhase)); - - yawOsc = motion.curAnim.joints[4].yaw * - Math.sin(filter.degToRad((cycle * adjFreq) + - motion.curAnim.joints[4].yawPhase)); - - rollOsc = motion.curAnim.joints[4].roll * - Math.sin(filter.degToRad((cycle * adjFreq) + - motion.curAnim.joints[4].rollPhase)); - - pitchOffset = motion.curAnim.joints[4].pitchOffset; - yawOffset = motion.curAnim.joints[4].yawOffset; - rollOffset = motion.curAnim.joints[4].rollOffset; - } - - // apply toe rotations - MyAvatar.setJointData("RightToeBase", Quat.fromPitchYawRollDegrees( - pitchOsc + pitchOffset, - yawOsc + yawOffset, - rollOsc + rollOffset)); - - MyAvatar.setJointData("LeftToeBase", Quat.fromPitchYawRollDegrees( - pitchOsc + pitchOffset, - yawOsc - yawOffset, - rollOsc - rollOffset)); - - // spine - if (motion.curTransition !== nullTransition) { - - if (motion.curTransition.walkingAtStart) { - - pitchOsc = motion.curAnim.joints[5].pitch * - Math.sin(filter.degToRad((motion.cumulativeTime * - motion.curAnim.calibration.frequency * 2) + - motion.curAnim.joints[5].pitchPhase)) + - motion.curAnim.joints[5].pitchOffset; - - yawOsc = motion.curAnim.joints[5].yaw * - Math.sin(filter.degToRad((motion.cumulativeTime * - motion.curAnim.calibration.frequency) + - motion.curAnim.joints[5].yawPhase)) + - motion.curAnim - .joints[5].yawOffset; - - rollOsc = motion.curAnim.joints[5].roll * - Math.sin(filter.degToRad((motion.cumulativeTime * - motion.curAnim.calibration.frequency) + - motion.curAnim.joints[5].rollPhase)) + - motion.curAnim.joints[5].rollOffset; - - pitchOscLast = motion.curTransition.lastAnim.joints[5].pitch * - Math.sin(filter.degToRad((motion.walkWheelPos * 2) + - motion.curTransition.lastAnim.joints[5].pitchPhase)) + - motion.curTransition.lastAnim.joints[5].pitchOffset; - - yawOscLast = motion.curTransition.lastAnim.joints[5].yaw * - Math.sin(filter.degToRad((motion.walkWheelPos) + - motion.curTransition.lastAnim.joints[5].yawPhase)) + - motion.curTransition.lastAnim.joints[5].yawOffset; - - rollOscLast = motion.curTransition.lastAnim.joints[5].roll * - Math.sin(filter.degToRad((motion.walkWheelPos) + - motion.curTransition.lastAnim.joints[5].rollPhase)) + - motion.curTransition.lastAnim.joints[5].rollOffset; - } else { - - pitchOsc = motion.curAnim.joints[5].pitch * - Math.sin(filter.degToRad((cycle * adjFreq * 2) + - motion.curAnim.joints[5].pitchPhase)) + - motion.curAnim.joints[5].pitchOffset; - - yawOsc = motion.curAnim.joints[5].yaw * - Math.sin(filter.degToRad((cycle * adjFreq) + - motion.curAnim.joints[5].yawPhase)) + - motion.curAnim.joints[5].yawOffset; - - rollOsc = motion.curAnim.joints[5].roll * - Math.sin(filter.degToRad((cycle * adjFreq) + - motion.curAnim.joints[5].rollPhase)) + - motion.curAnim.joints[5].rollOffset; - - pitchOscLast = motion.curTransition.lastAnim.joints[5].pitch * - Math.sin(filter.degToRad((motion.cumulativeTime * - motion.curTransition.lastAnim.calibration.frequency * 2) + - motion.curTransition.lastAnim.joints[5].pitchPhase)) + - motion.curTransition.lastAnim.joints[5].pitchOffset; - - yawOscLast = motion.curTransition.lastAnim.joints[5].yaw * - Math.sin(filter.degToRad((motion.cumulativeTime * - motion.curTransition.lastAnim.calibration.frequency) + - motion.curTransition.lastAnim.joints[5].yawPhase)) + - motion.curTransition.lastAnim.joints[5].yawOffset; - - rollOscLast = motion.curTransition.lastAnim.joints[5].roll * - Math.sin(filter.degToRad((motion.cumulativeTime * - motion.curTransition.lastAnim.calibration.frequency) + - motion.curTransition.lastAnim.joints[5].rollPhase)) + - motion.curTransition.lastAnim.joints[5].rollOffset; - } - - pitchOsc = (transProgress * pitchOsc) + ((1 - transProgress) * pitchOscLast); - yawOsc = (transProgress * yawOsc) + ((1 - transProgress) * yawOscLast); - rollOsc = (transProgress * rollOsc) + ((1 - transProgress) * rollOscLast); - - } else { - - pitchOsc = motion.curAnim.joints[5].pitch * - Math.sin(filter.degToRad((cycle * adjFreq * 2) + - motion.curAnim.joints[5].pitchPhase)) + - motion.curAnim.joints[5].pitchOffset; - - yawOsc = motion.curAnim.joints[5].yaw * - Math.sin(filter.degToRad((cycle * adjFreq) + - motion.curAnim.joints[5].yawPhase)) + - motion.curAnim.joints[5].yawOffset; - - rollOsc = motion.curAnim.joints[5].roll * - Math.sin(filter.degToRad((cycle * adjFreq) + - motion.curAnim.joints[5].rollPhase)) + - motion.curAnim.joints[5].rollOffset; - } - - // apply spine joint rotations - MyAvatar.setJointData("Spine", Quat.fromPitchYawRollDegrees(pitchOsc, yawOsc, rollOsc)); - - // spine 1 - if (motion.curTransition !== nullTransition) { - - if (motion.curTransition.walkingAtStart) { - - pitchOsc = motion.curAnim.joints[6].pitch * - Math.sin(filter.degToRad((motion.cumulativeTime * - motion.curAnim.calibration.frequency * 2) + - motion.curAnim.joints[6].pitchPhase)) + - motion.curAnim.joints[6].pitchOffset; - - yawOsc = motion.curAnim.joints[6].yaw * - Math.sin(filter.degToRad((motion.cumulativeTime * - motion.curAnim.calibration.frequency) + - motion.curAnim.joints[6].yawPhase)) + - motion.curAnim.joints[6].yawOffset; - - rollOsc = motion.curAnim.joints[6].roll * - Math.sin(filter.degToRad((motion.cumulativeTime * - motion.curAnim.calibration.frequency) + - motion.curAnim.joints[6].rollPhase)) + - motion.curAnim.joints[6].rollOffset; - - pitchOscLast = motion.curTransition.lastAnim.joints[6].pitch * - Math.sin(filter.degToRad((motion.walkWheelPos * 2) + - motion.curTransition.lastAnim.joints[6].pitchPhase)) + - motion.curTransition.lastAnim.joints[6].pitchOffset; - - yawOscLast = motion.curTransition.lastAnim.joints[6].yaw * - Math.sin(filter.degToRad((motion.walkWheelPos) + - motion.curTransition.lastAnim.joints[6].yawPhase)) + - motion.curTransition.lastAnim.joints[6].yawOffset; - - rollOscLast = motion.curTransition.lastAnim.joints[6].roll * - Math.sin(filter.degToRad((motion.walkWheelPos) + - motion.curTransition.lastAnim.joints[6].rollPhase)) + - motion.curTransition.lastAnim.joints[6].rollOffset; - - } else { - - pitchOsc = motion.curAnim.joints[6].pitch * - Math.sin(filter.degToRad((cycle * adjFreq * 2) + - motion.curAnim.joints[6].pitchPhase)) + - motion.curAnim.joints[6].pitchOffset; - - yawOsc = motion.curAnim.joints[6].yaw * - Math.sin(filter.degToRad((cycle * adjFreq) + - motion.curAnim.joints[6].yawPhase)) + - motion.curAnim.joints[6].yawOffset; - - rollOsc = motion.curAnim.joints[6].roll * - Math.sin(filter.degToRad((cycle * adjFreq) + - motion.curAnim.joints[6].rollPhase)) + - motion.curAnim.joints[6].rollOffset; - - pitchOscLast = motion.curTransition.lastAnim.joints[6].pitch * - Math.sin(filter.degToRad((motion.cumulativeTime * - motion.curTransition.lastAnim.calibration.frequency * 2) + - motion.curTransition.lastAnim.joints[6].pitchPhase)) + - motion.curTransition.lastAnim.joints[6].pitchOffset; - - yawOscLast = motion.curTransition.lastAnim.joints[6].yaw * - Math.sin(filter.degToRad((motion.cumulativeTime * - motion.curTransition.lastAnim.calibration.frequency) + - motion.curTransition.lastAnim.joints[6].yawPhase)) + - motion.curTransition.lastAnim.joints[6].yawOffset; - - rollOscLast = motion.curTransition.lastAnim.joints[6].roll * - Math.sin(filter.degToRad((motion.cumulativeTime * - motion.curTransition.lastAnim.calibration.frequency) + - motion.curTransition.lastAnim.joints[6].rollPhase)) + - motion.curTransition.lastAnim.joints[6].rollOffset; - } - - pitchOsc = (transProgress * pitchOsc) + ((1 - transProgress) * pitchOscLast); - yawOsc = (transProgress * yawOsc) + ((1 - transProgress) * yawOscLast); - rollOsc = (transProgress * rollOsc) + ((1 - transProgress) * rollOscLast); - - } else { - - pitchOsc = motion.curAnim.joints[6].pitch * - Math.sin(filter.degToRad((cycle * adjFreq * 2) + - motion.curAnim.joints[6].pitchPhase)) + - motion.curAnim.joints[6].pitchOffset; - - yawOsc = motion.curAnim.joints[6].yaw * - Math.sin(filter.degToRad((cycle * adjFreq) + - motion.curAnim.joints[6].yawPhase)) + - motion.curAnim.joints[6].yawOffset; - - rollOsc = motion.curAnim.joints[6].roll * - Math.sin(filter.degToRad((cycle * adjFreq) + - motion.curAnim.joints[6].rollPhase)) + - motion.curAnim.joints[6].rollOffset; - } - - // apply spine1 joint rotations - MyAvatar.setJointData("Spine1", Quat.fromPitchYawRollDegrees(pitchOsc, yawOsc, rollOsc)); - - // spine 2 - if (motion.curTransition !== nullTransition) { - - if (motion.curTransition.walkingAtStart) { - - pitchOsc = motion.curAnim.joints[7].pitch * - Math.sin(filter.degToRad(motion.cumulativeTime * - motion.curAnim.calibration.frequency * 2 + - motion.curAnim.joints[7].pitchPhase)) + - motion.curAnim.joints[7].pitchOffset; - - yawOsc = motion.curAnim.joints[7].yaw * - Math.sin(filter.degToRad(motion.cumulativeTime * - motion.curAnim.calibration.frequency + - motion.curAnim.joints[7].yawPhase)) + - motion.curAnim.joints[7].yawOffset; - - rollOsc = motion.curAnim.joints[7].roll * - Math.sin(filter.degToRad(motion.cumulativeTime * - motion.curAnim.calibration.frequency + - motion.curAnim.joints[7].rollPhase)) + - motion.curAnim.joints[7].rollOffset; - - pitchOscLast = motion.curTransition.lastAnim.joints[7].pitch * - Math.sin(filter.degToRad(motion.walkWheelPos * 2 + - motion.curTransition.lastAnim.joints[7].pitchPhase)) + - motion.curTransition.lastAnim.joints[7].pitchOffset; - - yawOscLast = motion.curTransition.lastAnim.joints[7].yaw * - Math.sin(filter.degToRad(motion.walkWheelPos + - motion.curTransition.lastAnim.joints[7].yawPhase)) + - motion.curTransition.lastAnim.joints[7].yawOffset; - - rollOscLast = motion.curTransition.lastAnim.joints[7].roll * - Math.sin(filter.degToRad(motion.walkWheelPos + - motion.curTransition.lastAnim.joints[7].rollPhase)) + - motion.curTransition.lastAnim.joints[7].rollOffset; - } else { - - pitchOsc = motion.curAnim.joints[7].pitch * - Math.sin(filter.degToRad(cycle * adjFreq * 2 + - motion.curAnim.joints[7].pitchPhase)) + - motion.curAnim.joints[7].pitchOffset; - - yawOsc = motion.curAnim.joints[7].yaw * - Math.sin(filter.degToRad(cycle * adjFreq + - motion.curAnim.joints[7].yawPhase)) + - motion.curAnim.joints[7].yawOffset; - - rollOsc = motion.curAnim.joints[7].roll * - Math.sin(filter.degToRad(cycle * adjFreq + - motion.curAnim.joints[7].rollPhase)) + - motion.curAnim.joints[7].rollOffset; - - pitchOscLast = motion.curTransition.lastAnim.joints[7].pitch * - Math.sin(filter.degToRad(motion.cumulativeTime * 2 * - motion.curTransition.lastAnim.calibration.frequency + - motion.curTransition.lastAnim.joints[7].pitchPhase)) + - motion.curTransition.lastAnim.joints[7].pitchOffset; - - yawOscLast = motion.curTransition.lastAnim.joints[7].yaw * - Math.sin(filter.degToRad(motion.cumulativeTime * - motion.curTransition.lastAnim.calibration.frequency + - motion.curTransition.lastAnim.joints[7].yawPhase)) + - motion.curTransition.lastAnim.joints[7].yawOffset; - - rollOscLast = motion.curTransition.lastAnim.joints[7].roll * - Math.sin(filter.degToRad(motion.cumulativeTime * - motion.curTransition.lastAnim.calibration.frequency + - motion.curTransition.lastAnim.joints[7].rollPhase)) + - motion.curTransition.lastAnim.joints[7].rollOffset; - } - - pitchOsc = (transProgress * pitchOsc) + ((1 - transProgress) * pitchOscLast); - yawOsc = (transProgress * yawOsc) + ((1 - transProgress) * yawOscLast); - rollOsc = (transProgress * rollOsc) + ((1 - transProgress) * rollOscLast); - - } else { - - pitchOsc = motion.curAnim.joints[7].pitch * - Math.sin(filter.degToRad(cycle * adjFreq * 2 + - motion.curAnim.joints[7].pitchPhase)) + - motion.curAnim.joints[7].pitchOffset; - - yawOsc = motion.curAnim.joints[7].yaw * - Math.sin(filter.degToRad(cycle * adjFreq + - motion.curAnim.joints[7].yawPhase)) + - motion.curAnim.joints[7].yawOffset; - - rollOsc = motion.curAnim.joints[7].roll * - Math.sin(filter.degToRad(cycle * adjFreq + - motion.curAnim.joints[7].rollPhase)) + - motion.curAnim.joints[7].rollOffset; - } - - // apply spine2 joint rotations - MyAvatar.setJointData("Spine2", Quat.fromPitchYawRollDegrees(pitchOsc, yawOsc, rollOsc)); - - if (!motion.armsFree) { - - // shoulders - if (motion.curTransition !== nullTransition) { - - if (motion.curTransition.walkingAtStart) { - - pitchOsc = motion.curAnim.joints[8].pitch * - Math.sin(filter.degToRad(motion.cumulativeTime * - motion.curAnim.calibration.frequency + - motion.curAnim.joints[8].pitchPhase)) + - motion.curAnim.joints[8].pitchOffset; - - yawOsc = motion.curAnim.joints[8].yaw * - Math.sin(filter.degToRad(motion.cumulativeTime * - motion.curAnim.calibration.frequency + - motion.curAnim.joints[8].yawPhase)); - - rollOsc = motion.curAnim.joints[8].roll * - Math.sin(filter.degToRad(motion.cumulativeTime * - motion.curAnim.calibration.frequency + - motion.curAnim.joints[8].rollPhase)) + - motion.curAnim.joints[8].rollOffset; - - yawOffset = motion.curAnim.joints[8].yawOffset; - - pitchOscLast = motion.curTransition.lastAnim.joints[8].pitch * - Math.sin(filter.degToRad(motion.walkWheelPos + - motion.curTransition.lastAnim.joints[8].pitchPhase)) + - motion.curTransition.lastAnim.joints[8].pitchOffset; - - yawOscLast = motion.curTransition.lastAnim.joints[8].yaw * - Math.sin(filter.degToRad(motion.walkWheelPos + - motion.curTransition.lastAnim.joints[8].yawPhase)) - - rollOscLast = motion.curTransition.lastAnim.joints[8].roll * - Math.sin(filter.degToRad(motion.walkWheelPos + - motion.curTransition.lastAnim.joints[8].rollPhase)) + - motion.curTransition.lastAnim.joints[8].rollOffset; - - yawOffsetLast = motion.curTransition.lastAnim.joints[8].yawOffset; - - } else { - - pitchOsc = motion.curAnim.joints[8].pitch * - Math.sin(filter.degToRad((cycle * adjFreq) + - motion.curAnim.joints[8].pitchPhase)) + - motion.curAnim.joints[8].pitchOffset; - - yawOsc = motion.curAnim.joints[8].yaw * - Math.sin(filter.degToRad((cycle * adjFreq) + - motion.curAnim.joints[8].yawPhase)); - - rollOsc = motion.curAnim.joints[8].roll * - Math.sin(filter.degToRad((cycle * adjFreq) + - motion.curAnim.joints[8].rollPhase)) + - motion.curAnim.joints[8].rollOffset; - - yawOffset = motion.curAnim.joints[8].yawOffset; - - pitchOscLast = motion.curTransition.lastAnim.joints[8].pitch * - Math.sin(filter.degToRad(motion.cumulativeTime * - motion.curTransition.lastAnim.calibration.frequency + - motion.curTransition.lastAnim.joints[8].pitchPhase)) + - motion.curTransition.lastAnim.joints[8].pitchOffset; - - yawOscLast = motion.curTransition.lastAnim.joints[8].yaw * - Math.sin(filter.degToRad(motion.cumulativeTime * - motion.curTransition.lastAnim.calibration.frequency + - motion.curTransition.lastAnim.joints[8].yawPhase)) - - rollOscLast = motion.curTransition.lastAnim.joints[8].roll * - Math.sin(filter.degToRad(motion.cumulativeTime * - motion.curTransition.lastAnim.calibration.frequency + - motion.curTransition.lastAnim.joints[8].rollPhase)) + - motion.curTransition.lastAnim.joints[8].rollOffset; - - yawOffsetLast = motion.curTransition.lastAnim.joints[8].yawOffset; - } - - pitchOsc = (transProgress * pitchOsc) + ((1 - transProgress) * pitchOscLast); - yawOsc = (transProgress * yawOsc) + ((1 - transProgress) * yawOscLast); - rollOsc = (transProgress * rollOsc) + ((1 - transProgress) * rollOscLast); - - yawOffset = (transProgress * yawOffset) + ((1 - transProgress) * yawOffsetLast); - - } else { - - pitchOsc = motion.curAnim.joints[8].pitch * - Math.sin(filter.degToRad((cycle * adjFreq) + - motion.curAnim.joints[8].pitchPhase)) + - motion.curAnim.joints[8].pitchOffset; - - yawOsc = motion.curAnim.joints[8].yaw * - Math.sin(filter.degToRad((cycle * adjFreq) + - motion.curAnim.joints[8].yawPhase)); - - rollOsc = motion.curAnim.joints[8].roll * - Math.sin(filter.degToRad((cycle * adjFreq) + - motion.curAnim.joints[8].rollPhase)) + - motion.curAnim.joints[8].rollOffset; - - yawOffset = motion.curAnim.joints[8].yawOffset; - } - - MyAvatar.setJointData("RightShoulder", Quat.fromPitchYawRollDegrees(pitchOsc, yawOsc + yawOffset, rollOsc)); - MyAvatar.setJointData("LeftShoulder", Quat.fromPitchYawRollDegrees(pitchOsc, yawOsc - yawOffset, -rollOsc)); - - // upper arms - if (motion.curTransition !== nullTransition) { - - if (motion.curTransition.walkingAtStart) { - - pitchOsc = motion.curAnim.joints[9].pitch * - Math.sin(filter.degToRad((motion.cumulativeTime * - motion.curAnim.calibration.frequency) + - motion.curAnim.joints[9].pitchPhase)); - - yawOsc = motion.curAnim.joints[9].yaw * - Math.sin(filter.degToRad((motion.cumulativeTime * - motion.curAnim.calibration.frequency) + - motion.curAnim.joints[9].yawPhase)); - - rollOsc = motion.curAnim.joints[9].roll * - Math.sin(filter.degToRad((motion.cumulativeTime * - motion.curAnim.calibration.frequency * 2) + - motion.curAnim.joints[9].rollPhase)) + - motion.curAnim.joints[9].rollOffset; - - pitchOffset = motion.curAnim.joints[9].pitchOffset; - yawOffset = motion.curAnim.joints[9].yawOffset; - - pitchOscLast = motion.curTransition.lastAnim.joints[9].pitch * - Math.sin(filter.degToRad(motion.walkWheelPos + - motion.curTransition.lastAnim.joints[9].pitchPhase)); - - yawOscLast = motion.curTransition.lastAnim.joints[9].yaw * - Math.sin(filter.degToRad(motion.walkWheelPos + - motion.curTransition.lastAnim.joints[9].yawPhase)); - - rollOscLast = motion.curTransition.lastAnim.joints[9].roll * - Math.sin(filter.degToRad(motion.walkWheelPos + - motion.curTransition.lastAnim.joints[9].rollPhase)) + - motion.curTransition.lastAnim.joints[9].rollOffset; - - pitchOffsetLast = motion.curTransition.lastAnim.joints[9].pitchOffset; - yawOffsetLast = motion.curTransition.lastAnim.joints[9].yawOffset; - - } else { - - pitchOsc = motion.curAnim.joints[9].pitch * - Math.sin(filter.degToRad((cycle * adjFreq) + - motion.curAnim.joints[9].pitchPhase)); - - yawOsc = motion.curAnim.joints[9].yaw * - Math.sin(filter.degToRad((cycle * adjFreq) + - motion.curAnim.joints[9].yawPhase)); - - rollOsc = motion.curAnim.joints[9].roll * - Math.sin(filter.degToRad((cycle * adjFreq * 2) + - motion.curAnim.joints[9].rollPhase)) + - motion.curAnim.joints[9].rollOffset; - - pitchOffset = motion.curAnim.joints[9].pitchOffset; - yawOffset = motion.curAnim.joints[9].yawOffset; - - pitchOscLast = motion.curTransition.lastAnim.joints[9].pitch * - Math.sin(filter.degToRad(motion.cumulativeTime * - motion.curTransition.lastAnim.calibration.frequency + - motion.curTransition.lastAnim.joints[9].pitchPhase)) - - yawOscLast = motion.curTransition.lastAnim.joints[9].yaw * - Math.sin(filter.degToRad(motion.cumulativeTime * - motion.curTransition.lastAnim.calibration.frequency + - motion.curTransition.lastAnim.joints[9].yawPhase)) - - rollOscLast = motion.curTransition.lastAnim.joints[9].roll * - Math.sin(filter.degToRad(motion.cumulativeTime * - motion.curTransition.lastAnim.calibration.frequency + - motion.curTransition.lastAnim.joints[9].rollPhase)) + - motion.curTransition.lastAnim.joints[9].rollOffset; - - pitchOffsetLast = motion.curTransition.lastAnim.joints[9].pitchOffset; - yawOffsetLast = motion.curTransition.lastAnim.joints[9].yawOffset; - } - - pitchOsc = (transProgress * pitchOsc) + ((1 - transProgress) * pitchOscLast); - yawOsc = (transProgress * yawOsc) + ((1 - transProgress) * yawOscLast); - rollOsc = (transProgress * rollOsc) + ((1 - transProgress) * rollOscLast); - - pitchOffset = (transProgress * pitchOffset) + ((1 - transProgress) * pitchOffsetLast); - yawOffset = (transProgress * yawOffset) + ((1 - transProgress) * yawOffsetLast); - - } else { - - pitchOsc = motion.curAnim.joints[9].pitch * - Math.sin(filter.degToRad((cycle * adjFreq) + - motion.curAnim.joints[9].pitchPhase)); - - yawOsc = motion.curAnim.joints[9].yaw * - Math.sin(filter.degToRad((cycle * adjFreq) + - motion.curAnim.joints[9].yawPhase)); - - rollOsc = motion.curAnim.joints[9].roll * - Math.sin(filter.degToRad((cycle * adjFreq * 2) + - motion.curAnim.joints[9].rollPhase)) + - motion.curAnim.joints[9].rollOffset; - - pitchOffset = motion.curAnim.joints[9].pitchOffset; - yawOffset = motion.curAnim.joints[9].yawOffset; - - } - - MyAvatar.setJointData("RightArm", Quat.fromPitchYawRollDegrees( - (-1 * flyingModifier) * pitchOsc + pitchOffset, - yawOsc - yawOffset, - rollOsc)); - - MyAvatar.setJointData("LeftArm", Quat.fromPitchYawRollDegrees( - pitchOsc + pitchOffset, - yawOsc + yawOffset, - -rollOsc)); - - // forearms - if (motion.curTransition !== nullTransition) { - - if (motion.curTransition.walkingAtStart) { - - pitchOsc = motion.curAnim.joints[10].pitch * - Math.sin(filter.degToRad((motion.cumulativeTime * - motion.curAnim.calibration.frequency) + - motion.curAnim.joints[10].pitchPhase)) + - motion.curAnim.joints[10].pitchOffset; - - yawOsc = motion.curAnim.joints[10].yaw * - Math.sin(filter.degToRad((motion.cumulativeTime * - motion.curAnim.calibration.frequency) + - motion.curAnim.joints[10].yawPhase)); - - rollOsc = motion.curAnim.joints[10].roll * - Math.sin(filter.degToRad((motion.cumulativeTime * - motion.curAnim.calibration.frequency) + - motion.curAnim.joints[10].rollPhase)); - - yawOffset = motion.curAnim.joints[10].yawOffset; - rollOffset = motion.curAnim.joints[10].rollOffset; - - pitchOscLast = motion.curTransition.lastAnim.joints[10].pitch * - Math.sin(filter.degToRad((motion.walkWheelPos) + - motion.curTransition.lastAnim.joints[10].pitchPhase)) + - motion.curTransition.lastAnim.joints[10].pitchOffset; - - yawOscLast = motion.curTransition.lastAnim.joints[10].yaw * - Math.sin(filter.degToRad((motion.walkWheelPos) + - motion.curTransition.lastAnim.joints[10].yawPhase)); - - rollOscLast = motion.curTransition.lastAnim.joints[10].roll * - Math.sin(filter.degToRad((motion.walkWheelPos) + - motion.curTransition.lastAnim.joints[10].rollPhase)); - - yawOffsetLast = motion.curTransition.lastAnim.joints[10].yawOffset; - rollOffsetLast = motion.curTransition.lastAnim.joints[10].rollOffset; - - } else { - - pitchOsc = motion.curAnim.joints[10].pitch * - Math.sin(filter.degToRad((cycle * adjFreq) + - motion.curAnim.joints[10].pitchPhase)) + - motion.curAnim.joints[10].pitchOffset; - - yawOsc = motion.curAnim.joints[10].yaw * - Math.sin(filter.degToRad((cycle * adjFreq) + - motion.curAnim.joints[10].yawPhase)); - - rollOsc = motion.curAnim.joints[10].roll * - Math.sin(filter.degToRad((cycle * adjFreq) + - motion.curAnim.joints[10].rollPhase)); - - yawOffset = motion.curAnim.joints[10].yawOffset; - rollOffset = motion.curAnim.joints[10].rollOffset; - - pitchOscLast = motion.curTransition.lastAnim.joints[10].pitch * - Math.sin(filter.degToRad((motion.cumulativeTime * - motion.curTransition.lastAnim.calibration.frequency) + - motion.curTransition.lastAnim.joints[10].pitchPhase)) + - motion.curTransition.lastAnim.joints[10].pitchOffset; - - yawOscLast = motion.curTransition.lastAnim.joints[10].yaw * - Math.sin(filter.degToRad((motion.cumulativeTime * - motion.curTransition.lastAnim.calibration.frequency) + - motion.curTransition.lastAnim.joints[10].yawPhase)); - - rollOscLast = motion.curTransition.lastAnim.joints[10].roll * - Math.sin(filter.degToRad((motion.cumulativeTime * - motion.curTransition.lastAnim.calibration.frequency) + - motion.curTransition.lastAnim.joints[10].rollPhase)); - - yawOffsetLast = motion.curTransition.lastAnim.joints[10].yawOffset; - rollOffsetLast = motion.curTransition.lastAnim.joints[10].rollOffset; - } - - // blend the animations - pitchOsc = (transProgress * pitchOsc) + ((1 - transProgress) * pitchOscLast); - yawOsc = -(transProgress * yawOsc) + ((1 - transProgress) * yawOscLast); - rollOsc = (transProgress * rollOsc) + ((1 - transProgress) * rollOscLast); - - yawOffset = (transProgress * yawOffset) + ((1 - transProgress) * yawOffsetLast); - rollOffset = (transProgress * rollOffset) + ((1 - transProgress) * rollOffsetLast); - - } else { - - pitchOsc = motion.curAnim.joints[10].pitch * - Math.sin(filter.degToRad((cycle * adjFreq) + - motion.curAnim.joints[10].pitchPhase)) + - motion.curAnim.joints[10].pitchOffset; - - yawOsc = motion.curAnim.joints[10].yaw * - Math.sin(filter.degToRad((cycle * adjFreq) + - motion.curAnim.joints[10].yawPhase)); - - rollOsc = motion.curAnim.joints[10].roll * - Math.sin(filter.degToRad((cycle * adjFreq) + - motion.curAnim.joints[10].rollPhase)); - - yawOffset = motion.curAnim.joints[10].yawOffset; - rollOffset = motion.curAnim.joints[10].rollOffset; - } - - // apply forearms rotations - MyAvatar.setJointData("RightForeArm", - Quat.fromPitchYawRollDegrees(pitchOsc, yawOsc + yawOffset, rollOsc + rollOffset)); - MyAvatar.setJointData("LeftForeArm", - Quat.fromPitchYawRollDegrees(pitchOsc, yawOsc - yawOffset, rollOsc - rollOffset)); - - // hands - if (motion.curTransition !== nullTransition) { - - if (motion.curTransition.walkingAtStart) { - - pitchOsc = motion.curAnim.joints[11].pitch * - Math.sin(filter.degToRad((motion.cumulativeTime * - motion.curAnim.calibration.frequency) + - motion.curAnim.joints[11].pitchPhase)) + - motion.curAnim.joints[11].pitchOffset; - - yawOsc = motion.curAnim.joints[11].yaw * - Math.sin(filter.degToRad((motion.cumulativeTime * - motion.curAnim.calibration.frequency) + - motion.curAnim.joints[11].yawPhase)) + - motion.curAnim.joints[11].yawOffset; - - rollOsc = motion.curAnim.joints[11].roll * - Math.sin(filter.degToRad((motion.cumulativeTime * - motion.curAnim.calibration.frequency) + - motion.curAnim.joints[11].rollPhase)); - - pitchOscLast = motion.curTransition.lastAnim.joints[11].pitch * - Math.sin(filter.degToRad(motion.walkWheelPos + - motion.curTransition.lastAnim.joints[11].pitchPhase)) + - motion.curTransition.lastAnim.joints[11].pitchOffset; - - yawOscLast = motion.curTransition.lastAnim.joints[11].yaw * - Math.sin(filter.degToRad(motion.walkWheelPos + - motion.curTransition.lastAnim.joints[11].yawPhase)) + - motion.curTransition.lastAnim.joints[11].yawOffset; - - rollOscLast = motion.curTransition.lastAnim.joints[11].roll * - Math.sin(filter.degToRad(motion.walkWheelPos + - motion.curTransition.lastAnim.joints[11].rollPhase)) - - rollOffset = motion.curAnim.joints[11].rollOffset; - rollOffsetLast = motion.curTransition.lastAnim.joints[11].rollOffset; - - } else { - - pitchOsc = motion.curAnim.joints[11].pitch * - Math.sin(filter.degToRad((cycle * adjFreq) + - motion.curAnim.joints[11].pitchPhase)) + - motion.curAnim.joints[11].pitchOffset; - - yawOsc = motion.curAnim.joints[11].yaw * - Math.sin(filter.degToRad((cycle * adjFreq) + - motion.curAnim.joints[11].yawPhase)) + - motion.curAnim.joints[11].yawOffset; - - rollOsc = motion.curAnim.joints[11].roll * - Math.sin(filter.degToRad((cycle * adjFreq) + - motion.curAnim.joints[11].rollPhase)); - - rollOffset = motion.curAnim.joints[11].rollOffset; - - pitchOscLast = motion.curTransition.lastAnim.joints[11].pitch * - Math.sin(filter.degToRad(motion.cumulativeTime * - motion.curTransition.lastAnim.calibration.frequency + - motion.curTransition.lastAnim.joints[11].pitchPhase)) + - motion.curTransition.lastAnim.joints[11].pitchOffset; - - yawOscLast = motion.curTransition.lastAnim.joints[11].yaw * - Math.sin(filter.degToRad(motion.cumulativeTime * - motion.curTransition.lastAnim.calibration.frequency + - motion.curTransition.lastAnim.joints[11].yawPhase)) + - motion.curTransition.lastAnim.joints[11].yawOffset; - - rollOscLast = motion.curTransition.lastAnim.joints[11].roll * - Math.sin(filter.degToRad(motion.cumulativeTime * - motion.curTransition.lastAnim.calibration.frequency + - motion.curTransition.lastAnim.joints[11].rollPhase)) - - rollOffset = motion.curAnim.joints[11].rollOffset; - rollOffsetLast = motion.curTransition.lastAnim.joints[11].rollOffset; - } - - pitchOsc = (transProgress * pitchOsc) + ((1 - transProgress) * pitchOscLast); - yawOsc = (transProgress * yawOsc) + ((1 - transProgress) * yawOscLast); - rollOsc = (transProgress * rollOsc) + ((1 - transProgress) * rollOscLast); - - rollOffset = (transProgress * rollOffset) + ((1 - transProgress) * rollOffsetLast); - - } else { - - pitchOsc = motion.curAnim.joints[11].pitch * - Math.sin(filter.degToRad((cycle * adjFreq) + - motion.curAnim.joints[11].pitchPhase)) + - motion.curAnim.joints[11].pitchOffset; - - yawOsc = motion.curAnim.joints[11].yaw * - Math.sin(filter.degToRad((cycle * adjFreq) + - motion.curAnim.joints[11].yawPhase)) + - motion.curAnim.joints[11].yawOffset; - - rollOsc = motion.curAnim.joints[11].roll * - Math.sin(filter.degToRad((cycle * adjFreq) + - motion.curAnim.joints[11].rollPhase)); - - rollOffset = motion.curAnim.joints[11].rollOffset; - } - - // set the hand rotations - MyAvatar.setJointData("RightHand", - Quat.fromPitchYawRollDegrees(sideStepHandPitchSign * pitchOsc, yawOsc, rollOsc + rollOffset)); - MyAvatar.setJointData("LeftHand", - Quat.fromPitchYawRollDegrees(pitchOsc, -yawOsc, rollOsc - rollOffset)); - - } // end if (!motion.armsFree) - - // head and neck - if (motion.curTransition !== nullTransition) { - - if (motion.curTransition.walkingAtStart) { - - pitchOsc = 0.5 * motion.curAnim.joints[12].pitch * - Math.sin(filter.degToRad((motion.cumulativeTime * - motion.curAnim.calibration.frequency * 2) + - motion.curAnim.joints[12].pitchPhase)) + - motion.curAnim.joints[12].pitchOffset; - - yawOsc = 0.5 * motion.curAnim.joints[12].yaw * - Math.sin(filter.degToRad((motion.cumulativeTime * - motion.curAnim.calibration.frequency) + - motion.curAnim.joints[12].yawPhase)) + - motion.curAnim.joints[12].yawOffset; - - rollOsc = 0.5 * motion.curAnim.joints[12].roll * - Math.sin(filter.degToRad((motion.cumulativeTime * - motion.curAnim.calibration.frequency) + - motion.curAnim.joints[12].rollPhase)) + - motion.curAnim.joints[12].rollOffset; - - pitchOscLast = 0.5 * motion.curTransition.lastAnim.joints[12].pitch * - Math.sin(filter.degToRad((motion.walkWheelPos * 2) + - motion.curTransition.lastAnim.joints[12].pitchPhase)) + - motion.curTransition.lastAnim.joints[12].pitchOffset; - - yawOscLast = 0.5 * motion.curTransition.lastAnim.joints[12].yaw * - Math.sin(filter.degToRad((motion.walkWheelPos) + - motion.curTransition.lastAnim.joints[12].yawPhase)) + - motion.curTransition.lastAnim.joints[12].yawOffset; - - rollOscLast = 0.5 * motion.curTransition.lastAnim.joints[12].roll * - Math.sin(filter.degToRad((motion.walkWheelPos) + - motion.curTransition.lastAnim.joints[12].rollPhase)) + - motion.curTransition.lastAnim.joints[12].rollOffset; - - } else { - - pitchOsc = 0.5 * motion.curAnim.joints[12].pitch * - Math.sin(filter.degToRad((cycle * adjFreq * 2) + - motion.curAnim.joints[12].pitchPhase)) + - motion.curAnim.joints[12].pitchOffset; - - yawOsc = 0.5 * motion.curAnim.joints[12].yaw * - Math.sin(filter.degToRad((cycle * adjFreq) + - motion.curAnim.joints[12].yawPhase)) + - motion.curAnim.joints[12].yawOffset; - - rollOsc = 0.5 * motion.curAnim.joints[12].roll * - Math.sin(filter.degToRad((cycle * adjFreq) + - motion.curAnim.joints[12].rollPhase)) + - motion.curAnim.joints[12].rollOffset; - - pitchOscLast = 0.5 * motion.curTransition.lastAnim.joints[12].pitch * - Math.sin(filter.degToRad((motion.cumulativeTime * - motion.curTransition.lastAnim.calibration.frequency * 2) + - motion.curTransition.lastAnim.joints[12].pitchPhase)) + - motion.curTransition.lastAnim.joints[12].pitchOffset; - - yawOscLast = 0.5 * motion.curTransition.lastAnim.joints[12].yaw * - Math.sin(filter.degToRad((motion.cumulativeTime * - motion.curTransition.lastAnim.calibration.frequency) + - motion.curTransition.lastAnim.joints[12].yawPhase)) + - motion.curTransition.lastAnim.joints[12].yawOffset; - - rollOscLast = 0.5 * motion.curTransition.lastAnim.joints[12].roll * - Math.sin(filter.degToRad((motion.cumulativeTime * - motion.curTransition.lastAnim.calibration.frequency) + - motion.curTransition.lastAnim.joints[12].rollPhase)) + - motion.curTransition.lastAnim.joints[12].rollOffset; - } - - pitchOsc = (transProgress * pitchOsc) + ((1 - transProgress) * pitchOscLast); - yawOsc = (transProgress * yawOsc) + ((1 - transProgress) * yawOscLast); - rollOsc = (transProgress * rollOsc) + ((1 - transProgress) * rollOscLast); - - } else { - - pitchOsc = 0.5 * motion.curAnim.joints[12].pitch * - Math.sin(filter.degToRad((cycle * adjFreq * 2) + - motion.curAnim.joints[12].pitchPhase)) + - motion.curAnim.joints[12].pitchOffset; - - yawOsc = 0.5 * motion.curAnim.joints[12].yaw * - Math.sin(filter.degToRad((cycle * adjFreq) + - motion.curAnim.joints[12].yawPhase)) + - motion.curAnim.joints[12].yawOffset; - - rollOsc = 0.5 * motion.curAnim.joints[12].roll * - Math.sin(filter.degToRad((cycle * adjFreq) + - motion.curAnim.joints[12].rollPhase)) + - motion.curAnim.joints[12].rollOffset; - } - - MyAvatar.setJointData("Head", Quat.fromPitchYawRollDegrees(pitchOsc, yawOsc, rollOsc)); - MyAvatar.setJointData("Neck", Quat.fromPitchYawRollDegrees(pitchOsc, yawOsc, rollOsc)); -} - -// Begin by setting an internal state -state.setInternalState(state.STANDING); +// +// walk.js +// +// version 1.12 +// +// Created by David Wooldridge, Autumn 2014 +// +// Animates an avatar using procedural animation techniques +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +// constants +var MALE = 1; +var FEMALE = 2; +var MAX_WALK_SPEED = 2.5; +var TAKE_FLIGHT_SPEED = 4.55; +var TOP_SPEED = 300; +var UP = 1; +var DOWN = 2; +var LEFT = 4; +var RIGHT = 8; +var FORWARDS = 16; +var BACKWARDS = 32; +var PITCH = 64; +var YAW = 128; +var ROLL = 256; +var SAWTOOTH = 1; +var TRIANGLE = 2; +var SQUARE = 4; +var VERY_LONG_TIME = 1000000.0; +var VERY_SHORT_TIME = 0.000001; + +// ovelay images location +var pathToAssets = 'http://s3.amazonaws.com/hifi-public/procedural-animator/'; + +// load the UI +Script.include("./libraries/walkInterface.js"); + +// load filters (Bezier, Butterworth, add harmonics, averaging) +Script.include("./libraries/walkFilters.js"); + +// load objects, constructors and assets (state, Motion, Transition, walkAssets) +Script.include("./libraries/walkApi.js"); + +// initialise the motion properties and history object +var motion = new Motion(); + +// initialise Transitions +var nullTransition = new Transition(); +motion.currentTransition = nullTransition; + +// initialise the UI +walkInterface.initialise(state, motion, walkAssets); + +// Begin by setting the STANDING internal state +state.setInternalState(state.STANDING); + +// smoothing filters +var leanPitchFilter = filter.createButterworthFilter1(); +var leanPitchSmoothingFilter = filter.createAveragingFilter(10); +var leanRollSmoothingFilter = filter.createAveragingFilter(10); +var flyUpFilter = filter.createAveragingFilter(30); +var flyFilter = filter.createAveragingFilter(30); + +// Main loop +Script.update.connect(function(deltaTime) { + + if (state.powerOn) { + + // calculate avi linear speed + var speed = Vec3.length(MyAvatar.getVelocity()); + + // decide which animation should be playing + selectAnimation(deltaTime, speed); + + // turn the frequency time wheels + turnFrequencyTimeWheels(deltaTime, speed); + + // calculate (or fetch pre-calculated) stride length for this avi + setStrideLength(speed); + + // update the progress of any live transition + updateTransition(); + + // apply translation and rotations + animateAvatar(deltaTime, speed); + } +}); + +// helper function for selectAnimation() +function determineLocomotionMode(speed) { + + var locomotionMode = undefined; + + if (speed < 0.1 && motion.currentAnimation !== motion.selectedFlyBlend) { + + locomotionMode = state.STANDING; + + } else if (speed === 0 && motion.currentAnimation === motion.selectedFlyBlend) { + + locomotionMode = state.STANDING; + + } else if (speed < TAKE_FLIGHT_SPEED) { + + locomotionMode = state.WALKING; + + } else if (speed >= TAKE_FLIGHT_SPEED) { + + locomotionMode = state.FLYING; + } + + // maybe travelling at walking speed, but sideways? + if (locomotionMode === state.WALKING && + (motion.direction === LEFT || + motion.direction === RIGHT)) { + + locomotionMode = state.SIDE_STEP; + } + + // maybe completing a final step during a walking to standing transition? + if (locomotionMode === state.WALKING && + motion.currentTransition.percentToMove > 0) { + + locomotionMode = state.STANDING; + } + + // maybe starting to fly up or down? + if (locomotionMode === state.WALKING && + motion.direction === UP || motion.direction === DOWN) { + + locomotionMode = state.FLYING; + } + + // are we on a voxel surface? + if(spatialInformation.distanceToVoxels() > 0.2 && speed > 0.1) { + + locomotionMode = state.FLYING; + } + + return locomotionMode; +} + +// helper function for selectAnimation() +function determineDirection(localVelocity) { + + if (Math.abs(localVelocity.x) > Math.abs(localVelocity.y) && + Math.abs(localVelocity.x) > Math.abs(localVelocity.z)) { + + if (localVelocity.x < 0) { + return LEFT; + } else { + return RIGHT; + } + + } else if (Math.abs(localVelocity.y) > Math.abs(localVelocity.x) && + Math.abs(localVelocity.y) > Math.abs(localVelocity.z)) { + + if (localVelocity.y > 0) { + return UP; + } else { + return DOWN; + } + + } else if (Math.abs(localVelocity.z) > Math.abs(localVelocity.x) && + Math.abs(localVelocity.z) > Math.abs(localVelocity.y)) { + + if (localVelocity.z < 0) { + return FORWARDS; + } else { + return BACKWARDS; + } + } +} + +// advance the animation's frequency time wheels. advance frequency time wheels for any live transitions also +function turnFrequencyTimeWheels(deltaTime, speed) { + + var wheelAdvance = 0; + + // turn the frequency time wheel + if (motion.currentAnimation === motion.selectedWalk || + motion.currentAnimation === motion.selectedSideStepLeft || + motion.currentAnimation === motion.selectedSideStepRight) { + + // Using technique described here: http://www.gdcvault.com/play/1020583/Animation-Bootcamp-An-Indie-Approach + // wrap the stride length around a 'surveyor's wheel' twice and calculate the angular speed at the given (linear) speed + // omega = v / r , where r = circumference / 2 PI , where circumference = 2 * stride length + motion.frequencyTimeWheelRadius = motion.strideLength / Math.PI; + var angularVelocity = speed / motion.frequencyTimeWheelRadius; + + // calculate the degrees turned (at this angular speed) since last frame + wheelAdvance = filter.radToDeg(deltaTime * angularVelocity); + + } else { + + // turn the frequency time wheel by the amount specified for this animation + wheelAdvance = filter.radToDeg(motion.currentAnimation.calibration.frequency * deltaTime); + } + + if(motion.currentTransition !== nullTransition) { + + // the last animation is still playing so we turn it's frequency time wheel to maintain the animation + if (motion.currentTransition.lastAnimation === motion.selectedWalk) { + + // if at a stop angle (i.e. feet now under the avi) hold the wheel position for remainder of transition + var tolerance = motion.currentTransition.lastFrequencyTimeIncrement + 0.1; + if ((motion.currentTransition.lastFrequencyTimeWheelPos > + (motion.currentTransition.stopAngle - tolerance)) && + (motion.currentTransition.lastFrequencyTimeWheelPos < + (motion.currentTransition.stopAngle + tolerance))) { + + motion.currentTransition.lastFrequencyTimeIncrement = 0; + } + } + motion.currentTransition.advancePreviousFrequencyTimeWheel(); + } + + // advance the walk wheel the appropriate amount + motion.advanceFrequencyTimeWheel(wheelAdvance); +} + +// helper function for selectAnimation() +function setTransition(nextAnimation) { + + var lastTransition = motion.currentTransition; + motion.currentTransition = new Transition(nextAnimation, + motion.currentAnimation, + motion.currentTransition); + + if(motion.currentTransition.recursionDepth > 5) { + + delete motion.currentTransition; + motion.currentTransition = lastTransition; + } +} + +// select which animation should be played based on speed, mode of locomotion and direction of travel +function selectAnimation(deltaTime, speed) { + + var localVelocity = {x: 0, y: 0, z: 0}; + if (speed > 0) { + localVelocity = Vec3.multiplyQbyV(Quat.inverse(MyAvatar.orientation), MyAvatar.getVelocity()); + } + + // determine principle direction of movement + motion.direction = determineDirection(localVelocity); + + // determine mode of locomotion + var locomotionMode = determineLocomotionMode(speed); + + // select appropriate animation. If changing animation, initiate a new transition + // note: The transitions are work in progress: https://worklist.net/20186 + switch (locomotionMode) { + + case state.STANDING: { + + var onVoxelSurface = spatialInformation.distanceToVoxels() < 0.3 ? true : false; + + if (state.currentState !== state.STANDING) { + + if (onVoxelSurface) { + + setTransition(motion.selectedStand); + + } else { + + setTransition(motion.selectedHovering); + } + state.setInternalState(state.STANDING); + } + if (onVoxelSurface) { + + motion.currentAnimation = motion.selectedStand; + + } else { + + motion.currentAnimation = motion.selectedHovering; + } + break; + } + + case state.WALKING: { + + if (state.currentState !== state.WALKING) { + + setTransition(motion.selectedWalk); + // set the walk wheel to it's starting point for this animation + if (motion.direction === BACKWARDS) { + + motion.frequencyTimeWheelPos = motion.selectedWalk.calibration.startAngleBackwards; + + } else { + + motion.frequencyTimeWheelPos = motion.selectedWalk.calibration.startAngleForwards; + } + state.setInternalState(state.WALKING); + } + motion.currentAnimation = motion.selectedWalk; + break; + } + + case state.SIDE_STEP: { + + var selSideStep = undefined; + + if (state.currentState !== state.SIDE_STEP) { + + if (motion.direction === LEFT) { + // set the walk wheel to it's starting point for this animation + motion.frequencyTimeWheelPos = motion.selectedSideStepLeft.calibration.startAngle; + selSideStep = motion.selectedSideStepLeft; + + } else { + // set the walk wheel to it's starting point for this animation + motion.frequencyTimeWheelPos = motion.selectedSideStepRight.calibration.startAngle; + selSideStep = motion.selectedSideStepRight; + } + setTransition(selSideStep); + state.setInternalState(state.SIDE_STEP); + + } else if (motion.direction === LEFT) { + + if (motion.lastDirection !== LEFT) { + // set the walk wheel to it's starting point for this animation + motion.frequencyTimeWheelPos = motion.selectedSideStepLeft.calibration.startAngle; + setTransition(motion.selectedSideStepLeft); + } + selSideStep = motion.selectedSideStepLeft; + + } else { + + if (motion.lastDirection !== RIGHT) { + // set the walk wheel to it's starting point for this animation + motion.frequencyTimeWheelPos = motion.selectedSideStepRight.calibration.startAngle; + setTransition(motion.selectedSideStepRight); + } + selSideStep = motion.selectedSideStepRight; + } + motion.currentAnimation = selSideStep; + break; + } + + case state.FLYING: { + + // blend the up, down and forward flying animations relative to motion direction + animation.zeroAnimation(motion.selectedFlyBlend); + + var upVector = 0; + var forwardVector = 0; + + if (speed > 0) { + + // calculate directionals + upVector = localVelocity.y / speed; + forwardVector = -localVelocity.z / speed; + + // add damping + upVector = flyUpFilter.process(upVector); + forwardVector = flyFilter.process(forwardVector); + + // normalise + var denominator = Math.abs(upVector) + Math.abs(forwardVector); + upVector = upVector / denominator; + forwardVector = forwardVector / denominator; + } + + if (upVector > 0) { + + animation.blendAnimation(motion.selectedFlyUp, + motion.selectedFlyBlend, + upVector); + + } else if (upVector < 0) { + + animation.blendAnimation(motion.selectedFlyDown, + motion.selectedFlyBlend, + -upVector); + } else { + + forwardVector = 1; + } + animation.blendAnimation(motion.selectedFly, + motion.selectedFlyBlend, + Math.abs(forwardVector)); + + if (state.currentState !== state.FLYING) { + + state.setInternalState(state.FLYING); + setTransition(motion.selectedFlyBlend); + } + motion.currentAnimation = motion.selectedFlyBlend; + break; + } + + } // end switch(locomotionMode) + + // record frame details for future reference + motion.lastDirection = motion.direction; + motion.lastSpeed = localVelocity; + motion.lastDistanceToVoxels = motion.calibration.distanceToVoxels; + + return; +} + +// if the timing's right, recalculate the stride length. if not, fetch the previously calculated value +function setStrideLength(speed) { + + // if not at full speed the calculation could be wrong, as we may still be transitioning + var atMaxSpeed = speed / MAX_WALK_SPEED < 0.97 ? false : true; + + // walking? then get the stride length + if (motion.currentAnimation === motion.selectedWalk) { + + var strideMaxAt = motion.currentAnimation.calibration.forwardStrideMaxAt; + if (motion.direction === BACKWARDS) { + strideMaxAt = motion.currentAnimation.calibration.backwardsStrideMaxAt; + } + + var tolerance = 1.0; + if (motion.frequencyTimeWheelPos < (strideMaxAt + tolerance) && + motion.frequencyTimeWheelPos > (strideMaxAt - tolerance) && + atMaxSpeed && motion.currentTransition === nullTransition) { + + // measure and save stride length + var footRPos = MyAvatar.getJointPosition("RightFoot"); + var footLPos = MyAvatar.getJointPosition("LeftFoot"); + motion.strideLength = Vec3.distance(footRPos, footLPos); + + if (motion.direction === FORWARDS) { + motion.currentAnimation.calibration.strideLengthForwards = motion.strideLength; + } else if (motion.direction === BACKWARDS) { + motion.currentAnimation.calibration.strideLengthBackwards = motion.strideLength; + } + + } else { + + // use the previously saved value for stride length + if (motion.direction === FORWARDS) { + motion.strideLength = motion.currentAnimation.calibration.strideLengthForwards; + } else if (motion.direction === BACKWARDS) { + motion.strideLength = motion.currentAnimation.calibration.strideLengthBackwards; + } + } + } // end get walk stride length + + // sidestepping? get the stride length + if (motion.currentAnimation === motion.selectedSideStepLeft || + motion.currentAnimation === motion.selectedSideStepRight) { + + // if the timing's right, take a snapshot of the stride max and recalibrate the stride length + var tolerance = 1.0; + if (motion.direction === LEFT) { + + if (motion.frequencyTimeWheelPos < motion.currentAnimation.calibration.strideMaxAt + tolerance && + motion.frequencyTimeWheelPos > motion.currentAnimation.calibration.strideMaxAt - tolerance && + atMaxSpeed && motion.currentTransition === nullTransition) { + + var footRPos = MyAvatar.getJointPosition("RightFoot"); + var footLPos = MyAvatar.getJointPosition("LeftFoot"); + motion.strideLength = Vec3.distance(footRPos, footLPos); + motion.currentAnimation.calibration.strideLength = motion.strideLength; + + } else { + + motion.strideLength = motion.selectedSideStepLeft.calibration.strideLength; + } + + } else if (motion.direction === RIGHT) { + + if (motion.frequencyTimeWheelPos < motion.currentAnimation.calibration.strideMaxAt + tolerance && + motion.frequencyTimeWheelPos > motion.currentAnimation.calibration.strideMaxAt - tolerance && + atMaxSpeed && motion.currentTransition === nullTransition) { + + var footRPos = MyAvatar.getJointPosition("RightFoot"); + var footLPos = MyAvatar.getJointPosition("LeftFoot"); + motion.strideLength = Vec3.distance(footRPos, footLPos); + motion.currentAnimation.calibration.strideLength = motion.strideLength; + + } else { + + motion.strideLength = motion.selectedSideStepRight.calibration.strideLength; + } + } + } // end get sidestep stride length +} + +// initialise a new transition. update progress of a live transition +function updateTransition() { + + if (motion.currentTransition !== nullTransition) { + + // new transition? + if (motion.currentTransition.progress === 0) { + + // overlapping transitions? + if (motion.currentTransition.lastTransition !== nullTransition) { + + // is the last animation for the nested transition the same as the new animation? + if (motion.currentTransition.lastTransition.lastAnimation === motion.currentAnimation) { + + // sync the nested transitions's frequency time wheel for a smooth animation blend + motion.frequencyTimeWheelPos = motion.currentTransition.lastTransition.lastFrequencyTimeWheelPos; + } + } + + if (motion.currentTransition.lastAnimation === motion.selectedWalk) { + + // decide at which angle we should stop the frequency time wheel + var stopAngle = motion.selectedWalk.calibration.stopAngleForwards; + var percentToMove = 0; + var lastFrequencyTimeWheelPos = motion.currentTransition.lastFrequencyTimeWheelPos; + var lastElapsedFTDegrees = motion.currentTransition.lastElapsedFTDegrees; + + // set the stop angle depending on which quadrant of the walk cycle we are currently in + // and decide whether we need to take an extra step to complete the walk cycle or not + // - currently work in progress + if(lastFrequencyTimeWheelPos <= stopAngle && lastElapsedFTDegrees < 180) { + + // we have not taken a complete step yet, so we do need to do so before stopping + percentToMove = 100; + stopAngle += 180; + + } else if(lastFrequencyTimeWheelPos > stopAngle && lastFrequencyTimeWheelPos <= stopAngle + 90) { + + // take an extra step to complete the walk cycle and stop at the second stop angle + percentToMove = 100; + stopAngle += 180; + + } else if(lastFrequencyTimeWheelPos > stopAngle + 90 && lastFrequencyTimeWheelPos <= stopAngle + 180) { + + // stop on the other foot at the second stop angle for this walk cycle + percentToMove = 0; + if (motion.currentTransition.lastDirection === BACKWARDS) { + + percentToMove = 100; + + } else { + + stopAngle += 180; + } + + } else if(lastFrequencyTimeWheelPos > stopAngle + 180 && lastFrequencyTimeWheelPos <= stopAngle + 270) { + + // take an extra step to complete the walk cycle and stop at the first stop angle + percentToMove = 100; + } + + // set it all in motion + motion.currentTransition.stopAngle = stopAngle; + motion.currentTransition.percentToMove = percentToMove; + } + + } // end if new transition + + // update the Transition progress + if (motion.currentTransition.updateProgress() >= 1) { + + // it's time to kill off this transition + delete motion.currentTransition; + motion.currentTransition = nullTransition; + } + } +} + +// helper function for animateAvatar(). calculate the amount to lean forwards (or backwards) based on the avi's acceleration +function getLeanPitch(speed) { + + var leanProgress = undefined; + + if (motion.direction === LEFT || + motion.direction === RIGHT || + motion.direction === UP) { + + leanProgress = 0; + + } else { + + // boost lean for flying (leaning whilst walking is work in progress) + var signedSpeed = -Vec3.multiplyQbyV(Quat.inverse(MyAvatar.orientation), MyAvatar.getVelocity()).z; + var reverseMod = 1; + var BOOST = 6; + + if (signedSpeed < 0) { + + reverseMod = -1.9; + if (motion.direction === DOWN) { + + reverseMod *= -1; + } + } + leanProgress = reverseMod * BOOST * speed / TOP_SPEED; + } + + // use filters to shape the walking acceleration response + leanProgress = leanPitchFilter.process(leanProgress); + leanProgress = leanPitchSmoothingFilter.process(leanProgress); + return motion.calibration.pitchMax * leanProgress; +} + +// helper function for animateAvatar(). calculate the angle at which to bank into corners whilst turning +function getLeanRoll(deltaTime, speed) { + + var leanRollProgress = 0; + var angularVelocity = filter.radToDeg(MyAvatar.getAngularVelocity().y); + + leanRollProgress = speed / TOP_SPEED; + leanRollProgress *= Math.abs(angularVelocity) / motion.calibration.angularVelocityMax; + + // shape the response curve + leanRollProgress = filter.bezier((1 - leanRollProgress), + {x: 0, y: 0}, {x: 0, y: 1.3}, {x: 0.25, y: 0.5}, {x: 1, y: 1}).y; + + // which way to lean? + var turnSign = -1; + if (angularVelocity < 0.001) { + + turnSign = 1; + } + if (motion.direction === BACKWARDS || + motion.direction === LEFT) { + + turnSign *= -1; + } + + // add damping with averaging filter + leanRollProgress = leanRollSmoothingFilter.process(turnSign * leanRollProgress); + return motion.calibration.rollMax * leanRollProgress; +} + +// check for existence of object property (e.g. animation waveform synthesis filters) +function isDefined(value) { + + try { + if (typeof value != 'undefined') return true; + } catch (e) { + return false; + } +} + +// helper function for animateAvatar(). calculate joint translations based on animation file settings and frequency * time +function calculateTranslations(animation, ft, direction) { + + var jointName = "Hips"; + var joint = animation.joints[jointName]; + var jointTranslations = {x:0, y:0, z:0}; + + // gather modifiers and multipliers + modifiers = new JointModifiers(joint, direction); + + // calculate translations. Use synthesis filters where specified by the animation file. + + // sway (oscillation on the x-axis) + if(animation.filters.hasOwnProperty(jointName) && + 'swayFilter' in animation.filters[jointName]) { + + jointTranslations.x = joint.sway * + animation.filters[jointName].swayFilter. + calculate(filter.degToRad(ft + joint.swayPhase)) + + joint.swayOffset; + + } else { + + jointTranslations.x = joint.sway * + Math.sin(filter.degToRad(ft + joint.swayPhase)) + + joint.swayOffset; + } + + // bob (oscillation on the y-axis) + if(animation.filters.hasOwnProperty(jointName) && + 'bobFilter' in animation.filters[jointName]) { + + jointTranslations.y = joint.bob * + animation.filters[jointName].bobFilter.calculate + (filter.degToRad(modifiers.bobFrequencyMultiplier * ft + + joint.bobPhase + modifiers.bobReverseModifier)) + + joint.bobOffset; + + } else { + + jointTranslations.y = joint.bob * + Math.sin(filter.degToRad(modifiers.bobFrequencyMultiplier * ft + + joint.bobPhase + modifiers.bobReverseModifier)) + + joint.bobOffset; + + // check for specified low pass filter for this joint (currently Hips bob only) + if(animation.filters.hasOwnProperty(jointName) && + 'bobLPFilter' in animation.filters[jointName]) { + + jointTranslations.y = filter.clipTrough(jointTranslations.y, joint, 2); + jointTranslations.y = animation.filters[jointName].bobLPFilter.process(jointTranslations.y); + } + } + + // thrust (oscillation on the z-axis) + if(animation.filters.hasOwnProperty(jointName) && + 'thrustFilter' in animation.filters[jointName]) { + + jointTranslations.z = joint.thrust * + animation.filters[jointName].thrustFilter. + calculate(filter.degToRad(modifiers.thrustFrequencyMultiplier * ft + + joint.thrustPhase)) + + joint.thrustOffset; + + } else { + + jointTranslations.z = joint.thrust * + Math.sin(filter.degToRad(modifiers.thrustFrequencyMultiplier * ft + + joint.thrustPhase)) + + joint.thrustOffset; + } + + return jointTranslations; +} + +// helper function for animateAvatar(). calculate joint rotations based on animation file settings and frequency * time +function calculateRotations(jointName, animation, ft, direction) { + + var joint = animation.joints[jointName]; + var jointRotations = {x:0, y:0, z:0}; + + // gather modifiers and multipliers for this joint + modifiers = new JointModifiers(joint, direction); + + // calculate rotations. Use synthesis filters where specified by the animation file. + + // calculate pitch + if(animation.filters.hasOwnProperty(jointName) && + 'pitchFilter' in animation.filters[jointName]) { + + jointRotations.x = modifiers.pitchReverseInvert * (modifiers.pitchSign * joint.pitch * + animation.filters[jointName].pitchFilter.calculate + (filter.degToRad(ft * modifiers.pitchFrequencyMultiplier + + joint.pitchPhase + modifiers.pitchPhaseModifier + modifiers.pitchReverseModifier)) + + modifiers.pitchOffsetSign * joint.pitchOffset); + + } else { + + jointRotations.x = modifiers.pitchReverseInvert * (modifiers.pitchSign * joint.pitch * + Math.sin(filter.degToRad(ft * modifiers.pitchFrequencyMultiplier + + joint.pitchPhase + modifiers.pitchPhaseModifier + modifiers.pitchReverseModifier)) + + modifiers.pitchOffsetSign * joint.pitchOffset); + } + + // calculate yaw + if(animation.filters.hasOwnProperty(jointName) && + 'yawFilter' in animation.filters[jointName]) { + + jointRotations.y = modifiers.yawSign * joint.yaw * + animation.filters[jointName].yawFilter.calculate + (filter.degToRad(ft + joint.yawPhase + modifiers.yawReverseModifier)) + + modifiers.yawOffsetSign * joint.yawOffset; + + } else { + + jointRotations.y = modifiers.yawSign * joint.yaw * + Math.sin(filter.degToRad(ft + joint.yawPhase + modifiers.yawReverseModifier)) + + modifiers.yawOffsetSign * joint.yawOffset; + } + + // calculate roll + if(animation.filters.hasOwnProperty(jointName) && + 'rollFilter' in animation.filters[jointName]) { + + jointRotations.z = modifiers.rollSign * joint.roll * + animation.filters[jointName].rollFilter.calculate + (filter.degToRad(ft + joint.rollPhase + modifiers.rollReverseModifier)) + + modifiers.rollOffsetSign * joint.rollOffset; + + } else { + + jointRotations.z = modifiers.rollSign * joint.roll * + Math.sin(filter.degToRad(ft + joint.rollPhase + modifiers.rollReverseModifier)) + + modifiers.rollOffsetSign * joint.rollOffset; + } + return jointRotations; +} + +// animate the avatar using sine waves, geometric waveforms and harmonic generators +function animateAvatar(deltaTime, speed) { + + // adjust leaning direction for flying + var flyingModifier = 1; + if (state.currentState.FLYING) { + + flyingModifier = -1; + } + + // leaning in response to speed and acceleration (affects Hips pitch and z-axis acceleration driven offset) + var leanPitch = getLeanPitch(speed); + + // hips translations + var hipsTranslations = undefined; + if (motion.currentTransition !== nullTransition) { + + hipsTranslations = motion.currentTransition.blendTranslations(motion.frequencyTimeWheelPos, motion.direction); + + } else { + + hipsTranslations = calculateTranslations(motion.currentAnimation, + motion.frequencyTimeWheelPos, + motion.direction); + } + + // factor in any acceleration driven leaning + hipsTranslations.z += motion.calibration.hipsToFeet * Math.sin(filter.degToRad(leanPitch)); + + // apply translations + MyAvatar.setSkeletonOffset(hipsTranslations); + + // joint rotations + for (jointName in walkAssets.animationReference.joints) { + + // ignore arms rotations if 'arms free' is selected for Leap / Hydra use + if((walkAssets.animationReference.joints[jointName].IKChain === "LeftArm" || + walkAssets.animationReference.joints[jointName].IKChain === "RightArm") && + motion.armsFree) { + + continue; + } + + if (isDefined(motion.currentAnimation.joints[jointName])) { + + var jointRotations = undefined; + + // if there's a live transition, blend the rotations with the last animation's rotations for this joint + if (motion.currentTransition !== nullTransition) { + + jointRotations = motion.currentTransition.blendRotations(jointName, + motion.frequencyTimeWheelPos, + motion.direction); + } else { + + jointRotations = calculateRotations(jointName, + motion.currentAnimation, + motion.frequencyTimeWheelPos, + motion.direction); + } + + // apply lean + if (jointName === "Hips") { + + jointRotations.x += leanPitch; + jointRotations.z += getLeanRoll(deltaTime, speed); + } + + // apply rotation + MyAvatar.setJointData(jointName, Quat.fromVec3Degrees(jointRotations)); + } + } +} \ No newline at end of file From efdc8f54948f2a031b4b77d607dcfa104b7266d9 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 4 Dec 2014 10:19:51 -0800 Subject: [PATCH 204/502] Fix stretch tools to work correctly with registrationPoint --- examples/libraries/entitySelectionTool.js | 43 ++++++++++++++--------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/examples/libraries/entitySelectionTool.js b/examples/libraries/entitySelectionTool.js index 3e50bff8f7..16dc52b239 100644 --- a/examples/libraries/entitySelectionTool.js +++ b/examples/libraries/entitySelectionTool.js @@ -1428,6 +1428,8 @@ SelectionDisplay = (function () { var initialDimensions = null; var initialIntersection = null; var initialProperties = null; + var registrationPoint = null; + var deltaPivot = null; var pickRayPosition = null; var rotation = null; @@ -1440,18 +1442,29 @@ SelectionDisplay = (function () { rotation = SelectionManager.localRotation; initialPosition = SelectionManager.localPosition; initialDimensions = SelectionManager.localDimensions; + registrationPoint = SelectionManager.localRegistrationPoint; } else { rotation = SelectionManager.worldRotation; initialPosition = SelectionManager.worldPosition; initialDimensions = SelectionManager.worldDimensions; + registrationPoint = SelectionManager.worldRegistrationPoint; } - var scaledOffset = { - x: initialDimensions.x * offset.x * 0.5, - y: initialDimensions.y * offset.y * 0.5, - z: initialDimensions.z * offset.z * 0.5, - }; - pickRayPosition = Vec3.sum(initialPosition, Vec3.multiplyQbyV(rotation, scaledOffset)); + // Modify range of registrationPoint to be [-0.5, 0.5] + var centeredRP = Vec3.subtract(registrationPoint, { x: 0.5, y: 0.5, z: 0.5 }); + + // Scale pivot to be in the same range as registrationPoint + var scaledPivot = Vec3.multiply(0.5, pivot) + deltaPivot = Vec3.subtract(centeredRP, scaledPivot); + + var scaledOffset = Vec3.multiply(0.5, offset); + + // Offset from the registration point + offsetRP = Vec3.subtract(scaledOffset, centeredRP); + + // Scaled offset in world coordinates + var scaledOffsetWorld = vec3Mult(initialDimensions, offsetRP); + pickRayPosition = Vec3.sum(initialPosition, Vec3.multiplyQbyV(rotation, scaledOffsetWorld)); if (numDimensions == 1 && mask.x) { var start = Vec3.multiplyQbyV(rotation, { x: -10000, y: 0, z: 0 }); @@ -1578,8 +1591,7 @@ SelectionDisplay = (function () { newDimensions.y = Math.max(newDimensions.y, MINIMUM_DIMENSION); newDimensions.z = Math.max(newDimensions.z, MINIMUM_DIMENSION); - var p = Vec3.multiply(0.5, pivot); - var changeInPosition = Vec3.multiplyQbyV(rotation, vec3Mult(p, changeInDimensions)); + var changeInPosition = Vec3.multiplyQbyV(rotation, vec3Mult(deltaPivot, changeInDimensions)); var newPosition = Vec3.sum(initialPosition, changeInPosition); for (var i = 0; i < SelectionManager.selections.length; i++) { @@ -1617,20 +1629,19 @@ SelectionDisplay = (function () { function addStretchTool(overlay, mode, pivot, direction, offset) { if (!pivot) { - pivot = Vec3.multiply(-1, direction); - pivot.y = direction.y; + pivot = direction; } var tool = makeStretchTool(mode, direction, pivot, offset); addGrabberTool(overlay, tool); } - addStretchTool(grabberNEAR, "STRETCH_NEAR", { x: 0, y: 0, z: -1 }, { x: 0, y: 0, z: 1 }, { x: 0, y: 0, z: -1 }); - addStretchTool(grabberFAR, "STRETCH_FAR", { x: 0, y: 0, z: 1 }, { x: 0, y: 0, z: -1 }, { x: 0, y: 0, z: 1 }); - addStretchTool(grabberTOP, "STRETCH_TOP", { x: 0, y: 1, z: 0 }, { x: 0, y: -1, z: 0 }, { x: 0, y: 1, z: 0 }); - addStretchTool(grabberBOTTOM, "STRETCH_BOTTOM", { x: 0, y: -1, z: 0 }, { x: 0, y: 1, z: 0 }, { x: 0, y: -1, z: 0 }); - addStretchTool(grabberRIGHT, "STRETCH_RIGHT", { x: 1, y: 0, z: 0 }, { x: -1, y: 0, z: 0 }, { x: 1, y: 0, z: 0 }); - addStretchTool(grabberLEFT, "STRETCH_LEFT", { x: -1, y: 0, z: 0 }, { x: 1, y: 0, z: 0 }, { x: -1, y: 0, z: 0 }); + addStretchTool(grabberNEAR, "STRETCH_NEAR", { x: 0, y: 0, z: 1 }, { x: 0, y: 0, z: 1 }, { x: 0, y: 0, z: -1 }); + addStretchTool(grabberFAR, "STRETCH_FAR", { x: 0, y: 0, z: -1 }, { x: 0, y: 0, z: -1 }, { x: 0, y: 0, z: 1 }); + addStretchTool(grabberTOP, "STRETCH_TOP", { x: 0, y: -1, z: 0 }, { x: 0, y: -1, z: 0 }, { x: 0, y: 1, z: 0 }); + addStretchTool(grabberBOTTOM, "STRETCH_BOTTOM", { x: 0, y: 1, z: 0 }, { x: 0, y: 1, z: 0 }, { x: 0, y: -1, z: 0 }); + addStretchTool(grabberRIGHT, "STRETCH_RIGHT", { x: -1, y: 0, z: 0 }, { x: -1, y: 0, z: 0 }, { x: 1, y: 0, z: 0 }); + addStretchTool(grabberLEFT, "STRETCH_LEFT", { x: 1, y: 0, z: 0 }, { x: 1, y: 0, z: 0 }, { x: -1, y: 0, z: 0 }); addStretchTool(grabberLBN, "STRETCH_LBN", null, {x: 1, y: 0, z: 1}, { x: -1, y: -1, z: -1 }); addStretchTool(grabberRBN, "STRETCH_RBN", null, {x: -1, y: 0, z: 1}, { x: 1, y: -1, z: -1 }); From b2c5b19fd7228f569a4e86db585b335acee1c8bf Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 4 Dec 2014 10:20:02 -0800 Subject: [PATCH 205/502] Remove print --- examples/libraries/gridTool.js | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/libraries/gridTool.js b/examples/libraries/gridTool.js index aa412b1a76..7d98befec8 100644 --- a/examples/libraries/gridTool.js +++ b/examples/libraries/gridTool.js @@ -90,7 +90,6 @@ Grid = function(opts) { } that.snapToSpacing = function(delta, majorOnly) { - print('snaptogrid? ' + snapToGrid); if (!snapToGrid) { return delta; } From acd5495b2ab4a2ef33eb62312d27cff351a36a3a Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 4 Dec 2014 10:29:10 -0800 Subject: [PATCH 206/502] Add getRelativeCenterPosition --- examples/libraries/entitySelectionTool.js | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/examples/libraries/entitySelectionTool.js b/examples/libraries/entitySelectionTool.js index 16dc52b239..e30b9d2d95 100644 --- a/examples/libraries/entitySelectionTool.js +++ b/examples/libraries/entitySelectionTool.js @@ -218,6 +218,17 @@ function normalizeDegrees(degrees) { return degrees; } +// Return the enter position of an entity relative to it's registrationPoint +// A registration point of (0.5, 0.5, 0.5) will have an offset of (0, 0, 0) +// A registration point of (1.0, 1.0, 1.0) will have an offset of (-dimensions.x / 2, -dimensions.y / 2, -dimensions.z / 2) +function getRelativeCenterPosition(dimensions, registrationPoint) { + return { + x: -dimensions.x * (registrationPoint.x - 0.5), + y: -dimensions.y * (registrationPoint.y - 0.5), + z: -dimensions.z * (registrationPoint.z - 0.5), + } +} + SelectionDisplay = (function () { var that = {}; @@ -1005,12 +1016,7 @@ SelectionDisplay = (function () { z: dimensions.z * registrationPoint.z, }; - // Center of entity, relative to registration point - var center = { - x: dimensions.x / 2 - registrationPointDimensions.x, - y: dimensions.y / 2 - registrationPointDimensions.y, - z: dimensions.z / 2 - registrationPointDimensions.z, - }; + center = getRelativeCenterPosition(position, dimensions, registrationPoint); // Distances in world coordinates relative to the registration point var left = -registrationPointDimensions.x; From 1f82831bcc0ea6a01d4ea7d2748f173173557d6f Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 4 Dec 2014 10:47:09 -0800 Subject: [PATCH 207/502] Fix call to getRelativeCenterPosition --- examples/libraries/entitySelectionTool.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/libraries/entitySelectionTool.js b/examples/libraries/entitySelectionTool.js index e30b9d2d95..2953203fc6 100644 --- a/examples/libraries/entitySelectionTool.js +++ b/examples/libraries/entitySelectionTool.js @@ -1016,7 +1016,8 @@ SelectionDisplay = (function () { z: dimensions.z * registrationPoint.z, }; - center = getRelativeCenterPosition(position, dimensions, registrationPoint); + // Center of entity, relative to registration point + center = getRelativeCenterPosition(dimensions, registrationPoint); // Distances in world coordinates relative to the registration point var left = -registrationPointDimensions.x; From 11f10f95122f71dfe816d2e16f1d9c4ffd95423d Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 4 Dec 2014 10:54:04 -0800 Subject: [PATCH 208/502] make sphere entities pick off their actual sphere, fix bug in ray picking multiple items with different distances --- libraries/entities/src/EntityTreeElement.cpp | 17 ++++++++++----- libraries/entities/src/SphereEntityItem.cpp | 23 ++++++++++++++++++++ libraries/entities/src/SphereEntityItem.h | 5 +++++ 3 files changed, 39 insertions(+), 6 deletions(-) diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index 3f73a05679..e18f79276e 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -516,17 +516,22 @@ bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, con if (entity->findDetailedRayIntersection(origin, direction, keepSearching, element, localDistance, localFace, intersectedObject)) { + + if (localDistance < distance) { + distance = localDistance; + face = localFace; + *intersectedObject = (void*)entity; + somethingIntersected = true; + } + } + } else { + // if the entity type doesn't support a detailed intersection, then just return the non-AABox results + if (localDistance < distance) { distance = localDistance; face = localFace; *intersectedObject = (void*)entity; somethingIntersected = true; } - } else { - // if the entity type doesn't support a detailed intersection, then just return the non-AABox results - distance = localDistance; - face = localFace; - *intersectedObject = (void*)entity; - somethingIntersected = true; } } } diff --git a/libraries/entities/src/SphereEntityItem.cpp b/libraries/entities/src/SphereEntityItem.cpp index f5b8eb27e9..12fdd7a8c4 100644 --- a/libraries/entities/src/SphereEntityItem.cpp +++ b/libraries/entities/src/SphereEntityItem.cpp @@ -93,3 +93,26 @@ void SphereEntityItem::recalculateCollisionShape() { float largestDiameter = glm::max(dimensionsInMeters.x, dimensionsInMeters.y, dimensionsInMeters.z); _sphereShape.setRadius(largestDiameter / 2.0f); } + +bool SphereEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, + bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, + void** intersectedObject) const { + + // NOTE: origin and direction are in tree units. But our _sphereShape is in meters, so we need to + // do a little math to make these match each other. + RayIntersectionInfo rayInfo; + rayInfo._rayStart = origin * (float)TREE_SCALE; + rayInfo._rayDirection = direction; + + // TODO: Note this is really doing ray intersections against a sphere, which is fine except in cases + // where our dimensions actually make us an ellipsoid. But we'll live with this for now until we + // get a more full fledged physics library + if (_sphereShape.findRayIntersection(rayInfo)) { + distance = rayInfo._hitDistance / (float)TREE_SCALE; + return true; + } + return false; +} + + + diff --git a/libraries/entities/src/SphereEntityItem.h b/libraries/entities/src/SphereEntityItem.h index 21cb58223b..bb4f41726c 100644 --- a/libraries/entities/src/SphereEntityItem.h +++ b/libraries/entities/src/SphereEntityItem.h @@ -56,6 +56,11 @@ public: // TODO: implement proper contains for 3D ellipsoid //virtual bool contains(const glm::vec3& point) const; + virtual bool supportsDetailedRayIntersection() const { return true; } + virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, + bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, + void** intersectedObject) const; + protected: virtual void recalculateCollisionShape(); From 3b6936b47d842035ca0cb5a403618775ce2d0f06 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 4 Dec 2014 11:16:01 -0800 Subject: [PATCH 209/502] Changed Mag and reticules data representation --- interface/src/devices/SixenseManager.cpp | 2 - interface/src/ui/ApplicationOverlay.cpp | 782 +++++++++++------------ interface/src/ui/ApplicationOverlay.h | 28 +- 3 files changed, 380 insertions(+), 432 deletions(-) diff --git a/interface/src/devices/SixenseManager.cpp b/interface/src/devices/SixenseManager.cpp index 6d227027ed..7a555eb902 100644 --- a/interface/src/devices/SixenseManager.cpp +++ b/interface/src/devices/SixenseManager.cpp @@ -540,8 +540,6 @@ void SixenseManager::emulateMouse(PalmData* palm, int index) { //a magnification window was clicked on int clickX = pos.x(); int clickY = pos.y(); - //Checks for magnification window click - application->getApplicationOverlay().getClickLocation(clickX, clickY); //Set pos to the new click location, which may be the same if no magnification window is open pos.setX(clickX); pos.setY(clickY); diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 8a55408bd1..5a644718c7 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -30,9 +30,13 @@ const quint64 MSECS_TO_USECS = 1000ULL; const float WHITE_TEXT[] = { 0.93f, 0.93f, 0.93f }; const float RETICLE_COLOR[] = { 0.0f, 198.0f / 255.0f, 244.0f / 255.0f }; +static const float MOUSE_PITCH_RANGE = 1.0f * PI; +static const float MOUSE_YAW_RANGE = 0.5f * TWO_PI; + const float CONNECTION_STATUS_BORDER_COLOR[] = { 1.0f, 0.0f, 0.0f }; const float CONNECTION_STATUS_BORDER_LINE_WIDTH = 4.0f; + // Return a point's coordinates on a sphere from it's polar (theta) and azimutal (phi) angles. glm::vec3 getPoint(float radius, float theta, float phi) { return glm::vec3(radius * glm::sin(theta) * glm::sin(phi), @@ -40,6 +44,86 @@ glm::vec3 getPoint(float radius, float theta, float phi) { radius * glm::sin(theta) * (-glm::cos(phi))); } +//Checks if the given ray intersects the sphere at the origin. result will store a multiplier that should +//be multiplied by dir and added to origin to get the location of the collision +bool raySphereIntersect(const glm::vec3 &dir, const glm::vec3 &origin, float r, float* result) +{ + //Source: http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection + + //Compute A, B and C coefficients + float a = glm::dot(dir, dir); + float b = 2 * glm::dot(dir, origin); + float c = glm::dot(origin, origin) - (r * r); + + //Find discriminant + float disc = b * b - 4 * a * c; + + // if discriminant is negative there are no real roots, so return + // false as ray misses sphere + if (disc < 0) { + return false; + } + + // compute q as described above + float distSqrt = sqrtf(disc); + float q; + if (b < 0) { + q = (-b - distSqrt) / 2.0; + } else { + q = (-b + distSqrt) / 2.0; + } + + // compute t0 and t1 + float t0 = q / a; + float t1 = c / q; + + // make sure t0 is smaller than t1 + if (t0 > t1) { + // if t0 is bigger than t1 swap them around + float temp = t0; + t0 = t1; + t1 = temp; + } + + // if t1 is less than zero, the object is in the ray's negative direction + // and consequently the ray misses the sphere + if (t1 < 0) { + return false; + } + + // if t0 is less than zero, the intersection point is at t1 + if (t0 < 0) { + *result = t1; + return true; + } else { // else the intersection point is at t0 + *result = t0; + return true; + } +} + +void renderReticule(glm::quat orientation, float alpha) { + const float reticleSize = TWO_PI / 80.0f; + + glm::vec3 topLeft = getPoint(1.0f, PI_OVER_TWO + reticleSize / 2.0f, - reticleSize / 2.0f); + glm::vec3 topRight = getPoint(1.0f, PI_OVER_TWO + reticleSize / 2.0f, + reticleSize / 2.0f); + glm::vec3 bottomLeft = getPoint(1.0f, PI_OVER_TWO - reticleSize / 2.0f, - reticleSize / 2.0f); + glm::vec3 bottomRight = getPoint(1.0f, PI_OVER_TWO - reticleSize / 2.0f, + reticleSize / 2.0f); + + glPushMatrix(); { + glm::vec3 axis = glm::axis(orientation); + glRotatef(glm::degrees(glm::angle(orientation)), axis.x, axis.y, axis.z); + + glBegin(GL_QUADS); { + glColor4f(RETICLE_COLOR[0], RETICLE_COLOR[1], RETICLE_COLOR[2], alpha); + + glTexCoord2f(0.0f, 0.0f); glVertex3f(topLeft.x, topLeft.y, topLeft.z); + glTexCoord2f(1.0f, 0.0f); glVertex3f(bottomLeft.x, bottomLeft.y, bottomLeft.z); + glTexCoord2f(1.0f, 1.0f); glVertex3f(bottomRight.x, bottomRight.y, bottomRight.z); + glTexCoord2f(0.0f, 1.0f); glVertex3f(topRight.x, topRight.y, topRight.z); + } glEnd(); + } glPopMatrix(); +} + ApplicationOverlay::ApplicationOverlay() : _textureFov(glm::radians(DEFAULT_OCULUS_UI_ANGULAR_SIZE)), _textureAspectRatio(1.0f), @@ -125,152 +209,241 @@ void ApplicationOverlay::renderOverlay(bool renderToTexture) { // Draws the FBO texture for the screen void ApplicationOverlay::displayOverlayTexture() { - if (_alpha == 0.0f) { return; } - - Application* application = Application::getInstance(); - GLCanvas* glWidget = application->getGLWidget(); - + GLCanvas* glWidget = Application::getInstance()->getGLWidget(); glEnable(GL_TEXTURE_2D); glActiveTexture(GL_TEXTURE0); _overlays.bindTexture(); glMatrixMode(GL_PROJECTION); - glPushMatrix(); - - glLoadIdentity(); - gluOrtho2D(0, glWidget->getDeviceWidth(), glWidget->getDeviceHeight(), 0); - glDisable(GL_DEPTH_TEST); - glDisable(GL_LIGHTING); - glEnable(GL_BLEND); - - glBegin(GL_QUADS); - glColor4f(1.0f, 1.0f, 1.0f, _alpha); - glTexCoord2f(0, 0); glVertex2i(0, glWidget->getDeviceHeight()); - glTexCoord2f(1, 0); glVertex2i(glWidget->getDeviceWidth(), glWidget->getDeviceHeight()); - glTexCoord2f(1, 1); glVertex2i(glWidget->getDeviceWidth(), 0); - glTexCoord2f(0, 1); glVertex2i(0, 0); - glEnd(); - glColor4f(1.0f, 1.0f, 1.0f, 1.0f); - - glPopMatrix(); + glPushMatrix(); { + glLoadIdentity(); + gluOrtho2D(0, glWidget->getDeviceWidth(), glWidget->getDeviceHeight(), 0); + glDisable(GL_DEPTH_TEST); + glDisable(GL_LIGHTING); + glEnable(GL_BLEND); + + glBegin(GL_QUADS); { + glColor4f(1.0f, 1.0f, 1.0f, _alpha); + glTexCoord2f(0, 0); glVertex2i(0, glWidget->getDeviceHeight()); + glTexCoord2f(1, 0); glVertex2i(glWidget->getDeviceWidth(), glWidget->getDeviceHeight()); + glTexCoord2f(1, 1); glVertex2i(glWidget->getDeviceWidth(), 0); + glTexCoord2f(0, 1); glVertex2i(0, 0); + } glEnd(); + } glPopMatrix(); + glDisable(GL_TEXTURE_2D); } -void ApplicationOverlay::computeOculusPickRay(float x, float y, glm::vec3& direction) const { - static const float MOUSE_PITCH_RANGE = 1.0f * PI; - static const float MOUSE_YAW_RANGE = 0.5f * TWO_PI; - - const MyAvatar* myAvatar = Application::getInstance()->getAvatar(); - const GLCanvas* glWidget = Application::getInstance()->getGLWidget(); - const int widgetWidth = glWidget->width(); - const int widgetHeight = glWidget->height(); +// Draws the FBO texture for Oculus rift. +void ApplicationOverlay::displayOverlayTextureOculus(Camera& whichCamera) { + if (_alpha == 0.0f) { + return; + } + glEnable(GL_TEXTURE_2D); + glActiveTexture(GL_TEXTURE0); + _overlays.bindTexture(); - const float pitch = -(y / widgetHeight - 0.5f) * MOUSE_PITCH_RANGE; - const float yaw = -(x / widgetWidth - 0.5f) * MOUSE_YAW_RANGE; + glEnable(GL_BLEND); + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE); + glEnable(GL_DEPTH_TEST); + glDepthMask(GL_TRUE); + glDisable(GL_LIGHTING); + glEnable(GL_ALPHA_TEST); + glAlphaFunc(GL_GREATER, 0.01f); + + + //Update and draw the magnifiers + MyAvatar* myAvatar = Application::getInstance()->getAvatar(); + const glm::quat& orientation = myAvatar->getOrientation(); + const glm::vec3& position = myAvatar->getDefaultEyePosition(); + const float scale = myAvatar->getScale() * _oculusUIRadius; + + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); { + glTranslatef(position.x, position.y, position.z); + glm::mat4 rotation = glm::toMat4(orientation); + glMultMatrixf(&rotation[0][0]); + glScalef(scale, scale, scale); + for (int i = 0; i < NUMBER_OF_RETICULES; i++) { + + if (_magActive[i]) { + _magSizeMult[i] += MAG_SPEED; + if (_magSizeMult[i] > 1.0f) { + _magSizeMult[i] = 1.0f; + } + } else { + _magSizeMult[i] -= MAG_SPEED; + if (_magSizeMult[i] < 0.0f) { + _magSizeMult[i] = 0.0f; + } + } + + if (_magSizeMult[i] > 0.0f) { + //Render magnifier, but dont show border for mouse magnifier + float pitch = -(_reticulePosition[MOUSE].y / widgetHeight - 0.5f) * MOUSE_PITCH_RANGE; + float yaw = -(_reticulePosition[MOUSE].x / widgetWidth - 0.5f) * MOUSE_YAW_RANGE; + float projection = + + renderMagnifier(_reticulePosition[i], _magSizeMult[i], i != MOUSE); + } + } + + glDepthMask(GL_FALSE); + glDisable(GL_ALPHA_TEST); + + glColor4f(1.0f, 1.0f, 1.0f, _alpha); + + + static float textureFOV = 0.0f, textureAspectRatio = 1.0f; + if (textureFOV != _textureFov || + textureAspectRatio != _textureAspectRatio) { + textureFOV = _textureFov; + textureAspectRatio = _textureAspectRatio; + + _overlays.buildVBO(_textureFov, _textureAspectRatio, 80, 80); + } + _overlays.render(); + renderPointersOculus(myAvatar->getDefaultEyePosition()); + + glDepthMask(GL_TRUE); + _overlays.releaseTexture(); + glDisable(GL_TEXTURE_2D); + + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE); + glEnable(GL_LIGHTING); + } glPopMatrix(); +} + +// Draws the FBO texture for 3DTV. +void ApplicationOverlay::displayOverlayTexture3DTV(Camera& whichCamera, float aspectRatio, float fov) { + if (_alpha == 0.0f) { + return; + } + + Application* application = Application::getInstance(); + + MyAvatar* myAvatar = application->getAvatar(); + const glm::vec3& viewMatrixTranslation = application->getViewMatrixTranslation(); + + glActiveTexture(GL_TEXTURE0); + + glEnable(GL_BLEND); + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE); + _overlays.bindTexture(); + glEnable(GL_DEPTH_TEST); + glDisable(GL_LIGHTING); + glEnable(GL_TEXTURE_2D); + + glMatrixMode(GL_MODELVIEW); + + glPushMatrix(); + glLoadIdentity(); + // Transform to world space + glm::quat rotation = whichCamera.getRotation(); + glm::vec3 axis2 = glm::axis(rotation); + glRotatef(-glm::degrees(glm::angle(rotation)), axis2.x, axis2.y, axis2.z); + glTranslatef(viewMatrixTranslation.x, viewMatrixTranslation.y, viewMatrixTranslation.z); + + // Translate to the front of the camera + glm::vec3 pos = whichCamera.getPosition(); + glm::quat rot = myAvatar->getOrientation(); + glm::vec3 axis = glm::axis(rot); + + glTranslatef(pos.x, pos.y, pos.z); + glRotatef(glm::degrees(glm::angle(rot)), axis.x, axis.y, axis.z); + + glColor4f(1.0f, 1.0f, 1.0f, _alpha); + + //Render + const GLfloat distance = 1.0f; + + const GLfloat halfQuadHeight = distance * tan(fov); + const GLfloat halfQuadWidth = halfQuadHeight * aspectRatio; + const GLfloat quadWidth = halfQuadWidth * 2.0f; + const GLfloat quadHeight = halfQuadHeight * 2.0f; + + GLfloat x = -halfQuadWidth; + GLfloat y = -halfQuadHeight; + glDisable(GL_DEPTH_TEST); + + glBegin(GL_QUADS); + + glTexCoord2f(0.0f, 1.0f); glVertex3f(x, y + quadHeight, -distance); + glTexCoord2f(1.0f, 1.0f); glVertex3f(x + quadWidth, y + quadHeight, -distance); + glTexCoord2f(1.0f, 0.0f); glVertex3f(x + quadWidth, y, -distance); + glTexCoord2f(0.0f, 0.0f); glVertex3f(x, y, -distance); + + glEnd(); + + if (_crosshairTexture == 0) { + _crosshairTexture = Application::getInstance()->getGLWidget()->bindTexture(QImage(Application::resourcesPath() + "images/sixense-reticle.png")); + } + + //draw the mouse pointer + glBindTexture(GL_TEXTURE_2D, _crosshairTexture); + + const float reticleSize = 40.0f / application->getGLWidget()->width() * quadWidth; + x -= reticleSize / 2.0f; + y += reticleSize / 2.0f; + const float mouseX = (application->getMouseX() / (float)application->getGLWidget()->width()) * quadWidth; + const float mouseY = (1.0 - (application->getMouseY() / (float)application->getGLWidget()->height())) * quadHeight; + + glBegin(GL_QUADS); + + glColor3f(RETICLE_COLOR[0], RETICLE_COLOR[1], RETICLE_COLOR[2]); + + glTexCoord2d(0.0f, 0.0f); glVertex3f(x + mouseX, y + mouseY, -distance); + glTexCoord2d(1.0f, 0.0f); glVertex3f(x + mouseX + reticleSize, y + mouseY, -distance); + glTexCoord2d(1.0f, 1.0f); glVertex3f(x + mouseX + reticleSize, y + mouseY - reticleSize, -distance); + glTexCoord2d(0.0f, 1.0f); glVertex3f(x + mouseX, y + mouseY - reticleSize, -distance); + + glEnd(); + + glEnable(GL_DEPTH_TEST); + + glPopMatrix(); + + glDepthMask(GL_TRUE); + glBindTexture(GL_TEXTURE_2D, 0); + glDisable(GL_TEXTURE_2D); + + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE); + glEnable(GL_LIGHTING); + + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); +} + + + + + +void ApplicationOverlay::computeOculusPickRay(float x, float y, glm::vec3& direction) const { + const float pitch = (0.5f - y) * MOUSE_PITCH_RANGE; + const float yaw = (0.5f - x) * MOUSE_YAW_RANGE; const glm::quat orientation(glm::vec3(pitch, yaw, 0.0f)); const glm::vec3 localDirection = orientation * IDENTITY_FRONT; //Rotate the UI pick ray by the avatar orientation + const MyAvatar* myAvatar = Application::getInstance()->getAvatar(); direction = myAvatar->getOrientation() * localDirection; } -// Calculates the click location on the screen by taking into account any -// opened magnification windows. -void ApplicationOverlay::getClickLocation(int &x, int &y) const { - int dx; - int dy; - const float xRange = MAGNIFY_WIDTH * MAGNIFY_MULT / 2.0f; - const float yRange = MAGNIFY_HEIGHT * MAGNIFY_MULT / 2.0f; - - //Loop through all magnification windows - for (int i = 0; i < NUMBER_OF_MAGNIFIERS; i++) { - if (_magActive[i]) { - dx = x - _magX[i]; - dy = y - _magY[i]; - //Check to see if they clicked inside a mag window - if (abs(dx) <= xRange && abs(dy) <= yRange) { - //Move the click to the actual UI location by inverting the magnification - x = dx / MAGNIFY_MULT + _magX[i]; - y = dy / MAGNIFY_MULT + _magY[i]; - return; - } - } - } -} - -//Checks if the given ray intersects the sphere at the origin. result will store a multiplier that should -//be multiplied by dir and added to origin to get the location of the collision -bool raySphereIntersect(const glm::vec3 &dir, const glm::vec3 &origin, float r, float* result) -{ - //Source: http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection - - //Compute A, B and C coefficients - float a = glm::dot(dir, dir); - float b = 2 * glm::dot(dir, origin); - float c = glm::dot(origin, origin) - (r * r); - - //Find discriminant - float disc = b * b - 4 * a * c; - - // if discriminant is negative there are no real roots, so return - // false as ray misses sphere - if (disc < 0) { - return false; - } - - // compute q as described above - float distSqrt = sqrtf(disc); - float q; - if (b < 0) { - q = (-b - distSqrt) / 2.0; - } else { - q = (-b + distSqrt) / 2.0; - } - - // compute t0 and t1 - float t0 = q / a; - float t1 = c / q; - - // make sure t0 is smaller than t1 - if (t0 > t1) { - // if t0 is bigger than t1 swap them around - float temp = t0; - t0 = t1; - t1 = temp; - } - - // if t1 is less than zero, the object is in the ray's negative direction - // and consequently the ray misses the sphere - if (t1 < 0) { - return false; - } - - // if t0 is less than zero, the intersection point is at t1 - if (t0 < 0) { - *result = t1; - return true; - } else { // else the intersection point is at t0 - *result = t0; - return true; - } -} - //Caculate the click location using one of the sixense controllers. Scale is not applied QPoint ApplicationOverlay::getPalmClickLocation(const PalmData *palm) const { - Application* application = Application::getInstance(); GLCanvas* glWidget = application->getGLWidget(); MyAvatar* myAvatar = application->getAvatar(); glm::vec3 tip = myAvatar->getLaserPointerTipPosition(palm); glm::vec3 eyePos = myAvatar->getHead()->getEyePosition(); - glm::quat orientation = glm::inverse(myAvatar->getOrientation()); - glm::vec3 dir = orientation * glm::normalize(application->getCamera()->getPosition() - tip); //direction of ray goes towards camera - glm::vec3 tipPos = orientation * (tip - eyePos); + glm::quat invOrientation = glm::inverse(myAvatar->getOrientation()); + //direction of ray goes towards camera + glm::vec3 dir = invOrientation * glm::normalize(application->getCamera()->getPosition() - tip); + glm::vec3 tipPos = invOrientation * (tip - eyePos); QPoint rv; @@ -336,196 +509,7 @@ bool ApplicationOverlay::calculateRayUICollisionPoint(const glm::vec3& position, return false; } -// Draws the FBO texture for Oculus rift. -void ApplicationOverlay::displayOverlayTextureOculus(Camera& whichCamera) { - if (_alpha == 0.0f) { - return; - } - - Application* application = Application::getInstance(); - - MyAvatar* myAvatar = application->getAvatar(); - - glActiveTexture(GL_TEXTURE0); - - glEnable(GL_BLEND); - glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE); - glEnable(GL_DEPTH_TEST); - glDisable(GL_LIGHTING); - glEnable(GL_TEXTURE_2D); - - _overlays.bindTexture(); - - glMatrixMode(GL_MODELVIEW); - - glDepthMask(GL_TRUE); - - glEnable(GL_ALPHA_TEST); - glAlphaFunc(GL_GREATER, 0.01f); - - //Update and draw the magnifiers - - const glm::quat& orientation = myAvatar->getOrientation(); - const glm::vec3& position = myAvatar->getDefaultEyePosition(); - const float scale = myAvatar->getScale() * _oculusUIRadius; - - - glPushMatrix(); { - glTranslatef(position.x, position.y, position.z); - glm::mat4 rotation = glm::toMat4(orientation); - glMultMatrixf(&rotation[0][0]); - glScalef(scale, scale, scale); - for (int i = 0; i < NUMBER_OF_MAGNIFIERS; i++) { - - if (_magActive[i]) { - _magSizeMult[i] += MAG_SPEED; - if (_magSizeMult[i] > 1.0f) { - _magSizeMult[i] = 1.0f; - } - } else { - _magSizeMult[i] -= MAG_SPEED; - if (_magSizeMult[i] < 0.0f) { - _magSizeMult[i] = 0.0f; - } - } - - if (_magSizeMult[i] > 0.0f) { - //Render magnifier, but dont show border for mouse magnifier - renderMagnifier(_magX[i], _magY[i], _magSizeMult[i], i != MOUSE); - } - } - - glDepthMask(GL_FALSE); - glDisable(GL_ALPHA_TEST); - - glColor4f(1.0f, 1.0f, 1.0f, _alpha); - - - static float textureFOV = 0.0f, textureAspectRatio = 1.0f; - static QSize size; - if (textureFOV != _textureFov || - textureAspectRatio != _textureAspectRatio || - size != application->getGLWidget()->getDeviceSize()) { - textureFOV = _textureFov; - textureAspectRatio = _textureAspectRatio; - size = application->getGLWidget()->getDeviceSize(); - - _overlays.buildVBO(_textureFov, _textureAspectRatio, 80, 80); - } - _overlays.render(); - - renderPointersOculus(myAvatar->getDefaultEyePosition()); - - glDepthMask(GL_TRUE); - _overlays.releaseTexture(); - glDisable(GL_TEXTURE_2D); - - glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE); - glEnable(GL_LIGHTING); - - glColor4f(1.0f, 1.0f, 1.0f, 1.0f); - } glPopMatrix(); -} - -// Draws the FBO texture for 3DTV. -void ApplicationOverlay::displayOverlayTexture3DTV(Camera& whichCamera, float aspectRatio, float fov) { - if (_alpha == 0.0f) { - return; - } - - Application* application = Application::getInstance(); - - MyAvatar* myAvatar = application->getAvatar(); - const glm::vec3& viewMatrixTranslation = application->getViewMatrixTranslation(); - - glActiveTexture(GL_TEXTURE0); - - glEnable(GL_BLEND); - glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE); - _overlays.bindTexture(); - glEnable(GL_DEPTH_TEST); - glDisable(GL_LIGHTING); - glEnable(GL_TEXTURE_2D); - - glMatrixMode(GL_MODELVIEW); - - glPushMatrix(); - glLoadIdentity(); - // Transform to world space - glm::quat rotation = whichCamera.getRotation(); - glm::vec3 axis2 = glm::axis(rotation); - glRotatef(-glm::degrees(glm::angle(rotation)), axis2.x, axis2.y, axis2.z); - glTranslatef(viewMatrixTranslation.x, viewMatrixTranslation.y, viewMatrixTranslation.z); - - // Translate to the front of the camera - glm::vec3 pos = whichCamera.getPosition(); - glm::quat rot = myAvatar->getOrientation(); - glm::vec3 axis = glm::axis(rot); - - glTranslatef(pos.x, pos.y, pos.z); - glRotatef(glm::degrees(glm::angle(rot)), axis.x, axis.y, axis.z); - - glColor4f(1.0f, 1.0f, 1.0f, _alpha); - - //Render - const GLfloat distance = 1.0f; - - const GLfloat halfQuadHeight = distance * tan(fov); - const GLfloat halfQuadWidth = halfQuadHeight * aspectRatio; - const GLfloat quadWidth = halfQuadWidth * 2.0f; - const GLfloat quadHeight = halfQuadHeight * 2.0f; - - GLfloat x = -halfQuadWidth; - GLfloat y = -halfQuadHeight; - glDisable(GL_DEPTH_TEST); - - glBegin(GL_QUADS); - - glTexCoord2f(0.0f, 1.0f); glVertex3f(x, y + quadHeight, -distance); - glTexCoord2f(1.0f, 1.0f); glVertex3f(x + quadWidth, y + quadHeight, -distance); - glTexCoord2f(1.0f, 0.0f); glVertex3f(x + quadWidth, y, -distance); - glTexCoord2f(0.0f, 0.0f); glVertex3f(x, y, -distance); - - glEnd(); - - if (_crosshairTexture == 0) { - _crosshairTexture = Application::getInstance()->getGLWidget()->bindTexture(QImage(Application::resourcesPath() + "images/sixense-reticle.png")); - } - - //draw the mouse pointer - glBindTexture(GL_TEXTURE_2D, _crosshairTexture); - - const float reticleSize = 40.0f / application->getGLWidget()->width() * quadWidth; - x -= reticleSize / 2.0f; - y += reticleSize / 2.0f; - const float mouseX = (application->getMouseX() / (float)application->getGLWidget()->width()) * quadWidth; - const float mouseY = (1.0 - (application->getMouseY() / (float)application->getGLWidget()->height())) * quadHeight; - - glBegin(GL_QUADS); - - glColor3f(RETICLE_COLOR[0], RETICLE_COLOR[1], RETICLE_COLOR[2]); - - glTexCoord2d(0.0f, 0.0f); glVertex3f(x + mouseX, y + mouseY, -distance); - glTexCoord2d(1.0f, 0.0f); glVertex3f(x + mouseX + reticleSize, y + mouseY, -distance); - glTexCoord2d(1.0f, 1.0f); glVertex3f(x + mouseX + reticleSize, y + mouseY - reticleSize, -distance); - glTexCoord2d(0.0f, 1.0f); glVertex3f(x + mouseX, y + mouseY - reticleSize, -distance); - - glEnd(); - - glEnable(GL_DEPTH_TEST); - - glPopMatrix(); - - glDepthMask(GL_TRUE); - glBindTexture(GL_TEXTURE_2D, 0); - glDisable(GL_TEXTURE_2D); - - glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE); - glEnable(GL_LIGHTING); - - glColor4f(1.0f, 1.0f, 1.0f, 1.0f); -} //Renders optional pointers void ApplicationOverlay::renderPointers() { @@ -544,10 +528,7 @@ void ApplicationOverlay::renderPointers() { //If we are in oculus, render reticle later _reticleActive[MOUSE] = true; _magActive[MOUSE] = true; - _mouseX[MOUSE] = application->getMouseX(); - _mouseY[MOUSE] = application->getMouseY(); - _magX[MOUSE] = _mouseX[MOUSE]; - _magY[MOUSE] = _mouseY[MOUSE]; + _reticulePosition[MOUSE] = glm::vec2(application->getMouseX(), application->getMouseY()); _reticleActive[LEFT_CONTROLLER] = false; _reticleActive[RIGHT_CONTROLLER] = false; @@ -567,9 +548,9 @@ void ApplicationOverlay::renderControllerPointers() { MyAvatar* myAvatar = application->getAvatar(); //Static variables used for storing controller state - static quint64 pressedTime[NUMBER_OF_MAGNIFIERS] = { 0ULL, 0ULL, 0ULL }; - static bool isPressed[NUMBER_OF_MAGNIFIERS] = { false, false, false }; - static bool stateWhenPressed[NUMBER_OF_MAGNIFIERS] = { false, false, false }; + static quint64 pressedTime[NUMBER_OF_RETICULES] = { 0ULL, 0ULL, 0ULL }; + static bool isPressed[NUMBER_OF_RETICULES] = { false, false, false }; + static bool stateWhenPressed[NUMBER_OF_RETICULES] = { false, false, false }; const HandData* handData = Application::getInstance()->getAvatar()->getHandData(); @@ -616,14 +597,11 @@ void ApplicationOverlay::renderControllerPointers() { QPoint point = getPalmClickLocation(palmData); - _mouseX[index] = point.x(); - _mouseY[index] = point.y(); + _reticulePosition[index] = glm::vec2(point.x(), point.y()); //When button 2 is pressed we drag the mag window if (isPressed[index]) { _magActive[index] = true; - _magX[index] = point.x(); - _magY[index] = point.y(); } // If oculus is enabled, we draw the crosshairs later @@ -676,30 +654,6 @@ void ApplicationOverlay::renderControllerPointers() { } } - -void renderReticule(glm::quat orientation, float alpha) { - const float reticleSize = TWO_PI / 80.0f; - - glm::vec3 topLeft = getPoint(1.0f, PI_OVER_TWO + reticleSize / 2.0f, - reticleSize / 2.0f); - glm::vec3 topRight = getPoint(1.0f, PI_OVER_TWO + reticleSize / 2.0f, + reticleSize / 2.0f); - glm::vec3 bottomLeft = getPoint(1.0f, PI_OVER_TWO - reticleSize / 2.0f, - reticleSize / 2.0f); - glm::vec3 bottomRight = getPoint(1.0f, PI_OVER_TWO - reticleSize / 2.0f, + reticleSize / 2.0f); - - glPushMatrix(); { - glm::vec3 axis = glm::axis(orientation); - glRotatef(glm::degrees(glm::angle(orientation)), axis.x, axis.y, axis.z); - - glBegin(GL_QUADS); { - glColor4f(RETICLE_COLOR[0], RETICLE_COLOR[1], RETICLE_COLOR[2], alpha); - - glTexCoord2f(0.0f, 0.0f); glVertex3f(topLeft.x, topLeft.y, topLeft.z); - glTexCoord2f(1.0f, 0.0f); glVertex3f(bottomLeft.x, bottomLeft.y, bottomLeft.z); - glTexCoord2f(1.0f, 1.0f); glVertex3f(bottomRight.x, bottomRight.y, bottomRight.z); - glTexCoord2f(0.0f, 1.0f); glVertex3f(topRight.x, topRight.y, topRight.z); - } glEnd(); - } glPopMatrix(); -} - void ApplicationOverlay::renderPointersOculus(const glm::vec3& eyePos) { GLCanvas* glWidget = Application::getInstance()->getGLWidget(); const int widgetWidth = glWidget->width(); @@ -781,13 +735,8 @@ void ApplicationOverlay::renderPointersOculus(const glm::vec3& eyePos) { //Mouse Pointer if (_reticleActive[MOUSE]) { - float mouseX = (float)_mouseX[MOUSE]; - float mouseY = (float)_mouseY[MOUSE]; - - static const float MOUSE_PITCH_RANGE = 1.0f * PI; - static const float MOUSE_YAW_RANGE = 0.5f * TWO_PI; - float pitch = -(mouseY / widgetHeight - 0.5f) * MOUSE_PITCH_RANGE; - float yaw = -(mouseX / widgetWidth - 0.5f) * MOUSE_YAW_RANGE; + float pitch = -(_reticulePosition[MOUSE].y / widgetHeight - 0.5f) * MOUSE_PITCH_RANGE; + float yaw = -(_reticulePosition[MOUSE].x / widgetWidth - 0.5f) * MOUSE_YAW_RANGE; glm::quat orientation(glm::vec3(pitch, yaw, 0.0f)); renderReticule(orientation, _alpha); @@ -796,6 +745,76 @@ void ApplicationOverlay::renderPointersOculus(const glm::vec3& eyePos) { glEnable(GL_DEPTH_TEST); } +//Renders a small magnification of the currently bound texture at the coordinates +void ApplicationOverlay::renderMagnifier(glm::vec2 magPos, float sizeMult, bool showBorder) const { + Application* application = Application::getInstance(); + GLCanvas* glWidget = application->getGLWidget(); + + const int widgetWidth = glWidget->width(); + const int widgetHeight = glWidget->height(); + + if (magPos.x < 0 || magPos.x > widgetWidth || magPos.y < 0 || magPos.y > widgetHeight) { + return; + } + + const float halfWidth = (MAGNIFY_WIDTH / _textureAspectRatio) * sizeMult / 2.0f; + const float halfHeight = MAGNIFY_HEIGHT * sizeMult / 2.0f; + // Magnification Texture Coordinates + float magnifyULeft = (magPos.x - halfWidth) / (float)widgetWidth; + float magnifyURight = (magPos.x + halfWidth) / (float)widgetWidth; + float magnifyVBottom = 1.0f - (magPos.y - halfHeight) / (float)widgetHeight; + float magnifyVTop = 1.0f - (magPos.y + halfHeight) / (float)widgetHeight; + + const float newHalfWidth = halfWidth * MAGNIFY_MULT; + const float newHalfHeight = halfHeight * MAGNIFY_MULT; + //Get new UV coordinates from our magnification window + float newULeft = (magPos.x - newHalfWidth) / (float)widgetWidth; + float newURight = (magPos.x + newHalfWidth) / (float)widgetWidth; + float newVBottom = 1.0f - (magPos.y - newHalfHeight) / (float)widgetHeight; + float newVTop = 1.0f - (magPos.y + newHalfHeight) / (float)widgetHeight; + + // Find spherical coordinates from newUV, fov and aspect ratio + float radius = _oculusUIRadius * application->getAvatar()->getScale(); + const float leftPhi = (newULeft - 0.5f) * _textureFov * _textureAspectRatio; + const float rightPhi = (newURight - 0.5f) * _textureFov * _textureAspectRatio; + const float bottomTheta = PI_OVER_TWO - (newVBottom - 0.5f) * _textureFov; + const float topTheta = PI_OVER_TWO - (newVTop - 0.5f) * _textureFov; + + glm::vec3 bottomLeft = getPoint(radius, bottomTheta, leftPhi); + glm::vec3 bottomRight = getPoint(radius, bottomTheta, rightPhi); + glm::vec3 topLeft = getPoint(radius, topTheta, leftPhi); + glm::vec3 topRight = getPoint(radius, topTheta, rightPhi); + + glPushMatrix(); { + if (showBorder) { + glDisable(GL_TEXTURE_2D); + glLineWidth(1.0f); + //Outer Line + glBegin(GL_LINE_STRIP); { + glColor4f(1.0f, 0.0f, 0.0f, _alpha); + + glVertex3f(topLeft.x, topLeft.y, topLeft.z); + glVertex3f(bottomLeft.x, bottomLeft.y, bottomLeft.z); + glVertex3f(bottomRight.x, bottomRight.y, bottomRight.z); + glVertex3f(topRight.x, topRight.y, topRight.z); + glVertex3f(topLeft.x, topLeft.y, topLeft.z); + } glEnd(); + + glEnable(GL_TEXTURE_2D); + } + glColor4f(1.0f, 1.0f, 1.0f, _alpha); + + glBegin(GL_QUADS); { + glTexCoord2f(magnifyULeft, magnifyVBottom); glVertex3f(bottomLeft.x, bottomLeft.y, bottomLeft.z); + glTexCoord2f(magnifyURight, magnifyVBottom); glVertex3f(bottomRight.x, bottomRight.y, bottomRight.z); + glTexCoord2f(magnifyURight, magnifyVTop); glVertex3f(topRight.x, topRight.y, topRight.z); + glTexCoord2f(magnifyULeft, magnifyVTop); glVertex3f(topLeft.x, topLeft.y, topLeft.z); + } glEnd(); + } glPopMatrix(); +} + + + void ApplicationOverlay::renderAudioMeter() { Application* application = Application::getInstance(); @@ -993,70 +1012,7 @@ void ApplicationOverlay::renderDomainConnectionStatusBorder() { } } -//Renders a small magnification of the currently bound texture at the coordinates -void ApplicationOverlay::renderMagnifier(int mouseX, int mouseY, float sizeMult, bool showBorder) const { - Application* application = Application::getInstance(); - GLCanvas* glWidget = application->getGLWidget(); - - const int widgetWidth = glWidget->width(); - const int widgetHeight = glWidget->height(); - - const float halfWidth = (MAGNIFY_WIDTH / _textureAspectRatio) * sizeMult / 2.0f; - const float halfHeight = MAGNIFY_HEIGHT * sizeMult / 2.0f; - // Magnification Texture Coordinates - float magnifyULeft = (mouseX - halfWidth) / (float)widgetWidth; - float magnifyURight = (mouseX + halfWidth) / (float)widgetWidth; - float magnifyVBottom = 1.0f - (mouseY - halfHeight) / (float)widgetHeight; - float magnifyVTop = 1.0f - (mouseY + halfHeight) / (float)widgetHeight; - - - const float newHalfWidth = halfWidth * MAGNIFY_MULT; - const float newHalfHeight = halfHeight * MAGNIFY_MULT; - //Get new UV coordinates from our magnification window - float newULeft = (mouseX - newHalfWidth) / (float)widgetWidth; - float newURight = (mouseX + newHalfWidth) / (float)widgetWidth; - float newVBottom = 1.0f - (mouseY - newHalfHeight) / (float)widgetHeight; - float newVTop = 1.0f - (mouseY + newHalfHeight) / (float)widgetHeight; - - // Find spherical coordinates from newUV, fov and aspect ratio - float radius = _oculusUIRadius * application->getAvatar()->getScale(); - const float leftPhi = (newULeft - 0.5f) * _textureFov * _textureAspectRatio; - const float rightPhi = (newURight - 0.5f) * _textureFov * _textureAspectRatio; - const float bottomTheta = PI_OVER_TWO - (newVBottom - 0.5f) * _textureFov; - const float topTheta = PI_OVER_TWO - (newVTop - 0.5f) * _textureFov; - - glm::vec3 bottomLeft = getPoint(radius, bottomTheta, leftPhi); - glm::vec3 bottomRight = getPoint(radius, bottomTheta, rightPhi); - glm::vec3 topLeft = getPoint(radius, topTheta, leftPhi); - glm::vec3 topRight = getPoint(radius, topTheta, rightPhi); - - glPushMatrix(); { - if (showBorder) { - glDisable(GL_TEXTURE_2D); - glLineWidth(1.0f); - //Outer Line - glBegin(GL_LINE_STRIP); { - glColor4f(1.0f, 0.0f, 0.0f, _alpha); - - glVertex3f(topLeft.x, topLeft.y, topLeft.z); - glVertex3f(bottomLeft.x, bottomLeft.y, bottomLeft.z); - glVertex3f(bottomRight.x, bottomRight.y, bottomRight.z); - glVertex3f(topRight.x, topRight.y, topRight.z); - glVertex3f(topLeft.x, topLeft.y, topLeft.z); - } glEnd(); - - glEnable(GL_TEXTURE_2D); - } - glColor4f(1.0f, 1.0f, 1.0f, _alpha); - - glBegin(GL_QUADS); { - glTexCoord2f(magnifyULeft, magnifyVBottom); glVertex3f(bottomLeft.x, bottomLeft.y, bottomLeft.z); - glTexCoord2f(magnifyURight, magnifyVBottom); glVertex3f(bottomRight.x, bottomRight.y, bottomRight.z); - glTexCoord2f(magnifyURight, magnifyVTop); glVertex3f(topRight.x, topRight.y, topRight.z); - glTexCoord2f(magnifyULeft, magnifyVTop); glVertex3f(topLeft.x, topLeft.y, topLeft.z); - } glEnd(); - } glPopMatrix(); -} + ApplicationOverlay::TexturedHemisphere::TexturedHemisphere() : _vertices(0), diff --git a/interface/src/ui/ApplicationOverlay.h b/interface/src/ui/ApplicationOverlay.h index 5fa93f6521..7c423b3a06 100644 --- a/interface/src/ui/ApplicationOverlay.h +++ b/interface/src/ui/ApplicationOverlay.h @@ -22,7 +22,6 @@ const float MAGNIFY_MULT = 2.0f; // Handles the drawing of the overlays to the screen class ApplicationOverlay { public: - ApplicationOverlay(); ~ApplicationOverlay(); @@ -30,14 +29,10 @@ public: void displayOverlayTexture(); void displayOverlayTextureOculus(Camera& whichCamera); void displayOverlayTexture3DTV(Camera& whichCamera, float aspectRatio, float fov); + void computeOculusPickRay(float x, float y, glm::vec3& direction) const; - void getClickLocation(int &x, int &y) const; QPoint getPalmClickLocation(const PalmData *palm) const; bool calculateRayUICollisionPoint(const glm::vec3& position, const glm::vec3& direction, glm::vec3& result) const; - - - // Getters - float getAlpha() const { return _alpha; } private: // Interleaved vertex data @@ -70,31 +65,30 @@ private: VerticesIndices _vbo; }; - void renderPointers(); + void renderPointers();; + void renderMagnifier(glm::vec2 magPos, float sizeMult, bool showBorder) const; + void renderControllerPointers(); void renderPointersOculus(const glm::vec3& eyePos); - void renderMagnifier(int mouseX, int mouseY, float sizeMult, bool showBorder) const; + void renderAudioMeter(); void renderStatsAndLogs(); void renderDomainConnectionStatusBorder(); TexturedHemisphere _overlays; - float _trailingAudioLoudness; float _textureFov; float _textureAspectRatio; - enum MagnifyDevices { MOUSE, LEFT_CONTROLLER, RIGHT_CONTROLLER, NUMBER_OF_MAGNIFIERS }; - bool _reticleActive[NUMBER_OF_MAGNIFIERS]; - int _mouseX[NUMBER_OF_MAGNIFIERS]; - int _mouseY[NUMBER_OF_MAGNIFIERS]; - bool _magActive[NUMBER_OF_MAGNIFIERS]; - int _magX[NUMBER_OF_MAGNIFIERS]; - int _magY[NUMBER_OF_MAGNIFIERS]; - float _magSizeMult[NUMBER_OF_MAGNIFIERS]; + enum Reticules { MOUSE, LEFT_CONTROLLER, RIGHT_CONTROLLER, NUMBER_OF_RETICULES }; + bool _reticleActive[NUMBER_OF_RETICULES]; + glm::vec2 _reticulePosition[NUMBER_OF_RETICULES]; + bool _magActive[NUMBER_OF_RETICULES]; + float _magSizeMult[NUMBER_OF_RETICULES]; float _alpha; float _oculusUIRadius; + float _trailingAudioLoudness; GLuint _crosshairTexture; }; From 1ee45e8bd1f5bdb26745eff045eff1f19c7de035 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 4 Dec 2014 11:24:56 -0800 Subject: [PATCH 210/502] Fix entity tool rotation to rotate around registration point --- examples/libraries/entitySelectionTool.js | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/examples/libraries/entitySelectionTool.js b/examples/libraries/entitySelectionTool.js index 2953203fc6..fa97e9351f 100644 --- a/examples/libraries/entitySelectionTool.js +++ b/examples/libraries/entitySelectionTool.js @@ -1786,17 +1786,27 @@ SelectionDisplay = (function () { } var yawChange = Quat.fromVec3Degrees({ x: 0, y: angleFromZero, z: 0 }); + + // Entities should only reposition if we are rotating multiple selections around + // the selections center point. Otherwise, the rotation will be around the entities + // registration point which does not need repositioning. + var reposition = SelectionManager.selections.length > 1; for (var i = 0; i < SelectionManager.selections.length; i++) { var entityID = SelectionManager.selections[i]; var properties = Entities.getEntityProperties(entityID); var initialProperties = SelectionManager.savedProperties[entityID.id]; - var dPos = Vec3.subtract(initialProperties.position, initialPosition); - dPos = Vec3.multiplyQbyV(yawChange, dPos); - Entities.editEntity(entityID, { - position: Vec3.sum(initialPosition, dPos), + var newProperties = { rotation: Quat.multiply(yawChange, initialProperties.rotation), - }); + }; + + if (reposition) { + var dPos = Vec3.subtract(initialProperties.position, initialPosition); + dPos = Vec3.multiplyQbyV(yawChange, dPos); + newProperties.position = Vec3.sum(initialPosition, dPos); + } + + Entities.editEntity(entityID, newProperties); } updateRotationDegreesOverlay(angleFromZero, yawHandleRotation, yawCenter); From b6fd3628c8524799c60bfa8a9c2f1405c7ad3bc1 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 4 Dec 2014 12:00:38 -0800 Subject: [PATCH 211/502] first round of hacking on implementing rendering of models for detailed ray picking --- interface/resources/shaders/select.frag | 25 ++ interface/resources/shaders/select.vert | 26 ++ .../entities/RenderableModelEntityItem.cpp | 382 ++++++++++++++++++ .../src/entities/RenderableModelEntityItem.h | 11 + interface/src/renderer/Model.cpp | 20 +- interface/src/renderer/Model.h | 6 +- 6 files changed, 468 insertions(+), 2 deletions(-) create mode 100644 interface/resources/shaders/select.frag create mode 100644 interface/resources/shaders/select.vert diff --git a/interface/resources/shaders/select.frag b/interface/resources/shaders/select.frag new file mode 100644 index 0000000000..a7c5067fbc --- /dev/null +++ b/interface/resources/shaders/select.frag @@ -0,0 +1,25 @@ +#version 120 + +// +// simple.frag +// fragment shader +// +// Created by Andrzej Kapolka on 9/15/14. +// 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 +// + +// the interpolated normal +varying vec4 normal; + +// the glow intensity +uniform float glowIntensity; + +void main(void) { + // set the diffuse, normal, specular data + gl_FragData[0] = vec4(1.0f, 1.0f, 0.0f, 0.0f); //vec4(gl_Color.rgb, glowIntensity); + gl_FragData[1] = vec4(1.0f, 1.0f, 0.0f, 0.0f); //normalize(normal) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0); + gl_FragData[2] = vec4(1.0f, 1.0f, 0.0f, 0.0f); //vec4(gl_FrontMaterial.specular.rgb, gl_FrontMaterial.shininess / 128.0); +} diff --git a/interface/resources/shaders/select.vert b/interface/resources/shaders/select.vert new file mode 100644 index 0000000000..9f76597fd6 --- /dev/null +++ b/interface/resources/shaders/select.vert @@ -0,0 +1,26 @@ +#version 120 + +// +// simple.vert +// vertex shader +// +// Created by Andrzej Kapolka on 9/15/14. +// 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 +// + +// the interpolated normal +varying vec4 normal; + +void main(void) { + // transform and store the normal for interpolation + normal = normalize(gl_ModelViewMatrix * vec4(gl_Normal, 0.0)); + + // pass along the diffuse color + gl_FrontColor = vec4(1.0f, 0.0f, 0.0f, 0.0f); //gl_Color; + + // use standard pipeline transform + gl_Position = ftransform(); +} diff --git a/interface/src/entities/RenderableModelEntityItem.cpp b/interface/src/entities/RenderableModelEntityItem.cpp index 10b18ad9c5..11d16c39f8 100644 --- a/interface/src/entities/RenderableModelEntityItem.cpp +++ b/interface/src/entities/RenderableModelEntityItem.cpp @@ -133,6 +133,9 @@ void RenderableModelEntityItem::render(RenderArgs* args) { getModel(renderer); } + + + if (_model) { // handle animations.. if (hasAnimation()) { @@ -257,7 +260,386 @@ EntityItemProperties RenderableModelEntityItem::getProperties() const { return properties; } +bool RenderableModelEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, + bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, + void** intersectedObject) const { + + // extents is the entity relative, scaled, centered extents of the entity + 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 entityFrameOrigin = glm::vec3(worldToEntityMatrix * glm::vec4(origin, 1.0f)); + glm::vec3 entityFrameDirection = glm::vec3(worldToEntityMatrix * glm::vec4(direction, 0.0f)); + + float depth = depthOfRayIntersection(entityFrameOrigin, entityFrameDirection); + + return true; // we only got here if we intersected our non-aabox +} +/* +void RenderableModelEntityItem::renderEntityAsBillboard() { + TextureCache* textureCache = Application->getInstance()->getTextureCache(); + textureCache->getPrimaryFramebufferObject()->bind(); + + const int BILLBOARD_SIZE = 64; + renderRearViewMirror(QRect(0, _glWidget->getDeviceHeight() - BILLBOARD_SIZE, BILLBOARD_SIZE, BILLBOARD_SIZE), true); + + //QImage image(BILLBOARD_SIZE, BILLBOARD_SIZE, QImage::Format_ARGB32); + //glReadPixels(0, 0, BILLBOARD_SIZE, BILLBOARD_SIZE, GL_BGRA, GL_UNSIGNED_BYTE, image.bits()); + + textureCache->getPrimaryFramebufferObject()->release(); + + return image; +} +*/ + +float RenderableModelEntityItem::depthOfRayIntersection(const glm::vec3& entityFrameOrigin, const glm::vec3& entityFrameDirection) const { + qDebug() << "RenderableModelEntityItem::depthOfRayIntersection()...."; + + Application::getInstance()->getTextureCache()->getPrimaryFramebufferObject()->bind(); + + glEnable(GL_SCISSOR_TEST); + glEnable(GL_LIGHTING); // enable? + glEnable(GL_DEPTH_TEST); + glDisable(GL_BLEND); // we don't need blending + + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + + // * we know the direction that the ray is coming into our bounding box. + // * we know the location on our bounding box that the ray intersected + // * because this API is theoretically called for things that aren't on the screen, + // or could be off in the distance, but with an original ray pick origin ALSO off + // in the distance, we don't really know the "pixel" size of the model at that + // place in space. In fact that concept really doesn't make sense at all... so + // we need to pick our own "scale" based on whatever level of precision makes + // sense... what makes sense? + // * we could say that we allow ray intersections down to some N meters (say 1cm + // or 0.01 meters) in real space. The model's bounds in meters are known. + // + // + float renderGranularity = 0.01f; // 1cm of render granularity - this could be ridiculous for large models + + qDebug() << " renderGranularity:" << renderGranularity; + + // note: these are in tree units, not meters + glm::vec3 dimensions = getDimensions(); + glm::vec3 registrationPoint = getRegistrationPoint(); + glm::vec3 corner = -(dimensions * registrationPoint); + + AABox entityFrameBox(corner, dimensions); + entityFrameBox.scale((float)TREE_SCALE); + + // rotationBetween(v1, v2) -- Helper function return the rotation from the first vector onto the second + //glm::quat viewRotation = rotationBetween(entityFrameDirection, IDENTITY_FRONT); + //glm::quat viewRotation = rotationBetween(IDENTITY_FRONT, entityFrameDirection); + glm::quat viewRotation = rotationBetween(glm::vec3(0.0f, 1.0f, 0.0f), IDENTITY_FRONT); + //glm::quat viewRotation = rotationBetween(IDENTITY_FRONT, IDENTITY_FRONT); + + // I'd like to calculate the tightest bounding box around the entity for + // the direction of the + glm::vec3 minima(FLT_MAX, FLT_MAX, FLT_MAX); + glm::vec3 maxima(-FLT_MAX, -FLT_MAX, -FLT_MAX); + const int VERTEX_COUNT = 8; + for (int j = 0; j < VERTEX_COUNT; j++) { + glm::vec3 vertex = entityFrameBox.getVertex((BoxVertex)j); + qDebug() << " vertex[" << j <<"]:" << vertex; + + glm::vec3 rotated = viewRotation * vertex; + qDebug() << " rotated[" << j <<"]:" << rotated; + + minima = glm::min(minima, rotated); + maxima = glm::max(maxima, rotated); + } + + qDebug() << " minima:" << minima; + qDebug() << " maxima:" << maxima; + + int width = glm::round((maxima.x - minima.x) / renderGranularity); + int height = glm::round((maxima.y - minima.y) / renderGranularity); + + qDebug() << " width:" << width; + qDebug() << " height:" << height; + + glViewport(0, 0, width, height); + glScissor(0, 0, width, height); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glLoadIdentity(); + glOrtho(minima.x, maxima.x, minima.y, maxima.y, -maxima.z, -minima.z); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glm::vec3 axis = glm::axis(viewRotation); + glRotatef(glm::degrees(glm::angle(viewRotation)), axis.x, axis.y, axis.z); + + glm::vec3 entityFrameOriginInMeters = entityFrameOrigin * (float)TREE_SCALE; + glm::vec3 entityFrameDirectionInMeters = entityFrameDirection * (float)TREE_SCALE; + //glTranslatef(entityFrameOriginInMerters.x, entityFrameOriginInMerters.y, entityFrameOriginInMerters.z); + + Application::getInstance()->setupWorldLight(); + Application::getInstance()->updateUntranslatedViewMatrix(); + + + bool renderAsModel = true; + + if (renderAsModel) { + const float alpha = 1.0f; + + glm::vec3 position = getPositionInMeters(); + glm::vec3 center = getCenterInMeters(); + dimensions = getDimensions() * (float)TREE_SCALE; + glm::quat rotation = getRotation(); + + const float MAX_COLOR = 255.0f; + glColor4f(1.0f, 0.0f, 0.0f, 1.0f); + + glPushMatrix(); + { + //glTranslatef(position.x, position.y, position.z); + //glm::vec3 axis = glm::axis(rotation); + //glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z); + + + glPushMatrix(); + glm::vec3 positionToCenter = center - position; + //glTranslatef(positionToCenter.x, positionToCenter.y, positionToCenter.z); + + //glScalef(dimensions.x, dimensions.y, dimensions.z); + //Application::getInstance()->getDeferredLightingEffect()->renderSolidSphere(0.5f, 15, 15); + + //_model->setRotation(rotation); + //_model->setScaleToFit(true, glm::vec3(1.0f,1.0f,1.0f)); + + //glm::vec3(0.0f,2.0f,0.0f) + _model->setSnapModelToRegistrationPoint(true, glm::vec3(0.5f,0.5f,0.5f)); + _model->setTranslation(glm::vec3(0.0f,0.0f,0.0f)); + _model->simulate(0.0f); + _model->render(alpha, Model::DEFAULT_RENDER_MODE); + + //_model->render(1.0f, Model::DEFAULT_RENDER_MODE); + + //_model->setScaleToFit(true, dimensions); + _model->setSnapModelToRegistrationPoint(true, getRegistrationPoint()); + _model->setTranslation(position); + _model->simulate(0.0f); + + glPushMatrix(); + glScalef(dimensions.x, dimensions.y, dimensions.z); + Application::getInstance()->getDeferredLightingEffect()->renderWireSphere(0.5f, 15, 15); + glPopMatrix(); + + /* + glBegin(GL_LINES); + + // low-z side - blue + glColor4f(0.0f, 0.0f, 1.0f, 1.0f); + glVertex3f(-0.5f, -0.5f, -0.5f); + glVertex3f(0.5f, -0.5f, -0.5f); + glVertex3f(-0.5f, 0.5f, -0.5f); + glVertex3f(0.5f, 0.5f, -0.5f); + glVertex3f(0.5f, 0.5f, -0.5f); + glVertex3f(0.5f, -0.5f, -0.5f); + glVertex3f(-0.5f, 0.5f, -0.5f); + glVertex3f(-0.5f, -0.5f, -0.5f); + + // high-z side - cyan + glColor4f(0.0f, 1.0f, 1.0f, 1.0f); + glVertex3f(-0.5f, -0.5f, 0.5f); + glVertex3f( 0.5f, -0.5f, 0.5f); + glVertex3f(-0.5f, 0.5f, 0.5f); + glVertex3f( 0.5f, 0.5f, 0.5f); + glVertex3f( 0.5f, 0.5f, 0.5f); + glVertex3f( 0.5f, -0.5f, 0.5f); + glVertex3f(-0.5f, 0.5f, 0.5f); + glVertex3f(-0.5f, -0.5f, 0.5f); + + // low-x side - yellow + glColor4f(1.0f, 1.0f, 0.0f, 1.0f); + glVertex3f(-0.5f, -0.5f, -0.5f); + glVertex3f(-0.5f, -0.5f, 0.5f); + + glVertex3f(-0.5f, -0.5f, 0.5f); + glVertex3f(-0.5f, 0.5f, 0.5f); + + glVertex3f(-0.5f, 0.5f, 0.5f); + glVertex3f(-0.5f, 0.5f, -0.5f); + + glVertex3f(-0.5f, 0.5f, -0.5f); + glVertex3f(-0.5f, -0.5f, -0.5f); + + // high-x side - red + glColor4f(1.0f, 0.0f, 0.0f, 1.0f); + glVertex3f(0.5f, -0.5f, -0.5f); + glVertex3f(0.5f, -0.5f, 0.5f); + glVertex3f(0.5f, -0.5f, 0.5f); + glVertex3f(0.5f, 0.5f, 0.5f); + glVertex3f(0.5f, 0.5f, 0.5f); + glVertex3f(0.5f, 0.5f, -0.5f); + glVertex3f(0.5f, 0.5f, -0.5f); + glVertex3f(0.5f, -0.5f, -0.5f); + // origin and direction - green + float distanceToHit; + BoxFace ignoreFace; + + entityFrameBox.findRayIntersection(entityFrameOriginInMeters, entityFrameDirectionInMeters, distanceToHit, ignoreFace); + glm::vec3 pointOfIntersection = entityFrameOriginInMeters + (entityFrameDirectionInMeters * distanceToHit); + +qDebug() << "distanceToHit: " << distanceToHit; +qDebug() << "pointOfIntersection: " << pointOfIntersection; + + glm::vec3 pointA = pointOfIntersection + (entityFrameDirectionInMeters * -1.0f); + glm::vec3 pointB = pointOfIntersection + (entityFrameDirectionInMeters * 1.0f); +qDebug() << "pointA: " << pointA; +qDebug() << "pointB: " << pointB; + + glColor4f(0.0f, 1.0f, 0.0f, 1.0f); + glVertex3f(pointA.x, pointA.y, pointA.z); + glVertex3f(pointB.x, pointB.y, pointB.z); + + glEnd(); + */ + + + glPopMatrix(); + } + glPopMatrix(); + + + } else { + glm::vec3 position = getPositionInMeters(); + glm::vec3 center = getCenterInMeters(); + dimensions = getDimensions() * (float)TREE_SCALE; + glm::quat rotation = getRotation(); + + glColor4f(1.0f, 0.0f, 1.0f, 1.0f); + glLineWidth(2.0f); + + glPushMatrix(); + { + //glTranslatef(position.x, position.y, position.z); + glm::vec3 axis = glm::axis(rotation); + glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z); + + + glPushMatrix(); + glm::vec3 positionToCenter = center - position; + glTranslatef(positionToCenter.x, positionToCenter.y, positionToCenter.z); + + glScalef(dimensions.x, dimensions.y, dimensions.z); + //Application::getInstance()->getDeferredLightingEffect()->renderWireCube(1.0f); + Application::getInstance()->getDeferredLightingEffect()->renderWireSphere(0.5f, 15, 15); + + glBegin(GL_LINES); + + // low-z side - blue + glColor4f(0.0f, 0.0f, 1.0f, 1.0f); + glVertex3f(-0.5f, -0.5f, -0.5f); + glVertex3f(0.5f, -0.5f, -0.5f); + glVertex3f(-0.5f, 0.5f, -0.5f); + glVertex3f(0.5f, 0.5f, -0.5f); + glVertex3f(0.5f, 0.5f, -0.5f); + glVertex3f(0.5f, -0.5f, -0.5f); + glVertex3f(-0.5f, 0.5f, -0.5f); + glVertex3f(-0.5f, -0.5f, -0.5f); + + // high-z side - cyan + glColor4f(0.0f, 1.0f, 1.0f, 1.0f); + glVertex3f(-0.5f, -0.5f, 0.5f); + glVertex3f( 0.5f, -0.5f, 0.5f); + glVertex3f(-0.5f, 0.5f, 0.5f); + glVertex3f( 0.5f, 0.5f, 0.5f); + glVertex3f( 0.5f, 0.5f, 0.5f); + glVertex3f( 0.5f, -0.5f, 0.5f); + glVertex3f(-0.5f, 0.5f, 0.5f); + glVertex3f(-0.5f, -0.5f, 0.5f); + + // low-x side - yellow + glColor4f(1.0f, 1.0f, 0.0f, 1.0f); + glVertex3f(-0.5f, -0.5f, -0.5f); + glVertex3f(-0.5f, -0.5f, 0.5f); + + glVertex3f(-0.5f, -0.5f, 0.5f); + glVertex3f(-0.5f, 0.5f, 0.5f); + + glVertex3f(-0.5f, 0.5f, 0.5f); + glVertex3f(-0.5f, 0.5f, -0.5f); + + glVertex3f(-0.5f, 0.5f, -0.5f); + glVertex3f(-0.5f, -0.5f, -0.5f); + + // high-x side - red + glColor4f(1.0f, 0.0f, 0.0f, 1.0f); + glVertex3f(0.5f, -0.5f, -0.5f); + glVertex3f(0.5f, -0.5f, 0.5f); + glVertex3f(0.5f, -0.5f, 0.5f); + glVertex3f(0.5f, 0.5f, 0.5f); + glVertex3f(0.5f, 0.5f, 0.5f); + glVertex3f(0.5f, 0.5f, -0.5f); + glVertex3f(0.5f, 0.5f, -0.5f); + glVertex3f(0.5f, -0.5f, -0.5f); + + + // origin and direction - green + float distanceToHit; + BoxFace ignoreFace; + + entityFrameBox.findRayIntersection(entityFrameOriginInMeters, entityFrameDirectionInMeters, distanceToHit, ignoreFace); + glm::vec3 pointOfIntersection = entityFrameOriginInMeters + (entityFrameDirectionInMeters * distanceToHit); + +qDebug() << "distanceToHit: " << distanceToHit; +qDebug() << "pointOfIntersection: " << pointOfIntersection; + + glm::vec3 pointA = pointOfIntersection + (entityFrameDirectionInMeters * -1.0f); + glm::vec3 pointB = pointOfIntersection + (entityFrameDirectionInMeters * 1.0f); +qDebug() << "pointA: " << pointA; +qDebug() << "pointB: " << pointB; + + glColor4f(0.0f, 1.0f, 0.0f, 1.0f); + glVertex3f(pointA.x, pointA.y, pointA.z); + glVertex3f(pointB.x, pointB.y, pointB.z); + + glEnd(); + + glPopMatrix(); + } + glPopMatrix(); + } + + QImage colorData(width, height, QImage::Format_ARGB32); + QVector depthData(width * height); + + glReadPixels(0, 0, width, height, GL_BGRA, GL_UNSIGNED_BYTE, colorData.bits()); + glReadPixels(0, 0, width, height, GL_DEPTH_COMPONENT, GL_FLOAT, depthData.data()); + + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + + glEnable(GL_BLEND); + glDisable(GL_SCISSOR_TEST); + + Application::getInstance()->getTextureCache()->getPrimaryFramebufferObject()->release(); + + glViewport(0, 0, Application::getInstance()->getGLWidget()->width(), Application::getInstance()->getGLWidget()->height()); + + QImage imageData = colorData.mirrored(false,true); + + bool saved = imageData.save("/Users/zappoman/Development/foo.bmp"); + + qDebug() << " saved:" << saved; + + + return 0.0f; +} + diff --git a/interface/src/entities/RenderableModelEntityItem.h b/interface/src/entities/RenderableModelEntityItem.h index 48c9a26051..09db54d64f 100644 --- a/interface/src/entities/RenderableModelEntityItem.h +++ b/interface/src/entities/RenderableModelEntityItem.h @@ -28,6 +28,9 @@ #include #include +#include +#include + class RenderableModelEntityItem : public ModelEntityItem { public: static EntityItem* factory(const EntityItemID& entityID, const EntityItemProperties& properties); @@ -51,6 +54,11 @@ public: virtual void somethingChangedNotification() { _needsInitialSimulation = true; } virtual void render(RenderArgs* args); + virtual bool supportsDetailedRayIntersection() const { return true; } + virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, + bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, + void** intersectedObject) const; + Model* getModel(EntityTreeRenderer* renderer); private: void remapTextures(); @@ -63,6 +71,9 @@ private: QString _currentTextures; QStringList _originalTextures; bool _originalTexturesRead; + + float depthOfRayIntersection(const glm::vec3& entityFrameOrigin, const glm::vec3& entityFrameDirection) const; + }; #endif // hifi_RenderableModelEntityItem_h diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index b2570b7c28..74aa190a26 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -103,6 +103,9 @@ Model::SkinLocations Model::_skinNormalSpecularMapLocations; Model::SkinLocations Model::_skinShadowLocations; Model::SkinLocations Model::_skinTranslucentLocations; +ProgramObject Model::_selectProgram; +Model::Locations Model::_selectLocations; + void Model::setScale(const glm::vec3& scale) { setScaleInternal(scale); // if anyone sets scale manually, then we are no longer scaled to fit @@ -269,7 +272,7 @@ void Model::init() { _program.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/model.vert"); _program.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + "shaders/model.frag"); _program.link(); - + initProgram(_program, _locations); _normalMapProgram.addShaderFromSourceFile(QGLShader::Vertex, @@ -387,6 +390,14 @@ void Model::init() { _skinTranslucentProgram.link(); initSkinProgram(_skinTranslucentProgram, _skinTranslucentLocations); + + + // select/ray picking program + _selectProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/select.vert"); + _selectProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + "shaders/select.frag"); + _selectProgram.link(); + initProgram(_selectProgram, _selectLocations); + } } @@ -2148,6 +2159,13 @@ void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, f ProgramObject* activeProgram = program; Locations* activeLocations = locations; + // XXXBHG - hack to render yellow + if (mode == SELECT_RENDER_MODE) { + //activeProgram = &_selectProgram; + //activeLocations = &_selectLocations; + // need skin version + } + if (isSkinned) { activeProgram = skinProgram; activeLocations = skinLocations; diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index d24e4d9f2e..9fdec3f25b 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -86,7 +86,7 @@ public: void reset(); virtual void simulate(float deltaTime, bool fullUpdate = true); - enum RenderMode { DEFAULT_RENDER_MODE, SHADOW_RENDER_MODE, DIFFUSE_RENDER_MODE, NORMAL_RENDER_MODE }; + enum RenderMode { DEFAULT_RENDER_MODE, SHADOW_RENDER_MODE, DIFFUSE_RENDER_MODE, NORMAL_RENDER_MODE, SELECT_RENDER_MODE }; bool render(float alpha = 1.0f, RenderMode mode = DEFAULT_RENDER_MODE, RenderArgs* args = NULL); @@ -318,6 +318,8 @@ private: static ProgramObject _skinTranslucentProgram; static ProgramObject _skinShadowProgram; + + static ProgramObject _selectProgram; static int _normalMapTangentLocation; static int _normalSpecularMapTangentLocation; @@ -343,6 +345,8 @@ private: static Locations _lightmapSpecularMapLocations; static Locations _lightmapNormalSpecularMapLocations; + static Locations _selectLocations; + static void initProgram(ProgramObject& program, Locations& locations, int specularTextureUnit = 1); class SkinLocations : public Locations { From f4e1af6abc2f0d17f5965a57cbb006765cd56131 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 4 Dec 2014 12:02:30 -0800 Subject: [PATCH 212/502] clean code in GeometryCache around the FBX file loader --- interface/src/renderer/GeometryCache.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/interface/src/renderer/GeometryCache.cpp b/interface/src/renderer/GeometryCache.cpp index b64b8f1a90..2d876a287f 100644 --- a/interface/src/renderer/GeometryCache.cpp +++ b/interface/src/renderer/GeometryCache.cpp @@ -832,7 +832,6 @@ void GeometryReader::run() { if (!_reply) { throw QString("Reply is NULL ?!"); } - QString urlnameQ = _url.path().toLower(); std::string urlname = _url.path().toLower().toStdString(); bool urlValid = true; urlValid &= !urlname.empty(); @@ -841,8 +840,7 @@ void GeometryReader::run() { || _url.path().toLower().endsWith(".svo"); if (urlValid) { - QString urlnameQ = _url.path().toLower(); - std::string urlnameQstd = urlnameQ.toStdString(); + // Let's read the binaries from the network QByteArray fileBinary = _reply->readAll(); if (fileBinary.isEmpty() || fileBinary.isNull()) { throw QString("Read File binary is empty?!"); @@ -868,8 +866,7 @@ void GeometryReader::run() { } else { throw QString("url is invalid"); } - // _url.path().toLower().endsWith(".svo") ? readSVO(_reply->readAll()) : readFBX(_reply->readAll(), _mapping))); - + } catch (const QString& error) { qDebug() << "Error reading " << _url << ": " << error; QMetaObject::invokeMethod(geometry.data(), "finishedLoading", Q_ARG(bool, false)); From 5e2d1c33644a39d9aa65374c48ea5f3324e915af Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Thu, 4 Dec 2014 21:15:10 +0100 Subject: [PATCH 213/502] more comfortable movement setting --- examples/virtualKeyboard.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/virtualKeyboard.js b/examples/virtualKeyboard.js index cd2ce9f7ba..58b44e8585 100644 --- a/examples/virtualKeyboard.js +++ b/examples/virtualKeyboard.js @@ -34,7 +34,7 @@ const CURSOR_HEIGHT = 33.9; // VIEW_ANGLE can be adjusted to your likings, the smaller the faster movement. // Try setting it to 60 if it goes too fast for you. -const VIEW_ANGLE = 30.0; +const VIEW_ANGLE = 40.0; const VIEW_ANGLE_BY_TWO = VIEW_ANGLE / 2; const SPAWN_DISTANCE = 1; From e3a34f6db0c835c0bf1f24c13eb6bf7aee054386 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 4 Dec 2014 12:17:31 -0800 Subject: [PATCH 214/502] Add multi-speed control to gamepad.js --- examples/gamepad.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/examples/gamepad.js b/examples/gamepad.js index a2f1034e26..0012103c4e 100644 --- a/examples/gamepad.js +++ b/examples/gamepad.js @@ -16,6 +16,8 @@ var AXIS_STRAFE = Joysticks.AXIS_LEFT_X; var AXIS_FORWARD = Joysticks.AXIS_LEFT_Y; var AXIS_ROTATE = Joysticks.AXIS_RIGHT_X; +var BUTTON_SPRINT = Joysticks.BUTTON_LEFT_STICK; + var BUTTON_TURN_AROUND = Joysticks.BUTTON_RIGHT_STICK; var BUTTON_FLY_UP = Joysticks.BUTTON_RIGHT_SHOULDER; @@ -31,7 +33,8 @@ var BUTTON_WARP_RIGHT = Joysticks.BUTTON_DPAD_RIGHT; var WARP_DISTANCE = 1; // Walk speed in m/s -var MOVE_SPEED = 2; +var MOVE_SPEED = 0.5; +var MOVE_SPRINT_SPEED = 2; // Amount to rotate in radians var ROTATE_INCREMENT = Math.PI / 8; @@ -49,6 +52,7 @@ var flyUpButtonState = false; // Current move direction, axis aligned - that is, looking down and moving forward // will not move you into the ground, but instead will keep you on the horizontal plane. var moveDirection = { x: 0, y: 0, z: 0 }; +var sprintButtonState = false; var warpActive = false; var warpPosition = { x: 0, y: 0, z: 0 }; @@ -173,6 +177,8 @@ function reportButtonValue(button, newValue, oldValue) { MyAvatar.orientation = Quat.multiply( Quat.fromPitchYawRollRadians(0, Math.PI, 0), MyAvatar.orientation); } + } else if (button == BUTTON_SPRINT) { + sprintButtonState = newValue; } else if (newValue) { var direction = null; @@ -209,9 +215,10 @@ function update(dt) { var move = copyVec3(moveDirection); move.y = 0; if (Vec3.length(move) > 0) { + speed = sprintButtonState ? MOVE_SPRINT_SPEED : MOVE_SPEED; velocity = Vec3.multiplyQbyV(Camera.getOrientation(), move); velocity.y = 0; - velocity = Vec3.multiply(Vec3.normalize(velocity), MOVE_SPEED); + velocity = Vec3.multiply(Vec3.normalize(velocity), speed); } if (moveDirection.y != 0) { From 3215957398c554376a808bd545f1335b4398c9af Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 4 Dec 2014 12:31:40 -0800 Subject: [PATCH 215/502] better interpretation of the hifi light intensity and fixes for compilation on mac --- libraries/fbx/src/FBXReader.cpp | 9 ++++++--- libraries/fbx/src/FBXReader.h | 7 +++++++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 80d8660b9f..827af802e5 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -1200,11 +1200,11 @@ FBXLight extractLight(const FBXNode& object) { FBXLight light; foreach (const FBXNode& subobject, object.children) { - std::string childname = subobject.name; + std::string childname = QString(subobject.name).toStdString(); if (subobject.name == "Properties70") { foreach (const FBXNode& property, subobject.children) { int valIndex = 4; - std::string propName = property.name; + std::string propName = QString(property.name).toStdString(); if (property.name == "P") { std::string propname = property.properties.at(0).toString().toStdString(); if (propname == "Intensity") { @@ -1784,6 +1784,9 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, auto lit = lights.find(childID.toStdString()); if (lit != lights.end()) { lightmapLevel = (*lit).second.intensity; + if (lightmapLevel <= 0.0f) { + loadLightmaps = false; + } } } } @@ -2094,7 +2097,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, emissiveParams.y = lightmapLevel; QString emissiveTextureID = emissiveTextures.value(childID); QString ambientTextureID = ambientTextures.value(childID); - if (!emissiveTextureID.isNull() || !ambientTextureID.isNull()) { + if (loadLightmaps && (!emissiveTextureID.isNull() || !ambientTextureID.isNull())) { if (!emissiveTextureID.isNull()) { emissiveTexture = getTexture(emissiveTextureID, textureNames, textureFilenames, textureContent, textureParams); diff --git a/libraries/fbx/src/FBXReader.h b/libraries/fbx/src/FBXReader.h index aacfbc0a98..c34a9677a6 100644 --- a/libraries/fbx/src/FBXReader.h +++ b/libraries/fbx/src/FBXReader.h @@ -172,6 +172,13 @@ public: Transform transform; float intensity; glm::vec3 color; + + FBXLight() : + name(), + transform(), + intensity(1.0f), + color(1.0f) + {} }; Q_DECLARE_METATYPE(FBXAnimationFrame) From 842ee714b82785d2ae93b55be9ac10b1119bc97f Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 4 Dec 2014 13:08:16 -0800 Subject: [PATCH 216/502] make text entities correctly ray pick --- libraries/entities/src/TextEntityItem.cpp | 49 ++++++++++++++++++++++- libraries/entities/src/TextEntityItem.h | 5 +++ 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/libraries/entities/src/TextEntityItem.cpp b/libraries/entities/src/TextEntityItem.cpp index 491240c178..17ef33ee1c 100644 --- a/libraries/entities/src/TextEntityItem.cpp +++ b/libraries/entities/src/TextEntityItem.cpp @@ -10,9 +10,12 @@ // +#include + #include #include +#include #include "EntityTree.h" #include "EntityTreeElement.h" @@ -110,4 +113,48 @@ void TextEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBits APPEND_ENTITY_PROPERTY(PROP_LINE_HEIGHT, appendValue, getLineHeight()); APPEND_ENTITY_PROPERTY(PROP_TEXT_COLOR, appendColor, getTextColor()); APPEND_ENTITY_PROPERTY(PROP_BACKGROUND_COLOR, appendColor, getBackgroundColor()); -} \ No newline at end of file +} + + +bool TextEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, + bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, + void** intersectedObject) 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 = _rotation * UNROTATED_NORMAL; + plane.setNormal(normal); + plane.setPoint(_position); // 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; +} diff --git a/libraries/entities/src/TextEntityItem.h b/libraries/entities/src/TextEntityItem.h index 019d230c36..a3d323aefd 100644 --- a/libraries/entities/src/TextEntityItem.h +++ b/libraries/entities/src/TextEntityItem.h @@ -41,6 +41,11 @@ public: ReadBitstreamToTreeParams& args, EntityPropertyFlags& propertyFlags, bool overwriteLocalData); + virtual bool supportsDetailedRayIntersection() const { return true; } + virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, + bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, + void** intersectedObject) const; + static const QString DEFAULT_TEXT; void setText(const QString& value) { _text = value; } const QString& getText() const { return _text; } From 5ec9a9b6eda41117da2002c2f56da4d89693cfcf Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 4 Dec 2014 13:08:16 -0800 Subject: [PATCH 217/502] make text entities correctly ray pick --- libraries/entities/src/TextEntityItem.cpp | 49 ++++++++++++++++++++++- libraries/entities/src/TextEntityItem.h | 5 +++ 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/libraries/entities/src/TextEntityItem.cpp b/libraries/entities/src/TextEntityItem.cpp index 491240c178..17ef33ee1c 100644 --- a/libraries/entities/src/TextEntityItem.cpp +++ b/libraries/entities/src/TextEntityItem.cpp @@ -10,9 +10,12 @@ // +#include + #include #include +#include #include "EntityTree.h" #include "EntityTreeElement.h" @@ -110,4 +113,48 @@ void TextEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBits APPEND_ENTITY_PROPERTY(PROP_LINE_HEIGHT, appendValue, getLineHeight()); APPEND_ENTITY_PROPERTY(PROP_TEXT_COLOR, appendColor, getTextColor()); APPEND_ENTITY_PROPERTY(PROP_BACKGROUND_COLOR, appendColor, getBackgroundColor()); -} \ No newline at end of file +} + + +bool TextEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, + bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, + void** intersectedObject) 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 = _rotation * UNROTATED_NORMAL; + plane.setNormal(normal); + plane.setPoint(_position); // 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; +} diff --git a/libraries/entities/src/TextEntityItem.h b/libraries/entities/src/TextEntityItem.h index 019d230c36..a3d323aefd 100644 --- a/libraries/entities/src/TextEntityItem.h +++ b/libraries/entities/src/TextEntityItem.h @@ -41,6 +41,11 @@ public: ReadBitstreamToTreeParams& args, EntityPropertyFlags& propertyFlags, bool overwriteLocalData); + virtual bool supportsDetailedRayIntersection() const { return true; } + virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, + bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, + void** intersectedObject) const; + static const QString DEFAULT_TEXT; void setText(const QString& value) { _text = value; } const QString& getText() const { return _text; } From 500b8a49d1969d4ab412af7164e008b903f02b57 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 4 Dec 2014 14:17:24 -0800 Subject: [PATCH 218/502] Add button to gamepad.js to toggle mirror mode --- examples/gamepad.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/examples/gamepad.js b/examples/gamepad.js index 0012103c4e..d8a7e33fe3 100644 --- a/examples/gamepad.js +++ b/examples/gamepad.js @@ -18,6 +18,8 @@ var AXIS_ROTATE = Joysticks.AXIS_RIGHT_X; var BUTTON_SPRINT = Joysticks.BUTTON_LEFT_STICK; +var BUTTON_TOGGLE_MIRROR = Joysticks.BUTTON_FACE_LEFT; + var BUTTON_TURN_AROUND = Joysticks.BUTTON_RIGHT_STICK; var BUTTON_FLY_UP = Joysticks.BUTTON_RIGHT_SHOULDER; @@ -49,6 +51,10 @@ var WARP_PICK_MAX_DISTANCE = 100; var flyDownButtonState = false; var flyUpButtonState = false; +// When toggling to mirror mode, this stores the mode the user was previously in +// so it can be toggled back to. +var toggledFromCameraMode = 'first person'; + // Current move direction, axis aligned - that is, looking down and moving forward // will not move you into the ground, but instead will keep you on the horizontal plane. var moveDirection = { x: 0, y: 0, z: 0 }; @@ -179,6 +185,16 @@ function reportButtonValue(button, newValue, oldValue) { } } else if (button == BUTTON_SPRINT) { sprintButtonState = newValue; + } else if (button == BUTTON_TOGGLE_MIRROR) { + if (newValue) { + var currentMode = Camera.mode; + if (currentMode == "mirror") { + Camera.mode = toggledFromCameraMode; + } else { + toggledFromCameraMode = currentMode; + Camera.mode = "mirror"; + } + } } else if (newValue) { var direction = null; From 4168993ebe2415e83bf6cf499b24d69b60ec42cb Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 4 Dec 2014 14:23:47 -0800 Subject: [PATCH 219/502] Replace c++11 usage of auto by explicit declaration --- libraries/fbx/src/FBXReader.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 827af802e5..a750ab53e2 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -1781,7 +1781,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, QString parentID = getID(connection.properties, 2); ooChildToParent.insert(childID, parentID); if (!hifiGlobalNodeID.isEmpty() && (parentID == hifiGlobalNodeID)) { - auto lit = lights.find(childID.toStdString()); + std::map< std::string, FBXLight >::iterator lit = lights.find(childID.toStdString()); if (lit != lights.end()) { lightmapLevel = (*lit).second.intensity; if (lightmapLevel <= 0.0f) { @@ -1856,8 +1856,8 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, // TODO: check if is code is needed if (!lights.empty()) { if (hifiGlobalNodeID.isEmpty()) { - auto l = (*lights.begin()); - lightmapLevel = (l.second).intensity; + std::map< std::string, FBXLight >::iterator l = lights.begin(); + lightmapLevel = (*l).second.intensity; } } From 3bbee640fbf4f78327ef1df7f6faf10c7c32ac66 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 4 Dec 2014 14:48:03 -0800 Subject: [PATCH 220/502] Make gamepad mirror button toggle --- examples/gamepad.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/gamepad.js b/examples/gamepad.js index d8a7e33fe3..e9033995d3 100644 --- a/examples/gamepad.js +++ b/examples/gamepad.js @@ -188,12 +188,12 @@ function reportButtonValue(button, newValue, oldValue) { } else if (button == BUTTON_TOGGLE_MIRROR) { if (newValue) { var currentMode = Camera.mode; - if (currentMode == "mirror") { - Camera.mode = toggledFromCameraMode; - } else { + if (currentMode != "mirror") { toggledFromCameraMode = currentMode; - Camera.mode = "mirror"; } + Camera.mode = "mirror"; + } else { + Camera.mode = toggledFromCameraMode; } } else if (newValue) { var direction = null; From ba3f051c8cf0fd952de55eca995489d644fbc427 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 4 Dec 2014 15:11:16 -0800 Subject: [PATCH 221/502] Disable the warp button in gamepad.js --- examples/gamepad.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/gamepad.js b/examples/gamepad.js index e9033995d3..cc275e6267 100644 --- a/examples/gamepad.js +++ b/examples/gamepad.js @@ -24,7 +24,7 @@ var BUTTON_TURN_AROUND = Joysticks.BUTTON_RIGHT_STICK; var BUTTON_FLY_UP = Joysticks.BUTTON_RIGHT_SHOULDER; var BUTTON_FLY_DOWN = Joysticks.BUTTON_LEFT_SHOULDER; -var BUTTON_WARP = Joysticks.BUTTON_FACE_RIGHT; +var BUTTON_WARP = null; // Disable for now var BUTTON_WARP_FORWARD = Joysticks.BUTTON_DPAD_UP; var BUTTON_WARP_BACKWARD = Joysticks.BUTTON_DPAD_DOWN; From a7185738e9e961be7afe5e66c151024efb0fc097 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Fri, 5 Dec 2014 00:52:36 +0100 Subject: [PATCH 222/502] virtualkeyboard: scaling text in input box --- examples/virtualKeyboard.js | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/examples/virtualKeyboard.js b/examples/virtualKeyboard.js index 58b44e8585..3d00f934e2 100644 --- a/examples/virtualKeyboard.js +++ b/examples/virtualKeyboard.js @@ -56,6 +56,7 @@ const TEXT_MARGIN_BOTTOM = 0.17; var windowDimensions = Controller.getViewportDimensions(); var cursor = null; var keyboard = new Keyboard(); +var textFontSize = 9; var text = null; var textText = ""; var textSizeMeasureOverlay = Overlays.addOverlay("text3d", {visible: false}); @@ -65,15 +66,39 @@ function appendChar(char) { updateTextOverlay(); Overlays.editOverlay(text, {text: textText}); } + function deleteChar() { if (textText.length > 0) { textText = textText.substring(0, textText.length - 1); updateTextOverlay(); } } + function updateTextOverlay() { - Overlays.editOverlay(text, {text: textText}); + var textwidth = Overlays.textWidth(text, textText); + var textLines = textText.split("\n"); + var maxLineWidth = 0; + for (textLine in textLines) { + var lineWidth = Overlays.textWidth(text, textLines[textLine]); + if (lineWidth > maxLineWidth) { + maxLineWidth = lineWidth; + } + } + var suggestedFontSize = (windowDimensions.x / maxLineWidth) * textFontSize * 0.90; + var maxFontSize = 240 / textLines.length; + textFontSize = (suggestedFontSize > maxFontSize) ? maxFontSize : suggestedFontSize; + var topMargin = (250 - (textFontSize * textLines.length)) / 2; + Overlays.editOverlay(text, {text: textText, font: {size: textFontSize}, topMargin: topMargin}); + var maxLineWidth = 0; + for (textLine in textLines) { + var lineWidth = Overlays.textWidth(text, textLines[textLine]); + if (lineWidth > maxLineWidth) { + maxLineWidth = lineWidth; + } + } + Overlays.editOverlay(text, {leftMargin: (windowDimensions.x - maxLineWidth) / 2}); } + keyboard.onKeyPress = function(event) { if (event.event == 'keypress') { appendChar(event.char); @@ -141,12 +166,13 @@ keyboard.onFullyLoaded = function() { height: 250, backgroundColor: { red: 255, green: 255, blue: 255}, color: { red: 0, green: 0, blue: 0}, - topMargin: 10, - leftMargin: 8, - font: {size: 28}, + topMargin: 5, + leftMargin: 0, + font: {size: textFontSize}, text: "", alpha: 0.8 }); + updateTextOverlay(); // the cursor is being loaded after the keyboard, else it will be on the background of the keyboard cursor = new Cursor(); cursor.onUpdate = function(position) { From c0ba9e73c28725a6662e70d5f7a53879a318d7ea Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Fri, 5 Dec 2014 01:07:49 +0100 Subject: [PATCH 223/502] fixed font height bq --- examples/virtualKeyboard.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/virtualKeyboard.js b/examples/virtualKeyboard.js index 3d00f934e2..2340bcab6e 100644 --- a/examples/virtualKeyboard.js +++ b/examples/virtualKeyboard.js @@ -85,9 +85,9 @@ function updateTextOverlay() { } } var suggestedFontSize = (windowDimensions.x / maxLineWidth) * textFontSize * 0.90; - var maxFontSize = 240 / textLines.length; + var maxFontSize = 190 / textLines.length; textFontSize = (suggestedFontSize > maxFontSize) ? maxFontSize : suggestedFontSize; - var topMargin = (250 - (textFontSize * textLines.length)) / 2; + var topMargin = (250 - (textFontSize * textLines.length)) / 4; Overlays.editOverlay(text, {text: textText, font: {size: textFontSize}, topMargin: topMargin}); var maxLineWidth = 0; for (textLine in textLines) { From 1102b4d633841e54cc780caccd49698af8357eba Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 4 Dec 2014 16:40:55 -0800 Subject: [PATCH 224/502] Moving GPU into it's own library --- interface/CMakeLists.txt | 2 +- libraries/gpu/CMakeLists.txt | 52 +++++++++++++++++++ .../gpu}/src/gpu/Batch.cpp | 0 {interface => libraries/gpu}/src/gpu/Batch.h | 4 +- .../gpu}/src/gpu/Context.cpp | 0 .../gpu}/src/gpu/Context.h | 4 +- {interface => libraries/gpu}/src/gpu/Format.h | 2 +- .../gpu}/src/gpu/GLBackend.cpp | 2 +- .../gpu}/src/gpu/GLBackend.h | 6 +-- libraries/gpu/src/gpu/GPUConfig.h | 30 +++++++++++ .../gpu}/src/gpu/Resource.cpp | 0 .../gpu}/src/gpu/Resource.h | 4 +- .../gpu}/src/gpu/Stream.cpp | 0 {interface => libraries/gpu}/src/gpu/Stream.h | 6 +-- 14 files changed, 97 insertions(+), 15 deletions(-) create mode 100644 libraries/gpu/CMakeLists.txt rename {interface => libraries/gpu}/src/gpu/Batch.cpp (100%) rename {interface => libraries/gpu}/src/gpu/Batch.h (98%) rename {interface => libraries/gpu}/src/gpu/Context.cpp (100%) rename {interface => libraries/gpu}/src/gpu/Context.h (94%) rename {interface => libraries/gpu}/src/gpu/Format.h (98%) rename {interface => libraries/gpu}/src/gpu/GLBackend.cpp (99%) rename {interface => libraries/gpu}/src/gpu/GLBackend.h (98%) create mode 100644 libraries/gpu/src/gpu/GPUConfig.h rename {interface => libraries/gpu}/src/gpu/Resource.cpp (100%) rename {interface => libraries/gpu}/src/gpu/Resource.h (98%) rename {interface => libraries/gpu}/src/gpu/Stream.cpp (100%) rename {interface => libraries/gpu}/src/gpu/Stream.h (97%) diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index eb788ac49a..38dd02c655 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -107,7 +107,7 @@ endif() add_executable(${TARGET_NAME} MACOSX_BUNDLE ${INTERFACE_SRCS} ${QM}) # link required hifi libraries -link_hifi_libraries(shared octree voxels fbx metavoxels networking entities avatars audio animation script-engine physics) +link_hifi_libraries(shared octree voxels gpu fbx metavoxels networking entities avatars audio animation script-engine physics) # find any optional and required libraries find_package(ZLIB REQUIRED) diff --git a/libraries/gpu/CMakeLists.txt b/libraries/gpu/CMakeLists.txt new file mode 100644 index 0000000000..712e4320b5 --- /dev/null +++ b/libraries/gpu/CMakeLists.txt @@ -0,0 +1,52 @@ +set(TARGET_NAME gpu) + +# use setup_hifi_library macro to setup our project and link appropriate Qt modules +setup_hifi_library() + +include_glm() + +link_hifi_libraries(shared) +if (APPLE) + # link in required OS X frameworks and include the right GL headers + find_library(CoreFoundation CoreFoundation) + find_library(OpenGL OpenGL) + + target_link_libraries(${TARGET_NAME} ${CoreFoundation} ${OpenGL}) + + # install command for OS X bundle + INSTALL(TARGETS ${TARGET_NAME} + BUNDLE DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/install" COMPONENT Runtime + RUNTIME DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/install" COMPONENT Runtime + ) +else (APPLE) + find_package(OpenGL REQUIRED) + + if (${OPENGL_INCLUDE_DIR}) + include_directories(SYSTEM "${OPENGL_INCLUDE_DIR}") + endif () + + target_link_libraries(${TARGET_NAME} "${OPENGL_LIBRARY}") + + # link target to external libraries + if (WIN32) + find_package(GLEW REQUIRED) + include_directories(${GLEW_INCLUDE_DIRS}) + + # we're using static GLEW, so define GLEW_STATIC + add_definitions(-DGLEW_STATIC) + + target_link_libraries(${TARGET_NAME} "${GLEW_LIBRARIES}" "${NSIGHT_LIBRARIES}" opengl32.lib) + + # try to find the Nsight package and add it to the build if we find it + find_package(NSIGHT) + if (NSIGHT_FOUND) + include_directories(${NSIGHT_INCLUDE_DIRS}) + add_definitions(-DNSIGHT_FOUND) + target_link_libraries(${TARGET_NAME} "${NSIGHT_LIBRARIES}") + endif () + + endif() +endif (APPLE) + +# call macro to link our dependencies and bubble them up via a property on our target +link_shared_dependencies() diff --git a/interface/src/gpu/Batch.cpp b/libraries/gpu/src/gpu/Batch.cpp similarity index 100% rename from interface/src/gpu/Batch.cpp rename to libraries/gpu/src/gpu/Batch.cpp diff --git a/interface/src/gpu/Batch.h b/libraries/gpu/src/gpu/Batch.h similarity index 98% rename from interface/src/gpu/Batch.h rename to libraries/gpu/src/gpu/Batch.h index 5304740dd3..601ae63a77 100644 --- a/interface/src/gpu/Batch.h +++ b/libraries/gpu/src/gpu/Batch.h @@ -12,13 +12,13 @@ #define hifi_gpu_Batch_h #include -#include "InterfaceConfig.h" +#include "GPUConfig.h" #include "Transform.h" #include -#include "gpu/Stream.h" +#include "Stream.h" #if defined(NSIGHT_FOUND) #include "nvToolsExt.h" diff --git a/interface/src/gpu/Context.cpp b/libraries/gpu/src/gpu/Context.cpp similarity index 100% rename from interface/src/gpu/Context.cpp rename to libraries/gpu/src/gpu/Context.cpp diff --git a/interface/src/gpu/Context.h b/libraries/gpu/src/gpu/Context.h similarity index 94% rename from interface/src/gpu/Context.h rename to libraries/gpu/src/gpu/Context.h index 8398288cb9..3a0fffb4ef 100644 --- a/interface/src/gpu/Context.h +++ b/libraries/gpu/src/gpu/Context.h @@ -12,9 +12,9 @@ #define hifi_gpu_Context_h #include -#include "InterfaceConfig.h" +#include "GPUConfig.h" -#include "gpu/Resource.h" +#include "Resource.h" namespace gpu { diff --git a/interface/src/gpu/Format.h b/libraries/gpu/src/gpu/Format.h similarity index 98% rename from interface/src/gpu/Format.h rename to libraries/gpu/src/gpu/Format.h index 8faa995924..d216495b4c 100644 --- a/interface/src/gpu/Format.h +++ b/libraries/gpu/src/gpu/Format.h @@ -12,7 +12,7 @@ #define hifi_gpu_Format_h #include -#include "InterfaceConfig.h" +#include "GPUConfig.h" namespace gpu { diff --git a/interface/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp similarity index 99% rename from interface/src/gpu/GLBackend.cpp rename to libraries/gpu/src/gpu/GLBackend.cpp index 1f8e7bf99f..85f0dde858 100644 --- a/interface/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -12,7 +12,7 @@ #include -#include "gpu/Batch.h" +#include "Batch.h" using namespace gpu; diff --git a/interface/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h similarity index 98% rename from interface/src/gpu/GLBackend.h rename to libraries/gpu/src/gpu/GLBackend.h index 0e4b38d89e..5a40e9ca36 100644 --- a/interface/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -12,10 +12,10 @@ #define hifi_gpu_GLBackend_h #include -#include "InterfaceConfig.h" +#include "GPUConfig.h" -#include "gpu/Context.h" -#include "gpu/Batch.h" +#include "Context.h" +#include "Batch.h" #include diff --git a/libraries/gpu/src/gpu/GPUConfig.h b/libraries/gpu/src/gpu/GPUConfig.h new file mode 100644 index 0000000000..024cf73112 --- /dev/null +++ b/libraries/gpu/src/gpu/GPUConfig.h @@ -0,0 +1,30 @@ +// +// GPUConfig.h +// libraries/gpu/src/gpu +// +// Created by Sam Gateau on 12/4/14. +// Copyright 2013 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 gpu__GPUConfig__ +#define gpu__GPUConfig__ + +#define GL_GLEXT_PROTOTYPES 1 + +#if defined(APPLE) +#include + +#elif defined(UNIX) +#include +#include + +#elif defined(WIN32) +#include +#include + +#endif + +#endif diff --git a/interface/src/gpu/Resource.cpp b/libraries/gpu/src/gpu/Resource.cpp similarity index 100% rename from interface/src/gpu/Resource.cpp rename to libraries/gpu/src/gpu/Resource.cpp diff --git a/interface/src/gpu/Resource.h b/libraries/gpu/src/gpu/Resource.h similarity index 98% rename from interface/src/gpu/Resource.h rename to libraries/gpu/src/gpu/Resource.h index 52108c215a..6247efe675 100644 --- a/interface/src/gpu/Resource.h +++ b/libraries/gpu/src/gpu/Resource.h @@ -12,9 +12,9 @@ #define hifi_gpu_Resource_h #include -#include "InterfaceConfig.h" +#include "GPUConfig.h" -#include "gpu/Format.h" +#include "Format.h" #include diff --git a/interface/src/gpu/Stream.cpp b/libraries/gpu/src/gpu/Stream.cpp similarity index 100% rename from interface/src/gpu/Stream.cpp rename to libraries/gpu/src/gpu/Stream.cpp diff --git a/interface/src/gpu/Stream.h b/libraries/gpu/src/gpu/Stream.h similarity index 97% rename from interface/src/gpu/Stream.h rename to libraries/gpu/src/gpu/Stream.h index d024182531..93abfeeca3 100644 --- a/interface/src/gpu/Stream.h +++ b/libraries/gpu/src/gpu/Stream.h @@ -12,10 +12,10 @@ #define hifi_gpu_Stream_h #include -#include "InterfaceConfig.h" +#include "GPUConfig.h" -#include "gpu/Resource.h" -#include "gpu/Format.h" +#include "Resource.h" +#include "Format.h" #include #include From 9819658e202692105b43f1fbc650ca9f382c3a4f Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 4 Dec 2014 16:41:19 -0800 Subject: [PATCH 225/502] Spanner subdivision streaming bits. --- .../metavoxels/src/AttributeRegistry.cpp | 61 ++++++++++++++----- libraries/metavoxels/src/Bitstream.cpp | 14 ++++- libraries/metavoxels/src/Bitstream.h | 10 ++- libraries/metavoxels/src/SharedObject.cpp | 4 +- libraries/metavoxels/src/SharedObject.h | 9 +-- libraries/metavoxels/src/Spanner.cpp | 8 ++- libraries/metavoxels/src/Spanner.h | 4 +- 7 files changed, 81 insertions(+), 29 deletions(-) diff --git a/libraries/metavoxels/src/AttributeRegistry.cpp b/libraries/metavoxels/src/AttributeRegistry.cpp index fbc7f0d110..afdc0c923f 100644 --- a/libraries/metavoxels/src/AttributeRegistry.cpp +++ b/libraries/metavoxels/src/AttributeRegistry.cpp @@ -1274,25 +1274,37 @@ void SpannerSetAttribute::writeMetavoxelRoot(const MetavoxelNode& root, Metavoxe void SpannerSetAttribute::readMetavoxelDelta(MetavoxelData& data, const MetavoxelNode& reference, MetavoxelStreamState& state) { - forever { - SharedObjectPointer object; - state.base.stream >> object; - if (!object) { - break; + readMetavoxelSubdivision(data, state); +} + +static void writeDeltaSubdivision(SharedObjectSet& oldSet, SharedObjectSet& newSet, Bitstream& stream) { + for (SharedObjectSet::iterator newIt = newSet.begin(); newIt != newSet.end(); ) { + SharedObjectSet::iterator oldIt = oldSet.find(*newIt); + if (oldIt == oldSet.end()) { + stream << *newIt; // added + newIt = newSet.erase(newIt); + + } else { + oldSet.erase(oldIt); + newIt++; } - data.toggle(state.base.attribute, object); } - // even if the root is empty, it should still exist - if (!data.getRoot(state.base.attribute)) { - data.createRoot(state.base.attribute); + foreach (const SharedObjectPointer& object, oldSet) { + stream << object; // removed } + stream << SharedObjectPointer(); + foreach (const SharedObjectPointer& object, newSet) { + object->maybeWriteSubdivision(stream); + } + stream << SharedObjectPointer(); } void SpannerSetAttribute::writeMetavoxelDelta(const MetavoxelNode& root, const MetavoxelNode& reference, MetavoxelStreamState& state) { - state.base.visit = Spanner::getAndIncrementNextVisit(); - root.writeSpannerDelta(reference, state); - state.base.stream << SharedObjectPointer(); + SharedObjectSet oldSet, newSet; + reference.getSpanners(this, state.minimum, state.size, state.base.referenceLOD, oldSet); + root.getSpanners(this, state.minimum, state.size, state.base.lod, newSet); + writeDeltaSubdivision(oldSet, newSet, state.base.stream); } void SpannerSetAttribute::readMetavoxelSubdivision(MetavoxelData& data, MetavoxelStreamState& state) { @@ -1302,14 +1314,31 @@ void SpannerSetAttribute::readMetavoxelSubdivision(MetavoxelData& data, Metavoxe if (!object) { break; } - data.insert(state.base.attribute, object); + data.toggle(state.base.attribute, object); + } + forever { + SharedObjectPointer object; + state.base.stream >> object; + if (!object) { + break; + } + SharedObjectPointer newObject = object->readSubdivision(state.base.stream); + if (newObject != object) { + data.replace(state.base.attribute, object, newObject); + state.base.stream.addSubdividedObject(newObject); + } + } + // even if the root is empty, it should still exist + if (!data.getRoot(state.base.attribute)) { + data.createRoot(state.base.attribute); } } void SpannerSetAttribute::writeMetavoxelSubdivision(const MetavoxelNode& root, MetavoxelStreamState& state) { - state.base.visit = Spanner::getAndIncrementNextVisit(); - root.writeSpannerSubdivision(state); - state.base.stream << SharedObjectPointer(); + SharedObjectSet oldSet, newSet; + root.getSpanners(this, state.minimum, state.size, state.base.referenceLOD, oldSet); + root.getSpanners(this, state.minimum, state.size, state.base.lod, newSet); + writeDeltaSubdivision(oldSet, newSet, state.base.stream); } bool SpannerSetAttribute::metavoxelRootsEqual(const MetavoxelNode& firstRoot, const MetavoxelNode& secondRoot, diff --git a/libraries/metavoxels/src/Bitstream.cpp b/libraries/metavoxels/src/Bitstream.cpp index e4af43feee..c3bd05d3c7 100644 --- a/libraries/metavoxels/src/Bitstream.cpp +++ b/libraries/metavoxels/src/Bitstream.cpp @@ -267,7 +267,9 @@ Bitstream::ReadMappings Bitstream::getAndResetReadMappings() { _typeStreamerStreamer.getAndResetTransientValues(), _attributeStreamer.getAndResetTransientValues(), _scriptStringStreamer.getAndResetTransientValues(), - _sharedObjectStreamer.getAndResetTransientValues() }; + _sharedObjectStreamer.getAndResetTransientValues(), + _subdividedObjects }; + _subdividedObjects.clear(); return mappings; } @@ -291,6 +293,16 @@ void Bitstream::persistReadMappings(const ReadMappings& mappings) { reference = it.value(); _weakSharedObjectHash.remove(it.value()->getRemoteID()); } + foreach (const SharedObjectPointer& object, mappings.subdividedObjects) { + QPointer& reference = _sharedObjectReferences[object->getRemoteOriginID()]; + if (reference && reference != object) { + int id = _sharedObjectStreamer.removePersistentValue(reference.data()); + if (id != 0) { + _sharedObjectStreamer.insertPersistentValue(id, object); + } + } + reference = object; + } } void Bitstream::persistAndResetReadMappings() { diff --git a/libraries/metavoxels/src/Bitstream.h b/libraries/metavoxels/src/Bitstream.h index e5aa30fac5..121aa6c672 100644 --- a/libraries/metavoxels/src/Bitstream.h +++ b/libraries/metavoxels/src/Bitstream.h @@ -99,10 +99,12 @@ public: int takePersistentID(P value) { return _persistentIDs.take(value); } - void removePersistentValue(V value) { int id = _valueIDs.take(value); _persistentValues.remove(id); } + int removePersistentValue(V value) { int id = _valueIDs.take(value); _persistentValues.remove(id); return id; } V takePersistentValue(int id) { V value = _persistentValues.take(id); _valueIDs.remove(value); return value; } + void insertPersistentValue(int id, V value) { _valueIDs.insert(value, id); _persistentValues.insert(id, value); } + void copyPersistentMappings(const RepeatedValueStreamer& other); void clearPersistentMappings(); @@ -289,6 +291,7 @@ public: QHash attributeValues; QHash scriptStringValues; QHash sharedObjectValues; + QVector subdividedObjects; }; /// Performs all of the various lazily initializations (of object streamers, etc.) If multiple threads need to use @@ -374,6 +377,9 @@ public: /// Resets to the initial state. void reset(); + /// Adds a subdivided object, which will be added to the read mappings and used as a reference if persisted. + void addSubdividedObject(const SharedObjectPointer& object) { _subdividedObjects.append(object); } + /// Returns the set of transient mappings gathered during writing and resets them. WriteMappings getAndResetWriteMappings(); @@ -576,6 +582,8 @@ private: RepeatedValueStreamer _scriptStringStreamer; RepeatedValueStreamer _sharedObjectStreamer; + QVector _subdividedObjects; + WeakSharedObjectHash _sharedObjectReferences; WeakSharedObjectHash _weakSharedObjectHash; diff --git a/libraries/metavoxels/src/SharedObject.cpp b/libraries/metavoxels/src/SharedObject.cpp index 95dc75fec0..dcfa9732b3 100644 --- a/libraries/metavoxels/src/SharedObject.cpp +++ b/libraries/metavoxels/src/SharedObject.cpp @@ -147,11 +147,11 @@ void SharedObject::readExtraDelta(Bitstream& in, const SharedObject* reference) // nothing by default } -void SharedObject::writeExtraSubdivision(Bitstream& out) { +void SharedObject::maybeWriteSubdivision(Bitstream& out) { // nothing by default } -SharedObject* SharedObject::readExtraSubdivision(Bitstream& in) { +SharedObject* SharedObject::readSubdivision(Bitstream& in) { return this; } diff --git a/libraries/metavoxels/src/SharedObject.h b/libraries/metavoxels/src/SharedObject.h index cf9bf4e645..ebea322bf1 100644 --- a/libraries/metavoxels/src/SharedObject.h +++ b/libraries/metavoxels/src/SharedObject.h @@ -92,12 +92,13 @@ public: /// Reads the delta-encoded non-property contents of this object from the specified stream. virtual void readExtraDelta(Bitstream& in, const SharedObject* reference); - /// Writes the subdivision of the non-property contents of this object to the specified stream. - virtual void writeExtraSubdivision(Bitstream& out); + /// Writes the subdivision of the contents of this object (preceeded by a + /// reference to the object itself) to the specified stream if necessary. + virtual void maybeWriteSubdivision(Bitstream& out); - /// Reads the subdivision of the non-property contents of this object from the specified stream. + /// Reads the subdivision of this object from the specified stream. /// \return the modified object, or this if no modification was performed - virtual SharedObject* readExtraSubdivision(Bitstream& in); + virtual SharedObject* readSubdivision(Bitstream& in); private: diff --git a/libraries/metavoxels/src/Spanner.cpp b/libraries/metavoxels/src/Spanner.cpp index f2a1ebb27f..1dc55a7904 100644 --- a/libraries/metavoxels/src/Spanner.cpp +++ b/libraries/metavoxels/src/Spanner.cpp @@ -3016,7 +3016,7 @@ void Heightfield::readExtraDelta(Bitstream& in, const SharedObject* reference) { } } -void Heightfield::writeExtraSubdivision(Bitstream& out) { +void Heightfield::maybeWriteSubdivision(Bitstream& out) { MetavoxelLOD lod, referenceLOD; if (out.getContext()) { MetavoxelStreamBase* base = static_cast(out.getContext()); @@ -3026,13 +3026,13 @@ void Heightfield::writeExtraSubdivision(Bitstream& out) { HeightfieldStreamBase base = { out, lod, referenceLOD }; HeightfieldStreamState state = { base, glm::vec2(), 1.0f }; - if (state.becameSubdivided()) { + if (state.becameSubdividedOrCollapsed()) { out << SharedObjectPointer(this); _root->writeSubdivision(state); } } -SharedObject* Heightfield::readExtraSubdivision(Bitstream& in) { +SharedObject* Heightfield::readSubdivision(Bitstream& in) { MetavoxelLOD lod, referenceLOD; if (in.getContext()) { MetavoxelStreamBase* base = static_cast(in.getContext()); @@ -3046,6 +3046,8 @@ SharedObject* Heightfield::readExtraSubdivision(Bitstream& in) { HeightfieldNodePointer root(_root->readSubdivision(state)); if (_root != root) { Heightfield* newHeightfield = static_cast(clone(true)); + newHeightfield->setRemoteID(getRemoteID()); + newHeightfield->setRemoteOriginID(getRemoteOriginID()); newHeightfield->setRoot(root); return newHeightfield; } diff --git a/libraries/metavoxels/src/Spanner.h b/libraries/metavoxels/src/Spanner.h index bbfcbff1ff..bec1355b48 100644 --- a/libraries/metavoxels/src/Spanner.h +++ b/libraries/metavoxels/src/Spanner.h @@ -642,8 +642,8 @@ public: virtual void readExtra(Bitstream& in); virtual void writeExtraDelta(Bitstream& out, const SharedObject* reference) const; virtual void readExtraDelta(Bitstream& in, const SharedObject* reference); - virtual void writeExtraSubdivision(Bitstream& out); - virtual SharedObject* readExtraSubdivision(Bitstream& in); + virtual void maybeWriteSubdivision(Bitstream& out); + virtual SharedObject* readSubdivision(Bitstream& in); signals: From 37ffa48fa3ef45e6f1840f8327ead23e45846c05 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 4 Dec 2014 16:43:12 -0800 Subject: [PATCH 226/502] more work on improved model picking --- .../entities/RenderableModelEntityItem.cpp | 385 +----------------- .../src/entities/RenderableModelEntityItem.h | 3 - interface/src/renderer/Model.cpp | 7 + 3 files changed, 18 insertions(+), 377 deletions(-) diff --git a/interface/src/entities/RenderableModelEntityItem.cpp b/interface/src/entities/RenderableModelEntityItem.cpp index 11d16c39f8..ccd6622856 100644 --- a/interface/src/entities/RenderableModelEntityItem.cpp +++ b/interface/src/entities/RenderableModelEntityItem.cpp @@ -263,383 +263,20 @@ EntityItemProperties RenderableModelEntityItem::getProperties() const { bool RenderableModelEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, void** intersectedObject) const { - - // extents is the entity relative, scaled, centered extents of the entity - 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 entityFrameOrigin = glm::vec3(worldToEntityMatrix * glm::vec4(origin, 1.0f)); - glm::vec3 entityFrameDirection = glm::vec3(worldToEntityMatrix * glm::vec4(direction, 0.0f)); - - float depth = depthOfRayIntersection(entityFrameOrigin, entityFrameDirection); - - return true; // we only got here if we intersected our non-aabox -} - - -/* -void RenderableModelEntityItem::renderEntityAsBillboard() { - TextureCache* textureCache = Application->getInstance()->getTextureCache(); - textureCache->getPrimaryFramebufferObject()->bind(); - - const int BILLBOARD_SIZE = 64; - renderRearViewMirror(QRect(0, _glWidget->getDeviceHeight() - BILLBOARD_SIZE, BILLBOARD_SIZE, BILLBOARD_SIZE), true); - - //QImage image(BILLBOARD_SIZE, BILLBOARD_SIZE, QImage::Format_ARGB32); - //glReadPixels(0, 0, BILLBOARD_SIZE, BILLBOARD_SIZE, GL_BGRA, GL_UNSIGNED_BYTE, image.bits()); - - textureCache->getPrimaryFramebufferObject()->release(); - - return image; -} -*/ - -float RenderableModelEntityItem::depthOfRayIntersection(const glm::vec3& entityFrameOrigin, const glm::vec3& entityFrameDirection) const { - qDebug() << "RenderableModelEntityItem::depthOfRayIntersection()...."; + qDebug() << "RenderableModelEntityItem::findDetailedRayIntersection()...."; + qDebug() << " origin:" << origin; + glm::vec3 originInMeters = origin * (float)TREE_SCALE; + qDebug() << " originInMeters:" << originInMeters; + QString extraInfo; + float localDistance; + bool intersectsModel = _model->findRayIntersectionAgainstSubMeshes(originInMeters, direction, localDistance, face, extraInfo); - Application::getInstance()->getTextureCache()->getPrimaryFramebufferObject()->bind(); - - glEnable(GL_SCISSOR_TEST); - glEnable(GL_LIGHTING); // enable? - glEnable(GL_DEPTH_TEST); - glDisable(GL_BLEND); // we don't need blending - - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - - // * we know the direction that the ray is coming into our bounding box. - // * we know the location on our bounding box that the ray intersected - // * because this API is theoretically called for things that aren't on the screen, - // or could be off in the distance, but with an original ray pick origin ALSO off - // in the distance, we don't really know the "pixel" size of the model at that - // place in space. In fact that concept really doesn't make sense at all... so - // we need to pick our own "scale" based on whatever level of precision makes - // sense... what makes sense? - // * we could say that we allow ray intersections down to some N meters (say 1cm - // or 0.01 meters) in real space. The model's bounds in meters are known. - // - // - float renderGranularity = 0.01f; // 1cm of render granularity - this could be ridiculous for large models - - qDebug() << " renderGranularity:" << renderGranularity; - - // note: these are in tree units, not meters - glm::vec3 dimensions = getDimensions(); - glm::vec3 registrationPoint = getRegistrationPoint(); - glm::vec3 corner = -(dimensions * registrationPoint); - - AABox entityFrameBox(corner, dimensions); - entityFrameBox.scale((float)TREE_SCALE); - - // rotationBetween(v1, v2) -- Helper function return the rotation from the first vector onto the second - //glm::quat viewRotation = rotationBetween(entityFrameDirection, IDENTITY_FRONT); - //glm::quat viewRotation = rotationBetween(IDENTITY_FRONT, entityFrameDirection); - glm::quat viewRotation = rotationBetween(glm::vec3(0.0f, 1.0f, 0.0f), IDENTITY_FRONT); - //glm::quat viewRotation = rotationBetween(IDENTITY_FRONT, IDENTITY_FRONT); - - // I'd like to calculate the tightest bounding box around the entity for - // the direction of the - glm::vec3 minima(FLT_MAX, FLT_MAX, FLT_MAX); - glm::vec3 maxima(-FLT_MAX, -FLT_MAX, -FLT_MAX); - const int VERTEX_COUNT = 8; - for (int j = 0; j < VERTEX_COUNT; j++) { - glm::vec3 vertex = entityFrameBox.getVertex((BoxVertex)j); - qDebug() << " vertex[" << j <<"]:" << vertex; - - glm::vec3 rotated = viewRotation * vertex; - qDebug() << " rotated[" << j <<"]:" << rotated; - - minima = glm::min(minima, rotated); - maxima = glm::max(maxima, rotated); + if (intersectsModel) { + distance = localDistance / (float)TREE_SCALE; } - qDebug() << " minima:" << minima; - qDebug() << " maxima:" << maxima; - - int width = glm::round((maxima.x - minima.x) / renderGranularity); - int height = glm::round((maxima.y - minima.y) / renderGranularity); - - qDebug() << " width:" << width; - qDebug() << " height:" << height; - - glViewport(0, 0, width, height); - glScissor(0, 0, width, height); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - glLoadIdentity(); - glOrtho(minima.x, maxima.x, minima.y, maxima.y, -maxima.z, -minima.z); - - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - glm::vec3 axis = glm::axis(viewRotation); - glRotatef(glm::degrees(glm::angle(viewRotation)), axis.x, axis.y, axis.z); - - glm::vec3 entityFrameOriginInMeters = entityFrameOrigin * (float)TREE_SCALE; - glm::vec3 entityFrameDirectionInMeters = entityFrameDirection * (float)TREE_SCALE; - //glTranslatef(entityFrameOriginInMerters.x, entityFrameOriginInMerters.y, entityFrameOriginInMerters.z); - - Application::getInstance()->setupWorldLight(); - Application::getInstance()->updateUntranslatedViewMatrix(); - - - bool renderAsModel = true; - - if (renderAsModel) { - const float alpha = 1.0f; - - glm::vec3 position = getPositionInMeters(); - glm::vec3 center = getCenterInMeters(); - dimensions = getDimensions() * (float)TREE_SCALE; - glm::quat rotation = getRotation(); - - const float MAX_COLOR = 255.0f; - glColor4f(1.0f, 0.0f, 0.0f, 1.0f); - - glPushMatrix(); - { - //glTranslatef(position.x, position.y, position.z); - //glm::vec3 axis = glm::axis(rotation); - //glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z); - - - glPushMatrix(); - glm::vec3 positionToCenter = center - position; - //glTranslatef(positionToCenter.x, positionToCenter.y, positionToCenter.z); - - //glScalef(dimensions.x, dimensions.y, dimensions.z); - //Application::getInstance()->getDeferredLightingEffect()->renderSolidSphere(0.5f, 15, 15); - - //_model->setRotation(rotation); - //_model->setScaleToFit(true, glm::vec3(1.0f,1.0f,1.0f)); - - //glm::vec3(0.0f,2.0f,0.0f) - _model->setSnapModelToRegistrationPoint(true, glm::vec3(0.5f,0.5f,0.5f)); - _model->setTranslation(glm::vec3(0.0f,0.0f,0.0f)); - _model->simulate(0.0f); - _model->render(alpha, Model::DEFAULT_RENDER_MODE); - - //_model->render(1.0f, Model::DEFAULT_RENDER_MODE); - - //_model->setScaleToFit(true, dimensions); - _model->setSnapModelToRegistrationPoint(true, getRegistrationPoint()); - _model->setTranslation(position); - _model->simulate(0.0f); - - glPushMatrix(); - glScalef(dimensions.x, dimensions.y, dimensions.z); - Application::getInstance()->getDeferredLightingEffect()->renderWireSphere(0.5f, 15, 15); - glPopMatrix(); - - /* - glBegin(GL_LINES); - - // low-z side - blue - glColor4f(0.0f, 0.0f, 1.0f, 1.0f); - glVertex3f(-0.5f, -0.5f, -0.5f); - glVertex3f(0.5f, -0.5f, -0.5f); - glVertex3f(-0.5f, 0.5f, -0.5f); - glVertex3f(0.5f, 0.5f, -0.5f); - glVertex3f(0.5f, 0.5f, -0.5f); - glVertex3f(0.5f, -0.5f, -0.5f); - glVertex3f(-0.5f, 0.5f, -0.5f); - glVertex3f(-0.5f, -0.5f, -0.5f); - - // high-z side - cyan - glColor4f(0.0f, 1.0f, 1.0f, 1.0f); - glVertex3f(-0.5f, -0.5f, 0.5f); - glVertex3f( 0.5f, -0.5f, 0.5f); - glVertex3f(-0.5f, 0.5f, 0.5f); - glVertex3f( 0.5f, 0.5f, 0.5f); - glVertex3f( 0.5f, 0.5f, 0.5f); - glVertex3f( 0.5f, -0.5f, 0.5f); - glVertex3f(-0.5f, 0.5f, 0.5f); - glVertex3f(-0.5f, -0.5f, 0.5f); - - // low-x side - yellow - glColor4f(1.0f, 1.0f, 0.0f, 1.0f); - glVertex3f(-0.5f, -0.5f, -0.5f); - glVertex3f(-0.5f, -0.5f, 0.5f); - - glVertex3f(-0.5f, -0.5f, 0.5f); - glVertex3f(-0.5f, 0.5f, 0.5f); - - glVertex3f(-0.5f, 0.5f, 0.5f); - glVertex3f(-0.5f, 0.5f, -0.5f); - - glVertex3f(-0.5f, 0.5f, -0.5f); - glVertex3f(-0.5f, -0.5f, -0.5f); - - // high-x side - red - glColor4f(1.0f, 0.0f, 0.0f, 1.0f); - glVertex3f(0.5f, -0.5f, -0.5f); - glVertex3f(0.5f, -0.5f, 0.5f); - glVertex3f(0.5f, -0.5f, 0.5f); - glVertex3f(0.5f, 0.5f, 0.5f); - glVertex3f(0.5f, 0.5f, 0.5f); - glVertex3f(0.5f, 0.5f, -0.5f); - glVertex3f(0.5f, 0.5f, -0.5f); - glVertex3f(0.5f, -0.5f, -0.5f); - - - // origin and direction - green - float distanceToHit; - BoxFace ignoreFace; - - entityFrameBox.findRayIntersection(entityFrameOriginInMeters, entityFrameDirectionInMeters, distanceToHit, ignoreFace); - glm::vec3 pointOfIntersection = entityFrameOriginInMeters + (entityFrameDirectionInMeters * distanceToHit); - -qDebug() << "distanceToHit: " << distanceToHit; -qDebug() << "pointOfIntersection: " << pointOfIntersection; - - glm::vec3 pointA = pointOfIntersection + (entityFrameDirectionInMeters * -1.0f); - glm::vec3 pointB = pointOfIntersection + (entityFrameDirectionInMeters * 1.0f); -qDebug() << "pointA: " << pointA; -qDebug() << "pointB: " << pointB; - - glColor4f(0.0f, 1.0f, 0.0f, 1.0f); - glVertex3f(pointA.x, pointA.y, pointA.z); - glVertex3f(pointB.x, pointB.y, pointB.z); - - glEnd(); - */ - - - glPopMatrix(); - } - glPopMatrix(); - - - } else { - glm::vec3 position = getPositionInMeters(); - glm::vec3 center = getCenterInMeters(); - dimensions = getDimensions() * (float)TREE_SCALE; - glm::quat rotation = getRotation(); - - glColor4f(1.0f, 0.0f, 1.0f, 1.0f); - glLineWidth(2.0f); - - glPushMatrix(); - { - //glTranslatef(position.x, position.y, position.z); - glm::vec3 axis = glm::axis(rotation); - glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z); - - - glPushMatrix(); - glm::vec3 positionToCenter = center - position; - glTranslatef(positionToCenter.x, positionToCenter.y, positionToCenter.z); - - glScalef(dimensions.x, dimensions.y, dimensions.z); - //Application::getInstance()->getDeferredLightingEffect()->renderWireCube(1.0f); - Application::getInstance()->getDeferredLightingEffect()->renderWireSphere(0.5f, 15, 15); - - glBegin(GL_LINES); - - // low-z side - blue - glColor4f(0.0f, 0.0f, 1.0f, 1.0f); - glVertex3f(-0.5f, -0.5f, -0.5f); - glVertex3f(0.5f, -0.5f, -0.5f); - glVertex3f(-0.5f, 0.5f, -0.5f); - glVertex3f(0.5f, 0.5f, -0.5f); - glVertex3f(0.5f, 0.5f, -0.5f); - glVertex3f(0.5f, -0.5f, -0.5f); - glVertex3f(-0.5f, 0.5f, -0.5f); - glVertex3f(-0.5f, -0.5f, -0.5f); - - // high-z side - cyan - glColor4f(0.0f, 1.0f, 1.0f, 1.0f); - glVertex3f(-0.5f, -0.5f, 0.5f); - glVertex3f( 0.5f, -0.5f, 0.5f); - glVertex3f(-0.5f, 0.5f, 0.5f); - glVertex3f( 0.5f, 0.5f, 0.5f); - glVertex3f( 0.5f, 0.5f, 0.5f); - glVertex3f( 0.5f, -0.5f, 0.5f); - glVertex3f(-0.5f, 0.5f, 0.5f); - glVertex3f(-0.5f, -0.5f, 0.5f); - - // low-x side - yellow - glColor4f(1.0f, 1.0f, 0.0f, 1.0f); - glVertex3f(-0.5f, -0.5f, -0.5f); - glVertex3f(-0.5f, -0.5f, 0.5f); - - glVertex3f(-0.5f, -0.5f, 0.5f); - glVertex3f(-0.5f, 0.5f, 0.5f); - - glVertex3f(-0.5f, 0.5f, 0.5f); - glVertex3f(-0.5f, 0.5f, -0.5f); - - glVertex3f(-0.5f, 0.5f, -0.5f); - glVertex3f(-0.5f, -0.5f, -0.5f); - - // high-x side - red - glColor4f(1.0f, 0.0f, 0.0f, 1.0f); - glVertex3f(0.5f, -0.5f, -0.5f); - glVertex3f(0.5f, -0.5f, 0.5f); - glVertex3f(0.5f, -0.5f, 0.5f); - glVertex3f(0.5f, 0.5f, 0.5f); - glVertex3f(0.5f, 0.5f, 0.5f); - glVertex3f(0.5f, 0.5f, -0.5f); - glVertex3f(0.5f, 0.5f, -0.5f); - glVertex3f(0.5f, -0.5f, -0.5f); - - - // origin and direction - green - float distanceToHit; - BoxFace ignoreFace; - - entityFrameBox.findRayIntersection(entityFrameOriginInMeters, entityFrameDirectionInMeters, distanceToHit, ignoreFace); - glm::vec3 pointOfIntersection = entityFrameOriginInMeters + (entityFrameDirectionInMeters * distanceToHit); - -qDebug() << "distanceToHit: " << distanceToHit; -qDebug() << "pointOfIntersection: " << pointOfIntersection; - - glm::vec3 pointA = pointOfIntersection + (entityFrameDirectionInMeters * -1.0f); - glm::vec3 pointB = pointOfIntersection + (entityFrameDirectionInMeters * 1.0f); -qDebug() << "pointA: " << pointA; -qDebug() << "pointB: " << pointB; - - glColor4f(0.0f, 1.0f, 0.0f, 1.0f); - glVertex3f(pointA.x, pointA.y, pointA.z); - glVertex3f(pointB.x, pointB.y, pointB.z); - - glEnd(); - - glPopMatrix(); - } - glPopMatrix(); - } - - QImage colorData(width, height, QImage::Format_ARGB32); - QVector depthData(width * height); - - glReadPixels(0, 0, width, height, GL_BGRA, GL_UNSIGNED_BYTE, colorData.bits()); - glReadPixels(0, 0, width, height, GL_DEPTH_COMPONENT, GL_FLOAT, depthData.data()); - - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); - - glEnable(GL_BLEND); - glDisable(GL_SCISSOR_TEST); - - Application::getInstance()->getTextureCache()->getPrimaryFramebufferObject()->release(); - - glViewport(0, 0, Application::getInstance()->getGLWidget()->width(), Application::getInstance()->getGLWidget()->height()); - - QImage imageData = colorData.mirrored(false,true); - - bool saved = imageData.save("/Users/zappoman/Development/foo.bmp"); - - qDebug() << " saved:" << saved; - - - return 0.0f; + return intersectsModel; // we only got here if we intersected our non-aabox } + diff --git a/interface/src/entities/RenderableModelEntityItem.h b/interface/src/entities/RenderableModelEntityItem.h index 09db54d64f..4c6bb5a046 100644 --- a/interface/src/entities/RenderableModelEntityItem.h +++ b/interface/src/entities/RenderableModelEntityItem.h @@ -71,9 +71,6 @@ private: QString _currentTextures; QStringList _originalTextures; bool _originalTexturesRead; - - float depthOfRayIntersection(const glm::vec3& entityFrameOrigin, const glm::vec3& entityFrameDirection) const; - }; #endif // hifi_RenderableModelEntityItem_h diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 74aa190a26..9941be566a 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -536,6 +536,8 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g return intersectedSomething; } + qDebug() << "Model::findRayIntersectionAgainstSubMeshes()..."; + // extents is the entity relative, scaled, centered extents of the entity glm::vec3 position = _translation; glm::mat4 rotation = glm::mat4_cast(_rotation); @@ -544,11 +546,14 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g glm::mat4 worldToModelMatrix = glm::inverse(modelToWorldMatrix); Extents modelExtents = getMeshExtents(); // NOTE: unrotated + qDebug() << " modelExtents:" << modelExtents; glm::vec3 dimensions = modelExtents.maximum - modelExtents.minimum; glm::vec3 corner = dimensions * -0.5f; // since we're going to do the ray picking in the model frame of reference AABox overlayFrameBox(corner, dimensions); + qDebug() << " overlayFrameBox:" << overlayFrameBox; + glm::vec3 modelFrameOrigin = glm::vec3(worldToModelMatrix * glm::vec4(origin, 1.0f)); glm::vec3 modelFrameDirection = glm::vec3(worldToModelMatrix * glm::vec4(direction, 0.0f)); @@ -560,11 +565,13 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g float distanceToSubMesh; BoxFace subMeshFace; int subMeshIndex = 0; + // If we hit the models box, then consider the submeshes... foreach(const AABox& subMeshBox, _calculatedMeshBoxes) { const FBXGeometry& geometry = _geometry->getFBXGeometry(); + qDebug() << "subMeshBox[" << subMeshIndex <<"]:" << subMeshBox; if (subMeshBox.findRayIntersection(origin, direction, distanceToSubMesh, subMeshFace)) { if (distanceToSubMesh < bestDistance) { bestDistance = distanceToSubMesh; From f13bf65554c3c8629f5d6cb45e5f72154a48c91b Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 4 Dec 2014 16:43:34 -0800 Subject: [PATCH 227/502] more work on improved model picking --- interface/resources/shaders/select.frag | 25 ------------------------ interface/resources/shaders/select.vert | 26 ------------------------- 2 files changed, 51 deletions(-) delete mode 100644 interface/resources/shaders/select.frag delete mode 100644 interface/resources/shaders/select.vert diff --git a/interface/resources/shaders/select.frag b/interface/resources/shaders/select.frag deleted file mode 100644 index a7c5067fbc..0000000000 --- a/interface/resources/shaders/select.frag +++ /dev/null @@ -1,25 +0,0 @@ -#version 120 - -// -// simple.frag -// fragment shader -// -// Created by Andrzej Kapolka on 9/15/14. -// 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 -// - -// the interpolated normal -varying vec4 normal; - -// the glow intensity -uniform float glowIntensity; - -void main(void) { - // set the diffuse, normal, specular data - gl_FragData[0] = vec4(1.0f, 1.0f, 0.0f, 0.0f); //vec4(gl_Color.rgb, glowIntensity); - gl_FragData[1] = vec4(1.0f, 1.0f, 0.0f, 0.0f); //normalize(normal) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0); - gl_FragData[2] = vec4(1.0f, 1.0f, 0.0f, 0.0f); //vec4(gl_FrontMaterial.specular.rgb, gl_FrontMaterial.shininess / 128.0); -} diff --git a/interface/resources/shaders/select.vert b/interface/resources/shaders/select.vert deleted file mode 100644 index 9f76597fd6..0000000000 --- a/interface/resources/shaders/select.vert +++ /dev/null @@ -1,26 +0,0 @@ -#version 120 - -// -// simple.vert -// vertex shader -// -// Created by Andrzej Kapolka on 9/15/14. -// 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 -// - -// the interpolated normal -varying vec4 normal; - -void main(void) { - // transform and store the normal for interpolation - normal = normalize(gl_ModelViewMatrix * vec4(gl_Normal, 0.0)); - - // pass along the diffuse color - gl_FrontColor = vec4(1.0f, 0.0f, 0.0f, 0.0f); //gl_Color; - - // use standard pipeline transform - gl_Position = ftransform(); -} From 6b5fdceb6e2c8dd656123d16dff49752d000e503 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 4 Dec 2014 16:48:04 -0800 Subject: [PATCH 228/502] more work on improved model picking --- .../src/entities/RenderableModelEntityItem.h | 3 --- interface/src/renderer/Model.cpp | 18 ------------------ interface/src/renderer/Model.h | 6 +----- 3 files changed, 1 insertion(+), 26 deletions(-) diff --git a/interface/src/entities/RenderableModelEntityItem.h b/interface/src/entities/RenderableModelEntityItem.h index 4c6bb5a046..9ed85beeaa 100644 --- a/interface/src/entities/RenderableModelEntityItem.h +++ b/interface/src/entities/RenderableModelEntityItem.h @@ -28,9 +28,6 @@ #include #include -#include -#include - class RenderableModelEntityItem : public ModelEntityItem { public: static EntityItem* factory(const EntityItemID& entityID, const EntityItemProperties& properties); diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 9941be566a..19176c4833 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -103,9 +103,6 @@ Model::SkinLocations Model::_skinNormalSpecularMapLocations; Model::SkinLocations Model::_skinShadowLocations; Model::SkinLocations Model::_skinTranslucentLocations; -ProgramObject Model::_selectProgram; -Model::Locations Model::_selectLocations; - void Model::setScale(const glm::vec3& scale) { setScaleInternal(scale); // if anyone sets scale manually, then we are no longer scaled to fit @@ -390,14 +387,6 @@ void Model::init() { _skinTranslucentProgram.link(); initSkinProgram(_skinTranslucentProgram, _skinTranslucentLocations); - - - // select/ray picking program - _selectProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/select.vert"); - _selectProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + "shaders/select.frag"); - _selectProgram.link(); - initProgram(_selectProgram, _selectLocations); - } } @@ -2166,13 +2155,6 @@ void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, f ProgramObject* activeProgram = program; Locations* activeLocations = locations; - // XXXBHG - hack to render yellow - if (mode == SELECT_RENDER_MODE) { - //activeProgram = &_selectProgram; - //activeLocations = &_selectLocations; - // need skin version - } - if (isSkinned) { activeProgram = skinProgram; activeLocations = skinLocations; diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 9fdec3f25b..b16cf11b09 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -86,7 +86,7 @@ public: void reset(); virtual void simulate(float deltaTime, bool fullUpdate = true); - enum RenderMode { DEFAULT_RENDER_MODE, SHADOW_RENDER_MODE, DIFFUSE_RENDER_MODE, NORMAL_RENDER_MODE, SELECT_RENDER_MODE }; + enum RenderMode { DEFAULT_RENDER_MODE, SHADOW_RENDER_MODE, DIFFUSE_RENDER_MODE, NORMAL_RENDER_MODE }; bool render(float alpha = 1.0f, RenderMode mode = DEFAULT_RENDER_MODE, RenderArgs* args = NULL); @@ -319,8 +319,6 @@ private: static ProgramObject _skinShadowProgram; - static ProgramObject _selectProgram; - static int _normalMapTangentLocation; static int _normalSpecularMapTangentLocation; @@ -345,8 +343,6 @@ private: static Locations _lightmapSpecularMapLocations; static Locations _lightmapNormalSpecularMapLocations; - static Locations _selectLocations; - static void initProgram(ProgramObject& program, Locations& locations, int specularTextureUnit = 1); class SkinLocations : public Locations { From 466d99bcbb89f20d8e4c683eeb5a5defd4101348 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 4 Dec 2014 17:12:06 -0800 Subject: [PATCH 229/502] Removed unused members. --- interface/src/gpu/GLBackend.cpp | 1 - libraries/fbx/src/FBXReader.cpp | 1 - libraries/metavoxels/src/Spanner.cpp | 1 - 3 files changed, 3 deletions(-) diff --git a/interface/src/gpu/GLBackend.cpp b/interface/src/gpu/GLBackend.cpp index 1f8e7bf99f..10567e65ba 100644 --- a/interface/src/gpu/GLBackend.cpp +++ b/interface/src/gpu/GLBackend.cpp @@ -445,7 +445,6 @@ void GLBackend::updateTransform() { _transform._lastMode = GL_PROJECTION; } CHECK_GL_ERROR();*/ - _transform._invalidProj; } if (_transform._invalidModel || _transform._invalidView) { diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 5f215ac4d0..289051eafb 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -1477,7 +1477,6 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, } else if (object.name == "Texture") { TextureParam tex; - bool texparam = false; foreach (const FBXNode& subobject, object.children) { if (subobject.name == "RelativeFilename") { // trim off any path information diff --git a/libraries/metavoxels/src/Spanner.cpp b/libraries/metavoxels/src/Spanner.cpp index 1dc55a7904..216d4d7d1d 100644 --- a/libraries/metavoxels/src/Spanner.cpp +++ b/libraries/metavoxels/src/Spanner.cpp @@ -1127,7 +1127,6 @@ bool HeightfieldStreamState::becameSubdividedOrCollapsed() const { const int X_MAXIMUM_FLAG = 1; const int Y_MAXIMUM_FLAG = 2; -const int MAXIMUM_FLAG_MASK = X_MAXIMUM_FLAG | Y_MAXIMUM_FLAG; static glm::vec2 getNextMinimum(const glm::vec2& minimum, float nextSize, int index) { return minimum + glm::vec2( From da1bb83eb0b34c8ea9c7b50c105c0dad4436f43f Mon Sep 17 00:00:00 2001 From: dev Date: Thu, 4 Dec 2014 17:14:41 -0800 Subject: [PATCH 230/502] compiling the gpu library on mac --- libraries/gpu/CMakeLists.txt | 8 +------- libraries/gpu/src/gpu/GPUConfig.h | 3 ++- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/libraries/gpu/CMakeLists.txt b/libraries/gpu/CMakeLists.txt index 712e4320b5..577f9f7a58 100644 --- a/libraries/gpu/CMakeLists.txt +++ b/libraries/gpu/CMakeLists.txt @@ -8,16 +8,10 @@ include_glm() link_hifi_libraries(shared) if (APPLE) # link in required OS X frameworks and include the right GL headers - find_library(CoreFoundation CoreFoundation) find_library(OpenGL OpenGL) - target_link_libraries(${TARGET_NAME} ${CoreFoundation} ${OpenGL}) + target_link_libraries(${TARGET_NAME} ${OpenGL}) - # install command for OS X bundle - INSTALL(TARGETS ${TARGET_NAME} - BUNDLE DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/install" COMPONENT Runtime - RUNTIME DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/install" COMPONENT Runtime - ) else (APPLE) find_package(OpenGL REQUIRED) diff --git a/libraries/gpu/src/gpu/GPUConfig.h b/libraries/gpu/src/gpu/GPUConfig.h index 024cf73112..0d0a140e62 100644 --- a/libraries/gpu/src/gpu/GPUConfig.h +++ b/libraries/gpu/src/gpu/GPUConfig.h @@ -14,7 +14,8 @@ #define GL_GLEXT_PROTOTYPES 1 -#if defined(APPLE) +#ifdef __APPLE__ +#include #include #elif defined(UNIX) From 16da10bf19f401ed86f3c172275a27f53eb9e3a8 Mon Sep 17 00:00:00 2001 From: dev Date: Thu, 4 Dec 2014 17:15:59 -0800 Subject: [PATCH 231/502] compiling the gpu library on mac --- libraries/gpu/src/gpu/GPUConfig.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/gpu/src/gpu/GPUConfig.h b/libraries/gpu/src/gpu/GPUConfig.h index 0d0a140e62..faecfd4889 100644 --- a/libraries/gpu/src/gpu/GPUConfig.h +++ b/libraries/gpu/src/gpu/GPUConfig.h @@ -14,7 +14,7 @@ #define GL_GLEXT_PROTOTYPES 1 -#ifdef __APPLE__ +#if defined(__APPLE__) #include #include From 7026af7b9ab68789f83851b513a8d23b4d75c13f Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 4 Dec 2014 17:26:14 -0800 Subject: [PATCH 232/502] Centrilized Oculus interference in pickRay --- interface/src/Application.cpp | 11 +- interface/src/Camera.cpp | 17 +-- interface/src/entities/EntityTreeRenderer.cpp | 13 +- .../scripting/JoystickScriptingInterface.cpp | 2 +- interface/src/ui/ApplicationOverlay.cpp | 132 ++++++++++-------- interface/src/ui/ApplicationOverlay.h | 11 +- interface/src/ui/NodeBounds.cpp | 11 +- 7 files changed, 102 insertions(+), 95 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 9ab87fdc30..06965df947 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1131,7 +1131,7 @@ void Application::keyPressEvent(QKeyEvent* event) { if (!event->isAutoRepeat()) { // this starts an HFActionEvent HFActionEvent startActionEvent(HFActionEvent::startType(), - _viewFrustum.computePickRay(0.5f, 0.5f)); + _myCamera.computeViewPickRay(0.5f, 0.5f)); sendEvent(this, &startActionEvent); } @@ -1222,7 +1222,7 @@ void Application::keyReleaseEvent(QKeyEvent* event) { case Qt::Key_Space: { if (!event->isAutoRepeat()) { // this ends the HFActionEvent - HFActionEvent endActionEvent(HFActionEvent::endType(), _viewFrustum.computePickRay(0.5f, 0.5f)); + HFActionEvent endActionEvent(HFActionEvent::endType(), _myCamera.computeViewPickRay(0.5f, 0.5f)); sendEvent(this, &endActionEvent); } @@ -1253,7 +1253,6 @@ void Application::focusOutEvent(QFocusEvent* event) { } void Application::mouseMoveEvent(QMouseEvent* event, unsigned int deviceID) { - bool showMouse = true; // Used by application overlay to determine how to draw cursor(s) @@ -2079,8 +2078,10 @@ void Application::updateMouseRay() { x = _mouseX / (float)_glWidget->width(); y = _mouseY / (float)_glWidget->height(); } - _viewFrustum.computePickRay(x, y, _mouseRayOrigin, _mouseRayDirection); - + PickRay pickRay = _myCamera.computeViewPickRay(x, y); + _mouseRayOrigin = pickRay.origin; + _mouseRayDirection = pickRay.direction; + // adjust for mirroring if (_myCamera.getMode() == CAMERA_MODE_MIRROR) { glm::vec3 mouseRayOffset = _mouseRayOrigin - _viewFrustum.getPosition(); diff --git a/interface/src/Camera.cpp b/interface/src/Camera.cpp index 6e5a83790e..d069afb96a 100644 --- a/interface/src/Camera.cpp +++ b/interface/src/Camera.cpp @@ -97,20 +97,17 @@ void Camera::setFarClip(float f) { PickRay Camera::computePickRay(float x, float y) { float screenWidth = Application::getInstance()->getGLWidget()->width(); float screenHeight = Application::getInstance()->getGLWidget()->height(); - PickRay result; - if (OculusManager::isConnected()) { - result.origin = getPosition(); - Application::getInstance()->getApplicationOverlay().computeOculusPickRay(x / screenWidth, y / screenHeight, result.direction); - } else { - Application::getInstance()->getViewFrustum()->computePickRay(x / screenWidth, y / screenHeight, - result.origin, result.direction); - } - return result; + + return computeViewPickRay(x / screenWidth, y / screenHeight); } PickRay Camera::computeViewPickRay(float xRatio, float yRatio) { PickRay result; - Application::getInstance()->getViewFrustum()->computePickRay(xRatio, yRatio, result.origin, result.direction); + if (OculusManager::isConnected()) { + Application::getInstance()->getApplicationOverlay().computeOculusPickRay(xRatio, yRatio, result.origin, result.direction); + } else { + Application::getInstance()->getViewFrustum()->computePickRay(xRatio, yRatio, result.origin, result.direction); + } return result; } diff --git a/interface/src/entities/EntityTreeRenderer.cpp b/interface/src/entities/EntityTreeRenderer.cpp index 5aacd36a12..67f19159cd 100644 --- a/interface/src/entities/EntityTreeRenderer.cpp +++ b/interface/src/entities/EntityTreeRenderer.cpp @@ -635,18 +635,7 @@ void EntityTreeRenderer::deleteReleasedModels() { } PickRay EntityTreeRenderer::computePickRay(float x, float y) { - float screenWidth = Application::getInstance()->getGLWidget()->width(); - float screenHeight = Application::getInstance()->getGLWidget()->height(); - PickRay result; - if (OculusManager::isConnected()) { - Camera* camera = Application::getInstance()->getCamera(); - result.origin = camera->getPosition(); - Application::getInstance()->getApplicationOverlay().computeOculusPickRay(x / screenWidth, y / screenHeight, result.direction); - } else { - ViewFrustum* viewFrustum = Application::getInstance()->getViewFrustum(); - viewFrustum->computePickRay(x / screenWidth, y / screenHeight, result.origin, result.direction); - } - return result; + return Application::getInstance()->getCamera()->computePickRay(x, y); } diff --git a/interface/src/scripting/JoystickScriptingInterface.cpp b/interface/src/scripting/JoystickScriptingInterface.cpp index 40109703d6..039dc40961 100644 --- a/interface/src/scripting/JoystickScriptingInterface.cpp +++ b/interface/src/scripting/JoystickScriptingInterface.cpp @@ -133,7 +133,7 @@ void JoystickScriptingInterface::update() { // global action events fire in the center of the screen HFActionEvent actionEvent(actionType, - Application::getInstance()->getViewFrustum()->computePickRay(0.5f, 0.5f)); + Application::getInstance()->getCamera()->computeViewPickRay(0.5f, 0.5f)); qApp->sendEvent(qApp, &actionEvent); } diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 5a644718c7..36babb64e0 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -30,18 +30,19 @@ const quint64 MSECS_TO_USECS = 1000ULL; const float WHITE_TEXT[] = { 0.93f, 0.93f, 0.93f }; const float RETICLE_COLOR[] = { 0.0f, 198.0f / 255.0f, 244.0f / 255.0f }; -static const float MOUSE_PITCH_RANGE = 1.0f * PI; -static const float MOUSE_YAW_RANGE = 0.5f * TWO_PI; const float CONNECTION_STATUS_BORDER_COLOR[] = { 1.0f, 0.0f, 0.0f }; const float CONNECTION_STATUS_BORDER_LINE_WIDTH = 4.0f; +static const float MOUSE_PITCH_RANGE = 1.0f * PI; +static const float MOUSE_YAW_RANGE = 0.5f * TWO_PI; -// Return a point's coordinates on a sphere from it's polar (theta) and azimutal (phi) angles. -glm::vec3 getPoint(float radius, float theta, float phi) { - return glm::vec3(radius * glm::sin(theta) * glm::sin(phi), - radius * glm::cos(theta), - radius * glm::sin(theta) * (-glm::cos(phi))); + +// Return a point's coordinates on a sphere from pitch and yaw +glm::vec3 getPoint(float yaw, float pitch) { + return glm::vec3(glm::cos(-pitch) * (-glm::sin(yaw)), + glm::sin(-pitch), + glm::cos(-pitch) * (-glm::cos(yaw))); } //Checks if the given ray intersects the sphere at the origin. result will store a multiplier that should @@ -104,10 +105,10 @@ bool raySphereIntersect(const glm::vec3 &dir, const glm::vec3 &origin, float r, void renderReticule(glm::quat orientation, float alpha) { const float reticleSize = TWO_PI / 80.0f; - glm::vec3 topLeft = getPoint(1.0f, PI_OVER_TWO + reticleSize / 2.0f, - reticleSize / 2.0f); - glm::vec3 topRight = getPoint(1.0f, PI_OVER_TWO + reticleSize / 2.0f, + reticleSize / 2.0f); - glm::vec3 bottomLeft = getPoint(1.0f, PI_OVER_TWO - reticleSize / 2.0f, - reticleSize / 2.0f); - glm::vec3 bottomRight = getPoint(1.0f, PI_OVER_TWO - reticleSize / 2.0f, + reticleSize / 2.0f); + glm::vec3 topLeft = getPoint(reticleSize / 2.0f, -reticleSize / 2.0f); + glm::vec3 topRight = getPoint(-reticleSize / 2.0f, -reticleSize / 2.0f); + glm::vec3 bottomLeft = getPoint(reticleSize / 2.0f, reticleSize / 2.0f); + glm::vec3 bottomRight = getPoint(-reticleSize / 2.0f, reticleSize / 2.0f); glPushMatrix(); { glm::vec3 axis = glm::axis(orientation); @@ -284,11 +285,9 @@ void ApplicationOverlay::displayOverlayTextureOculus(Camera& whichCamera) { if (_magSizeMult[i] > 0.0f) { //Render magnifier, but dont show border for mouse magnifier - float pitch = -(_reticulePosition[MOUSE].y / widgetHeight - 0.5f) * MOUSE_PITCH_RANGE; - float yaw = -(_reticulePosition[MOUSE].x / widgetWidth - 0.5f) * MOUSE_YAW_RANGE; - float projection = + glm::vec2 projection = screenToOverlay(_reticulePosition[i]); - renderMagnifier(_reticulePosition[i], _magSizeMult[i], i != MOUSE); + renderMagnifier(projection, _magSizeMult[i], i != MOUSE); } } @@ -296,7 +295,6 @@ void ApplicationOverlay::displayOverlayTextureOculus(Camera& whichCamera) { glDisable(GL_ALPHA_TEST); glColor4f(1.0f, 1.0f, 1.0f, _alpha); - static float textureFOV = 0.0f, textureAspectRatio = 1.0f; if (textureFOV != _textureFov || @@ -417,11 +415,7 @@ void ApplicationOverlay::displayOverlayTexture3DTV(Camera& whichCamera, float as glColor4f(1.0f, 1.0f, 1.0f, 1.0f); } - - - - -void ApplicationOverlay::computeOculusPickRay(float x, float y, glm::vec3& direction) const { +void ApplicationOverlay::computeOculusPickRay(float x, float y, glm::vec3& origin, glm::vec3& direction) const { const float pitch = (0.5f - y) * MOUSE_PITCH_RANGE; const float yaw = (0.5f - x) * MOUSE_YAW_RANGE; const glm::quat orientation(glm::vec3(pitch, yaw, 0.0f)); @@ -429,6 +423,7 @@ void ApplicationOverlay::computeOculusPickRay(float x, float y, glm::vec3& direc //Rotate the UI pick ray by the avatar orientation const MyAvatar* myAvatar = Application::getInstance()->getAvatar(); + origin = myAvatar->getDefaultEyePosition(); direction = myAvatar->getOrientation() * localDirection; } @@ -497,7 +492,7 @@ bool ApplicationOverlay::calculateRayUICollisionPoint(const glm::vec3& position, glm::quat orientation = myAvatar->getOrientation(); - glm::vec3 relativePosition = orientation * (position - myAvatar->getHead()->getEyePosition()); + glm::vec3 relativePosition = orientation * (position - myAvatar->getDefaultEyePosition()); glm::vec3 relativeDirection = orientation * direction; float t; @@ -655,10 +650,6 @@ void ApplicationOverlay::renderControllerPointers() { } void ApplicationOverlay::renderPointersOculus(const glm::vec3& eyePos) { - GLCanvas* glWidget = Application::getInstance()->getGLWidget(); - const int widgetWidth = glWidget->width(); - const int widgetHeight = glWidget->height(); - glBindTexture(GL_TEXTURE_2D, _crosshairTexture); glDisable(GL_DEPTH_TEST); glMatrixMode(GL_MODELVIEW); @@ -735,10 +726,8 @@ void ApplicationOverlay::renderPointersOculus(const glm::vec3& eyePos) { //Mouse Pointer if (_reticleActive[MOUSE]) { - float pitch = -(_reticulePosition[MOUSE].y / widgetHeight - 0.5f) * MOUSE_PITCH_RANGE; - float yaw = -(_reticulePosition[MOUSE].x / widgetWidth - 0.5f) * MOUSE_YAW_RANGE; - glm::quat orientation(glm::vec3(pitch, yaw, 0.0f)); - + glm::vec2 projection = screenToSpherical(_reticulePosition[MOUSE]); + glm::quat orientation(glm::vec3(-projection.y, projection.x, 0.0f)); renderReticule(orientation, _alpha); } @@ -753,37 +742,26 @@ void ApplicationOverlay::renderMagnifier(glm::vec2 magPos, float sizeMult, bool const int widgetWidth = glWidget->width(); const int widgetHeight = glWidget->height(); - if (magPos.x < 0 || magPos.x > widgetWidth || magPos.y < 0 || magPos.y > widgetHeight) { - return; - } - const float halfWidth = (MAGNIFY_WIDTH / _textureAspectRatio) * sizeMult / 2.0f; const float halfHeight = MAGNIFY_HEIGHT * sizeMult / 2.0f; // Magnification Texture Coordinates - float magnifyULeft = (magPos.x - halfWidth) / (float)widgetWidth; - float magnifyURight = (magPos.x + halfWidth) / (float)widgetWidth; - float magnifyVBottom = 1.0f - (magPos.y - halfHeight) / (float)widgetHeight; - float magnifyVTop = 1.0f - (magPos.y + halfHeight) / (float)widgetHeight; + const float magnifyULeft = (magPos.x - halfWidth) / (float)widgetWidth; + const float magnifyURight = (magPos.x + halfWidth) / (float)widgetWidth; + const float magnifyVTop = 1.0f - (magPos.y - halfHeight) / (float)widgetHeight; + const float magnifyVBottom = 1.0f - (magPos.y + halfHeight) / (float)widgetHeight; const float newHalfWidth = halfWidth * MAGNIFY_MULT; const float newHalfHeight = halfHeight * MAGNIFY_MULT; - //Get new UV coordinates from our magnification window - float newULeft = (magPos.x - newHalfWidth) / (float)widgetWidth; - float newURight = (magPos.x + newHalfWidth) / (float)widgetWidth; - float newVBottom = 1.0f - (magPos.y - newHalfHeight) / (float)widgetHeight; - float newVTop = 1.0f - (magPos.y + newHalfHeight) / (float)widgetHeight; + //Get yaw / pitch value for the corners + const glm::vec2 topLeftYawPitch = overlayToSpherical(glm::vec2(magPos.x - newHalfWidth, + magPos.y - newHalfHeight)); + const glm::vec2 bottomRightYawPitch = overlayToSpherical(glm::vec2(magPos.x + newHalfWidth, + magPos.y + newHalfHeight)); - // Find spherical coordinates from newUV, fov and aspect ratio - float radius = _oculusUIRadius * application->getAvatar()->getScale(); - const float leftPhi = (newULeft - 0.5f) * _textureFov * _textureAspectRatio; - const float rightPhi = (newURight - 0.5f) * _textureFov * _textureAspectRatio; - const float bottomTheta = PI_OVER_TWO - (newVBottom - 0.5f) * _textureFov; - const float topTheta = PI_OVER_TWO - (newVTop - 0.5f) * _textureFov; - - glm::vec3 bottomLeft = getPoint(radius, bottomTheta, leftPhi); - glm::vec3 bottomRight = getPoint(radius, bottomTheta, rightPhi); - glm::vec3 topLeft = getPoint(radius, topTheta, leftPhi); - glm::vec3 topRight = getPoint(radius, topTheta, rightPhi); + const glm::vec3 bottomLeft = getPoint(topLeftYawPitch.x, bottomRightYawPitch.y); + const glm::vec3 bottomRight = getPoint(bottomRightYawPitch.x, bottomRightYawPitch.y); + const glm::vec3 topLeft = getPoint(topLeftYawPitch.x, topLeftYawPitch.y); + const glm::vec3 topRight = getPoint(bottomRightYawPitch.x, topLeftYawPitch.y); glPushMatrix(); { if (showBorder) { @@ -1065,14 +1043,14 @@ void ApplicationOverlay::TexturedHemisphere::buildVBO(const float fov, for (int i = 0; i < stacks; i++) { float stacksRatio = (float)i / (float)(stacks - 1); // First stack is 0.0f, last stack is 1.0f // abs(theta) <= fov / 2.0f - float theta = PI_OVER_TWO - fov * (stacksRatio - 0.5f); + float pitch = -fov * (stacksRatio - 0.5f); for (int j = 0; j < slices; j++) { float slicesRatio = (float)j / (float)(slices - 1); // First slice is 0.0f, last slice is 1.0f // abs(phi) <= fov * aspectRatio / 2.0f - float phi = fov * aspectRatio * (slicesRatio - 0.5f); + float yaw = -fov * aspectRatio * (slicesRatio - 0.5f); - vertexPtr->position = getPoint(1.0f, theta, phi); + vertexPtr->position = getPoint(yaw, pitch); vertexPtr->uv.x = slicesRatio; vertexPtr->uv.y = stacksRatio; vertexPtr++; @@ -1180,3 +1158,43 @@ void ApplicationOverlay::TexturedHemisphere::render() { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); } + +glm::vec2 ApplicationOverlay::screenToSpherical(glm::vec2 screenPos) const { + QSize screenSize = Application::getInstance()->getGLWidget()->getDeviceSize(); + float yaw = -(screenPos.x / screenSize.width() - 0.5f) * MOUSE_YAW_RANGE; + float pitch = (screenPos.y / screenSize.height() - 0.5f) * MOUSE_PITCH_RANGE; + + return glm::vec2(yaw, pitch); +} + +glm::vec2 ApplicationOverlay::sphericalToScreen(glm::vec2 sphericalPos) const { + QSize screenSize = Application::getInstance()->getGLWidget()->getDeviceSize(); + float x = (-sphericalPos.x / MOUSE_YAW_RANGE + 0.5f) * screenSize.width(); + float y = (sphericalPos.y / MOUSE_PITCH_RANGE + 0.5f) * screenSize.height(); + + return glm::vec2(x, y); +} + +glm::vec2 ApplicationOverlay::sphericalToOverlay(glm::vec2 sphericalPos) const { + QSize screenSize = Application::getInstance()->getGLWidget()->getDeviceSize(); + float x = (-sphericalPos.x / (_textureFov * _textureAspectRatio) + 0.5f) * screenSize.width(); + float y = (sphericalPos.y / _textureFov + 0.5f) * screenSize.height(); + + return glm::vec2(x, y); +} + +glm::vec2 ApplicationOverlay::overlayToSpherical(glm::vec2 overlayPos) const { + QSize screenSize = Application::getInstance()->getGLWidget()->getDeviceSize(); + float yaw = -(overlayPos.x / screenSize.width() - 0.5f) * _textureFov * _textureAspectRatio; + float pitch = (overlayPos.y / screenSize.height() - 0.5f) * _textureFov; + + return glm::vec2(yaw, pitch); +} + +glm::vec2 ApplicationOverlay::screenToOverlay(glm::vec2 screenPos) const { + return sphericalToOverlay(screenToSpherical(screenPos)); +} + +glm::vec2 ApplicationOverlay::overlayToScreen(glm::vec2 overlayPos) const { + return sphericalToScreen(overlayToSpherical(overlayPos)); +} diff --git a/interface/src/ui/ApplicationOverlay.h b/interface/src/ui/ApplicationOverlay.h index 7c423b3a06..399cd504b8 100644 --- a/interface/src/ui/ApplicationOverlay.h +++ b/interface/src/ui/ApplicationOverlay.h @@ -30,10 +30,17 @@ public: void displayOverlayTextureOculus(Camera& whichCamera); void displayOverlayTexture3DTV(Camera& whichCamera, float aspectRatio, float fov); - void computeOculusPickRay(float x, float y, glm::vec3& direction) const; + void computeOculusPickRay(float x, float y, glm::vec3& origin, glm::vec3& direction) const; QPoint getPalmClickLocation(const PalmData *palm) const; bool calculateRayUICollisionPoint(const glm::vec3& position, const glm::vec3& direction, glm::vec3& result) const; - + + glm::vec2 screenToSpherical(glm::vec2 screenPos) const; + glm::vec2 sphericalToScreen(glm::vec2 sphericalPos) const; + glm::vec2 sphericalToOverlay(glm::vec2 sphericalPos) const; + glm::vec2 overlayToSpherical(glm::vec2 overlayPos) const; + glm::vec2 screenToOverlay(glm::vec2 screenPos) const; + glm::vec2 overlayToScreen(glm::vec2 overlayPos) const; + private: // Interleaved vertex data struct TextureVertex { diff --git a/interface/src/ui/NodeBounds.cpp b/interface/src/ui/NodeBounds.cpp index 49509cc9cf..631129321c 100644 --- a/interface/src/ui/NodeBounds.cpp +++ b/interface/src/ui/NodeBounds.cpp @@ -38,12 +38,7 @@ void NodeBounds::draw() { // Compute ray to find selected nodes later on. We can't use the pre-computed ray in Application because it centers // itself after the cursor disappears. Application* application = Application::getInstance(); - GLCanvas* glWidget = application->getGLWidget(); - float mouseX = application->getMouseX() / (float)glWidget->width(); - float mouseY = application->getMouseY() / (float)glWidget->height(); - glm::vec3 mouseRayOrigin; - glm::vec3 mouseRayDirection; - application->getViewFrustum()->computePickRay(mouseX, mouseY, mouseRayOrigin, mouseRayDirection); + PickRay pickRay = application->getCamera()->computeViewPickRay(application->getMouseX(), application->getMouseY()); // Variables to keep track of the selected node and properties to draw the cube later if needed Node* selectedNode = NULL; @@ -106,8 +101,8 @@ void NodeBounds::draw() { float distance; BoxFace face; - bool inside = serverBounds.contains(mouseRayOrigin); - bool colliding = serverBounds.findRayIntersection(mouseRayOrigin, mouseRayDirection, distance, face); + bool inside = serverBounds.contains(pickRay.origin); + bool colliding = serverBounds.findRayIntersection(pickRay.origin, pickRay.direction, distance, face); // If the camera is inside a node it will be "selected" if you don't have your cursor over another node // that you aren't inside. From 84da070901e65c0a3cb1a709e1813a061da47817 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 4 Dec 2014 18:27:03 -0800 Subject: [PATCH 233/502] Correct mouse position in occulus --- interface/src/Application.cpp | 86 +++++++++++++++++++------ interface/src/Application.h | 11 +++- interface/src/ui/ApplicationOverlay.cpp | 2 +- interface/src/ui/NodeBounds.cpp | 6 +- 4 files changed, 78 insertions(+), 27 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index fe6e81bd79..ca3fcfdd1b 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1305,18 +1305,20 @@ void Application::mousePressEvent(QMouseEvent* event, unsigned int deviceID) { if (event->button() == Qt::LeftButton) { _mouseX = event->x(); _mouseY = event->y(); - _mouseDragStartedX = _mouseX; - _mouseDragStartedY = _mouseY; + _mouseDragStartedX = getTrueMouseX(); + _mouseDragStartedY = getTrueMouseY(); _mousePressed = true; - - if (_audio.mousePressEvent(_mouseX, _mouseY)) { - // stop propagation - return; - } - - if (_rearMirrorTools->mousePressEvent(_mouseX, _mouseY)) { - // stop propagation - return; + + if (mouseOnScreen()) { + if (_audio.mousePressEvent(getMouseX(), getMouseY())) { + // stop propagation + return; + } + + if (_rearMirrorTools->mousePressEvent(getMouseX(), getMouseY())) { + // stop propagation + return; + } } // nobody handled this - make it an action event on the _window object @@ -1349,11 +1351,12 @@ void Application::mouseReleaseEvent(QMouseEvent* event, unsigned int deviceID) { _mouseY = event->y(); _mousePressed = false; - checkBandwidthMeterClick(); - if (Menu::getInstance()->isOptionChecked(MenuOption::Stats)) { + if (Menu::getInstance()->isOptionChecked(MenuOption::Stats) && mouseOnScreen()) { // let's set horizontal offset to give stats some margin to mirror int horizontalOffset = MIRROR_VIEW_WIDTH; - Stats::getInstance()->checkClick(_mouseX, _mouseY, _mouseDragStartedX, _mouseDragStartedY, horizontalOffset); + Stats::getInstance()->checkClick(getMouseX(), getMouseY(), + getMouseDragStartedX(), getMouseDragStartedY(), horizontalOffset); + checkBandwidthMeterClick(); } // fire an action end event @@ -1546,13 +1549,13 @@ void Application::idle() { void Application::checkBandwidthMeterClick() { // ... to be called upon button release - if (Menu::getInstance()->isOptionChecked(MenuOption::Bandwidth) && Menu::getInstance()->isOptionChecked(MenuOption::Stats) && Menu::getInstance()->isOptionChecked(MenuOption::UserInterface) && - glm::compMax(glm::abs(glm::ivec2(_mouseX - _mouseDragStartedX, _mouseY - _mouseDragStartedY))) - <= BANDWIDTH_METER_CLICK_MAX_DRAG_LENGTH - && _bandwidthMeter.isWithinArea(_mouseX, _mouseY, _glWidget->width(), _glWidget->height())) { + glm::compMax(glm::abs(glm::ivec2(getMouseX() - getMouseDragStartedX(), + getMouseY() - getMouseDragStartedY()))) + <= BANDWIDTH_METER_CLICK_MAX_DRAG_LENGTH + && _bandwidthMeter.isWithinArea(getMouseX(), getMouseY(), _glWidget->width(), _glWidget->height())) { // The bandwidth meter is visible, the click didn't get dragged too far and // we actually hit the bandwidth meter @@ -1666,6 +1669,48 @@ glm::vec3 Application::getMouseVoxelWorldCoordinates(const VoxelDetail& mouseVox (mouseVoxel.z + mouseVoxel.s / 2.0f) * TREE_SCALE); } +bool Application::mouseOnScreen() const { + if (OculusManager::isConnected()) { + return getMouseX() >= 0 && getMouseX() <= _glWidget->getDeviceWidth() && + getMouseY() >= 0 && getMouseY() <= _glWidget->getDeviceHeight(); + } + return true; +} + +int Application::getMouseX() const { + if (OculusManager::isConnected()) { + glm::vec2 pos = _applicationOverlay.screenToOverlay(glm::vec2(getTrueMouseX(), getTrueMouseY())); + return pos.x; + } + return getTrueMouseX(); +} + +int Application::getMouseY() const { + if (OculusManager::isConnected()) { + glm::vec2 pos = _applicationOverlay.screenToOverlay(glm::vec2(getTrueMouseX(), getTrueMouseY())); + return pos.y; + } + return getTrueMouseY(); +} + +int Application::getMouseDragStartedX() const { + if (OculusManager::isConnected()) { + glm::vec2 pos = _applicationOverlay.screenToOverlay(glm::vec2(getTrueMouseDragStartedX(), + getTrueMouseDragStartedY())); + return pos.x; + } + return getTrueMouseDragStartedX(); +} + +int Application::getMouseDragStartedY() const { + if (OculusManager::isConnected()) { + glm::vec2 pos = _applicationOverlay.screenToOverlay(glm::vec2(getTrueMouseDragStartedX(), + getTrueMouseDragStartedY())); + return pos.y; + } + return getTrueMouseDragStartedY(); +} + FaceTracker* Application::getActiveFaceTracker() { return (_dde.isActive() ? static_cast(&_dde) : (_faceshift.isActive() ? static_cast(&_faceshift) : @@ -1898,7 +1943,6 @@ void Application::init() { _mouseX = _glWidget->width() / 2; _mouseY = _glWidget->height() / 2; - QCursor::setPos(_mouseX, _mouseY); // TODO: move _myAvatar out of Application. Move relevant code to MyAvataar or AvatarManager _avatarManager.init(); @@ -2076,8 +2120,8 @@ void Application::updateMouseRay() { // if the mouse pointer isn't visible, act like it's at the center of the screen float x = 0.5f, y = 0.5f; if (!_mouseHidden) { - x = _mouseX / (float)_glWidget->width(); - y = _mouseY / (float)_glWidget->height(); + x = getTrueMouseX() / (float)_glWidget->width(); + y = getTrueMouseY() / (float)_glWidget->height(); } PickRay pickRay = _myCamera.computeViewPickRay(x, y); _mouseRayOrigin = pickRay.origin; diff --git a/interface/src/Application.h b/interface/src/Application.h index b737141b40..7c24eaec8e 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -213,8 +213,15 @@ public: bool isMouseHidden() const { return _mouseHidden; } const glm::vec3& getMouseRayOrigin() const { return _mouseRayOrigin; } const glm::vec3& getMouseRayDirection() const { return _mouseRayDirection; } - int getMouseX() const { return _mouseX; } - int getMouseY() const { return _mouseY; } + bool mouseOnScreen() const; + int getMouseX() const; + int getMouseY() const; + int getTrueMouseX() const { return _mouseX; } + int getTrueMouseY() const { return _mouseY; } + int getMouseDragStartedX() const; + int getMouseDragStartedY() const; + int getTrueMouseDragStartedX() const { return _mouseDragStartedX; } + int getTrueMouseDragStartedY() const { return _mouseDragStartedY; } bool getLastMouseMoveWasSimulated() const { return _lastMouseMoveWasSimulated;; } Faceshift* getFaceshift() { return &_faceshift; } Visage* getVisage() { return &_visage; } diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 36babb64e0..287cd60a84 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -523,7 +523,7 @@ void ApplicationOverlay::renderPointers() { //If we are in oculus, render reticle later _reticleActive[MOUSE] = true; _magActive[MOUSE] = true; - _reticulePosition[MOUSE] = glm::vec2(application->getMouseX(), application->getMouseY()); + _reticulePosition[MOUSE] = glm::vec2(application->getTrueMouseX(), application->getTrueMouseY()); _reticleActive[LEFT_CONTROLLER] = false; _reticleActive[RIGHT_CONTROLLER] = false; diff --git a/interface/src/ui/NodeBounds.cpp b/interface/src/ui/NodeBounds.cpp index 631129321c..3c6b4c625a 100644 --- a/interface/src/ui/NodeBounds.cpp +++ b/interface/src/ui/NodeBounds.cpp @@ -38,7 +38,7 @@ void NodeBounds::draw() { // Compute ray to find selected nodes later on. We can't use the pre-computed ray in Application because it centers // itself after the cursor disappears. Application* application = Application::getInstance(); - PickRay pickRay = application->getCamera()->computeViewPickRay(application->getMouseX(), application->getMouseY()); + PickRay pickRay = application->getCamera()->computeViewPickRay(application->getTrueMouseX(), application->getTrueMouseY()); // Variables to keep track of the selected node and properties to draw the cube later if needed Node* selectedNode = NULL; @@ -220,8 +220,8 @@ void NodeBounds::drawOverlay() { const int MOUSE_OFFSET = 10; const int BACKGROUND_BEVEL = 3; - int mouseX = application->getMouseX(), - mouseY = application->getMouseY(), + int mouseX = application->getTrueMouseX(), + mouseY = application->getTrueMouseY(), textWidth = widthText(TEXT_SCALE, 0, _overlayText); glColor4f(0.4f, 0.4f, 0.4f, 0.6f); renderBevelCornersRect(mouseX + MOUSE_OFFSET, mouseY - TEXT_HEIGHT - PADDING, From 9f444581e9175d0c440255dd8f0b8d0e10728030 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 4 Dec 2014 18:53:30 -0800 Subject: [PATCH 234/502] Fixed JS picking in oculus --- interface/src/Application.cpp | 1 - interface/src/ui/overlays/Overlays.cpp | 9 ++++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index ca3fcfdd1b..32517bc896 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1288,7 +1288,6 @@ void Application::mouseMoveEvent(QMouseEvent* event, unsigned int deviceID) { } void Application::mousePressEvent(QMouseEvent* event, unsigned int deviceID) { - if (!_aboutToQuit) { _entities.mousePressEvent(event, deviceID); } diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 455b73fb80..d991cb762c 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -244,6 +245,11 @@ void Overlays::deleteOverlay(unsigned int id) { } unsigned int Overlays::getOverlayAtPoint(const glm::vec2& point) { + glm::vec2 pointCpy = point; + if (OculusManager::isConnected()) { + pointCpy = Application::getInstance()->getApplicationOverlay().screenToOverlay(point); + } + QReadLocker lock(&_lock); QMapIterator i(_overlays2D); i.toBack(); @@ -251,7 +257,8 @@ unsigned int Overlays::getOverlayAtPoint(const glm::vec2& point) { i.previous(); unsigned int thisID = i.key(); Overlay2D* thisOverlay = static_cast(i.value()); - if (thisOverlay->getVisible() && thisOverlay->isLoaded() && thisOverlay->getBounds().contains(point.x, point.y, false)) { + if (thisOverlay->getVisible() && thisOverlay->isLoaded() && + thisOverlay->getBounds().contains(pointCpy.x, pointCpy.y, false)) { return thisID; } } From d2b0cdbac31c08ca6dc96dfdce0596fa73d07180 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 4 Dec 2014 19:31:59 -0800 Subject: [PATCH 235/502] Hydra reticule rendering for Oculus --- interface/src/ui/ApplicationOverlay.cpp | 84 ++++--------------------- 1 file changed, 13 insertions(+), 71 deletions(-) diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 287cd60a84..71d1a728df 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -29,6 +29,7 @@ const quint64 MSECS_TO_USECS = 1000ULL; const float WHITE_TEXT[] = { 0.93f, 0.93f, 0.93f }; const float RETICLE_COLOR[] = { 0.0f, 198.0f / 255.0f, 244.0f / 255.0f }; +const float reticleSize = TWO_PI / 100.0f; const float CONNECTION_STATUS_BORDER_COLOR[] = { 1.0f, 0.0f, 0.0f }; @@ -103,8 +104,6 @@ bool raySphereIntersect(const glm::vec3 &dir, const glm::vec3 &origin, float r, } void renderReticule(glm::quat orientation, float alpha) { - const float reticleSize = TWO_PI / 80.0f; - glm::vec3 topLeft = getPoint(reticleSize / 2.0f, -reticleSize / 2.0f); glm::vec3 topRight = getPoint(-reticleSize / 2.0f, -reticleSize / 2.0f); glm::vec3 bottomLeft = getPoint(reticleSize / 2.0f, reticleSize / 2.0f); @@ -523,7 +522,7 @@ void ApplicationOverlay::renderPointers() { //If we are in oculus, render reticle later _reticleActive[MOUSE] = true; _magActive[MOUSE] = true; - _reticulePosition[MOUSE] = glm::vec2(application->getTrueMouseX(), application->getTrueMouseY()); + _reticulePosition[MOUSE] = glm::vec2(application->getMouseX(), application->getMouseY()); _reticleActive[LEFT_CONTROLLER] = false; _reticleActive[RIGHT_CONTROLLER] = false; @@ -658,70 +657,17 @@ void ApplicationOverlay::renderPointersOculus(const glm::vec3& eyePos) { MyAvatar* myAvatar = Application::getInstance()->getAvatar(); for (int i = 0; i < (int)myAvatar->getHand()->getNumPalms(); i++) { -// PalmData& palm = myAvatar->getHand()->getPalms()[i]; -// if (palm.isActive()) { -// glm::vec3 tip = myAvatar->getLaserPointerTipPosition(&palm); -// glm::vec3 tipPos = (tip - eyePos); -// -// float length = glm::length(eyePos - tip); -// float size = 0.03f * length; -// -// glm::vec3 up = glm::vec3(0.0, 1.0, 0.0) * size; -// glm::vec3 right = glm::vec3(1.0, 0.0, 0.0) * size; -// -// cursorVerts[0] = -right + up; -// cursorVerts[1] = right + up; -// cursorVerts[2] = right - up; -// cursorVerts[3] = -right - up; -// -// glPushMatrix(); -// -// // objToCamProj is the vector in world coordinates from the -// // local origin to the camera projected in the XZ plane -// glm::vec3 cursorToCameraXZ(-tipPos.x, 0, -tipPos.z); -// cursorToCameraXZ = glm::normalize(cursorToCameraXZ); -// -// //Translate the cursor to the tip of the oculus ray -// glTranslatef(tip.x, tip.y, tip.z); -// -// glm::vec3 direction(0, 0, 1); -// // easy fix to determine wether the angle is negative or positive -// // for positive angles upAux will be a vector pointing in the -// // positive y direction, otherwise upAux will point downwards -// // effectively reversing the rotation. -// glm::vec3 upAux = glm::cross(direction, cursorToCameraXZ); -// -// // compute the angle -// float angleCosine = glm::dot(direction, cursorToCameraXZ); -// -// //Rotate in XZ direction -// glRotatef(acos(angleCosine) * DEGREES_PER_RADIAN, upAux[0], upAux[1], upAux[2]); -// -// glm::vec3 cursorToCamera = glm::normalize(-tipPos); -// -// // Compute the angle between cursorToCameraXZ and cursorToCamera, -// angleCosine = glm::dot(cursorToCameraXZ, cursorToCamera); -// -// //Rotate in Y direction -// if (cursorToCamera.y < 0) { -// glRotatef(acos(angleCosine) * DEGREES_PER_RADIAN, 1, 0, 0); -// } else { -// glRotatef(acos(angleCosine) * DEGREES_PER_RADIAN, -1, 0, 0); -// } -// -// glBegin(GL_QUADS); -// -// glColor4f(RETICLE_COLOR[0], RETICLE_COLOR[1], RETICLE_COLOR[2], _alpha); -// -// glTexCoord2f(0.0f, 0.0f); glVertex3f(cursorVerts[0].x, cursorVerts[0].y, cursorVerts[0].z); -// glTexCoord2f(1.0f, 0.0f); glVertex3f(cursorVerts[1].x, cursorVerts[1].y, cursorVerts[1].z); -// glTexCoord2f(1.0f, 1.0f); glVertex3f(cursorVerts[2].x, cursorVerts[2].y, cursorVerts[2].z); -// glTexCoord2f(0.0f, 1.0f); glVertex3f(cursorVerts[3].x, cursorVerts[3].y, cursorVerts[3].z); -// -// glEnd(); -// -// glPopMatrix(); -// } + PalmData& palm = myAvatar->getHand()->getPalms()[i]; + if (palm.isActive()) { + glm::vec3 tip = myAvatar->getLaserPointerTipPosition(&palm); + glm::vec3 tipDirection = glm::normalize(glm::inverse(myAvatar->getOrientation()) * (tip - eyePos)); + float pitch = -glm::asin(tipDirection.y); + float yawSign = glm::sign(-tipDirection.x); + float yaw = glm::acos(-tipDirection.z) * + ((yawSign == 0.0f) ? 1.0f : yawSign); + glm::quat orientation = glm::quat(glm::vec3(pitch, yaw, 0.0f)); + renderReticule(orientation, _alpha); + } } //Mouse Pointer @@ -791,8 +737,6 @@ void ApplicationOverlay::renderMagnifier(glm::vec2 magPos, float sizeMult, bool } glPopMatrix(); } - - void ApplicationOverlay::renderAudioMeter() { Application* application = Application::getInstance(); @@ -990,8 +934,6 @@ void ApplicationOverlay::renderDomainConnectionStatusBorder() { } } - - ApplicationOverlay::TexturedHemisphere::TexturedHemisphere() : _vertices(0), _indices(0), From 90d4e7bae92e9357741a4a9990c926d405c06e78 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 4 Dec 2014 19:38:39 -0800 Subject: [PATCH 236/502] Comments --- interface/src/ui/ApplicationOverlay.cpp | 2 +- interface/src/ui/ApplicationOverlay.h | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 71d1a728df..c029a2e00f 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -39,7 +39,7 @@ static const float MOUSE_PITCH_RANGE = 1.0f * PI; static const float MOUSE_YAW_RANGE = 0.5f * TWO_PI; -// Return a point's coordinates on a sphere from pitch and yaw +// Return a point's cartesian coordinates on a sphere from pitch and yaw glm::vec3 getPoint(float yaw, float pitch) { return glm::vec3(glm::cos(-pitch) * (-glm::sin(yaw)), glm::sin(-pitch), diff --git a/interface/src/ui/ApplicationOverlay.h b/interface/src/ui/ApplicationOverlay.h index 399cd504b8..2ca430aae6 100644 --- a/interface/src/ui/ApplicationOverlay.h +++ b/interface/src/ui/ApplicationOverlay.h @@ -34,6 +34,13 @@ public: QPoint getPalmClickLocation(const PalmData *palm) const; bool calculateRayUICollisionPoint(const glm::vec3& position, const glm::vec3& direction, glm::vec3& result) const; + // Converter from one frame of reference to another. + // Frame of reference: + // Screen: Position on the screen (x,y) + // Spherical: Pitch and yaw that gives the position on the sphere we project on (yaw,pitch) + // Overlay: Position on the overlay (x,y) + // (x,y) in Overlay are similar than (x,y) in Screen except they can be outside of the bound of te screen. + // This allows for picking outside of the screen projection in 3D. glm::vec2 screenToSpherical(glm::vec2 screenPos) const; glm::vec2 sphericalToScreen(glm::vec2 sphericalPos) const; glm::vec2 sphericalToOverlay(glm::vec2 sphericalPos) const; From 7322cd3ecee1e80613ab0362ab68cb62a4e7fd44 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 4 Dec 2014 20:16:50 -0800 Subject: [PATCH 237/502] Coding Standard --- interface/src/ui/overlays/Overlays.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index d991cb762c..25e667e56c 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -245,9 +245,9 @@ void Overlays::deleteOverlay(unsigned int id) { } unsigned int Overlays::getOverlayAtPoint(const glm::vec2& point) { - glm::vec2 pointCpy = point; + glm::vec2 pointCopy = point; if (OculusManager::isConnected()) { - pointCpy = Application::getInstance()->getApplicationOverlay().screenToOverlay(point); + pointCopy = Application::getInstance()->getApplicationOverlay().screenToOverlay(point); } QReadLocker lock(&_lock); @@ -258,7 +258,7 @@ unsigned int Overlays::getOverlayAtPoint(const glm::vec2& point) { unsigned int thisID = i.key(); Overlay2D* thisOverlay = static_cast(i.value()); if (thisOverlay->getVisible() && thisOverlay->isLoaded() && - thisOverlay->getBounds().contains(pointCpy.x, pointCpy.y, false)) { + thisOverlay->getBounds().contains(pointCopy.x, pointCopy.y, false)) { return thisID; } } From dff22b01b6757cae80d233b4ba1fd66a20f386f1 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Fri, 5 Dec 2014 01:58:45 -0800 Subject: [PATCH 238/502] Allow loading "MDR" files saved by Wilbur, fix for reallocating error. --- libraries/metavoxels/src/Spanner.cpp | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/libraries/metavoxels/src/Spanner.cpp b/libraries/metavoxels/src/Spanner.cpp index 216d4d7d1d..956dc45729 100644 --- a/libraries/metavoxels/src/Spanner.cpp +++ b/libraries/metavoxels/src/Spanner.cpp @@ -608,22 +608,27 @@ static int getHeightfieldSize(int size) { void HeightfieldHeightEditor::select() { QSettings settings; QString result = QFileDialog::getOpenFileName(this, "Select Height Image", settings.value("heightDir").toString(), - "Images (*.png *.jpg *.bmp *.raw)"); + "Images (*.png *.jpg *.bmp *.raw *.mdr)"); if (result.isNull()) { return; } settings.setValue("heightDir", QFileInfo(result).path()); const quint16 CONVERSION_OFFSET = 1; - if (result.toLower().endsWith(".raw")) { + QString lowerResult = result.toLower(); + bool isMDR = lowerResult.endsWith(".mdr"); + if (lowerResult.endsWith(".raw") || isMDR) { QFile input(result); input.open(QIODevice::ReadOnly); QDataStream in(&input); in.setByteOrder(QDataStream::LittleEndian); - QVector rawContents; - while (!in.atEnd()) { - quint16 height; - in >> height; - rawContents.append(height); + if (isMDR) { + const int MDR_HEADER_SIZE = 1024; + input.seek(MDR_HEADER_SIZE); + } + int available = input.bytesAvailable() / sizeof(quint16); + QVector rawContents(available); + for (quint16* height = rawContents.data(), *end = height + available; height != end; height++) { + in >> *height; } if (rawContents.isEmpty()) { QMessageBox::warning(this, "Invalid Image", "The selected image could not be read."); From c5247ca65b0cfde24b83fd7e8969dc9c9111ae96 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Fri, 5 Dec 2014 08:45:00 -0800 Subject: [PATCH 239/502] Add ability to set injector properties during playing, and orbitingSound.js --- examples/orbitingSound.js | 49 +++++++++++++++++++ .../audio/src/AudioScriptingInterface.cpp | 7 +++ libraries/audio/src/AudioScriptingInterface.h | 2 + 3 files changed, 58 insertions(+) create mode 100644 examples/orbitingSound.js diff --git a/examples/orbitingSound.js b/examples/orbitingSound.js new file mode 100644 index 0000000000..903d73cebc --- /dev/null +++ b/examples/orbitingSound.js @@ -0,0 +1,49 @@ +// +// orbitingSound.js +// examples +// +// Created by Philip Rosedale on December 4, 2014 +// Copyright 2014 High Fidelity, Inc. +// +// An object playing a sound appears and circles you, changing brightness with the audio playing. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +var RADIUS = 2.0; +var orbitCenter = Vec3.sum(Camera.position, Vec3.multiply(Quat.getFront(Camera.getOrientation()), RADIUS)); +var time = 0; +var SPEED = 1.0; +var currentPosition = { x: 0, y: 0, z: 0 }; +var trailingLoudness = 0.0; + +var soundClip = SoundCache.getSound("https://s3.amazonaws.com/hifi-public/sounds/Tabla+Loops/Tabla1.wav"); + +var properties = { + type: "Box", + position: orbitCenter, + dimensions: { x: 0.25, y: 0.25, z: 0.25 }, + color: { red: 100, green: 0, blue : 0 } + }; + +var objectId = Entities.addEntity(properties); +var sound = Audio.playSound(soundClip, { position: orbitCenter, loop: true, volume: 0.5 }); + +function update(deltaTime) { + time += deltaTime; + currentPosition = { x: orbitCenter.x + Math.cos(time * SPEED) * RADIUS, y: orbitCenter.y, z: orbitCenter.z + Math.sin(time * SPEED) * RADIUS }; + trailingLoudness = 0.9 * trailingLoudness + 0.1 * Audio.getLoudness(sound); + Entities.editEntity( objectId, { position: currentPosition, color: { red: Math.min(trailingLoudness * 2000, 255), green: 0, blue: 0 } } ); + //if (Audio.isInjectorPlaying(sound)) { + Audio.setInjectorOptions(sound, { position: currentPosition }); + //} else { + // sound = Audio.playSound(soundClip, { position: orbitCenter, loop: true, volume: 0.5 }); + //} +} + +Script.scriptEnding.connect(function() { + Entities.deleteEntity(objectId); + Audio.stopInjector(sound); +}); + +Script.update.connect(update); \ No newline at end of file diff --git a/libraries/audio/src/AudioScriptingInterface.cpp b/libraries/audio/src/AudioScriptingInterface.cpp index b604e2825b..8cd133ad40 100644 --- a/libraries/audio/src/AudioScriptingInterface.cpp +++ b/libraries/audio/src/AudioScriptingInterface.cpp @@ -85,6 +85,13 @@ bool AudioScriptingInterface::isInjectorPlaying(AudioInjector* injector) { return (injector != NULL); } +void AudioScriptingInterface::setInjectorOptions(AudioInjector* injector, const AudioInjectorOptions& injectorOptions) { + AudioInjectorOptions optionsCopy = injectorOptions; + if (injector) { + injector->setOptions(optionsCopy); + } +} + float AudioScriptingInterface::getLoudness(AudioInjector* injector) { if (injector) { return injector->getLoudness(); diff --git a/libraries/audio/src/AudioScriptingInterface.h b/libraries/audio/src/AudioScriptingInterface.h index 5b67666a97..b437286ecf 100644 --- a/libraries/audio/src/AudioScriptingInterface.h +++ b/libraries/audio/src/AudioScriptingInterface.h @@ -35,6 +35,8 @@ public slots: void stopInjector(AudioInjector* injector); bool isInjectorPlaying(AudioInjector* injector); + void setInjectorOptions(AudioInjector* injector, const AudioInjectorOptions& injectorOptions); + void injectorStopped(); signals: From bc609016a91ca8a2fb14406f213b0bf07603cea4 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Fri, 5 Dec 2014 08:59:41 -0800 Subject: [PATCH 240/502] remove debug --- examples/orbitingSound.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/examples/orbitingSound.js b/examples/orbitingSound.js index 903d73cebc..54e319faaa 100644 --- a/examples/orbitingSound.js +++ b/examples/orbitingSound.js @@ -34,11 +34,7 @@ function update(deltaTime) { currentPosition = { x: orbitCenter.x + Math.cos(time * SPEED) * RADIUS, y: orbitCenter.y, z: orbitCenter.z + Math.sin(time * SPEED) * RADIUS }; trailingLoudness = 0.9 * trailingLoudness + 0.1 * Audio.getLoudness(sound); Entities.editEntity( objectId, { position: currentPosition, color: { red: Math.min(trailingLoudness * 2000, 255), green: 0, blue: 0 } } ); - //if (Audio.isInjectorPlaying(sound)) { - Audio.setInjectorOptions(sound, { position: currentPosition }); - //} else { - // sound = Audio.playSound(soundClip, { position: orbitCenter, loop: true, volume: 0.5 }); - //} + Audio.setInjectorOptions(sound, { position: currentPosition }); } Script.scriptEnding.connect(function() { From feab9423758b639fccbd3a958ce52d27faea1c91 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 5 Dec 2014 10:01:16 -0800 Subject: [PATCH 241/502] Revert "get rid of redundant _displayViewFrustum and use _viewFrustum" This reverts commit 6d385d9a75de786e0d1f583ad8448c30a9df2492. --- interface/src/Application.cpp | 4 ++-- interface/src/Application.h | 2 ++ interface/src/MetavoxelSystem.cpp | 6 +++--- interface/src/renderer/DeferredLightingEffect.cpp | 4 ++-- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 85b21b073f..44f83102e2 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2910,7 +2910,7 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly, RenderAr // transform by eye offset // load the view frustum - loadViewFrustum(whichCamera, _viewFrustum); + loadViewFrustum(whichCamera, _displayViewFrustum); // flip x if in mirror mode (also requires reversing winding order for backface culling) if (whichCamera.getMode() == CAMERA_MODE_MIRROR) { @@ -3184,7 +3184,7 @@ void Application::computeOffAxisFrustum(float& left, float& right, float& bottom float& farVal, glm::vec4& nearClipPlane, glm::vec4& farClipPlane) const { // allow 3DTV/Oculus to override parameters from camera - _viewFrustum.computeOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane); + _displayViewFrustum.computeOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane); if (OculusManager::isConnected()) { OculusManager::overrideOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane); diff --git a/interface/src/Application.h b/interface/src/Application.h index b737141b40..e432f7fdf0 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -196,6 +196,7 @@ public: const AudioReflector* getAudioReflector() const { return &_audioReflector; } Camera* getCamera() { return &_myCamera; } ViewFrustum* getViewFrustum() { return &_viewFrustum; } + ViewFrustum* getDisplayViewFrustum() { return &_displayViewFrustum; } ViewFrustum* getShadowViewFrustum() { return &_shadowViewFrustum; } VoxelImporter* getVoxelImporter() { return &_voxelImporter; } VoxelSystem* getVoxels() { return &_voxels; } @@ -517,6 +518,7 @@ private: ViewFrustum _viewFrustum; // current state of view frustum, perspective, orientation, etc. ViewFrustum _lastQueriedViewFrustum; /// last view frustum used to query octree servers (voxels) + ViewFrustum _displayViewFrustum; ViewFrustum _shadowViewFrustum; quint64 _lastQueriedTime; diff --git a/interface/src/MetavoxelSystem.cpp b/interface/src/MetavoxelSystem.cpp index 996b92e22d..b98fea8eca 100644 --- a/interface/src/MetavoxelSystem.cpp +++ b/interface/src/MetavoxelSystem.cpp @@ -192,7 +192,7 @@ static const float EIGHT_BIT_MAXIMUM_RECIPROCAL = 1.0f / EIGHT_BIT_MAXIMUM; void MetavoxelSystem::render() { // update the frustum - ViewFrustum* viewFrustum = Application::getInstance()->getViewFrustum(); + ViewFrustum* viewFrustum = Application::getInstance()->getDisplayViewFrustum(); _frustum.set(viewFrustum->getFarTopLeft(), viewFrustum->getFarTopRight(), viewFrustum->getFarBottomLeft(), viewFrustum->getFarBottomRight(), viewFrustum->getNearTopLeft(), viewFrustum->getNearTopRight(), viewFrustum->getNearBottomLeft(), viewFrustum->getNearBottomRight()); @@ -1896,7 +1896,7 @@ private: SpannerRenderVisitor::SpannerRenderVisitor(const MetavoxelLOD& lod) : SpannerVisitor(QVector() << AttributeRegistry::getInstance()->getSpannersAttribute(), QVector(), QVector(), lod, - encodeOrder(Application::getInstance()->getViewFrustum()->getDirection())), + encodeOrder(Application::getInstance()->getDisplayViewFrustum()->getDirection())), _containmentDepth(INT_MAX) { } @@ -1932,7 +1932,7 @@ private: BufferRenderVisitor::BufferRenderVisitor(const AttributePointer& attribute) : MetavoxelVisitor(QVector() << attribute), - _order(encodeOrder(Application::getInstance()->getViewFrustum()->getDirection())), + _order(encodeOrder(Application::getInstance()->getDisplayViewFrustum()->getDirection())), _containmentDepth(INT_MAX) { } diff --git a/interface/src/renderer/DeferredLightingEffect.cpp b/interface/src/renderer/DeferredLightingEffect.cpp index 63d874cda7..be4e457131 100644 --- a/interface/src/renderer/DeferredLightingEffect.cpp +++ b/interface/src/renderer/DeferredLightingEffect.cpp @@ -232,8 +232,8 @@ void DeferredLightingEffect::render() { // enlarge the scales slightly to account for tesselation const float SCALE_EXPANSION = 0.05f; - const glm::vec3& eyePoint = Application::getInstance()->getViewFrustum()->getPosition(); - float nearRadius = glm::distance(eyePoint, Application::getInstance()->getViewFrustum()->getNearTopLeft()); + const glm::vec3& eyePoint = Application::getInstance()->getDisplayViewFrustum()->getPosition(); + float nearRadius = glm::distance(eyePoint, Application::getInstance()->getDisplayViewFrustum()->getNearTopLeft()); if (!_pointLights.isEmpty()) { _pointLight.bind(); From 9753c82a3bc5b5bdb2cea5f596c71e66d0823b67 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 2 Dec 2014 11:45:33 -0800 Subject: [PATCH 242/502] get rid of redundant _displayViewFrustum and use _viewFrustum --- interface/src/Application.cpp | 4 ++-- interface/src/Application.h | 2 -- interface/src/MetavoxelSystem.cpp | 6 +++--- interface/src/renderer/DeferredLightingEffect.cpp | 4 ++-- 4 files changed, 7 insertions(+), 9 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 44f83102e2..85b21b073f 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2910,7 +2910,7 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly, RenderAr // transform by eye offset // load the view frustum - loadViewFrustum(whichCamera, _displayViewFrustum); + loadViewFrustum(whichCamera, _viewFrustum); // flip x if in mirror mode (also requires reversing winding order for backface culling) if (whichCamera.getMode() == CAMERA_MODE_MIRROR) { @@ -3184,7 +3184,7 @@ void Application::computeOffAxisFrustum(float& left, float& right, float& bottom float& farVal, glm::vec4& nearClipPlane, glm::vec4& farClipPlane) const { // allow 3DTV/Oculus to override parameters from camera - _displayViewFrustum.computeOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane); + _viewFrustum.computeOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane); if (OculusManager::isConnected()) { OculusManager::overrideOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane); diff --git a/interface/src/Application.h b/interface/src/Application.h index e432f7fdf0..b737141b40 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -196,7 +196,6 @@ public: const AudioReflector* getAudioReflector() const { return &_audioReflector; } Camera* getCamera() { return &_myCamera; } ViewFrustum* getViewFrustum() { return &_viewFrustum; } - ViewFrustum* getDisplayViewFrustum() { return &_displayViewFrustum; } ViewFrustum* getShadowViewFrustum() { return &_shadowViewFrustum; } VoxelImporter* getVoxelImporter() { return &_voxelImporter; } VoxelSystem* getVoxels() { return &_voxels; } @@ -518,7 +517,6 @@ private: ViewFrustum _viewFrustum; // current state of view frustum, perspective, orientation, etc. ViewFrustum _lastQueriedViewFrustum; /// last view frustum used to query octree servers (voxels) - ViewFrustum _displayViewFrustum; ViewFrustum _shadowViewFrustum; quint64 _lastQueriedTime; diff --git a/interface/src/MetavoxelSystem.cpp b/interface/src/MetavoxelSystem.cpp index b98fea8eca..996b92e22d 100644 --- a/interface/src/MetavoxelSystem.cpp +++ b/interface/src/MetavoxelSystem.cpp @@ -192,7 +192,7 @@ static const float EIGHT_BIT_MAXIMUM_RECIPROCAL = 1.0f / EIGHT_BIT_MAXIMUM; void MetavoxelSystem::render() { // update the frustum - ViewFrustum* viewFrustum = Application::getInstance()->getDisplayViewFrustum(); + ViewFrustum* viewFrustum = Application::getInstance()->getViewFrustum(); _frustum.set(viewFrustum->getFarTopLeft(), viewFrustum->getFarTopRight(), viewFrustum->getFarBottomLeft(), viewFrustum->getFarBottomRight(), viewFrustum->getNearTopLeft(), viewFrustum->getNearTopRight(), viewFrustum->getNearBottomLeft(), viewFrustum->getNearBottomRight()); @@ -1896,7 +1896,7 @@ private: SpannerRenderVisitor::SpannerRenderVisitor(const MetavoxelLOD& lod) : SpannerVisitor(QVector() << AttributeRegistry::getInstance()->getSpannersAttribute(), QVector(), QVector(), lod, - encodeOrder(Application::getInstance()->getDisplayViewFrustum()->getDirection())), + encodeOrder(Application::getInstance()->getViewFrustum()->getDirection())), _containmentDepth(INT_MAX) { } @@ -1932,7 +1932,7 @@ private: BufferRenderVisitor::BufferRenderVisitor(const AttributePointer& attribute) : MetavoxelVisitor(QVector() << attribute), - _order(encodeOrder(Application::getInstance()->getDisplayViewFrustum()->getDirection())), + _order(encodeOrder(Application::getInstance()->getViewFrustum()->getDirection())), _containmentDepth(INT_MAX) { } diff --git a/interface/src/renderer/DeferredLightingEffect.cpp b/interface/src/renderer/DeferredLightingEffect.cpp index be4e457131..63d874cda7 100644 --- a/interface/src/renderer/DeferredLightingEffect.cpp +++ b/interface/src/renderer/DeferredLightingEffect.cpp @@ -232,8 +232,8 @@ void DeferredLightingEffect::render() { // enlarge the scales slightly to account for tesselation const float SCALE_EXPANSION = 0.05f; - const glm::vec3& eyePoint = Application::getInstance()->getDisplayViewFrustum()->getPosition(); - float nearRadius = glm::distance(eyePoint, Application::getInstance()->getDisplayViewFrustum()->getNearTopLeft()); + const glm::vec3& eyePoint = Application::getInstance()->getViewFrustum()->getPosition(); + float nearRadius = glm::distance(eyePoint, Application::getInstance()->getViewFrustum()->getNearTopLeft()); if (!_pointLights.isEmpty()) { _pointLight.bind(); From e68e3fe774df3dd9d9942735718823cb06fca6bf Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 5 Dec 2014 10:06:17 -0800 Subject: [PATCH 243/502] Revert "get rid of redundant _displayViewFrustum and use _viewFrustum" This reverts commit 6d385d9a75de786e0d1f583ad8448c30a9df2492. --- interface/src/Application.cpp | 4 ++-- interface/src/Application.h | 2 ++ interface/src/MetavoxelSystem.cpp | 6 +++--- interface/src/renderer/DeferredLightingEffect.cpp | 4 ++-- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 85b21b073f..44f83102e2 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2910,7 +2910,7 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly, RenderAr // transform by eye offset // load the view frustum - loadViewFrustum(whichCamera, _viewFrustum); + loadViewFrustum(whichCamera, _displayViewFrustum); // flip x if in mirror mode (also requires reversing winding order for backface culling) if (whichCamera.getMode() == CAMERA_MODE_MIRROR) { @@ -3184,7 +3184,7 @@ void Application::computeOffAxisFrustum(float& left, float& right, float& bottom float& farVal, glm::vec4& nearClipPlane, glm::vec4& farClipPlane) const { // allow 3DTV/Oculus to override parameters from camera - _viewFrustum.computeOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane); + _displayViewFrustum.computeOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane); if (OculusManager::isConnected()) { OculusManager::overrideOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane); diff --git a/interface/src/Application.h b/interface/src/Application.h index b737141b40..e432f7fdf0 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -196,6 +196,7 @@ public: const AudioReflector* getAudioReflector() const { return &_audioReflector; } Camera* getCamera() { return &_myCamera; } ViewFrustum* getViewFrustum() { return &_viewFrustum; } + ViewFrustum* getDisplayViewFrustum() { return &_displayViewFrustum; } ViewFrustum* getShadowViewFrustum() { return &_shadowViewFrustum; } VoxelImporter* getVoxelImporter() { return &_voxelImporter; } VoxelSystem* getVoxels() { return &_voxels; } @@ -517,6 +518,7 @@ private: ViewFrustum _viewFrustum; // current state of view frustum, perspective, orientation, etc. ViewFrustum _lastQueriedViewFrustum; /// last view frustum used to query octree servers (voxels) + ViewFrustum _displayViewFrustum; ViewFrustum _shadowViewFrustum; quint64 _lastQueriedTime; diff --git a/interface/src/MetavoxelSystem.cpp b/interface/src/MetavoxelSystem.cpp index 996b92e22d..b98fea8eca 100644 --- a/interface/src/MetavoxelSystem.cpp +++ b/interface/src/MetavoxelSystem.cpp @@ -192,7 +192,7 @@ static const float EIGHT_BIT_MAXIMUM_RECIPROCAL = 1.0f / EIGHT_BIT_MAXIMUM; void MetavoxelSystem::render() { // update the frustum - ViewFrustum* viewFrustum = Application::getInstance()->getViewFrustum(); + ViewFrustum* viewFrustum = Application::getInstance()->getDisplayViewFrustum(); _frustum.set(viewFrustum->getFarTopLeft(), viewFrustum->getFarTopRight(), viewFrustum->getFarBottomLeft(), viewFrustum->getFarBottomRight(), viewFrustum->getNearTopLeft(), viewFrustum->getNearTopRight(), viewFrustum->getNearBottomLeft(), viewFrustum->getNearBottomRight()); @@ -1896,7 +1896,7 @@ private: SpannerRenderVisitor::SpannerRenderVisitor(const MetavoxelLOD& lod) : SpannerVisitor(QVector() << AttributeRegistry::getInstance()->getSpannersAttribute(), QVector(), QVector(), lod, - encodeOrder(Application::getInstance()->getViewFrustum()->getDirection())), + encodeOrder(Application::getInstance()->getDisplayViewFrustum()->getDirection())), _containmentDepth(INT_MAX) { } @@ -1932,7 +1932,7 @@ private: BufferRenderVisitor::BufferRenderVisitor(const AttributePointer& attribute) : MetavoxelVisitor(QVector() << attribute), - _order(encodeOrder(Application::getInstance()->getViewFrustum()->getDirection())), + _order(encodeOrder(Application::getInstance()->getDisplayViewFrustum()->getDirection())), _containmentDepth(INT_MAX) { } diff --git a/interface/src/renderer/DeferredLightingEffect.cpp b/interface/src/renderer/DeferredLightingEffect.cpp index 63d874cda7..be4e457131 100644 --- a/interface/src/renderer/DeferredLightingEffect.cpp +++ b/interface/src/renderer/DeferredLightingEffect.cpp @@ -232,8 +232,8 @@ void DeferredLightingEffect::render() { // enlarge the scales slightly to account for tesselation const float SCALE_EXPANSION = 0.05f; - const glm::vec3& eyePoint = Application::getInstance()->getViewFrustum()->getPosition(); - float nearRadius = glm::distance(eyePoint, Application::getInstance()->getViewFrustum()->getNearTopLeft()); + const glm::vec3& eyePoint = Application::getInstance()->getDisplayViewFrustum()->getPosition(); + float nearRadius = glm::distance(eyePoint, Application::getInstance()->getDisplayViewFrustum()->getNearTopLeft()); if (!_pointLights.isEmpty()) { _pointLight.bind(); From 563cd6f7e369ee29d57979f0ee80aad60efde290 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Fri, 5 Dec 2014 10:10:21 -0800 Subject: [PATCH 244/502] watch your language... --- libraries/fbx/src/FBXReader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index a750ab53e2..f8451637a8 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -1520,7 +1520,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, } } else { std::string whatisthat = subobject.name; - if (whatisthat == "WTF") { + if (whatisthat == "Shape") { } } #endif From 0ece6c0968dc2764c0cdfbc16f5198b2f3fd12fd Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 5 Dec 2014 10:43:15 -0800 Subject: [PATCH 245/502] Update properties window to show properties for locked entities --- examples/html/entityProperties.html | 150 ++++++++++++++-------------- 1 file changed, 75 insertions(+), 75 deletions(-) diff --git a/examples/html/entityProperties.html b/examples/html/entityProperties.html index a79edfb181..87ab066c5c 100644 --- a/examples/html/entityProperties.html +++ b/examples/html/entityProperties.html @@ -163,99 +163,99 @@ disableChildren(document.getElementById("properties"), 'input'); elLocked.removeAttribute('disabled'); } else { - enableChildren(document.getElementById("properties"), 'input'); + enableChildren(document.getElementById("properties-table"), 'input'); + } - elVisible.checked = properties.visible; + elVisible.checked = properties.visible; - elPositionX.value = properties.position.x.toFixed(2); - elPositionY.value = properties.position.y.toFixed(2); - elPositionZ.value = properties.position.z.toFixed(2); + elPositionX.value = properties.position.x.toFixed(2); + elPositionY.value = properties.position.y.toFixed(2); + elPositionZ.value = properties.position.z.toFixed(2); - elDimensionsX.value = properties.dimensions.x.toFixed(2); - elDimensionsY.value = properties.dimensions.y.toFixed(2); - elDimensionsZ.value = properties.dimensions.z.toFixed(2); + elDimensionsX.value = properties.dimensions.x.toFixed(2); + elDimensionsY.value = properties.dimensions.y.toFixed(2); + elDimensionsZ.value = properties.dimensions.z.toFixed(2); - elRegistrationX.value = properties.registrationPoint.x.toFixed(2); - elRegistrationY.value = properties.registrationPoint.y.toFixed(2); - elRegistrationZ.value = properties.registrationPoint.z.toFixed(2); + elRegistrationX.value = properties.registrationPoint.x.toFixed(2); + elRegistrationY.value = properties.registrationPoint.y.toFixed(2); + elRegistrationZ.value = properties.registrationPoint.z.toFixed(2); - elLinearVelocityX.value = properties.velocity.x.toFixed(2); - elLinearVelocityY.value = properties.velocity.y.toFixed(2); - elLinearVelocityZ.value = properties.velocity.z.toFixed(2); - elLinearDamping.value = properties.damping.toFixed(2); + elLinearVelocityX.value = properties.velocity.x.toFixed(2); + elLinearVelocityY.value = properties.velocity.y.toFixed(2); + elLinearVelocityZ.value = properties.velocity.z.toFixed(2); + elLinearDamping.value = properties.damping.toFixed(2); - elAngularVelocityX.value = properties.angularVelocity.x.toFixed(2); - elAngularVelocityY.value = properties.angularVelocity.y.toFixed(2); - elAngularVelocityZ.value = properties.angularVelocity.z.toFixed(2); - elAngularDamping.value = properties.angularDamping.toFixed(2); + elAngularVelocityX.value = properties.angularVelocity.x.toFixed(2); + elAngularVelocityY.value = properties.angularVelocity.y.toFixed(2); + elAngularVelocityZ.value = properties.angularVelocity.z.toFixed(2); + elAngularDamping.value = properties.angularDamping.toFixed(2); - elGravityX.value = properties.gravity.x.toFixed(2); - elGravityY.value = properties.gravity.y.toFixed(2); - elGravityZ.value = properties.gravity.z.toFixed(2); + elGravityX.value = properties.gravity.x.toFixed(2); + elGravityY.value = properties.gravity.y.toFixed(2); + elGravityZ.value = properties.gravity.z.toFixed(2); - elMass.value = properties.mass.toFixed(2); - elIgnoreForCollisions.checked = properties.ignoreForCollisions; - elCollisionsWillMove.checked = properties.collisionsWillMove; - elLifetime.value = properties.lifetime; + elMass.value = properties.mass.toFixed(2); + elIgnoreForCollisions.checked = properties.ignoreForCollisions; + elCollisionsWillMove.checked = properties.collisionsWillMove; + elLifetime.value = properties.lifetime; - if (properties.type != "Box") { - elBoxSection.style.display = 'none'; - } else { - elBoxSection.style.display = 'block'; + if (properties.type != "Box") { + elBoxSection.style.display = 'none'; + } else { + elBoxSection.style.display = 'block'; - elBoxColorRed.value = properties.color.red; - elBoxColorGreen.value = properties.color.green; - elBoxColorBlue.value = properties.color.blue; - } + elBoxColorRed.value = properties.color.red; + elBoxColorGreen.value = properties.color.green; + elBoxColorBlue.value = properties.color.blue; + } - if (properties.type != "Model") { - elModelSection.style.display = 'none'; - } else { - elModelSection.style.display = 'block'; - elModelURL.value = properties.modelURL; - elModelAnimationURL.value = properties.animationURL; - elModelAnimationPlaying.checked = properties.animationIsPlaying; - elModelAnimationFPS.value = properties.animationFPS; - } + if (properties.type != "Model") { + elModelSection.style.display = 'none'; + } else { + elModelSection.style.display = 'block'; + elModelURL.value = properties.modelURL; + elModelAnimationURL.value = properties.animationURL; + elModelAnimationPlaying.checked = properties.animationIsPlaying; + elModelAnimationFPS.value = properties.animationFPS; + } - if (properties.type != "Text") { - elTextSection.style.display = 'none'; - } else { - elTextSection.style.display = 'block'; + if (properties.type != "Text") { + elTextSection.style.display = 'none'; + } else { + elTextSection.style.display = 'block'; - elTextText.value = properties.text; - elTextLineHeight.value = properties.lineHeight; - elTextTextColorRed.value = properties.textColor.red; - elTextTextColorGreen.value = properties.textColor.green; - elTextTextColorBlue.value = properties.textColor.blue; - elTextBackgroundColorRed.value = properties.backgroundColor.red; - elTextBackgroundColorGreen.value = properties.backgroundColor.green; - elTextBackgroundColorBlue.value = properties.backgroundColor.blue; - } + elTextText.value = properties.text; + elTextLineHeight.value = properties.lineHeight; + elTextTextColorRed.value = properties.textColor.red; + elTextTextColorGreen.value = properties.textColor.green; + elTextTextColorBlue.value = properties.textColor.blue; + elTextBackgroundColorRed.value = properties.backgroundColor.red; + elTextBackgroundColorGreen.value = properties.backgroundColor.green; + elTextBackgroundColorBlue.value = properties.backgroundColor.blue; + } - if (properties.type != "Light") { - elLightSection.style.display = 'none'; - } else { - elLightSection.style.display = 'block'; + if (properties.type != "Light") { + elLightSection.style.display = 'none'; + } else { + elLightSection.style.display = 'block'; - elLightDiffuseRed.value = properties.diffuseColor.red; - elLightDiffuseGreen.value = properties.diffuseColor.green; - elLightDiffuseBlue.value = properties.diffuseColor.blue; + elLightDiffuseRed.value = properties.diffuseColor.red; + elLightDiffuseGreen.value = properties.diffuseColor.green; + elLightDiffuseBlue.value = properties.diffuseColor.blue; - elLightAmbientRed.value = properties.ambientColor.red; - elLightAmbientGreen.value = properties.ambientColor.green; - elLightAmbientBlue.value = properties.ambientColor.blue; + elLightAmbientRed.value = properties.ambientColor.red; + elLightAmbientGreen.value = properties.ambientColor.green; + elLightAmbientBlue.value = properties.ambientColor.blue; - elLightSpecularRed.value = properties.specularColor.red; - elLightSpecularGreen.value = properties.specularColor.green; - elLightSpecularBlue.value = properties.specularColor.blue; + elLightSpecularRed.value = properties.specularColor.red; + elLightSpecularGreen.value = properties.specularColor.green; + elLightSpecularBlue.value = properties.specularColor.blue; - elLightConstantAttenuation.value = properties.constantAttenuation; - elLightLinearAttenuation.value = properties.linearAttenuation; - elLightQuadraticAttenuation.value = properties.quadraticAttenuation; - elLightExponent.value = properties.exponent; - elLightCutoff.value = properties.cutoff; - } + elLightConstantAttenuation.value = properties.constantAttenuation; + elLightLinearAttenuation.value = properties.linearAttenuation; + elLightQuadraticAttenuation.value = properties.quadraticAttenuation; + elLightExponent.value = properties.exponent; + elLightCutoff.value = properties.cutoff; } } } From 849397288e07f8257653261ff585f816459edca6 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 5 Dec 2014 10:46:35 -0800 Subject: [PATCH 246/502] Update properties tool to be a resizable table --- examples/html/entityProperties.html | 521 +++++++++++++++------------- examples/html/style.css | 64 +++- 2 files changed, 331 insertions(+), 254 deletions(-) diff --git a/examples/html/entityProperties.html b/examples/html/entityProperties.html index 87ab066c5c..97e16fcf11 100644 --- a/examples/html/entityProperties.html +++ b/examples/html/entityProperties.html @@ -160,7 +160,7 @@ elLocked.checked = properties.locked; if (properties.locked) { - disableChildren(document.getElementById("properties"), 'input'); + disableChildren(document.getElementById("properties-table"), 'input'); elLocked.removeAttribute('disabled'); } else { enableChildren(document.getElementById("properties-table"), 'input'); @@ -345,7 +345,7 @@ elModelAnimationPlaying.addEventListener('change', createEmitCheckedPropertyUpdateFunction('animationIsPlaying')); elModelAnimationFPS.addEventListener('change', createEmitNumberPropertyUpdateFunction('animationFPS')); elModelAnimationFrame.addEventListener('change', createEmitNumberPropertyUpdateFunction('animationFrameIndex')); - + elTextText.addEventListener('change', createEmitTextPropertyUpdateFunction('text')); elTextLineHeight.addEventListener('change', createEmitNumberPropertyUpdateFunction('lineHeight')); @@ -361,6 +361,50 @@ elTextBackgroundColorGreen.addEventListener('change', textBackgroundColorChangeFunction); elTextBackgroundColorBlue.addEventListener('change', textBackgroundColorChangeFunction); + + var resizing = false; + var startX = 0; + var originalWidth = 0; + var resizeHandleWidth = 10; + + var col1 = document.querySelector("#col-label"); + + document.body.addEventListener('mousemove', function(event) { + if (resizing) { + var dX = event.x - startX; + col1.style.width = (originalWidth + dX) + "px"; + } + }); + document.body.addEventListener('mouseup', function(event) { + resizing = false; + }); + document.body.addEventListener('mouseleave', function(event) { + resizing = false; + }); + var els = document.querySelectorAll("#properties-table td"); + for (var i = 0; i < els.length; i++) { + var el = els[i]; + el.addEventListener('mousemove', function(event) { + if (!resizing) { + var distance = this.offsetWidth - event.offsetX; + if (distance < resizeHandleWidth) { + document.body.style.cursor = "ew-resize"; + } else { + document.body.style.cursor = "initial"; + } + } + }); + el.addEventListener('mousedown', function(event) { + var distance = this.offsetWidth - event.offsetX; + if (distance < resizeHandleWidth) { + startX = event.x; + originalWidth = this.offsetWidth; + resizing = true; + target = this; + } + }); + } + } @@ -368,272 +412,269 @@
-
-
- - - -
- -
- - + + + + + + + + + + + + + -
- - +
+ + + -
- - - X - Y - Z - -
+ + + + -
- - - X - Y - Z - -
+ + + + -
- - +
+ + + + + + + + + + + -
- - - X - Y - Z - -
-
- - +
+ + + + + + + + + + + + + + + -
- - - X - Y - Z - -
+ + + + -
- - +
+ + + -
- - +
+ + + -
- - +
+ + + -
- - +
+ + + -
-
- - - Red - Green - Blue - -
-
+ + + + -
-
- - - - -
-
- - - - -
-
- - - - -
-
- - - - -
-
- - - - -
-
-
-
- - - - -
-
- - - - -
-
- - - Red - Green - Blue - -
-
- - - Red - Green - Blue - -
-
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -
-
- - - - -
-
- - - Red - Green - Blue - -
-
- - - Red - Green - Blue - -
-
- - - Red - Green - Blue - -
-
- - - - -
-
- - - - -
-
- - - - -
-
- - - - -
-
- - - - -
-
- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Type + + +
Locked - - +
Visible - - +
Position +
X
+
Y
+
Z
+
Registration +
X
+
Y
+
Z
+
Width - - -
- - +
Height - - -
- - +
Depth - - +
Linear +
X
+
Y
+
Z
+
Linear Damping - - -
- - - Pitch - Roll - Yaw - -
-
- - +
Angular +
Pitch
+
Yaw
+
Roll
+
Angular Damping - - +
Gravity +
X
+
Y
+
Z
+
Mass - - +
Ignore For Collisions - - +
Collisions Will Move - - +
Lifetime - - +
Color +
Red
+
Green
+
Blue
+
Model URL + +
Animation URL + +
Animation Playing + +
Animation FPS + +
Animation Frame + +
Text + +
Line Height + +
Text Color +
Red
+
Green
+
Blue
+
Background Color +
Red
+
Green
+
Blue
+
Spot Light + +
Diffuse +
Red
+
Green
+
Blue
+
Ambient +
Red
+
Green
+
Blue
+
Specular +
Red
+
Green
+
Blue
+
Constant Attenuation + +
Linear Attenuation + +
Quadratic Attenuation + +
Exponent + +
Cutoff (degrees) + +
diff --git a/examples/html/style.css b/examples/html/style.css index b721c31b88..424933e14e 100644 --- a/examples/html/style.css +++ b/examples/html/style.css @@ -17,15 +17,6 @@ body { user-select: none; } -input { - line-height: 2; -} - -.input-left { - display: inline-block; - width: 20px; -} - .color-box { display: inline-block; width: 20px; @@ -63,7 +54,6 @@ input { .property-section label { font-weight: bold; - vertical-align: middle; } .property-section span { @@ -89,9 +79,10 @@ input[type=button] { font-size: .9em; } -input.coord { - width: 6em; - height: 2em; +input { + padding: 2px; + border: 1px solid #999; + background-color: #eee; } table#entity-table { @@ -105,7 +96,7 @@ table#entity-table { cursor: pointer; } -tr.selected { +#entity-table tr.selected { background-color: #AAA; } @@ -130,3 +121,48 @@ th#entity-type { th#entity-url { } + + +div.input-area { + display: inline-block; +} + +input { +} + + + +table#properties-table { + border: none; + border-collapse: collapse; + width: 100%; + background-color: #efefef; + font-family: Arial; + font-size: 12px; + table-layout: fixed; +} + +#properties-table tr { + border-bottom: 1px solid #e5e5e5; +} + +#properties-table td.label { + padding-right: 10px; + border-right: 1px solid #999; + text-align: right; + font-weight: bold; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + + vertical-align: middle; + height: 1.2em; +} + +#properties-table td { + padding: 5px 0px 5px 10px; +} + +col#col-label { + width: 130px; +} From f5a1c264925962abd32480bf148a6ffd03124448 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 5 Dec 2014 11:08:00 -0800 Subject: [PATCH 247/502] Add backgroundAlpha property to 2D and 3D text overlays --- examples/overlaysExample.js | 4 +++- interface/src/ui/overlays/Text3DOverlay.cpp | 10 ++++++++++ interface/src/ui/overlays/Text3DOverlay.h | 2 ++ interface/src/ui/overlays/TextOverlay.cpp | 9 +++++++++ interface/src/ui/overlays/TextOverlay.h | 3 +++ 5 files changed, 27 insertions(+), 1 deletion(-) diff --git a/examples/overlaysExample.js b/examples/overlaysExample.js index 0d47f7ca64..4aa5b1cd75 100644 --- a/examples/overlaysExample.js +++ b/examples/overlaysExample.js @@ -69,7 +69,8 @@ var text = Overlays.addOverlay("text", { topMargin: 4, leftMargin: 4, text: "Here is some text.\nAnd a second line.", - alpha: 0.7 + alpha: 0.7, + backgroundAlpha: 0.5 }); // This will create an image overlay, which starts out as invisible @@ -170,6 +171,7 @@ var clipboardPreview = Overlays.addOverlay("clipboard", { // Demonstrate retrieving overlay properties print("Text overlay text property value =\n" + Overlays.getProperty(text, "text")); print("Text overlay alpha =\n" + Overlays.getProperty(text, "alpha")); +print("Text overlay background alpha =\n" + Overlays.getProperty(text, "backgroundAlpha")); print("Text overlay visible =\n" + Overlays.getProperty(text, "visible")); print("Text overlay font size =\n" + Overlays.getProperty(text, "font").size); print("Text overlay anchor =\n" + Overlays.getProperty(text, "anchor")); diff --git a/interface/src/ui/overlays/Text3DOverlay.cpp b/interface/src/ui/overlays/Text3DOverlay.cpp index dbb423ad99..bd3ab47bce 100644 --- a/interface/src/ui/overlays/Text3DOverlay.cpp +++ b/interface/src/ui/overlays/Text3DOverlay.cpp @@ -16,12 +16,14 @@ #include "ui/TextRenderer.h" const xColor DEFAULT_BACKGROUND_COLOR = { 0, 0, 0 }; +const float DEFAULT_BACKGROUND_ALPHA = 0.7f; const float DEFAULT_MARGIN = 0.1f; const int FIXED_FONT_POINT_SIZE = 40; const float LINE_SCALE_RATIO = 1.2f; Text3DOverlay::Text3DOverlay() : _backgroundColor(DEFAULT_BACKGROUND_COLOR), + _backgroundAlpha(DEFAULT_BACKGROUND_ALPHA), _lineHeight(0.1f), _leftMargin(DEFAULT_MARGIN), _topMargin(DEFAULT_MARGIN), @@ -35,6 +37,7 @@ Text3DOverlay::Text3DOverlay(const Text3DOverlay* text3DOverlay) : Planar3DOverlay(text3DOverlay), _text(text3DOverlay->_text), _backgroundColor(text3DOverlay->_backgroundColor), + _backgroundAlpha(text3DOverlay->_backgroundAlpha), _lineHeight(text3DOverlay->_lineHeight), _leftMargin(text3DOverlay->_leftMargin), _topMargin(text3DOverlay->_topMargin), @@ -166,6 +169,10 @@ void Text3DOverlay::setProperties(const QScriptValue& properties) { } } + if (properties.property("backgroundAlpha").isValid()) { + _backgroundAlpha = properties.property("backgroundAlpha").toVariant().toFloat(); + } + if (properties.property("lineHeight").isValid()) { setLineHeight(properties.property("lineHeight").toVariant().toFloat()); } @@ -200,6 +207,9 @@ QScriptValue Text3DOverlay::getProperty(const QString& property) { if (property == "backgroundColor") { return xColorToScriptValue(_scriptEngine, _backgroundColor); } + if (property == "backgroundAlpha") { + return _backgroundAlpha; + } if (property == "lineHeight") { return _lineHeight; } diff --git a/interface/src/ui/overlays/Text3DOverlay.h b/interface/src/ui/overlays/Text3DOverlay.h index c624830ac8..d74131391a 100644 --- a/interface/src/ui/overlays/Text3DOverlay.h +++ b/interface/src/ui/overlays/Text3DOverlay.h @@ -37,6 +37,7 @@ public: float getBottomMargin() const { return _bottomMargin; } bool getIsFacingAvatar() const { return _isFacingAvatar; } xColor getBackgroundColor(); + float getBackgroundAlpha() const { return _backgroundAlpha; } // setters void setText(const QString& text) { _text = text; } @@ -59,6 +60,7 @@ private: QString _text; xColor _backgroundColor; + float _backgroundAlpha; float _lineHeight; float _leftMargin; float _topMargin; diff --git a/interface/src/ui/overlays/TextOverlay.cpp b/interface/src/ui/overlays/TextOverlay.cpp index 1d72cf7f05..68823d813d 100644 --- a/interface/src/ui/overlays/TextOverlay.cpp +++ b/interface/src/ui/overlays/TextOverlay.cpp @@ -19,6 +19,7 @@ TextOverlay::TextOverlay() : _backgroundColor(DEFAULT_BACKGROUND_COLOR), + _backgroundAlpha(DEFAULT_BACKGROUND_ALPHA), _leftMargin(DEFAULT_MARGIN), _topMargin(DEFAULT_MARGIN), _fontSize(DEFAULT_FONTSIZE) @@ -29,6 +30,7 @@ TextOverlay::TextOverlay(const TextOverlay* textOverlay) : Overlay2D(textOverlay), _text(textOverlay->_text), _backgroundColor(textOverlay->_backgroundColor), + _backgroundAlpha(textOverlay->_backgroundAlpha), _leftMargin(textOverlay->_leftMargin), _topMargin(textOverlay->_topMargin), _fontSize(textOverlay->_fontSize) @@ -125,6 +127,10 @@ void TextOverlay::setProperties(const QScriptValue& properties) { } } + if (properties.property("backgroundAlpha").isValid()) { + _backgroundAlpha = properties.property("backgroundAlpha").toVariant().toFloat(); + } + if (properties.property("leftMargin").isValid()) { setLeftMargin(properties.property("leftMargin").toVariant().toInt()); } @@ -150,6 +156,9 @@ QScriptValue TextOverlay::getProperty(const QString& property) { if (property == "backgroundColor") { return xColorToScriptValue(_scriptEngine, _backgroundColor); } + if (property == "backgroundAlpha") { + return _backgroundAlpha; + } if (property == "leftMargin") { return _leftMargin; } diff --git a/interface/src/ui/overlays/TextOverlay.h b/interface/src/ui/overlays/TextOverlay.h index 703e15be10..754faea2bc 100644 --- a/interface/src/ui/overlays/TextOverlay.h +++ b/interface/src/ui/overlays/TextOverlay.h @@ -28,6 +28,7 @@ #include "Overlay2D.h" const xColor DEFAULT_BACKGROUND_COLOR = { 0, 0, 0 }; +const float DEFAULT_BACKGROUND_ALPHA = 0.7f; const int DEFAULT_MARGIN = 10; const int DEFAULT_FONTSIZE = 11; const int DEFAULT_FONT_WEIGHT = 50; @@ -46,6 +47,7 @@ public: int getLeftMargin() const { return _leftMargin; } int getTopMargin() const { return _topMargin; } xColor getBackgroundColor(); + float getBackgroundAlpha() const { return _backgroundAlpha; } // setters void setText(const QString& text) { _text = text; } @@ -62,6 +64,7 @@ public: private: QString _text; xColor _backgroundColor; + float _backgroundAlpha; int _leftMargin; int _topMargin; int _fontSize; From bd6ea9b4e782930280933ce02f5cbd338ffc20e4 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 5 Dec 2014 11:18:03 -0800 Subject: [PATCH 248/502] Render with backgroundAlpha property --- interface/src/ui/overlays/Text3DOverlay.cpp | 5 +++-- interface/src/ui/overlays/TextOverlay.cpp | 6 +++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/interface/src/ui/overlays/Text3DOverlay.cpp b/interface/src/ui/overlays/Text3DOverlay.cpp index bd3ab47bce..2e80fae8a0 100644 --- a/interface/src/ui/overlays/Text3DOverlay.cpp +++ b/interface/src/ui/overlays/Text3DOverlay.cpp @@ -91,8 +91,8 @@ void Text3DOverlay::render(RenderArgs* args) { const float MAX_COLOR = 255.0f; xColor backgroundColor = getBackgroundColor(); - float alpha = getAlpha(); - glColor4f(backgroundColor.red / MAX_COLOR, backgroundColor.green / MAX_COLOR, backgroundColor.blue / MAX_COLOR, alpha); + glColor4f(backgroundColor.red / MAX_COLOR, backgroundColor.green / MAX_COLOR, backgroundColor.blue / MAX_COLOR, + getBackgroundAlpha()); glm::vec2 dimensions = getDimensions(); glm::vec2 halfDimensions = dimensions * 0.5f; @@ -127,6 +127,7 @@ void Text3DOverlay::render(RenderArgs* args) { enableClipPlane(GL_CLIP_PLANE3, 0.0f, 1.0f, 0.0f, -clipMinimum.y); glColor3f(_color.red / MAX_COLOR, _color.green / MAX_COLOR, _color.blue / MAX_COLOR); + float alpha = getAlpha(); QStringList lines = _text.split("\n"); int lineOffset = maxHeight; foreach(QString thisLine, lines) { diff --git a/interface/src/ui/overlays/TextOverlay.cpp b/interface/src/ui/overlays/TextOverlay.cpp index 68823d813d..272c9bc916 100644 --- a/interface/src/ui/overlays/TextOverlay.cpp +++ b/interface/src/ui/overlays/TextOverlay.cpp @@ -65,11 +65,10 @@ void TextOverlay::render(RenderArgs* args) { return; // do nothing if we're not visible } - const float MAX_COLOR = 255.0f; xColor backgroundColor = getBackgroundColor(); - float alpha = getAlpha(); - glColor4f(backgroundColor.red / MAX_COLOR, backgroundColor.green / MAX_COLOR, backgroundColor.blue / MAX_COLOR, alpha); + glColor4f(backgroundColor.red / MAX_COLOR, backgroundColor.green / MAX_COLOR, backgroundColor.blue / MAX_COLOR, + getBackgroundAlpha()); glBegin(GL_QUADS); glVertex2f(_bounds.left(), _bounds.top()); @@ -87,6 +86,7 @@ void TextOverlay::render(RenderArgs* args) { int y = _bounds.top() + _topMargin + topAdjust; glColor3f(_color.red / MAX_COLOR, _color.green / MAX_COLOR, _color.blue / MAX_COLOR); + float alpha = getAlpha(); QStringList lines = _text.split("\n"); int lineOffset = 0; foreach(QString thisLine, lines) { From a6b86da47af2f75ec013d6e3eaa6d08793629f7c Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 5 Dec 2014 11:31:27 -0800 Subject: [PATCH 249/502] basics of triangle picking working for models --- examples/developerMenuItems.js | 1 + interface/src/Menu.h | 1 + .../entities/RenderableModelEntityItem.cpp | 9 +- interface/src/renderer/Model.cpp | 148 +++++++++++++++++- interface/src/renderer/Model.h | 12 +- interface/src/ui/overlays/Base3DOverlay.cpp | 2 +- interface/src/ui/overlays/Base3DOverlay.h | 4 +- .../src/ui/overlays/BillboardOverlay.cpp | 2 +- interface/src/ui/overlays/BillboardOverlay.h | 2 +- interface/src/ui/overlays/Circle3DOverlay.cpp | 2 +- interface/src/ui/overlays/Circle3DOverlay.h | 2 +- interface/src/ui/overlays/ModelOverlay.cpp | 4 +- interface/src/ui/overlays/ModelOverlay.h | 4 +- interface/src/ui/overlays/Planar3DOverlay.cpp | 2 +- interface/src/ui/overlays/Planar3DOverlay.h | 2 +- interface/src/ui/overlays/Volume3DOverlay.cpp | 2 +- interface/src/ui/overlays/Volume3DOverlay.h | 2 +- libraries/entities/src/EntityTreeElement.cpp | 23 ++- libraries/entities/src/EntityTreeElement.h | 2 +- libraries/fbx/src/FBXReader.cpp | 1 + libraries/fbx/src/FBXReader.h | 1 + libraries/octree/src/OctreeElement.cpp | 45 ++++-- libraries/octree/src/OctreeElement.h | 2 +- libraries/shared/src/GeometryUtil.cpp | 46 ++++++ libraries/shared/src/GeometryUtil.h | 16 ++ 25 files changed, 298 insertions(+), 39 deletions(-) diff --git a/examples/developerMenuItems.js b/examples/developerMenuItems.js index 221975c9c8..0d2c4895ea 100644 --- a/examples/developerMenuItems.js +++ b/examples/developerMenuItems.js @@ -24,6 +24,7 @@ function setupMenus() { Menu.addMenuItem({ menuName: "Developer > Entities", menuItemName: "Disable Light Entities", isCheckable: true, isChecked: false }); Menu.addMenuItem({ menuName: "Developer > Entities", menuItemName: "Don't Attempt to Reduce Material Switches", isCheckable: true, isChecked: false }); Menu.addMenuItem({ menuName: "Developer > Entities", menuItemName: "Don't Attempt Render Entities as Scene", isCheckable: true, isChecked: false }); + Menu.addMenuItem({ menuName: "Developer > Entities", menuItemName: "Pick Against Model Triangles", isCheckable: true, isChecked: false }); Menu.addMenu("Developer > Entities > Culling"); Menu.addMenuItem({ menuName: "Developer > Entities > Culling", menuItemName: "Don't Cull Out Of View Mesh Parts", isCheckable: true, isChecked: false }); Menu.addMenuItem({ menuName: "Developer > Entities > Culling", menuItemName: "Don't Cull Too Small Mesh Parts", isCheckable: true, isChecked: false }); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 0d46c4020d..520c83177e 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -432,6 +432,7 @@ namespace MenuOption { const QString OldVoxelCullingMode = "Old Voxel Culling Mode"; const QString Pair = "Pair"; const QString PasteToVoxel = "Paste to Voxel..."; + const QString PickAgainstModelTriangles = "Pick Against Model Triangles"; const QString PipelineWarnings = "Log Render Pipeline Warnings"; const QString Preferences = "Preferences..."; const QString Quit = "Quit"; diff --git a/interface/src/entities/RenderableModelEntityItem.cpp b/interface/src/entities/RenderableModelEntityItem.cpp index ccd6622856..6bc6f52782 100644 --- a/interface/src/entities/RenderableModelEntityItem.cpp +++ b/interface/src/entities/RenderableModelEntityItem.cpp @@ -133,9 +133,6 @@ void RenderableModelEntityItem::render(RenderArgs* args) { getModel(renderer); } - - - if (_model) { // handle animations.. if (hasAnimation()) { @@ -175,7 +172,7 @@ void RenderableModelEntityItem::render(RenderArgs* args) { // TODO: this is the majority of model render time. And rendering of a cube model vs the basic Box render // is significantly more expensive. Is there a way to call this that doesn't cost us as much? PerformanceTimer perfTimer("model->render"); - bool dontRenderAsScene = Menu::getInstance()->isOptionChecked(MenuOption::DontRenderEntitiesAsScene); + bool dontRenderAsScene = true; // Menu::getInstance()->isOptionChecked(MenuOption::DontRenderEntitiesAsScene); if (dontRenderAsScene) { _model->render(alpha, modelRenderMode, args); } else { @@ -270,10 +267,14 @@ bool RenderableModelEntityItem::findDetailedRayIntersection(const glm::vec3& ori qDebug() << " originInMeters:" << originInMeters; QString extraInfo; float localDistance; + bool intersectsModel = _model->findRayIntersectionAgainstSubMeshes(originInMeters, direction, localDistance, face, extraInfo); if (intersectsModel) { + // NOTE: findRayIntersectionAgainstSubMeshes() does work in meters, but we're expected to return + // results in tree scale. distance = localDistance / (float)TREE_SCALE; + qDebug() << " --hit this mode -- returning distance:" << distance; } return intersectsModel; // we only got here if we intersected our non-aabox diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 19176c4833..6b398284a3 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -54,6 +54,7 @@ Model::Model(QObject* parent) : _blendNumber(0), _appliedBlendNumber(0), _calculatedMeshBoxesValid(false), + _calculatedMeshTrianglesValid(false), _meshGroupsKnown(false) { // we may have been created in the network thread, but we live in the main thread @@ -516,7 +517,7 @@ void Model::setJointStates(QVector states) { } bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const glm::vec3& direction, - float& distance, BoxFace& face, QString& extraInfo) const { + float& distance, BoxFace& face, QString& extraInfo) { bool intersectedSomething = false; @@ -524,8 +525,12 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g if (!isActive()) { return intersectedSomething; } + + bool pickAgainstTriangles = Menu::getInstance()->isOptionChecked(MenuOption::PickAgainstModelTriangles); qDebug() << "Model::findRayIntersectionAgainstSubMeshes()..."; + qDebug() << " origin:" << origin; + qDebug() << " direction:" << direction; // extents is the entity relative, scaled, centered extents of the entity glm::vec3 position = _translation; @@ -538,31 +543,58 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g qDebug() << " modelExtents:" << modelExtents; glm::vec3 dimensions = modelExtents.maximum - modelExtents.minimum; - glm::vec3 corner = dimensions * -0.5f; // since we're going to do the ray picking in the model frame of reference + glm::vec3 corner = dimensions * _registrationPoint; // since we're going to do the ray picking in the model frame of reference AABox overlayFrameBox(corner, dimensions); qDebug() << " overlayFrameBox:" << overlayFrameBox; glm::vec3 modelFrameOrigin = glm::vec3(worldToModelMatrix * glm::vec4(origin, 1.0f)); glm::vec3 modelFrameDirection = glm::vec3(worldToModelMatrix * glm::vec4(direction, 0.0f)); + qDebug() << " modelFrameOrigin:" << modelFrameOrigin; + qDebug() << " modelFrameDirection:" << modelFrameDirection; // we can use the AABox's ray intersection by mapping our origin and direction into the model frame // and testing intersection there. if (overlayFrameBox.findRayIntersection(modelFrameOrigin, modelFrameDirection, distance, face)) { float bestDistance = std::numeric_limits::max(); + float bestTriangleDistance = std::numeric_limits::max(); + bool someTriangleHit = false; + float distanceToSubMesh; BoxFace subMeshFace; int subMeshIndex = 0; - + + const FBXGeometry& geometry = _geometry->getFBXGeometry(); // If we hit the models box, then consider the submeshes... foreach(const AABox& subMeshBox, _calculatedMeshBoxes) { - const FBXGeometry& geometry = _geometry->getFBXGeometry(); qDebug() << "subMeshBox[" << subMeshIndex <<"]:" << subMeshBox; if (subMeshBox.findRayIntersection(origin, direction, distanceToSubMesh, subMeshFace)) { if (distanceToSubMesh < bestDistance) { + + if (pickAgainstTriangles) { + if (!_calculatedMeshTrianglesValid) { + recalcuateMeshBoxes(); + } + // check our triangles here.... + const QVector& meshTriangles = _calculatedMeshTriangles[subMeshIndex]; + int t = 0; + foreach (const Triangle& triangle, meshTriangles) { + //qDebug() << "triangle["<< t <<"] :" << triangle.v0 << ", "<< triangle.v1 << ", " << triangle.v2; + t++; + + float thisTriangleDistance; + if (findRayTrianlgeIntersection(origin, direction, triangle, thisTriangleDistance)) { + if (thisTriangleDistance < bestTriangleDistance) { + bestTriangleDistance = thisTriangleDistance; + someTriangleHit = true; + } + } + } + } + bestDistance = distanceToSubMesh; intersectedSomething = true; face = subMeshFace; @@ -571,6 +603,27 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g } subMeshIndex++; } + + // if we were asked to pick against triangles, and we didn't hit one, then we + // do not consider this model to be hit at all. + if (pickAgainstTriangles && !someTriangleHit) { + intersectedSomething = false; + } + qDebug() << "pickAgainstTriangles:" << pickAgainstTriangles; + qDebug() << "someTriangleHit:" << someTriangleHit; + qDebug() << "bestTriangleDistance:" << bestTriangleDistance; + qDebug() << "bestDistance:" << bestDistance; + + if (intersectedSomething) { + qDebug() << " --- we hit this model --- "; + + if (pickAgainstTriangles) { + distance = bestTriangleDistance; + } else { + distance = bestDistance; + } + qDebug() << "distance:" << distance; + } return intersectedSomething; } @@ -579,17 +632,92 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g } void Model::recalcuateMeshBoxes() { - if (!_calculatedMeshBoxesValid) { + bool pickAgainstTriangles = Menu::getInstance()->isOptionChecked(MenuOption::PickAgainstModelTriangles); + bool calculatedMeshTrianglesNeeded = pickAgainstTriangles && !_calculatedMeshTrianglesValid; + + if (!_calculatedMeshBoxesValid || calculatedMeshTrianglesNeeded) { + qDebug() << "Model::recalcuateMeshBoxes()"; PerformanceTimer perfTimer("calculatedMeshBoxes"); const FBXGeometry& geometry = _geometry->getFBXGeometry(); int numberOfMeshes = geometry.meshes.size(); _calculatedMeshBoxes.resize(numberOfMeshes); + _calculatedMeshTriangles.clear(); for (int i = 0; i < numberOfMeshes; i++) { const FBXMesh& mesh = geometry.meshes.at(i); Extents scaledMeshExtents = calculateScaledOffsetExtents(mesh.meshExtents); + + qDebug() << "mesh.meshExtents["< thisMeshTriangles; + for (int j = 0; j < mesh.parts.size(); j++) { + const FBXMeshPart& part = mesh.parts.at(j); + + const int INDICES_PER_TRIANGLE = 3; + const int INDICES_PER_QUAD = 4; + + if (part.quadIndices.size() > 0) { + int numberOfQuads = part.quadIndices.size() / INDICES_PER_QUAD; + qDebug() << "numberOfQuads:" << numberOfQuads; + int vIndex = 0; + for (int q = 0; q < numberOfQuads; q++) { + int i0 = part.quadIndices[vIndex++]; + int i1 = part.quadIndices[vIndex++]; + int i2 = part.quadIndices[vIndex++]; + int i3 = part.quadIndices[vIndex++]; + + glm::vec3 v0 = calculateScaledOffsetPoint(glm::vec3(mesh.modelTransform * glm::vec4(mesh.vertices[i0], 1.0f))); + glm::vec3 v1 = calculateScaledOffsetPoint(glm::vec3(mesh.modelTransform * glm::vec4(mesh.vertices[i1], 1.0f))); + glm::vec3 v2 = calculateScaledOffsetPoint(glm::vec3(mesh.modelTransform * glm::vec4(mesh.vertices[i2], 1.0f))); + glm::vec3 v3 = calculateScaledOffsetPoint(glm::vec3(mesh.modelTransform * glm::vec4(mesh.vertices[i3], 1.0f))); + + Triangle tri1 = { v0, v1, v3 }; + Triangle tri2 = { v1, v2, v3 }; + + //qDebug() << "quad["<< q <<"].t1 :" << v0 << ", "<< v1 << ", " << v3; + //qDebug() << "quad["<< q <<"].t2 :" << v1 << ", "<< v2 << ", " << v3; + + thisMeshTriangles.push_back(tri1); + thisMeshTriangles.push_back(tri2); + } + } + + if (part.triangleIndices.size() > 0) { + int numberOfTris = part.triangleIndices.size() / INDICES_PER_TRIANGLE; + qDebug() << "numberOfTris:" << numberOfTris; + int vIndex = 0; + for (int t = 0; t < numberOfTris; t++) { + int i0 = part.triangleIndices[vIndex++]; + int i1 = part.triangleIndices[vIndex++]; + int i2 = part.triangleIndices[vIndex++]; + + glm::vec3 v0 = calculateScaledOffsetPoint(glm::vec3(mesh.modelTransform * glm::vec4(mesh.vertices[i0], 1.0f))); + glm::vec3 v1 = calculateScaledOffsetPoint(glm::vec3(mesh.modelTransform * glm::vec4(mesh.vertices[i1], 1.0f))); + glm::vec3 v2 = calculateScaledOffsetPoint(glm::vec3(mesh.modelTransform * glm::vec4(mesh.vertices[i2], 1.0f))); + + Triangle tri = { v0, v1, v2 }; + + //qDebug() << "triangle["<< t <<"] :" << v0 << ", " << v1 << ", " << v2; + + thisMeshTriangles.push_back(tri); + } + } + } + + _calculatedMeshTriangles.push_back(thisMeshTriangles); + qDebug() << "------------------------------------------------------------------------------"; + } + } _calculatedMeshBoxesValid = true; + _calculatedMeshTrianglesValid = pickAgainstTriangles; } } @@ -851,6 +979,15 @@ Extents Model::calculateScaledOffsetExtents(const Extents& extents) const { return translatedExtents; } +glm::vec3 Model::calculateScaledOffsetPoint(const glm::vec3& point) const { + // we need to include any fst scaling, translation, and rotation, which is captured in the offset matrix + glm::vec3 offsetPoint = glm::vec3(_geometry->getFBXGeometry().offset * glm::vec4(point, 1.0f)); + glm::vec3 scaledPoint = ((offsetPoint + _offset) * _scale); + glm::vec3 rotatedPoint = _rotation * scaledPoint; + glm::vec3 translatedPoint = rotatedPoint + _translation; + return translatedPoint; +} + bool Model::getJointState(int index, glm::quat& rotation) const { if (index == -1 || index >= _jointStates.size()) { @@ -1149,6 +1286,7 @@ void Model::simulate(float deltaTime, bool fullUpdate) { if (isActive() && fullUpdate) { _calculatedMeshBoxesValid = false; // if we have to simulate, we need to assume our mesh boxes are all invalid + _calculatedMeshTrianglesValid = false; // check for scale to fit if (_scaleToFit && !_scaledToFit) { diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index b16cf11b09..406622e6a8 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -19,6 +19,7 @@ #include "Transform.h" #include #include +#include #include #include "AnimationHandle.h" @@ -34,7 +35,6 @@ class Shape; #include "RenderArgs.h" class ViewFrustum; - #include "gpu/Stream.h" #include "gpu/Batch.h" @@ -119,6 +119,9 @@ public: /// Returns the scaled equivalent of some extents in model space. Extents calculateScaledOffsetExtents(const Extents& extents) const; + /// Returns the scaled equivalent of a point in model space. + glm::vec3 calculateScaledOffsetPoint(const glm::vec3& point) const; + /// Returns a reference to the shared geometry. const QSharedPointer& getGeometry() const { return _geometry; } @@ -194,7 +197,7 @@ public: { _geometry->setTextureWithNameToURL(name, url); } bool findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const glm::vec3& direction, - float& distance, BoxFace& face, QString& extraInfo) const; + float& distance, BoxFace& face, QString& extraInfo); protected: QSharedPointer _geometry; @@ -361,8 +364,11 @@ private: static void initSkinProgram(ProgramObject& program, SkinLocations& locations, int specularTextureUnit = 1); - QVector _calculatedMeshBoxes; + QVector _calculatedMeshBoxes; // world coordinate AABoxes for all sub mesh boxes bool _calculatedMeshBoxesValid; + + QVector< QVector > _calculatedMeshTriangles; // world coordinate triangles for all sub meshes + bool _calculatedMeshTrianglesValid; void recalcuateMeshBoxes(); diff --git a/interface/src/ui/overlays/Base3DOverlay.cpp b/interface/src/ui/overlays/Base3DOverlay.cpp index 55b4c88812..a9588cd7a3 100644 --- a/interface/src/ui/overlays/Base3DOverlay.cpp +++ b/interface/src/ui/overlays/Base3DOverlay.cpp @@ -167,7 +167,7 @@ QScriptValue Base3DOverlay::getProperty(const QString& property) { } bool Base3DOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - float& distance, BoxFace& face) const { + float& distance, BoxFace& face) { return false; } diff --git a/interface/src/ui/overlays/Base3DOverlay.h b/interface/src/ui/overlays/Base3DOverlay.h index d57f9731c4..b5314bd6d3 100644 --- a/interface/src/ui/overlays/Base3DOverlay.h +++ b/interface/src/ui/overlays/Base3DOverlay.h @@ -50,10 +50,10 @@ public: virtual void setProperties(const QScriptValue& properties); virtual QScriptValue getProperty(const QString& property); - virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face) const; + virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face); virtual bool findRayIntersectionExtraInfo(const glm::vec3& origin, const glm::vec3& direction, - float& distance, BoxFace& face, QString& extraInfo) const { + float& distance, BoxFace& face, QString& extraInfo) { return findRayIntersection(origin, direction, distance, face); } diff --git a/interface/src/ui/overlays/BillboardOverlay.cpp b/interface/src/ui/overlays/BillboardOverlay.cpp index 5fbad7839a..f9ad7fdb38 100644 --- a/interface/src/ui/overlays/BillboardOverlay.cpp +++ b/interface/src/ui/overlays/BillboardOverlay.cpp @@ -213,7 +213,7 @@ void BillboardOverlay::replyFinished() { } bool BillboardOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - float& distance, BoxFace& face) const { + float& distance, BoxFace& face) { if (_billboardTexture) { float maxSize = glm::max(_fromImage.width(), _fromImage.height()); diff --git a/interface/src/ui/overlays/BillboardOverlay.h b/interface/src/ui/overlays/BillboardOverlay.h index be947acf98..03daef934d 100644 --- a/interface/src/ui/overlays/BillboardOverlay.h +++ b/interface/src/ui/overlays/BillboardOverlay.h @@ -35,7 +35,7 @@ public: void setClipFromSource(const QRect& bounds) { _fromImage = bounds; } virtual QScriptValue getProperty(const QString& property); - virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face) const; + virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face); virtual BillboardOverlay* createClone() const; diff --git a/interface/src/ui/overlays/Circle3DOverlay.cpp b/interface/src/ui/overlays/Circle3DOverlay.cpp index d19297b589..68d589d20b 100644 --- a/interface/src/ui/overlays/Circle3DOverlay.cpp +++ b/interface/src/ui/overlays/Circle3DOverlay.cpp @@ -355,7 +355,7 @@ QScriptValue Circle3DOverlay::getProperty(const QString& property) { bool Circle3DOverlay::findRayIntersection(const glm::vec3& origin, - const glm::vec3& direction, float& distance, BoxFace& face) const { + const glm::vec3& direction, float& distance, BoxFace& face) { bool intersects = Planar3DOverlay::findRayIntersection(origin, direction, distance, face); if (intersects) { diff --git a/interface/src/ui/overlays/Circle3DOverlay.h b/interface/src/ui/overlays/Circle3DOverlay.h index b428be7a43..92fdf54c82 100644 --- a/interface/src/ui/overlays/Circle3DOverlay.h +++ b/interface/src/ui/overlays/Circle3DOverlay.h @@ -48,7 +48,7 @@ public: void setMajorTickMarksColor(const xColor& value) { _majorTickMarksColor = value; } void setMinorTickMarksColor(const xColor& value) { _minorTickMarksColor = value; } - virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face) const; + virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face); virtual Circle3DOverlay* createClone() const; diff --git a/interface/src/ui/overlays/ModelOverlay.cpp b/interface/src/ui/overlays/ModelOverlay.cpp index 60049e0b3b..ecce137f4d 100644 --- a/interface/src/ui/overlays/ModelOverlay.cpp +++ b/interface/src/ui/overlays/ModelOverlay.cpp @@ -170,14 +170,14 @@ QScriptValue ModelOverlay::getProperty(const QString& property) { } bool ModelOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - float& distance, BoxFace& face) const { + float& distance, BoxFace& face) { QString subMeshNameTemp; return _model.findRayIntersectionAgainstSubMeshes(origin, direction, distance, face, subMeshNameTemp); } bool ModelOverlay::findRayIntersectionExtraInfo(const glm::vec3& origin, const glm::vec3& direction, - float& distance, BoxFace& face, QString& extraInfo) const { + float& distance, BoxFace& face, QString& extraInfo) { return _model.findRayIntersectionAgainstSubMeshes(origin, direction, distance, face, extraInfo); } diff --git a/interface/src/ui/overlays/ModelOverlay.h b/interface/src/ui/overlays/ModelOverlay.h index 80b52ea27e..567498feb5 100644 --- a/interface/src/ui/overlays/ModelOverlay.h +++ b/interface/src/ui/overlays/ModelOverlay.h @@ -26,9 +26,9 @@ public: virtual void render(RenderArgs* args); virtual void setProperties(const QScriptValue& properties); virtual QScriptValue getProperty(const QString& property); - virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face) const; + virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face); virtual bool findRayIntersectionExtraInfo(const glm::vec3& origin, const glm::vec3& direction, - float& distance, BoxFace& face, QString& extraInfo) const; + float& distance, BoxFace& face, QString& extraInfo); virtual ModelOverlay* createClone() const; diff --git a/interface/src/ui/overlays/Planar3DOverlay.cpp b/interface/src/ui/overlays/Planar3DOverlay.cpp index a8288b241c..628ff6a7dc 100644 --- a/interface/src/ui/overlays/Planar3DOverlay.cpp +++ b/interface/src/ui/overlays/Planar3DOverlay.cpp @@ -92,7 +92,7 @@ QScriptValue Planar3DOverlay::getProperty(const QString& property) { } bool Planar3DOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - float& distance, BoxFace& face) const { + float& distance, BoxFace& face) { RayIntersectionInfo rayInfo; rayInfo._rayStart = origin; diff --git a/interface/src/ui/overlays/Planar3DOverlay.h b/interface/src/ui/overlays/Planar3DOverlay.h index d34fe44ebc..9355265f80 100644 --- a/interface/src/ui/overlays/Planar3DOverlay.h +++ b/interface/src/ui/overlays/Planar3DOverlay.h @@ -39,7 +39,7 @@ public: virtual void setProperties(const QScriptValue& properties); virtual QScriptValue getProperty(const QString& property); - virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face) const; + virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face); protected: glm::vec2 _dimensions; diff --git a/interface/src/ui/overlays/Volume3DOverlay.cpp b/interface/src/ui/overlays/Volume3DOverlay.cpp index c4192a15b2..40fea5c8c9 100644 --- a/interface/src/ui/overlays/Volume3DOverlay.cpp +++ b/interface/src/ui/overlays/Volume3DOverlay.cpp @@ -100,7 +100,7 @@ QScriptValue Volume3DOverlay::getProperty(const QString& property) { } bool Volume3DOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - float& distance, BoxFace& face) const { + float& distance, BoxFace& face) { // extents is the entity relative, scaled, centered extents of the entity glm::vec3 position = getPosition(); diff --git a/interface/src/ui/overlays/Volume3DOverlay.h b/interface/src/ui/overlays/Volume3DOverlay.h index 005646c036..7938641a8f 100644 --- a/interface/src/ui/overlays/Volume3DOverlay.h +++ b/interface/src/ui/overlays/Volume3DOverlay.h @@ -41,7 +41,7 @@ public: virtual void setProperties(const QScriptValue& properties); virtual QScriptValue getProperty(const QString& property); - virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face) const; + virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face); protected: glm::vec3 _dimensions; diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index e18f79276e..e0ebe47412 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -475,7 +475,7 @@ bool EntityTreeElement::bestFitBounds(const glm::vec3& minPoint, const glm::vec3 bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, - void** intersectedObject) { + void** intersectedObject, float distanceToElementCube) { // only called if we do intersect our bounding cube, but find if we actually intersect with entities... @@ -509,15 +509,32 @@ bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, con // we can use the AABox's ray intersection by mapping our origin and direction into the entity frame // and testing intersection there. + qDebug() << "EntityTreeElement::findDetailedRayIntersection()...."; + qDebug() << " origin:" << origin; + qDebug() << " checking entity:" << entity->getEntityItemID() << "-" << qPrintable(EntityTypes::getEntityTypeName(entity->getType())); + qDebug() << " distance:" << distance; + if (entityFrameBox.findRayIntersection(entityFrameOrigin, entityFrameDirection, localDistance, localFace)) { + qDebug() << " localDistance:" << localDistance; + if (localDistance < distance) { + qDebug() << " localDistance < distance... continue..."; + // now ask the entity if we actually intersect if (entity->supportsDetailedRayIntersection()) { + + qDebug() << " entity->supportsDetailedRayIntersection()...."; if (entity->findDetailedRayIntersection(origin, direction, keepSearching, element, localDistance, localFace, intersectedObject)) { + + qDebug() << " localDistance (detailed):" << localDistance; if (localDistance < distance) { + + qDebug() << " localDistance < distance..."; + qDebug() << " CHOOSING THIS ONE ---> " << entity->getEntityItemID() << "-" << qPrintable(EntityTypes::getEntityTypeName(entity->getType())); + distance = localDistance; face = localFace; *intersectedObject = (void*)entity; @@ -527,6 +544,10 @@ bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, con } else { // if the entity type doesn't support a detailed intersection, then just return the non-AABox results if (localDistance < distance) { + + qDebug() << " localDistance < distance..."; + qDebug() << " CHOOSING THIS ONE ---> " << entity->getEntityItemID() << "-" << qPrintable(EntityTypes::getEntityTypeName(entity->getType())); + distance = localDistance; face = localFace; *intersectedObject = (void*)entity; diff --git a/libraries/entities/src/EntityTreeElement.h b/libraries/entities/src/EntityTreeElement.h index ab3754749b..e59b35189f 100644 --- a/libraries/entities/src/EntityTreeElement.h +++ b/libraries/entities/src/EntityTreeElement.h @@ -137,7 +137,7 @@ public: virtual bool canRayIntersect() const { return hasEntities(); } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, - void** intersectedObject); + void** intersectedObject, float distanceToElementCube); virtual bool findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration, void** penetratedObject) const; diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 8126463d27..d52d342d78 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -2044,6 +2044,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, extracted.mesh.meshExtents.minimum = glm::min(extracted.mesh.meshExtents.minimum, transformedVertex); extracted.mesh.meshExtents.maximum = glm::max(extracted.mesh.meshExtents.maximum, transformedVertex); + extracted.mesh.modelTransform = modelTransform; } // look for textures, material properties diff --git a/libraries/fbx/src/FBXReader.h b/libraries/fbx/src/FBXReader.h index c34a9677a6..659893c128 100644 --- a/libraries/fbx/src/FBXReader.h +++ b/libraries/fbx/src/FBXReader.h @@ -149,6 +149,7 @@ public: QVector clusters; Extents meshExtents; + glm::mat4 modelTransform; bool isEye; diff --git a/libraries/octree/src/OctreeElement.cpp b/libraries/octree/src/OctreeElement.cpp index e5db8b24f8..e085298c33 100644 --- a/libraries/octree/src/OctreeElement.cpp +++ b/libraries/octree/src/OctreeElement.cpp @@ -1339,28 +1339,54 @@ bool OctreeElement::findRayIntersection(const glm::vec3& origin, const glm::vec3 keepSearching = true; // assume that we will continue searching after this. AACube cube = getAACube(); - float localDistance; + float distanceToElementCube = std::numeric_limits::max(); + float distanceToElementDetails = distance; BoxFace localFace; + qDebug() << "OctreeElement::findRayIntersection()...."; + qDebug() << " origin:" << origin; + qDebug() << " checking element:" << cube; + qDebug() << " distance:" << distance; + // if the ray doesn't intersect with our cube, we can stop searching! - if (!cube.findRayIntersection(origin, direction, localDistance, localFace)) { + if (!cube.findRayIntersection(origin, direction, distanceToElementCube, localFace)) { + qDebug() << " didn't intersect cube... done searching..."; keepSearching = false; // no point in continuing to search return false; // we did not intersect } + qDebug() << " distanceToElementCube:" << distanceToElementCube; + // by default, we only allow intersections with leaves with content if (!canRayIntersect()) { return false; // we don't intersect with non-leaves, and we keep searching } // we did hit this element, so calculate appropriate distances - localDistance *= TREE_SCALE; - if (localDistance < distance) { + //localDistance *= TREE_SCALE; + + // if the distance to the element cube is not less than the current best distance, then it's not possible + // for any details inside the cube to be closer so we don't need to consider them. + if (distanceToElementCube < distance) { + + qDebug() << " distanceToElementCube < distance:" << (distanceToElementCube < distance); + qDebug() << " continue.... call... findDetailedRayIntersection()..."; + //qDebug() << " distanceToElementCube < distance -- continue.... call... findDetailedRayIntersection()..."; + if (findDetailedRayIntersection(origin, direction, keepSearching, - element, distance, face, intersectedObject)) { - distance = localDistance; - face = localFace; - return true; + element, distanceToElementDetails, face, intersectedObject, distanceToElementCube)) { + + qDebug() << " findDetailedRayIntersection() -- intersected something"; + if (distanceToElementDetails < distance) { + qDebug() << " distanceToElementDetails < distance -- THIS ONE IS GOOD -------"; + + distance = distanceToElementDetails; + face = localFace; + + qDebug() << " distance:" << distance << " -- THIS ONE IS GOOD -------"; + + return true; + } } } return false; @@ -1368,11 +1394,12 @@ bool OctreeElement::findRayIntersection(const glm::vec3& origin, const glm::vec3 bool OctreeElement::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, - void** intersectedObject) { + void** intersectedObject, float distanceToElementCube) { // we did hit this element, so calculate appropriate distances if (hasContent()) { element = this; + distance = distanceToElementCube; if (intersectedObject) { *intersectedObject = this; } diff --git a/libraries/octree/src/OctreeElement.h b/libraries/octree/src/OctreeElement.h index 2bd5e3ae1e..9161a9b171 100644 --- a/libraries/octree/src/OctreeElement.h +++ b/libraries/octree/src/OctreeElement.h @@ -123,7 +123,7 @@ public: virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, - void** intersectedObject); + void** intersectedObject, float distanceToElementCube); virtual bool findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration, void** penetratedObject) const; diff --git a/libraries/shared/src/GeometryUtil.cpp b/libraries/shared/src/GeometryUtil.cpp index 1b6472a18f..c064630f83 100644 --- a/libraries/shared/src/GeometryUtil.cpp +++ b/libraries/shared/src/GeometryUtil.cpp @@ -252,6 +252,52 @@ bool findRayCapsuleIntersection(const glm::vec3& origin, const glm::vec3& direct return true; } +bool findRayTrianlgeIntersection(const glm::vec3& origin, const glm::vec3& direction, + const glm::vec3& v0, const glm::vec3& v1, const glm::vec3& v2, float& distance) { + + glm::vec3 e1, e2, h, s, q; + float a, f, u, v, t; + + e1 = v1 - v0; + e2 = v2 - v0; + + h = glm::cross(direction, e2); + a = glm::dot(e1, h); + + if (a > -0.00001 && a < 0.00001) { + return false; + } + + f = 1/a; + s = origin - v0; + u = f * glm::dot(s,h); + + if (u < 0.0 || u > 1.0) { + return false; + } + + q = glm::cross(s, e1); + v = f * glm::dot(direction, q); + + if (v < 0.0 || u + v > 1.0) { + return false; + } + + // at this stage we can compute t to find out where the intersection point is on the line + t = f * glm::dot(e2,q); + + // ray intersection + if (t > 0.00001) { + distance = t; + return true; + } else { + // this means that there is a line intersection but not a ray intersection + return false; + } + return false; +} + + // Do line segments (r1p1.x, r1p1.y)--(r1p2.x, r1p2.y) and (r2p1.x, r2p1.y)--(r2p2.x, r2p2.y) intersect? // from: http://ptspts.blogspot.com/2010/06/how-to-determine-if-two-line-segments.html bool doLineSegmentsIntersect(glm::vec2 r1p1, glm::vec2 r1p2, glm::vec2 r2p1, glm::vec2 r2p2) { diff --git a/libraries/shared/src/GeometryUtil.h b/libraries/shared/src/GeometryUtil.h index b521a79771..f439352ca8 100644 --- a/libraries/shared/src/GeometryUtil.h +++ b/libraries/shared/src/GeometryUtil.h @@ -76,6 +76,22 @@ bool findRaySphereIntersection(const glm::vec3& origin, const glm::vec3& directi bool findRayCapsuleIntersection(const glm::vec3& origin, const glm::vec3& direction, const glm::vec3& start, const glm::vec3& end, float radius, float& distance); +bool findRayTrianlgeIntersection(const glm::vec3& origin, const glm::vec3& direction, + const glm::vec3& v0, const glm::vec3& v1, const glm::vec3& v2, float& distance); + +class Triangle { +public: + glm::vec3 v0; + glm::vec3 v1; + glm::vec3 v2; +}; + +inline bool findRayTrianlgeIntersection(const glm::vec3& origin, const glm::vec3& direction, + const Triangle& triangle, float& distance) { + return findRayTrianlgeIntersection(origin, direction, triangle.v0, triangle.v1, triangle.v2, distance); +} + + bool doLineSegmentsIntersect(glm::vec2 r1p1, glm::vec2 r1p2, glm::vec2 r2p1, glm::vec2 r2p2); bool isOnSegment(float xi, float yi, float xj, float yj, float xk, float yk); int computeDirection(float xi, float yi, float xj, float yj, float xk, float yk); From 69792178b95f5eb4a1223456fb3052aeff0fed8d Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Fri, 5 Dec 2014 13:43:04 -0800 Subject: [PATCH 250/502] trying to fix the linux compilation --- libraries/gpu/src/gpu/GPUConfig.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/libraries/gpu/src/gpu/GPUConfig.h b/libraries/gpu/src/gpu/GPUConfig.h index faecfd4889..393a476182 100644 --- a/libraries/gpu/src/gpu/GPUConfig.h +++ b/libraries/gpu/src/gpu/GPUConfig.h @@ -18,14 +18,15 @@ #include #include -#elif defined(UNIX) -#include -#include - #elif defined(WIN32) #include #include +#else +#include +#include + + #endif #endif From 2c8b1721cc56c08503467819c7261e00cf70ee62 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Fri, 5 Dec 2014 14:06:41 -0800 Subject: [PATCH 251/502] Add warp from right ('O') button on gamepad --- examples/butterflies.js | 2 +- examples/headMove.js | 88 +++++++++++++++++++++++++---------------- 2 files changed, 54 insertions(+), 36 deletions(-) diff --git a/examples/butterflies.js b/examples/butterflies.js index 9bd568d011..069a0d6792 100644 --- a/examples/butterflies.js +++ b/examples/butterflies.js @@ -32,7 +32,7 @@ var startTimeInSeconds = new Date().getTime() / 1000; var NATURAL_SIZE_OF_BUTTERFLY = { x: 1.0, y: 0.4, z: 0.2 }; var lifeTime = 3600; // One hour lifespan -var range = 5.0; // Over what distance in meters do you want the flock to fly around +var range = 7.0; // Over what distance in meters do you want the flock to fly around var frame = 0; var DISTANCE_IN_FRONT_OF_ME = 1.5; diff --git a/examples/headMove.js b/examples/headMove.js index 4d2e4ded07..943664b70f 100644 --- a/examples/headMove.js +++ b/examples/headMove.js @@ -11,6 +11,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +var gamepads = {}; + var debug = false; var willMove = false; @@ -19,7 +21,6 @@ var warpPosition = { x: 0, y: 0, z: 0 }; var hipsToEyes; var restoreCountdownTimer; -var headTurningTimer = 0.0; // Overlays to show target location @@ -62,13 +63,6 @@ function restoreCameraState() { Camera.mode = oldMode; } -function activateWarp() { - if (warpActive) return; - warpActive = true; - - updateWarp(); -} - var WATCH_AVATAR_DISTANCE = 2.5; var sound = SoundCache.getSound("http://public.highfidelity.io/sounds/Footsteps/FootstepW2Right-12db.wav"); @@ -132,6 +126,22 @@ function updateWarp() { }); } +function activateWarp() { + if (warpActive) return; + warpActive = true; + movingWithHead = true; + hipsToEyes = MyAvatar.getEyePosition().y - MyAvatar.position.y; + headStartPosition = MyAvatar.getTrackedHeadPosition(); + headStartDeltaPitch = MyAvatar.getHeadDeltaPitch(); + headStartFinalPitch = MyAvatar.getHeadFinalPitch(); + headStartRoll = MyAvatar.getHeadFinalRoll(); + headStartYaw = MyAvatar.getHeadFinalYaw(); + deltaYaw = 0.0; + warpPosition = MyAvatar.position; + warpPosition.y += hipsToEyes; + updateWarp(); +} + function finishWarp() { if (!warpActive) return; warpActive = false; @@ -152,6 +162,9 @@ function finishWarp() { cameraPosition = Vec3.subtract(MyAvatar.position, Vec3.multiplyQbyV(Camera.getOrientation(), { x: 0, y: -hipsToEyes, z: -hipsToEyes * WATCH_AVATAR_DISTANCE })); Camera.setPosition(cameraPosition); playSound(); + if (watchAvatar) { + restoreCountdownTimer = RESTORE_TIME; + } } } @@ -169,35 +182,11 @@ function update(deltaTime) { restoreCountDownTimer = 0.0; } } - var HEAD_TURN_TIME = 0.10; - var HEAD_TURN_DEGREES = 4.0; - var HEAD_TURN_START_ANGLE = 45.0; - var currentYaw = MyAvatar.getHeadFinalYaw(); - if (Math.abs(currentYaw) > HEAD_TURN_START_ANGLE) { - headTurningTimer += deltaTime; - if (headTurningTimer > HEAD_TURN_TIME) { - headTurningTimer = 0.0; - MyAvatar.orientation = Quat.multiply(Quat.fromPitchYawRollDegrees(0, (currentYaw > 0) ? HEAD_TURN_DEGREES: -HEAD_TURN_DEGREES, 0), - MyAvatar.orientation); - } - } else { - headTurningTimer = 0.0; - } } Controller.keyPressEvent.connect(function(event) { if (event.text == "SPACE" && !event.isAutoRepeat && !movingWithHead) { keyDownTime = 0.0; - movingWithHead = true; - hipsToEyes = MyAvatar.getEyePosition().y - MyAvatar.position.y; - headStartPosition = MyAvatar.getTrackedHeadPosition(); - headStartDeltaPitch = MyAvatar.getHeadDeltaPitch(); - headStartFinalPitch = MyAvatar.getHeadFinalPitch(); - headStartRoll = MyAvatar.getHeadFinalRoll(); - headStartYaw = MyAvatar.getHeadFinalYaw(); - deltaYaw = 0.0; - warpPosition = MyAvatar.position; - warpPosition.y += hipsToEyes; activateWarp(); } }); @@ -223,11 +212,40 @@ Controller.keyReleaseEvent.connect(function(event) { } timeSinceLastUp = 0.0; finishWarp(); - if (watchAvatar) { - restoreCountdownTimer = RESTORE_TIME; - } } }); +function reportButtonValue(button, newValue, oldValue) { + if (button == Joysticks.BUTTON_FACE_RIGHT) { + if (newValue) { + activateWarp(); + } else { + finishWarp(); + } + } +} + Script.update.connect(update); +function addJoystick(gamepad) { + gamepad.buttonStateChanged.connect(reportButtonValue); + + gamepads[gamepad.instanceId] = gamepad; + + print("Added gamepad: " + gamepad.name + " (" + gamepad.instanceId + ")"); +} + +function removeJoystick(gamepad) { + delete gamepads[gamepad.instanceId] + + print("Removed gamepad: " + gamepad.name + " (" + gamepad.instanceId + ")"); +} + +var allJoysticks = Joysticks.getAllJoysticks(); +for (var i = 0; i < allJoysticks.length; i++) { + addJoystick(allJoysticks[i]); +} + +Joysticks.joystickAdded.connect(addJoystick); +Joysticks.joystickRemoved.connect(removeJoystick); + From 0ccbb98bdee1985567b24a39c38fc0cd05368890 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 5 Dec 2014 15:03:35 -0800 Subject: [PATCH 252/502] more work on improved model picking --- libraries/entities/src/EntityTreeElement.cpp | 26 +++++++++++++++++--- libraries/octree/src/OctreeElement.cpp | 10 ++++++-- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index e0ebe47412..c452dab5cb 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -478,10 +478,19 @@ bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, con void** intersectedObject, float distanceToElementCube) { // only called if we do intersect our bounding cube, but find if we actually intersect with entities... + + qDebug() << "EntityTreeElement::findDetailedRayIntersection()...."; + qDebug() << " origin:" << origin; + qDebug() << " distance:" << distance; + qDebug() << " number of entities:" << _entityItems->size(); + int entityNumber = 0; QList::iterator entityItr = _entityItems->begin(); QList::const_iterator entityEnd = _entityItems->end(); bool somethingIntersected = false; + + //float bestEntityDistance = distance; + while(entityItr != entityEnd) { EntityItem* entity = (*entityItr); @@ -489,9 +498,16 @@ bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, con float localDistance; BoxFace localFace; + qDebug() << "EntityTreeElement::findDetailedRayIntersection()...."; + qDebug() << " checking entity[" << entityNumber << "]:" << entity->getEntityItemID() << "-" << qPrintable(EntityTypes::getEntityTypeName(entity->getType())); + qDebug() << " checking the AABox:" << entityBox; + // if the ray doesn't intersect with our cube, we can stop searching! if (entityBox.findRayIntersection(origin, direction, localDistance, localFace)) { + qDebug() << " AABox for entity intersects!"; + qDebug() << " localDistance:" << localDistance; + // extents is the entity relative, scaled, centered extents of the entity glm::mat4 rotation = glm::mat4_cast(entity->getRotation()); glm::mat4 translation = glm::translate(entity->getPosition()); @@ -509,12 +525,10 @@ bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, con // we can use the AABox's ray intersection by mapping our origin and direction into the entity frame // and testing intersection there. - qDebug() << "EntityTreeElement::findDetailedRayIntersection()...."; - qDebug() << " origin:" << origin; - qDebug() << " checking entity:" << entity->getEntityItemID() << "-" << qPrintable(EntityTypes::getEntityTypeName(entity->getType())); - qDebug() << " distance:" << distance; + qDebug() << " checking the entityFrameBox:" << entityFrameBox; if (entityFrameBox.findRayIntersection(entityFrameOrigin, entityFrameDirection, localDistance, localFace)) { + qDebug() << " entityFrameBox intersects!"; qDebug() << " localDistance:" << localDistance; if (localDistance < distance) { @@ -559,7 +573,11 @@ bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, con } ++entityItr; + entityNumber++; } + + qDebug() << " EntityTreeElement::findDetailedRayIntersection().... returning somethingIntersected:" << somethingIntersected << "keepSearching:" << keepSearching; + return somethingIntersected; } diff --git a/libraries/octree/src/OctreeElement.cpp b/libraries/octree/src/OctreeElement.cpp index e085298c33..330624f4b9 100644 --- a/libraries/octree/src/OctreeElement.cpp +++ b/libraries/octree/src/OctreeElement.cpp @@ -1343,9 +1343,12 @@ bool OctreeElement::findRayIntersection(const glm::vec3& origin, const glm::vec3 float distanceToElementDetails = distance; BoxFace localFace; + AACube debugCube = cube; + debugCube.scale((float)TREE_SCALE); + qDebug() << "OctreeElement::findRayIntersection()...."; qDebug() << " origin:" << origin; - qDebug() << " checking element:" << cube; + qDebug() << " checking element:" << debugCube << "in meters"; qDebug() << " distance:" << distance; // if the ray doesn't intersect with our cube, we can stop searching! @@ -1359,6 +1362,7 @@ bool OctreeElement::findRayIntersection(const glm::vec3& origin, const glm::vec3 // by default, we only allow intersections with leaves with content if (!canRayIntersect()) { + qDebug() << " NOT canRayIntersect() -- no point in calling detailed..."; return false; // we don't intersect with non-leaves, and we keep searching } @@ -1367,9 +1371,10 @@ bool OctreeElement::findRayIntersection(const glm::vec3& origin, const glm::vec3 // if the distance to the element cube is not less than the current best distance, then it's not possible // for any details inside the cube to be closer so we don't need to consider them. - if (distanceToElementCube < distance) { + if (cube.contains(origin) || distanceToElementCube < distance) { qDebug() << " distanceToElementCube < distance:" << (distanceToElementCube < distance); + qDebug() << " cube.contains(origin):" << (cube.contains(origin)); qDebug() << " continue.... call... findDetailedRayIntersection()..."; //qDebug() << " distanceToElementCube < distance -- continue.... call... findDetailedRayIntersection()..."; @@ -1403,6 +1408,7 @@ bool OctreeElement::findDetailedRayIntersection(const glm::vec3& origin, const g if (intersectedObject) { *intersectedObject = this; } + qDebug() << " OctreeElement::findDetailedRayIntersection().... hasContent() -- done searching..."; keepSearching = false; return true; // we did intersect } From 896a34212b455ca8ab3ba9bb1593e93a76a0eae5 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 5 Dec 2014 15:27:24 -0800 Subject: [PATCH 253/502] Fix sections not properly updating in properties tool --- examples/html/entityProperties.html | 202 +++++++++++++++------------- 1 file changed, 106 insertions(+), 96 deletions(-) diff --git a/examples/html/entityProperties.html b/examples/html/entityProperties.html index 97e16fcf11..0308d7f5e7 100644 --- a/examples/html/entityProperties.html +++ b/examples/html/entityProperties.html @@ -104,12 +104,12 @@ var elCollisionsWillMove = document.getElementById("property-collisions-will-move"); var elLifetime = document.getElementById("property-lifetime"); - var elBoxSection = document.getElementById("box-section"); + var elBoxSections = document.querySelectorAll(".box-section"); var elBoxColorRed = document.getElementById("property-box-red"); var elBoxColorGreen = document.getElementById("property-box-green"); var elBoxColorBlue = document.getElementById("property-box-blue"); - var elLightSection = document.getElementById('light-section'); + var elLightSections = document.querySelectorAll(".light-section"); var elLightSpotLight = document.getElementById("property-light-spot-light"); var elLightDiffuseRed = document.getElementById("property-light-diffuse-red"); var elLightDiffuseGreen = document.getElementById("property-light-diffuse-green"); @@ -129,14 +129,14 @@ var elLightExponent = document.getElementById("property-light-exponent"); var elLightCutoff = document.getElementById("property-light-cutoff"); - var elModelSection = document.getElementById("model-section"); + var elModelSections = document.querySelectorAll(".model-section"); var elModelURL = document.getElementById("property-model-url"); var elModelAnimationURL = document.getElementById("property-model-animation-url"); var elModelAnimationPlaying = document.getElementById("property-model-animation-playing"); var elModelAnimationFPS = document.getElementById("property-model-animation-fps"); var elModelAnimationFrame = document.getElementById("property-model-animation-frame"); - var elTextSection = document.getElementById("text-section"); + var elTextSections = document.querySelectorAll(".text-section"); var elTextText = document.getElementById("property-text-text"); var elTextLineHeight = document.getElementById("property-text-line-height"); var elTextTextColorRed = document.getElementById("property-text-text-color-red"); @@ -200,9 +200,13 @@ elLifetime.value = properties.lifetime; if (properties.type != "Box") { - elBoxSection.style.display = 'none'; + for (var i = 0; i < elBoxSections.length; i++) { + elBoxSections[i].style.display = 'none'; + } } else { - elBoxSection.style.display = 'block'; + for (var i = 0; i < elBoxSections.length; i++) { + elBoxSections[i].style.display = 'table-row'; + } elBoxColorRed.value = properties.color.red; elBoxColorGreen.value = properties.color.green; @@ -210,9 +214,14 @@ } if (properties.type != "Model") { - elModelSection.style.display = 'none'; + for (var i = 0; i < elModelSections.length; i++) { + elModelSections[i].style.display = 'none'; + } } else { - elModelSection.style.display = 'block'; + for (var i = 0; i < elModelSections.length; i++) { + elModelSections[i].style.display = 'table-row'; + } + elModelURL.value = properties.modelURL; elModelAnimationURL.value = properties.animationURL; elModelAnimationPlaying.checked = properties.animationIsPlaying; @@ -220,9 +229,13 @@ } if (properties.type != "Text") { - elTextSection.style.display = 'none'; + for (var i = 0; i < elTextSections.length; i++) { + elTextSections[i].style.display = 'none'; + } } else { - elTextSection.style.display = 'block'; + for (var i = 0; i < elTextSections.length; i++) { + elTextSections[i].style.display = 'table-row'; + } elTextText.value = properties.text; elTextLineHeight.value = properties.lineHeight; @@ -235,9 +248,13 @@ } if (properties.type != "Light") { - elLightSection.style.display = 'none'; + for (var i = 0; i < elLightSections.length; i++) { + elLightSections[i].style.display = 'none'; + } } else { - elLightSection.style.display = 'block'; + for (var i = 0; i < elLightSections.length; i++) { + elLightSections[i].style.display = 'table-row'; + } elLightDiffuseRed.value = properties.diffuseColor.red; elLightDiffuseGreen.value = properties.diffuseColor.green; @@ -437,7 +454,7 @@ - + Position @@ -446,7 +463,7 @@
Y
Z
- + Registration @@ -455,55 +472,45 @@
Y
Z
- + - Width + Dimensions - +
X
+
Y
+
Z
- - - Height - - - - - - Depth - - - - + - Linear + Linear Velocity
X
Y
Z
- + Linear Damping + - - Angular + Angular Velocity
Pitch
Yaw
Roll
- + Angular Damping - + Gravity @@ -512,168 +519,171 @@
Y
Z
- + Mass - + Ignore For Collisions - + Collisions Will Move - + Lifetime + + - + Color -
Red
-
Green
-
Blue
+
R
+
G
+
B
- + - + Model URL - - + + Animation URL - - + + Animation Playing - - + + Animation FPS - - + + Animation Frame - + - + + Text - - + + Line Height - - + + Text Color -
Red
-
Green
-
Blue
+
R
+
G
+
B
- - + + Background Color -
Red
-
Green
-
Blue
+
R
+
G
+
B
- + - + Spot Light - - + + Diffuse -
Red
-
Green
-
Blue
+
R
+
G
+
B
- - + + Ambient -
Red
-
Green
-
Blue
+
R
+
G
+
B
- - + + Specular -
Red
-
Green
-
Blue
+
R
+
G
+
B
- - + + Constant Attenuation - - + + Linear Attenuation - - + + Quadratic Attenuation - - + + Exponent - - + + Cutoff (degrees) - + From a89411fd5eeb2f7e1a07e482b9f04441d7e9a910 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 5 Dec 2014 15:27:40 -0800 Subject: [PATCH 254/502] Add script URL to properties tool --- examples/html/entityProperties.html | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/examples/html/entityProperties.html b/examples/html/entityProperties.html index 0308d7f5e7..17eb0ad88f 100644 --- a/examples/html/entityProperties.html +++ b/examples/html/entityProperties.html @@ -103,6 +103,7 @@ var elIgnoreForCollisions = document.getElementById("property-ignore-for-collisions"); var elCollisionsWillMove = document.getElementById("property-collisions-will-move"); var elLifetime = document.getElementById("property-lifetime"); + var elScriptURL = document.getElementById("property-script-url"); var elBoxSections = document.querySelectorAll(".box-section"); var elBoxColorRed = document.getElementById("property-box-red"); @@ -198,6 +199,7 @@ elIgnoreForCollisions.checked = properties.ignoreForCollisions; elCollisionsWillMove.checked = properties.collisionsWillMove; elLifetime.value = properties.lifetime; + elScriptURL.value = properties.script; if (properties.type != "Box") { for (var i = 0; i < elBoxSections.length; i++) { @@ -324,6 +326,7 @@ elIgnoreForCollisions.addEventListener('change', createEmitCheckedPropertyUpdateFunction('ignoreForCollisions')); elCollisionsWillMove.addEventListener('change', createEmitCheckedPropertyUpdateFunction('collisionsWillMove')); elLifetime.addEventListener('change', createEmitNumberPropertyUpdateFunction('lifetime')); + elScriptURL.addEventListener('change', createEmitTextPropertyUpdateFunction('script')); var boxColorChangeFunction = createEmitColorPropertyUpdateFunction( 'color', elBoxColorRed, elBoxColorGreen, elBoxColorBlue); @@ -550,6 +553,11 @@ + Script URL + + + + From ccdb13c951129351336296f578d7c7d3f2b937d7 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Sat, 6 Dec 2014 00:33:33 +0100 Subject: [PATCH 255/502] virtualkeyboard: moved files to hifi public bucket --- examples/virtualKeyboard.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/examples/virtualKeyboard.js b/examples/virtualKeyboard.js index 2340bcab6e..e48da8a4d1 100644 --- a/examples/virtualKeyboard.js +++ b/examples/virtualKeyboard.js @@ -15,14 +15,16 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +Script.include("libraries/globals.js"); + const KBD_UPPERCASE_DEFAULT = 0; const KBD_LOWERCASE_DEFAULT = 1; const KBD_UPPERCASE_HOVER = 2; const KBD_LOWERCASE_HOVER = 3; const KBD_BACKGROUND = 4; -const KEYBOARD_URL = "http://test.thoys.nl/hifi/images/virtualKeyboard/keyboard.svg"; -const CURSOR_URL = "http://test.thoys.nl/hifi/images/virtualKeyboard/cursor.svg"; +const KEYBOARD_URL = HIFI_PUBLIC_BUCKET + "images/keyboard.svg"; +const CURSOR_URL = HIFI_PUBLIC_BUCKET + "images/cursor.svg"; const SPACEBAR_CHARCODE = 32; From ae647d39d0f62c94de93ec1bb85d01cfd0fb0292 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 5 Dec 2014 16:14:18 -0800 Subject: [PATCH 256/502] fix models with registrations other than 0,0,0 --- interface/src/renderer/Model.cpp | 24 ++++++++++++++++---- libraries/entities/src/EntityTreeElement.cpp | 4 ++++ libraries/octree/src/OctreeElement.cpp | 4 ++++ 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 6b398284a3..a259e42117 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -543,10 +543,10 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g qDebug() << " modelExtents:" << modelExtents; glm::vec3 dimensions = modelExtents.maximum - modelExtents.minimum; - glm::vec3 corner = dimensions * _registrationPoint; // since we're going to do the ray picking in the model frame of reference - AABox overlayFrameBox(corner, dimensions); + glm::vec3 corner = -(dimensions * _registrationPoint); // since we're going to do the ray picking in the model frame of reference + AABox modelFrameBox(corner, dimensions); - qDebug() << " overlayFrameBox:" << overlayFrameBox; + qDebug() << " modelFrameBox:" << modelFrameBox; glm::vec3 modelFrameOrigin = glm::vec3(worldToModelMatrix * glm::vec4(origin, 1.0f)); glm::vec3 modelFrameDirection = glm::vec3(worldToModelMatrix * glm::vec4(direction, 0.0f)); @@ -555,7 +555,9 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g // we can use the AABox's ray intersection by mapping our origin and direction into the model frame // and testing intersection there. - if (overlayFrameBox.findRayIntersection(modelFrameOrigin, modelFrameDirection, distance, face)) { + if (modelFrameBox.findRayIntersection(modelFrameOrigin, modelFrameDirection, distance, face)) { + + qDebug() << " modelFrameBox.findRayIntersection() HITS!!!"; float bestDistance = std::numeric_limits::max(); float bestTriangleDistance = std::numeric_limits::max(); @@ -566,14 +568,21 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g int subMeshIndex = 0; const FBXGeometry& geometry = _geometry->getFBXGeometry(); + + qDebug() << " Checking mesh boxes...."; // If we hit the models box, then consider the submeshes... foreach(const AABox& subMeshBox, _calculatedMeshBoxes) { - qDebug() << "subMeshBox[" << subMeshIndex <<"]:" << subMeshBox; + qDebug() << " subMeshBox[" << subMeshIndex <<"]:" << subMeshBox; if (subMeshBox.findRayIntersection(origin, direction, distanceToSubMesh, subMeshFace)) { + qDebug() << " subMeshBox[" << subMeshIndex <<"].findRayIntersection() HITS!"; + qDebug() << " subMeshBox[" << subMeshIndex <<"].distanceToSubMesh:" << distanceToSubMesh; + qDebug() << " bestDistance:" << bestDistance; if (distanceToSubMesh < bestDistance) { + qDebug() << " distanceToSubMesh < bestDistance !! looks like a good match!"; + if (pickAgainstTriangles) { if (!_calculatedMeshTrianglesValid) { recalcuateMeshBoxes(); @@ -599,6 +608,8 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g intersectedSomething = true; face = subMeshFace; extraInfo = geometry.getModelNameOfMesh(subMeshIndex); + } else { + qDebug() << " distanceToSubMesh >= bestDistance !! TOO FAR AWAY!"; } } subMeshIndex++; @@ -607,6 +618,7 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g // if we were asked to pick against triangles, and we didn't hit one, then we // do not consider this model to be hit at all. if (pickAgainstTriangles && !someTriangleHit) { + qDebug() << "pickAgainstTriangles && !someTriangleHit --- call it a NON-HIT!"; intersectedSomething = false; } qDebug() << "pickAgainstTriangles:" << pickAgainstTriangles; @@ -626,6 +638,8 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g } return intersectedSomething; + } else { + qDebug() << "modelFrameBox.findRayIntersection()... DID NOT INTERSECT..."; } return intersectedSomething; diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index c452dab5cb..aea278adf6 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -553,6 +553,8 @@ bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, con face = localFace; *intersectedObject = (void*)entity; somethingIntersected = true; + } else { + qDebug() << " localDistance >= distance... TOO FAR AWAY"; } } } else { @@ -566,6 +568,8 @@ bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, con face = localFace; *intersectedObject = (void*)entity; somethingIntersected = true; + } else { + qDebug() << " localDistance >= distance... TOO FAR AWAY"; } } } diff --git a/libraries/octree/src/OctreeElement.cpp b/libraries/octree/src/OctreeElement.cpp index 330624f4b9..9f6e0530a8 100644 --- a/libraries/octree/src/OctreeElement.cpp +++ b/libraries/octree/src/OctreeElement.cpp @@ -1391,6 +1391,10 @@ bool OctreeElement::findRayIntersection(const glm::vec3& origin, const glm::vec3 qDebug() << " distance:" << distance << " -- THIS ONE IS GOOD -------"; return true; + } else { + qDebug() << " distanceToElementDetails:" << distanceToElementDetails; + qDebug() << " distance:" << distance; + qDebug() << " distanceToElementDetails >= distance -- THIS ONE IS NOT SELECTED even though it INTERSECTED -------"; } } } From ee124f580df3beca04d0b2b44e03009bb0a43a48 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 5 Dec 2014 17:02:49 -0800 Subject: [PATCH 257/502] removed _mouse{X,Y} --- interface/src/Application.cpp | 17 +---------------- interface/src/Application.h | 6 ++---- 2 files changed, 3 insertions(+), 20 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 0ecb99fbcc..41e925fd9d 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -165,8 +165,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : _scaleMirror(1.0f), _rotateMirror(0.0f), _raiseMirror(0.0f), - _mouseX(0), - _mouseY(0), _lastMouseMove(usecTimestampNow()), _lastMouseMoveWasSimulated(false), _mouseHidden(false), @@ -1282,9 +1280,6 @@ void Application::mouseMoveEvent(QMouseEvent* event, unsigned int deviceID) { _mouseHidden = false; _seenMouseMove = true; } - - _mouseX = event->x(); - _mouseY = event->y(); } void Application::mousePressEvent(QMouseEvent* event, unsigned int deviceID) { @@ -1302,8 +1297,6 @@ void Application::mousePressEvent(QMouseEvent* event, unsigned int deviceID) { if (activeWindow() == _window) { if (event->button() == Qt::LeftButton) { - _mouseX = event->x(); - _mouseY = event->y(); _mouseDragStartedX = getTrueMouseX(); _mouseDragStartedY = getTrueMouseY(); _mousePressed = true; @@ -1346,8 +1339,6 @@ void Application::mouseReleaseEvent(QMouseEvent* event, unsigned int deviceID) { if (activeWindow() == _window) { if (event->button() == Qt::LeftButton) { - _mouseX = event->x(); - _mouseY = event->y(); _mousePressed = false; if (Menu::getInstance()->isOptionChecked(MenuOption::Stats) && mouseOnScreen()) { @@ -1940,9 +1931,6 @@ void Application::init() { _voxelShader.init(); _pointShader.init(); - _mouseX = _glWidget->width() / 2; - _mouseY = _glWidget->height() / 2; - // TODO: move _myAvatar out of Application. Move relevant code to MyAvataar or AvatarManager _avatarManager.init(); _myCamera.setMode(CAMERA_MODE_FIRST_PERSON); @@ -3557,9 +3545,6 @@ void Application::deleteVoxelAt(const VoxelDetail& voxel) { } void Application::resetSensors() { - _mouseX = _glWidget->width() / 2; - _mouseY = _glWidget->height() / 2; - _faceshift.reset(); _visage.reset(); _dde.reset(); @@ -3572,7 +3557,7 @@ void Application::resetSensors() { QScreen* currentScreen = _window->windowHandle()->screen(); QWindow* mainWindow = _window->windowHandle(); QPoint windowCenter = mainWindow->geometry().center(); - QCursor::setPos(currentScreen, windowCenter); + _glWidget->cursor().setPos(currentScreen, windowCenter); _myAvatar->reset(); diff --git a/interface/src/Application.h b/interface/src/Application.h index 8fb0cb090d..58dec1da1f 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -217,8 +217,8 @@ public: bool mouseOnScreen() const; int getMouseX() const; int getMouseY() const; - int getTrueMouseX() const { return _mouseX; } - int getTrueMouseY() const { return _mouseY; } + int getTrueMouseX() const { return _glWidget->mapFromGlobal(QCursor::pos()).x(); } + int getTrueMouseY() const { return _glWidget->mapFromGlobal(QCursor::pos()).y(); } int getMouseDragStartedX() const; int getMouseDragStartedY() const; int getTrueMouseDragStartedX() const { return _mouseDragStartedX; } @@ -563,8 +563,6 @@ private: Environment _environment; - int _mouseX; - int _mouseY; int _mouseDragStartedX; int _mouseDragStartedY; quint64 _lastMouseMove; From 1bb08ef30f0cfb4aa0a56e9b394cf69ceef2c7af Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 5 Dec 2014 17:10:58 -0800 Subject: [PATCH 258/502] Centered reticule --- interface/src/ui/ApplicationOverlay.cpp | 30 ++++++++++++++++++++----- interface/src/ui/ApplicationOverlay.h | 3 ++- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index c029a2e00f..f4e9e627ad 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -127,6 +127,7 @@ void renderReticule(glm::quat orientation, float alpha) { ApplicationOverlay::ApplicationOverlay() : _textureFov(glm::radians(DEFAULT_OCULUS_UI_ANGULAR_SIZE)), _textureAspectRatio(1.0f), + _lastMouseMove(0), _alpha(1.0f), _oculusUIRadius(1.0f), _crosshairTexture(0) { @@ -284,7 +285,8 @@ void ApplicationOverlay::displayOverlayTextureOculus(Camera& whichCamera) { if (_magSizeMult[i] > 0.0f) { //Render magnifier, but dont show border for mouse magnifier - glm::vec2 projection = screenToOverlay(_reticulePosition[i]); + glm::vec2 projection = screenToOverlay(glm::vec2(_reticulePosition[MOUSE].x(), + _reticulePosition[MOUSE].y())); renderMagnifier(projection, _magSizeMult[i], i != MOUSE); } @@ -520,13 +522,30 @@ void ApplicationOverlay::renderPointers() { if (OculusManager::isConnected() && !application->getLastMouseMoveWasSimulated()) { //If we are in oculus, render reticle later + if (_lastMouseMove == 0) { + _lastMouseMove = usecTimestampNow(); + } + QPoint position = QPoint(application->getTrueMouseX(), application->getTrueMouseY()); + + static const int MAX_IDLE_TIME = 3; + if (_reticulePosition[MOUSE] != position) { + _lastMouseMove = usecTimestampNow(); + } else if (usecTimestampNow() - _lastMouseMove > MAX_IDLE_TIME * USECS_PER_SECOND) { + float pitch, yaw, roll; + OculusManager::getEulerAngles(yaw, pitch, roll); + glm::vec2 screenPos = sphericalToScreen(glm::vec2(yaw, -pitch)); + + position = QPoint(screenPos.x, screenPos.y); + QCursor::setPos(application->getGLWidget()->mapToGlobal(position)); + } + + _reticulePosition[MOUSE] = position; _reticleActive[MOUSE] = true; _magActive[MOUSE] = true; - _reticulePosition[MOUSE] = glm::vec2(application->getMouseX(), application->getMouseY()); _reticleActive[LEFT_CONTROLLER] = false; _reticleActive[RIGHT_CONTROLLER] = false; - } else if (application->getLastMouseMoveWasSimulated() && Menu::getInstance()->isOptionChecked(MenuOption::SixenseMouseInput)) { + _lastMouseMove = 0; //only render controller pointer if we aren't already rendering a mouse pointer _reticleActive[MOUSE] = false; _magActive[MOUSE] = false; @@ -591,7 +610,7 @@ void ApplicationOverlay::renderControllerPointers() { QPoint point = getPalmClickLocation(palmData); - _reticulePosition[index] = glm::vec2(point.x(), point.y()); + _reticulePosition[index] = point; //When button 2 is pressed we drag the mag window if (isPressed[index]) { @@ -672,7 +691,8 @@ void ApplicationOverlay::renderPointersOculus(const glm::vec3& eyePos) { //Mouse Pointer if (_reticleActive[MOUSE]) { - glm::vec2 projection = screenToSpherical(_reticulePosition[MOUSE]); + glm::vec2 projection = screenToSpherical(glm::vec2(_reticulePosition[MOUSE].x(), + _reticulePosition[MOUSE].y())); glm::quat orientation(glm::vec3(-projection.y, projection.x, 0.0f)); renderReticule(orientation, _alpha); } diff --git a/interface/src/ui/ApplicationOverlay.h b/interface/src/ui/ApplicationOverlay.h index 2ca430aae6..538a163d0e 100644 --- a/interface/src/ui/ApplicationOverlay.h +++ b/interface/src/ui/ApplicationOverlay.h @@ -96,9 +96,10 @@ private: enum Reticules { MOUSE, LEFT_CONTROLLER, RIGHT_CONTROLLER, NUMBER_OF_RETICULES }; bool _reticleActive[NUMBER_OF_RETICULES]; - glm::vec2 _reticulePosition[NUMBER_OF_RETICULES]; + QPoint _reticulePosition[NUMBER_OF_RETICULES]; bool _magActive[NUMBER_OF_RETICULES]; float _magSizeMult[NUMBER_OF_RETICULES]; + quint64 _lastMouseMove; float _alpha; float _oculusUIRadius; From d89d10d26362d4b01d81ada9af392d354a03d554 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 5 Dec 2014 17:36:46 -0800 Subject: [PATCH 259/502] Hide cusor in VR mode --- interface/src/Application.cpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 41e925fd9d..2d92a99cab 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2342,7 +2342,20 @@ void Application::update(float deltaTime) { _prioVR.update(deltaTime); } - + + static QCursor cursor; + if (OculusManager::isConnected() && + Menu::getInstance()->isOptionChecked(MenuOption::EnableVRMode)){ + if (_window->cursor().shape() != Qt::BlankCursor) { + qDebug() << "Hiding cursor" << _window->cursor().shape(); + cursor = _window->cursor(); + _window->setCursor(QCursor(Qt::BlankCursor)); + } + } else if(_window->cursor().shape() == Qt::BlankCursor) { + qDebug() << "Showing cursor" << _window->cursor().shape(); + _window->setCursor(cursor); + } + // Dispatch input events _controllerScriptingInterface.updateInputControllers(); From 7d96ad5836bd6dcdc3feff80c22426ce5912c636 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 5 Dec 2014 18:08:53 -0800 Subject: [PATCH 260/502] cleanup of EntitySimulation API * remove EntityItem::_simulationState (only useful to EntitySimulation) * move code from SimpleEntitySimuation to EntitySimulation * EntitySimulation now maintans many QSets of entities * cleanup and clarify use of EnityTree::updateEntity() * reduced cost of polling for entity expiries * changed "UpdateFlags" to "DirtyFlags" and clarified what they're for --- .../entities/RenderableModelEntityItem.cpp | 6 +- .../src/entities/RenderableModelEntityItem.h | 4 +- .../entities/src/EntityCollisionSystem.cpp | 10 +- libraries/entities/src/EntityItem.cpp | 74 +++--- libraries/entities/src/EntityItem.h | 60 +++-- libraries/entities/src/EntitySimulation.cpp | 168 +++++++++++- libraries/entities/src/EntitySimulation.h | 39 ++- libraries/entities/src/EntityTree.cpp | 48 ++-- libraries/entities/src/EntityTree.h | 8 + libraries/entities/src/EntityTreeElement.cpp | 2 +- libraries/entities/src/ModelEntityItem.cpp | 13 +- libraries/entities/src/ModelEntityItem.h | 2 +- .../entities/src/MovingEntitiesOperator.cpp | 9 +- .../entities/src/MovingEntitiesOperator.h | 3 +- .../entities/src/SimpleEntitySimulation.cpp | 239 ++++-------------- .../entities/src/SimpleEntitySimulation.h | 28 +- 16 files changed, 384 insertions(+), 329 deletions(-) diff --git a/interface/src/entities/RenderableModelEntityItem.cpp b/interface/src/entities/RenderableModelEntityItem.cpp index 10b18ad9c5..6c8d85507d 100644 --- a/interface/src/entities/RenderableModelEntityItem.cpp +++ b/interface/src/entities/RenderableModelEntityItem.cpp @@ -150,7 +150,7 @@ void RenderableModelEntityItem::render(RenderArgs* args) { } glm::quat rotation = getRotation(); - if (needsSimulation() && _model->isActive()) { + if (needsToCallUpdate() && _model->isActive()) { _model->setScaleToFit(true, dimensions); _model->setSnapModelToRegistrationPoint(true, getRegistrationPoint()); _model->setRotation(rotation); @@ -245,8 +245,8 @@ Model* RenderableModelEntityItem::getModel(EntityTreeRenderer* renderer) { return result; } -bool RenderableModelEntityItem::needsSimulation() const { - return _needsInitialSimulation || getSimulationState() == EntityItem::Moving; +bool RenderableModelEntityItem::needsToCallUpdate() const { + return _needsInitialSimulation || ModelEntityItem::needsToCallUpdate(); } EntityItemProperties RenderableModelEntityItem::getProperties() const { diff --git a/interface/src/entities/RenderableModelEntityItem.h b/interface/src/entities/RenderableModelEntityItem.h index 48c9a26051..0aa2578a6c 100644 --- a/interface/src/entities/RenderableModelEntityItem.h +++ b/interface/src/entities/RenderableModelEntityItem.h @@ -52,9 +52,11 @@ public: virtual void render(RenderArgs* args); Model* getModel(EntityTreeRenderer* renderer); + + bool needsToCallUpdate() const; + private: void remapTextures(); - bool needsSimulation() const; Model* _model; bool _needsInitialSimulation; diff --git a/libraries/entities/src/EntityCollisionSystem.cpp b/libraries/entities/src/EntityCollisionSystem.cpp index 2ac8ea596d..b74b9fac80 100644 --- a/libraries/entities/src/EntityCollisionSystem.cpp +++ b/libraries/entities/src/EntityCollisionSystem.cpp @@ -208,7 +208,9 @@ void EntityCollisionSystem::updateCollisionWithEntities(EntityItem* entityA) { propertiesA.setPosition(newPositionA * (float)TREE_SCALE); propertiesA.setLastEdited(now); - _entityTree->updateEntity(idA, propertiesA); + // NOTE: EntityTree::updateEntity() will cause the entity to get sorted correctly in the EntitySimulation, + // thereby waking up static non-moving entities. + _entityTree->updateEntity(entityA, propertiesA); _packetSender->queueEditEntityMessage(PacketTypeEntityAddOrEdit, idA, propertiesA); } @@ -225,7 +227,9 @@ void EntityCollisionSystem::updateCollisionWithEntities(EntityItem* entityA) { propertiesB.setPosition(newPositionB * (float)TREE_SCALE); propertiesB.setLastEdited(now); - _entityTree->updateEntity(idB, propertiesB); + // NOTE: EntityTree::updateEntity() will cause the entity to get sorted correctly in the EntitySimulation, + // thereby waking up static non-moving entities. + _entityTree->updateEntity(entityB, propertiesB); _packetSender->queueEditEntityMessage(PacketTypeEntityAddOrEdit, idB, propertiesB); } } @@ -331,6 +335,6 @@ void EntityCollisionSystem::applyHardCollision(EntityItem* entity, const Collisi properties.setVelocity(velocity * (float)TREE_SCALE); properties.setLastEdited(usecTimestampNow()); - _entityTree->updateEntity(entityItemID, properties); + _entityTree->updateEntity(entity, properties); _packetSender->queueEditEntityMessage(PacketTypeEntityAddOrEdit, entityItemID, properties); } diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 98dda6f33f..d0d07d1227 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -58,6 +58,7 @@ void EntityItem::initFromEntityItemID(const EntityItemID& entityItemID) { _lastEditedFromRemote = 0; _lastEditedFromRemoteInRemoteTime = 0; + _lastSimulated = 0; _lastUpdated = 0; _created = 0; // TODO: when do we actually want to make this "now" _changedOnServer = 0; @@ -88,12 +89,12 @@ EntityItem::EntityItem(const EntityItemID& entityItemID) { _lastEdited = 0; _lastEditedFromRemote = 0; _lastEditedFromRemoteInRemoteTime = 0; + _lastSimulated = 0; _lastUpdated = 0; _created = 0; - _updateFlags = 0; + _dirtyFlags = 0; _changedOnServer = 0; initFromEntityItemID(entityItemID); - _simulationState = EntityItem::Static; } EntityItem::EntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) { @@ -101,13 +102,13 @@ EntityItem::EntityItem(const EntityItemID& entityItemID, const EntityItemPropert _lastEdited = 0; _lastEditedFromRemote = 0; _lastEditedFromRemoteInRemoteTime = 0; + _lastSimulated = 0; _lastUpdated = 0; _created = properties.getCreated(); - _updateFlags = 0; + _dirtyFlags = 0; _changedOnServer = 0; initFromEntityItemID(entityItemID); setProperties(properties, true); // force copy - _simulationState = EntityItem::Static; } EntityPropertyFlags EntityItem::getEntityProperties(EncodeBitstreamParams& params) const { @@ -154,7 +155,7 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet ByteCountCoded typeCoder = getType(); QByteArray encodedType = typeCoder; - quint64 updateDelta = getLastUpdated() <= getLastEdited() ? 0 : getLastUpdated() - getLastEdited(); + quint64 updateDelta = getLastMoved() <= getLastEdited() ? 0 : getLastMoved() - getLastEdited(); ByteCountCoded updateDeltaCoder = updateDelta; QByteArray encodedUpdateDelta = updateDeltaCoder; EntityPropertyFlags propertyFlags(PROP_LAST_ITEM); @@ -450,9 +451,9 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef ByteCountCoded updateDeltaCoder = encodedUpdateDelta; quint64 updateDelta = updateDeltaCoder; if (overwriteLocalData) { - _lastUpdated = lastEditedFromBufferAdjusted + updateDelta; // don't adjust for clock skew since we already did that for _lastEdited + _lastSimulated = _lastUpdated = lastEditedFromBufferAdjusted + updateDelta; // don't adjust for clock skew since we already did that for _lastEdited if (wantDebug) { - qDebug() << "_lastUpdated=" << _lastUpdated; + qDebug() << "_lastUpdated =" << _lastUpdated; qDebug() << "_lastEdited=" << _lastEdited; qDebug() << "lastEditedFromBufferAdjusted=" << lastEditedFromBufferAdjusted; } @@ -565,20 +566,20 @@ bool EntityItem::isRestingOnSurface() const { && _gravity.y < 0.0f; } -void EntityItem::update(const quint64& updateTime) { +void EntityItem::simulate(const quint64& now) { bool wantDebug = false; - if (_lastUpdated == 0) { - _lastUpdated = updateTime; + if (_lastSimulated == 0) { + _lastSimulated = now; } - float timeElapsed = (float)(updateTime - _lastUpdated) / (float)(USECS_PER_SECOND); + float timeElapsed = (float)(now - _lastSimulated) / (float)(USECS_PER_SECOND); if (wantDebug) { qDebug() << "********** EntityItem::update()"; qDebug() << " entity ID=" << getEntityItemID(); - qDebug() << " updateTime=" << updateTime; - qDebug() << " _lastUpdated=" << _lastUpdated; + qDebug() << " now=" << now; + qDebug() << " _lastSimulated=" << _lastSimulated; qDebug() << " timeElapsed=" << timeElapsed; qDebug() << " hasVelocity=" << hasVelocity(); qDebug() << " hasGravity=" << hasGravity(); @@ -611,10 +612,10 @@ void EntityItem::update(const quint64& updateTime) { } } - _lastUpdated = updateTime; + _lastSimulated = now; if (wantDebug) { - qDebug() << " ********** EntityItem::update() .... SETTING _lastUpdated=" << _lastUpdated; + qDebug() << " ********** EntityItem::update() .... SETTING _lastSimulated=" << _lastSimulated; } if (hasAngularVelocity()) { @@ -707,6 +708,7 @@ void EntityItem::update(const quint64& updateTime) { velocity = NO_VELOCITY; } + // NOTE: the simulation should NOT set any DirtyFlags on this entity setPosition(position); // this will automatically recalculate our collision shape setVelocity(velocity); @@ -719,20 +721,18 @@ void EntityItem::update(const quint64& updateTime) { } } -EntityItem::SimulationState EntityItem::computeSimulationState() const { - if (hasVelocity() || (hasGravity() && !isRestingOnSurface()) || hasAngularVelocity()) { - return EntityItem::Moving; - } - if (isMortal()) { - return EntityItem::Mortal; - } - return EntityItem::Static; +bool EntityItem::isMoving() const { + return hasVelocity() || (hasGravity() && !isRestingOnSurface()) || hasAngularVelocity(); } bool EntityItem::lifetimeHasExpired() const { return isMortal() && (getAge() > getLifetime()); } +quint64 EntityItem::getExpiry() const { + return _created + (quint64)(_lifetime * (float)USECS_PER_SECOND); +} + EntityItemProperties EntityItem::getProperties() const { EntityItemProperties properties; properties._id = getID(); @@ -948,7 +948,7 @@ void EntityItem::updatePosition(const glm::vec3& value) { if (_position != value) { _position = value; recalculateCollisionShape(); - _updateFlags |= EntityItem::UPDATE_POSITION; + _dirtyFlags |= EntityItem::DIRTY_POSITION; } } @@ -957,7 +957,7 @@ void EntityItem::updatePositionInMeters(const glm::vec3& value) { if (_position != position) { _position = position; recalculateCollisionShape(); - _updateFlags |= EntityItem::UPDATE_POSITION; + _dirtyFlags |= EntityItem::DIRTY_POSITION; } } @@ -965,7 +965,7 @@ void EntityItem::updateDimensions(const glm::vec3& value) { if (_dimensions != value) { _dimensions = value; recalculateCollisionShape(); - _updateFlags |= EntityItem::UPDATE_SHAPE; + _dirtyFlags |= EntityItem::DIRTY_SHAPE; } } @@ -974,7 +974,7 @@ void EntityItem::updateDimensionsInMeters(const glm::vec3& value) { if (_dimensions != dimensions) { _dimensions = dimensions; recalculateCollisionShape(); - _updateFlags |= EntityItem::UPDATE_SHAPE; + _dirtyFlags |= EntityItem::DIRTY_SHAPE; } } @@ -982,21 +982,21 @@ void EntityItem::updateRotation(const glm::quat& rotation) { if (_rotation != rotation) { _rotation = rotation; recalculateCollisionShape(); - _updateFlags |= EntityItem::UPDATE_POSITION; + _dirtyFlags |= EntityItem::DIRTY_POSITION; } } void EntityItem::updateMass(float value) { if (_mass != value) { _mass = value; - _updateFlags |= EntityItem::UPDATE_MASS; + _dirtyFlags |= EntityItem::DIRTY_MASS; } } void EntityItem::updateVelocity(const glm::vec3& value) { if (_velocity != value) { _velocity = value; - _updateFlags |= EntityItem::UPDATE_VELOCITY; + _dirtyFlags |= EntityItem::DIRTY_VELOCITY; } } @@ -1004,14 +1004,14 @@ void EntityItem::updateVelocityInMeters(const glm::vec3& value) { glm::vec3 velocity = value / (float) TREE_SCALE; if (_velocity != velocity) { _velocity = velocity; - _updateFlags |= EntityItem::UPDATE_VELOCITY; + _dirtyFlags |= EntityItem::DIRTY_VELOCITY; } } void EntityItem::updateGravity(const glm::vec3& value) { if (_gravity != value) { _gravity = value; - _updateFlags |= EntityItem::UPDATE_VELOCITY; + _dirtyFlags |= EntityItem::DIRTY_VELOCITY; } } @@ -1019,35 +1019,35 @@ void EntityItem::updateGravityInMeters(const glm::vec3& value) { glm::vec3 gravity = value / (float) TREE_SCALE; if (_gravity != gravity) { _gravity = gravity; - _updateFlags |= EntityItem::UPDATE_VELOCITY; + _dirtyFlags |= EntityItem::DIRTY_VELOCITY; } } void EntityItem::updateAngularVelocity(const glm::vec3& value) { if (_angularVelocity != value) { _angularVelocity = value; - _updateFlags |= EntityItem::UPDATE_VELOCITY; + _dirtyFlags |= EntityItem::DIRTY_VELOCITY; } } void EntityItem::updateIgnoreForCollisions(bool value) { if (_ignoreForCollisions != value) { _ignoreForCollisions = value; - _updateFlags |= EntityItem::UPDATE_COLLISION_GROUP; + _dirtyFlags |= EntityItem::DIRTY_COLLISION_GROUP; } } void EntityItem::updateCollisionsWillMove(bool value) { if (_collisionsWillMove != value) { _collisionsWillMove = value; - _updateFlags |= EntityItem::UPDATE_MOTION_TYPE; + _dirtyFlags |= EntityItem::DIRTY_MOTION_TYPE; } } void EntityItem::updateLifetime(float value) { if (_lifetime != value) { _lifetime = value; - _updateFlags |= EntityItem::UPDATE_LIFETIME; + _dirtyFlags |= EntityItem::DIRTY_LIFETIME; } } diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 7dbcaed8fc..f0d3330087 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -41,15 +41,14 @@ class EntityTreeElementExtraEncodeData; class EntityItem { public: - enum EntityUpdateFlags { - UPDATE_POSITION = 0x0001, - UPDATE_VELOCITY = 0x0002, - UPDATE_MASS = 0x0004, - UPDATE_COLLISION_GROUP = 0x0008, - UPDATE_MOTION_TYPE = 0x0010, - UPDATE_SHAPE = 0x0020, - UPDATE_LIFETIME = 0x0040 - //UPDATE_APPEARANCE = 0x8000, + enum EntityDirtyFlags { + DIRTY_POSITION = 0x0001, + DIRTY_VELOCITY = 0x0002, + DIRTY_MASS = 0x0004, + DIRTY_COLLISION_GROUP = 0x0008, + DIRTY_MOTION_TYPE = 0x0010, + DIRTY_SHAPE = 0x0020, + DIRTY_LIFETIME = 0x0040 }; DONT_ALLOW_INSTANTIATION // This class can not be instantiated directly @@ -77,12 +76,12 @@ public: /// has changed. This will be called with properties change or when new data is loaded from a stream virtual void somethingChangedNotification() { } - quint64 getLastUpdated() const { return _lastUpdated; } /// Last simulated time of this entity universal usecs + quint64 getLastSimulated() const { return _lastSimulated; } /// Last simulated time of this entity universal usecs /// Last edited time of this entity universal usecs quint64 getLastEdited() const { return _lastEdited; } void setLastEdited(quint64 lastEdited) - { _lastEdited = _lastUpdated = lastEdited; _changedOnServer = glm::max(lastEdited, _changedOnServer); } + { _lastEdited = _lastSimulated = _lastUpdated = lastEdited; _changedOnServer = glm::max(lastEdited, _changedOnServer); } float getEditedAgo() const /// Elapsed seconds since this entity was last edited { return (float)(usecTimestampNow() - getLastEdited()) / (float)USECS_PER_SECOND; } @@ -121,17 +120,14 @@ public: unsigned char* bufferOut, int sizeIn, int& sizeOut); static void adjustEditPacketForClockSkew(unsigned char* codeColorBuffer, size_t length, int clockSkew); - virtual void update(const quint64& now); + + // perform update + virtual void update(const quint64& now) { _lastUpdated = now; } - typedef enum SimulationState_t { - Static, - Mortal, - Moving - } SimulationState; + // perform linear extrapolation for SimpleEntitySimulation + void simulate(const quint64& now); - // computes the SimulationState that the entity SHOULD be in. - // Use getSimulationState() to find the state under which it is currently categorized. - virtual SimulationState computeSimulationState() const; + bool needsToCallUpdate() const { return false; } virtual void debugDump() const; @@ -221,11 +217,14 @@ public: /// age of this entity in seconds float getAge() const { return (float)(usecTimestampNow() - _created) / (float)USECS_PER_SECOND; } bool lifetimeHasExpired() const; + quint64 getExpiry() const; // position, size, and bounds related helpers float getSize() const; /// get maximum dimension in domain scale units (0.0 - 1.0) AACube getMaximumAACube() const; AACube getMinimumAACube() const; + AACube getOldMaximumAACube() const { return _oldMaximumAACube; } + void setOldMaximumAACube(const AACube& cube) { _oldMaximumAACube = cube; } AABox getAABox() const; /// axis aligned bounding box in domain scale units (0.0 - 1.0) static const QString DEFAULT_SCRIPT; @@ -278,7 +277,7 @@ public: virtual const Shape& getCollisionShapeInMeters() const { return _collisionShape; } virtual bool contains(const glm::vec3& point) const { return getAABox().contains(point); } - // updateFoo() methods to be used when changes need to be accumulated in the _updateFlags + // updateFoo() methods to be used when changes need to be accumulated in the _dirtyFlags void updatePosition(const glm::vec3& value); void updatePositionInMeters(const glm::vec3& value); void updateDimensions(const glm::vec3& value); @@ -294,12 +293,11 @@ public: void updateCollisionsWillMove(bool value); void updateLifetime(float value); - uint32_t getUpdateFlags() const { return _updateFlags; } - void clearUpdateFlags() { _updateFlags = 0; } - - SimulationState getSimulationState() const { return _simulationState; } + uint32_t getDirtyFlags() const { return _dirtyFlags; } + void clearDirtyFlags(uint32_t mask = 0xffff) { _dirtyFlags &= ~mask; } - void setSimulationState(SimulationState state) { _simulationState = state; } + bool isMoving() const; + protected: virtual void initFromEntityItemID(const EntityItemID& entityItemID); // maybe useful to allow subclasses to init @@ -309,7 +307,8 @@ protected: QUuid _id; uint32_t _creatorTokenID; bool _newlyCreated; - quint64 _lastUpdated; + quint64 _lastSimulated; // last time this entity called simulate() + quint64 _lastUpdated; // last time this entity called update() quint64 _lastEdited; // this is the last official local or remote edit time quint64 _lastEditedFromRemote; // this is the last time we received and edit from the server quint64 _lastEditedFromRemoteInRemoteTime; // time in server time space the last time we received and edit from the server @@ -343,11 +342,10 @@ protected: void setRadius(float value); AACubeShape _collisionShape; - SimulationState _simulationState; // only set by EntityTree + AACube _oldMaximumAACube; // remember this so we know where the entity used to live in the tree - // UpdateFlags are set whenever a property changes that requires the change to be communicated to other - // data structures. It is the responsibility of the EntityTree to relay changes entity and clear flags. - uint32_t _updateFlags; + // DirtyFlags are set whenever a property changes that the EntitySimulation needs to know about. + uint32_t _dirtyFlags; // things that have changed from EXTERNAL changes (via script or packet) but NOT from simulation }; diff --git a/libraries/entities/src/EntitySimulation.cpp b/libraries/entities/src/EntitySimulation.cpp index 8058c2f24e..223df588d5 100644 --- a/libraries/entities/src/EntitySimulation.cpp +++ b/libraries/entities/src/EntitySimulation.cpp @@ -9,12 +9,178 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include + #include "EntitySimulation.h" +#include "MovingEntitiesOperator.h" void EntitySimulation::setEntityTree(EntityTree* tree) { if (_entityTree && _entityTree != tree) { - clearEntities(); + _mortalEntities.clear(); + _nextExpiry = quint64(-1); + _updateableEntities.clear(); + _entitiesToBeSorted.clear(); } _entityTree = tree; } +void EntitySimulation::updateEntities(QSet& entitiesToDelete) { + quint64 now = usecTimestampNow(); + + // these methods may accumulate entries in _entitiesToBeDeleted + expireMortalEntities(now); + callUpdateOnEntitiesThatNeedIt(now); + updateEntitiesInternal(now); + sortEntitiesThatMoved(); + + // at this point we harvest _entitiesToBeDeleted + entitiesToDelete.unite(_entitiesToDelete); + _entitiesToDelete.clear(); +} + +void EntitySimulation::expireMortalEntities(const quint64& now) { + if (now > _nextExpiry) { + // only search for expired entities if we expect to find one + _nextExpiry = quint64(-1); + QSet::iterator itemItr = _mortalEntities.begin(); + while (itemItr != _mortalEntities.end()) { + EntityItem* entity = *itemItr; + quint64 expiry = entity->getExpiry(); + if (expiry < now) { + _entitiesToDelete.insert(entity); + itemItr = _mortalEntities.erase(itemItr); + _updateableEntities.remove(entity); + _entitiesToBeSorted.remove(entity); + removeEntityInternal(entity); + } else { + if (expiry < _nextExpiry) { + // remeber the smallest _nextExpiry so we know when to start the next search + _nextExpiry = expiry; + } + ++itemItr; + } + } + } +} + +void EntitySimulation::callUpdateOnEntitiesThatNeedIt(const quint64& now) { + PerformanceTimer perfTimer("updatingEntities"); + QSet::iterator itemItr = _updateableEntities.begin(); + while (itemItr != _updateableEntities.end()) { + EntityItem* entity = *itemItr; + // TODO: catch transition from needing update to not as a "change" + // so we don't have to scan for it here. + if (!entity->needsToCallUpdate()) { + itemItr = _updateableEntities.erase(itemItr); + } else { + entity->update(now); + ++itemItr; + } + } +} + +void EntitySimulation::sortEntitiesThatMoved() { + // NOTE: this is only for entities that have been moved by THIS EntitySimulation. + // External changes to entity position/shape are expected to be sorted outside of the EntitySimulation. + PerformanceTimer perfTimer("sortingEntities"); + MovingEntitiesOperator moveOperator(_entityTree); + AACube domainBounds(glm::vec3(0.0f,0.0f,0.0f), 1.0f); + QSet::iterator itemItr = _entitiesToBeSorted.begin(); + while (itemItr != _entitiesToBeSorted.end()) { + EntityItem* entity = *itemItr; + // check to see if this movement has sent the entity outside of the domain. + AACube newCube = entity->getMaximumAACube(); + if (!domainBounds.touches(newCube)) { + qDebug() << "Entity " << entity->getEntityItemID() << " moved out of domain bounds."; + _entitiesToDelete.insert(entity); + _mortalEntities.remove(entity); + _updateableEntities.remove(entity); + removeEntityInternal(entity); + } else { + moveOperator.addEntityToMoveList(entity, newCube); + } + ++itemItr; + } + _entitiesToBeSorted.clear(); + + if (moveOperator.hasMovingEntities()) { + PerformanceTimer perfTimer("recurseTreeWithOperator"); + _entityTree->recurseTreeWithOperator(&moveOperator); + moveOperator.finish(); + } +} + +void EntitySimulation::addEntity(EntityItem* entity) { + assert(entity); + if (entity->isMortal()) { + _mortalEntities.insert(entity); + quint64 expiry = entity->getExpiry(); + if (expiry < _nextExpiry) { + _nextExpiry = expiry; + } + } + if (entity->needsToCallUpdate()) { + _updateableEntities.insert(entity); + } + addEntityInternal(entity); +} + +void EntitySimulation::removeEntity(EntityItem* entity) { + assert(entity); + _updateableEntities.remove(entity); + _mortalEntities.remove(entity); + _entitiesToBeSorted.remove(entity); + _entitiesToDelete.remove(entity); + removeEntityInternal(entity); +} + +void EntitySimulation::entityChanged(EntityItem* entity) { + assert(entity); + + // Although it is not the responsibility of the EntitySimulation to sort the tree for EXTERNAL changes + // it IS responsibile for triggering deletes for entities that leave the bounds of the domain, hence + // we must check for that case here, however we rely on the change event to have set DIRTY_POSITION flag. + bool wasRemoved = false; + uint32_t dirtyFlags = entity->getDirtyFlags(); + if (dirtyFlags & EntityItem::DIRTY_POSITION) { + AACube domainBounds(glm::vec3(0.0f,0.0f,0.0f), 1.0f); + AACube newCube = entity->getMaximumAACube(); + if (!domainBounds.touches(newCube)) { + qDebug() << "Entity " << entity->getEntityItemID() << " moved out of domain bounds."; + _entitiesToDelete.insert(entity); + _mortalEntities.remove(entity); + _updateableEntities.remove(entity); + removeEntityInternal(entity); + wasRemoved = true; + } + } + if (!wasRemoved) { + if (dirtyFlags & EntityItem::DIRTY_LIFETIME) { + if (entity->isMortal()) { + _mortalEntities.insert(entity); + quint64 expiry = entity->getExpiry(); + if (expiry < _nextExpiry) { + _nextExpiry = expiry; + } + } else { + _mortalEntities.remove(entity); + } + entity->clearDirtyFlags(EntityItem::DIRTY_LIFETIME); + } + if (entity->needsToCallUpdate()) { + _updateableEntities.insert(entity); + } else { + _updateableEntities.remove(entity); + } + entityChangedInternal(entity); + } + entity->clearDirtyFlags(); +} + +void EntitySimulation::clearEntities() { + _mortalEntities.clear(); + _nextExpiry = quint64(-1); + _updateableEntities.clear(); + _entitiesToBeSorted.clear(); + clearEntitiesInternal(); +} diff --git a/libraries/entities/src/EntitySimulation.h b/libraries/entities/src/EntitySimulation.h index 770d6ebdb0..506e2ed9d0 100644 --- a/libraries/entities/src/EntitySimulation.h +++ b/libraries/entities/src/EntitySimulation.h @@ -14,36 +14,61 @@ #include +#include + #include "EntityTree.h" class EntitySimulation { public: EntitySimulation() : _entityTree(NULL) { } - virtual ~EntitySimulation() {} + virtual ~EntitySimulation() { setEntityTree(NULL); } /// \param tree pointer to EntityTree which is stored internally - virtual void setEntityTree(EntityTree* tree); + void setEntityTree(EntityTree* tree); /// \param[out] entitiesToDelete list of entities removed from simulation and should be deleted. - virtual void update(QSet& entitiesToDelete) = 0; + void updateEntities(QSet& entitiesToDelete); /// \param entity pointer to EntityItem to add to the simulation /// \sideeffect the EntityItem::_simulationState member may be updated to indicate membership to internal list - virtual void addEntity(EntityItem* entity) = 0; + void addEntity(EntityItem* entity); /// \param entity pointer to EntityItem to removed from the simulation /// \sideeffect the EntityItem::_simulationState member may be updated to indicate non-membership to internal list - virtual void removeEntity(EntityItem* entity) = 0; + void removeEntity(EntityItem* entity); /// \param entity pointer to EntityItem to that may have changed in a way that would affect its simulation - virtual void entityChanged(EntityItem* entity) = 0; + /// call this whenever an entity was changed from some EXTERNAL event (NOT by the EntitySimulation itself) + void entityChanged(EntityItem* entity); - virtual void clearEntities() = 0; + void clearEntities(); EntityTree* getEntityTree() { return _entityTree; } protected: + + // These pure virtual methods are protected because they are not to be called will-nilly. The base class + // calls them in the right places. + virtual void updateEntitiesInternal(const quint64& now) = 0; + virtual void addEntityInternal(EntityItem* entity) = 0; + virtual void removeEntityInternal(EntityItem* entity) = 0; + virtual void entityChangedInternal(EntityItem* entity) = 0; + virtual void clearEntitiesInternal() = 0; + + void expireMortalEntities(const quint64& now); + void callUpdateOnEntitiesThatNeedIt(const quint64& now); + void sortEntitiesThatMoved(); + + // back pointer to EntityTree structure EntityTree* _entityTree; + + // We maintain multiple lists, each for its distinct purpose. + // An entity may be in more than one list. + QSet _mortalEntities; // entities that have an expiry + quint64 _nextExpiry; + QSet _updateableEntities; // entities that need update() called + QSet _entitiesToBeSorted; // entities that were moved by THIS simulation and might need to be resorted in the tree + QSet _entitiesToDelete; }; #endif // hifi_EntitySimulation_h diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index d3d9e2da53..8c18f965aa 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -79,6 +79,7 @@ EntityItem* EntityTree::getOrCreateEntityItem(const EntityItemID& entityID, cons /// Adds a new entity item to the tree void EntityTree::postAddEntity(EntityItem* entity) { assert(entity); + entity->setOldMaximumAACube(entity->getMaximumAACube()); // check to see if we need to simulate this entity.. if (_simulation) { _simulation->addEntity(entity); @@ -99,51 +100,64 @@ bool EntityTree::updateEntity(const EntityItemID& entityID, const EntityItemProp qDebug() << "UNEXPECTED!!!! don't call updateEntity() on entity items that don't exist. entityID=" << entityID; return false; } - + + return updateEntityWithElement(existingEntity, properties, containingElement); +} + +bool EntityTree::updateEntity(EntityItem* entity, const EntityItemProperties& properties) { + EntityTreeElement* containingElement = getContainingElement(entity->getEntityItemID()); + if (!containingElement) { + qDebug() << "UNEXPECTED!!!! EntityTree::updateEntity() entity-->element lookup failed!!! entityID=" + << entity->getEntityItemID(); + return false; + } + return updateEntityWithElement(entity, properties, containingElement); +} + +bool EntityTree::updateEntityWithElement(EntityItem* entity, const EntityItemProperties& properties, + EntityTreeElement* containingElement) { // enforce support for locked entities. If an entity is currently locked, then the only // property we allow you to change is the locked property. - if (existingEntity->getLocked()) { + if (entity->getLocked()) { if (properties.lockedChanged()) { bool wantsLocked = properties.getLocked(); if (!wantsLocked) { EntityItemProperties tempProperties; tempProperties.setLocked(wantsLocked); - UpdateEntityOperator theOperator(this, containingElement, existingEntity, tempProperties); + UpdateEntityOperator theOperator(this, containingElement, entity, tempProperties); recurseTreeWithOperator(&theOperator); _isDirty = true; - if (_simulation && existingEntity->getUpdateFlags() != 0) { - _simulation->entityChanged(existingEntity); - } } } } else { - // check to see if we need to simulate this entity... - QString entityScriptBefore = existingEntity->getScript(); + QString entityScriptBefore = entity->getScript(); - UpdateEntityOperator theOperator(this, containingElement, existingEntity, properties); + UpdateEntityOperator theOperator(this, containingElement, entity, properties); recurseTreeWithOperator(&theOperator); + entity->setOldMaximumAACube(entity->getMaximumAACube()); _isDirty = true; - if (_simulation && existingEntity->getUpdateFlags() != 0) { - _simulation->entityChanged(existingEntity); + if (_simulation && entity->getDirtyFlags() != 0) { + _simulation->entityChanged(entity); } - QString entityScriptAfter = existingEntity->getScript(); + QString entityScriptAfter = entity->getScript(); if (entityScriptBefore != entityScriptAfter) { - emitEntityScriptChanging(entityID); // the entity script has changed + emit entityScriptChanging(entity->getEntityItemID()); // the entity script has changed } } - containingElement = getContainingElement(entityID); + // TODO: this final containingElement check should eventually be removed (or wrapped in an #ifdef DEBUG). + containingElement = getContainingElement(entity->getEntityItemID()); if (!containingElement) { - qDebug() << "UNEXPECTED!!!! after updateEntity() we no longer have a containing element??? entityID=" << entityID; + qDebug() << "UNEXPECTED!!!! after updateEntity() we no longer have a containing element??? entityID=" + << entity->getEntityItemID(); return false; } return true; } - EntityItem* EntityTree::addEntity(const EntityItemID& entityID, const EntityItemProperties& properties) { EntityItem* result = NULL; @@ -572,7 +586,7 @@ void EntityTree::update() { if (_simulation) { lockForWrite(); QSet entitiesToDelete; - _simulation->update(entitiesToDelete); + _simulation->updateEntities(entitiesToDelete); if (entitiesToDelete.size() > 0) { // translate into list of ID's QSet idsToDelete; diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index eeb0182042..9a0fb43ecb 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -82,7 +82,13 @@ public: void postAddEntity(EntityItem* entityItem); EntityItem* addEntity(const EntityItemID& entityID, const EntityItemProperties& properties); + + // use this method if you only know the entityID bool updateEntity(const EntityItemID& entityID, const EntityItemProperties& properties); + + // use this method if you have a pointer to the entity (avoid an extra entity lookup) + bool updateEntity(EntityItem* entity, const EntityItemProperties& properties); + void deleteEntity(const EntityItemID& entityID); void deleteEntities(QSet entityIDs); void removeEntityFromSimulation(EntityItem* entity); @@ -156,6 +162,8 @@ signals: private: + bool updateEntityWithElement(EntityItem* entity, const EntityItemProperties& properties, + EntityTreeElement* containingElement); static bool findNearPointOperation(OctreeElement* element, void* extraData); static bool findInSphereOperation(OctreeElement* element, void* extraData); static bool findInCubeOperation(OctreeElement* element, void* extraData); diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index e18f79276e..d3e303009c 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -757,7 +757,7 @@ int EntityTreeElement::readElementDataFromBuffer(const unsigned char* data, int EntityTreeElement* currentContainingElement = _myTree->getContainingElement(entityItemID); bytesForThisEntity = entityItem->readEntityDataFromBuffer(dataAt, bytesLeftToRead, args); - if (entityItem->getUpdateFlags()) { + if (entityItem->getDirtyFlags()) { _myTree->entityChanged(entityItem); } bool bestFitAfter = bestFitEntityBounds(entityItem); diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index 0de2035dec..565974d19e 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -373,17 +373,11 @@ bool ModelEntityItem::isAnimatingSomething() const { !getAnimationURL().isEmpty(); } -EntityItem::SimulationState ModelEntityItem::computeSimulationState() const { - // if we're animating then we need to have update() periodically called on this entity - // which means we need to categorized as Moving - return isAnimatingSomething() ? EntityItem::Moving : EntityItem::computeSimulationState(); +bool ModelEntityItem::needsToCallUpdate() const { + return isAnimatingSomething() ? true : EntityItem::needsToCallUpdate(); } -void ModelEntityItem::update(const quint64& updateTime) { - EntityItem::update(updateTime); // let our base class handle it's updates... - - quint64 now = updateTime; - +void ModelEntityItem::update(const quint64& now) { // only advance the frame index if we're playing if (getAnimationIsPlaying()) { float deltaTime = (float)(now - _lastAnimated) / (float)USECS_PER_SECOND; @@ -392,6 +386,7 @@ void ModelEntityItem::update(const quint64& updateTime) { } else { _lastAnimated = now; } + EntityItem::update(now); // let our base class handle it's updates... } void ModelEntityItem::debugDump() const { diff --git a/libraries/entities/src/ModelEntityItem.h b/libraries/entities/src/ModelEntityItem.h index 0b2508ec80..502b21af12 100644 --- a/libraries/entities/src/ModelEntityItem.h +++ b/libraries/entities/src/ModelEntityItem.h @@ -46,7 +46,7 @@ public: EntityPropertyFlags& propertyFlags, bool overwriteLocalData); virtual void update(const quint64& now); - virtual SimulationState computeSimulationState() const; + virtual bool needsToCallUpdate() const; virtual void debugDump() const; diff --git a/libraries/entities/src/MovingEntitiesOperator.cpp b/libraries/entities/src/MovingEntitiesOperator.cpp index 045e07a910..86b8de7b10 100644 --- a/libraries/entities/src/MovingEntitiesOperator.cpp +++ b/libraries/entities/src/MovingEntitiesOperator.cpp @@ -49,9 +49,10 @@ MovingEntitiesOperator::~MovingEntitiesOperator() { } -void MovingEntitiesOperator::addEntityToMoveList(EntityItem* entity, const AACube& oldCube, const AACube& newCube) { +void MovingEntitiesOperator::addEntityToMoveList(EntityItem* entity, const AACube& newCube) { EntityTreeElement* oldContainingElement = _tree->getContainingElement(entity->getEntityItemID()); AABox newCubeClamped = newCube.clamp(0.0f, 1.0f); + AACube oldCube = entity->getOldMaximumAACube(); AABox oldCubeClamped = oldCube.clamp(0.0f, 1.0f); if (_wantDebug) { @@ -290,3 +291,9 @@ OctreeElement* MovingEntitiesOperator::possiblyCreateChildAt(OctreeElement* elem } return NULL; } + +void MovingEntitiesOperator::finish() { + foreach(const EntityToMoveDetails& details, _entitiesToMove) { + details.entity->setOldMaximumAACube(details.newCube); + } +} diff --git a/libraries/entities/src/MovingEntitiesOperator.h b/libraries/entities/src/MovingEntitiesOperator.h index fbec898cec..bddf5da450 100644 --- a/libraries/entities/src/MovingEntitiesOperator.h +++ b/libraries/entities/src/MovingEntitiesOperator.h @@ -38,11 +38,12 @@ public: MovingEntitiesOperator(EntityTree* tree); ~MovingEntitiesOperator(); - void addEntityToMoveList(EntityItem* entity, const AACube& oldCube, const AACube& newCube); + void addEntityToMoveList(EntityItem* entity, const AACube& newCube); virtual bool preRecursion(OctreeElement* element); virtual bool postRecursion(OctreeElement* element); virtual OctreeElement* possiblyCreateChildAt(OctreeElement* element, int childIndex); bool hasMovingEntities() const { return _entitiesToMove.size() > 0; } + void finish(); private: EntityTree* _tree; QSet _entitiesToMove; diff --git a/libraries/entities/src/SimpleEntitySimulation.cpp b/libraries/entities/src/SimpleEntitySimulation.cpp index b3316978a9..b962f6980e 100644 --- a/libraries/entities/src/SimpleEntitySimulation.cpp +++ b/libraries/entities/src/SimpleEntitySimulation.cpp @@ -9,216 +9,63 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include -#include +//#include #include "EntityItem.h" -#include "MovingEntitiesOperator.h" #include "SimpleEntitySimulation.h" -void SimpleEntitySimulation::update(QSet& entitiesToDelete) { - quint64 now = usecTimestampNow(); - updateChangedEntities(now, entitiesToDelete); - updateMovingEntities(now, entitiesToDelete); - updateMortalEntities(now, entitiesToDelete); -} -void SimpleEntitySimulation::addEntity(EntityItem* entity) { - assert(entity && entity->getSimulationState() == EntityItem::Static); - EntityItem::SimulationState state = entity->computeSimulationState(); - switch(state) { - case EntityItem::Moving: - _movingEntities.push_back(entity); - entity->setSimulationState(state); - break; - case EntityItem::Mortal: - _mortalEntities.push_back(entity); - entity->setSimulationState(state); - break; - case EntityItem::Static: - default: - break; +void SimpleEntitySimulation::updateEntitiesInternal(const quint64& now) { + QSet::iterator itemItr = _movingEntities.begin(); + while (itemItr != _movingEntities.end()) { + EntityItem* entity = *itemItr; + if (!entity->isMoving()) { + itemItr = _movingEntities.erase(itemItr); + _movableButStoppedEntities.insert(entity); + } else { + entity->simulate(now); + _entitiesToBeSorted.insert(entity); + } } } -void SimpleEntitySimulation::removeEntity(EntityItem* entity) { - assert(entity); - // make sure to remove it from any of our simulation lists - EntityItem::SimulationState state = entity->getSimulationState(); - switch (state) { - case EntityItem::Moving: - _movingEntities.removeAll(entity); - break; - case EntityItem::Mortal: - _mortalEntities.removeAll(entity); - break; - - default: - break; +void SimpleEntitySimulation::addEntityInternal(EntityItem* entity) { + if (entity->getCollisionsWillMove()) { + if (entity->isMoving()) { + _movingEntities.insert(entity); + } else { + _movableButStoppedEntities.insert(entity); + } } - entity->setSimulationState(EntityItem::Static); - _changedEntities.remove(entity); } -void SimpleEntitySimulation::entityChanged(EntityItem* entity) { - assert(entity); - // we batch all changes and deal with them in updateChangedEntities() - _changedEntities.insert(entity); +void SimpleEntitySimulation::removeEntityInternal(EntityItem* entity) { + _movingEntities.remove(entity); + _movableButStoppedEntities.remove(entity); } -void SimpleEntitySimulation::clearEntities() { - foreach (EntityItem* entity, _changedEntities) { - entity->clearUpdateFlags(); - entity->setSimulationState(EntityItem::Static); +const int SIMPLE_SIMULATION_DIRTY_FLAGS = EntityItem::DIRTY_VELOCITY | EntityItem::DIRTY_MOTION_TYPE; + +void SimpleEntitySimulation::entityChangedInternal(EntityItem* entity) { + int dirtyFlags = entity->getDirtyFlags(); + if (dirtyFlags & SIMPLE_SIMULATION_DIRTY_FLAGS) { + if (entity->getCollisionsWillMove()) { + if (entity->isMoving()) { + _movingEntities.insert(entity); + _movableButStoppedEntities.remove(entity); + } else { + _movingEntities.remove(entity); + _movableButStoppedEntities.insert(entity); + } + } else { + _movingEntities.remove(entity); + _movableButStoppedEntities.remove(entity); + } } - _changedEntities.clear(); +} + +void SimpleEntitySimulation::clearEntitiesInternal() { _movingEntities.clear(); - _mortalEntities.clear(); -} - -void SimpleEntitySimulation::updateChangedEntities(quint64 now, QSet& entitiesToDelete) { - foreach (EntityItem* entity, _changedEntities) { - // check to see if the lifetime has expired, for immortal entities this is always false - if (entity->lifetimeHasExpired()) { - qDebug() << "Lifetime has expired for entity:" << entity->getEntityItemID(); - entitiesToDelete.insert(entity); - clearEntityState(entity); - } else { - updateEntityState(entity); - } - entity->clearUpdateFlags(); - } - _changedEntities.clear(); + _movableButStoppedEntities.clear(); } -void SimpleEntitySimulation::updateMovingEntities(quint64 now, QSet& entitiesToDelete) { - if (_entityTree && _movingEntities.size() > 0) { - PerformanceTimer perfTimer("_movingEntities"); - MovingEntitiesOperator moveOperator(_entityTree); - QList::iterator item_itr = _movingEntities.begin(); - while (item_itr != _movingEntities.end()) { - EntityItem* entity = *item_itr; - - // always check to see if the lifetime has expired, for immortal entities this is always false - if (entity->lifetimeHasExpired()) { - qDebug() << "Lifetime has expired for entity:" << entity->getEntityItemID(); - entitiesToDelete.insert(entity); - // remove entity from the list - item_itr = _movingEntities.erase(item_itr); - entity->setSimulationState(EntityItem::Static); - } else { - AACube oldCube = entity->getMaximumAACube(); - entity->update(now); - AACube newCube = entity->getMaximumAACube(); - - // check to see if this movement has sent the entity outside of the domain. - AACube domainBounds(glm::vec3(0.0f,0.0f,0.0f), 1.0f); - if (!domainBounds.touches(newCube)) { - qDebug() << "Entity " << entity->getEntityItemID() << " moved out of domain bounds."; - entitiesToDelete.insert(entity); - // remove entity from the list - item_itr = _movingEntities.erase(item_itr); - entity->setSimulationState(EntityItem::Static); - } else { - moveOperator.addEntityToMoveList(entity, oldCube, newCube); - EntityItem::SimulationState newState = entity->computeSimulationState(); - if (newState != EntityItem::Moving) { - if (newState == EntityItem::Mortal) { - _mortalEntities.push_back(entity); - } - // remove entity from the list - item_itr = _movingEntities.erase(item_itr); - entity->setSimulationState(newState); - } else { - ++item_itr; - } - } - } - } - if (moveOperator.hasMovingEntities()) { - PerformanceTimer perfTimer("recurseTreeWithOperator"); - _entityTree->recurseTreeWithOperator(&moveOperator); - } - } -} - -void SimpleEntitySimulation::updateMortalEntities(quint64 now, QSet& entitiesToDelete) { - QList::iterator item_itr = _mortalEntities.begin(); - while (item_itr != _mortalEntities.end()) { - EntityItem* entity = *item_itr; - // always check to see if the lifetime has expired, for immortal entities this is always false - if (entity->lifetimeHasExpired()) { - qDebug() << "Lifetime has expired for entity:" << entity->getEntityItemID(); - entitiesToDelete.insert(entity); - // remove entity from the list - item_itr = _mortalEntities.erase(item_itr); - entity->setSimulationState(EntityItem::Static); - } else { - // check to see if this entity is no longer moving - EntityItem::SimulationState newState = entity->computeSimulationState(); - if (newState != EntityItem::Mortal) { - if (newState == EntityItem::Moving) { - entity->update(now); - _movingEntities.push_back(entity); - } - // remove entity from the list - item_itr = _mortalEntities.erase(item_itr); - entity->setSimulationState(newState); - } else { - ++item_itr; - } - } - } -} - -void SimpleEntitySimulation::updateEntityState(EntityItem* entity) { - EntityItem::SimulationState oldState = entity->getSimulationState(); - EntityItem::SimulationState newState = entity->computeSimulationState(); - if (newState != oldState) { - switch (oldState) { - case EntityItem::Moving: - _movingEntities.removeAll(entity); - break; - - case EntityItem::Mortal: - _mortalEntities.removeAll(entity); - break; - - default: - break; - } - - switch (newState) { - case EntityItem::Moving: - _movingEntities.push_back(entity); - break; - - case EntityItem::Mortal: - _mortalEntities.push_back(entity); - break; - - default: - break; - } - entity->setSimulationState(newState); - } -} - -void SimpleEntitySimulation::clearEntityState(EntityItem* entity) { - EntityItem::SimulationState oldState = entity->getSimulationState(); - switch (oldState) { - case EntityItem::Moving: - _movingEntities.removeAll(entity); - break; - - case EntityItem::Mortal: - _mortalEntities.removeAll(entity); - break; - - default: - break; - } - entity->setSimulationState(EntityItem::Static); -} - - diff --git a/libraries/entities/src/SimpleEntitySimulation.h b/libraries/entities/src/SimpleEntitySimulation.h index 7d0e8f0113..92b6a28215 100644 --- a/libraries/entities/src/SimpleEntitySimulation.h +++ b/libraries/entities/src/SimpleEntitySimulation.h @@ -19,29 +19,17 @@ class SimpleEntitySimulation : public EntitySimulation { public: SimpleEntitySimulation() : EntitySimulation() { } - virtual ~SimpleEntitySimulation() { setEntityTree(NULL); } - - virtual void update(QSet& entitiesToDelete); - - virtual void addEntity(EntityItem* entity); - virtual void removeEntity(EntityItem* entity); - virtual void entityChanged(EntityItem* entity); - - virtual void clearEntities(); + virtual ~SimpleEntitySimulation() { clearEntitiesInternal(); } protected: - void updateEntityState(EntityItem* entity); - void clearEntityState(EntityItem* entity); + virtual void updateEntitiesInternal(const quint64& now); + virtual void addEntityInternal(EntityItem* entity); + virtual void removeEntityInternal(EntityItem* entity); + virtual void entityChangedInternal(EntityItem* entity); + virtual void clearEntitiesInternal(); - QList& getMovingEntities() { return _movingEntities; } - - void updateChangedEntities(quint64 now, QSet& entitiesToDelete); - void updateMovingEntities(quint64 now, QSet& entitiesToDelete); - void updateMortalEntities(quint64 now, QSet& entitiesToDelete); - - QSet _changedEntities; // entities that have changed in the last frame - QList _movingEntities; // entities that need to be updated - QList _mortalEntities; // non-moving entities that need to be checked for expiry + QSet _movingEntities; + QSet _movableButStoppedEntities; }; #endif // hifi_SimpleEntitySimulation_h From f1c6e2d1a23db6b3c276565110c6c3c0fa8fca69 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 5 Dec 2014 19:52:48 -0800 Subject: [PATCH 261/502] more debugging --- interface/src/Application.cpp | 17 ++++++++ .../entities/RenderableModelEntityItem.cpp | 2 + interface/src/renderer/Model.cpp | 39 +++++++++++++++++++ 3 files changed, 58 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 44f83102e2..863bca8a85 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -434,6 +434,23 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : #endif this->installEventFilter(this); + + + + + qDebug() << "------------------------------------------------------------"; + qDebug() << " test findRayTrianlgeIntersection()...."; + float distanceA; + bool testA = findRayTrianlgeIntersection(glm::vec3(0.5,0.5,1), glm::vec3(0,0,-1), glm::vec3(0,0,0), glm::vec3(1,0,0), glm::vec3(0,1,0), distanceA); + qDebug() << " testA:" << testA; + qDebug() << " distanceA:" << distanceA; + + float distanceB; + bool testB = findRayTrianlgeIntersection(glm::vec3(0.5,0.5,1), glm::vec3(0,0,-1), glm::vec3(0,0,0), glm::vec3(0,1,0), glm::vec3(1,0,0), distanceB); + qDebug() << " testB:" << testB; + qDebug() << " distanceB:" << distanceB; + qDebug() << "------------------------------------------------------------"; + } void Application::aboutToQuit() { diff --git a/interface/src/entities/RenderableModelEntityItem.cpp b/interface/src/entities/RenderableModelEntityItem.cpp index 6bc6f52782..e2fd50ceee 100644 --- a/interface/src/entities/RenderableModelEntityItem.cpp +++ b/interface/src/entities/RenderableModelEntityItem.cpp @@ -262,6 +262,8 @@ bool RenderableModelEntityItem::findDetailedRayIntersection(const glm::vec3& ori void** intersectedObject) const { qDebug() << "RenderableModelEntityItem::findDetailedRayIntersection()...."; + qDebug() << " this.id:" << getEntityItemID(); + qDebug() << " this.modelURL:" << getModelURL(); qDebug() << " origin:" << origin; glm::vec3 originInMeters = origin * (float)TREE_SCALE; qDebug() << " originInMeters:" << originInMeters; diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index a259e42117..3606a17cf8 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -584,6 +584,7 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g qDebug() << " distanceToSubMesh < bestDistance !! looks like a good match!"; if (pickAgainstTriangles) { + qDebug() << " subMeshBox[" << subMeshIndex <<"] --- check triangles!!"; if (!_calculatedMeshTrianglesValid) { recalcuateMeshBoxes(); } @@ -596,9 +597,15 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g float thisTriangleDistance; if (findRayTrianlgeIntersection(origin, direction, triangle, thisTriangleDistance)) { + qDebug() << " subMeshBox[" << subMeshIndex <<"].triangle[" << t <<"] --- HITS!!"; + qDebug() << " subMeshBox[" << subMeshIndex <<"].triangle[" << t <<"] thisTriangleDistance:" << thisTriangleDistance; + qDebug() << " subMeshBox[" << subMeshIndex <<"].triangle[" << t <<"] bestTriangleDistance:" << bestTriangleDistance; if (thisTriangleDistance < bestTriangleDistance) { bestTriangleDistance = thisTriangleDistance; someTriangleHit = true; + qDebug() << " subMeshBox[" << subMeshIndex <<"].triangle[" << t <<"] --- WOOT! BEST DISTANCE!"; + } else { + qDebug() << " subMeshBox[" << subMeshIndex <<"].triangle[" << t <<"] --- not best distance???"; } } } @@ -611,6 +618,38 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g } else { qDebug() << " distanceToSubMesh >= bestDistance !! TOO FAR AWAY!"; } + } else { + // TODO: this needs to be deleted... there shouldn't be any reason to run this here... if the mesh's bounding box + // doesn't intersect, then how can any of it's triangles!!!! + + qDebug() << " subMeshBox[" << subMeshIndex <<"].findRayIntersection() MISSES???"; + if (pickAgainstTriangles) { + qDebug() << " subMeshBox[" << subMeshIndex <<"] --- check triangles anyway!!"; + if (!_calculatedMeshTrianglesValid) { + recalcuateMeshBoxes(); + } + // check our triangles here.... + const QVector& meshTriangles = _calculatedMeshTriangles[subMeshIndex]; + int t = 0; + foreach (const Triangle& triangle, meshTriangles) { + //qDebug() << "triangle["<< t <<"] :" << triangle.v0 << ", "<< triangle.v1 << ", " << triangle.v2; + t++; + + float thisTriangleDistance; + if (findRayTrianlgeIntersection(origin, direction, triangle, thisTriangleDistance)) { + qDebug() << " subMeshBox[" << subMeshIndex <<"].triangle[" << t <<"] --- HITS!!"; + qDebug() << " subMeshBox[" << subMeshIndex <<"].triangle[" << t <<"] thisTriangleDistance:" << thisTriangleDistance; + qDebug() << " subMeshBox[" << subMeshIndex <<"].triangle[" << t <<"] bestTriangleDistance:" << bestTriangleDistance; + if (thisTriangleDistance < bestTriangleDistance) { + bestTriangleDistance = thisTriangleDistance; + someTriangleHit = true; + qDebug() << " subMeshBox[" << subMeshIndex <<"].triangle[" << t <<"] --- WOOT! BEST DISTANCE!"; + } else { + qDebug() << " subMeshBox[" << subMeshIndex <<"].triangle[" << t <<"] --- not best distance???"; + } + } + } + } } subMeshIndex++; } From 1fec69698ec66db629413af7b1288737fb7715a6 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 5 Dec 2014 23:23:21 -0800 Subject: [PATCH 262/502] get the triangle picking for submeshes working, remove some debug --- .../entities/RenderableModelEntityItem.cpp | 16 +- interface/src/renderer/Model.cpp | 200 ++++++++++-------- interface/src/renderer/Model.h | 1 + libraries/entities/src/EntityTreeElement.cpp | 44 ++-- libraries/octree/src/OctreeElement.cpp | 34 +-- libraries/shared/src/GeometryUtil.cpp | 8 +- 6 files changed, 169 insertions(+), 134 deletions(-) diff --git a/interface/src/entities/RenderableModelEntityItem.cpp b/interface/src/entities/RenderableModelEntityItem.cpp index e2fd50ceee..37efeb98ee 100644 --- a/interface/src/entities/RenderableModelEntityItem.cpp +++ b/interface/src/entities/RenderableModelEntityItem.cpp @@ -174,7 +174,9 @@ void RenderableModelEntityItem::render(RenderArgs* args) { PerformanceTimer perfTimer("model->render"); bool dontRenderAsScene = true; // Menu::getInstance()->isOptionChecked(MenuOption::DontRenderEntitiesAsScene); if (dontRenderAsScene) { - _model->render(alpha, modelRenderMode, args); + if (!_model->renderTriangleProxies()) { + _model->render(alpha, modelRenderMode, args); + } } else { _model->renderInScene(alpha, args); } @@ -261,12 +263,12 @@ bool RenderableModelEntityItem::findDetailedRayIntersection(const glm::vec3& ori bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, void** intersectedObject) const { - qDebug() << "RenderableModelEntityItem::findDetailedRayIntersection()...."; - qDebug() << " this.id:" << getEntityItemID(); - qDebug() << " this.modelURL:" << getModelURL(); - qDebug() << " origin:" << origin; + //qDebug() << "RenderableModelEntityItem::findDetailedRayIntersection()...."; + //qDebug() << " this.id:" << getEntityItemID(); + //qDebug() << " this.modelURL:" << getModelURL(); + //qDebug() << " origin:" << origin; glm::vec3 originInMeters = origin * (float)TREE_SCALE; - qDebug() << " originInMeters:" << originInMeters; + //qDebug() << " originInMeters:" << originInMeters; QString extraInfo; float localDistance; @@ -276,7 +278,7 @@ bool RenderableModelEntityItem::findDetailedRayIntersection(const glm::vec3& ori // NOTE: findRayIntersectionAgainstSubMeshes() does work in meters, but we're expected to return // results in tree scale. distance = localDistance / (float)TREE_SCALE; - qDebug() << " --hit this mode -- returning distance:" << distance; + //qDebug() << " --hit this mode -- returning distance:" << distance; } return intersectsModel; // we only got here if we intersected our non-aabox diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 3606a17cf8..8f684440da 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -516,6 +516,61 @@ void Model::setJointStates(QVector states) { _boundingRadius = radius; } +bool Model::renderTriangleProxies() { + if (!isActive()) { + return false; + } + if (_calculatedMeshTrianglesValid) { + int color = 0; + foreach (const QVector& meshTriangles, _calculatedMeshTriangles) { + switch(color) { + case 0: glColor3ub( 0, 0, 255); break; + case 1: glColor3ub( 0, 255, 0); break; + case 2: glColor3ub( 0, 255, 255); break; + case 3: glColor3ub(255, 0, 0); break; + case 4: glColor3ub(255, 0, 255); break; + case 5: glColor3ub(255, 255, 0); break; + case 6: glColor3ub( 0, 0, 128); break; + case 7: glColor3ub( 0, 128, 0); break; + case 8: glColor3ub( 0, 128, 128); break; + case 9: glColor3ub(128, 0, 0); break; + case 10: glColor3ub(128, 0, 128); break; + case 11: glColor3ub(128, 128, 0); break; + case 12: glColor3ub(128, 128, 255); break; + case 13: glColor3ub(128, 255, 128); break; + case 14: glColor3ub(128, 255, 255); break; + case 15: glColor3ub(255, 128, 128); break; + case 16: glColor3ub(255, 128, 255); break; + case 17: glColor3ub(255, 255, 128); break; + default: glColor3ub(255,255, 255); break; + } + + if (_calculatedMeshBoxes.size() > color) { + const AABox& box = _calculatedMeshBoxes[color]; + glm::vec3 center = box.calcCenter(); + glm::vec3 dimensions = box.getDimensions(); + glPushMatrix(); + glTranslatef(center.x, center.y, center.z); + glScalef(dimensions.x, dimensions.y, dimensions.z); + Application::getInstance()->getDeferredLightingEffect()->renderWireCube(1.0f); + glPopMatrix(); + } + + + glBegin(GL_TRIANGLES); + foreach (const Triangle& triangle, meshTriangles) { + //qDebug() << "triangle["<< t <<"] :" << triangle.v0 << ", "<< triangle.v1 << ", " << triangle.v2; + glVertex3f( triangle.v0.x, triangle.v0.y, triangle.v0.z); + glVertex3f( triangle.v1.x, triangle.v1.y, triangle.v1.z); + glVertex3f( triangle.v2.x, triangle.v2.y, triangle.v2.z); + } + glEnd(); + color++; + } + } + return _calculatedMeshTrianglesValid; +} + bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face, QString& extraInfo) { @@ -528,9 +583,9 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g bool pickAgainstTriangles = Menu::getInstance()->isOptionChecked(MenuOption::PickAgainstModelTriangles); - qDebug() << "Model::findRayIntersectionAgainstSubMeshes()..."; - qDebug() << " origin:" << origin; - qDebug() << " direction:" << direction; + //qDebug() << "Model::findRayIntersectionAgainstSubMeshes()..."; + //qDebug() << " origin:" << origin; + //qDebug() << " direction:" << direction; // extents is the entity relative, scaled, centered extents of the entity glm::vec3 position = _translation; @@ -540,24 +595,24 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g glm::mat4 worldToModelMatrix = glm::inverse(modelToWorldMatrix); Extents modelExtents = getMeshExtents(); // NOTE: unrotated - qDebug() << " modelExtents:" << modelExtents; + //qDebug() << " modelExtents:" << modelExtents; glm::vec3 dimensions = modelExtents.maximum - modelExtents.minimum; glm::vec3 corner = -(dimensions * _registrationPoint); // since we're going to do the ray picking in the model frame of reference AABox modelFrameBox(corner, dimensions); - qDebug() << " modelFrameBox:" << modelFrameBox; + //qDebug() << " modelFrameBox:" << modelFrameBox; glm::vec3 modelFrameOrigin = glm::vec3(worldToModelMatrix * glm::vec4(origin, 1.0f)); glm::vec3 modelFrameDirection = glm::vec3(worldToModelMatrix * glm::vec4(direction, 0.0f)); - qDebug() << " modelFrameOrigin:" << modelFrameOrigin; - qDebug() << " modelFrameDirection:" << modelFrameDirection; + //qDebug() << " modelFrameOrigin:" << modelFrameOrigin; + //qDebug() << " modelFrameDirection:" << modelFrameDirection; // we can use the AABox's ray intersection by mapping our origin and direction into the model frame // and testing intersection there. if (modelFrameBox.findRayIntersection(modelFrameOrigin, modelFrameDirection, distance, face)) { - qDebug() << " modelFrameBox.findRayIntersection() HITS!!!"; + //qDebug() << " modelFrameBox.findRayIntersection() HITS!!!"; float bestDistance = std::numeric_limits::max(); float bestTriangleDistance = std::numeric_limits::max(); @@ -569,22 +624,23 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g const FBXGeometry& geometry = _geometry->getFBXGeometry(); - qDebug() << " Checking mesh boxes...."; - + //qDebug() << " Checking mesh boxes...."; + // If we hit the models box, then consider the submeshes... foreach(const AABox& subMeshBox, _calculatedMeshBoxes) { - qDebug() << " subMeshBox[" << subMeshIndex <<"]:" << subMeshBox; + //qDebug() << " subMeshBox[" << subMeshIndex <<"]:" << subMeshBox; if (subMeshBox.findRayIntersection(origin, direction, distanceToSubMesh, subMeshFace)) { - qDebug() << " subMeshBox[" << subMeshIndex <<"].findRayIntersection() HITS!"; - qDebug() << " subMeshBox[" << subMeshIndex <<"].distanceToSubMesh:" << distanceToSubMesh; - qDebug() << " bestDistance:" << bestDistance; + //qDebug() << " subMeshBox[" << subMeshIndex <<"].findRayIntersection() HITS!"; + //qDebug() << " subMeshBox[" << subMeshIndex <<"].distanceToSubMesh:" << distanceToSubMesh; + //qDebug() << " bestDistance:" << bestDistance; if (distanceToSubMesh < bestDistance) { - qDebug() << " distanceToSubMesh < bestDistance !! looks like a good match!"; + //qDebug() << " distanceToSubMesh < bestDistance !! looks like a good match!"; if (pickAgainstTriangles) { - qDebug() << " subMeshBox[" << subMeshIndex <<"] --- check triangles!!"; + someTriangleHit = false; + //qDebug() << " subMeshBox[" << subMeshIndex <<"] --- check triangles!!"; if (!_calculatedMeshTrianglesValid) { recalcuateMeshBoxes(); } @@ -592,93 +648,59 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g const QVector& meshTriangles = _calculatedMeshTriangles[subMeshIndex]; int t = 0; foreach (const Triangle& triangle, meshTriangles) { - //qDebug() << "triangle["<< t <<"] :" << triangle.v0 << ", "<< triangle.v1 << ", " << triangle.v2; + //qDebug() << "checking triangle["<< t <<"] :" << triangle.v0 << ", "<< triangle.v1 << ", " << triangle.v2; t++; float thisTriangleDistance; if (findRayTrianlgeIntersection(origin, direction, triangle, thisTriangleDistance)) { - qDebug() << " subMeshBox[" << subMeshIndex <<"].triangle[" << t <<"] --- HITS!!"; - qDebug() << " subMeshBox[" << subMeshIndex <<"].triangle[" << t <<"] thisTriangleDistance:" << thisTriangleDistance; - qDebug() << " subMeshBox[" << subMeshIndex <<"].triangle[" << t <<"] bestTriangleDistance:" << bestTriangleDistance; - if (thisTriangleDistance < bestTriangleDistance) { + //qDebug() << "---- HIT triangle["<< t <<"] :" << triangle.v0 << ", "<< triangle.v1 << ", " << triangle.v2 << " -----"; + //qDebug() << " subMeshBox[" << subMeshIndex <<"].triangle[" << t <<"] --- HITS!!"; + //qDebug() << " subMeshBox[" << subMeshIndex <<"].triangle[" << t <<"] thisTriangleDistance:" << thisTriangleDistance; + //qDebug() << " subMeshBox[" << subMeshIndex <<"].triangle[" << t <<"] bestTriangleDistance:" << bestTriangleDistance; + if (thisTriangleDistance < bestDistance) { bestTriangleDistance = thisTriangleDistance; someTriangleHit = true; - qDebug() << " subMeshBox[" << subMeshIndex <<"].triangle[" << t <<"] --- WOOT! BEST DISTANCE!"; + + bestDistance = thisTriangleDistance; + intersectedSomething = true; + face = subMeshFace; + extraInfo = geometry.getModelNameOfMesh(subMeshIndex); + + //qDebug() << " subMeshBox[" << subMeshIndex <<"].triangle[" << t <<"] --- WOOT! BEST DISTANCE!"; } else { - qDebug() << " subMeshBox[" << subMeshIndex <<"].triangle[" << t <<"] --- not best distance???"; + //qDebug() << " subMeshBox[" << subMeshIndex <<"].triangle[" << t <<"] --- not best distance???"; } } } + } else { + // this is the non-triangle picking case... + bestDistance = distanceToSubMesh; + intersectedSomething = true; + face = subMeshFace; + extraInfo = geometry.getModelNameOfMesh(subMeshIndex); } - - bestDistance = distanceToSubMesh; - intersectedSomething = true; - face = subMeshFace; - extraInfo = geometry.getModelNameOfMesh(subMeshIndex); } else { - qDebug() << " distanceToSubMesh >= bestDistance !! TOO FAR AWAY!"; + //qDebug() << " distanceToSubMesh >= bestDistance !! TOO FAR AWAY!"; } - } else { - // TODO: this needs to be deleted... there shouldn't be any reason to run this here... if the mesh's bounding box - // doesn't intersect, then how can any of it's triangles!!!! - - qDebug() << " subMeshBox[" << subMeshIndex <<"].findRayIntersection() MISSES???"; - if (pickAgainstTriangles) { - qDebug() << " subMeshBox[" << subMeshIndex <<"] --- check triangles anyway!!"; - if (!_calculatedMeshTrianglesValid) { - recalcuateMeshBoxes(); - } - // check our triangles here.... - const QVector& meshTriangles = _calculatedMeshTriangles[subMeshIndex]; - int t = 0; - foreach (const Triangle& triangle, meshTriangles) { - //qDebug() << "triangle["<< t <<"] :" << triangle.v0 << ", "<< triangle.v1 << ", " << triangle.v2; - t++; - - float thisTriangleDistance; - if (findRayTrianlgeIntersection(origin, direction, triangle, thisTriangleDistance)) { - qDebug() << " subMeshBox[" << subMeshIndex <<"].triangle[" << t <<"] --- HITS!!"; - qDebug() << " subMeshBox[" << subMeshIndex <<"].triangle[" << t <<"] thisTriangleDistance:" << thisTriangleDistance; - qDebug() << " subMeshBox[" << subMeshIndex <<"].triangle[" << t <<"] bestTriangleDistance:" << bestTriangleDistance; - if (thisTriangleDistance < bestTriangleDistance) { - bestTriangleDistance = thisTriangleDistance; - someTriangleHit = true; - qDebug() << " subMeshBox[" << subMeshIndex <<"].triangle[" << t <<"] --- WOOT! BEST DISTANCE!"; - } else { - qDebug() << " subMeshBox[" << subMeshIndex <<"].triangle[" << t <<"] --- not best distance???"; - } - } - } - } - } + } subMeshIndex++; } - // if we were asked to pick against triangles, and we didn't hit one, then we - // do not consider this model to be hit at all. - if (pickAgainstTriangles && !someTriangleHit) { - qDebug() << "pickAgainstTriangles && !someTriangleHit --- call it a NON-HIT!"; - intersectedSomething = false; - } - qDebug() << "pickAgainstTriangles:" << pickAgainstTriangles; - qDebug() << "someTriangleHit:" << someTriangleHit; - qDebug() << "bestTriangleDistance:" << bestTriangleDistance; - qDebug() << "bestDistance:" << bestDistance; + //qDebug() << "pickAgainstTriangles:" << pickAgainstTriangles; + //qDebug() << "someTriangleHit:" << someTriangleHit; + //qDebug() << "bestTriangleDistance:" << bestTriangleDistance; + //qDebug() << "bestDistance:" << bestDistance; + //qDebug() << "intersectedSomething:" << intersectedSomething; if (intersectedSomething) { - qDebug() << " --- we hit this model --- "; - - if (pickAgainstTriangles) { - distance = bestTriangleDistance; - } else { - distance = bestDistance; - } - qDebug() << "distance:" << distance; + //qDebug() << " --- we hit this model --- "; + distance = bestDistance; + //qDebug() << "distance:" << distance; } return intersectedSomething; } else { - qDebug() << "modelFrameBox.findRayIntersection()... DID NOT INTERSECT..."; + //qDebug() << "modelFrameBox.findRayIntersection()... DID NOT INTERSECT..."; } return intersectedSomething; @@ -689,12 +711,14 @@ void Model::recalcuateMeshBoxes() { bool calculatedMeshTrianglesNeeded = pickAgainstTriangles && !_calculatedMeshTrianglesValid; if (!_calculatedMeshBoxesValid || calculatedMeshTrianglesNeeded) { - qDebug() << "Model::recalcuateMeshBoxes()"; + qDebug() << "************************************************************************************************"; + qDebug() << "Model::recalcuateMeshBoxes() -------------------------------------------------------------------"; PerformanceTimer perfTimer("calculatedMeshBoxes"); const FBXGeometry& geometry = _geometry->getFBXGeometry(); int numberOfMeshes = geometry.meshes.size(); _calculatedMeshBoxes.resize(numberOfMeshes); _calculatedMeshTriangles.clear(); + _calculatedMeshTriangles.resize(numberOfMeshes); for (int i = 0; i < numberOfMeshes; i++) { const FBXMesh& mesh = geometry.meshes.at(i); Extents scaledMeshExtents = calculateScaledOffsetExtents(mesh.meshExtents); @@ -731,8 +755,14 @@ void Model::recalcuateMeshBoxes() { glm::vec3 v2 = calculateScaledOffsetPoint(glm::vec3(mesh.modelTransform * glm::vec4(mesh.vertices[i2], 1.0f))); glm::vec3 v3 = calculateScaledOffsetPoint(glm::vec3(mesh.modelTransform * glm::vec4(mesh.vertices[i3], 1.0f))); - Triangle tri1 = { v0, v1, v3 }; - Triangle tri2 = { v1, v2, v3 }; + // Sam's + //Triangle tri1 = { v0, v1, v3 }; + //Triangle tri2 = { v1, v2, v3 }; + + // triangle 0 1 2 + // triangle 2 3 0 + Triangle tri1 = { v0, v1, v2 }; + Triangle tri2 = { v2, v3, v0 }; //qDebug() << "quad["<< q <<"].t1 :" << v0 << ", "<< v1 << ", " << v3; //qDebug() << "quad["<< q <<"].t2 :" << v1 << ", "<< v2 << ", " << v3; @@ -764,7 +794,7 @@ void Model::recalcuateMeshBoxes() { } } - _calculatedMeshTriangles.push_back(thisMeshTriangles); + _calculatedMeshTriangles[i] = thisMeshTriangles; qDebug() << "------------------------------------------------------------------------------"; } diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 406622e6a8..4145b7b3d9 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -89,6 +89,7 @@ public: enum RenderMode { DEFAULT_RENDER_MODE, SHADOW_RENDER_MODE, DIFFUSE_RENDER_MODE, NORMAL_RENDER_MODE }; bool render(float alpha = 1.0f, RenderMode mode = DEFAULT_RENDER_MODE, RenderArgs* args = NULL); + bool renderTriangleProxies(); // Scene rendering support static void startScene(RenderArgs::RenderSide renderSide); diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index aea278adf6..ac65245f4b 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -479,10 +479,10 @@ bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, con // only called if we do intersect our bounding cube, but find if we actually intersect with entities... - qDebug() << "EntityTreeElement::findDetailedRayIntersection()...."; - qDebug() << " origin:" << origin; - qDebug() << " distance:" << distance; - qDebug() << " number of entities:" << _entityItems->size(); + //qDebug() << "EntityTreeElement::findDetailedRayIntersection()...."; + //qDebug() << " origin:" << origin; + //qDebug() << " distance:" << distance; + //qDebug() << " number of entities:" << _entityItems->size(); int entityNumber = 0; QList::iterator entityItr = _entityItems->begin(); @@ -498,15 +498,15 @@ bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, con float localDistance; BoxFace localFace; - qDebug() << "EntityTreeElement::findDetailedRayIntersection()...."; - qDebug() << " checking entity[" << entityNumber << "]:" << entity->getEntityItemID() << "-" << qPrintable(EntityTypes::getEntityTypeName(entity->getType())); - qDebug() << " checking the AABox:" << entityBox; + //qDebug() << "EntityTreeElement::findDetailedRayIntersection()...."; + //qDebug() << " checking entity[" << entityNumber << "]:" << entity->getEntityItemID() << "-" << qPrintable(EntityTypes::getEntityTypeName(entity->getType())); + //qDebug() << " checking the AABox:" << entityBox; // if the ray doesn't intersect with our cube, we can stop searching! if (entityBox.findRayIntersection(origin, direction, localDistance, localFace)) { - qDebug() << " AABox for entity intersects!"; - qDebug() << " localDistance:" << localDistance; + //qDebug() << " AABox for entity intersects!"; + //qDebug() << " localDistance:" << localDistance; // extents is the entity relative, scaled, centered extents of the entity glm::mat4 rotation = glm::mat4_cast(entity->getRotation()); @@ -525,51 +525,51 @@ bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, con // we can use the AABox's ray intersection by mapping our origin and direction into the entity frame // and testing intersection there. - qDebug() << " checking the entityFrameBox:" << entityFrameBox; + //qDebug() << " checking the entityFrameBox:" << entityFrameBox; if (entityFrameBox.findRayIntersection(entityFrameOrigin, entityFrameDirection, localDistance, localFace)) { - qDebug() << " entityFrameBox intersects!"; - qDebug() << " localDistance:" << localDistance; + //qDebug() << " entityFrameBox intersects!"; + //qDebug() << " localDistance:" << localDistance; if (localDistance < distance) { - qDebug() << " localDistance < distance... continue..."; + //qDebug() << " localDistance < distance... continue..."; // now ask the entity if we actually intersect if (entity->supportsDetailedRayIntersection()) { - qDebug() << " entity->supportsDetailedRayIntersection()...."; + //qDebug() << " entity->supportsDetailedRayIntersection()...."; if (entity->findDetailedRayIntersection(origin, direction, keepSearching, element, localDistance, localFace, intersectedObject)) { - qDebug() << " localDistance (detailed):" << localDistance; + //qDebug() << " localDistance (detailed):" << localDistance; if (localDistance < distance) { - qDebug() << " localDistance < distance..."; - qDebug() << " CHOOSING THIS ONE ---> " << entity->getEntityItemID() << "-" << qPrintable(EntityTypes::getEntityTypeName(entity->getType())); + //qDebug() << " localDistance < distance..."; + //qDebug() << " CHOOSING THIS ONE ---> " << entity->getEntityItemID() << "-" << qPrintable(EntityTypes::getEntityTypeName(entity->getType())); distance = localDistance; face = localFace; *intersectedObject = (void*)entity; somethingIntersected = true; } else { - qDebug() << " localDistance >= distance... TOO FAR AWAY"; + //qDebug() << " localDistance >= distance... TOO FAR AWAY"; } } } else { // if the entity type doesn't support a detailed intersection, then just return the non-AABox results if (localDistance < distance) { - qDebug() << " localDistance < distance..."; - qDebug() << " CHOOSING THIS ONE ---> " << entity->getEntityItemID() << "-" << qPrintable(EntityTypes::getEntityTypeName(entity->getType())); + //qDebug() << " localDistance < distance..."; + //qDebug() << " CHOOSING THIS ONE ---> " << entity->getEntityItemID() << "-" << qPrintable(EntityTypes::getEntityTypeName(entity->getType())); distance = localDistance; face = localFace; *intersectedObject = (void*)entity; somethingIntersected = true; } else { - qDebug() << " localDistance >= distance... TOO FAR AWAY"; + //qDebug() << " localDistance >= distance... TOO FAR AWAY"; } } } @@ -580,7 +580,7 @@ bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, con entityNumber++; } - qDebug() << " EntityTreeElement::findDetailedRayIntersection().... returning somethingIntersected:" << somethingIntersected << "keepSearching:" << keepSearching; + //qDebug() << " EntityTreeElement::findDetailedRayIntersection().... returning somethingIntersected:" << somethingIntersected << "keepSearching:" << keepSearching; return somethingIntersected; } diff --git a/libraries/octree/src/OctreeElement.cpp b/libraries/octree/src/OctreeElement.cpp index 9f6e0530a8..e3ff06b2d3 100644 --- a/libraries/octree/src/OctreeElement.cpp +++ b/libraries/octree/src/OctreeElement.cpp @@ -1346,23 +1346,23 @@ bool OctreeElement::findRayIntersection(const glm::vec3& origin, const glm::vec3 AACube debugCube = cube; debugCube.scale((float)TREE_SCALE); - qDebug() << "OctreeElement::findRayIntersection()...."; - qDebug() << " origin:" << origin; - qDebug() << " checking element:" << debugCube << "in meters"; - qDebug() << " distance:" << distance; + //qDebug() << "OctreeElement::findRayIntersection()...."; + //qDebug() << " origin:" << origin; + //qDebug() << " checking element:" << debugCube << "in meters"; + //qDebug() << " distance:" << distance; // if the ray doesn't intersect with our cube, we can stop searching! if (!cube.findRayIntersection(origin, direction, distanceToElementCube, localFace)) { - qDebug() << " didn't intersect cube... done searching..."; + //qDebug() << " didn't intersect cube... done searching..."; keepSearching = false; // no point in continuing to search return false; // we did not intersect } - qDebug() << " distanceToElementCube:" << distanceToElementCube; + //qDebug() << " distanceToElementCube:" << distanceToElementCube; // by default, we only allow intersections with leaves with content if (!canRayIntersect()) { - qDebug() << " NOT canRayIntersect() -- no point in calling detailed..."; + //qDebug() << " NOT canRayIntersect() -- no point in calling detailed..."; return false; // we don't intersect with non-leaves, and we keep searching } @@ -1373,28 +1373,28 @@ bool OctreeElement::findRayIntersection(const glm::vec3& origin, const glm::vec3 // for any details inside the cube to be closer so we don't need to consider them. if (cube.contains(origin) || distanceToElementCube < distance) { - qDebug() << " distanceToElementCube < distance:" << (distanceToElementCube < distance); - qDebug() << " cube.contains(origin):" << (cube.contains(origin)); - qDebug() << " continue.... call... findDetailedRayIntersection()..."; + //qDebug() << " distanceToElementCube < distance:" << (distanceToElementCube < distance); + //qDebug() << " cube.contains(origin):" << (cube.contains(origin)); + //qDebug() << " continue.... call... findDetailedRayIntersection()..."; //qDebug() << " distanceToElementCube < distance -- continue.... call... findDetailedRayIntersection()..."; if (findDetailedRayIntersection(origin, direction, keepSearching, element, distanceToElementDetails, face, intersectedObject, distanceToElementCube)) { - qDebug() << " findDetailedRayIntersection() -- intersected something"; + //qDebug() << " findDetailedRayIntersection() -- intersected something"; if (distanceToElementDetails < distance) { - qDebug() << " distanceToElementDetails < distance -- THIS ONE IS GOOD -------"; + //qDebug() << " distanceToElementDetails < distance -- THIS ONE IS GOOD -------"; distance = distanceToElementDetails; face = localFace; - qDebug() << " distance:" << distance << " -- THIS ONE IS GOOD -------"; + //qDebug() << " distance:" << distance << " -- THIS ONE IS GOOD -------"; return true; } else { - qDebug() << " distanceToElementDetails:" << distanceToElementDetails; - qDebug() << " distance:" << distance; - qDebug() << " distanceToElementDetails >= distance -- THIS ONE IS NOT SELECTED even though it INTERSECTED -------"; + //qDebug() << " distanceToElementDetails:" << distanceToElementDetails; + //qDebug() << " distance:" << distance; + //qDebug() << " distanceToElementDetails >= distance -- THIS ONE IS NOT SELECTED even though it INTERSECTED -------"; } } } @@ -1412,7 +1412,7 @@ bool OctreeElement::findDetailedRayIntersection(const glm::vec3& origin, const g if (intersectedObject) { *intersectedObject = this; } - qDebug() << " OctreeElement::findDetailedRayIntersection().... hasContent() -- done searching..."; + //qDebug() << " OctreeElement::findDetailedRayIntersection().... hasContent() -- done searching..."; keepSearching = false; return true; // we did intersect } diff --git a/libraries/shared/src/GeometryUtil.cpp b/libraries/shared/src/GeometryUtil.cpp index c064630f83..f44c954a3a 100644 --- a/libraries/shared/src/GeometryUtil.cpp +++ b/libraries/shared/src/GeometryUtil.cpp @@ -252,6 +252,7 @@ bool findRayCapsuleIntersection(const glm::vec3& origin, const glm::vec3& direct return true; } + bool findRayTrianlgeIntersection(const glm::vec3& origin, const glm::vec3& direction, const glm::vec3& v0, const glm::vec3& v1, const glm::vec3& v2, float& distance) { @@ -264,7 +265,8 @@ bool findRayTrianlgeIntersection(const glm::vec3& origin, const glm::vec3& direc h = glm::cross(direction, e2); a = glm::dot(e1, h); - if (a > -0.00001 && a < 0.00001) { + if (a > EPSILON && a < EPSILON) { + qDebug() << "if (a > EPSILON && a < EPSILON)..."; return false; } @@ -287,17 +289,17 @@ bool findRayTrianlgeIntersection(const glm::vec3& origin, const glm::vec3& direc t = f * glm::dot(e2,q); // ray intersection - if (t > 0.00001) { + if (t > EPSILON) { distance = t; return true; } else { // this means that there is a line intersection but not a ray intersection + qDebug() << "if (t <= EPSILON)..."; return false; } return false; } - // Do line segments (r1p1.x, r1p1.y)--(r1p2.x, r1p2.y) and (r2p1.x, r2p1.y)--(r2p2.x, r2p2.y) intersect? // from: http://ptspts.blogspot.com/2010/06/how-to-determine-if-two-line-segments.html bool doLineSegmentsIntersect(glm::vec2 r1p1, glm::vec2 r1p2, glm::vec2 r2p1, glm::vec2 r2p2) { From fd00ad95caed61701a7eae47acc30a0923f393fa Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 6 Dec 2014 09:24:30 -0800 Subject: [PATCH 263/502] Fix voxel size text display --- examples/editVoxels.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/editVoxels.js b/examples/editVoxels.js index 1dd825d3cf..ff096973a3 100644 --- a/examples/editVoxels.js +++ b/examples/editVoxels.js @@ -319,7 +319,7 @@ function ScaleSelector() { width: this.SECOND_PART, height: this.height, topMargin: 13, text: this.scale.toString(), - alpha: 0.9, + backgroundAlpha: 0.0, visible: editToolsOn }); this.powerOverlay = Overlays.addOverlay("text", { @@ -327,7 +327,7 @@ function ScaleSelector() { width: this.SECOND_PART, height: this.height, leftMargin: 28, text: this.power.toString(), - alpha: 0.0, + backgroundAlpha: 0.0, visible: false }); this.setScale = function(scale) { From ec907d1d1da54eb00fec1791e8dae64edd1dea1f Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sat, 6 Dec 2014 09:44:30 -0800 Subject: [PATCH 264/502] removed debug --- libraries/shared/src/GeometryUtil.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/libraries/shared/src/GeometryUtil.cpp b/libraries/shared/src/GeometryUtil.cpp index f44c954a3a..e2736f8502 100644 --- a/libraries/shared/src/GeometryUtil.cpp +++ b/libraries/shared/src/GeometryUtil.cpp @@ -266,7 +266,6 @@ bool findRayTrianlgeIntersection(const glm::vec3& origin, const glm::vec3& direc a = glm::dot(e1, h); if (a > EPSILON && a < EPSILON) { - qDebug() << "if (a > EPSILON && a < EPSILON)..."; return false; } @@ -294,7 +293,6 @@ bool findRayTrianlgeIntersection(const glm::vec3& origin, const glm::vec3& direc return true; } else { // this means that there is a line intersection but not a ray intersection - qDebug() << "if (t <= EPSILON)..."; return false; } return false; From 303274a554d8876da4330395d1c8b2d9813ad7cc Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sat, 6 Dec 2014 10:59:48 -0800 Subject: [PATCH 265/502] tweaks and debug cleanup --- .../entities/RenderableModelEntityItem.cpp | 6 +-- interface/src/renderer/Model.cpp | 41 ++++--------------- interface/src/renderer/Model.h | 6 +-- 3 files changed, 14 insertions(+), 39 deletions(-) diff --git a/interface/src/entities/RenderableModelEntityItem.cpp b/interface/src/entities/RenderableModelEntityItem.cpp index 37efeb98ee..c5f5f0c98a 100644 --- a/interface/src/entities/RenderableModelEntityItem.cpp +++ b/interface/src/entities/RenderableModelEntityItem.cpp @@ -172,11 +172,9 @@ void RenderableModelEntityItem::render(RenderArgs* args) { // TODO: this is the majority of model render time. And rendering of a cube model vs the basic Box render // is significantly more expensive. Is there a way to call this that doesn't cost us as much? PerformanceTimer perfTimer("model->render"); - bool dontRenderAsScene = true; // Menu::getInstance()->isOptionChecked(MenuOption::DontRenderEntitiesAsScene); + bool dontRenderAsScene = Menu::getInstance()->isOptionChecked(MenuOption::DontRenderEntitiesAsScene); if (dontRenderAsScene) { - if (!_model->renderTriangleProxies()) { - _model->render(alpha, modelRenderMode, args); - } + _model->render(alpha, modelRenderMode, args); } else { _model->renderInScene(alpha, args); } diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 8f684440da..a59a76709a 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -571,8 +571,8 @@ bool Model::renderTriangleProxies() { return _calculatedMeshTrianglesValid; } -bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const glm::vec3& direction, - float& distance, BoxFace& face, QString& extraInfo) { +bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const glm::vec3& direction, float& distance, + BoxFace& face, QString& extraInfo, bool pickAgainstTriangles) { bool intersectedSomething = false; @@ -581,8 +581,6 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g return intersectedSomething; } - bool pickAgainstTriangles = Menu::getInstance()->isOptionChecked(MenuOption::PickAgainstModelTriangles); - //qDebug() << "Model::findRayIntersectionAgainstSubMeshes()..."; //qDebug() << " origin:" << origin; //qDebug() << " direction:" << direction; @@ -706,13 +704,10 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g return intersectedSomething; } -void Model::recalcuateMeshBoxes() { - bool pickAgainstTriangles = Menu::getInstance()->isOptionChecked(MenuOption::PickAgainstModelTriangles); +void Model::recalcuateMeshBoxes(bool pickAgainstTriangles) { bool calculatedMeshTrianglesNeeded = pickAgainstTriangles && !_calculatedMeshTrianglesValid; if (!_calculatedMeshBoxesValid || calculatedMeshTrianglesNeeded) { - qDebug() << "************************************************************************************************"; - qDebug() << "Model::recalcuateMeshBoxes() -------------------------------------------------------------------"; PerformanceTimer perfTimer("calculatedMeshBoxes"); const FBXGeometry& geometry = _geometry->getFBXGeometry(); int numberOfMeshes = geometry.meshes.size(); @@ -723,16 +718,9 @@ void Model::recalcuateMeshBoxes() { const FBXMesh& mesh = geometry.meshes.at(i); Extents scaledMeshExtents = calculateScaledOffsetExtents(mesh.meshExtents); - qDebug() << "mesh.meshExtents["< thisMeshTriangles; for (int j = 0; j < mesh.parts.size(); j++) { const FBXMeshPart& part = mesh.parts.at(j); @@ -742,7 +730,6 @@ void Model::recalcuateMeshBoxes() { if (part.quadIndices.size() > 0) { int numberOfQuads = part.quadIndices.size() / INDICES_PER_QUAD; - qDebug() << "numberOfQuads:" << numberOfQuads; int vIndex = 0; for (int q = 0; q < numberOfQuads; q++) { int i0 = part.quadIndices[vIndex++]; @@ -755,18 +742,14 @@ void Model::recalcuateMeshBoxes() { glm::vec3 v2 = calculateScaledOffsetPoint(glm::vec3(mesh.modelTransform * glm::vec4(mesh.vertices[i2], 1.0f))); glm::vec3 v3 = calculateScaledOffsetPoint(glm::vec3(mesh.modelTransform * glm::vec4(mesh.vertices[i3], 1.0f))); - // Sam's - //Triangle tri1 = { v0, v1, v3 }; - //Triangle tri2 = { v1, v2, v3 }; + // Sam's recommended triangle slices + Triangle tri1 = { v0, v1, v3 }; + Triangle tri2 = { v1, v2, v3 }; - // triangle 0 1 2 - // triangle 2 3 0 - Triangle tri1 = { v0, v1, v2 }; - Triangle tri2 = { v2, v3, v0 }; + // NOTE: Random guy on the internet's recommended triangle slices + //Triangle tri1 = { v0, v1, v2 }; + //Triangle tri2 = { v2, v3, v0 }; - //qDebug() << "quad["<< q <<"].t1 :" << v0 << ", "<< v1 << ", " << v3; - //qDebug() << "quad["<< q <<"].t2 :" << v1 << ", "<< v2 << ", " << v3; - thisMeshTriangles.push_back(tri1); thisMeshTriangles.push_back(tri2); } @@ -774,7 +757,6 @@ void Model::recalcuateMeshBoxes() { if (part.triangleIndices.size() > 0) { int numberOfTris = part.triangleIndices.size() / INDICES_PER_TRIANGLE; - qDebug() << "numberOfTris:" << numberOfTris; int vIndex = 0; for (int t = 0; t < numberOfTris; t++) { int i0 = part.triangleIndices[vIndex++]; @@ -787,17 +769,12 @@ void Model::recalcuateMeshBoxes() { Triangle tri = { v0, v1, v2 }; - //qDebug() << "triangle["<< t <<"] :" << v0 << ", " << v1 << ", " << v2; - thisMeshTriangles.push_back(tri); } } } - _calculatedMeshTriangles[i] = thisMeshTriangles; - qDebug() << "------------------------------------------------------------------------------"; } - } _calculatedMeshBoxesValid = true; _calculatedMeshTrianglesValid = pickAgainstTriangles; diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 4145b7b3d9..69dc6344ad 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -197,8 +197,8 @@ public: Q_INVOKABLE void setTextureWithNameToURL(const QString& name, const QUrl& url) { _geometry->setTextureWithNameToURL(name, url); } - bool findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const glm::vec3& direction, - float& distance, BoxFace& face, QString& extraInfo); + bool findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const glm::vec3& direction, float& distance, + BoxFace& face, QString& extraInfo, bool pickAgainstTriangles = false); protected: QSharedPointer _geometry; @@ -371,7 +371,7 @@ private: QVector< QVector > _calculatedMeshTriangles; // world coordinate triangles for all sub meshes bool _calculatedMeshTrianglesValid; - void recalcuateMeshBoxes(); + void recalcuateMeshBoxes(bool pickAgainstTriangles = false); void segregateMeshGroups(); // used to calculate our list of translucent vs opaque meshes From 4ee99ef38a69298a819ccf14b51c779aa88272af Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 6 Dec 2014 11:03:28 -0800 Subject: [PATCH 266/502] Remove dead code that's causing problems --- examples/editModels.js | 4 ---- examples/newEditEntities.js | 4 ---- 2 files changed, 8 deletions(-) diff --git a/examples/editModels.js b/examples/editModels.js index 8e3503b9b2..ec9e67881b 100644 --- a/examples/editModels.js +++ b/examples/editModels.js @@ -1169,8 +1169,6 @@ var toolBar = (function () { menuItemHeight = Tool.IMAGE_HEIGHT / 2 - 2; loadURLMenuItem = Overlays.addOverlay("text", { - x: newModelButton.x - menuItemWidth, - y: newModelButton.y + menuItemOffset, height: menuItemHeight, backgroundColor: menuBackgroundColor, topMargin: menuItemMargin, @@ -1180,8 +1178,6 @@ var toolBar = (function () { }); loadFileMenuItem = Overlays.addOverlay("text", { - x: newModelButton.x - menuItemWidth, - y: newModelButton.y + menuItemOffset + menuItemHeight, height: menuItemHeight, backgroundColor: menuBackgroundColor, topMargin: menuItemMargin, diff --git a/examples/newEditEntities.js b/examples/newEditEntities.js index ef1be8fef9..9bbb07651c 100644 --- a/examples/newEditEntities.js +++ b/examples/newEditEntities.js @@ -140,8 +140,6 @@ var toolBar = (function () { menuItemHeight = Tool.IMAGE_HEIGHT / 2 - 2; loadURLMenuItem = Overlays.addOverlay("text", { - x: newModelButton.x - menuItemWidth, - y: newModelButton.y + menuItemOffset, height: menuItemHeight, backgroundColor: menuBackgroundColor, topMargin: menuItemMargin, @@ -151,8 +149,6 @@ var toolBar = (function () { }); loadFileMenuItem = Overlays.addOverlay("text", { - x: newModelButton.x - menuItemWidth, - y: newModelButton.y + menuItemOffset + menuItemHeight, height: menuItemHeight, backgroundColor: menuBackgroundColor, topMargin: menuItemMargin, From ca62e61579c4714a007051480b0148cc81725dac Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 6 Dec 2014 11:11:52 -0800 Subject: [PATCH 267/502] Update scripts with text overlays to use new backgroundAlpha property --- examples/ControlACs.js | 1 + examples/Recorder.js | 3 +++ examples/editModels.js | 7 +++++++ examples/fallingSand.js | 4 ++-- examples/growTrees.js | 4 ++-- examples/libraries/ExportMenu.js | 2 +- examples/libraries/ToolTip.js | 1 + examples/libraries/entityCameraTool.js | 8 ++++++++ examples/libraries/entitySelectionTool.js | 1 + examples/libraries/progressDialog.js | 2 ++ examples/libraries/toolBars.js | 8 ++++++-- examples/lobby.js | 1 + examples/newEditEntities.js | 2 ++ examples/notifications.js | 5 +++-- examples/testModelOverlaySubMeshes.js | 1 + examples/textInputOverlayExample.js | 1 + 16 files changed, 42 insertions(+), 9 deletions(-) diff --git a/examples/ControlACs.js b/examples/ControlACs.js index bbdb1cc4ef..73a4385c24 100644 --- a/examples/ControlACs.js +++ b/examples/ControlACs.js @@ -117,6 +117,7 @@ function setupToolBars() { leftMargin: TEXT_MARGIN, topMargin: TEXT_MARGIN, alpha: ALPHA_OFF, + backgroundAlpha: ALPHA_OFF, visible: true })); } diff --git a/examples/Recorder.js b/examples/Recorder.js index 8c784bcea2..ff8c449012 100644 --- a/examples/Recorder.js +++ b/examples/Recorder.js @@ -115,6 +115,7 @@ function setupTimer() { width: 0, height: 0, alpha: 1.0, + backgroundAlpha: 1.0, visible: true }); @@ -129,6 +130,7 @@ function setupTimer() { width: slider.w, height: slider.h, alpha: 1.0, + backgroundAlpha: 1.0, visible: true }); slider.foreground = Overlays.addOverlay("text", { @@ -138,6 +140,7 @@ function setupTimer() { width: slider.pos * slider.w, height: slider.h, alpha: 1.0, + backgroundAlpha: 1.0, visible: true }); diff --git a/examples/editModels.js b/examples/editModels.js index ec9e67881b..c8ad2eb254 100644 --- a/examples/editModels.js +++ b/examples/editModels.js @@ -206,6 +206,7 @@ var progressDialog = (function () { height: backgroundHeight, imageURL: backgroundUrl, alpha: 0.9, + backgroundAlpha: 0.9, visible: false }); @@ -216,6 +217,7 @@ var progressDialog = (function () { textColor: textColor, backgroundColor: textBackground, alpha: 0.9, + backgroundAlpha: 0.9, visible: false }); @@ -226,6 +228,7 @@ var progressDialog = (function () { textColor: textColor, backgroundColor: textBackground, alpha: 0.9, + backgroundAlpha: 0.9, visible: false }); @@ -1174,6 +1177,7 @@ var toolBar = (function () { topMargin: menuItemMargin, text: "Model URL", alpha: 0.9, + backgroundAlpha: 0.9, visible: false }); @@ -1183,6 +1187,7 @@ var toolBar = (function () { topMargin: menuItemMargin, text: "Model File", alpha: 0.9, + backgroundAlpha: 0.9, visible: false }); @@ -1489,6 +1494,7 @@ var ExportMenu = function (opts) { width: scaleViewWidth, height: height, alpha: 0.0, + backgroundAlpha: 0.0, color: { red: 255, green: 255, blue: 255 }, text: "1" }); @@ -2476,6 +2482,7 @@ function Tooltip() { text: "", color: { red: 228, green: 228, blue: 228 }, alpha: 0.8, + backgroundAlpha: 0.8, visible: false }); this.show = function (doShow) { diff --git a/examples/fallingSand.js b/examples/fallingSand.js index 5018aeb9ca..c85196f10e 100644 --- a/examples/fallingSand.js +++ b/examples/fallingSand.js @@ -117,7 +117,7 @@ function ScaleSelector() { width: this.SECOND_PART, height: this.height, topMargin: 13, text: this.scale.toString(), - alpha: 0.0, + backgroundAlpha: 0.0, visible: editToolsOn, color: activeUIColor }); @@ -126,7 +126,7 @@ function ScaleSelector() { width: this.SECOND_PART, height: this.height, leftMargin: 28, text: this.power.toString(), - alpha: 0.0, + backgroundAlpha: 0.0, visible: false, color: activeUIColor }); diff --git a/examples/growTrees.js b/examples/growTrees.js index 13d6cdc587..a5b55eecd6 100644 --- a/examples/growTrees.js +++ b/examples/growTrees.js @@ -116,7 +116,7 @@ function ScaleSelector() { width: this.SECOND_PART, height: this.height, topMargin: 13, text: this.scale.toString(), - alpha: 0.0, + backgroundAlpha: 0.0, visible: editToolsOn, color: activeUIColor }); @@ -125,7 +125,7 @@ function ScaleSelector() { width: this.SECOND_PART, height: this.height, leftMargin: 28, text: this.power.toString(), - alpha: 0.0, + backgroundAlpha: 0.0, visible: false, color: activeUIColor }); diff --git a/examples/libraries/ExportMenu.js b/examples/libraries/ExportMenu.js index 0a47f2bd69..247391808f 100644 --- a/examples/libraries/ExportMenu.js +++ b/examples/libraries/ExportMenu.js @@ -81,7 +81,7 @@ ExportMenu = function (opts) { y: pos.y + margin, width: scaleViewWidth, height: height, - alpha: 0.0, + backgroundAlpha: 0.0, color: { red: 255, green: 255, blue: 255 }, text: "1" }); diff --git a/examples/libraries/ToolTip.js b/examples/libraries/ToolTip.js index 785a0e4d2f..590eba36d0 100644 --- a/examples/libraries/ToolTip.js +++ b/examples/libraries/ToolTip.js @@ -26,6 +26,7 @@ function Tooltip() { text: "", color: { red: 128, green: 128, blue: 128 }, alpha: 0.2, + backgroundAlpha: 0.2, visible: false }); this.show = function (doShow) { diff --git a/examples/libraries/entityCameraTool.js b/examples/libraries/entityCameraTool.js index 3cd2b8a97e..803a58f48e 100644 --- a/examples/libraries/entityCameraTool.js +++ b/examples/libraries/entityCameraTool.js @@ -390,6 +390,7 @@ var ZoomTool = function(opts) { leftMargin: 4, text: "+", alpha: 1.0, + backgroundAlpha: 1.0, visible: true, }); var decreaseButton = Overlays.addOverlay("text", { @@ -403,6 +404,7 @@ var ZoomTool = function(opts) { leftMargin: 4, text: "-", alpha: 1.0, + backgroundAlpha: 1.0, visible: true, }); var zoomBar = Overlays.addOverlay("text", { @@ -416,6 +418,7 @@ var ZoomTool = function(opts) { leftMargin: 4, text: "", alpha: 1.0, + backgroundAlpha: 1.0, visible: true, }); var zoomHandle = Overlays.addOverlay("text", { @@ -428,6 +431,7 @@ var ZoomTool = function(opts) { leftMargin: 4, text: "", alpha: 1.0, + backgroundAlpha: 1.0, visible: true, }); @@ -501,6 +505,7 @@ var ArrowTool = function(opts) { leftMargin: 4, text: "^", alpha: 1.0, + backgroundAlpha: 1.0, visible: true, }); var leftButton = Overlays.addOverlay("text", { @@ -514,6 +519,7 @@ var ArrowTool = function(opts) { leftMargin: 4, text: "<", alpha: 1.0, + backgroundAlpha: 1.0, visible: true, }); var rightButton = Overlays.addOverlay("text", { @@ -540,6 +546,7 @@ var ArrowTool = function(opts) { leftMargin: 4, text: "v", alpha: 1.0, + backgroundAlpha: 1.0, visible: true, }); var centerButton = Overlays.addOverlay("text", { @@ -553,6 +560,7 @@ var ArrowTool = function(opts) { leftMargin: 4, text: "", alpha: 1.0, + backgroundAlpha: 1.0, visible: true, }); diff --git a/examples/libraries/entitySelectionTool.js b/examples/libraries/entitySelectionTool.js index fa97e9351f..c05ccbcef5 100644 --- a/examples/libraries/entitySelectionTool.js +++ b/examples/libraries/entitySelectionTool.js @@ -368,6 +368,7 @@ SelectionDisplay = (function () { color: { red: 0, green: 0, blue: 0}, backgroundColor: { red: 255, green: 255, blue: 255 }, alpha: 0.7, + backgroundAlpha: 0.7, visible: false, isFacingAvatar: true, drawInFront: true, diff --git a/examples/libraries/progressDialog.js b/examples/libraries/progressDialog.js index dff0904372..7d3b1f88e2 100644 --- a/examples/libraries/progressDialog.js +++ b/examples/libraries/progressDialog.js @@ -40,6 +40,7 @@ progressDialog = (function () { textColor: textColor, backgroundColor: textBackground, alpha: 0.9, + backgroundAlpha: 0.9, visible: false }); @@ -50,6 +51,7 @@ progressDialog = (function () { textColor: textColor, backgroundColor: textBackground, alpha: 0.9, + backgroundAlpha: 0.9, visible: false }); diff --git a/examples/libraries/toolBars.js b/examples/libraries/toolBars.js index dc17f02869..5802625d7b 100644 --- a/examples/libraries/toolBars.js +++ b/examples/libraries/toolBars.js @@ -138,6 +138,7 @@ ToolBar = function(x, y, direction) { width: this.width, height: this.height, alpha: 1.0, + backgroundAlpha: 1.0, visible: false }); this.spacing = []; @@ -243,7 +244,10 @@ ToolBar = function(x, y, direction) { this.tools[tool].setAlpha(alpha); } if (this.back != null) { - Overlays.editOverlay(this.back, { alpha: alpha}); + Overlays.editOverlay(this.back, { + alpha: alpha, + backgroundAlpha: alpha + }); } } else { this.tools[tool].setAlpha(alpha); @@ -263,7 +267,7 @@ ToolBar = function(x, y, direction) { ((direction == ToolBar.VERTICAL) ? 1 : 2) * ToolBar.SPACING, visible: true, backgroundColor: color, - alpha: alpha + backgroundAlpha: alpha }); } } diff --git a/examples/lobby.js b/examples/lobby.js index 9e454eccc9..c5a9645e90 100644 --- a/examples/lobby.js +++ b/examples/lobby.js @@ -113,6 +113,7 @@ function drawLobby() { text: "", lineHeight: lineHeight, alpha: 0.9, + backgroundAlpha: 0.9, ignoreRayIntersection: true, visible: false, isFacingAvatar: true diff --git a/examples/newEditEntities.js b/examples/newEditEntities.js index 9bbb07651c..4abf56c8fd 100644 --- a/examples/newEditEntities.js +++ b/examples/newEditEntities.js @@ -145,6 +145,7 @@ var toolBar = (function () { topMargin: menuItemMargin, text: "Model URL", alpha: 0.9, + backgroundAlpha: 0.9, visible: false }); @@ -154,6 +155,7 @@ var toolBar = (function () { topMargin: menuItemMargin, text: "Model File", alpha: 0.9, + backgroundAlpha: 0.9, visible: false }); diff --git a/examples/notifications.js b/examples/notifications.js index 16e9dd70b2..2c2c4a5c0b 100644 --- a/examples/notifications.js +++ b/examples/notifications.js @@ -115,6 +115,7 @@ function createNotification(text) { color: textColor, backgroundColor: backColor, alpha: backgroundAlpha, + backgroundAlpha: backgroundAlpha, topMargin: topMargin, leftMargin: leftMargin, font: {size: fontSize}, @@ -160,7 +161,7 @@ function fadeIn(noticeIn, buttonIn) { pauseTimer = Script.setInterval(function() { q++; qFade = q / 10.0; - Overlays.editOverlay(noticeIn, {alpha: qFade}); + Overlays.editOverlay(noticeIn, {alpha: qFade, backgroundAlpha: qFade}); Overlays.editOverlay(buttonIn, {alpha: qFade}); if (q >= 9.0) { Script.clearInterval(pauseTimer); @@ -344,7 +345,7 @@ function fadeOut(noticeOut, buttonOut, arraysOut) { pauseTimer = Script.setInterval(function() { r--; rFade = r / 10.0; - Overlays.editOverlay(noticeOut, {alpha: rFade}); + Overlays.editOverlay(noticeOut, {alpha: rFade, backgroundAlpha: rFade}); Overlays.editOverlay(buttonOut, {alpha: rFade}); if (r < 0) { dismiss(noticeOut, buttonOut, arraysOut); diff --git a/examples/testModelOverlaySubMeshes.js b/examples/testModelOverlaySubMeshes.js index 5195b76e60..20ec10ef7c 100644 --- a/examples/testModelOverlaySubMeshes.js +++ b/examples/testModelOverlaySubMeshes.js @@ -57,6 +57,7 @@ var statusText = Overlays.addOverlay("text", { height: 20, backgroundColor: { red: 0, green: 0, blue: 0}, alpha: 1.0, + backgroundAlpha: 1.0, color: { red: 255, green: 255, blue: 255}, topMargin: 4, leftMargin: 4, diff --git a/examples/textInputOverlayExample.js b/examples/textInputOverlayExample.js index e837e81eb5..8a5fad81cd 100644 --- a/examples/textInputOverlayExample.js +++ b/examples/textInputOverlayExample.js @@ -44,6 +44,7 @@ var inputWindow = Overlays.addOverlay("text", { color: textColor, backgroundColor: backColor, alpha: backgroundAlpha, + backgroundAlpha: backgroundAlpha, topMargin: topMargin, leftMargin: leftMargin, font: {size: fontSize}, From 7ea85073f4397faba010fd4ff5f3afbaabc8e3fc Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sat, 6 Dec 2014 11:45:49 -0800 Subject: [PATCH 268/502] introduce precision picking in API form --- examples/developerMenuItems.js | 6 ++-- examples/editModels.js | 2 +- interface/src/Menu.h | 2 ++ interface/src/entities/EntityTreeRenderer.cpp | 17 ++++++--- interface/src/entities/EntityTreeRenderer.h | 3 +- .../entities/RenderableLightEntityItem.cpp | 2 +- .../src/entities/RenderableLightEntityItem.h | 2 +- .../entities/RenderableModelEntityItem.cpp | 29 ++++++++------- .../src/entities/RenderableModelEntityItem.h | 2 +- interface/src/renderer/Model.cpp | 2 +- libraries/entities/src/EntityItem.h | 2 +- .../entities/src/EntityScriptingInterface.cpp | 11 +++--- .../entities/src/EntityScriptingInterface.h | 7 ++-- libraries/entities/src/EntityTreeElement.cpp | 4 +-- libraries/entities/src/EntityTreeElement.h | 2 +- libraries/entities/src/SphereEntityItem.cpp | 2 +- libraries/entities/src/SphereEntityItem.h | 2 +- libraries/entities/src/TextEntityItem.cpp | 2 +- libraries/entities/src/TextEntityItem.h | 2 +- libraries/octree/src/Octree.cpp | 8 +++-- libraries/octree/src/Octree.h | 4 ++- libraries/octree/src/OctreeElement.cpp | 35 +++---------------- libraries/octree/src/OctreeElement.h | 4 +-- 23 files changed, 74 insertions(+), 78 deletions(-) diff --git a/examples/developerMenuItems.js b/examples/developerMenuItems.js index 0d2c4895ea..34bd3b3a75 100644 --- a/examples/developerMenuItems.js +++ b/examples/developerMenuItems.js @@ -19,15 +19,17 @@ function setupMenus() { if (!Menu.menuExists("Developer > Entities")) { Menu.addMenu("Developer > Entities"); Menu.addMenuItem({ menuName: "Developer > Entities", menuItemName: "Display Model Bounds", isCheckable: true, isChecked: false }); + Menu.addMenuItem({ menuName: "Developer > Entities", menuItemName: "Display Model Triangles", isCheckable: true, isChecked: false }); Menu.addMenuItem({ menuName: "Developer > Entities", menuItemName: "Display Model Element Bounds", isCheckable: true, isChecked: false }); Menu.addMenuItem({ menuName: "Developer > Entities", menuItemName: "Display Model Element Children", isCheckable: true, isChecked: false }); - Menu.addMenuItem({ menuName: "Developer > Entities", menuItemName: "Disable Light Entities", isCheckable: true, isChecked: false }); + Menu.addMenuItem({ menuName: "Developer > Entities", menuItemName: "Don't Do Precision Picking", isCheckable: true, isChecked: false }); Menu.addMenuItem({ menuName: "Developer > Entities", menuItemName: "Don't Attempt to Reduce Material Switches", isCheckable: true, isChecked: false }); Menu.addMenuItem({ menuName: "Developer > Entities", menuItemName: "Don't Attempt Render Entities as Scene", isCheckable: true, isChecked: false }); - Menu.addMenuItem({ menuName: "Developer > Entities", menuItemName: "Pick Against Model Triangles", isCheckable: true, isChecked: false }); + Menu.addMenuItem({ menuName: "Developer > Entities", menuItemName: "Don't Do Precision Picking", isCheckable: true, isChecked: false }); Menu.addMenu("Developer > Entities > Culling"); Menu.addMenuItem({ menuName: "Developer > Entities > Culling", menuItemName: "Don't Cull Out Of View Mesh Parts", isCheckable: true, isChecked: false }); Menu.addMenuItem({ menuName: "Developer > Entities > Culling", menuItemName: "Don't Cull Too Small Mesh Parts", isCheckable: true, isChecked: false }); + Menu.addMenuItem({ menuName: "Developer > Entities", menuItemName: "Disable Light Entities", isCheckable: true, isChecked: false }); } } diff --git a/examples/editModels.js b/examples/editModels.js index 8e3503b9b2..60ca9b6ca6 100644 --- a/examples/editModels.js +++ b/examples/editModels.js @@ -2554,7 +2554,7 @@ function mousePressEvent(event) { var pickRay = Camera.computePickRay(event.x, event.y); Vec3.print("[Mouse] Looking at: ", pickRay.origin); - var foundIntersection = Entities.findRayIntersection(pickRay); + var foundIntersection = Entities.findRayIntersection(pickRay, true); // we want precision picking here if(!foundIntersection.accurate) { return; diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 520c83177e..3f8a50af01 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -367,6 +367,7 @@ namespace MenuOption { const QString DontCullTooSmallMeshParts = "Don't Cull Too Small Mesh Parts"; const QString DontReduceMaterialSwitches = "Don't Attempt to Reduce Material Switches"; const QString DontRenderEntitiesAsScene = "Don't Render Entities as Scene"; + const QString DontDoPrecisionPicking = "Don't Do Precision Picking"; const QString DecreaseAvatarSize = "Decrease Avatar Size"; const QString DecreaseVoxelSize = "Decrease Voxel Size"; const QString DisableActivityLogger = "Disable Activity Logger"; @@ -378,6 +379,7 @@ namespace MenuOption { const QString DisplayHandTargets = "Show Hand Targets"; const QString DisplayHermiteData = "Display Hermite Data"; const QString DisplayModelBounds = "Display Model Bounds"; + const QString DisplayModelTriangles = "Display Model Triangles"; const QString DisplayModelElementChildProxies = "Display Model Element Children"; const QString DisplayModelElementProxy = "Display Model Element Bounds"; const QString DisplayTimingDetails = "Display Timing Details"; diff --git a/interface/src/entities/EntityTreeRenderer.cpp b/interface/src/entities/EntityTreeRenderer.cpp index 5aacd36a12..c6a6464438 100644 --- a/interface/src/entities/EntityTreeRenderer.cpp +++ b/interface/src/entities/EntityTreeRenderer.cpp @@ -650,7 +650,8 @@ PickRay EntityTreeRenderer::computePickRay(float x, float y) { } -RayToEntityIntersectionResult EntityTreeRenderer::findRayIntersectionWorker(const PickRay& ray, Octree::lockType lockType) { +RayToEntityIntersectionResult EntityTreeRenderer::findRayIntersectionWorker(const PickRay& ray, Octree::lockType lockType, + bool precisionPicking) { RayToEntityIntersectionResult result; if (_tree) { EntityTree* entityTree = static_cast(_tree); @@ -658,7 +659,8 @@ RayToEntityIntersectionResult EntityTreeRenderer::findRayIntersectionWorker(cons OctreeElement* element; EntityItem* intersectedEntity = NULL; result.intersects = entityTree->findRayIntersection(ray.origin, ray.direction, element, result.distance, result.face, - (void**)&intersectedEntity, lockType, &result.accurate); + (void**)&intersectedEntity, lockType, &result.accurate, + precisionPicking); if (result.intersects && intersectedEntity) { result.entityID = intersectedEntity->getEntityItemID(); result.properties = intersectedEntity->getProperties(); @@ -710,7 +712,9 @@ QScriptValueList EntityTreeRenderer::createEntityArgs(const EntityItemID& entity void EntityTreeRenderer::mousePressEvent(QMouseEvent* event, unsigned int deviceID) { PerformanceTimer perfTimer("EntityTreeRenderer::mousePressEvent"); PickRay ray = computePickRay(event->x(), event->y()); - RayToEntityIntersectionResult rayPickResult = findRayIntersectionWorker(ray, Octree::Lock); + + bool precisionPicking = !Menu::getInstance()->isOptionChecked(MenuOption::DontDoPrecisionPicking); + RayToEntityIntersectionResult rayPickResult = findRayIntersectionWorker(ray, Octree::Lock, precisionPicking); if (rayPickResult.intersects) { //qDebug() << "mousePressEvent over entity:" << rayPickResult.entityID; emit mousePressOnEntity(rayPickResult.entityID, MouseEvent(*event, deviceID)); @@ -734,7 +738,8 @@ void EntityTreeRenderer::mousePressEvent(QMouseEvent* event, unsigned int device void EntityTreeRenderer::mouseReleaseEvent(QMouseEvent* event, unsigned int deviceID) { PerformanceTimer perfTimer("EntityTreeRenderer::mouseReleaseEvent"); PickRay ray = computePickRay(event->x(), event->y()); - RayToEntityIntersectionResult rayPickResult = findRayIntersectionWorker(ray, Octree::Lock); + bool precisionPicking = !Menu::getInstance()->isOptionChecked(MenuOption::DontDoPrecisionPicking); + RayToEntityIntersectionResult rayPickResult = findRayIntersectionWorker(ray, Octree::Lock, precisionPicking); if (rayPickResult.intersects) { //qDebug() << "mouseReleaseEvent over entity:" << rayPickResult.entityID; emit mouseReleaseOnEntity(rayPickResult.entityID, MouseEvent(*event, deviceID)); @@ -768,7 +773,9 @@ void EntityTreeRenderer::mouseMoveEvent(QMouseEvent* event, unsigned int deviceI PerformanceTimer perfTimer("EntityTreeRenderer::mouseMoveEvent"); PickRay ray = computePickRay(event->x(), event->y()); - RayToEntityIntersectionResult rayPickResult = findRayIntersectionWorker(ray, Octree::TryLock); + + bool precisionPicking = false; // for mouse moves we do not do precision picking + RayToEntityIntersectionResult rayPickResult = findRayIntersectionWorker(ray, Octree::TryLock, precisionPicking); if (rayPickResult.intersects) { QScriptValueList entityScriptArgs = createMouseEventArgs(rayPickResult.entityID, event, deviceID); diff --git a/interface/src/entities/EntityTreeRenderer.h b/interface/src/entities/EntityTreeRenderer.h index 0042dd495f..40df81b46c 100644 --- a/interface/src/entities/EntityTreeRenderer.h +++ b/interface/src/entities/EntityTreeRenderer.h @@ -117,7 +117,8 @@ private: QList _releasedModels; void renderProxies(const EntityItem* entity, RenderArgs* args); PickRay computePickRay(float x, float y); - RayToEntityIntersectionResult findRayIntersectionWorker(const PickRay& ray, Octree::lockType lockType); + RayToEntityIntersectionResult findRayIntersectionWorker(const PickRay& ray, Octree::lockType lockType, + bool precisionPicking); EntityItemID _currentHoverOverEntityID; EntityItemID _currentClickingOnEntityID; diff --git a/interface/src/entities/RenderableLightEntityItem.cpp b/interface/src/entities/RenderableLightEntityItem.cpp index 91b2d35106..77dbb5da0b 100644 --- a/interface/src/entities/RenderableLightEntityItem.cpp +++ b/interface/src/entities/RenderableLightEntityItem.cpp @@ -93,7 +93,7 @@ void RenderableLightEntityItem::render(RenderArgs* args) { bool RenderableLightEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, - void** intersectedObject) const { + void** intersectedObject, bool precisionPicking) const { // TODO: this isn't really correct because we don't know if we actually live in the main tree of the applications's // EntityTreeRenderer. But we probably do. Technically we could be on the clipboard and someone might be trying to diff --git a/interface/src/entities/RenderableLightEntityItem.h b/interface/src/entities/RenderableLightEntityItem.h index 40fa31a4ce..2113f486cc 100644 --- a/interface/src/entities/RenderableLightEntityItem.h +++ b/interface/src/entities/RenderableLightEntityItem.h @@ -37,7 +37,7 @@ public: virtual bool supportsDetailedRayIntersection() const { return true; } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, - void** intersectedObject) const; + void** intersectedObject, bool precisionPicking) const; }; diff --git a/interface/src/entities/RenderableModelEntityItem.cpp b/interface/src/entities/RenderableModelEntityItem.cpp index c5f5f0c98a..2dd889538a 100644 --- a/interface/src/entities/RenderableModelEntityItem.cpp +++ b/interface/src/entities/RenderableModelEntityItem.cpp @@ -173,10 +173,18 @@ void RenderableModelEntityItem::render(RenderArgs* args) { // is significantly more expensive. Is there a way to call this that doesn't cost us as much? PerformanceTimer perfTimer("model->render"); bool dontRenderAsScene = Menu::getInstance()->isOptionChecked(MenuOption::DontRenderEntitiesAsScene); - if (dontRenderAsScene) { - _model->render(alpha, modelRenderMode, args); - } else { - _model->renderInScene(alpha, args); + bool displayModelTriangles = Menu::getInstance()->isOptionChecked(MenuOption::DisplayModelTriangles); + bool rendered = false; + if (displayModelTriangles) { + rendered = _model->renderTriangleProxies(); + } + + if (!rendered) { + if (dontRenderAsScene) { + _model->render(alpha, modelRenderMode, args); + } else { + _model->renderInScene(alpha, args); + } } } else { // if we couldn't get a model, then just draw a cube @@ -259,24 +267,21 @@ EntityItemProperties RenderableModelEntityItem::getProperties() const { bool RenderableModelEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, - void** intersectedObject) const { + void** intersectedObject, bool precisionPicking) const { - //qDebug() << "RenderableModelEntityItem::findDetailedRayIntersection()...."; - //qDebug() << " this.id:" << getEntityItemID(); - //qDebug() << " this.modelURL:" << getModelURL(); - //qDebug() << " origin:" << origin; glm::vec3 originInMeters = origin * (float)TREE_SCALE; - //qDebug() << " originInMeters:" << originInMeters; QString extraInfo; float localDistance; - bool intersectsModel = _model->findRayIntersectionAgainstSubMeshes(originInMeters, direction, localDistance, face, extraInfo); + qDebug() << "RenderableModelEntityItem::findDetailedRayIntersection() precisionPicking:" << precisionPicking; + + bool intersectsModel = _model->findRayIntersectionAgainstSubMeshes(originInMeters, direction, + localDistance, face, extraInfo, precisionPicking); if (intersectsModel) { // NOTE: findRayIntersectionAgainstSubMeshes() does work in meters, but we're expected to return // results in tree scale. distance = localDistance / (float)TREE_SCALE; - //qDebug() << " --hit this mode -- returning distance:" << distance; } return intersectsModel; // we only got here if we intersected our non-aabox diff --git a/interface/src/entities/RenderableModelEntityItem.h b/interface/src/entities/RenderableModelEntityItem.h index 9ed85beeaa..e187b944d8 100644 --- a/interface/src/entities/RenderableModelEntityItem.h +++ b/interface/src/entities/RenderableModelEntityItem.h @@ -54,7 +54,7 @@ public: virtual bool supportsDetailedRayIntersection() const { return true; } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, - void** intersectedObject) const; + void** intersectedObject, bool precisionPicking) const; Model* getModel(EntityTreeRenderer* renderer); private: diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index a59a76709a..ea075227cc 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -640,7 +640,7 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g someTriangleHit = false; //qDebug() << " subMeshBox[" << subMeshIndex <<"] --- check triangles!!"; if (!_calculatedMeshTrianglesValid) { - recalcuateMeshBoxes(); + recalcuateMeshBoxes(pickAgainstTriangles); } // check our triangles here.... const QVector& meshTriangles = _calculatedMeshTriangles[subMeshIndex]; diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 7dbcaed8fc..22d956886a 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -138,7 +138,7 @@ public: virtual bool supportsDetailedRayIntersection() const { return false; } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, - void** intersectedObject) const { return true; } + void** intersectedObject, bool precisionPicking) const { return true; } // attributes applicable to all entity types EntityTypes::EntityType getType() const { return _type; } diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 575a6c1a78..7e09e97f6f 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -196,16 +196,17 @@ QVector EntityScriptingInterface::findEntities(const glm::vec3& ce return result; } -RayToEntityIntersectionResult EntityScriptingInterface::findRayIntersection(const PickRay& ray) { - return findRayIntersectionWorker(ray, Octree::TryLock); +RayToEntityIntersectionResult EntityScriptingInterface::findRayIntersection(const PickRay& ray, bool precisionPicking) { + return findRayIntersectionWorker(ray, Octree::TryLock, precisionPicking); } -RayToEntityIntersectionResult EntityScriptingInterface::findRayIntersectionBlocking(const PickRay& ray) { - return findRayIntersectionWorker(ray, Octree::Lock); +RayToEntityIntersectionResult EntityScriptingInterface::findRayIntersectionBlocking(const PickRay& ray, bool precisionPicking) { + return findRayIntersectionWorker(ray, Octree::Lock, precisionPicking); } RayToEntityIntersectionResult EntityScriptingInterface::findRayIntersectionWorker(const PickRay& ray, - Octree::lockType lockType) { + Octree::lockType lockType, + bool precisionPicking) { RayToEntityIntersectionResult result; if (_entityTree) { OctreeElement* element; diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index da0c6c9f1a..1233af678d 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -90,11 +90,11 @@ public slots: /// If the scripting context has visible voxels, this will determine a ray intersection, the results /// may be inaccurate if the engine is unable to access the visible voxels, in which case result.accurate /// will be false. - Q_INVOKABLE RayToEntityIntersectionResult findRayIntersection(const PickRay& ray); + Q_INVOKABLE RayToEntityIntersectionResult findRayIntersection(const PickRay& ray, bool precisionPicking = false); /// If the scripting context has visible voxels, this will determine a ray intersection, and will block in /// order to return an accurate result - Q_INVOKABLE RayToEntityIntersectionResult findRayIntersectionBlocking(const PickRay& ray); + Q_INVOKABLE RayToEntityIntersectionResult findRayIntersectionBlocking(const PickRay& ray, bool precisionPicking = false); Q_INVOKABLE void setLightsArePickable(bool value); Q_INVOKABLE bool getLightsArePickable() const; @@ -124,7 +124,8 @@ private: void queueEntityMessage(PacketType packetType, EntityItemID entityID, const EntityItemProperties& properties); /// actually does the work of finding the ray intersection, can be called in locking mode or tryLock mode - RayToEntityIntersectionResult findRayIntersectionWorker(const PickRay& ray, Octree::lockType lockType); + RayToEntityIntersectionResult findRayIntersectionWorker(const PickRay& ray, Octree::lockType lockType, + bool precisionPicking); uint32_t _nextCreatorTokenID; EntityTree* _entityTree; diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index ac65245f4b..058b4503aa 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -475,7 +475,7 @@ bool EntityTreeElement::bestFitBounds(const glm::vec3& minPoint, const glm::vec3 bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, - void** intersectedObject, float distanceToElementCube) { + void** intersectedObject, bool precisionPicking, float distanceToElementCube) { // only called if we do intersect our bounding cube, but find if we actually intersect with entities... @@ -540,7 +540,7 @@ bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, con //qDebug() << " entity->supportsDetailedRayIntersection()...."; if (entity->findDetailedRayIntersection(origin, direction, keepSearching, element, localDistance, - localFace, intersectedObject)) { + localFace, intersectedObject, precisionPicking)) { //qDebug() << " localDistance (detailed):" << localDistance; diff --git a/libraries/entities/src/EntityTreeElement.h b/libraries/entities/src/EntityTreeElement.h index e59b35189f..4fbe9db323 100644 --- a/libraries/entities/src/EntityTreeElement.h +++ b/libraries/entities/src/EntityTreeElement.h @@ -137,7 +137,7 @@ public: virtual bool canRayIntersect() const { return hasEntities(); } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, - void** intersectedObject, float distanceToElementCube); + void** intersectedObject, bool precisionPicking, float distanceToElementCube); virtual bool findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration, void** penetratedObject) const; diff --git a/libraries/entities/src/SphereEntityItem.cpp b/libraries/entities/src/SphereEntityItem.cpp index 12fdd7a8c4..1960d9623e 100644 --- a/libraries/entities/src/SphereEntityItem.cpp +++ b/libraries/entities/src/SphereEntityItem.cpp @@ -96,7 +96,7 @@ void SphereEntityItem::recalculateCollisionShape() { bool SphereEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, - void** intersectedObject) const { + void** intersectedObject, bool precisionPicking) const { // NOTE: origin and direction are in tree units. But our _sphereShape is in meters, so we need to // do a little math to make these match each other. diff --git a/libraries/entities/src/SphereEntityItem.h b/libraries/entities/src/SphereEntityItem.h index bb4f41726c..5769498229 100644 --- a/libraries/entities/src/SphereEntityItem.h +++ b/libraries/entities/src/SphereEntityItem.h @@ -59,7 +59,7 @@ public: virtual bool supportsDetailedRayIntersection() const { return true; } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, - void** intersectedObject) const; + void** intersectedObject, bool precisionPicking) const; protected: virtual void recalculateCollisionShape(); diff --git a/libraries/entities/src/TextEntityItem.cpp b/libraries/entities/src/TextEntityItem.cpp index 17ef33ee1c..f8f518a581 100644 --- a/libraries/entities/src/TextEntityItem.cpp +++ b/libraries/entities/src/TextEntityItem.cpp @@ -118,7 +118,7 @@ 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) const { + void** intersectedObject, bool precisionPicking) const { RayIntersectionInfo rayInfo; rayInfo._rayStart = origin; diff --git a/libraries/entities/src/TextEntityItem.h b/libraries/entities/src/TextEntityItem.h index a3d323aefd..c980969bb1 100644 --- a/libraries/entities/src/TextEntityItem.h +++ b/libraries/entities/src/TextEntityItem.h @@ -44,7 +44,7 @@ public: virtual bool supportsDetailedRayIntersection() const { return true; } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, - void** intersectedObject) const; + void** intersectedObject, bool precisionPicking) const; static const QString DEFAULT_TEXT; void setText(const QString& value) { _text = value; } diff --git a/libraries/octree/src/Octree.cpp b/libraries/octree/src/Octree.cpp index f13f832920..1a432c8e59 100644 --- a/libraries/octree/src/Octree.cpp +++ b/libraries/octree/src/Octree.cpp @@ -693,13 +693,14 @@ public: BoxFace& face; void** intersectedObject; bool found; + bool precisionPicking; }; bool findRayIntersectionOp(OctreeElement* element, void* extraData) { RayArgs* args = static_cast(extraData); bool keepSearching = true; if (element->findRayIntersection(args->origin, args->direction, keepSearching, - args->element, args->distance, args->face, args->intersectedObject)) { + args->element, args->distance, args->face, args->intersectedObject, args->precisionPicking)) { args->found = true; } return keepSearching; @@ -707,8 +708,9 @@ bool findRayIntersectionOp(OctreeElement* element, void* extraData) { bool Octree::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, OctreeElement*& element, float& distance, BoxFace& face, void** intersectedObject, - Octree::lockType lockType, bool* accurateResult) { - RayArgs args = { origin / (float)(TREE_SCALE), direction, element, distance, face, intersectedObject, false}; + Octree::lockType lockType, bool* accurateResult, bool precisionPicking) { + RayArgs args = { origin / (float)(TREE_SCALE), direction, element, distance, face, + intersectedObject, false, precisionPicking}; distance = FLT_MAX; bool gotLock = false; diff --git a/libraries/octree/src/Octree.h b/libraries/octree/src/Octree.h index 4ac7e22d90..cde8565ca2 100644 --- a/libraries/octree/src/Octree.h +++ b/libraries/octree/src/Octree.h @@ -298,7 +298,9 @@ public: bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, OctreeElement*& node, float& distance, BoxFace& face, void** intersectedObject = NULL, - Octree::lockType lockType = Octree::TryLock, bool* accurateResult = NULL); + Octree::lockType lockType = Octree::TryLock, + bool* accurateResult = NULL, + bool precisionPicking = false); bool findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration, void** penetratedObject = NULL, Octree::lockType lockType = Octree::TryLock, bool* accurateResult = NULL); diff --git a/libraries/octree/src/OctreeElement.cpp b/libraries/octree/src/OctreeElement.cpp index e3ff06b2d3..29f1d52926 100644 --- a/libraries/octree/src/OctreeElement.cpp +++ b/libraries/octree/src/OctreeElement.cpp @@ -1334,7 +1334,7 @@ void OctreeElement::notifyUpdateHooks() { bool OctreeElement::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, - void** intersectedObject) { + void** intersectedObject, bool precisionPicking) { keepSearching = true; // assume that we will continue searching after this. @@ -1346,55 +1346,28 @@ bool OctreeElement::findRayIntersection(const glm::vec3& origin, const glm::vec3 AACube debugCube = cube; debugCube.scale((float)TREE_SCALE); - //qDebug() << "OctreeElement::findRayIntersection()...."; - //qDebug() << " origin:" << origin; - //qDebug() << " checking element:" << debugCube << "in meters"; - //qDebug() << " distance:" << distance; - // if the ray doesn't intersect with our cube, we can stop searching! if (!cube.findRayIntersection(origin, direction, distanceToElementCube, localFace)) { - //qDebug() << " didn't intersect cube... done searching..."; keepSearching = false; // no point in continuing to search return false; // we did not intersect } - //qDebug() << " distanceToElementCube:" << distanceToElementCube; - // by default, we only allow intersections with leaves with content if (!canRayIntersect()) { - //qDebug() << " NOT canRayIntersect() -- no point in calling detailed..."; return false; // we don't intersect with non-leaves, and we keep searching } - // we did hit this element, so calculate appropriate distances - //localDistance *= TREE_SCALE; - // if the distance to the element cube is not less than the current best distance, then it's not possible // for any details inside the cube to be closer so we don't need to consider them. if (cube.contains(origin) || distanceToElementCube < distance) { - //qDebug() << " distanceToElementCube < distance:" << (distanceToElementCube < distance); - //qDebug() << " cube.contains(origin):" << (cube.contains(origin)); - //qDebug() << " continue.... call... findDetailedRayIntersection()..."; - //qDebug() << " distanceToElementCube < distance -- continue.... call... findDetailedRayIntersection()..."; + if (findDetailedRayIntersection(origin, direction, keepSearching, element, distanceToElementDetails, + face, intersectedObject, precisionPicking, distanceToElementCube)) { - if (findDetailedRayIntersection(origin, direction, keepSearching, - element, distanceToElementDetails, face, intersectedObject, distanceToElementCube)) { - - //qDebug() << " findDetailedRayIntersection() -- intersected something"; if (distanceToElementDetails < distance) { - //qDebug() << " distanceToElementDetails < distance -- THIS ONE IS GOOD -------"; - distance = distanceToElementDetails; face = localFace; - - //qDebug() << " distance:" << distance << " -- THIS ONE IS GOOD -------"; - return true; - } else { - //qDebug() << " distanceToElementDetails:" << distanceToElementDetails; - //qDebug() << " distance:" << distance; - //qDebug() << " distanceToElementDetails >= distance -- THIS ONE IS NOT SELECTED even though it INTERSECTED -------"; } } } @@ -1403,7 +1376,7 @@ bool OctreeElement::findRayIntersection(const glm::vec3& origin, const glm::vec3 bool OctreeElement::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, - void** intersectedObject, float distanceToElementCube) { + void** intersectedObject, bool precisionPicking, float distanceToElementCube) { // we did hit this element, so calculate appropriate distances if (hasContent()) { diff --git a/libraries/octree/src/OctreeElement.h b/libraries/octree/src/OctreeElement.h index 9161a9b171..3bd13a2f3c 100644 --- a/libraries/octree/src/OctreeElement.h +++ b/libraries/octree/src/OctreeElement.h @@ -119,11 +119,11 @@ public: virtual bool canRayIntersect() const { return isLeaf(); } virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& node, float& distance, BoxFace& face, - void** intersectedObject = NULL); + void** intersectedObject = NULL, bool precisionPicking = false); virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, - void** intersectedObject, float distanceToElementCube); + void** intersectedObject, bool precisionPicking, float distanceToElementCube); virtual bool findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration, void** penetratedObject) const; From 3bb16ce831bf06e283c589c51f6106a2c271eff8 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sat, 6 Dec 2014 12:03:46 -0800 Subject: [PATCH 269/502] properly wire up precision picking in JS api --- interface/src/renderer/Model.cpp | 12 ++++++++---- interface/src/renderer/Model.h | 2 +- libraries/entities/src/EntityScriptingInterface.cpp | 5 ++++- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index ea075227cc..81ac44872d 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -574,6 +574,7 @@ bool Model::renderTriangleProxies() { bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face, QString& extraInfo, bool pickAgainstTriangles) { +//qDebug() << "Model::findRayIntersectionAgainstSubMeshes() pickAgainstTriangles:" << pickAgainstTriangles; bool intersectedSomething = false; // if we aren't active, we can't ray pick yet... @@ -640,13 +641,13 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g someTriangleHit = false; //qDebug() << " subMeshBox[" << subMeshIndex <<"] --- check triangles!!"; if (!_calculatedMeshTrianglesValid) { - recalcuateMeshBoxes(pickAgainstTriangles); + recalculateMeshBoxes(pickAgainstTriangles); } // check our triangles here.... const QVector& meshTriangles = _calculatedMeshTriangles[subMeshIndex]; int t = 0; foreach (const Triangle& triangle, meshTriangles) { - //qDebug() << "checking triangle["<< t <<"] :" << triangle.v0 << ", "<< triangle.v1 << ", " << triangle.v2; + // qDebug() << "checking triangle["<< t <<"] :" << triangle.v0 << ", "<< triangle.v1 << ", " << triangle.v2; t++; float thisTriangleDistance; @@ -704,8 +705,11 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g return intersectedSomething; } -void Model::recalcuateMeshBoxes(bool pickAgainstTriangles) { +// TODO: we seem to call this too often when things haven't actually changed... look into optimizing this +void Model::recalculateMeshBoxes(bool pickAgainstTriangles) { + //qDebug() << "recalculateMeshBoxes() pickAgainstTriangles:" << pickAgainstTriangles; bool calculatedMeshTrianglesNeeded = pickAgainstTriangles && !_calculatedMeshTrianglesValid; + //qDebug() << "recalculateMeshBoxes() calculatedMeshTrianglesNeeded:" << calculatedMeshTrianglesNeeded; if (!_calculatedMeshBoxesValid || calculatedMeshTrianglesNeeded) { PerformanceTimer perfTimer("calculatedMeshBoxes"); @@ -787,7 +791,7 @@ void Model::renderSetup(RenderArgs* args) { // against. We cache the results of these calculations so long as the model hasn't been // simulated and the mesh hasn't changed. if (args && !_calculatedMeshBoxesValid) { - recalcuateMeshBoxes(); + recalculateMeshBoxes(); } // set up dilated textures on first render after load/simulate diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 69dc6344ad..43b04b7a46 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -371,7 +371,7 @@ private: QVector< QVector > _calculatedMeshTriangles; // world coordinate triangles for all sub meshes bool _calculatedMeshTrianglesValid; - void recalcuateMeshBoxes(bool pickAgainstTriangles = false); + void recalculateMeshBoxes(bool pickAgainstTriangles = false); void segregateMeshGroups(); // used to calculate our list of translucent vs opaque meshes diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 7e09e97f6f..26870ad9bb 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -207,12 +207,15 @@ RayToEntityIntersectionResult EntityScriptingInterface::findRayIntersectionBlock RayToEntityIntersectionResult EntityScriptingInterface::findRayIntersectionWorker(const PickRay& ray, Octree::lockType lockType, bool precisionPicking) { + + RayToEntityIntersectionResult result; if (_entityTree) { OctreeElement* element; EntityItem* intersectedEntity = NULL; result.intersects = _entityTree->findRayIntersection(ray.origin, ray.direction, element, result.distance, result.face, - (void**)&intersectedEntity, lockType, &result.accurate); + (void**)&intersectedEntity, lockType, &result.accurate, + precisionPicking); if (result.intersects && intersectedEntity) { result.entityID = intersectedEntity->getEntityItemID(); result.properties = intersectedEntity->getProperties(); From 351819708bc1d9855175365b9814315650020746 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Sat, 6 Dec 2014 23:50:30 +0100 Subject: [PATCH 270/502] style fixes --- examples/virtualKeyboard.js | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/examples/virtualKeyboard.js b/examples/virtualKeyboard.js index e48da8a4d1..c89dc6fb04 100644 --- a/examples/virtualKeyboard.js +++ b/examples/virtualKeyboard.js @@ -77,7 +77,6 @@ function deleteChar() { } function updateTextOverlay() { - var textwidth = Overlays.textWidth(text, textText); var textLines = textText.split("\n"); var maxLineWidth = 0; for (textLine in textLines) { @@ -182,16 +181,16 @@ keyboard.onFullyLoaded = function() { }; }; -function KeyboardKey(keyboard, key_properties) { +function KeyboardKey(keyboard, keyProperties) { var tthis = this; this._focus = false; - this._beingpressed = false; - this.event = key_properties.event != undefined ? - key_properties.event : 'keypress'; - this.bounds = key_properties.bounds; - this.states = key_properties.states; + this._beingPressed = false; + this.event = keyProperties.event != undefined ? + keyProperties.event : 'keypress'; + this.bounds = keyProperties.bounds; + this.states = keyProperties.states; this.keyboard = keyboard; - this.key_state = key_properties.key_state != undefined ? key_properties.key_state : KBD_LOWERCASE_DEFAULT; + this.keyState = keyProperties.keyState != undefined ? keyProperties.keyState : KBD_LOWERCASE_DEFAULT; // one overlay per bound vector [this.bounds] this.overlays = []; this.getKeyEvent = function() { @@ -217,7 +216,7 @@ function KeyboardKey(keyboard, key_properties) { tthis.setState(eval('KBD_' + (tthis.keyboard.shift ? 'UPPERCASE' : 'LOWERCASE') + '_' + (tthis._focus ? 'HOVER' : 'DEFAULT'))); }; this.updateColor = function() { - var colorIntensity = this._beingpressed ? 128 : 255; + var colorIntensity = this._beingPressed ? 128 : 255; for (var i = 0; i < tthis.bounds.length; i++) { Overlays.editOverlay(tthis.overlays[i], {color: {red: colorIntensity, green: colorIntensity, blue: colorIntensity}} @@ -225,11 +224,11 @@ function KeyboardKey(keyboard, key_properties) { } }; this.press = function() { - tthis._beingpressed = true; + tthis._beingPressed = true; tthis.updateColor(); }; this.release = function() { - tthis._beingpressed = false; + tthis._beingPressed = false; tthis.updateColor(); }; this.blur = function() { @@ -241,10 +240,10 @@ function KeyboardKey(keyboard, key_properties) { tthis.updateState(); }; this.setState = function(state) { - tthis.key_state = state; + tthis.keyState = state; for (var i = 0; i < tthis.bounds.length; i++) { Overlays.editOverlay(tthis.overlays[i], { - subImage: {width: tthis.bounds[i][BOUND_W], height: tthis.bounds[i][BOUND_H], x: tthis.bounds[i][BOUND_X], y: (KEYBOARD_HEIGHT * tthis.key_state) + tthis.bounds[i][BOUND_Y]} + subImage: {width: tthis.bounds[i][BOUND_W], height: tthis.bounds[i][BOUND_H], x: tthis.bounds[i][BOUND_X], y: (KEYBOARD_HEIGHT * tthis.keyState) + tthis.bounds[i][BOUND_Y]} }); } }; @@ -278,7 +277,7 @@ function KeyboardKey(keyboard, key_properties) { y: this.keyboard.getY() + this.bounds[i][BOUND_Y] * keyboard.scale, width: this.bounds[i][BOUND_W] * keyboard.scale, height: this.bounds[i][BOUND_H] * keyboard.scale, - subImage: {width: this.bounds[i][BOUND_W], height: this.bounds[i][BOUND_H], x: this.bounds[i][BOUND_X], y: (KEYBOARD_HEIGHT * this.key_state) + this.bounds[i][BOUND_Y]}, + subImage: {width: this.bounds[i][BOUND_W], height: this.bounds[i][BOUND_H], x: this.bounds[i][BOUND_X], y: (KEYBOARD_HEIGHT * this.keyState) + this.bounds[i][BOUND_Y]}, alpha: 1 }); this.overlays.push(newOverlay); @@ -366,7 +365,7 @@ function Keyboard() { this.releaseKeys = function() { for (var i = 0; i < tthis.keys.length; i++) { - if (tthis.keys[i]._beingpressed) { + if (tthis.keys[i]._beingPressed) { if (tthis.keys[i].event != 'shift') { tthis.keys[i].release(); } @@ -504,9 +503,9 @@ function Keyboard() { {bounds: [[899, 355, 263, 67]], event: 'submit'} ]; - this.keyboardtextureloaded = function() { + this.keyboardTextureLoaded = function() { if (Overlays.isLoaded(tthis.background)) { - Script.clearInterval(tthis.keyboardtextureloaded_timer); + Script.clearInterval(tthis.keyboardTextureLoaded_timer); for (var i = 0; i < keyProperties.length; i++) { tthis.keys.push(new KeyboardKey(tthis, keyProperties[i])); } @@ -515,7 +514,7 @@ function Keyboard() { } } }; - this.keyboardtextureloaded_timer = Script.setInterval(this.keyboardtextureloaded, 250); + this.keyboardTextureLoaded_timer = Script.setInterval(this.keyboardTextureLoaded, 250); } function Cursor() { From a03984a561a78d21387f4b27dc9d0c6576acefdb Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sat, 6 Dec 2014 14:59:50 -0800 Subject: [PATCH 271/502] removed some debug code --- interface/src/Application.cpp | 17 ----------------- .../src/entities/RenderableModelEntityItem.cpp | 2 +- 2 files changed, 1 insertion(+), 18 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 863bca8a85..44f83102e2 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -434,23 +434,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : #endif this->installEventFilter(this); - - - - - qDebug() << "------------------------------------------------------------"; - qDebug() << " test findRayTrianlgeIntersection()...."; - float distanceA; - bool testA = findRayTrianlgeIntersection(glm::vec3(0.5,0.5,1), glm::vec3(0,0,-1), glm::vec3(0,0,0), glm::vec3(1,0,0), glm::vec3(0,1,0), distanceA); - qDebug() << " testA:" << testA; - qDebug() << " distanceA:" << distanceA; - - float distanceB; - bool testB = findRayTrianlgeIntersection(glm::vec3(0.5,0.5,1), glm::vec3(0,0,-1), glm::vec3(0,0,0), glm::vec3(0,1,0), glm::vec3(1,0,0), distanceB); - qDebug() << " testB:" << testB; - qDebug() << " distanceB:" << distanceB; - qDebug() << "------------------------------------------------------------"; - } void Application::aboutToQuit() { diff --git a/interface/src/entities/RenderableModelEntityItem.cpp b/interface/src/entities/RenderableModelEntityItem.cpp index 2dd889538a..51f46ff30c 100644 --- a/interface/src/entities/RenderableModelEntityItem.cpp +++ b/interface/src/entities/RenderableModelEntityItem.cpp @@ -273,7 +273,7 @@ bool RenderableModelEntityItem::findDetailedRayIntersection(const glm::vec3& ori QString extraInfo; float localDistance; - qDebug() << "RenderableModelEntityItem::findDetailedRayIntersection() precisionPicking:" << precisionPicking; + //qDebug() << "RenderableModelEntityItem::findDetailedRayIntersection() precisionPicking:" << precisionPicking; bool intersectsModel = _model->findRayIntersectionAgainstSubMeshes(originInMeters, direction, localDistance, face, extraInfo, precisionPicking); From c8e648c4d724b86aea1284a3867b560d80114d79 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sat, 6 Dec 2014 15:00:29 -0800 Subject: [PATCH 272/502] removed unused menu item --- interface/src/Menu.h | 1 - 1 file changed, 1 deletion(-) diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 3f8a50af01..138828d3e8 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -434,7 +434,6 @@ namespace MenuOption { const QString OldVoxelCullingMode = "Old Voxel Culling Mode"; const QString Pair = "Pair"; const QString PasteToVoxel = "Paste to Voxel..."; - const QString PickAgainstModelTriangles = "Pick Against Model Triangles"; const QString PipelineWarnings = "Log Render Pipeline Warnings"; const QString Preferences = "Preferences..."; const QString Quit = "Quit"; From 1a1fb18ba11cb966855441dd8a70a56d44f0bb8e Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sat, 6 Dec 2014 15:03:26 -0800 Subject: [PATCH 273/502] removed dead code --- interface/src/renderer/Model.cpp | 47 -------------------------------- 1 file changed, 47 deletions(-) diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 81ac44872d..91bb4735fd 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -556,10 +556,8 @@ bool Model::renderTriangleProxies() { glPopMatrix(); } - glBegin(GL_TRIANGLES); foreach (const Triangle& triangle, meshTriangles) { - //qDebug() << "triangle["<< t <<"] :" << triangle.v0 << ", "<< triangle.v1 << ", " << triangle.v2; glVertex3f( triangle.v0.x, triangle.v0.y, triangle.v0.z); glVertex3f( triangle.v1.x, triangle.v1.y, triangle.v1.z); glVertex3f( triangle.v2.x, triangle.v2.y, triangle.v2.z); @@ -574,7 +572,6 @@ bool Model::renderTriangleProxies() { bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face, QString& extraInfo, bool pickAgainstTriangles) { -//qDebug() << "Model::findRayIntersectionAgainstSubMeshes() pickAgainstTriangles:" << pickAgainstTriangles; bool intersectedSomething = false; // if we aren't active, we can't ray pick yet... @@ -582,10 +579,6 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g return intersectedSomething; } - //qDebug() << "Model::findRayIntersectionAgainstSubMeshes()..."; - //qDebug() << " origin:" << origin; - //qDebug() << " direction:" << direction; - // extents is the entity relative, scaled, centered extents of the entity glm::vec3 position = _translation; glm::mat4 rotation = glm::mat4_cast(_rotation); @@ -594,25 +587,18 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g glm::mat4 worldToModelMatrix = glm::inverse(modelToWorldMatrix); Extents modelExtents = getMeshExtents(); // NOTE: unrotated - //qDebug() << " modelExtents:" << modelExtents; glm::vec3 dimensions = modelExtents.maximum - modelExtents.minimum; glm::vec3 corner = -(dimensions * _registrationPoint); // since we're going to do the ray picking in the model frame of reference AABox modelFrameBox(corner, dimensions); - //qDebug() << " modelFrameBox:" << modelFrameBox; - glm::vec3 modelFrameOrigin = glm::vec3(worldToModelMatrix * glm::vec4(origin, 1.0f)); glm::vec3 modelFrameDirection = glm::vec3(worldToModelMatrix * glm::vec4(direction, 0.0f)); - //qDebug() << " modelFrameOrigin:" << modelFrameOrigin; - //qDebug() << " modelFrameDirection:" << modelFrameDirection; // we can use the AABox's ray intersection by mapping our origin and direction into the model frame // and testing intersection there. if (modelFrameBox.findRayIntersection(modelFrameOrigin, modelFrameDirection, distance, face)) { - //qDebug() << " modelFrameBox.findRayIntersection() HITS!!!"; - float bestDistance = std::numeric_limits::max(); float bestTriangleDistance = std::numeric_limits::max(); bool someTriangleHit = false; @@ -623,23 +609,13 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g const FBXGeometry& geometry = _geometry->getFBXGeometry(); - //qDebug() << " Checking mesh boxes...."; - // If we hit the models box, then consider the submeshes... foreach(const AABox& subMeshBox, _calculatedMeshBoxes) { - //qDebug() << " subMeshBox[" << subMeshIndex <<"]:" << subMeshBox; if (subMeshBox.findRayIntersection(origin, direction, distanceToSubMesh, subMeshFace)) { - //qDebug() << " subMeshBox[" << subMeshIndex <<"].findRayIntersection() HITS!"; - //qDebug() << " subMeshBox[" << subMeshIndex <<"].distanceToSubMesh:" << distanceToSubMesh; - //qDebug() << " bestDistance:" << bestDistance; if (distanceToSubMesh < bestDistance) { - - //qDebug() << " distanceToSubMesh < bestDistance !! looks like a good match!"; - if (pickAgainstTriangles) { someTriangleHit = false; - //qDebug() << " subMeshBox[" << subMeshIndex <<"] --- check triangles!!"; if (!_calculatedMeshTrianglesValid) { recalculateMeshBoxes(pickAgainstTriangles); } @@ -647,15 +623,10 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g const QVector& meshTriangles = _calculatedMeshTriangles[subMeshIndex]; int t = 0; foreach (const Triangle& triangle, meshTriangles) { - // qDebug() << "checking triangle["<< t <<"] :" << triangle.v0 << ", "<< triangle.v1 << ", " << triangle.v2; t++; float thisTriangleDistance; if (findRayTrianlgeIntersection(origin, direction, triangle, thisTriangleDistance)) { - //qDebug() << "---- HIT triangle["<< t <<"] :" << triangle.v0 << ", "<< triangle.v1 << ", " << triangle.v2 << " -----"; - //qDebug() << " subMeshBox[" << subMeshIndex <<"].triangle[" << t <<"] --- HITS!!"; - //qDebug() << " subMeshBox[" << subMeshIndex <<"].triangle[" << t <<"] thisTriangleDistance:" << thisTriangleDistance; - //qDebug() << " subMeshBox[" << subMeshIndex <<"].triangle[" << t <<"] bestTriangleDistance:" << bestTriangleDistance; if (thisTriangleDistance < bestDistance) { bestTriangleDistance = thisTriangleDistance; someTriangleHit = true; @@ -664,10 +635,6 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g intersectedSomething = true; face = subMeshFace; extraInfo = geometry.getModelNameOfMesh(subMeshIndex); - - //qDebug() << " subMeshBox[" << subMeshIndex <<"].triangle[" << t <<"] --- WOOT! BEST DISTANCE!"; - } else { - //qDebug() << " subMeshBox[" << subMeshIndex <<"].triangle[" << t <<"] --- not best distance???"; } } } @@ -678,28 +645,16 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g face = subMeshFace; extraInfo = geometry.getModelNameOfMesh(subMeshIndex); } - } else { - //qDebug() << " distanceToSubMesh >= bestDistance !! TOO FAR AWAY!"; } } subMeshIndex++; } - //qDebug() << "pickAgainstTriangles:" << pickAgainstTriangles; - //qDebug() << "someTriangleHit:" << someTriangleHit; - //qDebug() << "bestTriangleDistance:" << bestTriangleDistance; - //qDebug() << "bestDistance:" << bestDistance; - //qDebug() << "intersectedSomething:" << intersectedSomething; - if (intersectedSomething) { - //qDebug() << " --- we hit this model --- "; distance = bestDistance; - //qDebug() << "distance:" << distance; } return intersectedSomething; - } else { - //qDebug() << "modelFrameBox.findRayIntersection()... DID NOT INTERSECT..."; } return intersectedSomething; @@ -707,9 +662,7 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g // TODO: we seem to call this too often when things haven't actually changed... look into optimizing this void Model::recalculateMeshBoxes(bool pickAgainstTriangles) { - //qDebug() << "recalculateMeshBoxes() pickAgainstTriangles:" << pickAgainstTriangles; bool calculatedMeshTrianglesNeeded = pickAgainstTriangles && !_calculatedMeshTrianglesValid; - //qDebug() << "recalculateMeshBoxes() calculatedMeshTrianglesNeeded:" << calculatedMeshTrianglesNeeded; if (!_calculatedMeshBoxesValid || calculatedMeshTrianglesNeeded) { PerformanceTimer perfTimer("calculatedMeshBoxes"); From 08092e7abe2eaca2aa4bc97bac932a2adc6ab3c0 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sat, 6 Dec 2014 15:06:00 -0800 Subject: [PATCH 274/502] removed dead code --- libraries/entities/src/EntityTreeElement.cpp | 39 -------------------- 1 file changed, 39 deletions(-) diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index 058b4503aa..70def167a2 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -478,11 +478,6 @@ bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, con void** intersectedObject, bool precisionPicking, float distanceToElementCube) { // only called if we do intersect our bounding cube, but find if we actually intersect with entities... - - //qDebug() << "EntityTreeElement::findDetailedRayIntersection()...."; - //qDebug() << " origin:" << origin; - //qDebug() << " distance:" << distance; - //qDebug() << " number of entities:" << _entityItems->size(); int entityNumber = 0; QList::iterator entityItr = _entityItems->begin(); @@ -498,16 +493,9 @@ bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, con float localDistance; BoxFace localFace; - //qDebug() << "EntityTreeElement::findDetailedRayIntersection()...."; - //qDebug() << " checking entity[" << entityNumber << "]:" << entity->getEntityItemID() << "-" << qPrintable(EntityTypes::getEntityTypeName(entity->getType())); - //qDebug() << " checking the AABox:" << entityBox; - // if the ray doesn't intersect with our cube, we can stop searching! if (entityBox.findRayIntersection(origin, direction, localDistance, localFace)) { - //qDebug() << " AABox for entity intersects!"; - //qDebug() << " localDistance:" << localDistance; - // extents is the entity relative, scaled, centered extents of the entity glm::mat4 rotation = glm::mat4_cast(entity->getRotation()); glm::mat4 translation = glm::translate(entity->getPosition()); @@ -525,51 +513,27 @@ bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, con // we can use the AABox's ray intersection by mapping our origin and direction into the entity frame // and testing intersection there. - //qDebug() << " checking the entityFrameBox:" << entityFrameBox; - if (entityFrameBox.findRayIntersection(entityFrameOrigin, entityFrameDirection, localDistance, localFace)) { - //qDebug() << " entityFrameBox intersects!"; - //qDebug() << " localDistance:" << localDistance; - if (localDistance < distance) { - //qDebug() << " localDistance < distance... continue..."; - // now ask the entity if we actually intersect if (entity->supportsDetailedRayIntersection()) { - - //qDebug() << " entity->supportsDetailedRayIntersection()...."; - if (entity->findDetailedRayIntersection(origin, direction, keepSearching, element, localDistance, localFace, intersectedObject, precisionPicking)) { - //qDebug() << " localDistance (detailed):" << localDistance; - if (localDistance < distance) { - - //qDebug() << " localDistance < distance..."; - //qDebug() << " CHOOSING THIS ONE ---> " << entity->getEntityItemID() << "-" << qPrintable(EntityTypes::getEntityTypeName(entity->getType())); - distance = localDistance; face = localFace; *intersectedObject = (void*)entity; somethingIntersected = true; - } else { - //qDebug() << " localDistance >= distance... TOO FAR AWAY"; } } } else { // if the entity type doesn't support a detailed intersection, then just return the non-AABox results if (localDistance < distance) { - - //qDebug() << " localDistance < distance..."; - //qDebug() << " CHOOSING THIS ONE ---> " << entity->getEntityItemID() << "-" << qPrintable(EntityTypes::getEntityTypeName(entity->getType())); - distance = localDistance; face = localFace; *intersectedObject = (void*)entity; somethingIntersected = true; - } else { - //qDebug() << " localDistance >= distance... TOO FAR AWAY"; } } } @@ -579,9 +543,6 @@ bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, con ++entityItr; entityNumber++; } - - //qDebug() << " EntityTreeElement::findDetailedRayIntersection().... returning somethingIntersected:" << somethingIntersected << "keepSearching:" << keepSearching; - return somethingIntersected; } From 7011162c70e0ccbb442d94de95d4beb863f773e6 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sat, 6 Dec 2014 15:07:02 -0800 Subject: [PATCH 275/502] removed dead code --- libraries/octree/src/OctreeElement.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/octree/src/OctreeElement.cpp b/libraries/octree/src/OctreeElement.cpp index 29f1d52926..c6938ff1f6 100644 --- a/libraries/octree/src/OctreeElement.cpp +++ b/libraries/octree/src/OctreeElement.cpp @@ -1385,7 +1385,6 @@ bool OctreeElement::findDetailedRayIntersection(const glm::vec3& origin, const g if (intersectedObject) { *intersectedObject = this; } - //qDebug() << " OctreeElement::findDetailedRayIntersection().... hasContent() -- done searching..."; keepSearching = false; return true; // we did intersect } From 8dd1a2815f625d43ce1b2f6884a63fdb01d259c9 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sat, 6 Dec 2014 15:43:17 -0800 Subject: [PATCH 276/502] use precision picking in newEditEntities --- examples/newEditEntities.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/newEditEntities.js b/examples/newEditEntities.js index ef1be8fef9..606ff5955a 100644 --- a/examples/newEditEntities.js +++ b/examples/newEditEntities.js @@ -465,7 +465,7 @@ function rayPlaneIntersection(pickRay, point, normal) { function findClickedEntity(event) { var pickRay = Camera.computePickRay(event.x, event.y); - var foundIntersection = Entities.findRayIntersection(pickRay); + var foundIntersection = Entities.findRayIntersection(pickRay, true); // want precision picking if (!foundIntersection.accurate) { return null; From d698594899a669b9b69f4f4fb61d7380f80274cd Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sat, 6 Dec 2014 19:39:02 -0800 Subject: [PATCH 277/502] use common findRayTriangleIntersection --- interface/src/MetavoxelSystem.cpp | 25 +---------- interface/src/renderer/Model.cpp | 2 +- libraries/shared/src/GeometryUtil.cpp | 62 +++++++++------------------ libraries/shared/src/GeometryUtil.h | 6 +-- 4 files changed, 25 insertions(+), 70 deletions(-) diff --git a/interface/src/MetavoxelSystem.cpp b/interface/src/MetavoxelSystem.cpp index ebf2188b4d..87060d7dfa 100644 --- a/interface/src/MetavoxelSystem.cpp +++ b/interface/src/MetavoxelSystem.cpp @@ -21,6 +21,7 @@ #include +#include #include #include @@ -1095,30 +1096,6 @@ VoxelBuffer::VoxelBuffer(const QVector& vertices, const QVector _materials(materials) { } -static bool findRayTriangleIntersection(const glm::vec3& origin, const glm::vec3& direction, - const glm::vec3& v0, const glm::vec3& v1, const glm::vec3& v2, float& distance) { - glm::vec3 firstSide = v0 - v1; - glm::vec3 secondSide = v2 - v1; - glm::vec3 normal = glm::cross(secondSide, firstSide); - float dividend = glm::dot(normal, v1) - glm::dot(origin, normal); - if (dividend > 0.0f) { - return false; // origin below plane - } - float divisor = glm::dot(normal, direction); - if (divisor > -EPSILON) { - return false; - } - float t = dividend / divisor; - glm::vec3 point = origin + direction * t; - if (glm::dot(normal, glm::cross(point - v1, firstSide)) > 0.0f && - glm::dot(normal, glm::cross(secondSide, point - v1)) > 0.0f && - glm::dot(normal, glm::cross(point - v0, v2 - v0)) > 0.0f) { - distance = t; - return true; - } - return false; -} - bool VoxelBuffer::findFirstRayIntersection(const glm::vec3& entry, const glm::vec3& origin, const glm::vec3& direction, float& distance) const { float highest = _size - 1.0f; diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 91bb4735fd..71f5129a1e 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -626,7 +626,7 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g t++; float thisTriangleDistance; - if (findRayTrianlgeIntersection(origin, direction, triangle, thisTriangleDistance)) { + if (findRayTriangleIntersection(origin, direction, triangle, thisTriangleDistance)) { if (thisTriangleDistance < bestDistance) { bestTriangleDistance = thisTriangleDistance; someTriangleHit = true; diff --git a/libraries/shared/src/GeometryUtil.cpp b/libraries/shared/src/GeometryUtil.cpp index e2736f8502..5376883438 100644 --- a/libraries/shared/src/GeometryUtil.cpp +++ b/libraries/shared/src/GeometryUtil.cpp @@ -252,48 +252,26 @@ bool findRayCapsuleIntersection(const glm::vec3& origin, const glm::vec3& direct return true; } - -bool findRayTrianlgeIntersection(const glm::vec3& origin, const glm::vec3& direction, - const glm::vec3& v0, const glm::vec3& v1, const glm::vec3& v2, float& distance) { - - glm::vec3 e1, e2, h, s, q; - float a, f, u, v, t; - - e1 = v1 - v0; - e2 = v2 - v0; - - h = glm::cross(direction, e2); - a = glm::dot(e1, h); - - if (a > EPSILON && a < EPSILON) { - return false; - } - - f = 1/a; - s = origin - v0; - u = f * glm::dot(s,h); - - if (u < 0.0 || u > 1.0) { - return false; - } - - q = glm::cross(s, e1); - v = f * glm::dot(direction, q); - - if (v < 0.0 || u + v > 1.0) { - return false; - } - - // at this stage we can compute t to find out where the intersection point is on the line - t = f * glm::dot(e2,q); - - // ray intersection - if (t > EPSILON) { - distance = t; - return true; - } else { - // this means that there is a line intersection but not a ray intersection - return false; +bool findRayTriangleIntersection(const glm::vec3& origin, const glm::vec3& direction, + const glm::vec3& v0, const glm::vec3& v1, const glm::vec3& v2, float& distance) { + glm::vec3 firstSide = v0 - v1; + glm::vec3 secondSide = v2 - v1; + glm::vec3 normal = glm::cross(secondSide, firstSide); + float dividend = glm::dot(normal, v1) - glm::dot(origin, normal); + if (dividend > 0.0f) { + return false; // origin below plane + } + float divisor = glm::dot(normal, direction); + if (divisor > -EPSILON) { + return false; + } + float t = dividend / divisor; + glm::vec3 point = origin + direction * t; + if (glm::dot(normal, glm::cross(point - v1, firstSide)) > 0.0f && + glm::dot(normal, glm::cross(secondSide, point - v1)) > 0.0f && + glm::dot(normal, glm::cross(point - v0, v2 - v0)) > 0.0f) { + distance = t; + return true; } return false; } diff --git a/libraries/shared/src/GeometryUtil.h b/libraries/shared/src/GeometryUtil.h index f439352ca8..a6889ef73e 100644 --- a/libraries/shared/src/GeometryUtil.h +++ b/libraries/shared/src/GeometryUtil.h @@ -76,7 +76,7 @@ bool findRaySphereIntersection(const glm::vec3& origin, const glm::vec3& directi bool findRayCapsuleIntersection(const glm::vec3& origin, const glm::vec3& direction, const glm::vec3& start, const glm::vec3& end, float radius, float& distance); -bool findRayTrianlgeIntersection(const glm::vec3& origin, const glm::vec3& direction, +bool findRayTriangleIntersection(const glm::vec3& origin, const glm::vec3& direction, const glm::vec3& v0, const glm::vec3& v1, const glm::vec3& v2, float& distance); class Triangle { @@ -86,9 +86,9 @@ public: glm::vec3 v2; }; -inline bool findRayTrianlgeIntersection(const glm::vec3& origin, const glm::vec3& direction, +inline bool findRayTriangleIntersection(const glm::vec3& origin, const glm::vec3& direction, const Triangle& triangle, float& distance) { - return findRayTrianlgeIntersection(origin, direction, triangle.v0, triangle.v1, triangle.v2, distance); + return findRayTriangleIntersection(origin, direction, triangle.v0, triangle.v1, triangle.v2, distance); } From b08d5b87ca7e954a16c115c8d31fff1efb78aa67 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sun, 7 Dec 2014 01:28:06 -0800 Subject: [PATCH 278/502] implement proper ray picking against ellipsoids Conflicts: libraries/entities/src/SphereEntityItem.cpp --- libraries/entities/src/SphereEntityItem.cpp | 28 +++++++++++++-------- libraries/entities/src/SphereEntityItem.h | 2 ++ 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/libraries/entities/src/SphereEntityItem.cpp b/libraries/entities/src/SphereEntityItem.cpp index 12fdd7a8c4..651d4db4ef 100644 --- a/libraries/entities/src/SphereEntityItem.cpp +++ b/libraries/entities/src/SphereEntityItem.cpp @@ -10,9 +10,12 @@ // +#include + #include #include +#include #include "EntityTree.h" #include "EntityTreeElement.h" @@ -97,18 +100,21 @@ void SphereEntityItem::recalculateCollisionShape() { bool SphereEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, void** intersectedObject) const { - - // NOTE: origin and direction are in tree units. But our _sphereShape is in meters, so we need to - // do a little math to make these match each other. - RayIntersectionInfo rayInfo; - rayInfo._rayStart = origin * (float)TREE_SCALE; - rayInfo._rayDirection = direction; + // determine the ray in the frame of the entity transformed from a unit sphere + glm::mat4 translation = glm::translate(getPosition()); + glm::mat4 rotation = glm::mat4_cast(getRotation()); + glm::mat4 scale = glm::scale(getDimensions()); + glm::mat4 registration = glm::translate(glm::vec3(0.5f,0.5f,0.5f) - getRegistrationPoint()); + glm::mat4 entityToWorldMatrix = translation * rotation * scale * registration; + glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix); + glm::vec3 entityFrameOrigin = glm::vec3(worldToEntityMatrix * glm::vec4(origin, 1.0f)); + glm::vec3 entityFrameDirection = glm::normalize(glm::vec3(worldToEntityMatrix * glm::vec4(direction, 1.0f))); - // TODO: Note this is really doing ray intersections against a sphere, which is fine except in cases - // where our dimensions actually make us an ellipsoid. But we'll live with this for now until we - // get a more full fledged physics library - if (_sphereShape.findRayIntersection(rayInfo)) { - distance = rayInfo._hitDistance / (float)TREE_SCALE; + float localDistance; + if (findRaySphereIntersection(entityFrameOrigin, entityFrameDirection, glm::vec3(0.0f), 0.5f, localDistance)) { + glm::vec3 entityFrameHitAt = entityFrameOrigin + (entityFrameDirection * localDistance); + glm::vec3 hitAt = glm::vec3(entityToWorldMatrix * glm::vec4(entityFrameHitAt, 1.0f)); + distance = glm::distance(origin,hitAt); return true; } return false; diff --git a/libraries/entities/src/SphereEntityItem.h b/libraries/entities/src/SphereEntityItem.h index bb4f41726c..80b026e31d 100644 --- a/libraries/entities/src/SphereEntityItem.h +++ b/libraries/entities/src/SphereEntityItem.h @@ -61,6 +61,8 @@ public: bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, void** intersectedObject) const; + bool isCircle() const { return false && _dimensions.x == _dimensions.y && _dimensions.y == _dimensions.z; } + protected: virtual void recalculateCollisionShape(); From b9891748e14730cf2554b90aae440a0d038234c8 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sun, 7 Dec 2014 01:32:31 -0800 Subject: [PATCH 279/502] remove dead code --- libraries/entities/src/SphereEntityItem.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/libraries/entities/src/SphereEntityItem.h b/libraries/entities/src/SphereEntityItem.h index 80b026e31d..6553e225a7 100644 --- a/libraries/entities/src/SphereEntityItem.h +++ b/libraries/entities/src/SphereEntityItem.h @@ -60,9 +60,7 @@ public: virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, void** intersectedObject) const; - - bool isCircle() const { return false && _dimensions.x == _dimensions.y && _dimensions.y == _dimensions.z; } - + protected: virtual void recalculateCollisionShape(); From dd4f3a40066af77fa5ca33c83fc6fe7ff8c583d6 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sun, 7 Dec 2014 20:18:30 -0800 Subject: [PATCH 280/502] coding standard, added comments --- libraries/entities/src/SphereEntityItem.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libraries/entities/src/SphereEntityItem.cpp b/libraries/entities/src/SphereEntityItem.cpp index 651d4db4ef..35fe45c0e2 100644 --- a/libraries/entities/src/SphereEntityItem.cpp +++ b/libraries/entities/src/SphereEntityItem.cpp @@ -104,15 +104,18 @@ bool SphereEntityItem::findDetailedRayIntersection(const glm::vec3& origin, cons glm::mat4 translation = glm::translate(getPosition()); glm::mat4 rotation = glm::mat4_cast(getRotation()); glm::mat4 scale = glm::scale(getDimensions()); - glm::mat4 registration = glm::translate(glm::vec3(0.5f,0.5f,0.5f) - getRegistrationPoint()); + glm::mat4 registration = glm::translate(glm::vec3(0.5f, 0.5f, 0.5f) - getRegistrationPoint()); glm::mat4 entityToWorldMatrix = translation * rotation * scale * registration; glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix); glm::vec3 entityFrameOrigin = glm::vec3(worldToEntityMatrix * glm::vec4(origin, 1.0f)); glm::vec3 entityFrameDirection = glm::normalize(glm::vec3(worldToEntityMatrix * glm::vec4(direction, 1.0f))); float localDistance; + // NOTE: unit sphere has center of 0,0,0 and radius of 0.5 if (findRaySphereIntersection(entityFrameOrigin, entityFrameDirection, glm::vec3(0.0f), 0.5f, localDistance)) { + // determine where on the unit sphere the hit point occured glm::vec3 entityFrameHitAt = entityFrameOrigin + (entityFrameDirection * localDistance); + // then translate back to work coordinates glm::vec3 hitAt = glm::vec3(entityToWorldMatrix * glm::vec4(entityFrameHitAt, 1.0f)); distance = glm::distance(origin,hitAt); return true; From 497fbade9bf2db4a730dfb1a4e5f5299a00810fa Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 8 Dec 2014 06:48:04 -0800 Subject: [PATCH 281/502] fix crash in entity related AC scripts --- libraries/entities/src/EntityTree.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index d3d9e2da53..5f9aa4a159 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -19,9 +19,13 @@ #include "MovingEntitiesOperator.h" #include "UpdateEntityOperator.h" -EntityTree::EntityTree(bool shouldReaverage) : Octree(shouldReaverage), _simulation(NULL) { +EntityTree::EntityTree(bool shouldReaverage) : + Octree(shouldReaverage), + _fbxService(NULL), + _lightsArePickable(true), + _simulation(NULL) +{ _rootElement = createNewElement(); - _lightsArePickable = true; // assume they are by default } EntityTree::~EntityTree() { From 0f5930a43d0281f93815ca6b49353cb87d2f0260 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 8 Dec 2014 06:50:28 -0800 Subject: [PATCH 282/502] add identifyEntity() to butterflies script --- examples/butterflies.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/examples/butterflies.js b/examples/butterflies.js index 069a0d6792..edc33f7625 100644 --- a/examples/butterflies.js +++ b/examples/butterflies.js @@ -103,6 +103,9 @@ function updateButterflies(deltaTime) { var CHANCE_OF_IMPULSE = 0.04; for (var i = 0; i < numButterflies; i++) { if (Math.random() < CHANCE_OF_IMPULSE) { + if (!butterflies[i].isKnownID) { + butterflies[i] = Entities.identifyEntity(butterflies[i]); + } var properties = Entities.getEntityProperties(butterflies[i]); if (Vec3.length(Vec3.subtract(properties.position, flockPosition)) > range) { Entities.editEntity(butterflies[i], { position: flockPosition } ); From cf98bff28b91612bbd7b93872fd12f83e8d5158f Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 8 Dec 2014 07:23:45 -0800 Subject: [PATCH 283/502] enforce dimensions for Light and Text entities --- libraries/entities/src/EntityItem.h | 2 +- libraries/entities/src/LightEntityItem.cpp | 7 +++++++ libraries/entities/src/LightEntityItem.h | 3 +++ libraries/entities/src/TextEntityItem.cpp | 7 +++++++ libraries/entities/src/TextEntityItem.h | 3 +++ 5 files changed, 21 insertions(+), 1 deletion(-) diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 7dbcaed8fc..edabcb1f3f 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -160,7 +160,7 @@ public: float getLargestDimension() const { return glm::length(_dimensions); } /// get the largest possible dimension /// set dimensions in domain scale units (0.0 - 1.0) this will also reset radius appropriately - void setDimensions(const glm::vec3& value) { _dimensions = value; recalculateCollisionShape(); } + virtual void setDimensions(const glm::vec3& value) { _dimensions = value; recalculateCollisionShape(); } /// set dimensions in meter units (0.0 - TREE_SCALE) this will also reset radius appropriately void setDimensionsInMeters(const glm::vec3& value) { setDimensions(value / (float) TREE_SCALE); } diff --git a/libraries/entities/src/LightEntityItem.cpp b/libraries/entities/src/LightEntityItem.cpp index 20f28cd98c..a24fe58c2a 100644 --- a/libraries/entities/src/LightEntityItem.cpp +++ b/libraries/entities/src/LightEntityItem.cpp @@ -47,6 +47,13 @@ LightEntityItem::LightEntityItem(const EntityItemID& entityItemID, const EntityI _emptyShape.setRadius(0.0f); } +void LightEntityItem::setDimensions(const glm::vec3& value) { + float maxDimension = glm::max(value.x, value.y, value.z); + _dimensions = glm::vec3(maxDimension, maxDimension, maxDimension); + recalculateCollisionShape(); +} + + EntityItemProperties LightEntityItem::getProperties() const { EntityItemProperties properties = EntityItem::getProperties(); // get the properties from our base class diff --git a/libraries/entities/src/LightEntityItem.h b/libraries/entities/src/LightEntityItem.h index 2006efb896..eb9a2ed051 100644 --- a/libraries/entities/src/LightEntityItem.h +++ b/libraries/entities/src/LightEntityItem.h @@ -22,6 +22,9 @@ public: LightEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties); ALLOW_INSTANTIATION // This class can be instantiated + + /// set dimensions in domain scale units (0.0 - 1.0) this will also reset radius appropriately + virtual void setDimensions(const glm::vec3& value); // methods for getting/setting all properties of an entity virtual EntityItemProperties getProperties() const; diff --git a/libraries/entities/src/TextEntityItem.cpp b/libraries/entities/src/TextEntityItem.cpp index 17ef33ee1c..08fbcdfcf7 100644 --- a/libraries/entities/src/TextEntityItem.cpp +++ b/libraries/entities/src/TextEntityItem.cpp @@ -40,6 +40,13 @@ TextEntityItem::TextEntityItem(const EntityItemID& entityItemID, const EntityIte setProperties(properties, true); } +void TextEntityItem::setDimensions(const glm::vec3& value) { + // NOTE: Text Entities always have a "depth" of 1cm. + float fixedDepth = 0.01f / (float)TREE_SCALE; + _dimensions = glm::vec3(value.x, value.y, fixedDepth); + recalculateCollisionShape(); +} + EntityItemProperties TextEntityItem::getProperties() const { EntityItemProperties properties = EntityItem::getProperties(); // get the properties from our base class diff --git a/libraries/entities/src/TextEntityItem.h b/libraries/entities/src/TextEntityItem.h index a3d323aefd..4bdd8434b6 100644 --- a/libraries/entities/src/TextEntityItem.h +++ b/libraries/entities/src/TextEntityItem.h @@ -21,6 +21,9 @@ public: TextEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties); ALLOW_INSTANTIATION // This class can be instantiated + + /// set dimensions in domain scale units (0.0 - 1.0) this will also reset radius appropriately + virtual void setDimensions(const glm::vec3& value); // methods for getting/setting all properties of an entity virtual EntityItemProperties getProperties() const; From aefeda37bdde58c88d7b49692894744813de8dfc Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 8 Dec 2014 09:41:58 -0800 Subject: [PATCH 284/502] more debugging --- examples/libraries/entitySelectionTool.js | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/examples/libraries/entitySelectionTool.js b/examples/libraries/entitySelectionTool.js index fa97e9351f..a96eec9bbb 100644 --- a/examples/libraries/entitySelectionTool.js +++ b/examples/libraries/entitySelectionTool.js @@ -1772,17 +1772,27 @@ SelectionDisplay = (function () { var centerToZero = Vec3.subtract(center, zero); var centerToIntersect = Vec3.subtract(center, result.intersection); var angleFromZero = Vec3.orientedAngle(centerToZero, centerToIntersect, rotationNormal); - var distanceFromCenter = Vec3.distance(center, result.intersection); var snapToInner = distanceFromCenter < innerRadius; var snapAngle = snapToInner ? innerSnapAngle : 1.0; - angleFromZero = Math.floor(angleFromZero / snapAngle) * snapAngle; - + // for debugging if (debug) { Vec3.print(" result.intersection:",result.intersection); Overlays.editOverlay(rotateCurrentOverlay, { visible: true, start: center, end: result.intersection }); + Vec3.print(" centerToZero:", centerToZero); + Vec3.print(" centerToIntersect:", centerToIntersect); + Vec3.print(" rotationNormal:", rotationNormal); print(" angleFromZero:" + angleFromZero); + print(" distanceFromCenter:" + distanceFromCenter); + print(" snapAngle:" + snapAngle); + } + + angleFromZero = Math.floor(angleFromZero / snapAngle) * snapAngle; + + // for debugging + if (debug) { + print(" angleFromZero:" + angleFromZero + " --- after snap"); } var yawChange = Quat.fromVec3Degrees({ x: 0, y: angleFromZero, z: 0 }); From 299389ccef8ece4cf0cdd87a51f9c122de767ea2 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 8 Dec 2014 09:59:33 -0800 Subject: [PATCH 285/502] Fixed typo --- interface/src/Application.cpp | 2 -- interface/src/ui/ApplicationOverlay.cpp | 28 ++++++++++++------------- interface/src/ui/ApplicationOverlay.h | 10 ++++----- 3 files changed, 19 insertions(+), 21 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 2d92a99cab..6f12957b2d 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2347,12 +2347,10 @@ void Application::update(float deltaTime) { if (OculusManager::isConnected() && Menu::getInstance()->isOptionChecked(MenuOption::EnableVRMode)){ if (_window->cursor().shape() != Qt::BlankCursor) { - qDebug() << "Hiding cursor" << _window->cursor().shape(); cursor = _window->cursor(); _window->setCursor(QCursor(Qt::BlankCursor)); } } else if(_window->cursor().shape() == Qt::BlankCursor) { - qDebug() << "Showing cursor" << _window->cursor().shape(); _window->setCursor(cursor); } diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index f4e9e627ad..602e99ac31 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -103,7 +103,7 @@ bool raySphereIntersect(const glm::vec3 &dir, const glm::vec3 &origin, float r, } } -void renderReticule(glm::quat orientation, float alpha) { +void renderReticle(glm::quat orientation, float alpha) { glm::vec3 topLeft = getPoint(reticleSize / 2.0f, -reticleSize / 2.0f); glm::vec3 topRight = getPoint(-reticleSize / 2.0f, -reticleSize / 2.0f); glm::vec3 bottomLeft = getPoint(reticleSize / 2.0f, reticleSize / 2.0f); @@ -269,7 +269,7 @@ void ApplicationOverlay::displayOverlayTextureOculus(Camera& whichCamera) { glm::mat4 rotation = glm::toMat4(orientation); glMultMatrixf(&rotation[0][0]); glScalef(scale, scale, scale); - for (int i = 0; i < NUMBER_OF_RETICULES; i++) { + for (int i = 0; i < NUMBER_OF_RETICLES; i++) { if (_magActive[i]) { _magSizeMult[i] += MAG_SPEED; @@ -285,8 +285,8 @@ void ApplicationOverlay::displayOverlayTextureOculus(Camera& whichCamera) { if (_magSizeMult[i] > 0.0f) { //Render magnifier, but dont show border for mouse magnifier - glm::vec2 projection = screenToOverlay(glm::vec2(_reticulePosition[MOUSE].x(), - _reticulePosition[MOUSE].y())); + glm::vec2 projection = screenToOverlay(glm::vec2(_reticlePosition[MOUSE].x(), + _reticlePosition[MOUSE].y())); renderMagnifier(projection, _magSizeMult[i], i != MOUSE); } @@ -528,7 +528,7 @@ void ApplicationOverlay::renderPointers() { QPoint position = QPoint(application->getTrueMouseX(), application->getTrueMouseY()); static const int MAX_IDLE_TIME = 3; - if (_reticulePosition[MOUSE] != position) { + if (_reticlePosition[MOUSE] != position) { _lastMouseMove = usecTimestampNow(); } else if (usecTimestampNow() - _lastMouseMove > MAX_IDLE_TIME * USECS_PER_SECOND) { float pitch, yaw, roll; @@ -539,7 +539,7 @@ void ApplicationOverlay::renderPointers() { QCursor::setPos(application->getGLWidget()->mapToGlobal(position)); } - _reticulePosition[MOUSE] = position; + _reticlePosition[MOUSE] = position; _reticleActive[MOUSE] = true; _magActive[MOUSE] = true; _reticleActive[LEFT_CONTROLLER] = false; @@ -561,9 +561,9 @@ void ApplicationOverlay::renderControllerPointers() { MyAvatar* myAvatar = application->getAvatar(); //Static variables used for storing controller state - static quint64 pressedTime[NUMBER_OF_RETICULES] = { 0ULL, 0ULL, 0ULL }; - static bool isPressed[NUMBER_OF_RETICULES] = { false, false, false }; - static bool stateWhenPressed[NUMBER_OF_RETICULES] = { false, false, false }; + static quint64 pressedTime[NUMBER_OF_RETICLES] = { 0ULL, 0ULL, 0ULL }; + static bool isPressed[NUMBER_OF_RETICLES] = { false, false, false }; + static bool stateWhenPressed[NUMBER_OF_RETICLES] = { false, false, false }; const HandData* handData = Application::getInstance()->getAvatar()->getHandData(); @@ -610,7 +610,7 @@ void ApplicationOverlay::renderControllerPointers() { QPoint point = getPalmClickLocation(palmData); - _reticulePosition[index] = point; + _reticlePosition[index] = point; //When button 2 is pressed we drag the mag window if (isPressed[index]) { @@ -685,16 +685,16 @@ void ApplicationOverlay::renderPointersOculus(const glm::vec3& eyePos) { float yaw = glm::acos(-tipDirection.z) * ((yawSign == 0.0f) ? 1.0f : yawSign); glm::quat orientation = glm::quat(glm::vec3(pitch, yaw, 0.0f)); - renderReticule(orientation, _alpha); + renderReticle(orientation, _alpha); } } //Mouse Pointer if (_reticleActive[MOUSE]) { - glm::vec2 projection = screenToSpherical(glm::vec2(_reticulePosition[MOUSE].x(), - _reticulePosition[MOUSE].y())); + glm::vec2 projection = screenToSpherical(glm::vec2(_reticlePosition[MOUSE].x(), + _reticlePosition[MOUSE].y())); glm::quat orientation(glm::vec3(-projection.y, projection.x, 0.0f)); - renderReticule(orientation, _alpha); + renderReticle(orientation, _alpha); } glEnable(GL_DEPTH_TEST); diff --git a/interface/src/ui/ApplicationOverlay.h b/interface/src/ui/ApplicationOverlay.h index 538a163d0e..269adef4f3 100644 --- a/interface/src/ui/ApplicationOverlay.h +++ b/interface/src/ui/ApplicationOverlay.h @@ -94,11 +94,11 @@ private: float _textureFov; float _textureAspectRatio; - enum Reticules { MOUSE, LEFT_CONTROLLER, RIGHT_CONTROLLER, NUMBER_OF_RETICULES }; - bool _reticleActive[NUMBER_OF_RETICULES]; - QPoint _reticulePosition[NUMBER_OF_RETICULES]; - bool _magActive[NUMBER_OF_RETICULES]; - float _magSizeMult[NUMBER_OF_RETICULES]; + enum Reticles { MOUSE, LEFT_CONTROLLER, RIGHT_CONTROLLER, NUMBER_OF_RETICLES }; + bool _reticleActive[NUMBER_OF_RETICLES]; + QPoint _reticlePosition[NUMBER_OF_RETICLES]; + bool _magActive[NUMBER_OF_RETICLES]; + float _magSizeMult[NUMBER_OF_RETICLES]; quint64 _lastMouseMove; float _alpha; From 27bc394bed122f155a8bf08fc9d4796b266c4917 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 8 Dec 2014 10:52:53 -0800 Subject: [PATCH 286/502] repair collision info mismatch --- examples/collidingEntities.js | 12 +++++++----- interface/src/Application.cpp | 7 +++++++ interface/src/entities/EntityTreeRenderer.cpp | 12 ++++++++++++ interface/src/entities/EntityTreeRenderer.h | 3 +++ libraries/entities/src/EntityCollisionSystem.cpp | 13 +++++++------ libraries/entities/src/EntityCollisionSystem.h | 8 ++++---- libraries/entities/src/EntityScriptingInterface.h | 4 ++-- libraries/shared/src/RegisteredMetaTypes.cpp | 1 + libraries/shared/src/RegisteredMetaTypes.h | 2 ++ 9 files changed, 45 insertions(+), 17 deletions(-) diff --git a/examples/collidingEntities.js b/examples/collidingEntities.js index 57a3a1f709..4f03a9ee87 100644 --- a/examples/collidingEntities.js +++ b/examples/collidingEntities.js @@ -42,7 +42,7 @@ function draw(deltaTime) { var colorGreen = { red: 0, green: 255, blue: 0 }; var startPosition = { x: 2, - y: 0, + y: 1, z: 2 }; var largeRadius = 0.5; var verySlow = { @@ -55,9 +55,10 @@ function draw(deltaTime) { collisionsWillMove: true, position: startPosition, dimensions: {x: largeRadius, y: largeRadius, z: largeRadius}, + registrationPoint: { x: 0.5, y: 0.5, z: 0.5 }, color: colorGreen, - velocity: verySlow, - gravity: gravity, + //velocity: verySlow, + //gravity: gravity, damping: damping, lifetime: 20 }; @@ -71,7 +72,7 @@ function draw(deltaTime) { var center = { x: 0, - y: 0, + y: 1, z: 0 }; var entitySize = 0.1; @@ -97,9 +98,10 @@ function draw(deltaTime) { collisionsWillMove: true, position: center, dimensions: {x: entitySize, y: entitySize, z: entitySize}, + registrationPoint: { x: 0.5, y: 0.5, z: 0.5 }, color: color, velocity: velocity, - gravity: gravity, + //gravity: gravity, damping: damping, lifetime: 20 }; diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 2d92a99cab..0ba3727794 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2019,6 +2019,13 @@ void Application::init() { connect(&_entityCollisionSystem, &EntityCollisionSystem::entityCollisionWithEntity, ScriptEngine::getEntityScriptingInterface(), &EntityScriptingInterface::entityCollisionWithEntity); + // connect the _entityCollisionSystem to our EntityTreeRenderer since that's what handles running entity scripts + connect(&_entityCollisionSystem, &EntityCollisionSystem::entityCollisionWithVoxel, + &_entities, &EntityTreeRenderer::entityCollisionWithVoxel); + + connect(&_entityCollisionSystem, &EntityCollisionSystem::entityCollisionWithEntity, + &_entities, &EntityTreeRenderer::entityCollisionWithEntity); + // connect the _entities (EntityTreeRenderer) to our script engine's EntityScriptingInterface for firing // of events related clicking, hovering over, and entering entities _entities.connectSignalsToSlots(ScriptEngine::getEntityScriptingInterface()); diff --git a/interface/src/entities/EntityTreeRenderer.cpp b/interface/src/entities/EntityTreeRenderer.cpp index 055cbf5026..e9c4e456f2 100644 --- a/interface/src/entities/EntityTreeRenderer.cpp +++ b/interface/src/entities/EntityTreeRenderer.cpp @@ -884,3 +884,15 @@ void EntityTreeRenderer::changingEntityID(const EntityItemID& oldEntityID, const } } +void EntityTreeRenderer::entityCollisionWithVoxel(const EntityItemID& entityID, const VoxelDetail& voxel, + const Collision& collision) { + qDebug() << "EntityTreeRenderer::entityCollisionWithVoxel()... "; +} + +void EntityTreeRenderer::entityCollisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, + const Collision& collision) { + qDebug() << "EntityTreeRenderer::entityCollisionWithEntity()... "; + qDebug() << " idA:" << idA; + qDebug() << " idB:" << idB; +} + diff --git a/interface/src/entities/EntityTreeRenderer.h b/interface/src/entities/EntityTreeRenderer.h index 40df81b46c..a8695db36d 100644 --- a/interface/src/entities/EntityTreeRenderer.h +++ b/interface/src/entities/EntityTreeRenderer.h @@ -106,6 +106,9 @@ public slots: void deletingEntity(const EntityItemID& entityID); void changingEntityID(const EntityItemID& oldEntityID, const EntityItemID& newEntityID); void entitySciptChanging(const EntityItemID& entityID); + void entityCollisionWithVoxel(const EntityItemID& entityID, const VoxelDetail& voxel, const Collision& collision); + void entityCollisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const Collision& collision); + protected: virtual Octree* createTree() { return new EntityTree(true); } diff --git a/libraries/entities/src/EntityCollisionSystem.cpp b/libraries/entities/src/EntityCollisionSystem.cpp index 2ac8ea596d..110aef443f 100644 --- a/libraries/entities/src/EntityCollisionSystem.cpp +++ b/libraries/entities/src/EntityCollisionSystem.cpp @@ -70,13 +70,13 @@ void EntityCollisionSystem::checkEntity(EntityItem* entity) { } void EntityCollisionSystem::emitGlobalEntityCollisionWithVoxel(EntityItem* entity, - VoxelDetail* voxelDetails, const CollisionInfo& collision) { + VoxelDetail* voxelDetails, const Collision& collision) { EntityItemID entityItemID = entity->getEntityItemID(); emit entityCollisionWithVoxel(entityItemID, *voxelDetails, collision); } void EntityCollisionSystem::emitGlobalEntityCollisionWithEntity(EntityItem* entityA, - EntityItem* entityB, const CollisionInfo& collision) { + EntityItem* entityB, const Collision& collision) { EntityItemID idA = entityA->getEntityItemID(); EntityItemID idB = entityB->getEntityItemID(); @@ -104,7 +104,8 @@ void EntityCollisionSystem::updateCollisionWithVoxels(EntityItem* entity) { // the results to systems outside of this octree reference frame. collisionInfo._contactPoint = (float)TREE_SCALE * (entity->getPosition() + entity->getRadius() * glm::normalize(collisionInfo._penetration)); // let the global script run their collision scripts for Entities if they have them - emitGlobalEntityCollisionWithVoxel(entity, voxelDetails, collisionInfo); + Collision collision(collisionInfo._contactPoint, collisionInfo._penetration); + emitGlobalEntityCollisionWithVoxel(entity, voxelDetails, collision); // we must scale back down to the octree reference frame before updating the Entity properties collisionInfo._penetration /= (float)(TREE_SCALE); @@ -169,10 +170,10 @@ void EntityCollisionSystem::updateCollisionWithEntities(EntityItem* entityA) { quint64 now = usecTimestampNow(); - CollisionInfo collision; - collision._penetration = penetration; + Collision collision; + collision.penetration = penetration; // for now the contactPoint is the average between the the two paricle centers - collision._contactPoint = (0.5f * (float)TREE_SCALE) * (entityA->getPosition() + entityB->getPosition()); + collision.contactPoint = (0.5f * (float)TREE_SCALE) * (entityA->getPosition() + entityB->getPosition()); emitGlobalEntityCollisionWithEntity(entityA, entityB, collision); glm::vec3 axis = glm::normalize(penetration); diff --git a/libraries/entities/src/EntityCollisionSystem.h b/libraries/entities/src/EntityCollisionSystem.h index b4421ffc72..48b7c17ead 100644 --- a/libraries/entities/src/EntityCollisionSystem.h +++ b/libraries/entities/src/EntityCollisionSystem.h @@ -53,15 +53,15 @@ public: void updateCollisionSound(EntityItem* Entity, const glm::vec3 &penetration, float frequency); signals: - void entityCollisionWithVoxel(const EntityItemID& entityItemID, const VoxelDetail& voxel, const CollisionInfo& penetration); - void entityCollisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const CollisionInfo& penetration); + void entityCollisionWithVoxel(const EntityItemID& entityItemID, const VoxelDetail& voxel, const Collision& collision); + void entityCollisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const Collision& collision); private: void applyHardCollision(EntityItem* entity, const CollisionInfo& collisionInfo); static bool updateOperation(OctreeElement* element, void* extraData); - void emitGlobalEntityCollisionWithVoxel(EntityItem* Entity, VoxelDetail* voxelDetails, const CollisionInfo& penetration); - void emitGlobalEntityCollisionWithEntity(EntityItem* entityA, EntityItem* entityB, const CollisionInfo& penetration); + void emitGlobalEntityCollisionWithVoxel(EntityItem* Entity, VoxelDetail* voxelDetails, const Collision& penetration); + void emitGlobalEntityCollisionWithEntity(EntityItem* entityA, EntityItem* entityB, const Collision& penetration); EntityEditPacketSender* _packetSender; VoxelTree* _voxels; diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index 1233af678d..20aaf09f9a 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -102,8 +102,8 @@ public slots: Q_INVOKABLE void dumpTree() const; signals: - void entityCollisionWithVoxel(const EntityItemID& entityID, const VoxelDetail& voxel, const CollisionInfo& collision); - void entityCollisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const CollisionInfo& collision); + void entityCollisionWithVoxel(const EntityItemID& entityID, const VoxelDetail& voxel, const Collision& collision); + void entityCollisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const Collision& collision); void mousePressOnEntity(const EntityItemID& entityItemID, const MouseEvent& event); void mouseMoveOnEntity(const EntityItemID& entityItemID, const MouseEvent& event); diff --git a/libraries/shared/src/RegisteredMetaTypes.cpp b/libraries/shared/src/RegisteredMetaTypes.cpp index 02b9d5c927..cc8db8783f 100644 --- a/libraries/shared/src/RegisteredMetaTypes.cpp +++ b/libraries/shared/src/RegisteredMetaTypes.cpp @@ -26,6 +26,7 @@ static int xColorMetaTypeId = qRegisterMetaType(); static int pickRayMetaTypeId = qRegisterMetaType(); static int collisionMetaTypeId = qRegisterMetaType(); + void registerMetaTypes(QScriptEngine* engine) { qScriptRegisterMetaType(engine, vec4toScriptValue, vec4FromScriptValue); qScriptRegisterMetaType(engine, vec3toScriptValue, vec3FromScriptValue); diff --git a/libraries/shared/src/RegisteredMetaTypes.h b/libraries/shared/src/RegisteredMetaTypes.h index 0fd3138b06..b9278c9f2d 100644 --- a/libraries/shared/src/RegisteredMetaTypes.h +++ b/libraries/shared/src/RegisteredMetaTypes.h @@ -68,6 +68,8 @@ void pickRayFromScriptValue(const QScriptValue& object, PickRay& pickRay); class Collision { public: Collision() : contactPoint(0.0f), penetration(0.0f) { } + Collision(const glm::vec3& contactPoint, const glm::vec3& penetration) : + contactPoint(contactPoint), penetration(penetration) { } glm::vec3 contactPoint; glm::vec3 penetration; }; From 6fdfde31d92803f84e11d93cfc7f1b3d79ede230 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 8 Dec 2014 11:20:27 -0800 Subject: [PATCH 287/502] whoops, forgot to increment the iterator --- libraries/entities/src/SimpleEntitySimulation.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/entities/src/SimpleEntitySimulation.cpp b/libraries/entities/src/SimpleEntitySimulation.cpp index b962f6980e..17dbd46727 100644 --- a/libraries/entities/src/SimpleEntitySimulation.cpp +++ b/libraries/entities/src/SimpleEntitySimulation.cpp @@ -25,6 +25,7 @@ void SimpleEntitySimulation::updateEntitiesInternal(const quint64& now) { } else { entity->simulate(now); _entitiesToBeSorted.insert(entity); + ++itemItr; } } } From 3ce1d4a38d5aac469b22485dc1f4bd67b50a5189 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 8 Dec 2014 11:21:01 -0800 Subject: [PATCH 288/502] set dirty bit when script changes simulation stuff also fixes for linear and angular damping --- libraries/entities/src/EntityItem.cpp | 58 +++++++++++++++------------ libraries/entities/src/EntityItem.h | 10 +++-- 2 files changed, 40 insertions(+), 28 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index d0d07d1227..b271439662 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -29,7 +29,7 @@ const float EntityItem::DEFAULT_LOCAL_RENDER_ALPHA = 1.0f; const float EntityItem::DEFAULT_MASS = 1.0f; const float EntityItem::DEFAULT_LIFETIME = EntityItem::IMMORTAL; const QString EntityItem::DEFAULT_USER_DATA = QString(""); -const float EntityItem::DEFAULT_DAMPING = 0.5f; +const float EntityItem::DEFAULT_DAMPING = 2.0f; const glm::vec3 EntityItem::NO_VELOCITY = glm::vec3(0, 0, 0); const float EntityItem::EPSILON_VELOCITY_LENGTH = (1.0f / 1000.0f) / (float)TREE_SCALE; // really small: 1mm/second const glm::vec3 EntityItem::DEFAULT_VELOCITY = EntityItem::NO_VELOCITY; @@ -42,7 +42,7 @@ const glm::vec3 EntityItem::DEFAULT_DIMENSIONS = glm::vec3(0.1f, 0.1f, 0.1f); const glm::vec3 EntityItem::DEFAULT_REGISTRATION_POINT = glm::vec3(0.5f, 0.5f, 0.5f); // center const glm::vec3 EntityItem::NO_ANGULAR_VELOCITY = glm::vec3(0.0f, 0.0f, 0.0f); const glm::vec3 EntityItem::DEFAULT_ANGULAR_VELOCITY = NO_ANGULAR_VELOCITY; -const float EntityItem::DEFAULT_ANGULAR_DAMPING = 0.5f; +const float EntityItem::DEFAULT_ANGULAR_DAMPING = 2.0f; const bool EntityItem::DEFAULT_VISIBLE = true; const bool EntityItem::DEFAULT_IGNORE_FOR_COLLISIONS = false; const bool EntityItem::DEFAULT_COLLISIONS_WILL_MOVE = false; @@ -155,7 +155,7 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet ByteCountCoded typeCoder = getType(); QByteArray encodedType = typeCoder; - quint64 updateDelta = getLastMoved() <= getLastEdited() ? 0 : getLastMoved() - getLastEdited(); + quint64 updateDelta = getLastSimulated() <= getLastEdited() ? 0 : getLastSimulated() - getLastEdited(); ByteCountCoded updateDeltaCoder = updateDelta; QByteArray encodedUpdateDelta = updateDeltaCoder; EntityPropertyFlags propertyFlags(PROP_LAST_ITEM); @@ -632,13 +632,13 @@ void EntityItem::simulate(const quint64& now) { setRotation(rotation); // handle damping for angular velocity - if (getAngularDamping() > 0.0f) { - glm::vec3 dampingResistance = getAngularVelocity() * getAngularDamping(); - glm::vec3 newAngularVelocity = getAngularVelocity() - (dampingResistance * timeElapsed); + float dampingTimescale = getAngularDamping(); + if (dampingTimescale > 0.0f) { + float dampingFactor = glm::clamp(timeElapsed / dampingTimescale, 0.0f, 1.0f); + glm::vec3 newAngularVelocity = (1.0f - dampingFactor) * getAngularVelocity(); setAngularVelocity(newAngularVelocity); if (wantDebug) { - qDebug() << " getDamping():" << getDamping(); - qDebug() << " dampingResistance:" << dampingResistance; + qDebug() << " dampingTimescale :" << dampingTimescale; qDebug() << " newAngularVelocity:" << newAngularVelocity; } } @@ -689,13 +689,15 @@ void EntityItem::simulate(const quint64& now) { } // handle damping for velocity - glm::vec3 dampingResistance = velocity * getDamping(); - if (wantDebug) { - qDebug() << " getDamping():" << getDamping(); - qDebug() << " dampingResistance:" << dampingResistance; - qDebug() << " dampingResistance * timeElapsed:" << dampingResistance * timeElapsed; + float dampingTimescale = getDamping(); + if (dampingTimescale > 0.0f) { + float dampingFactor = glm::clamp(timeElapsed / dampingTimescale, 0.0f, 1.0f); + velocity *= (1.0f - dampingFactor); + if (wantDebug) { + qDebug() << " dampingTimescale:" << dampingTimescale; + qDebug() << " newVelocity:" << velocity; + } } - velocity -= dampingResistance * timeElapsed; if (wantDebug) { qDebug() << " velocity AFTER dampingResistance:" << velocity; @@ -778,23 +780,23 @@ bool EntityItem::setProperties(const EntityItemProperties& properties, bool forc } } - SET_ENTITY_PROPERTY_FROM_PROPERTIES(position, setPositionInMeters); // this will call recalculate collision shape if needed - SET_ENTITY_PROPERTY_FROM_PROPERTIES(dimensions, setDimensionsInMeters); // NOTE: radius is obsolete - SET_ENTITY_PROPERTY_FROM_PROPERTIES(rotation, setRotation); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(mass, setMass); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(velocity, setVelocityInMeters); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(gravity, setGravityInMeters); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(position, updatePositionInMeters); // this will call recalculate collision shape if needed + SET_ENTITY_PROPERTY_FROM_PROPERTIES(dimensions, updateDimensionsInMeters); // NOTE: radius is obsolete + SET_ENTITY_PROPERTY_FROM_PROPERTIES(rotation, updateRotation); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(mass, updateMass); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(velocity, updateVelocityInMeters); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(gravity, updateGravityInMeters); SET_ENTITY_PROPERTY_FROM_PROPERTIES(damping, setDamping); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(lifetime, setLifetime); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(script, setScript); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(lifetime, updateLifetime); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(script, updateScript); SET_ENTITY_PROPERTY_FROM_PROPERTIES(registrationPoint, setRegistrationPoint); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(angularVelocity, setAngularVelocity); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(angularVelocity, updateAngularVelocity); SET_ENTITY_PROPERTY_FROM_PROPERTIES(angularDamping, setAngularDamping); SET_ENTITY_PROPERTY_FROM_PROPERTIES(glowLevel, setGlowLevel); SET_ENTITY_PROPERTY_FROM_PROPERTIES(localRenderAlpha, setLocalRenderAlpha); SET_ENTITY_PROPERTY_FROM_PROPERTIES(visible, setVisible); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(ignoreForCollisions, setIgnoreForCollisions); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(collisionsWillMove, setCollisionsWillMove); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(ignoreForCollisions, updateIgnoreForCollisions); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(collisionsWillMove, updateCollisionsWillMove); SET_ENTITY_PROPERTY_FROM_PROPERTIES(locked, setLocked); SET_ENTITY_PROPERTY_FROM_PROPERTIES(userData, setUserData); @@ -1051,4 +1053,10 @@ void EntityItem::updateLifetime(float value) { } } +void EntityItem::updateScript(const QString& value) { + if (_script != value) { + _script = value; + _dirtyFlags |= EntityItem::DIRTY_SCRIPT; + } +} diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index f0d3330087..bde1ebc684 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -48,7 +48,10 @@ public: DIRTY_COLLISION_GROUP = 0x0008, DIRTY_MOTION_TYPE = 0x0010, DIRTY_SHAPE = 0x0020, - DIRTY_LIFETIME = 0x0040 + DIRTY_LIFETIME = 0x0040, + // add new simulation-relevant flags above + // all other flags below + DIRTY_SCRIPT = 0x8000 }; DONT_ALLOW_INSTANTIATION // This class can not be instantiated directly @@ -292,6 +295,7 @@ public: void updateIgnoreForCollisions(bool value); void updateCollisionsWillMove(bool value); void updateLifetime(float value); + void updateScript(const QString& value); uint32_t getDirtyFlags() const { return _dirtyFlags; } void clearDirtyFlags(uint32_t mask = 0xffff) { _dirtyFlags &= ~mask; } @@ -323,12 +327,12 @@ protected: float _mass; glm::vec3 _velocity; glm::vec3 _gravity; - float _damping; + float _damping; // timescale float _lifetime; QString _script; glm::vec3 _registrationPoint; glm::vec3 _angularVelocity; - float _angularDamping; + float _angularDamping; // timescale bool _visible; bool _ignoreForCollisions; bool _collisionsWillMove; From b4f18f15d7a4000fc42a10fc2f4ac67e1df58901 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 8 Dec 2014 11:49:42 -0800 Subject: [PATCH 289/502] Ignore Visage resources in .gitignore except for tracker.cfg --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index 6e6b69cb66..8365108df9 100644 --- a/.gitignore +++ b/.gitignore @@ -32,5 +32,9 @@ DerivedData interface/external/*/* !interface/external/*/readme.txt +# ignore interface optional resources +interface/resources/visage/* +!interface/resources/visage/tracker.cfg + # Ignore interfaceCache for Linux users interface/interfaceCache/ From 716fca6ae7250c2cc05445300e909c3c8e0f0fd1 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 8 Dec 2014 11:49:55 -0800 Subject: [PATCH 290/502] tabs to spaces --- examples/Recorder.js | 260 ++++++++++++++-------------- examples/textInputOverlayExample.js | 238 ++++++++++++------------- 2 files changed, 248 insertions(+), 250 deletions(-) diff --git a/examples/Recorder.js b/examples/Recorder.js index ff8c449012..ddfa3e0315 100644 --- a/examples/Recorder.js +++ b/examples/Recorder.js @@ -15,11 +15,11 @@ Script.include("libraries/toolBars.js"); var recordingFile = "recording.rec"; function setPlayerOptions() { - MyAvatar.setPlayFromCurrentLocation(true); - MyAvatar.setPlayerUseDisplayName(false); - MyAvatar.setPlayerUseAttachments(false); - MyAvatar.setPlayerUseHeadModel(false); - MyAvatar.setPlayerUseSkeletonModel(false); + MyAvatar.setPlayFromCurrentLocation(true); + MyAvatar.setPlayerUseDisplayName(false); + MyAvatar.setPlayerUseAttachments(false); + MyAvatar.setPlayerUseHeadModel(false); + MyAvatar.setPlayerUseSkeletonModel(false); } var windowDimensions = Controller.getViewportDimensions(); @@ -47,118 +47,118 @@ setupTimer(); var watchStop = false; function setupToolBar() { - if (toolBar != null) { - print("Multiple calls to Recorder.js:setupToolBar()"); - return; - } + if (toolBar != null) { + print("Multiple calls to Recorder.js:setupToolBar()"); + return; + } Tool.IMAGE_HEIGHT /= 2; Tool.IMAGE_WIDTH /= 2; - toolBar = new ToolBar(0, 0, ToolBar.HORIZONTAL); + toolBar = new ToolBar(0, 0, ToolBar.HORIZONTAL); toolBar.setBack(COLOR_TOOL_BAR, ALPHA_OFF); recordIcon = toolBar.addTool({ - imageURL: TOOL_ICON_URL + "recording-record.svg", - subImage: { x: 0, y: 0, width: Tool.IMAGE_WIDTH, height: Tool.IMAGE_HEIGHT }, - x: 0, y: 0, - width: Tool.IMAGE_WIDTH, - height: Tool.IMAGE_HEIGHT, - alpha: MyAvatar.isPlaying() ? ALPHA_OFF : ALPHA_ON, - visible: true - }, true, !MyAvatar.isRecording()); + imageURL: TOOL_ICON_URL + "recording-record.svg", + subImage: { x: 0, y: 0, width: Tool.IMAGE_WIDTH, height: Tool.IMAGE_HEIGHT }, + x: 0, y: 0, + width: Tool.IMAGE_WIDTH, + height: Tool.IMAGE_HEIGHT, + alpha: MyAvatar.isPlaying() ? ALPHA_OFF : ALPHA_ON, + visible: true + }, true, !MyAvatar.isRecording()); var playLoopWidthFactor = 1.65; playIcon = toolBar.addTool({ - imageURL: TOOL_ICON_URL + "play-pause.svg", - width: playLoopWidthFactor * Tool.IMAGE_WIDTH, - height: Tool.IMAGE_HEIGHT, - alpha: (MyAvatar.isRecording() || MyAvatar.playerLength() === 0) ? ALPHA_OFF : ALPHA_ON, - visible: true - }, false); + imageURL: TOOL_ICON_URL + "play-pause.svg", + width: playLoopWidthFactor * Tool.IMAGE_WIDTH, + height: Tool.IMAGE_HEIGHT, + alpha: (MyAvatar.isRecording() || MyAvatar.playerLength() === 0) ? ALPHA_OFF : ALPHA_ON, + visible: true + }, false); playLoopIcon = toolBar.addTool({ - imageURL: TOOL_ICON_URL + "play-and-loop.svg", - subImage: { x: 0, y: 0, width: playLoopWidthFactor * Tool.IMAGE_WIDTH, height: Tool.IMAGE_HEIGHT }, - width: playLoopWidthFactor * Tool.IMAGE_WIDTH, - height: Tool.IMAGE_HEIGHT, - alpha: (MyAvatar.isRecording() || MyAvatar.playerLength() === 0) ? ALPHA_OFF : ALPHA_ON, - visible: true - }, false); + imageURL: TOOL_ICON_URL + "play-and-loop.svg", + subImage: { x: 0, y: 0, width: playLoopWidthFactor * Tool.IMAGE_WIDTH, height: Tool.IMAGE_HEIGHT }, + width: playLoopWidthFactor * Tool.IMAGE_WIDTH, + height: Tool.IMAGE_HEIGHT, + alpha: (MyAvatar.isRecording() || MyAvatar.playerLength() === 0) ? ALPHA_OFF : ALPHA_ON, + visible: true + }, false); timerOffset = toolBar.width; spacing = toolBar.addSpacing(0); saveIcon = toolBar.addTool({ - imageURL: TOOL_ICON_URL + "recording-save.svg", - width: Tool.IMAGE_WIDTH, - height: Tool.IMAGE_HEIGHT, - alpha: (MyAvatar.isRecording() || MyAvatar.isPlaying() || MyAvatar.playerLength() === 0) ? ALPHA_OFF : ALPHA_ON, - visible: true - }, false); + imageURL: TOOL_ICON_URL + "recording-save.svg", + width: Tool.IMAGE_WIDTH, + height: Tool.IMAGE_HEIGHT, + alpha: (MyAvatar.isRecording() || MyAvatar.isPlaying() || MyAvatar.playerLength() === 0) ? ALPHA_OFF : ALPHA_ON, + visible: true + }, false); loadIcon = toolBar.addTool({ - imageURL: TOOL_ICON_URL + "recording-upload.svg", - width: Tool.IMAGE_WIDTH, - height: Tool.IMAGE_HEIGHT, - alpha: (MyAvatar.isRecording() || MyAvatar.isPlaying()) ? ALPHA_OFF : ALPHA_ON, - visible: true - }, false); + imageURL: TOOL_ICON_URL + "recording-upload.svg", + width: Tool.IMAGE_WIDTH, + height: Tool.IMAGE_HEIGHT, + alpha: (MyAvatar.isRecording() || MyAvatar.isPlaying()) ? ALPHA_OFF : ALPHA_ON, + visible: true + }, false); } function setupTimer() { - timer = Overlays.addOverlay("text", { - font: { size: 15 }, - text: (0.00).toFixed(3), - backgroundColor: COLOR_OFF, - x: 0, y: 0, - width: 0, - height: 0, - alpha: 1.0, + timer = Overlays.addOverlay("text", { + font: { size: 15 }, + text: (0.00).toFixed(3), + backgroundColor: COLOR_OFF, + x: 0, y: 0, + width: 0, + height: 0, + alpha: 1.0, backgroundAlpha: 1.0, - visible: true - }); + visible: true + }); slider = { x: 0, y: 0, - w: 200, h: 20, - pos: 0.0, // 0.0 <= pos <= 1.0 + w: 200, h: 20, + pos: 0.0, // 0.0 <= pos <= 1.0 }; slider.background = Overlays.addOverlay("text", { - text: "", - backgroundColor: { red: 128, green: 128, blue: 128 }, - x: slider.x, y: slider.y, - width: slider.w, - height: slider.h, - alpha: 1.0, - backgroundAlpha: 1.0, - visible: true - }); + text: "", + backgroundColor: { red: 128, green: 128, blue: 128 }, + x: slider.x, y: slider.y, + width: slider.w, + height: slider.h, + alpha: 1.0, + backgroundAlpha: 1.0, + visible: true + }); slider.foreground = Overlays.addOverlay("text", { - text: "", - backgroundColor: { red: 200, green: 200, blue: 200 }, - x: slider.x, y: slider.y, - width: slider.pos * slider.w, - height: slider.h, - alpha: 1.0, - backgroundAlpha: 1.0, - visible: true - }); + text: "", + backgroundColor: { red: 200, green: 200, blue: 200 }, + x: slider.x, y: slider.y, + width: slider.pos * slider.w, + height: slider.h, + alpha: 1.0, + backgroundAlpha: 1.0, + visible: true + }); } function updateTimer() { - var text = ""; - if (MyAvatar.isRecording()) { - text = formatTime(MyAvatar.recorderElapsed()); + var text = ""; + if (MyAvatar.isRecording()) { + text = formatTime(MyAvatar.recorderElapsed()); - } else { - text = formatTime(MyAvatar.playerElapsed()) + " / " + - formatTime(MyAvatar.playerLength()); - } + } else { + text = formatTime(MyAvatar.playerElapsed()) + " / " + + formatTime(MyAvatar.playerLength()); + } - Overlays.editOverlay(timer, { - text: text - }) + Overlays.editOverlay(timer, { + text: text + }) toolBar.changeSpacing(text.length * 8 + ((MyAvatar.isRecording()) ? 15 : 0), spacing); if (MyAvatar.isRecording()) { @@ -168,57 +168,56 @@ function updateTimer() { } Overlays.editOverlay(slider.foreground, { - width: slider.pos * slider.w - }); + width: slider.pos * slider.w + }); } function formatTime(time) { - var MIN_PER_HOUR = 60; - var SEC_PER_MIN = 60; - var MSEC_PER_SEC = 1000; + var MIN_PER_HOUR = 60; + var SEC_PER_MIN = 60; + var MSEC_PER_SEC = 1000; - var hours = Math.floor(time / (MSEC_PER_SEC * SEC_PER_MIN * MIN_PER_HOUR)); - time -= hours * (MSEC_PER_SEC * SEC_PER_MIN * MIN_PER_HOUR); + var hours = Math.floor(time / (MSEC_PER_SEC * SEC_PER_MIN * MIN_PER_HOUR)); + time -= hours * (MSEC_PER_SEC * SEC_PER_MIN * MIN_PER_HOUR); - var minutes = Math.floor(time / (MSEC_PER_SEC * SEC_PER_MIN)); - time -= minutes * (MSEC_PER_SEC * SEC_PER_MIN); + var minutes = Math.floor(time / (MSEC_PER_SEC * SEC_PER_MIN)); + time -= minutes * (MSEC_PER_SEC * SEC_PER_MIN); - var seconds = Math.floor(time / MSEC_PER_SEC); - seconds = time / MSEC_PER_SEC; + var seconds = Math.floor(time / MSEC_PER_SEC); + seconds = time / MSEC_PER_SEC; - var text = ""; - text += (hours > 0) ? hours + ":" : - ""; - text += (minutes > 0) ? ((minutes < 10 && text != "") ? "0" : "") + minutes + ":" : - ""; - text += ((seconds < 10 && text != "") ? "0" : "") + seconds.toFixed(3); - return text; + var text = ""; + text += (hours > 0) ? hours + ":" : + ""; + text += (minutes > 0) ? ((minutes < 10 && text != "") ? "0" : "") + minutes + ":" : + ""; + text += ((seconds < 10 && text != "") ? "0" : "") + seconds.toFixed(3); + return text; } function moveUI() { - var relative = { x: 70, y: 40 }; - toolBar.move(relative.x, - windowDimensions.y - relative.y); - Overlays.editOverlay(timer, { - x: relative.x + timerOffset - ToolBar.SPACING, - y: windowDimensions.y - relative.y - ToolBar.SPACING - }); + var relative = { x: 70, y: 40 }; + toolBar.move(relative.x, windowDimensions.y - relative.y); + Overlays.editOverlay(timer, { + x: relative.x + timerOffset - ToolBar.SPACING, + y: windowDimensions.y - relative.y - ToolBar.SPACING + }); slider.x = relative.x - ToolBar.SPACING; slider.y = windowDimensions.y - relative.y - slider.h - ToolBar.SPACING; Overlays.editOverlay(slider.background, { - x: slider.x, - y: slider.y, - }); + x: slider.x, + y: slider.y, + }); Overlays.editOverlay(slider.foreground, { - x: slider.x, - y: slider.y, - }); + x: slider.x, + y: slider.y, + }); } function mousePressEvent(event) { - clickedOverlay = Overlays.getOverlayAtPoint({ x: event.x, y: event.y }); + clickedOverlay = Overlays.getOverlayAtPoint({ x: event.x, y: event.y }); if (recordIcon === toolBar.clicked(clickedOverlay, false) && !MyAvatar.isPlaying()) { if (!MyAvatar.isRecording()) { @@ -270,7 +269,7 @@ function mousePressEvent(event) { if (!MyAvatar.isRecording() && !MyAvatar.isPlaying() && MyAvatar.playerLength() != 0) { recordingFile = Window.save("Save recording to file", ".", "Recordings (*.hfr)"); if (!(recordingFile === "null" || recordingFile === null || recordingFile === "")) { - MyAvatar.saveRecording(recordingFile); + MyAvatar.saveRecording(recordingFile); } } } else if (loadIcon === toolBar.clicked(clickedOverlay)) { @@ -286,8 +285,8 @@ function mousePressEvent(event) { } } } else if (MyAvatar.playerLength() > 0 && - slider.x < event.x && event.x < slider.x + slider.w && - slider.y < event.y && event.y < slider.y + slider.h) { + slider.x < event.x && event.x < slider.x + slider.w && + slider.y < event.y && event.y < slider.y + slider.h) { isSliding = true; slider.pos = (event.x - slider.x) / slider.w; MyAvatar.setPlayerTime(slider.pos * MyAvatar.playerLength()); @@ -311,14 +310,13 @@ function mouseReleaseEvent(event) { } function update() { - var newDimensions = Controller.getViewportDimensions(); - if (windowDimensions.x != newDimensions.x || - windowDimensions.y != newDimensions.y) { - windowDimensions = newDimensions; - moveUI(); - } + var newDimensions = Controller.getViewportDimensions(); + if (windowDimensions.x != newDimensions.x || windowDimensions.y != newDimensions.y) { + windowDimensions = newDimensions; + moveUI(); + } - updateTimer(); + updateTimer(); if (watchStop && !MyAvatar.isPlaying()) { watchStop = false; @@ -329,12 +327,12 @@ function update() { } function scriptEnding() { - if (MyAvatar.isRecording()) { - MyAvatar.stopRecording(); - } - if (MyAvatar.isPlaying()) { - MyAvatar.stopPlaying(); - } + if (MyAvatar.isRecording()) { + MyAvatar.stopRecording(); + } + if (MyAvatar.isPlaying()) { + MyAvatar.stopPlaying(); + } toolBar.cleanup(); Overlays.deleteOverlay(timer); Overlays.deleteOverlay(slider.background); diff --git a/examples/textInputOverlayExample.js b/examples/textInputOverlayExample.js index 8a5fad81cd..258e07fcc8 100644 --- a/examples/textInputOverlayExample.js +++ b/examples/textInputOverlayExample.js @@ -32,168 +32,168 @@ var clickedButton = false; var cursor = "|"; // add more characters to the string if required var keyString = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\ - ~!@#$%^&*()_+`1234567890-={}|[]\\:\";'<>?,./"; //permitted characters + ~!@#$%^&*()_+`1234567890-={}|[]\\:\";'<>?,./"; //permitted characters // This will create a text overlay that displays what you type var inputWindow = Overlays.addOverlay("text", { - x: locationX, - y: locationY, - width: width, - height: height, - color: textColor, - backgroundColor: backColor, - alpha: backgroundAlpha, - backgroundAlpha: backgroundAlpha, - topMargin: topMargin, - leftMargin: leftMargin, - font: {size: fontSize}, - text: writing, - visible: true - }); + x: locationX, + y: locationY, + width: width, + height: height, + color: textColor, + backgroundColor: backColor, + alpha: backgroundAlpha, + backgroundAlpha: backgroundAlpha, + topMargin: topMargin, + leftMargin: leftMargin, + font: {size: fontSize}, + text: writing, + visible: true +}); // This will create an image overlay of a button. var button1 = Overlays.addOverlay("image", { // green button - x: buttonLocationX, - y: locationY + 10, - width: 40, - height: 35, - subImage: { x: 0, y: 0, width: 39, height: 35 }, - imageURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/thumb.png", - color: readyColor, - visible: true - }); + x: buttonLocationX, + y: locationY + 10, + width: 40, + height: 35, + subImage: { x: 0, y: 0, width: 39, height: 35 }, + imageURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/thumb.png", + color: readyColor, + visible: true +}); // This will create an image overlay of another button. var button2 = Overlays.addOverlay("image", { // red button - x: buttonLocationX, - y: locationY + 60, - width: 40, - height: 35, - subImage: { x: 0, y: 0, width: 39, height: 35 }, - imageURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/thumb.png", - color: { red: 250, green: 2, blue: 2}, - visible: true, - }); + x: buttonLocationX, + y: locationY + 60, + width: 40, + height: 35, + subImage: { x: 0, y: 0, width: 39, height: 35 }, + imageURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/thumb.png", + color: { red: 250, green: 2, blue: 2}, + visible: true, +}); // When our script shuts down, we should clean up all of our overlays function scriptEnding() { - Overlays.deleteOverlay(inputWindow); - Overlays.deleteOverlay(button1); - Overlays.deleteOverlay(button2); - //Return control of keys to default on script ending - for(var i=0; i Date: Mon, 8 Dec 2014 12:47:37 -0800 Subject: [PATCH 291/502] Swap out the lobby model for the one with the correct light value --- examples/lobby.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/lobby.js b/examples/lobby.js index c5a9645e90..dd011d08a4 100644 --- a/examples/lobby.js +++ b/examples/lobby.js @@ -92,7 +92,7 @@ function drawLobby() { }; var orbShellProps = { - url: HIFI_PUBLIC_BUCKET + "models/sets/Lobby/Lobby_v8/forStephen1/LobbyShell1.fbx", + url: HIFI_PUBLIC_BUCKET + "models/sets/Lobby/Lobby_v8/forStephen1/LobbyShell1.4_LightTag.fbx", position: orbPosition, rotation: towardsMe, dimensions: orbDimensions, From 0592b74a064d13539e99a86aa277aef8c087aa3e Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 8 Dec 2014 14:15:03 -0800 Subject: [PATCH 292/502] make collision callbacks work --- examples/collidingEntities.js | 16 ++--------- .../entityScripts/changeColorOnCollision.js | 27 ++++++++++++++++++ interface/src/entities/EntityTreeRenderer.cpp | 28 ++++++++++++++++--- .../entities/src/EntityCollisionSystem.cpp | 2 +- libraries/octree/src/Octree.cpp | 2 +- 5 files changed, 56 insertions(+), 19 deletions(-) create mode 100644 examples/entityScripts/changeColorOnCollision.js diff --git a/examples/collidingEntities.js b/examples/collidingEntities.js index 4f03a9ee87..1feeaa8de5 100644 --- a/examples/collidingEntities.js +++ b/examples/collidingEntities.js @@ -22,11 +22,6 @@ var velocity = { y: 0, z: 1 }; -var gravity = { - x: 0, - y: 0, - z: 0 }; - var damping = 0.1; var color = { @@ -45,25 +40,20 @@ function draw(deltaTime) { y: 1, z: 2 }; var largeRadius = 0.5; - var verySlow = { - x: 0.01, - y: 0, - z: 0.01 }; var properties = { type: "Sphere", + script: "file:///Users/zappoman/Development/HiFi/hifi/examples/entityScripts/changeColorOnCollision.js", collisionsWillMove: true, position: startPosition, dimensions: {x: largeRadius, y: largeRadius, z: largeRadius}, registrationPoint: { x: 0.5, y: 0.5, z: 0.5 }, color: colorGreen, - //velocity: verySlow, - //gravity: gravity, damping: damping, lifetime: 20 }; - Entities.addEntity(properties); + //Entities.addEntity(properties); numberEntitiesAdded++; } @@ -95,13 +85,13 @@ function draw(deltaTime) { if (numberEntitiesAdded <= MAX_ENTITIES) { var properties = { type: "Sphere", + script: "file:///Users/zappoman/Development/HiFi/hifi/examples/entityScripts/changeColorOnCollision.js", collisionsWillMove: true, position: center, dimensions: {x: entitySize, y: entitySize, z: entitySize}, registrationPoint: { x: 0.5, y: 0.5, z: 0.5 }, color: color, velocity: velocity, - //gravity: gravity, damping: damping, lifetime: 20 }; diff --git a/examples/entityScripts/changeColorOnCollision.js b/examples/entityScripts/changeColorOnCollision.js new file mode 100644 index 0000000000..e19e63c35b --- /dev/null +++ b/examples/entityScripts/changeColorOnCollision.js @@ -0,0 +1,27 @@ +// +// changeColorOnCollision.js +// examples/entityScripts +// +// Created by Brad Hefta-Gaub on 12/8/14. +// 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 +// + +print("changeColorOnCollision.js"); + +(function(){ + function getRandomInt(min, max) { + return Math.floor(Math.random() * (max - min + 1)) + min; + } + + this.preload = function(myID) { + print("changeColorOnCollision.js--- preload!!!"); + }; + + this.collisionWithEntity = function(myID, otherID, collisionInfo) { + print("collisionWithEntity"); + Entities.editEntity(myID, { color: { red: getRandomInt(128,255), green: getRandomInt(128,255), blue: getRandomInt(128,255)} }); + }; +}) \ No newline at end of file diff --git a/interface/src/entities/EntityTreeRenderer.cpp b/interface/src/entities/EntityTreeRenderer.cpp index e9c4e456f2..b13cede725 100644 --- a/interface/src/entities/EntityTreeRenderer.cpp +++ b/interface/src/entities/EntityTreeRenderer.cpp @@ -886,13 +886,33 @@ void EntityTreeRenderer::changingEntityID(const EntityItemID& oldEntityID, const void EntityTreeRenderer::entityCollisionWithVoxel(const EntityItemID& entityID, const VoxelDetail& voxel, const Collision& collision) { - qDebug() << "EntityTreeRenderer::entityCollisionWithVoxel()... "; + QScriptValue entityScript = getPreviouslyLoadedEntityScript(entityID); + if (entityScript.property("collisionWithVoxel").isValid()) { + QScriptValueList args; + args << entityID.toScriptValue(_entitiesScriptEngine); + args << collisionToScriptValue(_entitiesScriptEngine, collision); + entityScript.property("collisionWithVoxel").call(entityScript, args); + } } void EntityTreeRenderer::entityCollisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const Collision& collision) { - qDebug() << "EntityTreeRenderer::entityCollisionWithEntity()... "; - qDebug() << " idA:" << idA; - qDebug() << " idB:" << idB; + QScriptValue entityScriptA = loadEntityScript(idA); + if (entityScriptA.property("collisionWithEntity").isValid()) { + QScriptValueList args; + args << idA.toScriptValue(_entitiesScriptEngine); + args << idB.toScriptValue(_entitiesScriptEngine); + args << collisionToScriptValue(_entitiesScriptEngine, collision); + entityScriptA.property("collisionWithEntity").call(entityScriptA, args); + } + + QScriptValue entityScriptB = loadEntityScript(idB); + if (entityScriptB.property("collisionWithEntity").isValid()) { + QScriptValueList args; + args << idB.toScriptValue(_entitiesScriptEngine); + args << idA.toScriptValue(_entitiesScriptEngine); + args << collisionToScriptValue(_entitiesScriptEngine, collision); + entityScriptB.property("collisionWithEntity").call(entityScriptA, args); + } } diff --git a/libraries/entities/src/EntityCollisionSystem.cpp b/libraries/entities/src/EntityCollisionSystem.cpp index 110aef443f..9c82cb4744 100644 --- a/libraries/entities/src/EntityCollisionSystem.cpp +++ b/libraries/entities/src/EntityCollisionSystem.cpp @@ -54,7 +54,7 @@ void EntityCollisionSystem::updateCollisions() { PerformanceTimer perfTimer("collisions"); assert(_entityTree); // update all Entities - if (_entityTree->tryLockForRead()) { + if (_entityTree->tryLockForWrite()) { foreach (EntityItem* entity, _movingEntities) { checkEntity(entity); } diff --git a/libraries/octree/src/Octree.cpp b/libraries/octree/src/Octree.cpp index 1a432c8e59..d6aad45b0d 100644 --- a/libraries/octree/src/Octree.cpp +++ b/libraries/octree/src/Octree.cpp @@ -46,7 +46,7 @@ Octree::Octree(bool shouldReaverage) : _isDirty(true), _shouldReaverage(shouldReaverage), _stopImport(false), - _lock(), + _lock(QReadWriteLock::Recursive), _isViewing(false), _isServer(false) { From cdeaaf2ca98d41f8c90d0462c7d80967e2f897f4 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 8 Dec 2014 15:06:34 -0800 Subject: [PATCH 293/502] fix deadlock in enter/leave events --- interface/src/entities/EntityTreeRenderer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/entities/EntityTreeRenderer.cpp b/interface/src/entities/EntityTreeRenderer.cpp index b13cede725..dd9a0b6a4f 100644 --- a/interface/src/entities/EntityTreeRenderer.cpp +++ b/interface/src/entities/EntityTreeRenderer.cpp @@ -233,7 +233,7 @@ void EntityTreeRenderer::update() { void EntityTreeRenderer::checkEnterLeaveEntities() { if (_tree) { - _tree->lockForRead(); + _tree->lockForWrite(); // so that our scripts can do edits if they want glm::vec3 avatarPosition = Application::getInstance()->getAvatar()->getPosition() / (float) TREE_SCALE; if (avatarPosition != _lastAvatarPosition) { From 7449821a9bb075f40883e2e3977bd7cc547add59 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 8 Dec 2014 15:06:50 -0800 Subject: [PATCH 294/502] add ID to the properties dialog box --- examples/libraries/entityPropertyDialogBox.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/examples/libraries/entityPropertyDialogBox.js b/examples/libraries/entityPropertyDialogBox.js index a162697560..a686ebb0f2 100644 --- a/examples/libraries/entityPropertyDialogBox.js +++ b/examples/libraries/entityPropertyDialogBox.js @@ -41,6 +41,8 @@ EntityPropertyDialogBox = (function () { array.push({ label: "Entity Type:" + properties.type, type: "header" }); index++; + array.push({ label: "ID:", value: properties.id }); + index++; array.push({ label: "Locked:", type: "checkbox", value: properties.locked }); index++; @@ -265,6 +267,7 @@ EntityPropertyDialogBox = (function () { var properties = propertiesForEditedEntity; var index = 0; index++; // skip type header + index++; // skip id item properties.locked = array[index++].value; if (properties.type == "Model") { properties.modelURL = array[index++].value; From 0d636314ba9ad98d7ea84e1185ab360b46055fd7 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 8 Dec 2014 16:20:39 -0800 Subject: [PATCH 295/502] fixed CR feedback --- examples/collidingEntities.js | 4 +--- examples/entityScripts/changeColorOnCollision.js | 7 ------- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/examples/collidingEntities.js b/examples/collidingEntities.js index 1feeaa8de5..7edbc9fecc 100644 --- a/examples/collidingEntities.js +++ b/examples/collidingEntities.js @@ -43,7 +43,6 @@ function draw(deltaTime) { var properties = { type: "Sphere", - script: "file:///Users/zappoman/Development/HiFi/hifi/examples/entityScripts/changeColorOnCollision.js", collisionsWillMove: true, position: startPosition, dimensions: {x: largeRadius, y: largeRadius, z: largeRadius}, @@ -53,7 +52,7 @@ function draw(deltaTime) { lifetime: 20 }; - //Entities.addEntity(properties); + Entities.addEntity(properties); numberEntitiesAdded++; } @@ -85,7 +84,6 @@ function draw(deltaTime) { if (numberEntitiesAdded <= MAX_ENTITIES) { var properties = { type: "Sphere", - script: "file:///Users/zappoman/Development/HiFi/hifi/examples/entityScripts/changeColorOnCollision.js", collisionsWillMove: true, position: center, dimensions: {x: entitySize, y: entitySize, z: entitySize}, diff --git a/examples/entityScripts/changeColorOnCollision.js b/examples/entityScripts/changeColorOnCollision.js index e19e63c35b..69a14f4b52 100644 --- a/examples/entityScripts/changeColorOnCollision.js +++ b/examples/entityScripts/changeColorOnCollision.js @@ -9,19 +9,12 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -print("changeColorOnCollision.js"); - (function(){ function getRandomInt(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; } - this.preload = function(myID) { - print("changeColorOnCollision.js--- preload!!!"); - }; - this.collisionWithEntity = function(myID, otherID, collisionInfo) { - print("collisionWithEntity"); Entities.editEntity(myID, { color: { red: getRandomInt(128,255), green: getRandomInt(128,255), blue: getRandomInt(128,255)} }); }; }) \ No newline at end of file From 27bfc9907f834071a406bb1c870d34c25eaf60af Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 8 Dec 2014 16:31:36 -0800 Subject: [PATCH 296/502] fix bug preventing butterflies from animating (forgot to make base method virtual) --- libraries/entities/src/EntityItem.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 314b1c23d5..6fb51cfdba 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -130,7 +130,7 @@ public: // perform linear extrapolation for SimpleEntitySimulation void simulate(const quint64& now); - bool needsToCallUpdate() const { return false; } + virtual bool needsToCallUpdate() const { return false; } virtual void debugDump() const; From 675a2dd989c5dfe4d8449564f871d93bf49dbb40 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 8 Dec 2014 16:32:25 -0800 Subject: [PATCH 297/502] add DIRTY_UPDATEABLE flag for changes that need it --- libraries/entities/src/EntityItem.h | 1 + libraries/entities/src/ModelEntityItem.cpp | 16 ++++++++++++++ libraries/entities/src/ModelEntityItem.h | 6 ++--- .../entities/src/SimpleEntitySimulation.cpp | 22 +++++++------------ 4 files changed, 28 insertions(+), 17 deletions(-) diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 6fb51cfdba..915440ee6a 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -49,6 +49,7 @@ public: DIRTY_MOTION_TYPE = 0x0010, DIRTY_SHAPE = 0x0020, DIRTY_LIFETIME = 0x0040, + DIRTY_UPDATEABLE = 0x0080, // add new simulation-relevant flags above // all other flags below DIRTY_SCRIPT = 0x8000 diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index 565974d19e..b9bf75178f 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -397,6 +397,11 @@ void ModelEntityItem::debugDump() const { qDebug() << " model URL:" << getModelURL(); } +void ModelEntityItem::setAnimationURL(const QString& url) { + _dirtyFlags |= EntityItem::DIRTY_UPDATEABLE; + _animationURL = url; +} + void ModelEntityItem::setAnimationSettings(const QString& value) { // the animations setting is a JSON string that may contain various animation settings. // if it includes fps, frameIndex, or running, those values will be parsed out and @@ -448,6 +453,17 @@ void ModelEntityItem::setAnimationSettings(const QString& value) { } _animationSettings = value; + _dirtyFlags |= EntityItem::DIRTY_UPDATEABLE; +} + +void ModelEntityItem::setAnimationIsPlaying(bool value) { + _dirtyFlags |= EntityItem::DIRTY_UPDATEABLE; + _animationLoop.setRunning(value); +} + +void ModelEntityItem::setAnimationFPS(float value) { + _dirtyFlags |= EntityItem::DIRTY_UPDATEABLE; + _animationLoop.setFPS(value); } QString ModelEntityItem::getAnimationSettings() const { diff --git a/libraries/entities/src/ModelEntityItem.h b/libraries/entities/src/ModelEntityItem.h index 502b21af12..6b4ca2416a 100644 --- a/libraries/entities/src/ModelEntityItem.h +++ b/libraries/entities/src/ModelEntityItem.h @@ -73,16 +73,16 @@ public: // model related properties void setModelURL(const QString& url) { _modelURL = url; } - void setAnimationURL(const QString& url) { _animationURL = url; } + void setAnimationURL(const QString& url); static const float DEFAULT_ANIMATION_FRAME_INDEX; void setAnimationFrameIndex(float value) { _animationLoop.setFrameIndex(value); } void setAnimationSettings(const QString& value); static const bool DEFAULT_ANIMATION_IS_PLAYING; - void setAnimationIsPlaying(bool value) { _animationLoop.setRunning(value); } + void setAnimationIsPlaying(bool value); static const float DEFAULT_ANIMATION_FPS; - void setAnimationFPS(float value) { _animationLoop.setFPS(value); } + void setAnimationFPS(float value); void setAnimationLoop(bool loop) { _animationLoop.setLoop(loop); } bool getAnimationLoop() const { return _animationLoop.getLoop(); } diff --git a/libraries/entities/src/SimpleEntitySimulation.cpp b/libraries/entities/src/SimpleEntitySimulation.cpp index 17dbd46727..6fd2d7c48c 100644 --- a/libraries/entities/src/SimpleEntitySimulation.cpp +++ b/libraries/entities/src/SimpleEntitySimulation.cpp @@ -31,12 +31,10 @@ void SimpleEntitySimulation::updateEntitiesInternal(const quint64& now) { } void SimpleEntitySimulation::addEntityInternal(EntityItem* entity) { - if (entity->getCollisionsWillMove()) { - if (entity->isMoving()) { - _movingEntities.insert(entity); - } else { - _movableButStoppedEntities.insert(entity); - } + if (entity->isMoving()) { + _movingEntities.insert(entity); + } else if (entity->getCollisionsWillMove()) { + _movableButStoppedEntities.insert(entity); } } @@ -50,14 +48,10 @@ const int SIMPLE_SIMULATION_DIRTY_FLAGS = EntityItem::DIRTY_VELOCITY | EntityIte void SimpleEntitySimulation::entityChangedInternal(EntityItem* entity) { int dirtyFlags = entity->getDirtyFlags(); if (dirtyFlags & SIMPLE_SIMULATION_DIRTY_FLAGS) { - if (entity->getCollisionsWillMove()) { - if (entity->isMoving()) { - _movingEntities.insert(entity); - _movableButStoppedEntities.remove(entity); - } else { - _movingEntities.remove(entity); - _movableButStoppedEntities.insert(entity); - } + if (entity->isMoving()) { + _movingEntities.insert(entity); + } else if (entity->getCollisionsWillMove()) { + _movableButStoppedEntities.remove(entity); } else { _movingEntities.remove(entity); _movableButStoppedEntities.remove(entity); From d0ca75dd2cc06c335ddc3e3dacc45fd0f890f805 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Mon, 8 Dec 2014 18:04:45 -0800 Subject: [PATCH 298/502] Reduce the MTU size to deal with Windows networking issue. --- libraries/metavoxels/src/DatagramSequencer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/metavoxels/src/DatagramSequencer.cpp b/libraries/metavoxels/src/DatagramSequencer.cpp index 1aeef8e450..5c5aee49c2 100644 --- a/libraries/metavoxels/src/DatagramSequencer.cpp +++ b/libraries/metavoxels/src/DatagramSequencer.cpp @@ -19,7 +19,7 @@ #include "MetavoxelMessages.h" // in sequencer parlance, a "packet" may consist of multiple datagrams. clarify when we refer to actual datagrams -const int MAX_DATAGRAM_SIZE = MAX_PACKET_SIZE; +const int MAX_DATAGRAM_SIZE = 1450; const int DEFAULT_MAX_PACKET_SIZE = 3000; From 3c09ca71cb6915e9fe8460fddbc5c929356b5fa0 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 8 Dec 2014 18:09:49 -0800 Subject: [PATCH 299/502] move emit of collisions to after done moving entities, so that callbacks can delete entities --- examples/collidingEntities.js | 4 +++- libraries/entities/src/EntityCollisionSystem.cpp | 14 +++++++------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/examples/collidingEntities.js b/examples/collidingEntities.js index 7edbc9fecc..fff41ab65d 100644 --- a/examples/collidingEntities.js +++ b/examples/collidingEntities.js @@ -22,7 +22,7 @@ var velocity = { y: 0, z: 1 }; -var damping = 0.1; +var damping = 0; var color = { red: 255, @@ -43,6 +43,7 @@ function draw(deltaTime) { var properties = { type: "Sphere", + script: "file:///Users/zappoman/Development/HiFi/hifi/examples/entityScripts/changeColorOnCollision.js", collisionsWillMove: true, position: startPosition, dimensions: {x: largeRadius, y: largeRadius, z: largeRadius}, @@ -84,6 +85,7 @@ function draw(deltaTime) { if (numberEntitiesAdded <= MAX_ENTITIES) { var properties = { type: "Sphere", + script: "file:///Users/zappoman/Development/HiFi/hifi/examples/entityScripts/changeColorOnCollision.js", collisionsWillMove: true, position: center, dimensions: {x: entitySize, y: entitySize, z: entitySize}, diff --git a/libraries/entities/src/EntityCollisionSystem.cpp b/libraries/entities/src/EntityCollisionSystem.cpp index f9a9ec733d..7669f73c7d 100644 --- a/libraries/entities/src/EntityCollisionSystem.cpp +++ b/libraries/entities/src/EntityCollisionSystem.cpp @@ -170,12 +170,6 @@ void EntityCollisionSystem::updateCollisionWithEntities(EntityItem* entityA) { quint64 now = usecTimestampNow(); - Collision collision; - collision.penetration = penetration; - // for now the contactPoint is the average between the the two paricle centers - collision.contactPoint = (0.5f * (float)TREE_SCALE) * (entityA->getPosition() + entityB->getPosition()); - emitGlobalEntityCollisionWithEntity(entityA, entityB, collision); - glm::vec3 axis = glm::normalize(penetration); glm::vec3 axialVelocity = glm::dot(relativeVelocity, axis) * axis; @@ -232,7 +226,13 @@ void EntityCollisionSystem::updateCollisionWithEntities(EntityItem* entityA) { // thereby waking up static non-moving entities. _entityTree->updateEntity(entityB, propertiesB); _packetSender->queueEditEntityMessage(PacketTypeEntityAddOrEdit, idB, propertiesB); - } + } + + // NOTE: Do this after updating the entities so that the callback can delete the entities if they want to + Collision collision; + collision.penetration = penetration; + collision.contactPoint = (0.5f * (float)TREE_SCALE) * (entityA->getPosition() + entityB->getPosition()); + emitGlobalEntityCollisionWithEntity(entityA, entityB, collision); } } } From 343f61044235e6df9e0dd49adbf797369739e353 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Mon, 8 Dec 2014 18:45:05 -0800 Subject: [PATCH 300/502] Use the 1450 limit everywhere, in case other places are running into the issue I experienced with metavoxels. --- libraries/metavoxels/src/DatagramSequencer.cpp | 2 +- libraries/networking/src/LimitedNodeList.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/metavoxels/src/DatagramSequencer.cpp b/libraries/metavoxels/src/DatagramSequencer.cpp index 5c5aee49c2..1aeef8e450 100644 --- a/libraries/metavoxels/src/DatagramSequencer.cpp +++ b/libraries/metavoxels/src/DatagramSequencer.cpp @@ -19,7 +19,7 @@ #include "MetavoxelMessages.h" // in sequencer parlance, a "packet" may consist of multiple datagrams. clarify when we refer to actual datagrams -const int MAX_DATAGRAM_SIZE = 1450; +const int MAX_DATAGRAM_SIZE = MAX_PACKET_SIZE; const int DEFAULT_MAX_PACKET_SIZE = 3000; diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index 2fc8751e3f..f367cb93ce 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -31,7 +31,7 @@ #include "DomainHandler.h" #include "Node.h" -const int MAX_PACKET_SIZE = 1500; +const int MAX_PACKET_SIZE = 1450; const quint64 NODE_SILENCE_THRESHOLD_MSECS = 2 * 1000; From e5aee44ceb60c0261533988e5ea7df740aad3fe0 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 9 Dec 2014 08:51:04 -0800 Subject: [PATCH 301/502] Add setting save/load to grid tool --- examples/html/gridControls.html | 6 +-- examples/libraries/gridTool.js | 77 ++++++++++++++++++++++++++++----- 2 files changed, 68 insertions(+), 15 deletions(-) diff --git a/examples/html/gridControls.html b/examples/html/gridControls.html index d95c9545e4..06090da423 100644 --- a/examples/html/gridControls.html +++ b/examples/html/gridControls.html @@ -29,11 +29,11 @@ elPosY.value = origin.y.toFixed(2); } - if (data.minorGridSpacing) { + if (data.minorGridSpacing !== undefined) { elMinorSpacing.value = data.minorGridSpacing; } - if (data.majorGridEvery) { + if (data.majorGridEvery !== undefined) { elMajorSpacing.value = data.majorGridEvery; } @@ -41,7 +41,7 @@ gridColor = data.gridColor; } - if (data.elSnapToGrid !== undefined) { + if (data.snapToGrid !== undefined) { elSnapToGrid.checked = data.snapToGrid == true; } diff --git a/examples/libraries/gridTool.js b/examples/libraries/gridTool.js index 7d98befec8..1793fb5b4f 100644 --- a/examples/libraries/gridTool.js +++ b/examples/libraries/gridTool.js @@ -1,3 +1,9 @@ +var SETTING_GRID_VISIBLE = 'gridVisible'; +var SETTING_GRID_SNAP_TO_GRID = 'gridSnapToGrid'; +var SETTING_GRID_MINOR_WIDTH= 'gridMinorWidth'; +var SETTING_GRID_MAJOR_EVERY = 'gridMajorEvery'; +var SETTING_GRID_COLOR = 'gridColor'; + Grid = function(opts) { var that = {}; @@ -12,9 +18,6 @@ Grid = function(opts) { var worldSize = 16384; - var minorGridWidth = 0.5; - var majorGridWidth = 1.5; - var snapToGrid = false; var gridOverlay = Overlays.addOverlay("grid", { @@ -23,7 +26,7 @@ Grid = function(opts) { color: { red: 0, green: 0, blue: 128 }, alpha: 1.0, rotation: Quat.fromPitchYawRollDegrees(90, 0, 0), - minorGridWidth: 0.1, + minorGridSpacing: 0.1, majorGridEvery: 2, }); @@ -40,16 +43,38 @@ Grid = function(opts) { that.getSnapToGrid = function() { return snapToGrid; }; that.setEnabled = function(enabled) { - that.enabled = enabled; - updateGrid(); + if (that.enabled != enabled) { + that.enabled = enabled; + + if (enabled) { + if (selectionManager.hasSelection()) { + that.setPosition(selectionManager.getBottomPosition()); + } else { + that.setPosition(MyAvatar.position); + } + } + + updateGrid(); + } } that.setVisible = function(visible, noUpdate) { - that.visible = visible; - updateGrid(); + if (visible != that.visible) { + that.visible = visible; + updateGrid(); - if (!noUpdate) { - that.emitUpdate(); + print("Setting visible"); + if (visible) { + if (selectionManager.hasSelection()) { + that.setPosition(selectionManager.getBottomPosition()); + } else { + that.setPosition(MyAvatar.position); + } + } + + if (!noUpdate) { + that.emitUpdate(); + } } } @@ -171,7 +196,7 @@ Grid = function(opts) { Overlays.editOverlay(gridOverlay, { position: { x: origin.y, y: origin.y, z: -origin.y }, visible: that.visible && that.enabled, - minorGridWidth: minorGridSpacing, + minorGridSpacing: minorGridSpacing, majorGridEvery: majorGridEvery, color: gridColor, alpha: gridAlpha, @@ -181,15 +206,43 @@ Grid = function(opts) { } function cleanup() { + saveSettings(); + Overlays.deleteOverlay(gridOverlay); } + function loadSettings() { + that.setVisible(Settings.getValue(SETTING_GRID_VISIBLE) == "true", true); + snapToGrid = Settings.getValue(SETTING_GRID_SNAP_TO_GRID) == "true"; + minorGridSpacing = parseFloat(Settings.getValue(SETTING_GRID_MINOR_WIDTH), 10); + majorGridEvery = parseInt(Settings.getValue(SETTING_GRID_MAJOR_EVERY), 10); + try { + var newColor = JSON.parse(Settings.getValue(SETTING_GRID_COLOR)); + if (newColor.red !== undefined && newColor.green !== undefined && newColor.blue !== undefined) { + gridColor.red = newColor.red; + gridColor.green = newColor.green; + gridColor.blue = newColor.blue; + } + } catch (e) { + } + updateGrid(); + } + + function saveSettings() { + Settings.setValue(SETTING_GRID_VISIBLE, that.visible); + Settings.setValue(SETTING_GRID_SNAP_TO_GRID, snapToGrid); + Settings.setValue(SETTING_GRID_MINOR_WIDTH, minorGridSpacing); + Settings.setValue(SETTING_GRID_MAJOR_EVERY, majorGridEvery); + Settings.setValue(SETTING_GRID_COLOR, JSON.stringify(gridColor)); + } + that.addListener = function(callback) { that.onUpdate = callback; } Script.scriptEnding.connect(cleanup); - updateGrid(); + + loadSettings(); that.onUpdate = null; From 2696f71be93b318098d5217ce455557d9343a13f Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 9 Dec 2014 08:54:28 -0800 Subject: [PATCH 302/502] Update edit entities to disable on wasd or arrow keys --- examples/newEditEntities.js | 45 ++++++++++++++++++++++++------------- 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/examples/newEditEntities.js b/examples/newEditEntities.js index ef1be8fef9..f9f604afe8 100644 --- a/examples/newEditEntities.js +++ b/examples/newEditEntities.js @@ -215,6 +215,28 @@ var toolBar = (function () { Overlays.editOverlay(loadFileMenuItem, { visible: active }); } + + that.setActive = function(active) { + if (active != isActive) { + isActive = active; + if (!isActive) { + entityListTool.setVisible(false); + gridTool.setVisible(false); + grid.setEnabled(false); + propertiesTool.setVisible(false); + selectionManager.clearSelections(); + cameraManager.disable(); + } else { + cameraManager.enable(); + entityListTool.setVisible(true); + gridTool.setVisible(true); + propertiesTool.setVisible(true); + grid.setEnabled(true); + } + } + toolBar.selectTool(activeButton, active); + }; + var RESIZE_INTERVAL = 50; var RESIZE_TIMEOUT = 20000; var RESIZE_MAX_CHECKS = RESIZE_TIMEOUT / RESIZE_INTERVAL; @@ -290,21 +312,7 @@ var toolBar = (function () { clickedOverlay = Overlays.getOverlayAtPoint({ x: event.x, y: event.y }); if (activeButton === toolBar.clicked(clickedOverlay)) { - isActive = !isActive; - if (!isActive) { - entityListTool.setVisible(false); - gridTool.setVisible(false); - grid.setEnabled(false); - propertiesTool.setVisible(false); - selectionManager.clearSelections(); - cameraManager.disable(); - } else { - cameraManager.enable(); - entityListTool.setVisible(true); - gridTool.setVisible(true); - grid.setEnabled(true); - propertiesTool.setVisible(true); - } + that.setActive(!isActive); return true; } @@ -817,6 +825,13 @@ function handeMenuEvent(menuItem) { Menu.menuItemEvent.connect(handeMenuEvent); +Controller.keyPressEvent.connect(function(event) { + if (event.text == 'w' || event.text == 'a' || event.text == 's' || event.text == 'd' + || event.text == 'UP' || event.text == 'DOWN' || event.text == 'LEFT' || event.text == 'RIGHT') { + toolBar.setActive(false); + } +}); + Controller.keyReleaseEvent.connect(function (event) { // since sometimes our menu shortcut keys don't work, trap our menu items here also and fire the appropriate menu items if (event.text == "`") { From 19ba2a1f84a6cd1ac0361e022885e2d1d134bdf4 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 9 Dec 2014 08:56:29 -0800 Subject: [PATCH 303/502] Remove print statement --- examples/libraries/gridTool.js | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/libraries/gridTool.js b/examples/libraries/gridTool.js index 1793fb5b4f..622822e108 100644 --- a/examples/libraries/gridTool.js +++ b/examples/libraries/gridTool.js @@ -63,7 +63,6 @@ Grid = function(opts) { that.visible = visible; updateGrid(); - print("Setting visible"); if (visible) { if (selectionManager.hasSelection()) { that.setPosition(selectionManager.getBottomPosition()); From 1eaa2caa6ccbd37fd871fa144ce9dab4732a60d8 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 9 Dec 2014 11:40:47 -0800 Subject: [PATCH 304/502] fix to crash on rapidly switching domains --- interface/src/entities/EntityTreeRenderer.cpp | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/interface/src/entities/EntityTreeRenderer.cpp b/interface/src/entities/EntityTreeRenderer.cpp index dd9a0b6a4f..2c2b81fa3a 100644 --- a/interface/src/entities/EntityTreeRenderer.cpp +++ b/interface/src/entities/EntityTreeRenderer.cpp @@ -151,12 +151,19 @@ QScriptValue EntityTreeRenderer::loadEntityScript(EntityItem* entity) { return QScriptValue(); // no entity... } + // NOTE: we keep local variables for the entityID and the script because + // below in loadScriptContents() it's possible for us to execute the + // application event loop, which may cause our entity to be deleted on + // us. We don't really need access the entity after this point, can + // can accomplish all we need to here with just the script "text" and the ID. EntityItemID entityID = entity->getEntityItemID(); + QString entityScript = entity->getScript(); + if (_entityScripts.contains(entityID)) { EntityScriptDetails details = _entityScripts[entityID]; // check to make sure our script text hasn't changed on us since we last loaded it - if (details.scriptText == entity->getScript()) { + if (details.scriptText == entityScript) { return details.scriptObject; // previously loaded } @@ -164,18 +171,18 @@ QScriptValue EntityTreeRenderer::loadEntityScript(EntityItem* entity) { // has changed and so we need to reload it. _entityScripts.remove(entityID); } - if (entity->getScript().isEmpty()) { + if (entityScript.isEmpty()) { return QScriptValue(); // no script } - QString scriptContents = loadScriptContents(entity->getScript()); + QString scriptContents = loadScriptContents(entityScript); QScriptSyntaxCheckResult syntaxCheck = QScriptEngine::checkSyntax(scriptContents); if (syntaxCheck.state() != QScriptSyntaxCheckResult::Valid) { qDebug() << "EntityTreeRenderer::loadEntityScript() entity:" << entityID; qDebug() << " " << syntaxCheck.errorMessage() << ":" << syntaxCheck.errorLineNumber() << syntaxCheck.errorColumnNumber(); - qDebug() << " SCRIPT:" << entity->getScript(); + qDebug() << " SCRIPT:" << entityScript; return QScriptValue(); // invalid script } @@ -184,12 +191,12 @@ QScriptValue EntityTreeRenderer::loadEntityScript(EntityItem* entity) { if (!entityScriptConstructor.isFunction()) { qDebug() << "EntityTreeRenderer::loadEntityScript() entity:" << entityID; qDebug() << " NOT CONSTRUCTOR"; - qDebug() << " SCRIPT:" << entity->getScript(); + qDebug() << " SCRIPT:" << entityScript; return QScriptValue(); // invalid script } QScriptValue entityScriptObject = entityScriptConstructor.construct(); - EntityScriptDetails newDetails = { entity->getScript(), entityScriptObject }; + EntityScriptDetails newDetails = { entityScript, entityScriptObject }; _entityScripts[entityID] = newDetails; return entityScriptObject; // newly constructed From a6f7a1ce15713124825193c143d3b0ba39dec9b8 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 9 Dec 2014 11:52:20 -0800 Subject: [PATCH 305/502] guard against NULL _models --- interface/src/entities/RenderableModelEntityItem.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/interface/src/entities/RenderableModelEntityItem.cpp b/interface/src/entities/RenderableModelEntityItem.cpp index 8509fa1f67..080162dc16 100644 --- a/interface/src/entities/RenderableModelEntityItem.cpp +++ b/interface/src/entities/RenderableModelEntityItem.cpp @@ -268,7 +268,10 @@ EntityItemProperties RenderableModelEntityItem::getProperties() const { bool RenderableModelEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, void** intersectedObject, bool precisionPicking) const { - + if (!_model) { + return true; + } + glm::vec3 originInMeters = origin * (float)TREE_SCALE; QString extraInfo; float localDistance; From eaaaa0687ca19d1d2a7839616d873f44fc6436de Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 9 Dec 2014 11:53:14 -0800 Subject: [PATCH 306/502] spacing --- libraries/octree/src/ViewFrustum.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/octree/src/ViewFrustum.cpp b/libraries/octree/src/ViewFrustum.cpp index 0549c60134..1d23bf800e 100644 --- a/libraries/octree/src/ViewFrustum.cpp +++ b/libraries/octree/src/ViewFrustum.cpp @@ -591,7 +591,7 @@ PickRay ViewFrustum::computePickRay(float x, float y) { } void ViewFrustum::computePickRay(float x, float y, glm::vec3& origin, glm::vec3& direction) const { - origin = _nearTopLeft + x*(_nearTopRight - _nearTopLeft) + y*(_nearBottomLeft - _nearTopLeft); + origin = _nearTopLeft + x * (_nearTopRight - _nearTopLeft) + y * (_nearBottomLeft - _nearTopLeft); direction = glm::normalize(origin - (_position + _orientation * _eyeOffsetPosition)); } From 649940de244b7fc509818448c3addb0aa0c49d51 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 9 Dec 2014 11:53:32 -0800 Subject: [PATCH 307/502] wrong pickray function --- interface/src/ui/NodeBounds.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/interface/src/ui/NodeBounds.cpp b/interface/src/ui/NodeBounds.cpp index 3c6b4c625a..b0d3ddd14f 100644 --- a/interface/src/ui/NodeBounds.cpp +++ b/interface/src/ui/NodeBounds.cpp @@ -38,7 +38,8 @@ void NodeBounds::draw() { // Compute ray to find selected nodes later on. We can't use the pre-computed ray in Application because it centers // itself after the cursor disappears. Application* application = Application::getInstance(); - PickRay pickRay = application->getCamera()->computeViewPickRay(application->getTrueMouseX(), application->getTrueMouseY()); + PickRay pickRay = application->getCamera()->computePickRay(application->getTrueMouseX(), + application->getTrueMouseY()); // Variables to keep track of the selected node and properties to draw the cube later if needed Node* selectedNode = NULL; From 79fc8a5a7114c1d012d859163cfbe8d3f24e5a46 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 9 Dec 2014 11:58:01 -0800 Subject: [PATCH 308/502] remove debug ryans rotate problem --- examples/libraries/entitySelectionTool.js | 74 ----------------------- examples/newEditEntities.js | 2 - 2 files changed, 76 deletions(-) diff --git a/examples/libraries/entitySelectionTool.js b/examples/libraries/entitySelectionTool.js index 382b8de215..8aff9c32ed 100644 --- a/examples/libraries/entitySelectionTool.js +++ b/examples/libraries/entitySelectionTool.js @@ -1749,13 +1749,6 @@ SelectionDisplay = (function () { pushCommandForSelections(); }, onMove: function(event) { - var debug = Menu.isOptionChecked("Debug Ryans Rotation Problems"); - - if (debug) { - print("rotateYaw()..."); - print(" event.x,y:" + event.x + "," + event.y); - } - var pickRay = Camera.computePickRay(event.x, event.y); Overlays.editOverlay(selectionBox, { ignoreRayIntersection: true, visible: false}); Overlays.editOverlay(baseOfEntityProjectionOverlay, { ignoreRayIntersection: true, visible: false }); @@ -1763,10 +1756,6 @@ SelectionDisplay = (function () { var result = Overlays.findRayIntersection(pickRay); - if (debug) { - print(" findRayIntersection() .... result.intersects:" + result.intersects); - } - if (result.intersects) { var center = yawCenter; var zero = yawZero; @@ -1776,26 +1765,7 @@ SelectionDisplay = (function () { var distanceFromCenter = Vec3.distance(center, result.intersection); var snapToInner = distanceFromCenter < innerRadius; var snapAngle = snapToInner ? innerSnapAngle : 1.0; - - // for debugging - if (debug) { - Vec3.print(" result.intersection:",result.intersection); - Overlays.editOverlay(rotateCurrentOverlay, { visible: true, start: center, end: result.intersection }); - Vec3.print(" centerToZero:", centerToZero); - Vec3.print(" centerToIntersect:", centerToIntersect); - Vec3.print(" rotationNormal:", rotationNormal); - print(" angleFromZero:" + angleFromZero); - print(" distanceFromCenter:" + distanceFromCenter); - print(" snapAngle:" + snapAngle); - } - angleFromZero = Math.floor(angleFromZero / snapAngle) * snapAngle; - - // for debugging - if (debug) { - print(" angleFromZero:" + angleFromZero + " --- after snap"); - } - var yawChange = Quat.fromVec3Degrees({ x: 0, y: angleFromZero, z: 0 }); // Entities should only reposition if we are rotating multiple selections around @@ -1906,23 +1876,12 @@ SelectionDisplay = (function () { pushCommandForSelections(); }, onMove: function(event) { - var debug = Menu.isOptionChecked("Debug Ryans Rotation Problems"); - - if (debug) { - print("rotatePitch()..."); - print(" event.x,y:" + event.x + "," + event.y); - } - var pickRay = Camera.computePickRay(event.x, event.y); Overlays.editOverlay(selectionBox, { ignoreRayIntersection: true, visible: false}); Overlays.editOverlay(baseOfEntityProjectionOverlay, { ignoreRayIntersection: true, visible: false }); Overlays.editOverlay(rotateOverlayTarget, { ignoreRayIntersection: false }); var result = Overlays.findRayIntersection(pickRay); - if (debug) { - print(" findRayIntersection() .... result.intersects:" + result.intersects); - } - if (result.intersects) { var properties = Entities.getEntityProperties(selectionManager.selections[0]); var center = pitchCenter; @@ -1936,13 +1895,6 @@ SelectionDisplay = (function () { var snapAngle = snapToInner ? innerSnapAngle : 1.0; angleFromZero = Math.floor(angleFromZero / snapAngle) * snapAngle; - // for debugging - if (debug) { - Vec3.print(" result.intersection:",result.intersection); - Overlays.editOverlay(rotateCurrentOverlay, { visible: true, start: center, end: result.intersection }); - print(" angleFromZero:" + angleFromZero); - } - var pitchChange = Quat.fromVec3Degrees({ x: angleFromZero, y: 0, z: 0 }); for (var i = 0; i < SelectionManager.selections.length; i++) { @@ -2043,23 +1995,12 @@ SelectionDisplay = (function () { pushCommandForSelections(); }, onMove: function(event) { - var debug = Menu.isOptionChecked("Debug Ryans Rotation Problems"); - - if (debug) { - print("rotateRoll()..."); - print(" event.x,y:" + event.x + "," + event.y); - } - var pickRay = Camera.computePickRay(event.x, event.y); Overlays.editOverlay(selectionBox, { ignoreRayIntersection: true, visible: false}); Overlays.editOverlay(baseOfEntityProjectionOverlay, { ignoreRayIntersection: true, visible: false }); Overlays.editOverlay(rotateOverlayTarget, { ignoreRayIntersection: false }); var result = Overlays.findRayIntersection(pickRay); - if (debug) { - print(" findRayIntersection() .... result.intersects:" + result.intersects); - } - if (result.intersects) { var properties = Entities.getEntityProperties(selectionManager.selections[0]); var center = rollCenter; @@ -2073,13 +2014,6 @@ SelectionDisplay = (function () { var snapAngle = snapToInner ? innerSnapAngle : 1.0; angleFromZero = Math.floor(angleFromZero / snapAngle) * snapAngle; - // for debugging - if (debug) { - Vec3.print(" result.intersection:",result.intersection); - Overlays.editOverlay(rotateCurrentOverlay, { visible: true, start: center, end: result.intersection }); - print(" angleFromZero:" + angleFromZero); - } - var rollChange = Quat.fromVec3Degrees({ x: 0, y: 0, z: angleFromZero }); for (var i = 0; i < SelectionManager.selections.length; i++) { var entityID = SelectionManager.selections[i]; @@ -2310,14 +2244,6 @@ SelectionDisplay = (function () { Overlays.editOverlay(rotateOverlayInner, { visible: true, rotation: overlayOrientation, position: overlayCenter }); Overlays.editOverlay(rotateOverlayOuter, { visible: true, rotation: overlayOrientation, position: overlayCenter, startAt: 0, endAt: 360 }); Overlays.editOverlay(rotateOverlayCurrent, { visible: true, rotation: overlayOrientation, position: overlayCenter, startAt: 0, endAt: 0 }); - - // for debugging - var debug = Menu.isOptionChecked("Debug Ryans Rotation Problems"); - if (debug) { - Overlays.editOverlay(rotateZeroOverlay, { visible: true, start: overlayCenter, end: result.intersection }); - Overlays.editOverlay(rotateCurrentOverlay, { visible: true, start: overlayCenter, end: result.intersection }); - } - Overlays.editOverlay(yawHandle, { visible: false }); Overlays.editOverlay(pitchHandle, { visible: false }); Overlays.editOverlay(rollHandle, { visible: false }); diff --git a/examples/newEditEntities.js b/examples/newEditEntities.js index 90208ba24e..f1b9dd4421 100644 --- a/examples/newEditEntities.js +++ b/examples/newEditEntities.js @@ -666,7 +666,6 @@ function setupModelMenus() { Menu.addMenuItem({ menuName: "File", menuItemName: "Models", isSeparator: true, beforeItem: "Settings" }); Menu.addMenuItem({ menuName: "File", menuItemName: "Export Models", shortcutKey: "CTRL+META+E", afterItem: "Models" }); Menu.addMenuItem({ menuName: "File", menuItemName: "Import Models", shortcutKey: "CTRL+META+I", afterItem: "Export Models" }); - Menu.addMenuItem({ menuName: "Developer", menuItemName: "Debug Ryans Rotation Problems", isCheckable: true }); Menu.addMenuItem({ menuName: "View", menuItemName: MENU_EASE_ON_FOCUS, afterItem: MENU_INSPECT_TOOL_ENABLED, isCheckable: true, isChecked: Settings.getValue(SETTING_EASE_ON_FOCUS) == "true" }); @@ -693,7 +692,6 @@ function cleanupModelMenus() { Menu.removeSeparator("File", "Models"); Menu.removeMenuItem("File", "Export Models"); Menu.removeMenuItem("File", "Import Models"); - Menu.removeMenuItem("Developer", "Debug Ryans Rotation Problems"); Menu.removeMenuItem("View", MENU_INSPECT_TOOL_ENABLED); Menu.removeMenuItem("View", MENU_EASE_ON_FOCUS); From 895e22fcdbe8aa6e24cb5477693df54bfcff2035 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 9 Dec 2014 12:12:04 -0800 Subject: [PATCH 309/502] removed debug code --- examples/collidingEntities.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/examples/collidingEntities.js b/examples/collidingEntities.js index fff41ab65d..233626df23 100644 --- a/examples/collidingEntities.js +++ b/examples/collidingEntities.js @@ -43,7 +43,6 @@ function draw(deltaTime) { var properties = { type: "Sphere", - script: "file:///Users/zappoman/Development/HiFi/hifi/examples/entityScripts/changeColorOnCollision.js", collisionsWillMove: true, position: startPosition, dimensions: {x: largeRadius, y: largeRadius, z: largeRadius}, @@ -85,7 +84,6 @@ function draw(deltaTime) { if (numberEntitiesAdded <= MAX_ENTITIES) { var properties = { type: "Sphere", - script: "file:///Users/zappoman/Development/HiFi/hifi/examples/entityScripts/changeColorOnCollision.js", collisionsWillMove: true, position: center, dimensions: {x: entitySize, y: entitySize, z: entitySize}, From 5fb9905186ba3ce1042ec7ae67cb50211df119b0 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 9 Dec 2014 12:14:21 -0800 Subject: [PATCH 310/502] Rather than reducing rate on first drop, wait until three consecutive packets have been dropped. --- .../metavoxels/src/DatagramSequencer.cpp | 20 +++++++++++++------ libraries/metavoxels/src/DatagramSequencer.h | 2 ++ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/libraries/metavoxels/src/DatagramSequencer.cpp b/libraries/metavoxels/src/DatagramSequencer.cpp index 1aeef8e450..65d548ba1c 100644 --- a/libraries/metavoxels/src/DatagramSequencer.cpp +++ b/libraries/metavoxels/src/DatagramSequencer.cpp @@ -45,7 +45,8 @@ DatagramSequencer::DatagramSequencer(const QByteArray& datagramHeader, QObject* _packetsToWrite(0.0f), _slowStartThreshold(DEFAULT_SLOW_START_THRESHOLD), _packetRateIncreasePacketNumber(0), - _packetRateDecreasePacketNumber(0) { + _packetRateDecreasePacketNumber(0), + _packetDropCount(0) { _outgoingPacketStream.setByteOrder(QDataStream::LittleEndian); _incomingDatagramStream.setByteOrder(QDataStream::LittleEndian); @@ -348,11 +349,18 @@ void DatagramSequencer::sendRecordLost(const SendRecord& record) { } } - // halve the rate and remember as threshold - if (record.packetNumber >= _packetRateDecreasePacketNumber) { - _packetsPerGroup = qMax(_packetsPerGroup * 0.5f, 1.0f); - _slowStartThreshold = _packetsPerGroup; - _packetRateDecreasePacketNumber = _outgoingPacketNumber + 1; + // if we've lost three in a row, halve the rate and remember as threshold + if (_packetDropCount == 0 || record.packetNumber == _lastPacketDropped + 1) { + _packetDropCount++; + _lastPacketDropped = record.packetNumber; + const int CONSECUTIVE_DROPS_BEFORE_REDUCTION = 3; + if (_packetDropCount >= CONSECUTIVE_DROPS_BEFORE_REDUCTION && record.packetNumber >= _packetRateDecreasePacketNumber) { + _packetsPerGroup = qMax(_packetsPerGroup * 0.5f, 1.0f); + _slowStartThreshold = _packetsPerGroup; + _packetRateDecreasePacketNumber = _outgoingPacketNumber + 1; + } + } else { + _packetDropCount = 0; } } diff --git a/libraries/metavoxels/src/DatagramSequencer.h b/libraries/metavoxels/src/DatagramSequencer.h index 02fbd0f365..d3d37f2621 100644 --- a/libraries/metavoxels/src/DatagramSequencer.h +++ b/libraries/metavoxels/src/DatagramSequencer.h @@ -238,6 +238,8 @@ private: float _slowStartThreshold; int _packetRateIncreasePacketNumber; int _packetRateDecreasePacketNumber; + int _packetDropCount; + int _lastPacketDropped; QHash _reliableOutputChannels; QHash _reliableInputChannels; From a63d0e77707a87c0aaeac9cda3254a6ec3c7e775 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 9 Dec 2014 08:58:52 -0800 Subject: [PATCH 311/502] Rename newEditEntities.js to editEntities.js --- examples/{newEditEntities.js => editEntities.js} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename examples/{newEditEntities.js => editEntities.js} (100%) diff --git a/examples/newEditEntities.js b/examples/editEntities.js similarity index 100% rename from examples/newEditEntities.js rename to examples/editEntities.js From ec62c6833cf84eff41d4b79e527cd36e95840f9f Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 9 Dec 2014 08:59:11 -0800 Subject: [PATCH 312/502] Make editEntities a default script and remove editVoxels.js --- examples/defaultScripts.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/examples/defaultScripts.js b/examples/defaultScripts.js index b655c25b27..dbd8ee18d9 100644 --- a/examples/defaultScripts.js +++ b/examples/defaultScripts.js @@ -9,8 +9,7 @@ // Script.load("lookWithTouch.js"); -Script.load("editVoxels.js"); -Script.load("editModels.js"); +Script.load("editEntities.js"); Script.load("selectAudioDevice.js"); Script.load("hydraMove.js"); Script.load("headMove.js"); From 0a4f74cf9c65d2e358306206cd17bc1bdc8f4746 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 9 Dec 2014 16:29:45 -0800 Subject: [PATCH 313/502] Single reticle in the lobby --- examples/lobby.js | 48 ----------------------------------------------- 1 file changed, 48 deletions(-) diff --git a/examples/lobby.js b/examples/lobby.js index dd011d08a4..6a2d85f64d 100644 --- a/examples/lobby.js +++ b/examples/lobby.js @@ -13,7 +13,6 @@ Script.include("libraries/globals.js"); var panelWall = false; var orbShell = false; -var reticle = false; var descriptionText = false; // used for formating the description text, in meters @@ -23,8 +22,6 @@ var numberOfLines = 2; var textMargin = 0.0625; var lineHeight = (textHeight - (2 * textMargin)) / numberOfLines; -var lastMouseMove = 0; -var IDLE_HOVER_TIME = 2000; // if you haven't moved the mouse in 2 seconds, and in HMD mode, then we use reticle for hover var avatarStickPosition = {}; var orbNaturalExtentsMin = { x: -1.230354, y: -1.22077, z: -1.210487 }; @@ -57,13 +54,6 @@ var elevatorSound = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Lobby/eleva var currentMuzakInjector = null; var currentSound = null; -var inOculusMode = false; - -function reticlePosition() { - var RETICLE_DISTANCE = 1; - return Vec3.sum(Camera.position, Vec3.multiply(Quat.getFront(Camera.orientation), RETICLE_DISTANCE)); -} - function textOverlayPosition() { var TEXT_DISTANCE_OUT = 6; var TEXT_DISTANCE_DOWN = -2; @@ -124,22 +114,6 @@ function drawLobby() { panelWall = Overlays.addOverlay("model", panelWallProps); orbShell = Overlays.addOverlay("model", orbShellProps); descriptionText = Overlays.addOverlay("text3d", descriptionTextProps); - - inOculusMode = Menu.isOptionChecked("Enable VR Mode"); - - // for HMD wearers, create a reticle in center of screen - if (inOculusMode) { - var CURSOR_SCALE = 0.025; - - reticle = Overlays.addOverlay("billboard", { - url: HIFI_PUBLIC_BUCKET + "images/cursor.svg", - position: reticlePosition(), - ignoreRayIntersection: true, - isFacingAvatar: true, - alpha: 1.0, - scale: CURSOR_SCALE - }); - } // add an attachment on this avatar so other people see them in the lobby MyAvatar.attach(HELMET_ATTACHMENT_URL, "Neck", {x: 0, y: 0, z: 0}, Quat.fromPitchYawRollDegrees(0, 0, 0), 1.15); @@ -227,14 +201,8 @@ function cleanupLobby() { Overlays.deleteOverlay(orbShell); Overlays.deleteOverlay(descriptionText); - - if (reticle) { - Overlays.deleteOverlay(reticle); - } - panelWall = false; orbShell = false; - reticle = false; Audio.stopInjector(currentDrone); currentDrone = null; @@ -358,20 +326,6 @@ function handleLookAt(pickRay) { function update(deltaTime) { maybeCleanupLobby(); if (panelWall) { - - if (reticle) { - Overlays.editOverlay(reticle, { - position: reticlePosition() - }); - - var nowDate = new Date(); - var now = nowDate.getTime(); - if (now - lastMouseMove > IDLE_HOVER_TIME) { - var pickRay = Camera.computeViewPickRay(0.5, 0.5); - handleLookAt(pickRay); - } - } - Overlays.editOverlay(descriptionText, { position: textOverlayPosition() }); // if the reticle is up then we may need to play the next muzak @@ -383,8 +337,6 @@ function update(deltaTime) { function mouseMoveEvent(event) { if (panelWall) { - var nowDate = new Date(); - lastMouseMove = nowDate.getTime(); var pickRay = Camera.computePickRay(event.x, event.y); handleLookAt(pickRay); } From 8765d9a9b3fb51238c22ae1592d273dfb25784d5 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 9 Dec 2014 16:30:37 -0800 Subject: [PATCH 314/502] Mouse cursor modifications --- interface/src/Application.cpp | 85 ++++++++-------------------- interface/src/Application.h | 7 +-- interface/src/ui/FramelessDialog.cpp | 6 +- 3 files changed, 30 insertions(+), 68 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 3824185f52..8a89444734 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -167,8 +167,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : _raiseMirror(0.0f), _lastMouseMove(usecTimestampNow()), _lastMouseMoveWasSimulated(false), - _mouseHidden(false), - _seenMouseMove(false), _touchAvgX(0.0f), _touchAvgY(0.0f), _isTouchPressed(false), @@ -1252,34 +1250,23 @@ void Application::focusOutEvent(QFocusEvent* event) { } void Application::mouseMoveEvent(QMouseEvent* event, unsigned int deviceID) { - bool showMouse = true; - // Used by application overlay to determine how to draw cursor(s) _lastMouseMoveWasSimulated = deviceID > 0; - - // If this mouse move event is emitted by a controller, dont show the mouse cursor - if (_lastMouseMoveWasSimulated) { - showMouse = false; + if (!_lastMouseMoveWasSimulated) { + _lastMouseMove = usecTimestampNow(); } if (!_aboutToQuit) { - _entities.mouseMoveEvent(event, deviceID); + return; } - + + _entities.mouseMoveEvent(event, deviceID); + _controllerScriptingInterface.emitMouseMoveEvent(event, deviceID); // send events to any registered scripts - // if one of our scripts have asked to capture this event, then stop processing it if (_controllerScriptingInterface.isMouseCaptured()) { return; } - - _lastMouseMove = usecTimestampNow(); - - if (_mouseHidden && showMouse && !OculusManager::isConnected() && !TV3DManager::isConnected()) { - getGLWidget()->setCursor(Qt::ArrowCursor); - _mouseHidden = false; - _seenMouseMove = true; - } } void Application::mousePressEvent(QMouseEvent* event, unsigned int deviceID) { @@ -2111,13 +2098,7 @@ void Application::updateMouseRay() { // make sure the frustum is up-to-date loadViewFrustum(_myCamera, _viewFrustum); - // if the mouse pointer isn't visible, act like it's at the center of the screen - float x = 0.5f, y = 0.5f; - if (!_mouseHidden) { - x = getTrueMouseX() / (float)_glWidget->width(); - y = getTrueMouseY() / (float)_glWidget->height(); - } - PickRay pickRay = _myCamera.computeViewPickRay(x, y); + PickRay pickRay = _myCamera.computePickRay(getTrueMouseX(), getTrueMouseY()); _mouseRayOrigin = pickRay.origin; _mouseRayDirection = pickRay.direction; @@ -2313,23 +2294,26 @@ void Application::updateCursor(float deltaTime) { bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); PerformanceWarning warn(showWarnings, "Application::updateCursor()"); - // watch mouse position, if it hasn't moved, hide the cursor + bool hideMouse = false; bool underMouse = _glWidget->underMouse(); - if (!_mouseHidden) { - quint64 now = usecTimestampNow(); - int elapsed = now - _lastMouseMove; - const int HIDE_CURSOR_TIMEOUT = 1 * 1000 * 1000; // 1 second - if (elapsed > HIDE_CURSOR_TIMEOUT && (underMouse || !_seenMouseMove)) { - getGLWidget()->setCursor(Qt::BlankCursor); - _mouseHidden = true; - } + + static const int HIDE_CURSOR_TIMEOUT = 1 * USECS_PER_SECOND; // 1 second + int elapsed = usecTimestampNow() - _lastMouseMove; + if ((elapsed > HIDE_CURSOR_TIMEOUT && underMouse) || + (OculusManager::isConnected() && Menu::getInstance()->isOptionChecked(MenuOption::EnableVRMode))) { + hideMouse = true; + } + + if (hideMouse != isMouseHidden()) { + setCursorVisible(!hideMouse); + } +} + +void Application::setCursorVisible(bool visible) { + if (visible) { + _glWidget->setCursor(Qt::ArrowCursor); } else { - // if the mouse is hidden, but we're not inside our window, then consider ourselves to be moving - if (!underMouse && _seenMouseMove) { - _lastMouseMove = usecTimestampNow(); - getGLWidget()->setCursor(Qt::ArrowCursor); - _mouseHidden = false; - } + _glWidget->setCursor(Qt::BlankCursor); } } @@ -2350,17 +2334,6 @@ void Application::update(float deltaTime) { } - static QCursor cursor; - if (OculusManager::isConnected() && - Menu::getInstance()->isOptionChecked(MenuOption::EnableVRMode)){ - if (_window->cursor().shape() != Qt::BlankCursor) { - cursor = _window->cursor(); - _window->setCursor(QCursor(Qt::BlankCursor)); - } - } else if(_window->cursor().shape() == Qt::BlankCursor) { - _window->setCursor(cursor); - } - // Dispatch input events _controllerScriptingInterface.updateInputControllers(); @@ -4372,14 +4345,6 @@ void Application::skipVersion(QString latestVersion) { skipFile.write(latestVersion.toStdString().c_str()); } -void Application::setCursorVisible(bool visible) { - if (visible) { - restoreOverrideCursor(); - } else { - setOverrideCursor(Qt::BlankCursor); - } -} - void Application::takeSnapshot() { QMediaPlayer* player = new QMediaPlayer(); QFileInfo inf = QFileInfo(Application::resourcesPath() + "sounds/snap.wav"); diff --git a/interface/src/Application.h b/interface/src/Application.h index 58dec1da1f..0f0bd91210 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -211,7 +211,8 @@ public: EntityTreeRenderer* getEntityClipboardRenderer() { return &_entityClipboardRenderer; } Environment* getEnvironment() { return &_environment; } bool isMousePressed() const { return _mousePressed; } - bool isMouseHidden() const { return _mouseHidden; } + bool isMouseHidden() const { return _glWidget->cursor().shape() == Qt::BlankCursor; } + void setCursorVisible(bool visible); const glm::vec3& getMouseRayOrigin() const { return _mouseRayOrigin; } const glm::vec3& getMouseRayDirection() const { return _mouseRayDirection; } bool mouseOnScreen() const; @@ -309,8 +310,6 @@ public: QStringList getRunningScripts() { return _scriptEnginesHash.keys(); } ScriptEngine* getScriptEngine(QString scriptHash) { return _scriptEnginesHash.contains(scriptHash) ? _scriptEnginesHash[scriptHash] : NULL; } - - void setCursorVisible(bool visible); bool isLookingAtMyAvatar(Avatar* avatar); @@ -567,8 +566,6 @@ private: int _mouseDragStartedY; quint64 _lastMouseMove; bool _lastMouseMoveWasSimulated; - bool _mouseHidden; - bool _seenMouseMove; glm::vec3 _mouseRayOrigin; glm::vec3 _mouseRayDirection; diff --git a/interface/src/ui/FramelessDialog.cpp b/interface/src/ui/FramelessDialog.cpp index 22a0233d76..ab997a0a75 100644 --- a/interface/src/ui/FramelessDialog.cpp +++ b/interface/src/ui/FramelessDialog.cpp @@ -122,21 +122,21 @@ void FramelessDialog::mousePressEvent(QMouseEvent* mouseEvent) { if (hitLeft || hitRight) { _isResizing = true; _resizeInitialWidth = size().width(); - QApplication::setOverrideCursor(Qt::SizeHorCursor); + setCursor(Qt::SizeHorCursor); } } else { bool hitTop = (_position == POSITION_TOP) && (abs(mouseEvent->pos().y() - size().height()) < RESIZE_HANDLE_WIDTH); if (hitTop) { _isResizing = true; _resizeInitialWidth = size().height(); - QApplication::setOverrideCursor(Qt::SizeHorCursor); + setCursor(Qt::SizeHorCursor); } } } } void FramelessDialog::mouseReleaseEvent(QMouseEvent* mouseEvent) { - QApplication::restoreOverrideCursor(); + unsetCursor(); _isResizing = false; } From 426517b072322a0fc68d46a956e8224372a91f26 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 9 Dec 2014 17:11:01 -0800 Subject: [PATCH 315/502] fix a bug in MovingEntitiesOperator that would sometimes leave dangling entities --- libraries/entities/src/EntityItem.h | 3 --- libraries/entities/src/EntitySimulation.cpp | 1 - libraries/entities/src/EntityTree.cpp | 2 -- .../entities/src/MovingEntitiesOperator.cpp | 19 +------------------ .../entities/src/MovingEntitiesOperator.h | 2 -- 5 files changed, 1 insertion(+), 26 deletions(-) diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 915440ee6a..d5a4689657 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -227,8 +227,6 @@ public: float getSize() const; /// get maximum dimension in domain scale units (0.0 - 1.0) AACube getMaximumAACube() const; AACube getMinimumAACube() const; - AACube getOldMaximumAACube() const { return _oldMaximumAACube; } - void setOldMaximumAACube(const AACube& cube) { _oldMaximumAACube = cube; } AABox getAABox() const; /// axis aligned bounding box in domain scale units (0.0 - 1.0) static const QString DEFAULT_SCRIPT; @@ -347,7 +345,6 @@ protected: void setRadius(float value); AACubeShape _collisionShape; - AACube _oldMaximumAACube; // remember this so we know where the entity used to live in the tree // DirtyFlags are set whenever a property changes that the EntitySimulation needs to know about. uint32_t _dirtyFlags; // things that have changed from EXTERNAL changes (via script or packet) but NOT from simulation diff --git a/libraries/entities/src/EntitySimulation.cpp b/libraries/entities/src/EntitySimulation.cpp index 223df588d5..6d3b81715d 100644 --- a/libraries/entities/src/EntitySimulation.cpp +++ b/libraries/entities/src/EntitySimulation.cpp @@ -106,7 +106,6 @@ void EntitySimulation::sortEntitiesThatMoved() { if (moveOperator.hasMovingEntities()) { PerformanceTimer perfTimer("recurseTreeWithOperator"); _entityTree->recurseTreeWithOperator(&moveOperator); - moveOperator.finish(); } } diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 48ea2b7c07..17178ccbed 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -83,7 +83,6 @@ EntityItem* EntityTree::getOrCreateEntityItem(const EntityItemID& entityID, cons /// Adds a new entity item to the tree void EntityTree::postAddEntity(EntityItem* entity) { assert(entity); - entity->setOldMaximumAACube(entity->getMaximumAACube()); // check to see if we need to simulate this entity.. if (_simulation) { _simulation->addEntity(entity); @@ -138,7 +137,6 @@ bool EntityTree::updateEntityWithElement(EntityItem* entity, const EntityItemPro UpdateEntityOperator theOperator(this, containingElement, entity, properties); recurseTreeWithOperator(&theOperator); - entity->setOldMaximumAACube(entity->getMaximumAACube()); _isDirty = true; if (_simulation && entity->getDirtyFlags() != 0) { diff --git a/libraries/entities/src/MovingEntitiesOperator.cpp b/libraries/entities/src/MovingEntitiesOperator.cpp index 86b8de7b10..1ec67967b6 100644 --- a/libraries/entities/src/MovingEntitiesOperator.cpp +++ b/libraries/entities/src/MovingEntitiesOperator.cpp @@ -52,14 +52,10 @@ MovingEntitiesOperator::~MovingEntitiesOperator() { void MovingEntitiesOperator::addEntityToMoveList(EntityItem* entity, const AACube& newCube) { EntityTreeElement* oldContainingElement = _tree->getContainingElement(entity->getEntityItemID()); AABox newCubeClamped = newCube.clamp(0.0f, 1.0f); - AACube oldCube = entity->getOldMaximumAACube(); - AABox oldCubeClamped = oldCube.clamp(0.0f, 1.0f); if (_wantDebug) { qDebug() << "MovingEntitiesOperator::addEntityToMoveList() -----------------------------"; - qDebug() << " oldCube:" << oldCube; qDebug() << " newCube:" << newCube; - qDebug() << " oldCubeClamped:" << oldCubeClamped; qDebug() << " newCubeClamped:" << newCubeClamped; if (oldContainingElement) { qDebug() << " oldContainingElement:" << oldContainingElement->getAACube(); @@ -86,9 +82,7 @@ void MovingEntitiesOperator::addEntityToMoveList(EntityItem* entity, const AACub details.entity = entity; details.oldFound = false; details.newFound = false; - details.oldCube = oldCube; details.newCube = newCube; - details.oldCubeClamped = oldCubeClamped; details.newCubeClamped = newCubeClamped; _entitiesToMove << details; _lookingCount++; @@ -97,7 +91,6 @@ void MovingEntitiesOperator::addEntityToMoveList(EntityItem* entity, const AACub qDebug() << "MovingEntitiesOperator::addEntityToMoveList() -----------------------------"; qDebug() << " details.entity:" << details.entity->getEntityItemID(); qDebug() << " details.oldContainingElementCube:" << details.oldContainingElementCube; - qDebug() << " details.oldCube:" << details.oldCube; qDebug() << " details.newCube:" << details.newCube; qDebug() << " details.newCubeClamped:" << details.newCubeClamped; qDebug() << " _lookingCount:" << _lookingCount; @@ -130,17 +123,14 @@ bool MovingEntitiesOperator::shouldRecurseSubTree(OctreeElement* element) { qDebug() << " element:" << element->getAACube(); qDebug() << " details.entity:" << details.entity->getEntityItemID(); qDebug() << " details.oldContainingElementCube:" << details.oldContainingElementCube; - qDebug() << " details.oldCube:" << details.oldCube; qDebug() << " details.newCube:" << details.newCube; qDebug() << " details.newCubeClamped:" << details.newCubeClamped; - qDebug() << " elementCube.contains(details.oldCube)" << elementCube.contains(details.oldCube); qDebug() << " elementCube.contains(details.newCube)" << elementCube.contains(details.newCube); - qDebug() << " elementCube.contains(details.oldCubeClamped)" << elementCube.contains(details.oldCubeClamped); qDebug() << " elementCube.contains(details.newCubeClamped)" << elementCube.contains(details.newCubeClamped); qDebug() << "--------------------------------------------------------------------------"; } - if (elementCube.contains(details.oldCubeClamped) || elementCube.contains(details.newCubeClamped)) { + if (elementCube.contains(details.oldContainingElementCube) || elementCube.contains(details.newCubeClamped)) { containsEntity = true; break; // if it contains at least one, we're good to go } @@ -179,7 +169,6 @@ bool MovingEntitiesOperator::preRecursion(OctreeElement* element) { qDebug() << " details.entity:" << details.entity->getEntityItemID(); qDebug() << " details.oldContainingElementCube:" << details.oldContainingElementCube; qDebug() << " entityTreeElement:" << entityTreeElement; - qDebug() << " details.oldCube:" << details.oldCube; qDebug() << " details.newCube:" << details.newCube; qDebug() << " details.newCubeClamped:" << details.newCubeClamped; qDebug() << " _lookingCount:" << _lookingCount; @@ -291,9 +280,3 @@ OctreeElement* MovingEntitiesOperator::possiblyCreateChildAt(OctreeElement* elem } return NULL; } - -void MovingEntitiesOperator::finish() { - foreach(const EntityToMoveDetails& details, _entitiesToMove) { - details.entity->setOldMaximumAACube(details.newCube); - } -} diff --git a/libraries/entities/src/MovingEntitiesOperator.h b/libraries/entities/src/MovingEntitiesOperator.h index bddf5da450..fefda3328e 100644 --- a/libraries/entities/src/MovingEntitiesOperator.h +++ b/libraries/entities/src/MovingEntitiesOperator.h @@ -17,7 +17,6 @@ public: EntityItem* entity; AACube oldCube; AACube newCube; - AABox oldCubeClamped; AABox newCubeClamped; EntityTreeElement* oldContainingElement; AACube oldContainingElementCube; @@ -43,7 +42,6 @@ public: virtual bool postRecursion(OctreeElement* element); virtual OctreeElement* possiblyCreateChildAt(OctreeElement* element, int childIndex); bool hasMovingEntities() const { return _entitiesToMove.size() > 0; } - void finish(); private: EntityTree* _tree; QSet _entitiesToMove; From 96c3a0edbd5455b6709320b14d9efa1091608fda Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Tue, 9 Dec 2014 17:39:05 -0800 Subject: [PATCH 316/502] option to suppress lobby text for now, defaults to true --- examples/lobby.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/examples/lobby.js b/examples/lobby.js index 9e454eccc9..4ab2841c0e 100644 --- a/examples/lobby.js +++ b/examples/lobby.js @@ -15,6 +15,7 @@ var panelWall = false; var orbShell = false; var reticle = false; var descriptionText = false; +var showText = false; // used for formating the description text, in meters var textWidth = 4; @@ -312,7 +313,7 @@ function handleLookAt(pickRay) { var actionLocation = locations[panelIndex]; if (actionLocation.description == "") { - Overlays.editOverlay(descriptionText, { text: actionLocation.name, visible: true }); + Overlays.editOverlay(descriptionText, { text: actionLocation.name, visible: showText }); } else { // handle line wrapping var allWords = actionLocation.description.split(" "); @@ -344,7 +345,7 @@ function handleLookAt(pickRay) { } } formatedDescription += currentGoodLine; - Overlays.editOverlay(descriptionText, { text: formatedDescription, visible: true }); + Overlays.editOverlay(descriptionText, { text: formatedDescription, visible: showText }); } } else { Overlays.editOverlay(descriptionText, { text: "", visible: false }); From 43dc35d549db1438c8fb927698848ae6841d31f5 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 9 Dec 2014 17:53:23 -0800 Subject: [PATCH 317/502] Use correct mouse coordinate --- interface/src/Application.cpp | 20 ++++++++++---------- interface/src/ui/ApplicationOverlay.cpp | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 8a89444734..4ad8e87204 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1128,7 +1128,8 @@ void Application::keyPressEvent(QKeyEvent* event) { if (!event->isAutoRepeat()) { // this starts an HFActionEvent HFActionEvent startActionEvent(HFActionEvent::startType(), - _myCamera.computeViewPickRay(0.5f, 0.5f)); + _myCamera.computePickRay(getTrueMouseX(), + getTrueMouseY())); sendEvent(this, &startActionEvent); } @@ -1219,10 +1220,11 @@ void Application::keyReleaseEvent(QKeyEvent* event) { case Qt::Key_Space: { if (!event->isAutoRepeat()) { // this ends the HFActionEvent - HFActionEvent endActionEvent(HFActionEvent::endType(), _myCamera.computeViewPickRay(0.5f, 0.5f)); + HFActionEvent endActionEvent(HFActionEvent::endType(), + _myCamera.computePickRay(getTrueMouseX(), + getTrueMouseY())); sendEvent(this, &endActionEvent); } - break; } case Qt::Key_Escape: { @@ -1231,7 +1233,6 @@ void Application::keyReleaseEvent(QKeyEvent* event) { HFBackEvent endBackEvent(HFBackEvent::endType()); sendEvent(this, &endBackEvent); } - break; } default: @@ -1256,7 +1257,7 @@ void Application::mouseMoveEvent(QMouseEvent* event, unsigned int deviceID) { _lastMouseMove = usecTimestampNow(); } - if (!_aboutToQuit) { + if (_aboutToQuit) { return; } @@ -1267,6 +1268,7 @@ void Application::mouseMoveEvent(QMouseEvent* event, unsigned int deviceID) { if (_controllerScriptingInterface.isMouseCaptured()) { return; } + } void Application::mousePressEvent(QMouseEvent* event, unsigned int deviceID) { @@ -2297,21 +2299,19 @@ void Application::updateCursor(float deltaTime) { bool hideMouse = false; bool underMouse = _glWidget->underMouse(); - static const int HIDE_CURSOR_TIMEOUT = 1 * USECS_PER_SECOND; // 1 second + static const int HIDE_CURSOR_TIMEOUT = 3 * USECS_PER_SECOND; // 3 second int elapsed = usecTimestampNow() - _lastMouseMove; if ((elapsed > HIDE_CURSOR_TIMEOUT && underMouse) || (OculusManager::isConnected() && Menu::getInstance()->isOptionChecked(MenuOption::EnableVRMode))) { hideMouse = true; } - if (hideMouse != isMouseHidden()) { - setCursorVisible(!hideMouse); - } + setCursorVisible(!hideMouse); } void Application::setCursorVisible(bool visible) { if (visible) { - _glWidget->setCursor(Qt::ArrowCursor); + _glWidget->unsetCursor(); } else { _glWidget->setCursor(Qt::BlankCursor); } diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 602e99ac31..f4e0c9769d 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -536,7 +536,7 @@ void ApplicationOverlay::renderPointers() { glm::vec2 screenPos = sphericalToScreen(glm::vec2(yaw, -pitch)); position = QPoint(screenPos.x, screenPos.y); - QCursor::setPos(application->getGLWidget()->mapToGlobal(position)); + application->getGLWidget()->cursor().setPos(application->getGLWidget()->mapToGlobal(position)); } _reticlePosition[MOUSE] = position; From 01c13cd6f114fcc36b1e03c70c24d077142c5e1e Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 9 Dec 2014 17:58:17 -0800 Subject: [PATCH 318/502] Fix the broken shadows by simply calling the needed setViewTransform which is used for rendering the ENitites and avatars --- interface/src/Application.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 3824185f52..ba2f806c29 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2874,8 +2874,13 @@ void Application::updateShadowMap() { // store view matrix without translation, which we'll use for precision-sensitive objects updateUntranslatedViewMatrix(); - // TODO: assign an equivalent viewTransform object to the application to match the current path which uses glMatrixStack - // setViewTransform(viewTransform); + + // Equivalent to what is happening with _untranslatedViewMatrix and the _viewMatrixTranslation + // the viewTransofmr object is updatded with the correct values and saved, + // this is what is used for rendering the Entities and avatars + Transform viewTransform; + viewTransform.setRotation(rotation); + setViewTransform(viewTransform); glEnable(GL_POLYGON_OFFSET_FILL); glPolygonOffset(1.1f, 4.0f); // magic numbers courtesy http://www.eecs.berkeley.edu/~ravir/6160/papers/shadowmaps.ppt From dc4c9cd545db08fccfeaaa9f18f98d4cba123bff Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 9 Dec 2014 18:00:14 -0800 Subject: [PATCH 319/502] Correctly Hide/Show cursor --- interface/src/Application.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 4ad8e87204..facdeb59ec 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2311,9 +2311,15 @@ void Application::updateCursor(float deltaTime) { void Application::setCursorVisible(bool visible) { if (visible) { - _glWidget->unsetCursor(); + if (overrideCursor() != NULL) { + restoreOverrideCursor(); + } } else { - _glWidget->setCursor(Qt::BlankCursor); + if (overrideCursor() != NULL) { + changeOverrideCursor(Qt::BlankCursor); + } else { + setOverrideCursor(Qt::BlankCursor); + } } } From 628046f13cac685286d7e9a6e2f295e199e8027c Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 9 Dec 2014 18:26:59 -0800 Subject: [PATCH 320/502] potential fix to crash on windows startup --- libraries/networking/src/ReceivedPacketProcessor.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libraries/networking/src/ReceivedPacketProcessor.cpp b/libraries/networking/src/ReceivedPacketProcessor.cpp index 59e1ecd456..db4c97f8d6 100644 --- a/libraries/networking/src/ReceivedPacketProcessor.cpp +++ b/libraries/networking/src/ReceivedPacketProcessor.cpp @@ -44,7 +44,9 @@ bool ReceivedPacketProcessor::process() { NetworkPacket& packet = _packets.front(); // get the oldest packet NetworkPacket temporary = packet; // make a copy of the packet in case the vector is resized on us _packets.erase(_packets.begin()); // remove the oldest packet - _nodePacketCounts[temporary.getNode()->getUUID()]--; + if (!temporary.getNode().isNull()) { + _nodePacketCounts[temporary.getNode()->getUUID()]--; + } unlock(); // let others add to the packets processPacket(temporary.getNode(), temporary.getByteArray()); // process our temporary copy midProcess(); From 136c3a2cce423a0dd7b90b5255da531a084626b2 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 9 Dec 2014 18:32:53 -0800 Subject: [PATCH 321/502] Replace 2D and 3D text overlay textWidth() method with textSize() --- interface/src/ui/overlays/Overlays.cpp | 8 ++++---- interface/src/ui/overlays/Overlays.h | 4 ++-- interface/src/ui/overlays/Text3DOverlay.cpp | 20 ++++++++++++++++---- interface/src/ui/overlays/Text3DOverlay.h | 2 +- interface/src/ui/overlays/TextOverlay.cpp | 16 ++++++++++++++-- interface/src/ui/overlays/TextOverlay.h | 2 +- libraries/shared/src/RegisteredMetaTypes.cpp | 12 ++++++++++++ libraries/shared/src/RegisteredMetaTypes.h | 4 ++++ 8 files changed, 54 insertions(+), 14 deletions(-) diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 25e667e56c..ace4ecf353 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -432,19 +432,19 @@ bool Overlays::isLoaded(unsigned int id) { return thisOverlay->isLoaded(); } -float Overlays::textWidth(unsigned int id, const QString& text) const { +QSizeF Overlays::textSize(unsigned int id, const QString& text) const { Overlay* thisOverlay = _overlays2D[id]; if (thisOverlay) { if (typeid(*thisOverlay) == typeid(TextOverlay)) { - return static_cast(thisOverlay)->textWidth(text); + return static_cast(thisOverlay)->textSize(text); } } else { thisOverlay = _overlays3D[id]; if (thisOverlay) { if (typeid(*thisOverlay) == typeid(Text3DOverlay)) { - return static_cast(thisOverlay)->textWidth(text); + return static_cast(thisOverlay)->textSize(text); } } } - return 0.0f; + return QSizeF(0.0f, 0.0f); } diff --git a/interface/src/ui/overlays/Overlays.h b/interface/src/ui/overlays/Overlays.h index 7acc2c7878..fb2c936a64 100644 --- a/interface/src/ui/overlays/Overlays.h +++ b/interface/src/ui/overlays/Overlays.h @@ -85,9 +85,9 @@ public slots: /// returns whether the overlay's assets are loaded or not bool isLoaded(unsigned int id); - /// returns the width of the given text in the specified overlay if it is a text overlay: in pixels if it is a 2D text + /// returns the size of the given text in the specified overlay if it is a text overlay: in pixels if it is a 2D text /// overlay; in meters if it is a 3D text overlay - float textWidth(unsigned int id, const QString& text) const; + QSizeF textSize(unsigned int id, const QString& text) const; private: QMap _overlays2D; diff --git a/interface/src/ui/overlays/Text3DOverlay.cpp b/interface/src/ui/overlays/Text3DOverlay.cpp index 2e80fae8a0..7db73dda8c 100644 --- a/interface/src/ui/overlays/Text3DOverlay.cpp +++ b/interface/src/ui/overlays/Text3DOverlay.cpp @@ -236,11 +236,23 @@ Text3DOverlay* Text3DOverlay::createClone() const { return new Text3DOverlay(this);; } -float Text3DOverlay::textWidth(const QString& text) const { +QSizeF Text3DOverlay::textSize(const QString& text) const { + QFont font(SANS_FONT_FAMILY, FIXED_FONT_POINT_SIZE); // Same font properties as render() QFontMetrics fontMetrics(font); - float scaleFactor = _lineHeight * LINE_SCALE_RATIO / (float)FIXED_FONT_POINT_SIZE; - return scaleFactor * (float)fontMetrics.width(qPrintable(text)); + const float TEXT_SCALE_ADJUST = 1.02f; // Experimentally detemined for the specified font + const int TEXT_HEIGHT_ADJUST = -6; + float scaleFactor = _lineHeight * TEXT_SCALE_ADJUST * LINE_SCALE_RATIO / (float)FIXED_FONT_POINT_SIZE; + + QStringList lines = text.split(QRegExp("\r\n|\r|\n")); + + float width = 0.0f; + for (int i = 0; i < lines.count(); i += 1) { + width = std::max(width, scaleFactor * (float)fontMetrics.width(qPrintable(lines[i]))); + } + + float height = lines.count() * scaleFactor * (float)(fontMetrics.height() + TEXT_HEIGHT_ADJUST); + + return QSizeF(width, height); } - diff --git a/interface/src/ui/overlays/Text3DOverlay.h b/interface/src/ui/overlays/Text3DOverlay.h index d74131391a..aefda852db 100644 --- a/interface/src/ui/overlays/Text3DOverlay.h +++ b/interface/src/ui/overlays/Text3DOverlay.h @@ -51,7 +51,7 @@ public: virtual void setProperties(const QScriptValue& properties); virtual QScriptValue getProperty(const QString& property); - float textWidth(const QString& text) const; // Meters + QSizeF textSize(const QString& test) const; // Meters virtual Text3DOverlay* createClone() const; diff --git a/interface/src/ui/overlays/TextOverlay.cpp b/interface/src/ui/overlays/TextOverlay.cpp index 272c9bc916..b603e1f3bf 100644 --- a/interface/src/ui/overlays/TextOverlay.cpp +++ b/interface/src/ui/overlays/TextOverlay.cpp @@ -169,8 +169,20 @@ QScriptValue TextOverlay::getProperty(const QString& property) { return Overlay2D::getProperty(property); } -float TextOverlay::textWidth(const QString& text) const { +QSizeF TextOverlay::textSize(const QString& text) const { + QFont font(SANS_FONT_FAMILY, _fontSize, DEFAULT_FONT_WEIGHT); // Same font properties as render() QFontMetrics fontMetrics(font); - return fontMetrics.width(qPrintable(text)); + const int TEXT_HEIGHT_ADJUST = -2; // Experimentally determined for the specified font + + QStringList lines = text.split(QRegExp("\r\n|\r|\n")); + + int width = 0; + for (int i = 0; i < lines.count(); i += 1) { + width = std::max(width, fontMetrics.width(qPrintable(lines[i]))); + } + + int height = lines.count() * (fontMetrics.height() + TEXT_HEIGHT_ADJUST); + + return QSizeF(width, height); } diff --git a/interface/src/ui/overlays/TextOverlay.h b/interface/src/ui/overlays/TextOverlay.h index 754faea2bc..793d705d3c 100644 --- a/interface/src/ui/overlays/TextOverlay.h +++ b/interface/src/ui/overlays/TextOverlay.h @@ -59,7 +59,7 @@ public: virtual TextOverlay* createClone() const; virtual QScriptValue getProperty(const QString& property); - float textWidth(const QString& text) const; // Pixels + QSizeF textSize(const QString& test) const; // Pixels private: QString _text; diff --git a/libraries/shared/src/RegisteredMetaTypes.cpp b/libraries/shared/src/RegisteredMetaTypes.cpp index cc8db8783f..4099384aea 100644 --- a/libraries/shared/src/RegisteredMetaTypes.cpp +++ b/libraries/shared/src/RegisteredMetaTypes.cpp @@ -39,6 +39,7 @@ void registerMetaTypes(QScriptEngine* engine) { qScriptRegisterMetaType(engine, pickRayToScriptValue, pickRayFromScriptValue); qScriptRegisterMetaType(engine, collisionToScriptValue, collisionFromScriptValue); qScriptRegisterMetaType(engine, quuidToScriptValue, quuidFromScriptValue); + qScriptRegisterMetaType(engine, qSizeFToScriptValue, qSizeFFromScriptValue); } QScriptValue vec4toScriptValue(QScriptEngine* engine, const glm::vec4& vec4) { @@ -206,3 +207,14 @@ void quuidFromScriptValue(const QScriptValue& object, QUuid& uuid) { uuid = fromString; } +QScriptValue qSizeFToScriptValue(QScriptEngine* engine, const QSizeF& qSizeF) { + QScriptValue obj = engine->newObject(); + obj.setProperty("width", qSizeF.width()); + obj.setProperty("height", qSizeF.height()); + return obj; +} + +void qSizeFFromScriptValue(const QScriptValue& object, QSizeF& qSizeF) { + qSizeF.setWidth(object.property("width").toVariant().toFloat()); + qSizeF.setHeight(object.property("height").toVariant().toFloat()); +} diff --git a/libraries/shared/src/RegisteredMetaTypes.h b/libraries/shared/src/RegisteredMetaTypes.h index b9278c9f2d..ca4898b65c 100644 --- a/libraries/shared/src/RegisteredMetaTypes.h +++ b/libraries/shared/src/RegisteredMetaTypes.h @@ -81,4 +81,8 @@ void collisionFromScriptValue(const QScriptValue &object, Collision& collision); QScriptValue quuidToScriptValue(QScriptEngine* engine, const QUuid& uuid); void quuidFromScriptValue(const QScriptValue& object, QUuid& uuid); +//Q_DECLARE_METATYPE(QSizeF) // Don't need to to this becase it's arleady a meta type +QScriptValue qSizeFToScriptValue(QScriptEngine* engine, const QSizeF& qSizeF); +void qSizeFFromScriptValue(const QScriptValue& object, QSizeF& qSizeF); + #endif // hifi_RegisteredMetaTypes_h From 3ea3a497c64396bef3444a00fa2bca447797e964 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 9 Dec 2014 18:33:29 -0800 Subject: [PATCH 322/502] Update scripts to use new textSize() method --- examples/editModels.js | 4 ++-- examples/lobby.js | 2 +- examples/newEditEntities.js | 4 ++-- examples/virtualKeyboard.js | 10 +++++----- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/examples/editModels.js b/examples/editModels.js index c961d55bed..e0ade3b6a3 100644 --- a/examples/editModels.js +++ b/examples/editModels.js @@ -1191,8 +1191,8 @@ var toolBar = (function () { visible: false }); - menuItemWidth = Math.max(Overlays.textWidth(loadURLMenuItem, "Model URL"), - Overlays.textWidth(loadFileMenuItem, "Model File")) + 20; + menuItemWidth = Math.max(Overlays.textSize(loadURLMenuItem, "Model URL").width, + Overlays.textSize(loadFileMenuItem, "Model File").width) + 20; Overlays.editOverlay(loadURLMenuItem, { width: menuItemWidth }); Overlays.editOverlay(loadFileMenuItem, { width: menuItemWidth }); diff --git a/examples/lobby.js b/examples/lobby.js index dd011d08a4..a1f161d8a5 100644 --- a/examples/lobby.js +++ b/examples/lobby.js @@ -331,7 +331,7 @@ function handleLookAt(pickRay) { } else { currentTestLine = allWords[currentTestWord]; } - var lineLength = Overlays.textWidth(descriptionText, currentTestLine); + var lineLength = Overlays.textSize(descriptionText, currentTestLine).width; if (lineLength < textWidth || wordsOnLine == 0) { wordsFormated++; currentTestWord++; diff --git a/examples/newEditEntities.js b/examples/newEditEntities.js index 43e304a76d..e9f42bf74c 100644 --- a/examples/newEditEntities.js +++ b/examples/newEditEntities.js @@ -159,8 +159,8 @@ var toolBar = (function () { visible: false }); - menuItemWidth = Math.max(Overlays.textWidth(loadURLMenuItem, "Model URL"), - Overlays.textWidth(loadFileMenuItem, "Model File")) + 20; + menuItemWidth = Math.max(Overlays.textSize(loadURLMenuItem, "Model URL").width, + Overlays.textSize(loadFileMenuItem, "Model File").width) + 20; Overlays.editOverlay(loadURLMenuItem, { width: menuItemWidth }); Overlays.editOverlay(loadFileMenuItem, { width: menuItemWidth }); diff --git a/examples/virtualKeyboard.js b/examples/virtualKeyboard.js index c89dc6fb04..ce793c6ea0 100644 --- a/examples/virtualKeyboard.js +++ b/examples/virtualKeyboard.js @@ -80,7 +80,7 @@ function updateTextOverlay() { var textLines = textText.split("\n"); var maxLineWidth = 0; for (textLine in textLines) { - var lineWidth = Overlays.textWidth(text, textLines[textLine]); + var lineWidth = Overlays.textSize(text, textLines[textLine]).width; if (lineWidth > maxLineWidth) { maxLineWidth = lineWidth; } @@ -92,7 +92,7 @@ function updateTextOverlay() { Overlays.editOverlay(text, {text: textText, font: {size: textFontSize}, topMargin: topMargin}); var maxLineWidth = 0; for (textLine in textLines) { - var lineWidth = Overlays.textWidth(text, textLines[textLine]); + var lineWidth = Overlays.textSize(text, textLines[textLine]).width; if (lineWidth > maxLineWidth) { maxLineWidth = lineWidth; } @@ -122,18 +122,18 @@ keyboard.onKeyRelease = function(event) { var textLines = textText.split("\n"); var maxLineWidth = 0; for (textLine in textLines) { - var lineWidth = Overlays.textWidth(textSizeMeasureOverlay, textLines[textLine]); + var lineWidth = Overlays.textSize(textSizeMeasureOverlay, textLines[textLine]).width; if (lineWidth > maxLineWidth) { maxLineWidth = lineWidth; } } var usernameLine = "--" + GlobalServices.myUsername; - var usernameWidth = Overlays.textWidth(textSizeMeasureOverlay, usernameLine); + var usernameWidth = Overlays.textSize(textSizeMeasureOverlay, usernameLine).width; if (maxLineWidth < usernameWidth) { maxLineWidth = usernameWidth; } else { var spaceableWidth = maxLineWidth - usernameWidth; - var spaceWidth = Overlays.textWidth(textSizeMeasureOverlay, " "); + var spaceWidth = Overlays.textSize(textSizeMeasureOverlay, " ").width; var numberOfSpaces = Math.floor(spaceableWidth / spaceWidth); for (var i = 0; i < numberOfSpaces; i++) { usernameLine = " " + usernameLine; From 8cf50b71eaa086e50c28a9606ddb2914c67b6694 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 9 Dec 2014 19:18:37 -0800 Subject: [PATCH 323/502] Update some comments to reflect changes --- interface/src/entities/RenderableTextEntityItem.cpp | 2 +- interface/src/ui/overlays/Text3DOverlay.cpp | 2 +- interface/src/ui/overlays/TextOverlay.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/interface/src/entities/RenderableTextEntityItem.cpp b/interface/src/entities/RenderableTextEntityItem.cpp index f790f6fa35..4059ee5751 100644 --- a/interface/src/entities/RenderableTextEntityItem.cpp +++ b/interface/src/entities/RenderableTextEntityItem.cpp @@ -63,7 +63,7 @@ void RenderableTextEntityItem::render(RenderArgs* args) { const int FIXED_FONT_SCALING_RATIO = FIXED_FONT_POINT_SIZE * 40.0f; // this is a ratio determined through experimentation - // Same font properties as textWidth() + // Same font properties as textSize() TextRenderer* textRenderer = TextRenderer::getInstance(SANS_FONT_FAMILY, FIXED_FONT_POINT_SIZE); float maxHeight = (float)textRenderer->calculateHeight("Xy") * LINE_SCALE_RATIO; diff --git a/interface/src/ui/overlays/Text3DOverlay.cpp b/interface/src/ui/overlays/Text3DOverlay.cpp index 7db73dda8c..41e36cb396 100644 --- a/interface/src/ui/overlays/Text3DOverlay.cpp +++ b/interface/src/ui/overlays/Text3DOverlay.cpp @@ -108,7 +108,7 @@ void Text3DOverlay::render(RenderArgs* args) { const int FIXED_FONT_SCALING_RATIO = FIXED_FONT_POINT_SIZE * 40.0f; // this is a ratio determined through experimentation - // Same font properties as textWidth() + // Same font properties as textSize() TextRenderer* textRenderer = TextRenderer::getInstance(SANS_FONT_FAMILY, FIXED_FONT_POINT_SIZE); float maxHeight = (float)textRenderer->calculateHeight("Xy") * LINE_SCALE_RATIO; diff --git a/interface/src/ui/overlays/TextOverlay.cpp b/interface/src/ui/overlays/TextOverlay.cpp index b603e1f3bf..ae8a7cbcfe 100644 --- a/interface/src/ui/overlays/TextOverlay.cpp +++ b/interface/src/ui/overlays/TextOverlay.cpp @@ -77,7 +77,7 @@ void TextOverlay::render(RenderArgs* args) { glVertex2f(_bounds.left(), _bounds.bottom()); glEnd(); - // Same font properties as textWidth() + // Same font properties as textSize() TextRenderer* textRenderer = TextRenderer::getInstance(SANS_FONT_FAMILY, _fontSize, DEFAULT_FONT_WEIGHT); const int leftAdjust = -1; // required to make text render relative to left edge of bounds From 88a576f84635e30c18087e4d569eaf25f8857e36 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 9 Dec 2014 19:35:38 -0800 Subject: [PATCH 324/502] fix action events for gamepad; --- interface/src/scripting/JoystickScriptingInterface.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/interface/src/scripting/JoystickScriptingInterface.cpp b/interface/src/scripting/JoystickScriptingInterface.cpp index 039dc40961..cbc4fee81c 100644 --- a/interface/src/scripting/JoystickScriptingInterface.cpp +++ b/interface/src/scripting/JoystickScriptingInterface.cpp @@ -132,8 +132,10 @@ void JoystickScriptingInterface::update() { : HFActionEvent::endType(); // global action events fire in the center of the screen - HFActionEvent actionEvent(actionType, - Application::getInstance()->getCamera()->computeViewPickRay(0.5f, 0.5f)); + Application* app = Application::getInstance(); + PickRay pickRay = app->getCamera()->computeViewPickRay(app->getTrueMouseX(), + app->getTrueMouseY()); + HFActionEvent actionEvent(actionType, pickRay); qApp->sendEvent(qApp, &actionEvent); } From 74a6fd5ca7970076068851b9c618952517067299 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 9 Dec 2014 20:03:00 -0800 Subject: [PATCH 325/502] fix joystick pick --- interface/src/scripting/JoystickScriptingInterface.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/scripting/JoystickScriptingInterface.cpp b/interface/src/scripting/JoystickScriptingInterface.cpp index cbc4fee81c..0490b1f704 100644 --- a/interface/src/scripting/JoystickScriptingInterface.cpp +++ b/interface/src/scripting/JoystickScriptingInterface.cpp @@ -133,8 +133,8 @@ void JoystickScriptingInterface::update() { // global action events fire in the center of the screen Application* app = Application::getInstance(); - PickRay pickRay = app->getCamera()->computeViewPickRay(app->getTrueMouseX(), - app->getTrueMouseY()); + PickRay pickRay = app->getCamera()->computePickRay(app->getTrueMouseX(), + app->getTrueMouseY()); HFActionEvent actionEvent(actionType, pickRay); qApp->sendEvent(qApp, &actionEvent); } From 10a6428277f16d997dc13005f83bffe4a966595e Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 10 Dec 2014 10:37:54 -0800 Subject: [PATCH 326/502] Chess board correct orientation --- examples/playChess.js | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/playChess.js b/examples/playChess.js index 57ed24f342..faa32f6cda 100644 --- a/examples/playChess.js +++ b/examples/playChess.js @@ -86,6 +86,7 @@ ChessGame.Board = (function(position, scale) { modelURL: ChessGame.BOARD.modelURL, position: this.position, dimensions: this.dimensions, + rotation: ChessGame.BOARD.rotation, userData: this.buildUserDataString() } this.entity = null; From f2ed1337b5b0417a83b78fe9793c9d88dcf355f7 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 10 Dec 2014 11:04:32 -0800 Subject: [PATCH 327/502] fix ray picking output distance to be meters --- libraries/octree/src/Octree.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libraries/octree/src/Octree.cpp b/libraries/octree/src/Octree.cpp index d6aad45b0d..0c92125b53 100644 --- a/libraries/octree/src/Octree.cpp +++ b/libraries/octree/src/Octree.cpp @@ -728,6 +728,10 @@ bool Octree::findRayIntersection(const glm::vec3& origin, const glm::vec3& direc } recurseTreeWithOperation(findRayIntersectionOp, &args); + + if (args.found) { + args.distance *= (float)(TREE_SCALE); // scale back up to meters + } if (gotLock) { unlock(); From 6fa1d7a7bd8c3247d432bdf9780d92d8e518ecd8 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 10 Dec 2014 14:08:59 -0800 Subject: [PATCH 328/502] Update lobby to start on the second row --- examples/lobby.js | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/examples/lobby.js b/examples/lobby.js index dd011d08a4..51b8feea7a 100644 --- a/examples/lobby.js +++ b/examples/lobby.js @@ -71,6 +71,23 @@ function textOverlayPosition() { Vec3.multiply(Quat.getUp(Camera.orientation), TEXT_DISTANCE_DOWN)); } +var panelLocationOrder = [ + 7, 8, 9, 10, 11, 12, 13, + 0, 1, 2, 3, 4, 5, 6, + 14, 15, 16, 17, 18, 19, 20 +]; + +// Location index is 0-based +function locationIndexToPanelIndex(locationIndex) { + return panelLocationOrder.indexOf(locationIndex) + 1; +} + +// Panel index is 1-based +function panelIndexToLocationIndex(panelIndex) { + return panelLocationOrder[panelIndex - 1]; +} + + var MAX_NUM_PANELS = 21; var DRONE_VOLUME = 0.3; @@ -168,7 +185,8 @@ function changeLobbyTextures() { }; for (var j = 0; j < NUM_PANELS; j++) { - textureProp["textures"]["file" + (j + 1)] = "http:" + locations[j].thumbnail_url + panelIndex = locationIndexToPanelIndex(j); + textureProp["textures"]["file" + panelIndex] = "http:" + locations[j].thumbnail_url; }; Overlays.editOverlay(panelWall, textureProp); @@ -259,12 +277,13 @@ function actionStartEvent(event) { var panelStringIndex = panelName.indexOf("Panel"); if (panelStringIndex != -1) { - var panelIndex = parseInt(panelName.slice(5)) - 1; - if (panelIndex < locations.length) { - var actionLocation = locations[panelIndex]; + var panelIndex = parseInt(panelName.slice(5)); + var locationIndex = panelIndexToLocationIndex(panelIndex); + if (locationIndex < locations.length) { + var actionLocation = locations[locationIndex]; print("Jumping to " + actionLocation.name + " at " + actionLocation.path - + " in " + actionLocation.domain.name + " after click on panel " + panelIndex); + + " in " + actionLocation.domain.name + " after click on panel " + panelIndex + " with location index " + locationIndex); Window.location = actionLocation; maybeCleanupLobby(); @@ -308,9 +327,10 @@ function handleLookAt(pickRay) { var panelName = result.extraInfo; var panelStringIndex = panelName.indexOf("Panel"); if (panelStringIndex != -1) { - var panelIndex = parseInt(panelName.slice(5)) - 1; - if (panelIndex < locations.length) { - var actionLocation = locations[panelIndex]; + var panelIndex = parseInt(panelName.slice(5)); + var locationIndex = panelIndexToLocationIndex(panelIndex); + if (locationIndex< locations.length) { + var actionLocation = locations[locationIndex]; if (actionLocation.description == "") { Overlays.editOverlay(descriptionText, { text: actionLocation.name, visible: true }); From a24acb485807a0fe757bf07c196a1a6c42ae25fa Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 10 Dec 2014 14:15:43 -0800 Subject: [PATCH 329/502] Fix style --- examples/lobby.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/lobby.js b/examples/lobby.js index 51b8feea7a..702fb732a1 100644 --- a/examples/lobby.js +++ b/examples/lobby.js @@ -329,7 +329,7 @@ function handleLookAt(pickRay) { if (panelStringIndex != -1) { var panelIndex = parseInt(panelName.slice(5)); var locationIndex = panelIndexToLocationIndex(panelIndex); - if (locationIndex< locations.length) { + if (locationIndex < locations.length) { var actionLocation = locations[locationIndex]; if (actionLocation.description == "") { From 961f6290741d2aee25ea7be659b1b00aaa48aef1 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 10 Dec 2014 14:26:42 -0800 Subject: [PATCH 330/502] Fix indentation, 4 -> 2 --- examples/lobby.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/examples/lobby.js b/examples/lobby.js index a72e61a629..5c856f1862 100644 --- a/examples/lobby.js +++ b/examples/lobby.js @@ -70,16 +70,14 @@ var panelLocationOrder = [ // Location index is 0-based function locationIndexToPanelIndex(locationIndex) { - return panelLocationOrder.indexOf(locationIndex) + 1; + return panelLocationOrder.indexOf(locationIndex) + 1; } // Panel index is 1-based function panelIndexToLocationIndex(panelIndex) { - return panelLocationOrder[panelIndex - 1]; + return panelLocationOrder[panelIndex - 1]; } - - var MAX_NUM_PANELS = 21; var DRONE_VOLUME = 0.3; From 9c9bfeed333d75b18f6e8b182fffc9da67e43dc1 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 10 Dec 2014 14:27:37 -0800 Subject: [PATCH 331/502] Add missing 'var' to local variable --- examples/lobby.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/lobby.js b/examples/lobby.js index 5c856f1862..647202bebc 100644 --- a/examples/lobby.js +++ b/examples/lobby.js @@ -158,7 +158,7 @@ function changeLobbyTextures() { }; for (var j = 0; j < NUM_PANELS; j++) { - panelIndex = locationIndexToPanelIndex(j); + var panelIndex = locationIndexToPanelIndex(j); textureProp["textures"]["file" + panelIndex] = "http:" + locations[j].thumbnail_url; }; From c57fd15bc9d480ebb8cbe8d001e2a37d1ac58331 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 10 Dec 2014 15:22:48 -0800 Subject: [PATCH 332/502] Rather than loading the entire FBX file into a byte array, read it straight from the QNetworkReply. --- interface/src/renderer/GeometryCache.cpp | 12 ++--- libraries/fbx/src/FBXReader.cpp | 56 +++++++++++++++++------- libraries/fbx/src/FBXReader.h | 6 +++ 3 files changed, 53 insertions(+), 21 deletions(-) diff --git a/interface/src/renderer/GeometryCache.cpp b/interface/src/renderer/GeometryCache.cpp index 2d876a287f..d753901243 100644 --- a/interface/src/renderer/GeometryCache.cpp +++ b/interface/src/renderer/GeometryCache.cpp @@ -841,14 +841,14 @@ void GeometryReader::run() { if (urlValid) { // Let's read the binaries from the network - QByteArray fileBinary = _reply->readAll(); - if (fileBinary.isEmpty() || fileBinary.isNull()) { - throw QString("Read File binary is empty?!"); - } - FBXGeometry fbxgeo; if (_url.path().toLower().endsWith(".svo")) { + QByteArray fileBinary = _reply->readAll(); + if (fileBinary.isEmpty() || fileBinary.isNull()) { + throw QString("Read File binary is empty?!"); + } fbxgeo = readSVO(fileBinary); + } else if (_url.path().toLower().endsWith(".fbx")) { bool grabLightmaps = true; float lightmapLevel = 1.0f; @@ -860,7 +860,7 @@ void GeometryReader::run() { } else if (_url.path().toLower().endsWith("palaceoforinthilian4.fbx")) { lightmapLevel = 3.5f; } - fbxgeo = readFBX(fileBinary, _mapping, grabLightmaps, lightmapLevel); + fbxgeo = readFBX(_reply, _mapping, grabLightmaps, lightmapLevel); } QMetaObject::invokeMethod(geometry.data(), "setGeometry", Q_ARG(const FBXGeometry&, fbxgeo)); } else { diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index d52d342d78..84c9d1800f 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -138,7 +138,15 @@ static int fbxGeometryMetaTypeId = qRegisterMetaType(); static int fbxAnimationFrameMetaTypeId = qRegisterMetaType(); static int fbxAnimationFrameVectorMetaTypeId = qRegisterMetaType >(); -template QVariant readBinaryArray(QDataStream& in) { +template int streamSize() { + return sizeof(T); +} + +template int streamSize() { + return 1; +} + +template QVariant readBinaryArray(QDataStream& in, int& position) { quint32 arrayLength; quint32 encoding; quint32 compressedLength; @@ -146,6 +154,7 @@ template QVariant readBinaryArray(QDataStream& in) { in >> arrayLength; in >> encoding; in >> compressedLength; + position += sizeof(quint32) * 3; QVector values; const unsigned int DEFLATE_ENCODING = 1; @@ -154,6 +163,7 @@ template QVariant readBinaryArray(QDataStream& in) { QByteArray compressed(sizeof(quint32) + compressedLength, 0); *((quint32*)compressed.data()) = qToBigEndian(arrayLength * sizeof(T)); in.readRawData(compressed.data() + sizeof(quint32), compressedLength); + position += compressedLength; QByteArray uncompressed = qUncompress(compressed); QDataStream uncompressedIn(uncompressed); uncompressedIn.setByteOrder(QDataStream::LittleEndian); @@ -167,65 +177,74 @@ template QVariant readBinaryArray(QDataStream& in) { for (quint32 i = 0; i < arrayLength; i++) { T value; in >> value; + position += streamSize(); values.append(value); } } return QVariant::fromValue(values); } -QVariant parseBinaryFBXProperty(QDataStream& in) { +QVariant parseBinaryFBXProperty(QDataStream& in, int& position) { char ch; in.device()->getChar(&ch); + position++; switch (ch) { case 'Y': { qint16 value; in >> value; + position += sizeof(qint16); return QVariant::fromValue(value); } case 'C': { bool value; in >> value; + position++; return QVariant::fromValue(value); } case 'I': { qint32 value; in >> value; + position += sizeof(qint32); return QVariant::fromValue(value); } case 'F': { float value; in >> value; + position += sizeof(float); return QVariant::fromValue(value); } case 'D': { double value; in >> value; + position += sizeof(double); return QVariant::fromValue(value); } case 'L': { qint64 value; in >> value; + position += sizeof(qint64); return QVariant::fromValue(value); } case 'f': { - return readBinaryArray(in); + return readBinaryArray(in, position); } case 'd': { - return readBinaryArray(in); + return readBinaryArray(in, position); } case 'l': { - return readBinaryArray(in); + return readBinaryArray(in, position); } case 'i': { - return readBinaryArray(in); + return readBinaryArray(in, position); } case 'b': { - return readBinaryArray(in); + return readBinaryArray(in, position); } case 'S': case 'R': { quint32 length; in >> length; + position += sizeof(quint32) + length; return QVariant::fromValue(in.device()->read(length)); } default: @@ -233,8 +252,8 @@ QVariant parseBinaryFBXProperty(QDataStream& in) { } } -FBXNode parseBinaryFBXNode(QDataStream& in) { - quint32 endOffset; +FBXNode parseBinaryFBXNode(QDataStream& in, int& position) { + qint32 endOffset; quint32 propertyCount; quint32 propertyListLength; quint8 nameLength; @@ -243,21 +262,23 @@ FBXNode parseBinaryFBXNode(QDataStream& in) { in >> propertyCount; in >> propertyListLength; in >> nameLength; + position += sizeof(quint32) * 3 + sizeof(quint8); FBXNode node; - const unsigned int MIN_VALID_OFFSET = 40; + const int MIN_VALID_OFFSET = 40; if (endOffset < MIN_VALID_OFFSET || nameLength == 0) { // use a null name to indicate a null node return node; } node.name = in.device()->read(nameLength); + position += nameLength; for (quint32 i = 0; i < propertyCount; i++) { - node.properties.append(parseBinaryFBXProperty(in)); + node.properties.append(parseBinaryFBXProperty(in, position)); } - while (endOffset > in.device()->pos()) { - FBXNode child = parseBinaryFBXNode(in); + while (endOffset > position) { + FBXNode child = parseBinaryFBXNode(in, position); if (child.name.isNull()) { return node; @@ -416,11 +437,12 @@ FBXNode parseFBX(QIODevice* device) { // skip the rest of the header const int HEADER_SIZE = 27; in.skipRawData(HEADER_SIZE); + int position = HEADER_SIZE; // parse the top-level node FBXNode top; while (device->bytesAvailable()) { - FBXNode next = parseBinaryFBXNode(in); + FBXNode next = parseBinaryFBXNode(in, position); if (next.name.isNull()) { return top; @@ -2516,7 +2538,11 @@ QByteArray writeMapping(const QVariantHash& mapping) { FBXGeometry readFBX(const QByteArray& model, const QVariantHash& mapping, bool loadLightmaps, float lightmapLevel) { QBuffer buffer(const_cast(&model)); buffer.open(QIODevice::ReadOnly); - return extractFBXGeometry(parseFBX(&buffer), mapping, loadLightmaps, lightmapLevel); + return readFBX(&buffer, mapping, loadLightmaps, lightmapLevel); +} + +FBXGeometry readFBX(QIODevice* device, const QVariantHash& mapping, bool loadLightmaps, float lightmapLevel) { + return extractFBXGeometry(parseFBX(device), mapping, loadLightmaps, lightmapLevel); } bool addMeshVoxelsOperation(OctreeElement* element, void* extraData) { diff --git a/libraries/fbx/src/FBXReader.h b/libraries/fbx/src/FBXReader.h index 659893c128..736da3a349 100644 --- a/libraries/fbx/src/FBXReader.h +++ b/libraries/fbx/src/FBXReader.h @@ -24,6 +24,8 @@ #include #include +class QIODevice; + class FBXNode; typedef QList FBXNodeList; @@ -272,6 +274,10 @@ QByteArray writeMapping(const QVariantHash& mapping); /// \exception QString if an error occurs in parsing FBXGeometry readFBX(const QByteArray& model, const QVariantHash& mapping, bool loadLightmaps = true, float lightmapLevel = 1.0f); +/// Reads FBX geometry from the supplied model and mapping data. +/// \exception QString if an error occurs in parsing +FBXGeometry readFBX(QIODevice* device, const QVariantHash& mapping, bool loadLightmaps = true, float lightmapLevel = 1.0f); + /// Reads SVO geometry from the supplied model data. FBXGeometry readSVO(const QByteArray& model); From eda7432868f950cb995456ee14b756abb3f0b736 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 10 Dec 2014 15:37:48 -0800 Subject: [PATCH 333/502] remove audio reflector --- examples/audioReflectorTools.js | 844 ------------------------------ interface/src/Application.cpp | 18 - interface/src/Application.h | 3 - interface/src/AudioReflector.cpp | 868 ------------------------------- interface/src/AudioReflector.h | 254 --------- interface/src/MetavoxelSystem.h | 1 + interface/src/ui/Stats.cpp | 98 ---- 7 files changed, 1 insertion(+), 2085 deletions(-) delete mode 100644 examples/audioReflectorTools.js delete mode 100644 interface/src/AudioReflector.cpp delete mode 100644 interface/src/AudioReflector.h diff --git a/examples/audioReflectorTools.js b/examples/audioReflectorTools.js deleted file mode 100644 index c5a88edd57..0000000000 --- a/examples/audioReflectorTools.js +++ /dev/null @@ -1,844 +0,0 @@ -// -// audioReflectorTools.js -// hifi -// -// Created by Brad Hefta-Gaub on 2/14/14. -// Copyright (c) 2014 HighFidelity, Inc. All rights reserved. -// -// Tools for manipulating the attributes of the AudioReflector behavior -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -Script.include("libraries/globals.js"); - -var delayScale = 100.0; -var fanoutScale = 10.0; -var speedScale = 20; -var factorScale = 5.0; -var localFactorScale = 1.0; -var reflectiveScale = 100.0; -var diffusionScale = 100.0; -var absorptionScale = 100.0; -var combFilterScale = 50.0; -var originalScale = 2.0; -var echoesScale = 2.0; - -// these three properties are bound together, if you change one, the others will also change -var reflectiveRatio = AudioReflector.getReflectiveRatio(); -var diffusionRatio = AudioReflector.getDiffusionRatio(); -var absorptionRatio = AudioReflector.getAbsorptionRatio(); - -var reflectiveThumbX; -var diffusionThumbX; -var absorptionThumbX; - -function setReflectiveRatio(reflective) { - var total = diffusionRatio + absorptionRatio + (reflective / reflectiveScale); - diffusionRatio = diffusionRatio / total; - absorptionRatio = absorptionRatio / total; - reflectiveRatio = (reflective / reflectiveScale) / total; - updateRatioValues(); -} - -function setDiffusionRatio(diffusion) { - var total = (diffusion / diffusionScale) + absorptionRatio + reflectiveRatio; - diffusionRatio = (diffusion / diffusionScale) / total; - absorptionRatio = absorptionRatio / total; - reflectiveRatio = reflectiveRatio / total; - updateRatioValues(); -} - -function setAbsorptionRatio(absorption) { - var total = diffusionRatio + (absorption / absorptionScale) + reflectiveRatio; - diffusionRatio = diffusionRatio / total; - absorptionRatio = (absorption / absorptionScale) / total; - reflectiveRatio = reflectiveRatio / total; - updateRatioValues(); -} - -function updateRatioSliders() { - reflectiveThumbX = reflectiveMinThumbX + ((reflectiveMaxThumbX - reflectiveMinThumbX) * reflectiveRatio); - diffusionThumbX = diffusionMinThumbX + ((diffusionMaxThumbX - diffusionMinThumbX) * diffusionRatio); - absorptionThumbX = absorptionMinThumbX + ((absorptionMaxThumbX - absorptionMinThumbX) * absorptionRatio); - - Overlays.editOverlay(reflectiveThumb, { x: reflectiveThumbX } ); - Overlays.editOverlay(diffusionThumb, { x: diffusionThumbX } ); - Overlays.editOverlay(absorptionThumb, { x: absorptionThumbX } ); -} - -function updateRatioValues() { - AudioReflector.setReflectiveRatio(reflectiveRatio); - AudioReflector.setDiffusionRatio(diffusionRatio); - AudioReflector.setAbsorptionRatio(absorptionRatio); -} - -var topY = 250; -var sliderHeight = 35; - -var delayY = topY; -topY += sliderHeight; -var delayLabel = Overlays.addOverlay("text", { - x: 40, - y: delayY, - width: 60, - height: sliderHeight, - color: { red: 0, green: 0, blue: 0}, - textColor: { red: 255, green: 255, blue: 255}, - topMargin: 12, - leftMargin: 5, - text: "Delay:" - }); - -var delaySlider = Overlays.addOverlay("image", { - // alternate form of expressing bounds - bounds: { x: 100, y: delayY, width: 150, height: sliderHeight}, - subImage: { x: 46, y: 0, width: 200, height: 71 }, - imageURL: HIFI_PUBLIC_BUCKET + "images/slider.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1 - }); - - -var delayMinThumbX = 110; -var delayMaxThumbX = delayMinThumbX + 110; -var delayThumbX = delayMinThumbX + ((delayMaxThumbX - delayMinThumbX) * (AudioReflector.getPreDelay() / delayScale)); -var delayThumb = Overlays.addOverlay("image", { - x: delayThumbX, - y: delayY + 9, - width: 18, - height: 17, - imageURL: HIFI_PUBLIC_BUCKET + "images/thumb.png", - color: { red: 255, green: 0, blue: 0}, - alpha: 1 - }); - -var fanoutY = topY; -topY += sliderHeight; - -var fanoutLabel = Overlays.addOverlay("text", { - x: 40, - y: fanoutY, - width: 60, - height: sliderHeight, - color: { red: 0, green: 0, blue: 0}, - textColor: { red: 255, green: 255, blue: 255}, - topMargin: 12, - leftMargin: 5, - text: "Fanout:" - }); - -var fanoutSlider = Overlays.addOverlay("image", { - // alternate form of expressing bounds - bounds: { x: 100, y: fanoutY, width: 150, height: sliderHeight}, - subImage: { x: 46, y: 0, width: 200, height: 71 }, - imageURL: HIFI_PUBLIC_BUCKET + "images/slider.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1 - }); - - -var fanoutMinThumbX = 110; -var fanoutMaxThumbX = fanoutMinThumbX + 110; -var fanoutThumbX = fanoutMinThumbX + ((fanoutMaxThumbX - fanoutMinThumbX) * (AudioReflector.getDiffusionFanout() / fanoutScale)); -var fanoutThumb = Overlays.addOverlay("image", { - x: fanoutThumbX, - y: fanoutY + 9, - width: 18, - height: 17, - imageURL: HIFI_PUBLIC_BUCKET + "images/thumb.png", - color: { red: 255, green: 255, blue: 0}, - alpha: 1 - }); - - -var speedY = topY; -topY += sliderHeight; - -var speedLabel = Overlays.addOverlay("text", { - x: 40, - y: speedY, - width: 60, - height: sliderHeight, - color: { red: 0, green: 0, blue: 0}, - textColor: { red: 255, green: 255, blue: 255}, - topMargin: 6, - leftMargin: 5, - text: "Speed\nin ms/m:" - }); - -var speedSlider = Overlays.addOverlay("image", { - // alternate form of expressing bounds - bounds: { x: 100, y: speedY, width: 150, height: sliderHeight}, - subImage: { x: 46, y: 0, width: 200, height: 71 }, - imageURL: HIFI_PUBLIC_BUCKET + "images/slider.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1 - }); - - -var speedMinThumbX = 110; -var speedMaxThumbX = speedMinThumbX + 110; -var speedThumbX = speedMinThumbX + ((speedMaxThumbX - speedMinThumbX) * (AudioReflector.getSoundMsPerMeter() / speedScale)); -var speedThumb = Overlays.addOverlay("image", { - x: speedThumbX, - y: speedY+9, - width: 18, - height: 17, - imageURL: HIFI_PUBLIC_BUCKET + "images/thumb.png", - color: { red: 0, green: 255, blue: 0}, - alpha: 1 - }); - -var factorY = topY; -topY += sliderHeight; - -var factorLabel = Overlays.addOverlay("text", { - x: 40, - y: factorY, - width: 60, - height: sliderHeight, - color: { red: 0, green: 0, blue: 0}, - textColor: { red: 255, green: 255, blue: 255}, - topMargin: 6, - leftMargin: 5, - text: "Attenuation\nFactor:" - }); - - -var factorSlider = Overlays.addOverlay("image", { - // alternate form of expressing bounds - bounds: { x: 100, y: factorY, width: 150, height: sliderHeight}, - subImage: { x: 46, y: 0, width: 200, height: 71 }, - imageURL: HIFI_PUBLIC_BUCKET + "images/slider.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1 - }); - - -var factorMinThumbX = 110; -var factorMaxThumbX = factorMinThumbX + 110; -var factorThumbX = factorMinThumbX + ((factorMaxThumbX - factorMinThumbX) * (AudioReflector.getDistanceAttenuationScalingFactor() / factorScale)); -var factorThumb = Overlays.addOverlay("image", { - x: factorThumbX, - y: factorY+9, - width: 18, - height: 17, - imageURL: HIFI_PUBLIC_BUCKET + "images/thumb.png", - color: { red: 0, green: 0, blue: 255}, - alpha: 1 - }); - -var localFactorY = topY; -topY += sliderHeight; - -var localFactorLabel = Overlays.addOverlay("text", { - x: 40, - y: localFactorY, - width: 60, - height: sliderHeight, - color: { red: 0, green: 0, blue: 0}, - textColor: { red: 255, green: 255, blue: 255}, - topMargin: 6, - leftMargin: 5, - text: "Local\nFactor:" - }); - - -var localFactorSlider = Overlays.addOverlay("image", { - // alternate form of expressing bounds - bounds: { x: 100, y: localFactorY, width: 150, height: sliderHeight}, - subImage: { x: 46, y: 0, width: 200, height: 71 }, - imageURL: HIFI_PUBLIC_BUCKET + "images/slider.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1 - }); - - -var localFactorMinThumbX = 110; -var localFactorMaxThumbX = localFactorMinThumbX + 110; -var localFactorThumbX = localFactorMinThumbX + ((localFactorMaxThumbX - localFactorMinThumbX) * (AudioReflector.getLocalAudioAttenuationFactor() / localFactorScale)); -var localFactorThumb = Overlays.addOverlay("image", { - x: localFactorThumbX, - y: localFactorY+9, - width: 18, - height: 17, - imageURL: HIFI_PUBLIC_BUCKET + "images/thumb.png", - color: { red: 0, green: 128, blue: 128}, - alpha: 1 - }); - -var combFilterY = topY; -topY += sliderHeight; - -var combFilterLabel = Overlays.addOverlay("text", { - x: 40, - y: combFilterY, - width: 60, - height: sliderHeight, - color: { red: 0, green: 0, blue: 0}, - textColor: { red: 255, green: 255, blue: 255}, - topMargin: 6, - leftMargin: 5, - text: "Comb Filter\nWindow:" - }); - - -var combFilterSlider = Overlays.addOverlay("image", { - // alternate form of expressing bounds - bounds: { x: 100, y: combFilterY, width: 150, height: sliderHeight}, - subImage: { x: 46, y: 0, width: 200, height: 71 }, - imageURL: HIFI_PUBLIC_BUCKET + "images/slider.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1 - }); - - -var combFilterMinThumbX = 110; -var combFilterMaxThumbX = combFilterMinThumbX + 110; -var combFilterThumbX = combFilterMinThumbX + ((combFilterMaxThumbX - combFilterMinThumbX) * (AudioReflector.getCombFilterWindow() / combFilterScale)); -var combFilterThumb = Overlays.addOverlay("image", { - x: combFilterThumbX, - y: combFilterY+9, - width: 18, - height: 17, - imageURL: HIFI_PUBLIC_BUCKET + "images/thumb.png", - color: { red: 128, green: 128, blue: 0}, - alpha: 1 - }); - - -var reflectiveY = topY; -topY += sliderHeight; - -var reflectiveLabel = Overlays.addOverlay("text", { - x: 40, - y: reflectiveY, - width: 60, - height: sliderHeight, - color: { red: 0, green: 0, blue: 0}, - textColor: { red: 255, green: 255, blue: 255}, - topMargin: 6, - leftMargin: 5, - text: "Reflective\nRatio:" - }); - - -var reflectiveSlider = Overlays.addOverlay("image", { - // alternate form of expressing bounds - bounds: { x: 100, y: reflectiveY, width: 150, height: sliderHeight}, - subImage: { x: 46, y: 0, width: 200, height: 71 }, - imageURL: HIFI_PUBLIC_BUCKET + "images/slider.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1 - }); - - -var reflectiveMinThumbX = 110; -var reflectiveMaxThumbX = reflectiveMinThumbX + 110; -reflectiveThumbX = reflectiveMinThumbX + ((reflectiveMaxThumbX - reflectiveMinThumbX) * AudioReflector.getReflectiveRatio()); -var reflectiveThumb = Overlays.addOverlay("image", { - x: reflectiveThumbX, - y: reflectiveY+9, - width: 18, - height: 17, - imageURL: HIFI_PUBLIC_BUCKET + "images/thumb.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1 - }); - -var diffusionY = topY; -topY += sliderHeight; - -var diffusionLabel = Overlays.addOverlay("text", { - x: 40, - y: diffusionY, - width: 60, - height: sliderHeight, - color: { red: 0, green: 0, blue: 0}, - textColor: { red: 255, green: 255, blue: 255}, - topMargin: 6, - leftMargin: 5, - text: "Diffusion\nRatio:" - }); - - -var diffusionSlider = Overlays.addOverlay("image", { - // alternate form of expressing bounds - bounds: { x: 100, y: diffusionY, width: 150, height: sliderHeight}, - subImage: { x: 46, y: 0, width: 200, height: 71 }, - imageURL: HIFI_PUBLIC_BUCKET + "images/slider.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1 - }); - - -var diffusionMinThumbX = 110; -var diffusionMaxThumbX = diffusionMinThumbX + 110; -diffusionThumbX = diffusionMinThumbX + ((diffusionMaxThumbX - diffusionMinThumbX) * AudioReflector.getDiffusionRatio()); -var diffusionThumb = Overlays.addOverlay("image", { - x: diffusionThumbX, - y: diffusionY+9, - width: 18, - height: 17, - imageURL: HIFI_PUBLIC_BUCKET + "images/thumb.png", - color: { red: 0, green: 255, blue: 255}, - alpha: 1 - }); - -var absorptionY = topY; -topY += sliderHeight; - -var absorptionLabel = Overlays.addOverlay("text", { - x: 40, - y: absorptionY, - width: 60, - height: sliderHeight, - color: { red: 0, green: 0, blue: 0}, - textColor: { red: 255, green: 255, blue: 255}, - topMargin: 6, - leftMargin: 5, - text: "Absorption\nRatio:" - }); - - -var absorptionSlider = Overlays.addOverlay("image", { - // alternate form of expressing bounds - bounds: { x: 100, y: absorptionY, width: 150, height: sliderHeight}, - subImage: { x: 46, y: 0, width: 200, height: 71 }, - imageURL: HIFI_PUBLIC_BUCKET + "images/slider.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1 - }); - - -var absorptionMinThumbX = 110; -var absorptionMaxThumbX = absorptionMinThumbX + 110; -absorptionThumbX = absorptionMinThumbX + ((absorptionMaxThumbX - absorptionMinThumbX) * AudioReflector.getAbsorptionRatio()); -var absorptionThumb = Overlays.addOverlay("image", { - x: absorptionThumbX, - y: absorptionY+9, - width: 18, - height: 17, - imageURL: HIFI_PUBLIC_BUCKET + "images/thumb.png", - color: { red: 255, green: 0, blue: 255}, - alpha: 1 - }); - -var originalY = topY; -topY += sliderHeight; - -var originalLabel = Overlays.addOverlay("text", { - x: 40, - y: originalY, - width: 60, - height: sliderHeight, - color: { red: 0, green: 0, blue: 0}, - textColor: { red: 255, green: 255, blue: 255}, - topMargin: 6, - leftMargin: 5, - text: "Original\nMix:" - }); - - -var originalSlider = Overlays.addOverlay("image", { - // alternate form of expressing bounds - bounds: { x: 100, y: originalY, width: 150, height: sliderHeight}, - subImage: { x: 46, y: 0, width: 200, height: 71 }, - imageURL: HIFI_PUBLIC_BUCKET + "images/slider.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1 - }); - - -var originalMinThumbX = 110; -var originalMaxThumbX = originalMinThumbX + 110; -var originalThumbX = originalMinThumbX + ((originalMaxThumbX - originalMinThumbX) * (AudioReflector.getOriginalSourceAttenuation() / originalScale)); -var originalThumb = Overlays.addOverlay("image", { - x: originalThumbX, - y: originalY+9, - width: 18, - height: 17, - imageURL: HIFI_PUBLIC_BUCKET + "images/thumb.png", - color: { red: 128, green: 128, blue: 0}, - alpha: 1 - }); - -var echoesY = topY; -topY += sliderHeight; - -var echoesLabel = Overlays.addOverlay("text", { - x: 40, - y: echoesY, - width: 60, - height: sliderHeight, - color: { red: 0, green: 0, blue: 0}, - textColor: { red: 255, green: 255, blue: 255}, - topMargin: 6, - leftMargin: 5, - text: "Echoes\nMix:" - }); - - -var echoesSlider = Overlays.addOverlay("image", { - // alternate form of expressing bounds - bounds: { x: 100, y: echoesY, width: 150, height: sliderHeight}, - subImage: { x: 46, y: 0, width: 200, height: 71 }, - imageURL: HIFI_PUBLIC_BUCKET + "images/slider.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1 - }); - - -var echoesMinThumbX = 110; -var echoesMaxThumbX = echoesMinThumbX + 110; -var echoesThumbX = echoesMinThumbX + ((echoesMaxThumbX - echoesMinThumbX) * (AudioReflector.getEchoesAttenuation() / echoesScale)); -var echoesThumb = Overlays.addOverlay("image", { - x: echoesThumbX, - y: echoesY+9, - width: 18, - height: 17, - imageURL: HIFI_PUBLIC_BUCKET + "images/thumb.png", - color: { red: 128, green: 128, blue: 0}, - alpha: 1 - }); - - -// When our script shuts down, we should clean up all of our overlays -function scriptEnding() { - Overlays.deleteOverlay(factorLabel); - Overlays.deleteOverlay(factorThumb); - Overlays.deleteOverlay(factorSlider); - - Overlays.deleteOverlay(combFilterLabel); - Overlays.deleteOverlay(combFilterThumb); - Overlays.deleteOverlay(combFilterSlider); - - Overlays.deleteOverlay(localFactorLabel); - Overlays.deleteOverlay(localFactorThumb); - Overlays.deleteOverlay(localFactorSlider); - - Overlays.deleteOverlay(speedLabel); - Overlays.deleteOverlay(speedThumb); - Overlays.deleteOverlay(speedSlider); - - Overlays.deleteOverlay(delayLabel); - Overlays.deleteOverlay(delayThumb); - Overlays.deleteOverlay(delaySlider); - - Overlays.deleteOverlay(fanoutLabel); - Overlays.deleteOverlay(fanoutThumb); - Overlays.deleteOverlay(fanoutSlider); - - Overlays.deleteOverlay(reflectiveLabel); - Overlays.deleteOverlay(reflectiveThumb); - Overlays.deleteOverlay(reflectiveSlider); - - Overlays.deleteOverlay(diffusionLabel); - Overlays.deleteOverlay(diffusionThumb); - Overlays.deleteOverlay(diffusionSlider); - - Overlays.deleteOverlay(absorptionLabel); - Overlays.deleteOverlay(absorptionThumb); - Overlays.deleteOverlay(absorptionSlider); - - Overlays.deleteOverlay(echoesLabel); - Overlays.deleteOverlay(echoesThumb); - Overlays.deleteOverlay(echoesSlider); - - Overlays.deleteOverlay(originalLabel); - Overlays.deleteOverlay(originalThumb); - Overlays.deleteOverlay(originalSlider); - -} -Script.scriptEnding.connect(scriptEnding); - - -var count = 0; - -// Our update() function is called at approximately 60fps, and we will use it to animate our various overlays -function update(deltaTime) { - count++; -} -Script.update.connect(update); - - -// The slider is handled in the mouse event callbacks. -var movingSliderDelay = false; -var movingSliderFanout = false; -var movingSliderSpeed = false; -var movingSliderFactor = false; -var movingSliderCombFilter = false; -var movingSliderLocalFactor = false; -var movingSliderReflective = false; -var movingSliderDiffusion = false; -var movingSliderAbsorption = false; -var movingSliderOriginal = false; -var movingSliderEchoes = false; - -var thumbClickOffsetX = 0; -function mouseMoveEvent(event) { - if (movingSliderDelay) { - newThumbX = event.x - thumbClickOffsetX; - if (newThumbX < delayMinThumbX) { - newThumbX = delayMinThumbX; - } - if (newThumbX > delayMaxThumbX) { - newThumbX = delayMaxThumbX; - } - Overlays.editOverlay(delayThumb, { x: newThumbX } ); - var delay = ((newThumbX - delayMinThumbX) / (delayMaxThumbX - delayMinThumbX)) * delayScale; - AudioReflector.setPreDelay(delay); - } - if (movingSliderFanout) { - newThumbX = event.x - thumbClickOffsetX; - if (newThumbX < fanoutMinThumbX) { - newThumbX = fanoutMinThumbX; - } - if (newThumbX > fanoutMaxThumbX) { - newThumbX = fanoutMaxThumbX; - } - Overlays.editOverlay(fanoutThumb, { x: newThumbX } ); - var fanout = Math.round(((newThumbX - fanoutMinThumbX) / (fanoutMaxThumbX - fanoutMinThumbX)) * fanoutScale); - AudioReflector.setDiffusionFanout(fanout); - } - if (movingSliderSpeed) { - newThumbX = event.x - thumbClickOffsetX; - if (newThumbX < speedMinThumbX) { - newThumbX = speedMminThumbX; - } - if (newThumbX > speedMaxThumbX) { - newThumbX = speedMaxThumbX; - } - Overlays.editOverlay(speedThumb, { x: newThumbX } ); - var speed = ((newThumbX - speedMinThumbX) / (speedMaxThumbX - speedMinThumbX)) * speedScale; - AudioReflector.setSoundMsPerMeter(speed); - } - if (movingSliderFactor) { - newThumbX = event.x - thumbClickOffsetX; - if (newThumbX < factorMinThumbX) { - newThumbX = factorMminThumbX; - } - if (newThumbX > factorMaxThumbX) { - newThumbX = factorMaxThumbX; - } - Overlays.editOverlay(factorThumb, { x: newThumbX } ); - var factor = ((newThumbX - factorMinThumbX) / (factorMaxThumbX - factorMinThumbX)) * factorScale; - AudioReflector.setDistanceAttenuationScalingFactor(factor); - } - if (movingSliderCombFilter) { - newThumbX = event.x - thumbClickOffsetX; - if (newThumbX < combFilterMinThumbX) { - newThumbX = combFilterMminThumbX; - } - if (newThumbX > combFilterMaxThumbX) { - newThumbX = combFilterMaxThumbX; - } - Overlays.editOverlay(combFilterThumb, { x: newThumbX } ); - var combFilter = ((newThumbX - combFilterMinThumbX) / (combFilterMaxThumbX - combFilterMinThumbX)) * combFilterScale; - AudioReflector.setCombFilterWindow(combFilter); - } - if (movingSliderLocalFactor) { - newThumbX = event.x - thumbClickOffsetX; - if (newThumbX < localFactorMinThumbX) { - newThumbX = localFactorMminThumbX; - } - if (newThumbX > localFactorMaxThumbX) { - newThumbX = localFactorMaxThumbX; - } - Overlays.editOverlay(localFactorThumb, { x: newThumbX } ); - var localFactor = ((newThumbX - localFactorMinThumbX) / (localFactorMaxThumbX - localFactorMinThumbX)) * localFactorScale; - AudioReflector.setLocalAudioAttenuationFactor(localFactor); - } - - if (movingSliderAbsorption) { - newThumbX = event.x - thumbClickOffsetX; - if (newThumbX < absorptionMinThumbX) { - newThumbX = absorptionMminThumbX; - } - if (newThumbX > absorptionMaxThumbX) { - newThumbX = absorptionMaxThumbX; - } - Overlays.editOverlay(absorptionThumb, { x: newThumbX } ); - var absorption = ((newThumbX - absorptionMinThumbX) / (absorptionMaxThumbX - absorptionMinThumbX)) * absorptionScale; - setAbsorptionRatio(absorption); - } - - if (movingSliderReflective) { - newThumbX = event.x - thumbClickOffsetX; - if (newThumbX < reflectiveMinThumbX) { - newThumbX = reflectiveMminThumbX; - } - if (newThumbX > reflectiveMaxThumbX) { - newThumbX = reflectiveMaxThumbX; - } - Overlays.editOverlay(reflectiveThumb, { x: newThumbX } ); - var reflective = ((newThumbX - reflectiveMinThumbX) / (reflectiveMaxThumbX - reflectiveMinThumbX)) * reflectiveScale; - setReflectiveRatio(reflective); - } - - if (movingSliderDiffusion) { - newThumbX = event.x - thumbClickOffsetX; - if (newThumbX < diffusionMinThumbX) { - newThumbX = diffusionMminThumbX; - } - if (newThumbX > diffusionMaxThumbX) { - newThumbX = diffusionMaxThumbX; - } - Overlays.editOverlay(diffusionThumb, { x: newThumbX } ); - var diffusion = ((newThumbX - diffusionMinThumbX) / (diffusionMaxThumbX - diffusionMinThumbX)) * diffusionScale; - setDiffusionRatio(diffusion); - } - if (movingSliderEchoes) { - newThumbX = event.x - thumbClickOffsetX; - if (newThumbX < echoesMinThumbX) { - newThumbX = echoesMminThumbX; - } - if (newThumbX > echoesMaxThumbX) { - newThumbX = echoesMaxThumbX; - } - Overlays.editOverlay(echoesThumb, { x: newThumbX } ); - var echoes = ((newThumbX - echoesMinThumbX) / (echoesMaxThumbX - echoesMinThumbX)) * echoesScale; - AudioReflector.setEchoesAttenuation(echoes); - } - if (movingSliderOriginal) { - newThumbX = event.x - thumbClickOffsetX; - if (newThumbX < originalMinThumbX) { - newThumbX = originalMminThumbX; - } - if (newThumbX > originalMaxThumbX) { - newThumbX = originalMaxThumbX; - } - Overlays.editOverlay(originalThumb, { x: newThumbX } ); - var original = ((newThumbX - originalMinThumbX) / (originalMaxThumbX - originalMinThumbX)) * originalScale; - AudioReflector.setOriginalSourceAttenuation(original); - } - -} - -// we also handle click detection in our mousePressEvent() -function mousePressEvent(event) { - var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y}); - if (clickedOverlay == delayThumb) { - movingSliderDelay = true; - thumbClickOffsetX = event.x - delayThumbX; - } - if (clickedOverlay == fanoutThumb) { - movingSliderFanout = true; - thumbClickOffsetX = event.x - fanoutThumbX; - } - if (clickedOverlay == speedThumb) { - movingSliderSpeed = true; - thumbClickOffsetX = event.x - speedThumbX; - } - if (clickedOverlay == factorThumb) { - movingSliderFactor = true; - thumbClickOffsetX = event.x - factorThumbX; - } - if (clickedOverlay == localFactorThumb) { - movingSliderLocalFactor = true; - thumbClickOffsetX = event.x - localFactorThumbX; - } - if (clickedOverlay == combFilterThumb) { - movingSliderCombFilter = true; - thumbClickOffsetX = event.x - combFilterThumbX; - } - if (clickedOverlay == diffusionThumb) { - movingSliderDiffusion = true; - thumbClickOffsetX = event.x - diffusionThumbX; - } - if (clickedOverlay == absorptionThumb) { - movingSliderAbsorption = true; - thumbClickOffsetX = event.x - absorptionThumbX; - } - if (clickedOverlay == reflectiveThumb) { - movingSliderReflective = true; - thumbClickOffsetX = event.x - reflectiveThumbX; - } - if (clickedOverlay == originalThumb) { - movingSliderOriginal = true; - thumbClickOffsetX = event.x - originalThumbX; - } - if (clickedOverlay == echoesThumb) { - movingSliderEchoes = true; - thumbClickOffsetX = event.x - echoesThumbX; - } -} - -function mouseReleaseEvent(event) { - if (movingSliderDelay) { - movingSliderDelay = false; - var delay = ((newThumbX - delayMinThumbX) / (delayMaxThumbX - delayMinThumbX)) * delayScale; - AudioReflector.setPreDelay(delay); - delayThumbX = newThumbX; - } - if (movingSliderFanout) { - movingSliderFanout = false; - var fanout = Math.round(((newThumbX - fanoutMinThumbX) / (fanoutMaxThumbX - fanoutMinThumbX)) * fanoutScale); - AudioReflector.setDiffusionFanout(fanout); - fanoutThumbX = newThumbX; - } - if (movingSliderSpeed) { - movingSliderSpeed = false; - var speed = ((newThumbX - speedMinThumbX) / (speedMaxThumbX - speedMinThumbX)) * speedScale; - AudioReflector.setSoundMsPerMeter(speed); - speedThumbX = newThumbX; - } - if (movingSliderFactor) { - movingSliderFactor = false; - var factor = ((newThumbX - factorMinThumbX) / (factorMaxThumbX - factorMinThumbX)) * factorScale; - AudioReflector.setDistanceAttenuationScalingFactor(factor); - factorThumbX = newThumbX; - } - if (movingSliderCombFilter) { - movingSliderCombFilter = false; - var combFilter = ((newThumbX - combFilterMinThumbX) / (combFilterMaxThumbX - combFilterMinThumbX)) * combFilterScale; - AudioReflector.setCombFilterWindow(combFilter); - combFilterThumbX = newThumbX; - } - if (movingSliderLocalFactor) { - movingSliderLocalFactor = false; - var localFactor = ((newThumbX - localFactorMinThumbX) / (localFactorMaxThumbX - localFactorMinThumbX)) * localFactorScale; - AudioReflector.setLocalAudioAttenuationFactor(localFactor); - localFactorThumbX = newThumbX; - } - if (movingSliderReflective) { - movingSliderReflective = false; - var reflective = ((newThumbX - reflectiveMinThumbX) / (reflectiveMaxThumbX - reflectiveMinThumbX)) * reflectiveScale; - setReflectiveRatio(reflective); - reflectiveThumbX = newThumbX; - updateRatioSliders(); - } - if (movingSliderDiffusion) { - movingSliderDiffusion = false; - var diffusion = ((newThumbX - diffusionMinThumbX) / (diffusionMaxThumbX - diffusionMinThumbX)) * diffusionScale; - setDiffusionRatio(diffusion); - diffusionThumbX = newThumbX; - updateRatioSliders(); - } - if (movingSliderAbsorption) { - movingSliderAbsorption = false; - var absorption = ((newThumbX - absorptionMinThumbX) / (absorptionMaxThumbX - absorptionMinThumbX)) * absorptionScale; - setAbsorptionRatio(absorption); - absorptionThumbX = newThumbX; - updateRatioSliders(); - } - if (movingSliderEchoes) { - movingSliderEchoes = false; - var echoes = ((newThumbX - echoesMinThumbX) / (echoesMaxThumbX - echoesMinThumbX)) * echoesScale; - AudioReflector.setEchoesAttenuation(echoes); - echoesThumbX = newThumbX; - } - if (movingSliderOriginal) { - movingSliderOriginal = false; - var original = ((newThumbX - originalMinThumbX) / (originalMaxThumbX - originalMinThumbX)) * originalScale; - AudioReflector.setOriginalSourceAttenuation(original); - originalThumbX = newThumbX; - } -} - -Controller.mouseMoveEvent.connect(mouseMoveEvent); -Controller.mousePressEvent.connect(mousePressEvent); -Controller.mouseReleaseEvent.connect(mouseReleaseEvent); - diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index d773208ac0..34aae77868 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2034,17 +2034,6 @@ void Application::init() { connect(_rearMirrorTools, SIGNAL(shrinkView()), SLOT(shrinkMirrorView())); connect(_rearMirrorTools, SIGNAL(resetView()), SLOT(resetSensors())); - // set up our audio reflector - _audioReflector.setMyAvatar(getAvatar()); - _audioReflector.setVoxels(_voxels.getTree()); - _audioReflector.setAudio(getAudio()); - _audioReflector.setAvatarManager(&_avatarManager); - - connect(getAudio(), &Audio::processInboundAudio, &_audioReflector, &AudioReflector::processInboundAudio,Qt::DirectConnection); - connect(getAudio(), &Audio::processLocalAudio, &_audioReflector, &AudioReflector::processLocalAudio,Qt::DirectConnection); - connect(getAudio(), &Audio::preProcessOriginalInboundAudio, &_audioReflector, - &AudioReflector::preProcessOriginalInboundAudio,Qt::DirectConnection); - connect(getAudio(), &Audio::muteToggled, AudioDeviceScriptingInterface::getInstance(), &AudioDeviceScriptingInterface::muteToggled, Qt::DirectConnection); @@ -3064,12 +3053,6 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly, RenderAr glColor3f(1,0,0); _geometryCache.renderSphere(originSphereRadius, 15, 15); - // draw the audio reflector overlay - { - PerformanceTimer perfTimer("audio"); - _audioReflector.render(); - } - // Draw voxels if (Menu::getInstance()->isOptionChecked(MenuOption::Voxels)) { PerformanceTimer perfTimer("voxels"); @@ -3997,7 +3980,6 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri scriptEngine->registerGlobalObject("AudioDevice", AudioDeviceScriptingInterface::getInstance()); scriptEngine->registerGlobalObject("AnimationCache", &_animationCache); scriptEngine->registerGlobalObject("SoundCache", &SoundCache::getInstance()); - scriptEngine->registerGlobalObject("AudioReflector", &_audioReflector); scriptEngine->registerGlobalObject("Account", AccountScriptingInterface::getInstance()); scriptEngine->registerGlobalObject("Metavoxels", &_metavoxels); diff --git a/interface/src/Application.h b/interface/src/Application.h index 0f0bd91210..bcb4c01c27 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -42,7 +42,6 @@ #include "MainWindow.h" #include "Audio.h" -#include "AudioReflector.h" #include "Camera.h" #include "DatagramProcessor.h" #include "Environment.h" @@ -193,7 +192,6 @@ public: bool isThrottleRendering() const { return _glWidget->isThrottleRendering(); } MyAvatar* getAvatar() { return _myAvatar; } Audio* getAudio() { return &_audio; } - const AudioReflector* getAudioReflector() const { return &_audioReflector; } Camera* getCamera() { return &_myCamera; } ViewFrustum* getViewFrustum() { return &_viewFrustum; } ViewFrustum* getDisplayViewFrustum() { return &_displayViewFrustum; } @@ -635,7 +633,6 @@ private: Overlays _overlays; ApplicationOverlay _applicationOverlay; - AudioReflector _audioReflector; RunningScriptsWidget* _runningScriptsWidget; QHash _scriptEnginesHash; bool _runningScriptsWidgetWasVisible; diff --git a/interface/src/AudioReflector.cpp b/interface/src/AudioReflector.cpp deleted file mode 100644 index 8a23ecee79..0000000000 --- a/interface/src/AudioReflector.cpp +++ /dev/null @@ -1,868 +0,0 @@ -// -// AudioReflector.cpp -// interface -// -// Created by Brad Hefta-Gaub on 4/2/2014 -// Copyright (c) 2014 High Fidelity, Inc. All rights reserved. -// - -#include - -#include "AudioReflector.h" -#include "Menu.h" - -const float DEFAULT_PRE_DELAY = 20.0f; // this delay in msecs will always be added to all reflections -const float DEFAULT_MS_DELAY_PER_METER = 3.0f; -const float MINIMUM_ATTENUATION_TO_REFLECT = 1.0f / 256.0f; -const float DEFAULT_DISTANCE_SCALING_FACTOR = 2.0f; -const float MAXIMUM_DELAY_MS = 1000.0 * 20.0f; // stop reflecting after path is this long -const int DEFAULT_DIFFUSION_FANOUT = 5; -const unsigned int ABSOLUTE_MAXIMUM_BOUNCE_COUNT = 10; -const float DEFAULT_LOCAL_ATTENUATION_FACTOR = 0.125; -const float DEFAULT_COMB_FILTER_WINDOW = 0.05f; //ms delay differential to avoid - -const float SLIGHTLY_SHORT = 0.999f; // slightly inside the distance so we're on the inside of the reflection point - -const float DEFAULT_ABSORPTION_RATIO = 0.125; // 12.5% is absorbed -const float DEFAULT_DIFFUSION_RATIO = 0.125; // 12.5% is diffused -const float DEFAULT_ORIGINAL_ATTENUATION = 1.0f; -const float DEFAULT_ECHO_ATTENUATION = 1.0f; - -AudioReflector::AudioReflector(QObject* parent) : - QObject(parent), - _preDelay(DEFAULT_PRE_DELAY), - _soundMsPerMeter(DEFAULT_MS_DELAY_PER_METER), - _distanceAttenuationScalingFactor(DEFAULT_DISTANCE_SCALING_FACTOR), - _localAudioAttenuationFactor(DEFAULT_LOCAL_ATTENUATION_FACTOR), - _combFilterWindow(DEFAULT_COMB_FILTER_WINDOW), - _diffusionFanout(DEFAULT_DIFFUSION_FANOUT), - _absorptionRatio(DEFAULT_ABSORPTION_RATIO), - _diffusionRatio(DEFAULT_DIFFUSION_RATIO), - _originalSourceAttenuation(DEFAULT_ORIGINAL_ATTENUATION), - _allEchoesAttenuation(DEFAULT_ECHO_ATTENUATION), - _withDiffusion(false), - _lastPreDelay(DEFAULT_PRE_DELAY), - _lastSoundMsPerMeter(DEFAULT_MS_DELAY_PER_METER), - _lastDistanceAttenuationScalingFactor(DEFAULT_DISTANCE_SCALING_FACTOR), - _lastLocalAudioAttenuationFactor(DEFAULT_LOCAL_ATTENUATION_FACTOR), - _lastDiffusionFanout(DEFAULT_DIFFUSION_FANOUT), - _lastAbsorptionRatio(DEFAULT_ABSORPTION_RATIO), - _lastDiffusionRatio(DEFAULT_DIFFUSION_RATIO), - _lastDontDistanceAttenuate(false), - _lastAlternateDistanceAttenuate(false) -{ - _reflections = 0; - _diffusionPathCount = 0; - _officialAverageAttenuation = _averageAttenuation = 0.0f; - _officialMaxAttenuation = _maxAttenuation = 0.0f; - _officialMinAttenuation = _minAttenuation = 0.0f; - _officialAverageDelay = _averageDelay = 0; - _officialMaxDelay = _maxDelay = 0; - _officialMinDelay = _minDelay = 0; - _inboundEchoesCount = 0; - _inboundEchoesSuppressedCount = 0; - _localEchoesCount = 0; - _localEchoesSuppressedCount = 0; -} - -bool AudioReflector::haveAttributesChanged() { - - // Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingWithDiffusions); - bool withDiffusion = true; - - // Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingDontDistanceAttenuate); - bool dontDistanceAttenuate = false; - - //Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingAlternateDistanceAttenuate); - bool alternateDistanceAttenuate = false; - - bool attributesChange = (_withDiffusion != withDiffusion - || _lastPreDelay != _preDelay - || _lastSoundMsPerMeter != _soundMsPerMeter - || _lastDistanceAttenuationScalingFactor != _distanceAttenuationScalingFactor - || _lastDiffusionFanout != _diffusionFanout - || _lastAbsorptionRatio != _absorptionRatio - || _lastDiffusionRatio != _diffusionRatio - || _lastDontDistanceAttenuate != dontDistanceAttenuate - || _lastAlternateDistanceAttenuate != alternateDistanceAttenuate); - - if (attributesChange) { - _withDiffusion = withDiffusion; - _lastPreDelay = _preDelay; - _lastSoundMsPerMeter = _soundMsPerMeter; - _lastDistanceAttenuationScalingFactor = _distanceAttenuationScalingFactor; - _lastDiffusionFanout = _diffusionFanout; - _lastAbsorptionRatio = _absorptionRatio; - _lastDiffusionRatio = _diffusionRatio; - _lastDontDistanceAttenuate = dontDistanceAttenuate; - _lastAlternateDistanceAttenuate = alternateDistanceAttenuate; - } - - return attributesChange; -} - -void AudioReflector::render() { - - // if we're not set up yet, or we're not processing spatial audio, then exit early - if (!_myAvatar || !_audio->getProcessSpatialAudio()) { - return; - } - - // use this oportunity to calculate our reflections - calculateAllReflections(); - - // only render if we've been asked to do so - bool renderPaths = false; // Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingRenderPaths) - if (renderPaths) { - drawRays(); - } -} - -// delay = 1ms per foot -// = 3ms per meter -float AudioReflector::getDelayFromDistance(float distance) { - float delay = (_soundMsPerMeter * distance); - bool includePreDelay = true; // Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingPreDelay) - if (includePreDelay) { - delay += _preDelay; - } - return delay; -} - -// attenuation = from the Audio Mixer -float AudioReflector::getDistanceAttenuationCoefficient(float distance) { - - - //!Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingDontDistanceAttenuate); - bool doDistanceAttenuation = true; - - //!Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingAlternateDistanceAttenuate); - bool originalFormula = true; - - float distanceCoefficient = 1.0f; - - if (doDistanceAttenuation) { - - if (originalFormula) { - const float DISTANCE_SCALE = 2.5f; - const float GEOMETRIC_AMPLITUDE_SCALAR = 0.3f; - const float DISTANCE_LOG_BASE = 2.5f; - const float DISTANCE_SCALE_LOG = logf(DISTANCE_SCALE) / logf(DISTANCE_LOG_BASE); - - float distanceSquareToSource = distance * distance; - - // calculate the distance coefficient using the distance to this node - distanceCoefficient = powf(GEOMETRIC_AMPLITUDE_SCALAR, - DISTANCE_SCALE_LOG + - (0.5f * logf(distanceSquareToSource) / logf(DISTANCE_LOG_BASE)) - 1); - distanceCoefficient = std::min(1.0f, distanceCoefficient * getDistanceAttenuationScalingFactor()); - } else { - - // From Fred: If we wanted something that would produce a tail that could go up to 5 seconds in a - // really big room, that would suggest the sound still has to be in the audible after traveling about - // 1500 meters. If it’s a sound of average volume, we probably have about 30 db, or 5 base2 orders - // of magnitude we can drop down before the sound becomes inaudible. (That’s approximate headroom - // based on a few sloppy assumptions.) So we could try a factor like 1 / (2^(D/300)) for starters. - // 1 / (2^(D/300)) - const float DISTANCE_BASE = 2.0f; - const float DISTANCE_DENOMINATOR = 300.0f; - const float DISTANCE_NUMERATOR = 300.0f; - distanceCoefficient = DISTANCE_NUMERATOR / powf(DISTANCE_BASE, (distance / DISTANCE_DENOMINATOR )); - distanceCoefficient = std::min(1.0f, distanceCoefficient * getDistanceAttenuationScalingFactor()); - } - } - - return distanceCoefficient; -} - -glm::vec3 AudioReflector::getFaceNormal(BoxFace face) { - // Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingSlightlyRandomSurfaces); - bool wantSlightRandomness = true; - glm::vec3 faceNormal; - const float MIN_RANDOM_LENGTH = 0.99f; - const float MAX_RANDOM_LENGTH = 1.0f; - const float NON_RANDOM_LENGTH = 1.0f; - float normalLength = wantSlightRandomness ? randFloatInRange(MIN_RANDOM_LENGTH, MAX_RANDOM_LENGTH) : NON_RANDOM_LENGTH; - float remainder = (1.0f - normalLength)/2.0f; - float remainderSignA = randomSign(); - float remainderSignB = randomSign(); - - if (face == MIN_X_FACE) { - faceNormal = glm::vec3(-normalLength, remainder * remainderSignA, remainder * remainderSignB); - } else if (face == MAX_X_FACE) { - faceNormal = glm::vec3(normalLength, remainder * remainderSignA, remainder * remainderSignB); - } else if (face == MIN_Y_FACE) { - faceNormal = glm::vec3(remainder * remainderSignA, -normalLength, remainder * remainderSignB); - } else if (face == MAX_Y_FACE) { - faceNormal = glm::vec3(remainder * remainderSignA, normalLength, remainder * remainderSignB); - } else if (face == MIN_Z_FACE) { - faceNormal = glm::vec3(remainder * remainderSignA, remainder * remainderSignB, -normalLength); - } else if (face == MAX_Z_FACE) { - faceNormal = glm::vec3(remainder * remainderSignA, remainder * remainderSignB, normalLength); - } - return faceNormal; -} - -// set up our buffers for our attenuated and delayed samples -const int NUMBER_OF_CHANNELS = 2; - -void AudioReflector::injectAudiblePoint(AudioSource source, const AudiblePoint& audiblePoint, - const QByteArray& samples, unsigned int sampleTime, int sampleRate) { - - bool wantEarSeparation = true; // Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingSeparateEars); - bool wantStereo = true; // Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingStereoSource); - glm::vec3 rightEarPosition = wantEarSeparation ? _myAvatar->getHead()->getRightEarPosition() : - _myAvatar->getHead()->getPosition(); - glm::vec3 leftEarPosition = wantEarSeparation ? _myAvatar->getHead()->getLeftEarPosition() : - _myAvatar->getHead()->getPosition(); - - int totalNumberOfSamples = samples.size() / sizeof(int16_t); - int totalNumberOfStereoSamples = samples.size() / (sizeof(int16_t) * NUMBER_OF_CHANNELS); - - const int16_t* originalSamplesData = (const int16_t*)samples.constData(); - QByteArray attenuatedLeftSamples; - QByteArray attenuatedRightSamples; - attenuatedLeftSamples.resize(samples.size()); - attenuatedRightSamples.resize(samples.size()); - - int16_t* attenuatedLeftSamplesData = (int16_t*)attenuatedLeftSamples.data(); - int16_t* attenuatedRightSamplesData = (int16_t*)attenuatedRightSamples.data(); - - // calculate the distance to the ears - float rightEarDistance = glm::distance(audiblePoint.location, rightEarPosition); - float leftEarDistance = glm::distance(audiblePoint.location, leftEarPosition); - - float rightEarDelayMsecs = getDelayFromDistance(rightEarDistance) + audiblePoint.delay; - float leftEarDelayMsecs = getDelayFromDistance(leftEarDistance) + audiblePoint.delay; - float averageEarDelayMsecs = (leftEarDelayMsecs + rightEarDelayMsecs) / 2.0f; - - bool safeToInject = true; // assume the best - - // check to see if this new injection point would be within the comb filter - // suppression window for any of the existing known delays - QMap& knownDelays = (source == INBOUND_AUDIO) ? _inboundAudioDelays : _localAudioDelays; - QMap::const_iterator lowerBound = knownDelays.lowerBound(averageEarDelayMsecs - _combFilterWindow); - if (lowerBound != knownDelays.end()) { - float closestFound = lowerBound.value(); - float deltaToClosest = (averageEarDelayMsecs - closestFound); - if (deltaToClosest > -_combFilterWindow && deltaToClosest < _combFilterWindow) { - safeToInject = false; - } - } - - // keep track of any of our suppressed echoes so we can report them in our statistics - if (!safeToInject) { - QVector& suppressedEchoes = (source == INBOUND_AUDIO) ? _inboundEchoesSuppressed : _localEchoesSuppressed; - suppressedEchoes << averageEarDelayMsecs; - } else { - knownDelays[averageEarDelayMsecs] = averageEarDelayMsecs; - - _totalDelay += rightEarDelayMsecs + leftEarDelayMsecs; - _delayCount += 2; - _maxDelay = std::max(_maxDelay,rightEarDelayMsecs); - _maxDelay = std::max(_maxDelay,leftEarDelayMsecs); - _minDelay = std::min(_minDelay,rightEarDelayMsecs); - _minDelay = std::min(_minDelay,leftEarDelayMsecs); - - int rightEarDelay = rightEarDelayMsecs * sampleRate / MSECS_PER_SECOND; - int leftEarDelay = leftEarDelayMsecs * sampleRate / MSECS_PER_SECOND; - - float rightEarAttenuation = audiblePoint.attenuation * - getDistanceAttenuationCoefficient(rightEarDistance + audiblePoint.distance); - - float leftEarAttenuation = audiblePoint.attenuation * - getDistanceAttenuationCoefficient(leftEarDistance + audiblePoint.distance); - - _totalAttenuation += rightEarAttenuation + leftEarAttenuation; - _attenuationCount += 2; - _maxAttenuation = std::max(_maxAttenuation,rightEarAttenuation); - _maxAttenuation = std::max(_maxAttenuation,leftEarAttenuation); - _minAttenuation = std::min(_minAttenuation,rightEarAttenuation); - _minAttenuation = std::min(_minAttenuation,leftEarAttenuation); - - // run through the samples, and attenuate them - for (int sample = 0; sample < totalNumberOfStereoSamples; sample++) { - int16_t leftSample = originalSamplesData[sample * NUMBER_OF_CHANNELS]; - int16_t rightSample = leftSample; - if (wantStereo) { - rightSample = originalSamplesData[(sample * NUMBER_OF_CHANNELS) + 1]; - } - - attenuatedLeftSamplesData[sample * NUMBER_OF_CHANNELS] = - leftSample * leftEarAttenuation * _allEchoesAttenuation; - attenuatedLeftSamplesData[sample * NUMBER_OF_CHANNELS + 1] = 0; - - attenuatedRightSamplesData[sample * NUMBER_OF_CHANNELS] = 0; - attenuatedRightSamplesData[sample * NUMBER_OF_CHANNELS + 1] = - rightSample * rightEarAttenuation * _allEchoesAttenuation; - } - - // now inject the attenuated array with the appropriate delay - unsigned int sampleTimeLeft = sampleTime + leftEarDelay; - unsigned int sampleTimeRight = sampleTime + rightEarDelay; - - _audio->addSpatialAudioToBuffer(sampleTimeLeft, attenuatedLeftSamples, totalNumberOfSamples); - _audio->addSpatialAudioToBuffer(sampleTimeRight, attenuatedRightSamples, totalNumberOfSamples); - - _injectedEchoes++; - } -} - - -void AudioReflector::preProcessOriginalInboundAudio(unsigned int sampleTime, - QByteArray& samples, const QAudioFormat& format) { - - if (_originalSourceAttenuation != 1.0f) { - int numberOfSamples = (samples.size() / sizeof(int16_t)); - int16_t* sampleData = (int16_t*)samples.data(); - for (int i = 0; i < numberOfSamples; i++) { - sampleData[i] = sampleData[i] * _originalSourceAttenuation; - } - } - -} - -void AudioReflector::processLocalAudio(unsigned int sampleTime, const QByteArray& samples, const QAudioFormat& format) { - bool processLocalAudio = true; // Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingProcessLocalAudio) - if (processLocalAudio) { - const int NUM_CHANNELS_INPUT = 1; - const int NUM_CHANNELS_OUTPUT = 2; - const int EXPECTED_SAMPLE_RATE = 24000; - if (format.channelCount() == NUM_CHANNELS_INPUT && format.sampleRate() == EXPECTED_SAMPLE_RATE) { - QAudioFormat outputFormat = format; - outputFormat.setChannelCount(NUM_CHANNELS_OUTPUT); - QByteArray stereoInputData(samples.size() * NUM_CHANNELS_OUTPUT, 0); - int numberOfSamples = (samples.size() / sizeof(int16_t)); - int16_t* monoSamples = (int16_t*)samples.data(); - int16_t* stereoSamples = (int16_t*)stereoInputData.data(); - - for (int i = 0; i < numberOfSamples; i++) { - stereoSamples[i* NUM_CHANNELS_OUTPUT] = monoSamples[i] * _localAudioAttenuationFactor; - stereoSamples[(i * NUM_CHANNELS_OUTPUT) + 1] = monoSamples[i] * _localAudioAttenuationFactor; - } - _localAudioDelays.clear(); - _localEchoesSuppressed.clear(); - echoAudio(LOCAL_AUDIO, sampleTime, stereoInputData, outputFormat); - _localEchoesCount = _localAudioDelays.size(); - _localEchoesSuppressedCount = _localEchoesSuppressed.size(); - } - } -} - -void AudioReflector::processInboundAudio(unsigned int sampleTime, const QByteArray& samples, const QAudioFormat& format) { - _inboundAudioDelays.clear(); - _inboundEchoesSuppressed.clear(); - echoAudio(INBOUND_AUDIO, sampleTime, samples, format); - _inboundEchoesCount = _inboundAudioDelays.size(); - _inboundEchoesSuppressedCount = _inboundEchoesSuppressed.size(); -} - -void AudioReflector::echoAudio(AudioSource source, unsigned int sampleTime, const QByteArray& samples, const QAudioFormat& format) { - QMutexLocker locker(&_mutex); - - _maxDelay = 0; - _maxAttenuation = 0.0f; - _minDelay = std::numeric_limits::max(); - _minAttenuation = std::numeric_limits::max(); - _totalDelay = 0.0f; - _delayCount = 0; - _totalAttenuation = 0.0f; - _attenuationCount = 0; - - // depending on if we're processing local or external audio, pick the correct points vector - QVector& audiblePoints = source == INBOUND_AUDIO ? _inboundAudiblePoints : _localAudiblePoints; - - int injectCalls = 0; - _injectedEchoes = 0; - foreach(const AudiblePoint& audiblePoint, audiblePoints) { - injectCalls++; - injectAudiblePoint(source, audiblePoint, samples, sampleTime, format.sampleRate()); - } - - /* - qDebug() << "injectCalls=" << injectCalls; - qDebug() << "_injectedEchoes=" << _injectedEchoes; - */ - - _averageDelay = _delayCount == 0 ? 0 : _totalDelay / _delayCount; - _averageAttenuation = _attenuationCount == 0 ? 0 : _totalAttenuation / _attenuationCount; - - if (_reflections == 0) { - _minDelay = 0.0f; - _minAttenuation = 0.0f; - } - - _officialMaxDelay = _maxDelay; - _officialMinDelay = _minDelay; - _officialMaxAttenuation = _maxAttenuation; - _officialMinAttenuation = _minAttenuation; - _officialAverageDelay = _averageDelay; - _officialAverageAttenuation = _averageAttenuation; - -} - -void AudioReflector::drawVector(const glm::vec3& start, const glm::vec3& end, const glm::vec3& color) { - glDisable(GL_LIGHTING); - glLineWidth(2.0); - - // Draw the vector itself - glBegin(GL_LINES); - glColor3f(color.x,color.y,color.z); - glVertex3f(start.x, start.y, start.z); - glVertex3f(end.x, end.y, end.z); - glEnd(); - - glEnable(GL_LIGHTING); -} - - - -AudioPath::AudioPath(AudioSource source, const glm::vec3& origin, const glm::vec3& direction, - float attenuation, float delay, float distance,bool isDiffusion, int bounceCount) : - - source(source), - isDiffusion(isDiffusion), - startPoint(origin), - startDirection(direction), - startDelay(delay), - startAttenuation(attenuation), - - lastPoint(origin), - lastDirection(direction), - lastDistance(distance), - lastDelay(delay), - lastAttenuation(attenuation), - bounceCount(bounceCount), - - finalized(false), - reflections() -{ -} - -void AudioReflector::addAudioPath(AudioSource source, const glm::vec3& origin, const glm::vec3& initialDirection, - float initialAttenuation, float initialDelay, float initialDistance, bool isDiffusion) { - - AudioPath* path = new AudioPath(source, origin, initialDirection, initialAttenuation, initialDelay, - initialDistance, isDiffusion, 0); - - QVector& audioPaths = source == INBOUND_AUDIO ? _inboundAudioPaths : _localAudioPaths; - - audioPaths.push_back(path); -} - -// NOTE: This is a prototype of an eventual utility that will identify the speaking sources for the inbound audio -// stream. It's not currently called but will be added soon. -void AudioReflector::identifyAudioSources() { - // looking for audio sources.... - foreach (const AvatarSharedPointer& avatarPointer, _avatarManager->getAvatarHash()) { - Avatar* avatar = static_cast(avatarPointer.data()); - if (!avatar->isInitialized()) { - continue; - } - qDebug() << "avatar["<< avatar <<"] loudness:" << avatar->getAudioLoudness(); - } -} - -void AudioReflector::calculateAllReflections() { - // only recalculate when we've moved, or if the attributes have changed - // TODO: what about case where new voxels are added in front of us??? - bool wantHeadOrientation = true; // Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingHeadOriented); - glm::quat orientation = wantHeadOrientation ? _myAvatar->getHead()->getFinalOrientationInWorldFrame() : _myAvatar->getOrientation(); - glm::vec3 origin = _myAvatar->getHead()->getPosition(); - glm::vec3 listenerPosition = _myAvatar->getHead()->getPosition(); - - bool shouldRecalc = _reflections == 0 - || !isSimilarPosition(origin, _origin) - || !isSimilarOrientation(orientation, _orientation) - || !isSimilarPosition(listenerPosition, _listenerPosition) - || haveAttributesChanged(); - - if (shouldRecalc) { - QMutexLocker locker(&_mutex); - quint64 start = usecTimestampNow(); - _origin = origin; - _orientation = orientation; - _listenerPosition = listenerPosition; - analyzePaths(); // actually does the work - quint64 end = usecTimestampNow(); - const bool wantDebugging = false; - if (wantDebugging) { - qDebug() << "newCalculateAllReflections() elapsed=" << (end - start); - } - } -} - -void AudioReflector::drawRays() { - const glm::vec3 RED(1,0,0); - const glm::vec3 GREEN(0,1,0); - const glm::vec3 BLUE(0,0,1); - const glm::vec3 CYAN(0,1,1); - - int diffusionNumber = 0; - - QMutexLocker locker(&_mutex); - - // draw the paths for inbound audio - foreach(AudioPath* const& path, _inboundAudioPaths) { - // if this is an original reflection, draw it in RED - if (path->isDiffusion) { - diffusionNumber++; - drawPath(path, GREEN); - } else { - drawPath(path, RED); - } - } - - bool processLocalAudio = true; // Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingProcessLocalAudio) - if (processLocalAudio) { - // draw the paths for local audio - foreach(AudioPath* const& path, _localAudioPaths) { - // if this is an original reflection, draw it in RED - if (path->isDiffusion) { - diffusionNumber++; - drawPath(path, CYAN); - } else { - drawPath(path, BLUE); - } - } - } -} - -void AudioReflector::drawPath(AudioPath* path, const glm::vec3& originalColor) { - glm::vec3 start = path->startPoint; - glm::vec3 color = originalColor; - const float COLOR_ADJUST_PER_BOUNCE = 0.75f; - - foreach (glm::vec3 end, path->reflections) { - drawVector(start, end, color); - start = end; - color = color * COLOR_ADJUST_PER_BOUNCE; - } -} - -void AudioReflector::clearPaths() { - // clear our inbound audio paths - foreach(AudioPath* const& path, _inboundAudioPaths) { - delete path; - } - _inboundAudioPaths.clear(); - _inboundAudiblePoints.clear(); // clear our inbound audible points - - // clear our local audio paths - foreach(AudioPath* const& path, _localAudioPaths) { - delete path; - } - _localAudioPaths.clear(); - _localAudiblePoints.clear(); // clear our local audible points -} - -// Here's how this works: we have an array of AudioPaths, we loop on all of our currently calculating audio -// paths, and calculate one ray per path. If that ray doesn't reflect, or reaches a max distance/attenuation, then it -// is considered finalized. -// If the ray hits a surface, then, based on the characteristics of that surface, it will calculate the new -// attenuation, path length, and delay for the primary path. For surfaces that have diffusion, it will also create -// fanout number of new paths, those new paths will have an origin of the reflection point, and an initial attenuation -// of their diffusion ratio. Those new paths will be added to the active audio paths, and be analyzed for the next loop. -void AudioReflector::analyzePaths() { - clearPaths(); - - // add our initial paths - glm::vec3 right = glm::normalize(_orientation * IDENTITY_RIGHT); - glm::vec3 up = glm::normalize(_orientation * IDENTITY_UP); - glm::vec3 front = glm::normalize(_orientation * IDENTITY_FRONT); - glm::vec3 left = -right; - glm::vec3 down = -up; - glm::vec3 back = -front; - glm::vec3 frontRightUp = glm::normalize(front + right + up); - glm::vec3 frontLeftUp = glm::normalize(front + left + up); - glm::vec3 backRightUp = glm::normalize(back + right + up); - glm::vec3 backLeftUp = glm::normalize(back + left + up); - glm::vec3 frontRightDown = glm::normalize(front + right + down); - glm::vec3 frontLeftDown = glm::normalize(front + left + down); - glm::vec3 backRightDown = glm::normalize(back + right + down); - glm::vec3 backLeftDown = glm::normalize(back + left + down); - - float initialAttenuation = 1.0f; - - bool wantPreDelay = true; // Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingPreDelay) - float preDelay = wantPreDelay ? _preDelay : 0.0f; - - // NOTE: we're still calculating our initial paths based on the listeners position. But the analysis code has been - // updated to support individual sound sources (which is how we support diffusion), we can use this new paradigm to - // add support for individual sound sources, and more directional sound sources - - addAudioPath(INBOUND_AUDIO, _origin, front, initialAttenuation, preDelay); - addAudioPath(INBOUND_AUDIO, _origin, right, initialAttenuation, preDelay); - addAudioPath(INBOUND_AUDIO, _origin, up, initialAttenuation, preDelay); - addAudioPath(INBOUND_AUDIO, _origin, down, initialAttenuation, preDelay); - addAudioPath(INBOUND_AUDIO, _origin, back, initialAttenuation, preDelay); - addAudioPath(INBOUND_AUDIO, _origin, left, initialAttenuation, preDelay); - addAudioPath(INBOUND_AUDIO, _origin, frontRightUp, initialAttenuation, preDelay); - addAudioPath(INBOUND_AUDIO, _origin, frontLeftUp, initialAttenuation, preDelay); - addAudioPath(INBOUND_AUDIO, _origin, backRightUp, initialAttenuation, preDelay); - addAudioPath(INBOUND_AUDIO, _origin, backLeftUp, initialAttenuation, preDelay); - addAudioPath(INBOUND_AUDIO, _origin, frontRightDown, initialAttenuation, preDelay); - addAudioPath(INBOUND_AUDIO, _origin, frontLeftDown, initialAttenuation, preDelay); - addAudioPath(INBOUND_AUDIO, _origin, backRightDown, initialAttenuation, preDelay); - addAudioPath(INBOUND_AUDIO, _origin, backLeftDown, initialAttenuation, preDelay); - - // the original paths for the local audio are directional to the front of the origin - addAudioPath(LOCAL_AUDIO, _origin, front, initialAttenuation, preDelay); - addAudioPath(LOCAL_AUDIO, _origin, frontRightUp, initialAttenuation, preDelay); - addAudioPath(LOCAL_AUDIO, _origin, frontLeftUp, initialAttenuation, preDelay); - addAudioPath(LOCAL_AUDIO, _origin, frontRightDown, initialAttenuation, preDelay); - addAudioPath(LOCAL_AUDIO, _origin, frontLeftDown, initialAttenuation, preDelay); - - // loop through all our audio paths and keep analyzing them until they complete - int steps = 0; - int acitvePaths = _inboundAudioPaths.size() + _localAudioPaths.size(); // when we start, all paths are active - while(acitvePaths > 0) { - acitvePaths = analyzePathsSingleStep(); - steps++; - } - _reflections = _inboundAudiblePoints.size() + _localAudiblePoints.size(); - _diffusionPathCount = countDiffusionPaths(); -} - -int AudioReflector::countDiffusionPaths() { - int diffusionCount = 0; - - foreach(AudioPath* const& path, _inboundAudioPaths) { - if (path->isDiffusion) { - diffusionCount++; - } - } - foreach(AudioPath* const& path, _localAudioPaths) { - if (path->isDiffusion) { - diffusionCount++; - } - } - return diffusionCount; -} - -int AudioReflector::analyzePathsSingleStep() { - // iterate all the active sound paths, calculate one step per active path - int activePaths = 0; - - QVector* pathsLists[] = { &_inboundAudioPaths, &_localAudioPaths }; - - for(unsigned int i = 0; i < sizeof(pathsLists) / sizeof(pathsLists[0]); i++) { - - QVector& pathList = *pathsLists[i]; - - foreach(AudioPath* const& path, pathList) { - - glm::vec3 start = path->lastPoint; - glm::vec3 direction = path->lastDirection; - OctreeElement* elementHit; // output from findRayIntersection - float distance; // output from findRayIntersection - BoxFace face; // output from findRayIntersection - - if (!path->finalized) { - activePaths++; - - if (path->bounceCount > ABSOLUTE_MAXIMUM_BOUNCE_COUNT) { - path->finalized = true; - } else if (_voxels->findRayIntersection(start, direction, elementHit, distance, face)) { - // TODO: we need to decide how we want to handle locking on the ray intersection, if we force lock, - // we get an accurate picture, but it could prevent rendering of the voxels. If we trylock (default), - // we might not get ray intersections where they may exist, but we can't really detect that case... - // add last parameter of Octree::Lock to force locking - handlePathPoint(path, distance, elementHit, face); - - } else { - // If we didn't intersect, but this was a diffusion ray, then we will go ahead and cast a short ray out - // from our last known point, in the last known direction, and leave that sound source hanging there - if (path->isDiffusion) { - const float MINIMUM_RANDOM_DISTANCE = 0.25f; - const float MAXIMUM_RANDOM_DISTANCE = 0.5f; - float distance = randFloatInRange(MINIMUM_RANDOM_DISTANCE, MAXIMUM_RANDOM_DISTANCE); - handlePathPoint(path, distance, NULL, UNKNOWN_FACE); - } else { - path->finalized = true; // if it doesn't intersect, then it is finished - } - } - } - } - } - return activePaths; -} - -void AudioReflector::handlePathPoint(AudioPath* path, float distance, OctreeElement* elementHit, BoxFace face) { - glm::vec3 start = path->lastPoint; - glm::vec3 direction = path->lastDirection; - glm::vec3 end = start + (direction * (distance * SLIGHTLY_SHORT)); - - float currentReflectiveAttenuation = path->lastAttenuation; // only the reflective components - float currentDelay = path->lastDelay; // start with our delay so far - float pathDistance = path->lastDistance; - - pathDistance += glm::distance(start, end); - - float toListenerDistance = glm::distance(end, _listenerPosition); - - // adjust our current delay by just the delay from the most recent ray - currentDelay += getDelayFromDistance(distance); - - // now we know the current attenuation for the "perfect" reflection case, but we now incorporate - // our surface materials to determine how much of this ray is absorbed, reflected, and diffused - SurfaceCharacteristics material = getSurfaceCharacteristics(elementHit); - - float reflectiveAttenuation = currentReflectiveAttenuation * material.reflectiveRatio; - float totalDiffusionAttenuation = currentReflectiveAttenuation * material.diffusionRatio; - - bool wantDiffusions = true; // Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingWithDiffusions); - int fanout = wantDiffusions ? _diffusionFanout : 0; - - float partialDiffusionAttenuation = fanout < 1 ? 0.0f : totalDiffusionAttenuation / (float)fanout; - - // total delay includes the bounce back to listener - float totalDelay = currentDelay + getDelayFromDistance(toListenerDistance); - float toListenerAttenuation = getDistanceAttenuationCoefficient(toListenerDistance + pathDistance); - - // if our resulting partial diffusion attenuation, is still above our minimum attenuation - // then we add new paths for each diffusion point - if ((partialDiffusionAttenuation * toListenerAttenuation) > MINIMUM_ATTENUATION_TO_REFLECT - && totalDelay < MAXIMUM_DELAY_MS) { - - // diffusions fan out from random places on the semisphere of the collision point - for(int i = 0; i < fanout; i++) { - glm::vec3 diffusion; - - // We're creating a random normal here. But we want it to be relatively dramatic compared to how we handle - // our slightly random surface normals. - const float MINIMUM_RANDOM_LENGTH = 0.5f; - const float MAXIMUM_RANDOM_LENGTH = 1.0f; - float randomness = randFloatInRange(MINIMUM_RANDOM_LENGTH, MAXIMUM_RANDOM_LENGTH); - float remainder = (1.0f - randomness)/2.0f; - float remainderSignA = randomSign(); - float remainderSignB = randomSign(); - - if (face == MIN_X_FACE) { - diffusion = glm::vec3(-randomness, remainder * remainderSignA, remainder * remainderSignB); - } else if (face == MAX_X_FACE) { - diffusion = glm::vec3(randomness, remainder * remainderSignA, remainder * remainderSignB); - } else if (face == MIN_Y_FACE) { - diffusion = glm::vec3(remainder * remainderSignA, -randomness, remainder * remainderSignB); - } else if (face == MAX_Y_FACE) { - diffusion = glm::vec3(remainder * remainderSignA, randomness, remainder * remainderSignB); - } else if (face == MIN_Z_FACE) { - diffusion = glm::vec3(remainder * remainderSignA, remainder * remainderSignB, -randomness); - } else if (face == MAX_Z_FACE) { - diffusion = glm::vec3(remainder * remainderSignA, remainder * remainderSignB, randomness); - } else if (face == UNKNOWN_FACE) { - float randomnessX = randFloatInRange(MINIMUM_RANDOM_LENGTH, MAXIMUM_RANDOM_LENGTH); - float randomnessY = randFloatInRange(MINIMUM_RANDOM_LENGTH, MAXIMUM_RANDOM_LENGTH); - float randomnessZ = randFloatInRange(MINIMUM_RANDOM_LENGTH, MAXIMUM_RANDOM_LENGTH); - diffusion = glm::vec3(direction.x * randomnessX, direction.y * randomnessY, direction.z * randomnessZ); - } - - diffusion = glm::normalize(diffusion); - - // add new audio path for these diffusions, the new path's source is the same as the original source - addAudioPath(path->source, end, diffusion, partialDiffusionAttenuation, currentDelay, pathDistance, true); - } - } else { - const bool wantDebugging = false; - if (wantDebugging) { - if ((partialDiffusionAttenuation * toListenerAttenuation) <= MINIMUM_ATTENUATION_TO_REFLECT) { - qDebug() << "too quiet to diffuse"; - qDebug() << " partialDiffusionAttenuation=" << partialDiffusionAttenuation; - qDebug() << " toListenerAttenuation=" << toListenerAttenuation; - qDebug() << " result=" << (partialDiffusionAttenuation * toListenerAttenuation); - qDebug() << " MINIMUM_ATTENUATION_TO_REFLECT=" << MINIMUM_ATTENUATION_TO_REFLECT; - } - if (totalDelay > MAXIMUM_DELAY_MS) { - qDebug() << "too delayed to diffuse"; - qDebug() << " totalDelay=" << totalDelay; - qDebug() << " MAXIMUM_DELAY_MS=" << MAXIMUM_DELAY_MS; - } - } - } - - // if our reflective attenuation is above our minimum, then add our reflection point and - // allow our path to continue - if (((reflectiveAttenuation + totalDiffusionAttenuation) * toListenerAttenuation) > MINIMUM_ATTENUATION_TO_REFLECT - && totalDelay < MAXIMUM_DELAY_MS) { - - // add this location, as the reflective attenuation as well as the total diffusion attenuation - // NOTE: we add the delay to the audible point, not back to the listener. The additional delay - // and attenuation to the listener is recalculated at the point where we actually inject the - // audio so that it can be adjusted to ear position - AudiblePoint point = {end, currentDelay, (reflectiveAttenuation + totalDiffusionAttenuation), pathDistance}; - - QVector& audiblePoints = path->source == INBOUND_AUDIO ? _inboundAudiblePoints : _localAudiblePoints; - - audiblePoints.push_back(point); - - // add this location to the path points, so we can visualize it - path->reflections.push_back(end); - - // now, if our reflective attenuation is over our minimum then keep going... - if (reflectiveAttenuation * toListenerAttenuation > MINIMUM_ATTENUATION_TO_REFLECT) { - glm::vec3 faceNormal = getFaceNormal(face); - path->lastDirection = glm::normalize(glm::reflect(direction,faceNormal)); - path->lastPoint = end; - path->lastAttenuation = reflectiveAttenuation; - path->lastDelay = currentDelay; - path->lastDistance = pathDistance; - path->bounceCount++; - } else { - path->finalized = true; // if we're too quiet, then we're done - } - } else { - const bool wantDebugging = false; - if (wantDebugging) { - if (((reflectiveAttenuation + totalDiffusionAttenuation) * toListenerAttenuation) <= MINIMUM_ATTENUATION_TO_REFLECT) { - qDebug() << "too quiet to add audible point"; - qDebug() << " reflectiveAttenuation + totalDiffusionAttenuation=" << (reflectiveAttenuation + totalDiffusionAttenuation); - qDebug() << " toListenerAttenuation=" << toListenerAttenuation; - qDebug() << " result=" << ((reflectiveAttenuation + totalDiffusionAttenuation) * toListenerAttenuation); - qDebug() << " MINIMUM_ATTENUATION_TO_REFLECT=" << MINIMUM_ATTENUATION_TO_REFLECT; - } - if (totalDelay > MAXIMUM_DELAY_MS) { - qDebug() << "too delayed to add audible point"; - qDebug() << " totalDelay=" << totalDelay; - qDebug() << " MAXIMUM_DELAY_MS=" << MAXIMUM_DELAY_MS; - } - } - path->finalized = true; // if we're too quiet, then we're done - } -} - -// TODO: eventually we will add support for different surface characteristics based on the element -// that is hit, which is why we pass in the elementHit to this helper function. But for now, all -// surfaces have the same characteristics -SurfaceCharacteristics AudioReflector::getSurfaceCharacteristics(OctreeElement* elementHit) { - SurfaceCharacteristics result = { getReflectiveRatio(), _absorptionRatio, _diffusionRatio }; - return result; -} - -void AudioReflector::setReflectiveRatio(float ratio) { - float safeRatio = std::max(0.0f, std::min(ratio, 1.0f)); - float currentReflectiveRatio = (1.0f - (_absorptionRatio + _diffusionRatio)); - float halfDifference = (safeRatio - currentReflectiveRatio) / 2.0f; - - // evenly distribute the difference between the two other ratios - _absorptionRatio -= halfDifference; - _diffusionRatio -= halfDifference; -} - -void AudioReflector::setAbsorptionRatio(float ratio) { - float safeRatio = std::max(0.0f, std::min(ratio, 1.0f)); - _absorptionRatio = safeRatio; - const float MAX_COMBINED_RATIO = 1.0f; - if (_absorptionRatio + _diffusionRatio > MAX_COMBINED_RATIO) { - _diffusionRatio = MAX_COMBINED_RATIO - _absorptionRatio; - } -} - -void AudioReflector::setDiffusionRatio(float ratio) { - float safeRatio = std::max(0.0f, std::min(ratio, 1.0f)); - _diffusionRatio = safeRatio; - const float MAX_COMBINED_RATIO = 1.0f; - if (_absorptionRatio + _diffusionRatio > MAX_COMBINED_RATIO) { - _absorptionRatio = MAX_COMBINED_RATIO - _diffusionRatio; - } -} - diff --git a/interface/src/AudioReflector.h b/interface/src/AudioReflector.h deleted file mode 100644 index 1bfb52ea09..0000000000 --- a/interface/src/AudioReflector.h +++ /dev/null @@ -1,254 +0,0 @@ -// -// AudioReflector.h -// interface -// -// Created by Brad Hefta-Gaub on 4/2/2014 -// Copyright (c) 2014 High Fidelity, Inc. All rights reserved. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef interface_AudioReflector_h -#define interface_AudioReflector_h - -#include - -#include - -#include "Audio.h" -#include "avatar/MyAvatar.h" -#include "avatar/AvatarManager.h" - -enum AudioSource { - LOCAL_AUDIO, - INBOUND_AUDIO -}; - -class AudioPath { -public: - AudioPath(AudioSource source = INBOUND_AUDIO, const glm::vec3& origin = glm::vec3(0.0f), - const glm::vec3& direction = glm::vec3(0.0f), float attenuation = 1.0f, - float delay = 0.0f, float distance = 0.0f, bool isDiffusion = false, int bounceCount = 0); - - AudioSource source; - bool isDiffusion; - glm::vec3 startPoint; - glm::vec3 startDirection; - float startDelay; - float startAttenuation; - - glm::vec3 lastPoint; - glm::vec3 lastDirection; - float lastDistance; - float lastDelay; - float lastAttenuation; - unsigned int bounceCount; - - bool finalized; - QVector reflections; -}; - -class AudiblePoint { -public: - glm::vec3 location; /// location of the audible point - float delay; /// includes total delay including pre delay to the point of the audible location, not to the listener's ears - float attenuation; /// only the reflective & diffusive portion of attenuation, doesn't include distance attenuation - float distance; /// includes total distance to the point of the audible location, not to the listener's ears -}; - -class SurfaceCharacteristics { -public: - float reflectiveRatio; - float absorptionRatio; - float diffusionRatio; -}; - -class AudioReflector : public QObject { - Q_OBJECT -public: - AudioReflector(QObject* parent = NULL); - - // setup functions to configure the resources used by the AudioReflector - void setVoxels(VoxelTree* voxels) { _voxels = voxels; } - void setMyAvatar(MyAvatar* myAvatar) { _myAvatar = myAvatar; } - void setAudio(Audio* audio) { _audio = audio; } - void setAvatarManager(AvatarManager* avatarManager) { _avatarManager = avatarManager; } - - void render(); /// must be called in the application render loop - - void preProcessOriginalInboundAudio(unsigned int sampleTime, QByteArray& samples, const QAudioFormat& format); - void processInboundAudio(unsigned int sampleTime, const QByteArray& samples, const QAudioFormat& format); - void processLocalAudio(unsigned int sampleTime, const QByteArray& samples, const QAudioFormat& format); - -public slots: - // statistics - int getReflections() const { return _reflections; } - float getAverageDelayMsecs() const { return _officialAverageDelay; } - float getAverageAttenuation() const { return _officialAverageAttenuation; } - float getMaxDelayMsecs() const { return _officialMaxDelay; } - float getMaxAttenuation() const { return _officialMaxAttenuation; } - float getMinDelayMsecs() const { return _officialMinDelay; } - float getMinAttenuation() const { return _officialMinAttenuation; } - float getDelayFromDistance(float distance); - int getDiffusionPathCount() const { return _diffusionPathCount; } - int getEchoesInjected() const { return _inboundEchoesCount + _localEchoesCount; } - int getEchoesSuppressed() const { return _inboundEchoesSuppressedCount + _localEchoesSuppressedCount; } - - /// ms of delay added to all echos - float getPreDelay() const { return _preDelay; } - void setPreDelay(float preDelay) { _preDelay = preDelay; } - - /// ms per meter that sound travels, larger means slower, which sounds bigger - float getSoundMsPerMeter() const { return _soundMsPerMeter; } - void setSoundMsPerMeter(float soundMsPerMeter) { _soundMsPerMeter = soundMsPerMeter; } - - /// scales attenuation to be louder or softer than the default distance attenuation - float getDistanceAttenuationScalingFactor() const { return _distanceAttenuationScalingFactor; } - void setDistanceAttenuationScalingFactor(float factor) { _distanceAttenuationScalingFactor = factor; } - - /// scales attenuation of local audio to be louder or softer than the default attenuation - float getLocalAudioAttenuationFactor() const { return _localAudioAttenuationFactor; } - void setLocalAudioAttenuationFactor(float factor) { _localAudioAttenuationFactor = factor; } - - /// ms window in which we will suppress echoes to reduce comb filter effects - float getCombFilterWindow() const { return _combFilterWindow; } - void setCombFilterWindow(float value) { _combFilterWindow = value; } - - /// number of points of diffusion from each reflection point, as fanout increases there are more chances for secondary - /// echoes, but each diffusion ray is quieter and therefore more likely to be below the sound floor - int getDiffusionFanout() const { return _diffusionFanout; } - void setDiffusionFanout(int fanout) { _diffusionFanout = fanout; } - - /// ratio 0.0 - 1.0 of amount of each ray that is absorbed upon hitting a surface - float getAbsorptionRatio() const { return _absorptionRatio; } - void setAbsorptionRatio(float ratio); - - // ratio 0.0 - 1.0 of amount of each ray that is diffused upon hitting a surface - float getDiffusionRatio() const { return _diffusionRatio; } - void setDiffusionRatio(float ratio); - - // remaining ratio 0.0 - 1.0 of amount of each ray that is cleanly reflected upon hitting a surface - float getReflectiveRatio() const { return (1.0f - (_absorptionRatio + _diffusionRatio)); } - void setReflectiveRatio(float ratio); - - // wet/dry mix - these don't affect any reflection calculations, only the final mix volumes - float getOriginalSourceAttenuation() const { return _originalSourceAttenuation; } - void setOriginalSourceAttenuation(float value) { _originalSourceAttenuation = value; } - float getEchoesAttenuation() const { return _allEchoesAttenuation; } - void setEchoesAttenuation(float value) { _allEchoesAttenuation = value; } - -signals: - -private: - VoxelTree* _voxels; // used to access voxel scene - MyAvatar* _myAvatar; // access to listener - Audio* _audio; // access to audio API - AvatarManager* _avatarManager; // access to avatar manager API - - // Helpers for drawing - void drawVector(const glm::vec3& start, const glm::vec3& end, const glm::vec3& color); - - // helper for generically calculating attenuation based on distance - float getDistanceAttenuationCoefficient(float distance); - - // statistics - int _reflections; - int _diffusionPathCount; - int _delayCount; - float _totalDelay; - float _averageDelay; - float _maxDelay; - float _minDelay; - float _officialAverageDelay; - float _officialMaxDelay; - float _officialMinDelay; - int _attenuationCount; - float _totalAttenuation; - float _averageAttenuation; - float _maxAttenuation; - float _minAttenuation; - float _officialAverageAttenuation; - float _officialMaxAttenuation; - float _officialMinAttenuation; - - - glm::vec3 _listenerPosition; - glm::vec3 _origin; - glm::quat _orientation; - - QVector _inboundAudioPaths; /// audio paths we're processing for inbound audio - QVector _inboundAudiblePoints; /// the audible points that have been calculated from the inbound audio paths - QMap _inboundAudioDelays; /// delay times for currently injected audio points - QVector _inboundEchoesSuppressed; /// delay times for currently injected audio points - int _inboundEchoesCount; - int _inboundEchoesSuppressedCount; - - QVector _localAudioPaths; /// audio paths we're processing for local audio - QVector _localAudiblePoints; /// the audible points that have been calculated from the local audio paths - QMap _localAudioDelays; /// delay times for currently injected audio points - QVector _localEchoesSuppressed; /// delay times for currently injected audio points - int _localEchoesCount; - int _localEchoesSuppressedCount; - - // adds a sound source to begin an audio path trace, these can be the initial sound sources with their directional properties, - // as well as diffusion sound sources - void addAudioPath(AudioSource source, const glm::vec3& origin, const glm::vec3& initialDirection, float initialAttenuation, - float initialDelay, float initialDistance = 0.0f, bool isDiffusion = false); - - // helper that handles audioPath analysis - int analyzePathsSingleStep(); - void handlePathPoint(AudioPath* path, float distance, OctreeElement* elementHit, BoxFace face); - void clearPaths(); - void analyzePaths(); - void drawRays(); - void drawPath(AudioPath* path, const glm::vec3& originalColor); - void calculateAllReflections(); - int countDiffusionPaths(); - glm::vec3 getFaceNormal(BoxFace face); - void identifyAudioSources(); - - void injectAudiblePoint(AudioSource source, const AudiblePoint& audiblePoint, const QByteArray& samples, unsigned int sampleTime, int sampleRate); - void echoAudio(AudioSource source, unsigned int sampleTime, const QByteArray& samples, const QAudioFormat& format); - - // return the surface characteristics of the element we hit - SurfaceCharacteristics getSurfaceCharacteristics(OctreeElement* elementHit = NULL); - - - QMutex _mutex; - - float _preDelay; - float _soundMsPerMeter; - float _distanceAttenuationScalingFactor; - float _localAudioAttenuationFactor; - float _combFilterWindow; - int _diffusionFanout; // number of points of diffusion from each reflection point - - // all elements have the same material for now... - float _absorptionRatio; - float _diffusionRatio; - float _reflectiveRatio; - - // wet/dry mix - these don't affect any reflection calculations, only the final mix volumes - float _originalSourceAttenuation; /// each sample of original signal will be multiplied by this - float _allEchoesAttenuation; /// each sample of all echo signals will be multiplied by this - - // remember the last known values at calculation - bool haveAttributesChanged(); - - bool _withDiffusion; - float _lastPreDelay; - float _lastSoundMsPerMeter; - float _lastDistanceAttenuationScalingFactor; - float _lastLocalAudioAttenuationFactor; - int _lastDiffusionFanout; - float _lastAbsorptionRatio; - float _lastDiffusionRatio; - bool _lastDontDistanceAttenuate; - bool _lastAlternateDistanceAttenuate; - - int _injectedEchoes; -}; - - -#endif // interface_AudioReflector_h diff --git a/interface/src/MetavoxelSystem.h b/interface/src/MetavoxelSystem.h index 26f3bd68a3..2ebf7e1146 100644 --- a/interface/src/MetavoxelSystem.h +++ b/interface/src/MetavoxelSystem.h @@ -22,6 +22,7 @@ #include #include "renderer/ProgramObject.h" +#include "renderer/TextureCache.h" class HeightfieldBaseLayerBatch; class HeightfieldSplatBatch; diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index d0a25f4f4a..77e6e0b6e1 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -669,104 +669,6 @@ void Stats::display( verticalOffset += STATS_PELS_PER_LINE; drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)voxelStats.str().c_str(), color); } - - if (_expanded && wantSpatialProcessing) { - verticalOffset += STATS_PELS_PER_LINE; // space one line... - - const AudioReflector* audioReflector = Application::getInstance()->getAudioReflector(); - - // add some reflection stats - char reflectionsStatus[128]; - - bool includeOriginal = true; //Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingIncludeOriginal) - bool separateEars = true; //Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingSeparateEars) - bool stereoSource = true; //Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingStereoSource) - bool randomSurfaces = true; //Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingSlightlyRandomSurfaces) - - sprintf(reflectionsStatus, "Reflections: %d, Original: %s, Ears: %s, Source: %s, Normals: %s", - audioReflector->getReflections(), - (includeOriginal ? "included" : "silent"), - (separateEars ? "two" : "one"), - (stereoSource ? "stereo" : "mono"), - (randomSurfaces ? "random" : "regular") - ); - - verticalOffset += STATS_PELS_PER_LINE; - drawText(horizontalOffset, verticalOffset, scale, rotation, font, reflectionsStatus, color); - - bool wantPreDelay = true; //Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingPreDelay) - float preDelay = wantPreDelay ? audioReflector->getPreDelay() : 0.0f; - - sprintf(reflectionsStatus, "Delay: pre: %6.3f, average %6.3f, max %6.3f, min %6.3f, speed: %6.3f", - preDelay, - audioReflector->getAverageDelayMsecs(), - audioReflector->getMaxDelayMsecs(), - audioReflector->getMinDelayMsecs(), - audioReflector->getSoundMsPerMeter()); - - verticalOffset += STATS_PELS_PER_LINE; - - drawText(horizontalOffset, verticalOffset, scale, rotation, font, reflectionsStatus, color); - - //Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingDontDistanceAttenuate); - bool distanceAttenuationDisabled = false; - - // Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingAlternateDistanceAttenuate); - bool alternateDistanceAttenuationEnabled = false; - - sprintf(reflectionsStatus, "Attenuation: average %5.3f, max %5.3f, min %5.3f, %s: %5.3f", - audioReflector->getAverageAttenuation(), - audioReflector->getMaxAttenuation(), - audioReflector->getMinAttenuation(), - (distanceAttenuationDisabled ? "Distance Factor [DISABLED]" : - alternateDistanceAttenuationEnabled ? "Distance Factor [ALTERNATE]" : "Distance Factor [STANARD]"), - audioReflector->getDistanceAttenuationScalingFactor()); - - verticalOffset += STATS_PELS_PER_LINE; - drawText(horizontalOffset, verticalOffset, scale, rotation, font, reflectionsStatus, color); - - bool localAudio = true; // Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingProcessLocalAudio); - sprintf(reflectionsStatus, "Local Audio: %s Attenuation: %5.3f", (localAudio ? "yes" : "no"), - audioReflector->getLocalAudioAttenuationFactor()); - - verticalOffset += STATS_PELS_PER_LINE; - drawText(horizontalOffset, verticalOffset, scale, rotation, font, reflectionsStatus, color); - - bool diffusionEnabled = true; //Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingWithDiffusions); - int fanout = diffusionEnabled ? audioReflector->getDiffusionFanout() : 0; - int diffusionPaths = diffusionEnabled ? audioReflector->getDiffusionPathCount() : 0; - sprintf(reflectionsStatus, "Diffusion: %s, Fanout: %d, Paths: %d", - (diffusionEnabled ? "yes" : "no"), fanout, diffusionPaths); - - verticalOffset += STATS_PELS_PER_LINE; - drawText(horizontalOffset, verticalOffset, scale, rotation, font, reflectionsStatus, color); - - const float AS_PERCENT = 100.0f; - float reflectiveRatio = audioReflector->getReflectiveRatio() * AS_PERCENT; - float diffusionRatio = audioReflector->getDiffusionRatio() * AS_PERCENT; - float absorptionRatio = audioReflector->getAbsorptionRatio() * AS_PERCENT; - sprintf(reflectionsStatus, "Ratios: Reflective: %5.3f, Diffusion: %5.3f, Absorption: %5.3f", - reflectiveRatio, diffusionRatio, absorptionRatio); - - verticalOffset += STATS_PELS_PER_LINE; - drawText(horizontalOffset, verticalOffset, scale, rotation, font, reflectionsStatus, color); - - sprintf(reflectionsStatus, "Comb Filter Window: %5.3f ms, Allowed: %d, Suppressed: %d", - audioReflector->getCombFilterWindow(), - audioReflector->getEchoesInjected(), - audioReflector->getEchoesSuppressed()); - - verticalOffset += STATS_PELS_PER_LINE; - drawText(horizontalOffset, verticalOffset, scale, rotation, font, reflectionsStatus, color); - - sprintf(reflectionsStatus, "Wet/Dry Mix: Original: %5.3f Echoes: %5.3f", - audioReflector->getOriginalSourceAttenuation(), - audioReflector->getEchoesAttenuation()); - - verticalOffset += STATS_PELS_PER_LINE; - drawText(horizontalOffset, verticalOffset, 0.10f, 0.0f, 2.0f, reflectionsStatus, color); - - } } void Stats::setMetavoxelStats(int internal, int leaves, int sendProgress, From 7f887ba75f5e304b3ecf3aabf9302ab4e9f95858 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 10 Dec 2014 15:46:10 -0800 Subject: [PATCH 334/502] more spatial audio removal --- interface/src/Audio.cpp | 119 ++----------------------------------- interface/src/Audio.h | 9 --- interface/src/ui/Stats.cpp | 4 -- 3 files changed, 4 insertions(+), 128 deletions(-) diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index 2214bb54cf..101d16d3ba 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -103,10 +103,6 @@ Audio::Audio(QObject* parent) : _gverb(NULL), _iconColor(1.0f), _iconPulseTimeReference(usecTimestampNow()), - _processSpatialAudio(false), - _spatialAudioStart(0), - _spatialAudioFinish(0), - _spatialAudioRingBuffer(NETWORK_BUFFER_LENGTH_SAMPLES_STEREO, true), // random access mode _scopeEnabled(false), _scopeEnabledPause(false), _scopeInputOffset(0), @@ -838,13 +834,6 @@ void Audio::handleAudioInput() { _lastInputLoudness = 0; } - // at this point we have clean monoAudioSamples, which match our target output... - // this is what we should send to our interested listeners - if (_processSpatialAudio && !_muted && !_isStereoInput && _audioOutput) { - QByteArray monoInputData((char*)networkAudioSamples, NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL * sizeof(int16_t)); - emit processLocalAudio(_spatialAudioStart, monoInputData, _desiredInputFormat); - } - if (!_isStereoInput && _proceduralAudioOutput) { processProceduralAudio(networkAudioSamples, NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL); } @@ -984,35 +973,11 @@ void Audio::processReceivedSamples(const QByteArray& inputBuffer, QByteArray& ou outputBuffer.resize(numDeviceOutputSamples * sizeof(int16_t)); const int16_t* receivedSamples; - if (_processSpatialAudio) { - unsigned int sampleTime = _spatialAudioStart; - QByteArray buffer = inputBuffer; + // copy the samples we'll resample from the ring buffer - this also + // pushes the read pointer of the ring buffer forwards + //receivedAudioStreamPopOutput.readSamples(receivedSamples, numNetworkOutputSamples); - // Accumulate direct transmission of audio from sender to receiver - bool includeOriginal = true; // Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingIncludeOriginal) - if (includeOriginal) { - emit preProcessOriginalInboundAudio(sampleTime, buffer, _desiredOutputFormat); - addSpatialAudioToBuffer(sampleTime, buffer, numNetworkOutputSamples); - } - - // Send audio off for spatial processing - emit processInboundAudio(sampleTime, buffer, _desiredOutputFormat); - - // copy the samples we'll resample from the spatial audio ring buffer - this also - // pushes the read pointer of the spatial audio ring buffer forwards - _spatialAudioRingBuffer.readSamples(_outputProcessingBuffer, numNetworkOutputSamples); - - // Advance the start point for the next packet of audio to arrive - _spatialAudioStart += numNetworkOutputSamples / _desiredOutputFormat.channelCount(); - - receivedSamples = _outputProcessingBuffer; - } else { - // copy the samples we'll resample from the ring buffer - this also - // pushes the read pointer of the ring buffer forwards - //receivedAudioStreamPopOutput.readSamples(receivedSamples, numNetworkOutputSamples); - - receivedSamples = reinterpret_cast(inputBuffer.data()); - } + receivedSamples = reinterpret_cast(inputBuffer.data()); // copy the packet from the RB to the output linearResampling(receivedSamples, @@ -1123,68 +1088,7 @@ void Audio::sendDownstreamAudioStatsPacket() { nodeList->writeDatagram(packet, dataAt - packet, audioMixer); } -// NOTE: numSamples is the total number of single channel samples, since callers will always call this with stereo -// data we know that we will have 2x samples for each stereo time sample at the format's sample rate -void Audio::addSpatialAudioToBuffer(unsigned int sampleTime, const QByteArray& spatialAudio, unsigned int numSamples) { - // Calculate the number of remaining samples available. The source spatial audio buffer will get - // clipped if there are insufficient samples available in the accumulation buffer. - unsigned int remaining = _spatialAudioRingBuffer.getSampleCapacity() - _spatialAudioRingBuffer.samplesAvailable(); - // Locate where in the accumulation buffer the new samples need to go - if (sampleTime >= _spatialAudioFinish) { - if (_spatialAudioStart == _spatialAudioFinish) { - // Nothing in the spatial audio ring buffer yet, Just do a straight copy, clipping if necessary - unsigned int sampleCount = (remaining < numSamples) ? remaining : numSamples; - if (sampleCount) { - _spatialAudioRingBuffer.writeSamples((int16_t*)spatialAudio.data(), sampleCount); - } - _spatialAudioFinish = _spatialAudioStart + sampleCount / _desiredOutputFormat.channelCount(); - } else { - // Spatial audio ring buffer already has data, but there is no overlap with the new sample. - // Compute the appropriate time delay and pad with silence until the new start time. - unsigned int delay = sampleTime - _spatialAudioFinish; - unsigned int delayCount = delay * _desiredOutputFormat.channelCount(); - unsigned int silentCount = (remaining < delayCount) ? remaining : delayCount; - if (silentCount) { - _spatialAudioRingBuffer.addSilentSamples(silentCount); - } - - // Recalculate the number of remaining samples - remaining -= silentCount; - unsigned int sampleCount = (remaining < numSamples) ? remaining : numSamples; - - // Copy the new spatial audio to the accumulation ring buffer - if (sampleCount) { - _spatialAudioRingBuffer.writeSamples((int16_t*)spatialAudio.data(), sampleCount); - } - _spatialAudioFinish += (sampleCount + silentCount) / _desiredOutputFormat.channelCount(); - } - } else { - // There is overlap between the spatial audio buffer and the new sample, mix the overlap - // Calculate the offset from the buffer's current read position, which should be located at _spatialAudioStart - unsigned int offset = (sampleTime - _spatialAudioStart) * _desiredOutputFormat.channelCount(); - unsigned int mixedSamplesCount = (_spatialAudioFinish - sampleTime) * _desiredOutputFormat.channelCount(); - mixedSamplesCount = (mixedSamplesCount < numSamples) ? mixedSamplesCount : numSamples; - - const int16_t* spatial = reinterpret_cast(spatialAudio.data()); - for (unsigned int i = 0; i < mixedSamplesCount; i++) { - int existingSample = _spatialAudioRingBuffer[i + offset]; - int newSample = spatial[i]; - int sumOfSamples = existingSample + newSample; - _spatialAudioRingBuffer[i + offset] = static_cast(glm::clamp(sumOfSamples, - std::numeric_limits::min(), std::numeric_limits::max())); - } - - // Copy the remaining unoverlapped spatial audio to the spatial audio buffer, if any - unsigned int nonMixedSampleCount = numSamples - mixedSamplesCount; - nonMixedSampleCount = (remaining < nonMixedSampleCount) ? remaining : nonMixedSampleCount; - if (nonMixedSampleCount) { - _spatialAudioRingBuffer.writeSamples((int16_t*)spatialAudio.data() + mixedSamplesCount, nonMixedSampleCount); - // Extend the finish time by the amount of unoverlapped samples - _spatialAudioFinish += nonMixedSampleCount / _desiredOutputFormat.channelCount(); - } - } -} bool Audio::mousePressEvent(int x, int y) { if (_iconBounds.contains(x, y)) { @@ -1264,16 +1168,6 @@ void Audio::selectAudioSourceSine440() { _noiseSourceEnabled = !_toneSourceEnabled; } -void Audio::toggleAudioSpatialProcessing() { - // spatial audio disabled for now - _processSpatialAudio = false; //!_processSpatialAudio; - if (_processSpatialAudio) { - _spatialAudioStart = 0; - _spatialAudioFinish = 0; - _spatialAudioRingBuffer.reset(); - } -} - // Take a pointer to the acquired microphone input samples and add procedural sounds void Audio::addProceduralSounds(int16_t* monoInput, int numSamples) { float sample; @@ -1995,11 +1889,6 @@ bool Audio::switchOutputToAudioDevice(const QAudioDeviceInfo& outputDeviceInfo) _timeSinceLastReceived.start(); - // setup spatial audio ringbuffer - int numFrameSamples = _outputFormat.sampleRate() * _desiredOutputFormat.channelCount(); - _spatialAudioRingBuffer.resizeForFrameSize(numFrameSamples); - _spatialAudioStart = _spatialAudioFinish = 0; - supportedFormat = true; } } diff --git a/interface/src/Audio.h b/interface/src/Audio.h index 166042878c..47fe00a84c 100644 --- a/interface/src/Audio.h +++ b/interface/src/Audio.h @@ -115,8 +115,6 @@ public: int getNetworkSampleRate() { return SAMPLE_RATE; } int getNetworkBufferLengthSamplesPerChannel() { return NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL; } - bool getProcessSpatialAudio() const { return _processSpatialAudio; } - float getInputRingBufferMsecsAvailable() const; float getInputRingBufferAverageMsecsAvailable() const { return (float)_inputRingBufferMsecsAvailableStats.getWindowAverage(); } @@ -131,7 +129,6 @@ public slots: void addReceivedAudioToStream(const QByteArray& audioByteArray); void parseAudioStreamStatsPacket(const QByteArray& packet); void parseAudioEnvironmentData(const QByteArray& packet); - void addSpatialAudioToBuffer(unsigned int sampleTime, const QByteArray& spatialAudio, unsigned int numSamples); void handleAudioInput(); void reset(); void resetStats(); @@ -145,7 +142,6 @@ public slots: void toggleScopePause(); void toggleStats(); void toggleStatsShowInjectedStreams(); - void toggleAudioSpatialProcessing(); void toggleStereoInput(); void selectAudioScopeFiveFrames(); void selectAudioScopeTwentyFrames(); @@ -254,11 +250,6 @@ private: float _iconColor; qint64 _iconPulseTimeReference; - bool _processSpatialAudio; /// Process received audio by spatial audio hooks - unsigned int _spatialAudioStart; /// Start of spatial audio interval (in sample rate time base) - unsigned int _spatialAudioFinish; /// End of spatial audio interval (in sample rate time base) - AudioRingBuffer _spatialAudioRingBuffer; /// Spatially processed audio - // Process procedural audio by // 1. Echo to the local procedural output device // 2. Mix with the audio input diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index 77e6e0b6e1..9abb3d1b78 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -477,10 +477,6 @@ void Stats::display( VoxelSystem* voxels = Application::getInstance()->getVoxels(); lines = _expanded ? 14 : 3; - bool wantSpatialProcessing = false; // Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessing) - if (_expanded && wantSpatialProcessing) { - lines += 10; // spatial audio processing adds 1 spacing line and 8 extra lines of info - } drawBackground(backgroundColor, horizontalOffset, 0, glWidget->width() - horizontalOffset, lines * STATS_PELS_PER_LINE + 10); From ff372c5f4e2b95f44f8c340491be1b68d45a0091 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 10 Dec 2014 16:53:21 -0800 Subject: [PATCH 335/502] Added lobby.js to default scripts --- examples/defaultScripts.js | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/defaultScripts.js b/examples/defaultScripts.js index dbd8ee18d9..d39fce0186 100644 --- a/examples/defaultScripts.js +++ b/examples/defaultScripts.js @@ -14,3 +14,4 @@ Script.load("selectAudioDevice.js"); Script.load("hydraMove.js"); Script.load("headMove.js"); Script.load("inspect.js"); +Script.load("lobby.js"); From ccf8d0a787acb16964c3a99ecc00b6902a3c65f9 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 10 Dec 2014 16:55:40 -0800 Subject: [PATCH 336/502] DefaultScript.js doesn't appear in running scripts --- examples/defaultScripts.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/defaultScripts.js b/examples/defaultScripts.js index d39fce0186..0ffa2dba05 100644 --- a/examples/defaultScripts.js +++ b/examples/defaultScripts.js @@ -15,3 +15,5 @@ Script.load("hydraMove.js"); Script.load("headMove.js"); Script.load("inspect.js"); Script.load("lobby.js"); + +Script.stop(); From d058b5554ea87a142c1beac15f5fb40c71a8838b Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 10 Dec 2014 16:58:36 -0800 Subject: [PATCH 337/502] make sure the running scripts widget doesn't start on the HMD screen --- interface/src/Application.cpp | 3 --- interface/src/ui/HMDToolsDialog.cpp | 1 - interface/src/ui/HMDToolsDialog.h | 2 ++ interface/src/ui/RunningScriptsWidget.cpp | 28 +++++++++++++++++++---- interface/src/ui/RunningScriptsWidget.h | 2 -- 5 files changed, 25 insertions(+), 11 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index d773208ac0..dc4b66ad93 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -415,9 +415,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : _previousScriptLocation = _settings->value("LastScriptLocation", QVariant("")).toString(); } - connect(_window, &MainWindow::windowGeometryChanged, - _runningScriptsWidget, &RunningScriptsWidget::setBoundary); - _trayIcon->show(); // set the local loopback interface for local sounds from audio scripts diff --git a/interface/src/ui/HMDToolsDialog.cpp b/interface/src/ui/HMDToolsDialog.cpp index 88924f68d1..580490f83b 100644 --- a/interface/src/ui/HMDToolsDialog.cpp +++ b/interface/src/ui/HMDToolsDialog.cpp @@ -79,7 +79,6 @@ HMDToolsDialog::HMDToolsDialog(QWidget* parent) : // keep track of changes to the number of screens connect(QApplication::desktop(), &QDesktopWidget::screenCountChanged, this, &HMDToolsDialog::screenCountChanged); - } HMDToolsDialog::~HMDToolsDialog() { diff --git a/interface/src/ui/HMDToolsDialog.h b/interface/src/ui/HMDToolsDialog.h index e3e5573533..d539b58d04 100644 --- a/interface/src/ui/HMDToolsDialog.h +++ b/interface/src/ui/HMDToolsDialog.h @@ -22,6 +22,8 @@ public: ~HMDToolsDialog(); QString getDebugDetails() const; + QScreen* getHMDScreen() const { return _hmdScreen; } + bool hasHMDScreen() const { return _hmdScreenNumber >= -1; } signals: void closed(); diff --git a/interface/src/ui/RunningScriptsWidget.cpp b/interface/src/ui/RunningScriptsWidget.cpp index 29c004bdb7..4fd19d4588 100644 --- a/interface/src/ui/RunningScriptsWidget.cpp +++ b/interface/src/ui/RunningScriptsWidget.cpp @@ -17,7 +17,9 @@ #include #include #include +#include #include +#include #include "Application.h" #include "Menu.h" @@ -82,10 +84,6 @@ void RunningScriptsWidget::loadSelectedScript() { } } -void RunningScriptsWidget::setBoundary(const QRect& rect) { - _boundary = rect; -} - void RunningScriptsWidget::setRunningScripts(const QStringList& list) { setUpdatesEnabled(false); QLayoutItem* widget; @@ -153,7 +151,27 @@ void RunningScriptsWidget::showEvent(QShowEvent* event) { ui->filterLineEdit->setFocus(); } - const QRect parentGeometry = parentWidget()->geometry(); + QRect parentGeometry = parentWidget()->geometry(); + + // If our parent window is on the HMD, then don't use it's geometry, instead use + // the "main screen" geometry. + HMDToolsDialog* hmdTools = Menu::getInstance()->getHMDToolsDialog(); + if (hmdTools && hmdTools->hasHMDScreen()) { + QScreen* hmdScreen = hmdTools->getHMDScreen(); + QWindow* appWindow = parentWidget()->windowHandle(); + QScreen* appScreen = appWindow->screen(); + + // if our app's screen is the hmd screen, we don't want to place the + // running scripts widget on it. So we need to pick a better screen. + // we will use the screen for the HMDTools since it's a guarenteed + // better screen. + if (appScreen == hmdScreen) { + QScreen* betterScreen = hmdTools->windowHandle()->screen(); + parentGeometry = betterScreen->geometry(); + } + + } + int titleBarHeight = UIUtil::getWindowTitleBarHeight(this); int menuBarHeight = Menu::getInstance()->geometry().height(); int topMargin = titleBarHeight + menuBarHeight; diff --git a/interface/src/ui/RunningScriptsWidget.h b/interface/src/ui/RunningScriptsWidget.h index 7493a1a5ce..8eace0c7b1 100644 --- a/interface/src/ui/RunningScriptsWidget.h +++ b/interface/src/ui/RunningScriptsWidget.h @@ -44,7 +44,6 @@ protected: public slots: void scriptStopped(const QString& scriptName); - void setBoundary(const QRect& rect); private slots: void allScriptsStopped(); @@ -61,7 +60,6 @@ private: ScriptsTableWidget* _recentlyLoadedScriptsTable; QStringList _recentlyLoadedScripts; QString _lastStoppedScript; - QRect _boundary; }; #endif // hifi_RunningScriptsWidget_h From 06d348c39936f51acb6398042e5305c5c589e28d Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 10 Dec 2014 17:13:34 -0800 Subject: [PATCH 338/502] get have addressbar avoid the hmd screen --- interface/src/ui/FramelessDialog.cpp | 39 +++++++++++++++++++++---- interface/src/ui/RunningScriptsWidget.h | 1 - 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/interface/src/ui/FramelessDialog.cpp b/interface/src/ui/FramelessDialog.cpp index ab997a0a75..8a170ab78d 100644 --- a/interface/src/ui/FramelessDialog.cpp +++ b/interface/src/ui/FramelessDialog.cpp @@ -9,8 +9,12 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include +#include + #include "Application.h" #include "FramelessDialog.h" +#include "Menu.h" const int RESIZE_HANDLE_WIDTH = 7; @@ -90,24 +94,47 @@ void FramelessDialog::showEvent(QShowEvent* event) { } void FramelessDialog::resizeAndPosition(bool resizeParent) { + QSize parentSize = parentWidget()->size(); + QRect parentGeometry = parentWidget()->geometry(); + + // If our parent window is on the HMD, then don't use it's geometry, instead use + // the "main screen" geometry. + HMDToolsDialog* hmdTools = Menu::getInstance()->getHMDToolsDialog(); + if (hmdTools && hmdTools->hasHMDScreen()) { + QScreen* hmdScreen = hmdTools->getHMDScreen(); + QWindow* appWindow = parentWidget()->windowHandle(); + QScreen* appScreen = appWindow->screen(); + + // if our app's screen is the hmd screen, we don't want to place the + // running scripts widget on it. So we need to pick a better screen. + // we will use the screen for the HMDTools since it's a guarenteed + // better screen. + if (appScreen == hmdScreen) { + QScreen* betterScreen = hmdTools->windowHandle()->screen(); + parentGeometry = betterScreen->geometry(); + parentSize = betterScreen->size(); + } + + } + // keep full app height or width depending on position if (_position == POSITION_LEFT || _position == POSITION_RIGHT) { - setFixedHeight(parentWidget()->size().height()); + setFixedHeight(parentSize.height()); } else { - setFixedWidth(parentWidget()->size().width()); + setFixedWidth(parentSize.width()); } // resize parrent if width is smaller than this dialog - if (resizeParent && parentWidget()->size().width() < size().width()) { - parentWidget()->resize(size().width(), parentWidget()->size().height()); + if (resizeParent && parentSize.width() < size().width()) { + parentWidget()->resize(size().width(), parentSize.height()); } if (_position == POSITION_LEFT || _position == POSITION_TOP) { // move to upper left corner - move(parentWidget()->geometry().topLeft()); + move(parentGeometry.topLeft()); } else if (_position == POSITION_RIGHT) { // move to upper right corner - QPoint pos = parentWidget()->geometry().topRight(); + QPoint pos = parentGeometry.topRight(); pos.setX(pos.x() - size().width()); move(pos); } diff --git a/interface/src/ui/RunningScriptsWidget.h b/interface/src/ui/RunningScriptsWidget.h index 8eace0c7b1..69833a890b 100644 --- a/interface/src/ui/RunningScriptsWidget.h +++ b/interface/src/ui/RunningScriptsWidget.h @@ -18,7 +18,6 @@ #include #include "ScriptsModel.h" -#include "FramelessDialog.h" #include "ScriptsTableWidget.h" namespace Ui { From ec54b609df13d20a01fe0ecbb18e6550ba2ba5e1 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 10 Dec 2014 17:23:39 -0800 Subject: [PATCH 339/502] dry up code and make chat window avoid the hmd screen --- interface/src/Application.cpp | 24 +++++++++++++++++++++++ interface/src/Application.h | 2 ++ interface/src/ui/ChatWindow.cpp | 2 +- interface/src/ui/FramelessDialog.cpp | 24 ++--------------------- interface/src/ui/RunningScriptsWidget.cpp | 22 +-------------------- 5 files changed, 30 insertions(+), 44 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index dc4b66ad93..cb3acc88f1 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -2714,6 +2715,29 @@ bool Application::isHMDMode() const { } } +QRect Application::getDesirableApplicationGeometry() { + QRect applicationGeometry = getWindow()->geometry(); + + // If our parent window is on the HMD, then don't use it's geometry, instead use + // the "main screen" geometry. + HMDToolsDialog* hmdTools = Menu::getInstance()->getHMDToolsDialog(); + if (hmdTools && hmdTools->hasHMDScreen()) { + QScreen* hmdScreen = hmdTools->getHMDScreen(); + QWindow* appWindow = getWindow()->windowHandle(); + QScreen* appScreen = appWindow->screen(); + + // if our app's screen is the hmd screen, we don't want to place the + // running scripts widget on it. So we need to pick a better screen. + // we will use the screen for the HMDTools since it's a guarenteed + // better screen. + if (appScreen == hmdScreen) { + QScreen* betterScreen = hmdTools->windowHandle()->screen(); + applicationGeometry = betterScreen->geometry(); + } + } + return applicationGeometry; +} + ///////////////////////////////////////////////////////////////////////////////////// // loadViewFrustum() // diff --git a/interface/src/Application.h b/interface/src/Application.h index 0f0bd91210..217d547c89 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -327,6 +327,8 @@ public: // rendering of several elements depend on that // TODO: carry that information on the Camera as a setting bool isHMDMode() const; + + QRect getDesirableApplicationGeometry(); signals: diff --git a/interface/src/ui/ChatWindow.cpp b/interface/src/ui/ChatWindow.cpp index 7869926ebe..747b4ae68d 100644 --- a/interface/src/ui/ChatWindow.cpp +++ b/interface/src/ui/ChatWindow.cpp @@ -124,7 +124,7 @@ void ChatWindow::showEvent(QShowEvent* event) { if (!event->spontaneous()) { _ui->messagePlainTextEdit->setFocus(); } - const QRect parentGeometry = parentWidget()->geometry(); + QRect parentGeometry = Application::getInstance()->getDesirableApplicationGeometry(); int titleBarHeight = UIUtil::getWindowTitleBarHeight(this); int menuBarHeight = Menu::getInstance()->geometry().height(); int topMargin = titleBarHeight + menuBarHeight; diff --git a/interface/src/ui/FramelessDialog.cpp b/interface/src/ui/FramelessDialog.cpp index 8a170ab78d..280354d974 100644 --- a/interface/src/ui/FramelessDialog.cpp +++ b/interface/src/ui/FramelessDialog.cpp @@ -94,29 +94,9 @@ void FramelessDialog::showEvent(QShowEvent* event) { } void FramelessDialog::resizeAndPosition(bool resizeParent) { - QSize parentSize = parentWidget()->size(); - QRect parentGeometry = parentWidget()->geometry(); + QRect parentGeometry = Application::getInstance()->getDesirableApplicationGeometry(); + QSize parentSize = parentGeometry.size(); - // If our parent window is on the HMD, then don't use it's geometry, instead use - // the "main screen" geometry. - HMDToolsDialog* hmdTools = Menu::getInstance()->getHMDToolsDialog(); - if (hmdTools && hmdTools->hasHMDScreen()) { - QScreen* hmdScreen = hmdTools->getHMDScreen(); - QWindow* appWindow = parentWidget()->windowHandle(); - QScreen* appScreen = appWindow->screen(); - - // if our app's screen is the hmd screen, we don't want to place the - // running scripts widget on it. So we need to pick a better screen. - // we will use the screen for the HMDTools since it's a guarenteed - // better screen. - if (appScreen == hmdScreen) { - QScreen* betterScreen = hmdTools->windowHandle()->screen(); - parentGeometry = betterScreen->geometry(); - parentSize = betterScreen->size(); - } - - } - // keep full app height or width depending on position if (_position == POSITION_LEFT || _position == POSITION_RIGHT) { setFixedHeight(parentSize.height()); diff --git a/interface/src/ui/RunningScriptsWidget.cpp b/interface/src/ui/RunningScriptsWidget.cpp index 4fd19d4588..cfd7428482 100644 --- a/interface/src/ui/RunningScriptsWidget.cpp +++ b/interface/src/ui/RunningScriptsWidget.cpp @@ -151,27 +151,7 @@ void RunningScriptsWidget::showEvent(QShowEvent* event) { ui->filterLineEdit->setFocus(); } - QRect parentGeometry = parentWidget()->geometry(); - - // If our parent window is on the HMD, then don't use it's geometry, instead use - // the "main screen" geometry. - HMDToolsDialog* hmdTools = Menu::getInstance()->getHMDToolsDialog(); - if (hmdTools && hmdTools->hasHMDScreen()) { - QScreen* hmdScreen = hmdTools->getHMDScreen(); - QWindow* appWindow = parentWidget()->windowHandle(); - QScreen* appScreen = appWindow->screen(); - - // if our app's screen is the hmd screen, we don't want to place the - // running scripts widget on it. So we need to pick a better screen. - // we will use the screen for the HMDTools since it's a guarenteed - // better screen. - if (appScreen == hmdScreen) { - QScreen* betterScreen = hmdTools->windowHandle()->screen(); - parentGeometry = betterScreen->geometry(); - } - - } - + QRect parentGeometry = Application::getInstance()->getDesirableApplicationGeometry(); int titleBarHeight = UIUtil::getWindowTitleBarHeight(this); int menuBarHeight = Menu::getInstance()->geometry().height(); int topMargin = titleBarHeight + menuBarHeight; From 0c746168ef31d4fdd19a6c4b413edd31456f8c11 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 10 Dec 2014 19:47:28 -0800 Subject: [PATCH 340/502] Update lobby to use new URLs + black panels in place of H --- examples/lobby.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/examples/lobby.js b/examples/lobby.js index 647202bebc..4528021a83 100644 --- a/examples/lobby.js +++ b/examples/lobby.js @@ -47,6 +47,10 @@ var ORB_SHIFT = { x: 0, y: -1.4, z: -0.8}; var HELMET_ATTACHMENT_URL = HIFI_PUBLIC_BUCKET + "models/attachments/IronManMaskOnly.fbx" +var LOBBY_PANEL_WALL_URL = HIFI_PUBLIC_BUCKET + "models/sets/Lobby/PanelWallForInterface.fbx"; +var LOBBY_BLANK_PANEL_TEXTURE_URL = HIFI_PUBLIC_BUCKET + "models/sets/Lobby/Texture.jpg"; +var LOBBY_SHELL_URL = HIFI_PUBLIC_BUCKET + "models/sets/Lobby/LobbyShellForInterface.fbx"; + var droneSound = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Lobby/drone.stereo.raw") var currentDrone = null; @@ -91,14 +95,14 @@ function drawLobby() { var orbPosition = Vec3.sum(Camera.position, Vec3.multiplyQbyV(towardsMe, ORB_SHIFT)); var panelWallProps = { - url: HIFI_PUBLIC_BUCKET + "models/sets/Lobby/Lobby_v8/forStephen1/PanelWall2.fbx", + url: LOBBY_PANEL_WALL_URL, position: Vec3.sum(orbPosition, Vec3.multiplyQbyV(towardsMe, panelsCenterShift)), rotation: towardsMe, dimensions: panelsDimensions }; var orbShellProps = { - url: HIFI_PUBLIC_BUCKET + "models/sets/Lobby/Lobby_v8/forStephen1/LobbyShell1.4_LightTag.fbx", + url: LOBBY_SHELL_URL, position: orbPosition, rotation: towardsMe, dimensions: orbDimensions, @@ -209,7 +213,7 @@ function cleanupLobby() { panelTexturesReset["textures"] = {}; for (var j = 0; j < MAX_NUM_PANELS; j++) { - panelTexturesReset["textures"]["file" + (j + 1)] = HIFI_PUBLIC_BUCKET + "models/sets/Lobby/LobbyPrototype/Texture.jpg"; + panelTexturesReset["textures"]["file" + (j + 1)] = LOBBY_BLANK_PANEL_TEXTURE_URL; }; Overlays.editOverlay(panelWall, panelTexturesReset); From f58d21d6f0c11a22aacd2483f66ee690b69e81b2 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 11 Dec 2014 10:21:11 -0800 Subject: [PATCH 341/502] have ShutdownEventListener handle WM_CLOSE or SIGTERM --- assignment-client/src/AssignmentClient.cpp | 10 ++++--- assignment-client/src/AssignmentClient.h | 2 -- .../src/AssignmentClientMonitor.cpp | 26 +++++++++---------- .../src/AssignmentClientMonitor.h | 1 + domain-server/src/DomainServer.cpp | 10 ++++--- domain-server/src/DomainServer.h | 3 --- .../shared/src/ShutdownEventListener.cpp | 26 +++++++++++++++++-- libraries/shared/src/ShutdownEventListener.h | 7 +++-- 8 files changed, 55 insertions(+), 30 deletions(-) diff --git a/assignment-client/src/AssignmentClient.cpp b/assignment-client/src/AssignmentClient.cpp index 9972adfda2..386d6e8a1d 100644 --- a/assignment-client/src/AssignmentClient.cpp +++ b/assignment-client/src/AssignmentClient.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include "AssignmentFactory.h" @@ -38,7 +39,6 @@ int hifiSockAddrMeta = qRegisterMetaType("HifiSockAddr"); AssignmentClient::AssignmentClient(int &argc, char **argv) : QCoreApplication(argc, argv), - _shutdownEventListener(this), _assignmentServerHostname(DEFAULT_ASSIGNMENT_SERVER_HOSTNAME), _localASPortSharedMem(NULL) { @@ -49,8 +49,12 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) : setApplicationName("assignment-client"); QSettings::setDefaultFormat(QSettings::IniFormat); - installNativeEventFilter(&_shutdownEventListener); - connect(&_shutdownEventListener, SIGNAL(receivedCloseEvent()), SLOT(quit())); + // setup a shutdown event listener to handle SIGTERM or WM_CLOSE for us +#ifdef _WIN32 + installNativeEventFilter(&ShutdownEventListener::getInstance()); +#else + ShutdownEventListener::getInstance(); +#endif // set the logging target to the the CHILD_TARGET_NAME LogHandler::getInstance().setTargetName(ASSIGNMENT_CLIENT_TARGET_NAME); diff --git a/assignment-client/src/AssignmentClient.h b/assignment-client/src/AssignmentClient.h index 566805d67f..053458f136 100644 --- a/assignment-client/src/AssignmentClient.h +++ b/assignment-client/src/AssignmentClient.h @@ -14,7 +14,6 @@ #include -#include "ShutdownEventListener.h" #include "ThreadedAssignment.h" class QSharedMemory; @@ -34,7 +33,6 @@ private slots: private: Assignment _requestAssignment; static SharedAssignmentPointer _currentAssignment; - ShutdownEventListener _shutdownEventListener; QString _assignmentServerHostname; HifiSockAddr _assignmentServerSocket; QSharedMemory* _localASPortSharedMem; diff --git a/assignment-client/src/AssignmentClientMonitor.cpp b/assignment-client/src/AssignmentClientMonitor.cpp index 358b963b4b..45e1f56d53 100644 --- a/assignment-client/src/AssignmentClientMonitor.cpp +++ b/assignment-client/src/AssignmentClientMonitor.cpp @@ -12,6 +12,7 @@ #include #include +#include #include "AssignmentClientMonitor.h" @@ -19,24 +20,19 @@ const char* NUM_FORKS_PARAMETER = "-n"; const QString ASSIGNMENT_CLIENT_MONITOR_TARGET_NAME = "assignment-client-monitor"; -void signalHandler(int param){ - // get the qApp and cast it to an AssignmentClientMonitor - AssignmentClientMonitor* app = qobject_cast(qApp); - - // tell it to stop the child processes and then go down - app->stopChildProcesses(); - app->quit(); -} - AssignmentClientMonitor::AssignmentClientMonitor(int &argc, char **argv, int numAssignmentClientForks) : QCoreApplication(argc, argv) -{ - // be a signal handler for SIGTERM so we can stop our children when we get it - signal(SIGTERM, signalHandler); - +{ // start the Logging class with the parent's target name LogHandler::getInstance().setTargetName(ASSIGNMENT_CLIENT_MONITOR_TARGET_NAME); + // setup a shutdown event listener to handle SIGTERM or WM_CLOSE for us +#ifdef _WIN32 + installNativeEventFilter(&ShutdownEventListener::getInstance()); +#else + ShutdownEventListener::getInstance(); +#endif + _childArguments = arguments(); // remove the parameter for the number of forks so it isn't passed to the child forked processes @@ -52,6 +48,10 @@ AssignmentClientMonitor::AssignmentClientMonitor(int &argc, char **argv, int num } } +AssignmentClientMonitor::~AssignmentClientMonitor() { + stopChildProcesses(); +} + void AssignmentClientMonitor::stopChildProcesses() { QList >::Iterator it = _childProcesses.begin(); diff --git a/assignment-client/src/AssignmentClientMonitor.h b/assignment-client/src/AssignmentClientMonitor.h index 9dbfcc495a..9a7bca9cb3 100644 --- a/assignment-client/src/AssignmentClientMonitor.h +++ b/assignment-client/src/AssignmentClientMonitor.h @@ -24,6 +24,7 @@ class AssignmentClientMonitor : public QCoreApplication { Q_OBJECT public: AssignmentClientMonitor(int &argc, char **argv, int numAssignmentClientForks); + ~AssignmentClientMonitor(); void stopChildProcesses(); private slots: diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 75db0b8022..bf9505671b 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include "DomainServerNodeData.h" @@ -41,7 +42,6 @@ const QString ICE_SERVER_DEFAULT_HOSTNAME = "ice.highfidelity.io"; DomainServer::DomainServer(int argc, char* argv[]) : QCoreApplication(argc, argv), - _shutdownEventListener(this), _httpManager(DOMAIN_SERVER_HTTP_PORT, QString("%1/resources/web/").arg(QCoreApplication::applicationDirPath()), this), _httpsManager(NULL), _allAssignments(), @@ -70,8 +70,12 @@ DomainServer::DomainServer(int argc, char* argv[]) : _settingsManager.setupConfigMap(arguments()); - installNativeEventFilter(&_shutdownEventListener); - connect(&_shutdownEventListener, SIGNAL(receivedCloseEvent()), SLOT(quit())); + // setup a shutdown event listener to handle SIGTERM or WM_CLOSE for us +#ifdef _WIN32 + installNativeEventFilter(&ShutdownEventListener::getInstance()); +#else + ShutdownEventListener::getInstance(); +#endif qRegisterMetaType("DomainServerWebSessionData"); qRegisterMetaTypeStreamOperators("DomainServerWebSessionData"); diff --git a/domain-server/src/DomainServer.h b/domain-server/src/DomainServer.h index 2a92c63923..76ab562f74 100644 --- a/domain-server/src/DomainServer.h +++ b/domain-server/src/DomainServer.h @@ -27,7 +27,6 @@ #include "DomainServerSettingsManager.h" #include "DomainServerWebSessionData.h" -#include "ShutdownEventListener.h" #include "WalletTransaction.h" #include "PendingAssignedNodeData.h" @@ -125,8 +124,6 @@ private: QJsonObject jsonForSocket(const HifiSockAddr& socket); QJsonObject jsonObjectForNode(const SharedNodePointer& node); - - ShutdownEventListener _shutdownEventListener; HTTPManager _httpManager; HTTPSManager* _httpsManager; diff --git a/libraries/shared/src/ShutdownEventListener.cpp b/libraries/shared/src/ShutdownEventListener.cpp index 6cd7592b69..94975b2418 100644 --- a/libraries/shared/src/ShutdownEventListener.cpp +++ b/libraries/shared/src/ShutdownEventListener.cpp @@ -9,21 +9,43 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include + #include "ShutdownEventListener.h" #ifdef Q_OS_WIN #include +#else +#include #endif -ShutdownEventListener::ShutdownEventListener(QObject* parent) : QObject(parent) { +ShutdownEventListener& ShutdownEventListener::getInstance() { + static ShutdownEventListener staticInstance; + return staticInstance; } +void signalHandler(int param) { + // tell the qApp it should quit + QMetaObject::invokeMethod(qApp, "quit"); +} + +ShutdownEventListener::ShutdownEventListener(QObject* parent) : + QObject(parent) +{ +#ifndef Q_OS_WIN + // be a signal handler for SIGTERM so we can stop our children when we get it + signal(SIGTERM, signalHandler); +#endif +} + + bool ShutdownEventListener::nativeEventFilter(const QByteArray &eventType, void* msg, long* result) { #ifdef Q_OS_WIN if (eventType == "windows_generic_MSG") { MSG* message = (MSG*)msg; if (message->message == WM_CLOSE) { - emit receivedCloseEvent(); + // tell our registered application to quit + QMetaObject::invokeMethod(qApp, "quit"); } } #endif diff --git a/libraries/shared/src/ShutdownEventListener.h b/libraries/shared/src/ShutdownEventListener.h index e39770c13d..f6d50401b2 100644 --- a/libraries/shared/src/ShutdownEventListener.h +++ b/libraries/shared/src/ShutdownEventListener.h @@ -18,12 +18,11 @@ class ShutdownEventListener : public QObject, public QAbstractNativeEventFilter { Q_OBJECT public: - ShutdownEventListener(QObject* parent = NULL); + static ShutdownEventListener& getInstance(); virtual bool nativeEventFilter(const QByteArray& eventType, void* message, long* result); - -signals: - void receivedCloseEvent(); +private: + ShutdownEventListener(QObject* parent = 0); }; #endif // hifi_ShutdownEventListener_h From 230b8740bf86ac9021c0f4b2b23628a1472d3e61 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 11 Dec 2014 11:23:27 -0800 Subject: [PATCH 342/502] add higher resolution images to lobby --- examples/lobby.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/lobby.js b/examples/lobby.js index 4528021a83..7163503a20 100644 --- a/examples/lobby.js +++ b/examples/lobby.js @@ -163,7 +163,8 @@ function changeLobbyTextures() { for (var j = 0; j < NUM_PANELS; j++) { var panelIndex = locationIndexToPanelIndex(j); - textureProp["textures"]["file" + panelIndex] = "http:" + locations[j].thumbnail_url; + textureProp["textures"]["file" + panelIndex] = HIFI_PUBLIC_BUCKET + "images/locations/" + + locations[j].id + "/hifi-location-" + locations[j].id + "_640x360.jpg"; }; Overlays.editOverlay(panelWall, textureProp); From b7d90236457d3fb42fcead9dc6d60f67f97e2668 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 11 Dec 2014 12:06:24 -0800 Subject: [PATCH 343/502] Don't stop defaultScripts --- examples/defaultScripts.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/examples/defaultScripts.js b/examples/defaultScripts.js index 0ffa2dba05..d39fce0186 100644 --- a/examples/defaultScripts.js +++ b/examples/defaultScripts.js @@ -15,5 +15,3 @@ Script.load("hydraMove.js"); Script.load("headMove.js"); Script.load("inspect.js"); Script.load("lobby.js"); - -Script.stop(); From c9bc95580d9d6be8f76a37c349802f5997b59d21 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 11 Dec 2014 12:30:17 -0800 Subject: [PATCH 344/502] add support for generic windowWatcher that keeps dialogs from being moved to HMD display --- interface/src/Application.cpp | 2 + interface/src/Application.h | 1 + interface/src/Menu.cpp | 13 +++ interface/src/ui/HMDToolsDialog.cpp | 155 +++++++++++++++++----------- interface/src/ui/HMDToolsDialog.h | 27 ++++- 5 files changed, 135 insertions(+), 63 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index cb3acc88f1..19055ab61b 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -142,6 +142,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : QApplication(argc, argv), _window(new MainWindow(desktop())), _glWidget(new GLCanvas()), + _toolWindow(NULL), _nodeThread(new QThread(this)), _datagramProcessor(), _undoStack(), @@ -371,6 +372,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : _glWidget->setMouseTracking(true); _toolWindow = new ToolWindow(); + qDebug() << "_toolWindow:" << _toolWindow; _toolWindow->setWindowFlags(_toolWindow->windowFlags() | Qt::WindowStaysOnTopHint); _toolWindow->setWindowTitle("Tools"); diff --git a/interface/src/Application.h b/interface/src/Application.h index 217d547c89..57b0cd2c2c 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -329,6 +329,7 @@ public: bool isHMDMode() const; QRect getDesirableApplicationGeometry(); + RunningScriptsWidget* getRunningScriptsWidget() { return _runningScriptsWidget; } signals: diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index ae12b5ff26..5e35f08e95 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -1303,6 +1303,10 @@ void Menu::bandwidthDetails() { connect(_bandwidthDialog, SIGNAL(closed()), SLOT(bandwidthDetailsClosed())); _bandwidthDialog->show(); + + if (_hmdToolsDialog) { + _hmdToolsDialog->watchWindow(_bandwidthDialog->windowHandle()); + } } _bandwidthDialog->raise(); } @@ -1384,6 +1388,9 @@ void Menu::toggleConsole() { void Menu::toggleToolWindow() { QMainWindow* toolWindow = Application::getInstance()->getToolWindow(); toolWindow->setVisible(!toolWindow->isVisible()); + if (_hmdToolsDialog) { + _hmdToolsDialog->watchWindow(toolWindow->windowHandle()); + } } void Menu::audioMuteToggled() { @@ -1406,6 +1413,9 @@ void Menu::octreeStatsDetails() { Application::getInstance()->getOcteeSceneStats()); connect(_octreeStatsDialog, SIGNAL(closed()), SLOT(octreeStatsDetailsClosed())); _octreeStatsDialog->show(); + if (_hmdToolsDialog) { + _hmdToolsDialog->watchWindow(_octreeStatsDialog->windowHandle()); + } } _octreeStatsDialog->raise(); } @@ -1586,6 +1596,9 @@ void Menu::lodTools() { _lodToolsDialog = new LodToolsDialog(Application::getInstance()->getGLWidget()); connect(_lodToolsDialog, SIGNAL(closed()), SLOT(lodToolsClosed())); _lodToolsDialog->show(); + if (_hmdToolsDialog) { + _hmdToolsDialog->watchWindow(_lodToolsDialog->windowHandle()); + } } _lodToolsDialog->raise(); } diff --git a/interface/src/ui/HMDToolsDialog.cpp b/interface/src/ui/HMDToolsDialog.cpp index 580490f83b..ab84980d80 100644 --- a/interface/src/ui/HMDToolsDialog.cpp +++ b/interface/src/ui/HMDToolsDialog.cpp @@ -67,12 +67,22 @@ HMDToolsDialog::HMDToolsDialog(QWidget* parent) : // watch for our dialog window moving screens. If it does we want to enforce our rules about // what screens we're allowed on - QWindow* dialogWindow = windowHandle(); - connect(dialogWindow, &QWindow::screenChanged, this, &HMDToolsDialog::dialogWindowScreenChanged); - connect(dialogWindow, &QWindow::xChanged, this, &HMDToolsDialog::dialogWindowGeometryChanged); - connect(dialogWindow, &QWindow::yChanged, this, &HMDToolsDialog::dialogWindowGeometryChanged); - connect(dialogWindow, &QWindow::widthChanged, this, &HMDToolsDialog::dialogWindowGeometryChanged); - connect(dialogWindow, &QWindow::heightChanged, this, &HMDToolsDialog::dialogWindowGeometryChanged); + watchWindow(windowHandle()); + if (Application::getInstance()->getRunningScriptsWidget()) { + watchWindow(Application::getInstance()->getRunningScriptsWidget()->windowHandle()); + } + if (Application::getInstance()->getToolWindow()) { + watchWindow(Application::getInstance()->getToolWindow()->windowHandle()); + } + if (Menu::getInstance()->getBandwidthDialog()) { + watchWindow(Menu::getInstance()->getBandwidthDialog()->windowHandle()); + } + if (Menu::getInstance()->getOctreeStatsDialog()) { + watchWindow(Menu::getInstance()->getOctreeStatsDialog()->windowHandle()); + } + if (Menu::getInstance()->getLodToolsDialog()) { + watchWindow(Menu::getInstance()->getLodToolsDialog()->windowHandle()); + } // when the application is about to quit, leave HDM mode connect(Application::getInstance(), SIGNAL(aboutToQuit()), this, SLOT(aboutToQuit())); @@ -82,67 +92,16 @@ HMDToolsDialog::HMDToolsDialog(QWidget* parent) : } HMDToolsDialog::~HMDToolsDialog() { + foreach(HMDWindowWatcher* watcher, _windowWatchers) { + delete watcher; + } + _windowWatchers.clear(); } void HMDToolsDialog::applicationWindowScreenChanged(QScreen* screen) { _debugDetails->setText(getDebugDetails()); } -void HMDToolsDialog::dialogWindowGeometryChanged(int arg) { - QWindow* dialogWindow = windowHandle(); - _previousDialogRect = rect(); - _previousDialogRect = QRect(dialogWindow->mapToGlobal(_previousDialogRect.topLeft()), - dialogWindow->mapToGlobal(_previousDialogRect.bottomRight())); - _previousDialogScreen = dialogWindow->screen(); -} - -void HMDToolsDialog::dialogWindowScreenChanged(QScreen* screen) { - _debugDetails->setText(getDebugDetails()); - - // if we have more than one screen, and a known hmdScreen then try to - // keep our dialog off of the hmdScreen - if (QApplication::desktop()->screenCount() > 1) { - - // we want to use a local variable here because we are not necesarily in HMD mode - int hmdScreenNumber = OculusManager::getHMDScreen(); - if (_hmdScreenNumber >= 0) { - QScreen* hmdScreen = QGuiApplication::screens()[hmdScreenNumber]; - if (screen == hmdScreen) { - qDebug() << "HMD Tools: Whoa! What are you doing? You don't want to move me to the HMD Screen!"; - QWindow* dialogWindow = windowHandle(); - - // try to pick a better screen - QScreen* betterScreen = NULL; - - QWindow* appWindow = Application::getInstance()->getWindow()->windowHandle(); - QScreen* appScreen = appWindow->screen(); - - if (_previousDialogScreen && _previousDialogScreen != hmdScreen) { - // first, if the previous dialog screen is not the HMD screen, then move it there. - betterScreen = appScreen; - } else if (appScreen != hmdScreen) { - // second, if the application screen is not the HMD screen, then move it there. - betterScreen = appScreen; - } else if (_previousScreen && _previousScreen != hmdScreen) { - // third, if the application screen is the HMD screen, we want to move it to - // the previous screen - betterScreen = _previousScreen; - } else { - // last, if we can't use the previous screen the use the primary desktop screen - int desktopPrimaryScreenNumber = QApplication::desktop()->primaryScreen(); - QScreen* desktopPrimaryScreen = QGuiApplication::screens()[desktopPrimaryScreenNumber]; - betterScreen = desktopPrimaryScreen; - } - - if (betterScreen) { - dialogWindow->setScreen(betterScreen); - dialogWindow->setGeometry(_previousDialogRect); - } - } - } - } -} - QString HMDToolsDialog::getDebugDetails() const { QString results; @@ -304,5 +263,79 @@ void HMDToolsDialog::screenCountChanged(int newCount) { _debugDetails->setText(getDebugDetails()); } +void HMDToolsDialog::watchWindow(QWindow* window) { + qDebug() << "HMDToolsDialog::watchWindow() window:" << window; + if (window && !_windowWatchers.contains(window)) { + HMDWindowWatcher* watcher = new HMDWindowWatcher(window, this); + _windowWatchers[window] = watcher; + } +} + + +HMDWindowWatcher::HMDWindowWatcher(QWindow* window, HMDToolsDialog* hmdTools) : + _window(window), + _hmdTools(hmdTools), + _previousScreen(NULL) +{ + connect(window, &QWindow::screenChanged, this, &HMDWindowWatcher::windowScreenChanged); + connect(window, &QWindow::xChanged, this, &HMDWindowWatcher::windowGeometryChanged); + connect(window, &QWindow::yChanged, this, &HMDWindowWatcher::windowGeometryChanged); + connect(window, &QWindow::widthChanged, this, &HMDWindowWatcher::windowGeometryChanged); + connect(window, &QWindow::heightChanged, this, &HMDWindowWatcher::windowGeometryChanged); +} + +HMDWindowWatcher::~HMDWindowWatcher() { +} + + +void HMDWindowWatcher::windowGeometryChanged(int arg) { + _previousRect = _window->geometry(); + _previousScreen = _window->screen(); +} + +void HMDWindowWatcher::windowScreenChanged(QScreen* screen) { + // if we have more than one screen, and a known hmdScreen then try to + // keep our dialog off of the hmdScreen + if (QApplication::desktop()->screenCount() > 1) { + + // we want to use a local variable here because we are not necesarily in HMD mode + int hmdScreenNumber = OculusManager::getHMDScreen(); + if (hmdScreenNumber >= 0) { + QScreen* hmdScreen = QGuiApplication::screens()[hmdScreenNumber]; + if (screen == hmdScreen) { + qDebug() << "HMD Tools: Whoa! What are you doing? You don't want to move me to the HMD Screen!"; + + // try to pick a better screen + QScreen* betterScreen = NULL; + + QScreen* lastApplicationScreen = _hmdTools->getLastApplicationScreen(); + QWindow* appWindow = Application::getInstance()->getWindow()->windowHandle(); + QScreen* appScreen = appWindow->screen(); + + if (_previousScreen && _previousScreen != hmdScreen) { + // first, if the previous dialog screen is not the HMD screen, then move it there. + betterScreen = _previousScreen; + } else if (appScreen != hmdScreen) { + // second, if the application screen is not the HMD screen, then move it there. + betterScreen = appScreen; + } else if (lastApplicationScreen && lastApplicationScreen != hmdScreen) { + // third, if the application screen is the HMD screen, we want to move it to + // the previous screen + betterScreen = lastApplicationScreen; + } else { + // last, if we can't use the previous screen the use the primary desktop screen + int desktopPrimaryScreenNumber = QApplication::desktop()->primaryScreen(); + QScreen* desktopPrimaryScreen = QGuiApplication::screens()[desktopPrimaryScreenNumber]; + betterScreen = desktopPrimaryScreen; + } + + if (betterScreen) { + _window->setScreen(betterScreen); + _window->setGeometry(_previousRect); + } + } + } + } +} diff --git a/interface/src/ui/HMDToolsDialog.h b/interface/src/ui/HMDToolsDialog.h index d539b58d04..10dc1c5c80 100644 --- a/interface/src/ui/HMDToolsDialog.h +++ b/interface/src/ui/HMDToolsDialog.h @@ -14,6 +14,8 @@ #include +class HMDWindowWatcher; + class HMDToolsDialog : public QDialog { Q_OBJECT public: @@ -23,7 +25,9 @@ public: QString getDebugDetails() const; QScreen* getHMDScreen() const { return _hmdScreen; } + QScreen* getLastApplicationScreen() const { return _previousScreen; } bool hasHMDScreen() const { return _hmdScreenNumber >= -1; } + void watchWindow(QWindow* window); signals: void closed(); @@ -34,8 +38,6 @@ public slots: void activateWindowAfterEnterMode(); void moveWindowAfterLeaveMode(); void applicationWindowScreenChanged(QScreen* screen); - void dialogWindowScreenChanged(QScreen* screen); - void dialogWindowGeometryChanged(int arg); void aboutToQuit(); void screenCountChanged(int newCount); @@ -60,6 +62,27 @@ private: QRect _previousDialogRect; QScreen* _previousDialogScreen; bool _inHDMMode; + + QHash _windowWatchers; +}; + + +class HMDWindowWatcher : public QObject { + Q_OBJECT +public: + // Sets up the UI + HMDWindowWatcher(QWindow* window, HMDToolsDialog* hmdTools); + ~HMDWindowWatcher(); + +public slots: + void windowScreenChanged(QScreen* screen); + void windowGeometryChanged(int arg); + +private: + QWindow* _window; + HMDToolsDialog* _hmdTools; + QRect _previousRect; + QScreen* _previousScreen; }; #endif // hifi_HMDToolsDialog_h From 29672aec096f86932371b22b5c7b3fb9fb3fceea Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 11 Dec 2014 13:55:10 -0800 Subject: [PATCH 345/502] removing VoxelShader and PointShader which were both disabled --- interface/src/Application.cpp | 4 - interface/src/Application.h | 6 - interface/src/Menu.h | 2 - interface/src/renderer/PointShader.cpp | 80 ----- interface/src/renderer/PointShader.h | 48 --- interface/src/renderer/VoxelShader.cpp | 73 ----- interface/src/renderer/VoxelShader.h | 49 --- interface/src/voxels/VoxelSystem.cpp | 425 ++++++------------------- interface/src/voxels/VoxelSystem.h | 17 - 9 files changed, 99 insertions(+), 605 deletions(-) delete mode 100644 interface/src/renderer/PointShader.cpp delete mode 100644 interface/src/renderer/PointShader.h delete mode 100644 interface/src/renderer/VoxelShader.cpp delete mode 100644 interface/src/renderer/VoxelShader.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 32d4557c66..a57b157e64 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1915,8 +1915,6 @@ void Application::init() { _deferredLightingEffect.init(); _glowEffect.init(); _ambientOcclusionEffect.init(); - _voxelShader.init(); - _pointShader.init(); // TODO: move _myAvatar out of Application. Move relevant code to MyAvataar or AvatarManager _avatarManager.init(); @@ -1987,8 +1985,6 @@ void Application::init() { // Set up VoxelSystem after loading preferences so we can get the desired max voxel count _voxels.setMaxVoxels(Menu::getInstance()->getMaxVoxels()); - _voxels.setUseVoxelShader(false); - _voxels.setVoxelsAsPoints(false); _voxels.setDisableFastVoxelPipeline(false); _voxels.init(); diff --git a/interface/src/Application.h b/interface/src/Application.h index 5700b7fb87..96858a6c73 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -64,9 +64,7 @@ #include "renderer/DeferredLightingEffect.h" #include "renderer/GeometryCache.h" #include "renderer/GlowEffect.h" -#include "renderer/PointShader.h" #include "renderer/TextureCache.h" -#include "renderer/VoxelShader.h" #include "scripting/ControllerScriptingInterface.h" #include "ui/BandwidthDialog.h" #include "ui/BandwidthMeter.h" @@ -295,8 +293,6 @@ public: NodeBounds& getNodeBoundsDisplay() { return _nodeBoundsDisplay; } - VoxelShader& getVoxelShader() { return _voxelShader; } - PointShader& getPointShader() { return _pointShader; } FileLogger* getLogger() { return _logger; } glm::vec2 getViewportDimensions() const { return glm::vec2(_glWidget->getDeviceWidth(), _glWidget->getDeviceHeight()); } @@ -588,8 +584,6 @@ private: DeferredLightingEffect _deferredLightingEffect; GlowEffect _glowEffect; AmbientOcclusionEffect _ambientOcclusionEffect; - VoxelShader _voxelShader; - PointShader _pointShader; Audio _audio; diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 138828d3e8..e2c687fff1 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -123,7 +123,6 @@ public: LodToolsDialog* getLodToolsDialog() const { return _lodToolsDialog; } HMDToolsDialog* getHMDToolsDialog() const { return _hmdToolsDialog; } int getMaxVoxels() const { return _maxVoxels; } - QAction* getUseVoxelShader() const { return _useVoxelShader; } bool getShadowsEnabled() const; @@ -304,7 +303,6 @@ private: float _avatarLODIncreaseFPS; float _avatarLODDistanceMultiplier; int _boundaryLevelAdjust; - QAction* _useVoxelShader; int _maxVoxelPacketsPerSecond; QString replaceLastOccurrence(QChar search, QChar replace, QString string); quint64 _lastAdjust; diff --git a/interface/src/renderer/PointShader.cpp b/interface/src/renderer/PointShader.cpp deleted file mode 100644 index 68df69f284..0000000000 --- a/interface/src/renderer/PointShader.cpp +++ /dev/null @@ -1,80 +0,0 @@ -// -// PointShader.cpp -// interface/src/renderer -// -// Created by Brad Hefta-Gaub on 10/30/13. -// Copyright 2013 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 this before QOpenGLFramebufferObject, which includes an earlier version of OpenGL -#include "InterfaceConfig.h" - -#include - -#include "Application.h" -#include "PointShader.h" -#include "ProgramObject.h" -#include "RenderUtil.h" - -PointShader::PointShader() - : _initialized(false) -{ - _program = NULL; -} - -PointShader::~PointShader() { - if (_initialized) { - delete _program; - } -} - -ProgramObject* PointShader::createPointShaderProgram(const QString& name) { - ProgramObject* program = new ProgramObject(); - program->addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/" + name + ".vert" ); - program->link(); - return program; -} - -void PointShader::init() { - if (_initialized) { - qDebug("[ERROR] PointShader is already initialized."); - return; - } - _program = createPointShaderProgram("point_size"); - _initialized = true; -} - -void PointShader::begin() { - _program->bind(); -} - -void PointShader::end() { - _program->release(); -} - -int PointShader::attributeLocation(const char* name) const { - if (_program) { - return _program->attributeLocation(name); - } else { - return -1; - } -} - -int PointShader::uniformLocation(const char* name) const { - if (_program) { - return _program->uniformLocation(name); - } else { - return -1; - } -} - -void PointShader::setUniformValue(int uniformLocation, float value) { - _program->setUniformValue(uniformLocation, value); -} - -void PointShader::setUniformValue(int uniformLocation, const glm::vec3& value) { - _program->setUniformValue(uniformLocation, value.x, value.y, value.z); -} diff --git a/interface/src/renderer/PointShader.h b/interface/src/renderer/PointShader.h deleted file mode 100644 index 1db4f1b201..0000000000 --- a/interface/src/renderer/PointShader.h +++ /dev/null @@ -1,48 +0,0 @@ -// -// PointShader.h -// interface/src/renderer -// -// Created by Brad Hefta-Gaub on 10/30/13. -// Copyright 2013 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_PointShader_h -#define hifi_PointShader_h - -#include - -class ProgramObject; - -/// A shader program that draws voxels as points with variable sizes -class PointShader : public QObject { - Q_OBJECT - -public: - PointShader(); - ~PointShader(); - - void init(); - - /// Starts using the voxel point shader program. - void begin(); - - /// Stops using the voxel point shader program. - void end(); - - /// Gets access to attributes from the shader program - int attributeLocation(const char* name) const; - int uniformLocation(const char* name) const; - void setUniformValue(int uniformLocation, float value); - void setUniformValue(int uniformLocation, const glm::vec3& value); - - static ProgramObject* createPointShaderProgram(const QString& name); - -private: - bool _initialized; - ProgramObject* _program; -}; - -#endif // hifi_PointShader_h diff --git a/interface/src/renderer/VoxelShader.cpp b/interface/src/renderer/VoxelShader.cpp deleted file mode 100644 index 0982304adf..0000000000 --- a/interface/src/renderer/VoxelShader.cpp +++ /dev/null @@ -1,73 +0,0 @@ -// -// VoxelShader.cpp -// interface/src/renderer -// -// Created by Brad Hefta-Gaub on 9/22/13. -// Copyright 2013 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 this before QOpenGLFramebufferObject, which includes an earlier version of OpenGL -#include "InterfaceConfig.h" - -#include - -#include "Application.h" -#include "VoxelShader.h" -#include "ProgramObject.h" -#include "RenderUtil.h" - -VoxelShader::VoxelShader() - : _initialized(false) -{ - _program = NULL; -} - -VoxelShader::~VoxelShader() { - if (_initialized) { - delete _program; - } -} - -ProgramObject* VoxelShader::createGeometryShaderProgram(const QString& name) { - ProgramObject* program = new ProgramObject(); - program->addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/passthrough.vert" ); - program->addShaderFromSourceFile(QGLShader::Geometry, Application::resourcesPath() + "shaders/" + name + ".geom" ); - program->setGeometryInputType(GL_POINTS); - program->setGeometryOutputType(GL_TRIANGLE_STRIP); - const int VERTICES_PER_FACE = 4; - const int FACES_PER_VOXEL = 6; - const int VERTICES_PER_VOXEL = VERTICES_PER_FACE * FACES_PER_VOXEL; - program->setGeometryOutputVertexCount(VERTICES_PER_VOXEL); - program->link(); - return program; -} - -void VoxelShader::init() { - if (_initialized) { - qDebug("[ERROR] TestProgram is already initialized."); - return; - } - - _program = createGeometryShaderProgram("voxel"); - _initialized = true; -} - -void VoxelShader::begin() { - _program->bind(); -} - -void VoxelShader::end() { - _program->release(); -} - -int VoxelShader::attributeLocation(const char * name) const { - if (_program) { - return _program->attributeLocation(name); - } else { - return -1; - } -} - diff --git a/interface/src/renderer/VoxelShader.h b/interface/src/renderer/VoxelShader.h deleted file mode 100644 index cfcd27bba7..0000000000 --- a/interface/src/renderer/VoxelShader.h +++ /dev/null @@ -1,49 +0,0 @@ -// -// VoxelShader.h -// interface/src/renderer -// -// Created by Brad Hefta-Gaub on 9/23/13. -// Copyright 2013 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_VoxelShader_h -#define hifi_VoxelShader_h - -#include - -class ProgramObject; - -/// A generic full screen glow effect. -class VoxelShader : public QObject { - Q_OBJECT - -public: - VoxelShader(); - ~VoxelShader(); - - void init(); - - /// Starts using the voxel geometry shader effect. - void begin(); - - /// Stops using the voxel geometry shader effect. - void end(); - - /// Gets access to attributes from the shader program - int attributeLocation(const char * name) const; - - static ProgramObject* createGeometryShaderProgram(const QString& name); - -public slots: - -private: - - bool _initialized; - - ProgramObject* _program; -}; - -#endif // hifi_VoxelShader_h diff --git a/interface/src/voxels/VoxelSystem.cpp b/interface/src/voxels/VoxelSystem.cpp index 8d16245962..8fbaf65f37 100644 --- a/interface/src/voxels/VoxelSystem.cpp +++ b/interface/src/voxels/VoxelSystem.cpp @@ -92,13 +92,6 @@ VoxelSystem::VoxelSystem(float treeScale, int maxVoxels, VoxelTree* tree) _viewFrustum = Application::getInstance()->getViewFrustum(); - _useVoxelShader = false; - _voxelsAsPoints = false; - _voxelShaderModeWhenVoxelsAsPointsEnabled = false; - - _writeVoxelShaderData = NULL; - _readVoxelShaderData = NULL; - _readVerticesArray = NULL; _writeVerticesArray = NULL; _readColorsArray = NULL; @@ -270,106 +263,30 @@ void VoxelSystem::setMaxVoxels(unsigned long maxVoxels) { } } -// This is called by the main application thread on both the initialization of the application and when -// the use voxel shader menu item is chosen -void VoxelSystem::setUseVoxelShader(bool useVoxelShader) { - if (_useVoxelShader == useVoxelShader) { - return; - } - - bool wasInitialized = _initialized; - if (wasInitialized) { - clearAllNodesBufferIndex(); - cleanupVoxelMemory(); - } - _useVoxelShader = useVoxelShader; - _usePrimitiveRenderer = false; - if (wasInitialized) { - initVoxelMemory(); - } - - if (wasInitialized) { - forceRedrawEntireTree(); - } -} - -void VoxelSystem::setVoxelsAsPoints(bool voxelsAsPoints) { - if (_voxelsAsPoints == voxelsAsPoints) { - return; - } - - bool wasInitialized = _initialized; - - // If we're "turning on" Voxels as points, we need to double check that we're in voxel shader mode. - // Voxels as points uses the VoxelShader memory model, so if we're not in voxel shader mode, - // then set it to voxel shader mode. - if (voxelsAsPoints) { - Menu::getInstance()->getUseVoxelShader()->setEnabled(false); - - // If enabling this... then do it before checking voxel shader status, that way, if voxel - // shader is already enabled, we just start drawing as points. - _voxelsAsPoints = true; - - if (!_useVoxelShader) { - setUseVoxelShader(true); - _voxelShaderModeWhenVoxelsAsPointsEnabled = false; - } else { - _voxelShaderModeWhenVoxelsAsPointsEnabled = true; - } - } else { - Menu::getInstance()->getUseVoxelShader()->setEnabled(true); - // if we're turning OFF voxels as point mode, then we check what the state of voxel shader was when we enabled - // voxels as points, if it was OFF, then we return it to that value. - if (_voxelShaderModeWhenVoxelsAsPointsEnabled == false) { - setUseVoxelShader(false); - } - // If disabling this... then do it AFTER checking previous voxel shader status, that way, if voxel - // shader is was not enabled, we switch back to normal mode before turning off points. - _voxelsAsPoints = false; - } - - // Set our voxels as points - if (wasInitialized) { - forceRedrawEntireTree(); - } -} - void VoxelSystem::cleanupVoxelMemory() { if (_initialized) { _readArraysLock.lockForWrite(); _initialized = false; // no longer initialized - if (_useVoxelShader) { - // these are used when in VoxelShader mode. - glDeleteBuffers(1, &_vboVoxelsID); - glDeleteBuffers(1, &_vboVoxelsIndicesID); + // Destroy glBuffers + glDeleteBuffers(1, &_vboVerticesID); + glDeleteBuffers(1, &_vboColorsID); - delete[] _writeVoxelShaderData; - delete[] _readVoxelShaderData; + glDeleteBuffers(1, &_vboIndicesTop); + glDeleteBuffers(1, &_vboIndicesBottom); + glDeleteBuffers(1, &_vboIndicesLeft); + glDeleteBuffers(1, &_vboIndicesRight); + glDeleteBuffers(1, &_vboIndicesFront); + glDeleteBuffers(1, &_vboIndicesBack); - _writeVoxelShaderData = _readVoxelShaderData = NULL; + delete[] _readVerticesArray; + delete[] _writeVerticesArray; + delete[] _readColorsArray; + delete[] _writeColorsArray; - } else { - // Destroy glBuffers - glDeleteBuffers(1, &_vboVerticesID); - glDeleteBuffers(1, &_vboColorsID); - - glDeleteBuffers(1, &_vboIndicesTop); - glDeleteBuffers(1, &_vboIndicesBottom); - glDeleteBuffers(1, &_vboIndicesLeft); - glDeleteBuffers(1, &_vboIndicesRight); - glDeleteBuffers(1, &_vboIndicesFront); - glDeleteBuffers(1, &_vboIndicesBack); - - delete[] _readVerticesArray; - delete[] _writeVerticesArray; - delete[] _readColorsArray; - delete[] _writeColorsArray; - - _readVerticesArray = NULL; - _writeVerticesArray = NULL; - _readColorsArray = NULL; - _writeColorsArray = NULL; - } + _readVerticesArray = NULL; + _writeVerticesArray = NULL; + _readColorsArray = NULL; + _writeColorsArray = NULL; delete _renderer; _renderer = 0; @@ -417,102 +334,55 @@ void VoxelSystem::initVoxelMemory() { _memoryUsageRAM = 0; _memoryUsageVBO = 0; // our VBO allocations as we know them - // if _voxelsAsPoints then we must have _useVoxelShader - if (_voxelsAsPoints && !_useVoxelShader) { - _useVoxelShader = true; - } + // Global Normals mode uses a technique of not including normals on any voxel vertices, and instead + // rendering the voxel faces in 6 passes that use a global call to glNormal3f() + setupFaceIndices(_vboIndicesTop, identityIndicesTop); + setupFaceIndices(_vboIndicesBottom, identityIndicesBottom); + setupFaceIndices(_vboIndicesLeft, identityIndicesLeft); + setupFaceIndices(_vboIndicesRight, identityIndicesRight); + setupFaceIndices(_vboIndicesFront, identityIndicesFront); + setupFaceIndices(_vboIndicesBack, identityIndicesBack); - if (_useVoxelShader) { - GLuint* indicesArray = new GLuint[_maxVoxels]; + // Depending on if we're using per vertex normals, we will need more or less vertex points per voxel + int vertexPointsPerVoxel = GLOBAL_NORMALS_VERTEX_POINTS_PER_VOXEL; + glGenBuffers(1, &_vboVerticesID); + glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID); + glBufferData(GL_ARRAY_BUFFER, vertexPointsPerVoxel * sizeof(GLfloat) * _maxVoxels, NULL, GL_DYNAMIC_DRAW); + _memoryUsageVBO += vertexPointsPerVoxel * sizeof(GLfloat) * _maxVoxels; - // populate the indicesArray - // this will not change given new voxels, so we can set it all up now - for (unsigned long n = 0; n < _maxVoxels; n++) { - indicesArray[n] = n; - } + // VBO for colorsArray + glGenBuffers(1, &_vboColorsID); + glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID); + glBufferData(GL_ARRAY_BUFFER, vertexPointsPerVoxel * sizeof(GLubyte) * _maxVoxels, NULL, GL_DYNAMIC_DRAW); + _memoryUsageVBO += vertexPointsPerVoxel * sizeof(GLubyte) * _maxVoxels; - // bind the indices VBO to the actual indices array - glGenBuffers(1, &_vboVoxelsIndicesID); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboVoxelsIndicesID); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * _maxVoxels, indicesArray, GL_STATIC_DRAW); - _memoryUsageVBO += sizeof(GLuint) * _maxVoxels; + // we will track individual dirty sections with these arrays of bools + _writeVoxelDirtyArray = new bool[_maxVoxels]; + memset(_writeVoxelDirtyArray, false, _maxVoxels * sizeof(bool)); + _memoryUsageRAM += (sizeof(bool) * _maxVoxels); - glGenBuffers(1, &_vboVoxelsID); - glBindBuffer(GL_ARRAY_BUFFER, _vboVoxelsID); - glBufferData(GL_ARRAY_BUFFER, _maxVoxels * sizeof(VoxelShaderVBOData), NULL, GL_DYNAMIC_DRAW); - _memoryUsageVBO += _maxVoxels * sizeof(VoxelShaderVBOData); + _readVoxelDirtyArray = new bool[_maxVoxels]; + memset(_readVoxelDirtyArray, false, _maxVoxels * sizeof(bool)); + _memoryUsageRAM += (sizeof(bool) * _maxVoxels); - // delete the indices and normals arrays that are no longer needed - delete[] indicesArray; + // prep the data structures for incoming voxel data + _writeVerticesArray = new GLfloat[vertexPointsPerVoxel * _maxVoxels]; + _memoryUsageRAM += (sizeof(GLfloat) * vertexPointsPerVoxel * _maxVoxels); + _readVerticesArray = new GLfloat[vertexPointsPerVoxel * _maxVoxels]; + _memoryUsageRAM += (sizeof(GLfloat) * vertexPointsPerVoxel * _maxVoxels); - // we will track individual dirty sections with these arrays of bools - _writeVoxelDirtyArray = new bool[_maxVoxels]; - memset(_writeVoxelDirtyArray, false, _maxVoxels * sizeof(bool)); - _memoryUsageRAM += (_maxVoxels * sizeof(bool)); + _writeColorsArray = new GLubyte[vertexPointsPerVoxel * _maxVoxels]; + _memoryUsageRAM += (sizeof(GLubyte) * vertexPointsPerVoxel * _maxVoxels); + _readColorsArray = new GLubyte[vertexPointsPerVoxel * _maxVoxels]; + _memoryUsageRAM += (sizeof(GLubyte) * vertexPointsPerVoxel * _maxVoxels); - _readVoxelDirtyArray = new bool[_maxVoxels]; - memset(_readVoxelDirtyArray, false, _maxVoxels * sizeof(bool)); - _memoryUsageRAM += (_maxVoxels * sizeof(bool)); - - // prep the data structures for incoming voxel data - _writeVoxelShaderData = new VoxelShaderVBOData[_maxVoxels]; - _memoryUsageRAM += (sizeof(VoxelShaderVBOData) * _maxVoxels); - - _readVoxelShaderData = new VoxelShaderVBOData[_maxVoxels]; - _memoryUsageRAM += (sizeof(VoxelShaderVBOData) * _maxVoxels); - - } else { - - // Global Normals mode uses a technique of not including normals on any voxel vertices, and instead - // rendering the voxel faces in 6 passes that use a global call to glNormal3f() - setupFaceIndices(_vboIndicesTop, identityIndicesTop); - setupFaceIndices(_vboIndicesBottom, identityIndicesBottom); - setupFaceIndices(_vboIndicesLeft, identityIndicesLeft); - setupFaceIndices(_vboIndicesRight, identityIndicesRight); - setupFaceIndices(_vboIndicesFront, identityIndicesFront); - setupFaceIndices(_vboIndicesBack, identityIndicesBack); - - // Depending on if we're using per vertex normals, we will need more or less vertex points per voxel - int vertexPointsPerVoxel = GLOBAL_NORMALS_VERTEX_POINTS_PER_VOXEL; - glGenBuffers(1, &_vboVerticesID); - glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID); - glBufferData(GL_ARRAY_BUFFER, vertexPointsPerVoxel * sizeof(GLfloat) * _maxVoxels, NULL, GL_DYNAMIC_DRAW); - _memoryUsageVBO += vertexPointsPerVoxel * sizeof(GLfloat) * _maxVoxels; - - // VBO for colorsArray - glGenBuffers(1, &_vboColorsID); - glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID); - glBufferData(GL_ARRAY_BUFFER, vertexPointsPerVoxel * sizeof(GLubyte) * _maxVoxels, NULL, GL_DYNAMIC_DRAW); - _memoryUsageVBO += vertexPointsPerVoxel * sizeof(GLubyte) * _maxVoxels; - - // we will track individual dirty sections with these arrays of bools - _writeVoxelDirtyArray = new bool[_maxVoxels]; - memset(_writeVoxelDirtyArray, false, _maxVoxels * sizeof(bool)); - _memoryUsageRAM += (sizeof(bool) * _maxVoxels); - - _readVoxelDirtyArray = new bool[_maxVoxels]; - memset(_readVoxelDirtyArray, false, _maxVoxels * sizeof(bool)); - _memoryUsageRAM += (sizeof(bool) * _maxVoxels); - - // prep the data structures for incoming voxel data - _writeVerticesArray = new GLfloat[vertexPointsPerVoxel * _maxVoxels]; - _memoryUsageRAM += (sizeof(GLfloat) * vertexPointsPerVoxel * _maxVoxels); - _readVerticesArray = new GLfloat[vertexPointsPerVoxel * _maxVoxels]; - _memoryUsageRAM += (sizeof(GLfloat) * vertexPointsPerVoxel * _maxVoxels); - - _writeColorsArray = new GLubyte[vertexPointsPerVoxel * _maxVoxels]; - _memoryUsageRAM += (sizeof(GLubyte) * vertexPointsPerVoxel * _maxVoxels); - _readColorsArray = new GLubyte[vertexPointsPerVoxel * _maxVoxels]; - _memoryUsageRAM += (sizeof(GLubyte) * vertexPointsPerVoxel * _maxVoxels); - - // create our simple fragment shader if we're the first system to init - if (!_program.isLinked()) { - _program.addShaderFromSourceFile(QGLShader::Vertex, - Application::resourcesPath() + "shaders/voxel.vert"); - _program.addShaderFromSourceFile(QGLShader::Fragment, - Application::resourcesPath() + "shaders/voxel.frag"); - _program.link(); - } + // create our simple fragment shader if we're the first system to init + if (!_program.isLinked()) { + _program.addShaderFromSourceFile(QGLShader::Vertex, + Application::resourcesPath() + "shaders/voxel.vert"); + _program.addShaderFromSourceFile(QGLShader::Fragment, + Application::resourcesPath() + "shaders/voxel.frag"); + _program.link(); } _renderer = new PrimitiveRenderer(_maxVoxels); @@ -882,25 +752,18 @@ void VoxelSystem::copyWrittenDataToReadArraysPartialVBOs() { void VoxelSystem::copyWrittenDataSegmentToReadArrays(glBufferIndex segmentStart, glBufferIndex segmentEnd) { int segmentLength = (segmentEnd - segmentStart) + 1; - if (_useVoxelShader) { - GLsizeiptr segmentSizeBytes = segmentLength * sizeof(VoxelShaderVBOData); - void* readDataAt = &_readVoxelShaderData[segmentStart]; - void* writeDataAt = &_writeVoxelShaderData[segmentStart]; - memcpy(readDataAt, writeDataAt, segmentSizeBytes); - } else { - // Depending on if we're using per vertex normals, we will need more or less vertex points per voxel - int vertexPointsPerVoxel = GLOBAL_NORMALS_VERTEX_POINTS_PER_VOXEL; + // Depending on if we're using per vertex normals, we will need more or less vertex points per voxel + int vertexPointsPerVoxel = GLOBAL_NORMALS_VERTEX_POINTS_PER_VOXEL; - GLsizeiptr segmentSizeBytes = segmentLength * vertexPointsPerVoxel * sizeof(GLfloat); - GLfloat* readVerticesAt = _readVerticesArray + (segmentStart * vertexPointsPerVoxel); - GLfloat* writeVerticesAt = _writeVerticesArray + (segmentStart * vertexPointsPerVoxel); - memcpy(readVerticesAt, writeVerticesAt, segmentSizeBytes); + GLsizeiptr segmentSizeBytes = segmentLength * vertexPointsPerVoxel * sizeof(GLfloat); + GLfloat* readVerticesAt = _readVerticesArray + (segmentStart * vertexPointsPerVoxel); + GLfloat* writeVerticesAt = _writeVerticesArray + (segmentStart * vertexPointsPerVoxel); + memcpy(readVerticesAt, writeVerticesAt, segmentSizeBytes); - segmentSizeBytes = segmentLength * vertexPointsPerVoxel * sizeof(GLubyte); - GLubyte* readColorsAt = _readColorsArray + (segmentStart * vertexPointsPerVoxel); - GLubyte* writeColorsAt = _writeColorsArray + (segmentStart * vertexPointsPerVoxel); - memcpy(readColorsAt, writeColorsAt, segmentSizeBytes); - } + segmentSizeBytes = segmentLength * vertexPointsPerVoxel * sizeof(GLubyte); + GLubyte* readColorsAt = _readColorsArray + (segmentStart * vertexPointsPerVoxel); + GLubyte* writeColorsAt = _writeColorsArray + (segmentStart * vertexPointsPerVoxel); + memcpy(readColorsAt, writeColorsAt, segmentSizeBytes); } void VoxelSystem::copyWrittenDataToReadArrays(bool fullVBOs) { @@ -1101,31 +964,15 @@ void VoxelSystem::updateArraysDetails(glBufferIndex nodeIndex, const glm::vec3& if (_initialized && nodeIndex <= _maxVoxels) { _writeVoxelDirtyArray[nodeIndex] = true; - if (_useVoxelShader) { - // write in position, scale, and color for the voxel - - if (_writeVoxelShaderData) { - VoxelShaderVBOData* writeVerticesAt = &_writeVoxelShaderData[nodeIndex]; - writeVerticesAt->x = startVertex.x * TREE_SCALE; - writeVerticesAt->y = startVertex.y * TREE_SCALE; - writeVerticesAt->z = startVertex.z * TREE_SCALE; - writeVerticesAt->s = voxelScale * TREE_SCALE; - writeVerticesAt->r = color[RED_INDEX]; - writeVerticesAt->g = color[GREEN_INDEX]; - writeVerticesAt->b = color[BLUE_INDEX]; - } - } else { - if (_writeVerticesArray && _writeColorsArray) { - int vertexPointsPerVoxel = GLOBAL_NORMALS_VERTEX_POINTS_PER_VOXEL; - for (int j = 0; j < vertexPointsPerVoxel; j++ ) { - GLfloat* writeVerticesAt = _writeVerticesArray + (nodeIndex * vertexPointsPerVoxel); - GLubyte* writeColorsAt = _writeColorsArray + (nodeIndex * vertexPointsPerVoxel); - *(writeVerticesAt+j) = startVertex[j % 3] + (identityVerticesGlobalNormals[j] * voxelScale); - *(writeColorsAt +j) = color[j % 3]; - } + if (_writeVerticesArray && _writeColorsArray) { + int vertexPointsPerVoxel = GLOBAL_NORMALS_VERTEX_POINTS_PER_VOXEL; + for (int j = 0; j < vertexPointsPerVoxel; j++ ) { + GLfloat* writeVerticesAt = _writeVerticesArray + (nodeIndex * vertexPointsPerVoxel); + GLubyte* writeColorsAt = _writeColorsArray + (nodeIndex * vertexPointsPerVoxel); + *(writeVerticesAt+j) = startVertex[j % 3] + (identityVerticesGlobalNormals[j] * voxelScale); + *(writeColorsAt +j) = color[j % 3]; } } - } } @@ -1253,44 +1100,34 @@ void VoxelSystem::updateVBOSegment(glBufferIndex segmentStart, glBufferIndex seg bool showWarning = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); PerformanceWarning warn(showWarning, "updateVBOSegment()"); - if (_useVoxelShader) { - int segmentLength = (segmentEnd - segmentStart) + 1; - GLintptr segmentStartAt = segmentStart * sizeof(VoxelShaderVBOData); - GLsizeiptr segmentSizeBytes = segmentLength * sizeof(VoxelShaderVBOData); - void* readVerticesFrom = &_readVoxelShaderData[segmentStart]; + int vertexPointsPerVoxel = GLOBAL_NORMALS_VERTEX_POINTS_PER_VOXEL; + int segmentLength = (segmentEnd - segmentStart) + 1; + GLintptr segmentStartAt = segmentStart * vertexPointsPerVoxel * sizeof(GLfloat); + GLsizeiptr segmentSizeBytes = segmentLength * vertexPointsPerVoxel * sizeof(GLfloat); + GLfloat* readVerticesFrom = _readVerticesArray + (segmentStart * vertexPointsPerVoxel); - glBindBuffer(GL_ARRAY_BUFFER, _vboVoxelsID); + { + PerformanceWarning warn(showWarning, "updateVBOSegment() : glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID);"); + glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID); + } + + { + PerformanceWarning warn(showWarning, "updateVBOSegment() : glBufferSubData() _vboVerticesID);"); glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readVerticesFrom); - } else { - int vertexPointsPerVoxel = GLOBAL_NORMALS_VERTEX_POINTS_PER_VOXEL; - int segmentLength = (segmentEnd - segmentStart) + 1; - GLintptr segmentStartAt = segmentStart * vertexPointsPerVoxel * sizeof(GLfloat); - GLsizeiptr segmentSizeBytes = segmentLength * vertexPointsPerVoxel * sizeof(GLfloat); - GLfloat* readVerticesFrom = _readVerticesArray + (segmentStart * vertexPointsPerVoxel); + } - { - PerformanceWarning warn(showWarning, "updateVBOSegment() : glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID);"); - glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID); - } + segmentStartAt = segmentStart * vertexPointsPerVoxel * sizeof(GLubyte); + segmentSizeBytes = segmentLength * vertexPointsPerVoxel * sizeof(GLubyte); + GLubyte* readColorsFrom = _readColorsArray + (segmentStart * vertexPointsPerVoxel); - { - PerformanceWarning warn(showWarning, "updateVBOSegment() : glBufferSubData() _vboVerticesID);"); - glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readVerticesFrom); - } + { + PerformanceWarning warn(showWarning, "updateVBOSegment() : glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID);"); + glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID); + } - segmentStartAt = segmentStart * vertexPointsPerVoxel * sizeof(GLubyte); - segmentSizeBytes = segmentLength * vertexPointsPerVoxel * sizeof(GLubyte); - GLubyte* readColorsFrom = _readColorsArray + (segmentStart * vertexPointsPerVoxel); - - { - PerformanceWarning warn(showWarning, "updateVBOSegment() : glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID);"); - glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID); - } - - { - PerformanceWarning warn(showWarning, "updateVBOSegment() : glBufferSubData() _vboColorsID);"); - glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readColorsFrom); - } + { + PerformanceWarning warn(showWarning, "updateVBOSegment() : glBufferSubData() _vboColorsID);"); + glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readColorsFrom); } } @@ -1306,70 +1143,6 @@ void VoxelSystem::render() { updateVBOs(); - // if not don't... then do... - if (_useVoxelShader) { - PerformanceWarning warn(showWarnings,"render().. _useVoxelShader openGL.."); - - - //Define this somewhere in your header file - #define BUFFER_OFFSET(i) ((void*)(i)) - - glBindBuffer(GL_ARRAY_BUFFER, _vboVoxelsID); - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(3, GL_FLOAT, sizeof(VoxelShaderVBOData), BUFFER_OFFSET(0)); //The starting point of the VBO, for the vertices - - int attributeLocation; - - if (!_voxelsAsPoints) { - Application::getInstance()->getVoxelShader().begin(); - attributeLocation = Application::getInstance()->getVoxelShader().attributeLocation("voxelSizeIn"); - glEnableVertexAttribArray(attributeLocation); - glVertexAttribPointer(attributeLocation, 1, GL_FLOAT, false, sizeof(VoxelShaderVBOData), BUFFER_OFFSET(3*sizeof(float))); - } else { - glEnable(GL_VERTEX_PROGRAM_POINT_SIZE); - - glm::vec2 viewDimensions = Application::getInstance()->getViewportDimensions(); - float viewportWidth = viewDimensions.x; - float viewportHeight = viewDimensions.y; - glm::vec3 cameraPosition = Application::getInstance()->getViewFrustum()->getPosition(); - PointShader& pointShader = Application::getInstance()->getPointShader(); - - pointShader.begin(); - - pointShader.setUniformValue(pointShader.uniformLocation("viewportWidth"), viewportWidth); - pointShader.setUniformValue(pointShader.uniformLocation("viewportHeight"), viewportHeight); - pointShader.setUniformValue(pointShader.uniformLocation("cameraPosition"), cameraPosition); - - attributeLocation = pointShader.attributeLocation("voxelSizeIn"); - glEnableVertexAttribArray(attributeLocation); - glVertexAttribPointer(attributeLocation, 1, GL_FLOAT, false, sizeof(VoxelShaderVBOData), BUFFER_OFFSET(3*sizeof(float))); - } - - - glEnableClientState(GL_COLOR_ARRAY); - glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(VoxelShaderVBOData), BUFFER_OFFSET(4*sizeof(float)));//The starting point of colors - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboVoxelsIndicesID); - - glDrawElements(GL_POINTS, _voxelsInReadArrays, GL_UNSIGNED_INT, BUFFER_OFFSET(0)); //The starting point of the IBO - - // deactivate vertex and color arrays after drawing - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_COLOR_ARRAY); - - // bind with 0 to switch back to normal operation - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - - if (!_voxelsAsPoints) { - Application::getInstance()->getVoxelShader().end(); - glDisableVertexAttribArray(attributeLocation); - } else { - Application::getInstance()->getPointShader().end(); - glDisableVertexAttribArray(attributeLocation); - glDisable(GL_VERTEX_PROGRAM_POINT_SIZE); - } - } else if (!_usePrimitiveRenderer) { if (_drawHaze) { glEnable(GL_FOG); diff --git a/interface/src/voxels/VoxelSystem.h b/interface/src/voxels/VoxelSystem.h index 8e60cbe073..4f4c624e15 100644 --- a/interface/src/voxels/VoxelSystem.h +++ b/interface/src/voxels/VoxelSystem.h @@ -25,7 +25,6 @@ #include "Camera.h" #include "Util.h" #include "world.h" -#include "renderer/VoxelShader.h" #include "PrimitiveRenderer.h" class ProgramObject; @@ -33,14 +32,6 @@ class ProgramObject; const int NUM_CHILDREN = 8; -struct VoxelShaderVBOData -{ - float x, y, z; // position - float s; // size - unsigned char r,g,b; // color -}; - - class VoxelSystem : public NodeData, public OctreeElementDeleteHook, public OctreeElementUpdateHook { Q_OBJECT @@ -97,8 +88,6 @@ public slots: void clearAllNodesBufferIndex(); void setDisableFastVoxelPipeline(bool disableFastVoxelPipeline); - void setUseVoxelShader(bool useVoxelShader); - void setVoxelsAsPoints(bool voxelsAsPoints); protected: float _treeScale; @@ -191,14 +180,8 @@ private: void initVoxelMemory(); void cleanupVoxelMemory(); - bool _useVoxelShader; - bool _voxelsAsPoints; - bool _voxelShaderModeWhenVoxelsAsPointsEnabled; - GLuint _vboVoxelsID; /// when using voxel shader, we'll use this VBO GLuint _vboVoxelsIndicesID; /// when using voxel shader, we'll use this VBO for our indexes - VoxelShaderVBOData* _writeVoxelShaderData; - VoxelShaderVBOData* _readVoxelShaderData; GLuint _vboVerticesID; GLuint _vboColorsID; From 208d3c8413579611e1b6f01a39d046ab82d451cb Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 11 Dec 2014 13:59:21 -0800 Subject: [PATCH 346/502] remove old unused shaders --- interface/resources/shaders/passthrough.vert | 21 --- interface/resources/shaders/point_size.vert | 174 ------------------- interface/resources/shaders/voxel.geom | 87 ---------- 3 files changed, 282 deletions(-) delete mode 100644 interface/resources/shaders/passthrough.vert delete mode 100644 interface/resources/shaders/point_size.vert delete mode 100644 interface/resources/shaders/voxel.geom diff --git a/interface/resources/shaders/passthrough.vert b/interface/resources/shaders/passthrough.vert deleted file mode 100644 index bb0a18eefa..0000000000 --- a/interface/resources/shaders/passthrough.vert +++ /dev/null @@ -1,21 +0,0 @@ -#version 120 - -// -// passthrough.vert -// vertex shader -// -// Copyright 2013 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 -// - -attribute float voxelSizeIn; -varying float voxelSize; - -void main(void) { - gl_FrontColor = gl_Color; - gl_Position = gl_Vertex; // don't call ftransform(), because we do projection in geometry shader - voxelSize = voxelSizeIn; -} \ No newline at end of file diff --git a/interface/resources/shaders/point_size.vert b/interface/resources/shaders/point_size.vert deleted file mode 100644 index 88c56bf0c4..0000000000 --- a/interface/resources/shaders/point_size.vert +++ /dev/null @@ -1,174 +0,0 @@ -#version 120 - -// -// point_size.vert -// vertex shader -// -// Copyright 2013 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 -// - -attribute float voxelSizeIn; -varying float voxelSize; - -uniform float viewportWidth; -uniform float viewportHeight; -uniform vec3 cameraPosition; - -// Bit codes for faces -const int NONE = 0; -const int RIGHT = 1; -const int LEFT = 2; -const int BOTTOM = 4; -const int BOTTOM_RIGHT = BOTTOM + RIGHT; -const int BOTTOM_LEFT = BOTTOM + LEFT; -const int TOP = 8; -const int TOP_RIGHT = TOP + RIGHT; -const int TOP_LEFT = TOP + LEFT; -const int NEAR = 16; -const int NEAR_RIGHT = NEAR + RIGHT; -const int NEAR_LEFT = NEAR + LEFT; -const int NEAR_BOTTOM = NEAR + BOTTOM; -const int NEAR_BOTTOM_RIGHT = NEAR + BOTTOM + RIGHT; -const int NEAR_BOTTOM_LEFT = NEAR + BOTTOM + LEFT; -const int NEAR_TOP = NEAR + TOP; -const int NEAR_TOP_RIGHT = NEAR + TOP + RIGHT; -const int NEAR_TOP_LEFT = NEAR + TOP + LEFT; -const int FAR = 32; -const int FAR_RIGHT = FAR + RIGHT; -const int FAR_LEFT = FAR + LEFT; -const int FAR_BOTTOM = FAR + BOTTOM; -const int FAR_BOTTOM_RIGHT = FAR + BOTTOM + RIGHT; -const int FAR_BOTTOM_LEFT = FAR + BOTTOM + LEFT; -const int FAR_TOP = FAR + TOP; -const int FAR_TOP_RIGHT = FAR + TOP + RIGHT; -const int FAR_TOP_LEFT = FAR + TOP + LEFT; - -// If we know the position of the camera relative to the voxel, we can a priori know the vertices that make the visible hull -// polygon. This also tells us which two vertices are known to make the longest possible distance between any pair of these -// vertices for the projected polygon. This is a visibleFaces table based on this knowledge. - -void main(void) { - // Note: the gl_Vertex in this case are in "world coordinates" meaning they've already been scaled to TREE_SCALE - // this is also true for voxelSizeIn. - vec4 bottomNearRight = gl_Vertex; - vec4 topFarLeft = (gl_Vertex + vec4(voxelSizeIn, voxelSizeIn, voxelSizeIn, 0.0)); - - int visibleFaces = NONE; - - // In order to use our visibleFaces "table" (implemented as if statements) below, we need to encode the 6-bit code to - // orient camera relative to the 6 defining faces of the voxel. Based on camera position relative to the bottomNearRight - // corner and the topFarLeft corner, we can calculate which hull and therefore which two vertices are furthest apart - // linearly once projected - if (cameraPosition.x < bottomNearRight.x) { - visibleFaces += RIGHT; - } - if (cameraPosition.x > topFarLeft.x) { - visibleFaces += LEFT; - } - if (cameraPosition.y < bottomNearRight.y) { - visibleFaces += BOTTOM; - } - if (cameraPosition.y > topFarLeft.y) { - visibleFaces += TOP; - } - if (cameraPosition.z < bottomNearRight.z) { - visibleFaces += NEAR; - } - if (cameraPosition.z > topFarLeft.z) { - visibleFaces += FAR; - } - - vec4 cornerAdjustOne; - vec4 cornerAdjustTwo; - - if (visibleFaces == RIGHT) { - cornerAdjustOne = vec4(0,0,0,0) * voxelSizeIn; - cornerAdjustTwo = vec4(0,1,1,0) * voxelSizeIn; - } else if (visibleFaces == LEFT) { - cornerAdjustOne = vec4(1,0,0,0) * voxelSizeIn; - cornerAdjustTwo = vec4(1,1,1,0) * voxelSizeIn; - } else if (visibleFaces == BOTTOM) { - cornerAdjustOne = vec4(0,0,0,0) * voxelSizeIn; - cornerAdjustTwo = vec4(1,0,1,0) * voxelSizeIn; - } else if (visibleFaces == TOP) { - cornerAdjustOne = vec4(0,1,0,0) * voxelSizeIn; - cornerAdjustTwo = vec4(1,1,1,0) * voxelSizeIn; - } else if (visibleFaces == NEAR) { - cornerAdjustOne = vec4(0,0,0,0) * voxelSizeIn; - cornerAdjustTwo = vec4(1,1,0,0) * voxelSizeIn; - } else if (visibleFaces == FAR) { - cornerAdjustOne = vec4(0,0,1,0) * voxelSizeIn; - cornerAdjustTwo = vec4(1,1,1,0) * voxelSizeIn; - } else if (visibleFaces == NEAR_BOTTOM_LEFT || - visibleFaces == FAR_TOP || - visibleFaces == FAR_TOP_RIGHT) { - cornerAdjustOne = vec4(0,1,0,0) * voxelSizeIn; - cornerAdjustTwo = vec4(1,0,1,0) * voxelSizeIn; - } else if (visibleFaces == FAR_TOP_LEFT || - visibleFaces == NEAR_RIGHT || - visibleFaces == NEAR_BOTTOM || - visibleFaces == NEAR_BOTTOM_RIGHT) { - cornerAdjustOne = vec4(0,0,1,0) * voxelSizeIn; - cornerAdjustTwo = vec4(1,1,0,0) * voxelSizeIn; - } else if (visibleFaces == NEAR_TOP_RIGHT || - visibleFaces == FAR_LEFT || - visibleFaces == FAR_BOTTOM_LEFT || - visibleFaces == BOTTOM_RIGHT || - visibleFaces == TOP_LEFT) { - cornerAdjustOne = vec4(1,0,0,0) * voxelSizeIn; - cornerAdjustTwo = vec4(0,1,1,0) * voxelSizeIn; - - // Everything else... - //} else if (visibleFaces == BOTTOM_LEFT || - // visibleFaces == TOP_RIGHT || - // visibleFaces == NEAR_LEFT || - // visibleFaces == FAR_RIGHT || - // visibleFaces == NEAR_TOP || - // visibleFaces == NEAR_TOP_LEFT || - // visibleFaces == FAR_BOTTOM || - // visibleFaces == FAR_BOTTOM_RIGHT) { - } else { - cornerAdjustOne = vec4(0,0,0,0) * voxelSizeIn; - cornerAdjustTwo = vec4(1,1,1,0) * voxelSizeIn; - } - - // Determine our corners - vec4 cornerOne = gl_Vertex + cornerAdjustOne; - vec4 cornerTwo = gl_Vertex + cornerAdjustTwo; - - // Find their model view projections - vec4 cornerOneMVP = gl_ModelViewProjectionMatrix * cornerOne; - vec4 cornerTwoMVP = gl_ModelViewProjectionMatrix * cornerTwo; - - // Map to x, y screen coordinates - vec2 cornerOneScreen = vec2(cornerOneMVP.x / cornerOneMVP.w, cornerOneMVP.y / cornerOneMVP.w); - if (cornerOneMVP.w < 0) { - cornerOneScreen.x = -cornerOneScreen.x; - cornerOneScreen.y = -cornerOneScreen.y; - } - - vec2 cornerTwoScreen = vec2(cornerTwoMVP.x / cornerTwoMVP.w, cornerTwoMVP.y / cornerTwoMVP.w); - if (cornerTwoMVP.w < 0) { - cornerTwoScreen.x = -cornerTwoScreen.x; - cornerTwoScreen.y = -cornerTwoScreen.y; - } - - // Find the distance between them in pixels - float voxelScreenWidth = abs(cornerOneScreen.x - cornerTwoScreen.x) * viewportWidth / 2.0; - float voxelScreenHeight = abs(cornerOneScreen.y - cornerTwoScreen.y) * viewportHeight / 2.0; - float voxelScreenLength = sqrt(voxelScreenHeight * voxelScreenHeight + voxelScreenWidth * voxelScreenWidth); - - // Find the center of the voxel - vec4 centerVertex = gl_Vertex; - float halfSizeIn = voxelSizeIn / 2; - centerVertex += vec4(halfSizeIn, halfSizeIn, halfSizeIn, 0.0); - vec4 center = gl_ModelViewProjectionMatrix * centerVertex; - - // Finally place the point at the center of the voxel, with a size equal to the maximum screen length - gl_Position = center; - gl_PointSize = voxelScreenLength; - gl_FrontColor = gl_Color; -} \ No newline at end of file diff --git a/interface/resources/shaders/voxel.geom b/interface/resources/shaders/voxel.geom deleted file mode 100644 index 4c850ed608..0000000000 --- a/interface/resources/shaders/voxel.geom +++ /dev/null @@ -1,87 +0,0 @@ -#version 120 -#extension GL_ARB_geometry_shader4 : enable - -// -// voxel.geom -// geometry shader -// -// Copyright 2013 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 -// - -// -// VOXEL GEOMETRY SHADER -// -// Input: gl_VerticesIn/gl_PositionIn -// GL_POINTS -// Assumes vertex shader has not transformed coordinates -// Each gl_PositionIn is the corner of voxel -// varying voxelSize - which is the voxel size -// -// Note: In vertex shader doesn't do any transform. Therefore passing the 3D world coordinates xyz to us -// -// Output: GL_TRIANGLE_STRIP -// -// Issues: -// how do we need to handle lighting of these colors?? -// how do we handle normals? -// check for size=0 and don't output the primitive -// - -varying in float voxelSize[1]; - -const int VERTICES_PER_FACE = 4; -const int COORD_PER_VERTEX = 3; -const int COORD_PER_FACE = COORD_PER_VERTEX * VERTICES_PER_FACE; - -void faceOfVoxel(vec4 corner, float scale, float[COORD_PER_FACE] facePoints, vec4 color, vec4 normal) { - for (int v = 0; v < VERTICES_PER_FACE; v++ ) { - vec4 vertex = corner; - for (int c = 0; c < COORD_PER_VERTEX; c++ ) { - int cIndex = c + (v * COORD_PER_VERTEX); - vertex[c] += (facePoints[cIndex] * scale); - } - - gl_FrontColor = color * (gl_LightModel.ambient + gl_LightSource[0].ambient + - gl_LightSource[0].diffuse * max(0.0, dot(normal, gl_LightSource[0].position))); - - gl_Position = gl_ModelViewProjectionMatrix * vertex; - EmitVertex(); - } - EndPrimitive(); -} - - -void main() { - //increment variable - int i; - vec4 corner; - float scale; - - float bottomFace[COORD_PER_FACE] = float[COORD_PER_FACE]( 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1 ); - float topFace[COORD_PER_FACE] = float[COORD_PER_FACE]( 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1 ); - float rightFace[COORD_PER_FACE] = float[COORD_PER_FACE]( 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1 ); - float leftFace[COORD_PER_FACE] = float[COORD_PER_FACE]( 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1 ); - float frontFace[COORD_PER_FACE] = float[COORD_PER_FACE]( 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0 ); - float backFace[COORD_PER_FACE] = float[COORD_PER_FACE]( 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1 ); - - vec4 bottomNormal = vec4(0.0, -1, 0.0, 0.0); - vec4 topNormal = vec4(0.0, 1, 0.0, 0.0); - vec4 rightNormal = vec4( -1, 0.0, 0.0, 0.0); - vec4 leftNormal = vec4( 1, 0.0, 0.0, 0.0); - vec4 frontNormal = vec4(0.0, 0.0, -1, 0.0); - vec4 backNormal = vec4(0.0, 0.0, 1, 0.0); - - for(i = 0; i < gl_VerticesIn; i++) { - corner = gl_PositionIn[i]; - scale = voxelSize[i]; - faceOfVoxel(corner, scale, bottomFace, gl_FrontColorIn[i], bottomNormal); - faceOfVoxel(corner, scale, topFace, gl_FrontColorIn[i], topNormal ); - faceOfVoxel(corner, scale, rightFace, gl_FrontColorIn[i], rightNormal ); - faceOfVoxel(corner, scale, leftFace, gl_FrontColorIn[i], leftNormal ); - faceOfVoxel(corner, scale, frontFace, gl_FrontColorIn[i], frontNormal ); - faceOfVoxel(corner, scale, backFace, gl_FrontColorIn[i], backNormal ); - } -} \ No newline at end of file From 3eb7314c98684c00a18e16a3fe16f82ebd82e0cc Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 11 Dec 2014 14:13:44 -0800 Subject: [PATCH 347/502] remove PrimitiveRenderer --- interface/src/voxels/PrimitiveRenderer.cpp | 742 --------------------- interface/src/voxels/PrimitiveRenderer.h | 503 -------------- interface/src/voxels/VoxelSystem.cpp | 534 ++------------- interface/src/voxels/VoxelSystem.h | 15 - 4 files changed, 61 insertions(+), 1733 deletions(-) delete mode 100644 interface/src/voxels/PrimitiveRenderer.cpp delete mode 100644 interface/src/voxels/PrimitiveRenderer.h diff --git a/interface/src/voxels/PrimitiveRenderer.cpp b/interface/src/voxels/PrimitiveRenderer.cpp deleted file mode 100644 index a212245289..0000000000 --- a/interface/src/voxels/PrimitiveRenderer.cpp +++ /dev/null @@ -1,742 +0,0 @@ -// -// PrimitiveRenderer.cpp -// interface/src/voxels -// -// 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 "InterfaceConfig.h" -#include "OctreeElement.h" -#include "PrimitiveRenderer.h" - -Primitive::Primitive() { -} - -Primitive::~Primitive() { -} - -// Simple dispatch between API and SPI - -const VertexElementList& Primitive::vertexElements() const { - return vVertexElements(); -} - -VertexElementIndexList& Primitive::vertexElementIndices() { - return vVertexElementIndices(); -} - -TriElementList& Primitive::triElements() { - return vTriElements(); -} - -void Primitive::releaseVertexElements() { - vReleaseVertexElements(); -} - -unsigned long Primitive::getMemoryUsage() { - return vGetMemoryUsage(); -} - - -Cube::Cube( - float x, - float y, - float z, - float s, - unsigned char r, - unsigned char g, - unsigned char b, - unsigned char faceExclusions - ) : - _cpuMemoryUsage(0) { - init(x, y, z, s, r, g, b, faceExclusions); -} - -Cube::~Cube() { - terminate(); -} - -void Cube::init( - float x, - float y, - float z, - float s, - unsigned char r, - unsigned char g, - unsigned char b, - unsigned char faceExclusions - ) { - - initializeVertices(x, y, z, s, r, g, b, faceExclusions); - initializeTris(faceExclusions); -} - -void Cube::terminate() { - - terminateTris(); - terminateVertices(); -} - -void Cube::initializeVertices( - float x, - float y, - float z, - float s, - unsigned char r, - unsigned char g, - unsigned char b, - unsigned char faceExclusions - ) { - - for (int i = 0; i < _sNumVerticesPerCube; i++) { - // Check whether the vertex is necessary for the faces indicated by faceExclusions bit mask. - // uncomment this line to load all faces: if (~0x00 & _sFaceIndexToHalfSpaceMask[i >> 2]) { - // uncomment this line to include shared faces: if (faceExclusions & _sFaceIndexToHalfSpaceMask[i >> 2]) { - // uncomment this line to exclude shared faces: - if (~faceExclusions & _sFaceIndexToHalfSpaceMask[i >> 2]) { - - VertexElement* v = new VertexElement(); - if (v) { - // Construct vertex position - v->position.x = x + s * _sVertexIndexToConstructionVector[i][0]; - v->position.y = y + s * _sVertexIndexToConstructionVector[i][1]; - v->position.z = z + s * _sVertexIndexToConstructionVector[i][2]; - - // Construct vertex normal - v->normal.x = _sVertexIndexToNormalVector[i >> 2][0]; - v->normal.y = _sVertexIndexToNormalVector[i >> 2][1]; - v->normal.z = _sVertexIndexToNormalVector[i >> 2][2]; - - // Construct vertex color -//#define FALSE_COLOR -#ifndef FALSE_COLOR - v->color.r = r; - v->color.g = g; - v->color.b = b; - v->color.a = 255; -#else - static unsigned char falseColor[6][3] = { - 192, 0, 0, // Bot - 0, 192, 0, // Top - 0, 0, 192, // Right - 192, 0, 192, // Left - 192, 192, 0, // Near - 192, 192, 192 // Far - }; - v->color.r = falseColor[i >> 2][0]; - v->color.g = falseColor[i >> 2][1]; - v->color.b = falseColor[i >> 2][2]; - v->color.a = 255; -#endif - - // Add vertex element to list - _vertices.push_back(v); - _cpuMemoryUsage += sizeof(VertexElement); - _cpuMemoryUsage += sizeof(VertexElement*); - } - } - } -} - -void Cube::terminateVertices() { - - for (VertexElementList::iterator it = _vertices.begin(); it != _vertices.end(); ++it) { - delete *it; - } - _cpuMemoryUsage -= _vertices.size() * (sizeof(VertexElement) + sizeof(VertexElement*)); - _vertices.clear(); -} - -void Cube::initializeTris( - unsigned char faceExclusions - ) { - - int index = 0; - for (int i = 0; i < _sNumFacesPerCube; i++) { - // Check whether the vertex is necessary for the faces indicated by faceExclusions bit mask. - // uncomment this line to load all faces: if (~0x00 & _sFaceIndexToHalfSpaceMask[i]) { - // uncomment this line to include shared faces: if (faceExclusions & _sFaceIndexToHalfSpaceMask[i]) { - // uncomment this line to exclude shared faces: - if (~faceExclusions & _sFaceIndexToHalfSpaceMask[i]) { - - int start = index; - // Create the triangulated face, two tris, six indices referencing four vertices, both - // with cw winding order, such that: - - // A-B - // |\| - // D-C - - // Store triangle ABC - - TriElement* tri = new TriElement(); - if (tri) { - tri->indices[0] = index++; - tri->indices[1] = index++; - tri->indices[2] = index; - - // Add tri element to list - _tris.push_back(tri); - _cpuMemoryUsage += sizeof(TriElement); - _cpuMemoryUsage += sizeof(TriElement*); - } - - // Now store triangle ACD - tri = new TriElement(); - if (tri) { - tri->indices[0] = start; - tri->indices[1] = index++; - tri->indices[2] = index++; - - // Add tri element to list - _tris.push_back(tri); - _cpuMemoryUsage += sizeof(TriElement); - _cpuMemoryUsage += sizeof(TriElement*); - } - } - } -} - -void Cube::terminateTris() { - - for (TriElementList::iterator it = _tris.begin(); it != _tris.end(); ++it) { - delete *it; - } - _cpuMemoryUsage -= _tris.size() * (sizeof(TriElement) + sizeof(TriElement*)); - _tris.clear(); -} - -const VertexElementList& Cube::vVertexElements() const { - return _vertices; -} - -VertexElementIndexList& Cube::vVertexElementIndices() { - return _vertexIndices; -} - -TriElementList& Cube::vTriElements() { - return _tris; -} - -void Cube::vReleaseVertexElements() { - terminateVertices(); -} - -unsigned long Cube::vGetMemoryUsage() { - return _cpuMemoryUsage; -} - -unsigned char Cube::_sFaceIndexToHalfSpaceMask[6] = { - OctreeElement::HalfSpace::Bottom, - OctreeElement::HalfSpace::Top, - OctreeElement::HalfSpace::Right, - OctreeElement::HalfSpace::Left, - OctreeElement::HalfSpace::Near, - OctreeElement::HalfSpace::Far, -}; - -// Construction vectors ordered such that the vertices of each face are -// clockwise in a right-handed coordinate system with B-L-N at 0,0,0. -float Cube::_sVertexIndexToConstructionVector[24][3] = { - // Bottom - { 0,0,0 }, - { 1,0,0 }, - { 1,0,1 }, - { 0,0,1 }, - // Top - { 0,1,0 }, - { 0,1,1 }, - { 1,1,1 }, - { 1,1,0 }, - // Right - { 1,0,0 }, - { 1,1,0 }, - { 1,1,1 }, - { 1,0,1 }, - // Left - { 0,0,0 }, - { 0,0,1 }, - { 0,1,1 }, - { 0,1,0 }, - // Near - { 0,0,0 }, - { 0,1,0 }, - { 1,1,0 }, - { 1,0,0 }, - // Far - { 0,0,1 }, - { 1,0,1 }, - { 1,1,1 }, - { 0,1,1 }, -}; - -// Normals for a right-handed coordinate system -float Cube::_sVertexIndexToNormalVector[6][3] = { - { 0,-1, 0 }, // Bottom - { 0, 1, 0 }, // Top - { 1, 0, 0 }, // Right - { -1, 0, 0 }, // Left - { 0, 0,-1 }, // Near - { 0, 0, 1 }, // Far -}; - -Renderer::Renderer() { -} - -Renderer::~Renderer() { -} - -// Simple dispatch between API and SPI -int Renderer::add( - Primitive* primitive - ) { - return vAdd(primitive); -} - -void Renderer::remove( - int id - ) { - vRemove(id); -} - -void Renderer::release() { - vRelease(); -} - -void Renderer::render() { - vRender(); -} - -unsigned long Renderer::getMemoryUsage() { - return vGetMemoryUsage(); -} - -unsigned long Renderer::getMemoryUsageGPU() { - return vGetMemoryUsageGPU(); -} - -PrimitiveRenderer::PrimitiveRenderer( - int maxCount - ) : - _maxCount(maxCount), - _triBufferId(0), - _vertexBufferId(0), - - _vertexElementCount(0), - _maxVertexElementCount(0), - - _triElementCount(0), - _maxTriElementCount(0), - - _primitives(), - _primitiveCount(0), - - _gpuMemoryUsage(0), - _cpuMemoryUsage(0) - -{ - init(); -} - -PrimitiveRenderer::~PrimitiveRenderer() { - - terminate(); -} - -void PrimitiveRenderer::init() { - - initializeGL(); - initializeBookkeeping(); -} - -void PrimitiveRenderer::initializeGL() { - - glGenBuffers(1, &_triBufferId); - glGenBuffers(1, &_vertexBufferId); - - // Set up the element array buffer containing the index ids - _maxTriElementCount = _maxCount * 2; - int size = _maxTriElementCount * _sIndicesPerTri * sizeof(GLint); - _gpuMemoryUsage += size; - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _triBufferId); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, size, 0, GL_DYNAMIC_DRAW); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - - // Set up the array buffer in the form of array of structures - // I chose AOS because it maximizes the amount of data tranferred - // by a single glBufferSubData call. - _maxVertexElementCount = _maxCount * 8; - size = _maxVertexElementCount * sizeof(VertexElement); - _gpuMemoryUsage += size; - - glBindBuffer(GL_ARRAY_BUFFER, _vertexBufferId); - glBufferData(GL_ARRAY_BUFFER, size, 0, GL_DYNAMIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); - - // Initialize the first tri element in the buffer to all zeros, the - // degenerate case - deconstructTriElement(0); - - // Initialize the first vertex element in the buffer to all zeros, the - // degenerate case - deconstructVertexElement(0); -} - -void PrimitiveRenderer::initializeBookkeeping() { - - // Start primitive count at one, because zero is reserved for the degenerate triangle - _primitives.resize(_maxCount + 1); - - // Set the counters - _primitiveCount = 1; - _vertexElementCount = 1; - _triElementCount = 1; - - // Guesstimate the memory consumption - _cpuMemoryUsage = sizeof(PrimitiveRenderer); - _cpuMemoryUsage += _availablePrimitiveIndex.capacity() * sizeof(int); - _cpuMemoryUsage += _availableVertexElementIndex.capacity() * sizeof(int); - _cpuMemoryUsage += _availableTriElementIndex.capacity() * sizeof(int); - _cpuMemoryUsage += _deconstructTriElementIndex.capacity() * sizeof(int); - _cpuMemoryUsage += _constructPrimitiveIndex.capacity() * sizeof(int); -} - -void PrimitiveRenderer::terminate() { - - terminateBookkeeping(); - terminateGL(); -} - -void PrimitiveRenderer::terminateGL() { - - if (_vertexBufferId) { - glDeleteBuffers(1, &_vertexBufferId); - _vertexBufferId = 0; - } - - if (_triBufferId) { - glDeleteBuffers(1, &_triBufferId); - _triBufferId = 0; - } -} - -void PrimitiveRenderer::terminateBookkeeping() { - - // Delete all of the primitives - for (int i = _primitiveCount + 1; --i > 0; ) { - Primitive* primitive = _primitives[i]; - if (primitive) { - _cpuMemoryUsage -= primitive->getMemoryUsage(); - _primitives[i] = 0; - delete primitive; - } - } - - // Drain the queues - _availablePrimitiveIndex.clear(); - _availableVertexElementIndex.clear(); - _availableTriElementIndex.clear(); - _deconstructTriElementIndex.clear(); - _constructPrimitiveIndex.clear(); - - _cpuMemoryUsage = sizeof(PrimitiveRenderer) + _primitives.size() * sizeof(Primitive *); -} - -void PrimitiveRenderer::constructElements( - Primitive* primitive - ) { - - // Load vertex elements - VertexElementIndexList& vertexElementIndexList = primitive->vertexElementIndices(); - const VertexElementList& vertices = primitive->vertexElements(); - { - for (VertexElementList::const_iterator it = vertices.begin(); it != vertices.end(); ++it ) { - int index = getAvailableVertexElementIndex(); - if (index != 0) { - // Store the vertex element index in the primitive's - // vertex element index list - vertexElementIndexList.push_back(index); - - VertexElement* vertex = *it; - transferVertexElement(index, vertex); - } else { - break; - } - } - } - - // Load tri elements - if (vertexElementIndexList.size() == vertices.size()) { - TriElementList& tris = primitive->triElements(); - - for (TriElementList::iterator it = tris.begin(); it != tris.end(); ++it) { - TriElement* tri = *it; - int index = getAvailableTriElementIndex(); - if (index != 0) { - int k; - k = tri->indices[0]; - tri->indices[0] = vertexElementIndexList[k]; - - k = tri->indices[1]; - tri->indices[1] = vertexElementIndexList[k]; - - k = tri->indices[2]; - tri->indices[2] = vertexElementIndexList[k]; - - tri->id = index; - transferTriElement(index, tri->indices); - } else { - break; - } - } - } else { - // TODO: failure mode - } -} - -void PrimitiveRenderer::deconstructElements( - Primitive* primitive - ) { - - // Schedule the tri elements of the face for deconstruction - { - TriElementList& tris = primitive->triElements(); - - for (TriElementList::const_iterator it = tris.begin(); it != tris.end(); ++it) { - const TriElement* tri = *it; - - if (tri->id) { - // Put the tri element index into decon queue - _deconstructTriElementIndex.push(tri->id); - } - } - } - - // Return the vertex element index to the available queue, it is not necessary - // to zero the data - { - VertexElementIndexList& vertexIndexList = primitive->vertexElementIndices(); - - for (VertexElementIndexList::const_iterator it = vertexIndexList.begin(); it != vertexIndexList.end(); ++it) { - int index = *it; - - if (index) { - // Put the vertex element index into the available queue - _availableVertexElementIndex.push(index); - } - } - } - - delete primitive; -} - -int PrimitiveRenderer::getAvailablePrimitiveIndex() { - - int index; - - // Check the available primitive index queue first for an available index. - if (!_availablePrimitiveIndex.isEmpty()) { - index = _availablePrimitiveIndex.pop(); - } else if (_primitiveCount < _maxCount) { - // There are no primitive indices available from the queue, - // make one up - index = _primitiveCount++; - } else { - index = 0; - } - return index; -} - -int PrimitiveRenderer::getAvailableVertexElementIndex() { - - int index; - - // Check the available vertex element queue first for an available index. - if (!_availableVertexElementIndex.isEmpty()) { - index = _availableVertexElementIndex.pop(); - } else if (_vertexElementCount < _maxVertexElementCount) { - // There are no vertex elements available from the queue, - // grab one from the end of the list - index = _vertexElementCount++; - } else { - index = 0; - } - return index; -} - -int PrimitiveRenderer::getAvailableTriElementIndex() { - - int index; - - // Check the tri elements scheduled for deconstruction queue first to - // intercept and reuse an index without it having to be destroyed - if (!_deconstructTriElementIndex.isEmpty()) { - index = _deconstructTriElementIndex.pop(); - } else if (!_availableTriElementIndex.isEmpty()) { - // Nothing available in the deconstruction queue, now - // check the available tri element queue for an available index. - index = _availableTriElementIndex.pop(); - } else if (_triElementCount < _maxTriElementCount) { - // There are no reusable tri elements available from the queue, - // grab one from the end of the list - index = _triElementCount++; - } else { - index = 0; - } - return index; -} - -void PrimitiveRenderer::deconstructTriElement( - int idx - ) { - - // Set the tri element to the degenerate case. - static int degenerate[3] = { 0, 0, 0 }; - transferTriElement(idx, degenerate); - -} - -void PrimitiveRenderer::deconstructVertexElement( - int idx - ) { - - // Set the vertex element to the degenerate case. - VertexElement degenerate; - memset(°enerate, 0, sizeof(degenerate)); - - transferVertexElement(idx, °enerate); - -} - -void PrimitiveRenderer::transferVertexElement( - int idx, - VertexElement* vertex - ) { - - glBindBuffer(GL_ARRAY_BUFFER, _vertexBufferId); - glBufferSubData(GL_ARRAY_BUFFER, idx * sizeof(VertexElement), sizeof(VertexElement), vertex); - glBindBuffer(GL_ARRAY_BUFFER, 0); -} - -void PrimitiveRenderer::transferTriElement( - int idx, - int tri[3] - ) { - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _triBufferId); - glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, idx * _sBytesPerTriElement, _sBytesPerTriElement, tri); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); -} - -int PrimitiveRenderer::vAdd( - Primitive* primitive - ) { - - QMutexLocker lock(&_guard); - int id = getAvailablePrimitiveIndex(); - if (id != 0) { - // Take ownership of primitive, including responsibility - // for destruction - _primitives[id] = primitive; - _constructPrimitiveIndex.push(id); - _cpuMemoryUsage += primitive->getMemoryUsage(); - } - return id; -} - -void PrimitiveRenderer::vRemove( - int id - ) { - - if (id != 0) { - QMutexLocker lock(&_guard); - - // Locate and remove the primitive by id in the vector map - Primitive* primitive = _primitives[id]; - if (primitive) { - _primitives[id] = 0; - _cpuMemoryUsage -= primitive->getMemoryUsage(); - deconstructElements(primitive); - - // Queue the index onto the available primitive stack. - _availablePrimitiveIndex.push(id); - } - } -} - -void PrimitiveRenderer::vRelease() { - - QMutexLocker lock(&_guard); - - terminateBookkeeping(); - initializeBookkeeping(); -} - -void PrimitiveRenderer::vRender() { - - int id; - QMutexLocker lock(&_guard); - - // Iterate over the set of triangle element array buffer ids scheduled for - // destruction. Set the triangle element to the degenerate case. Queue the id - // onto the available tri element stack. - while (!_deconstructTriElementIndex.isEmpty()) { - id = _deconstructTriElementIndex.pop(); - deconstructTriElement(id); - _availableTriElementIndex.push(id); - } - - // Iterate over the set of primitive ids scheduled for construction. Transfer - // primitive data to the GPU. - while (!_constructPrimitiveIndex.isEmpty()) { - id = _constructPrimitiveIndex.pop(); - Primitive* primitive = _primitives[id]; - if (primitive) { - constructElements(primitive); - - // No need to keep an extra copy of the vertices - _cpuMemoryUsage -= primitive->getMemoryUsage(); - primitive->releaseVertexElements(); - _cpuMemoryUsage += primitive->getMemoryUsage(); - } - } - - // The application uses clockwise winding for the definition of front face, this renderer - // aalso uses clockwise (that is the gl default) to construct the triangulation - // so... - //glFrontFace(GL_CW); - glEnable(GL_CULL_FACE); - - glBindBuffer(GL_ARRAY_BUFFER, _vertexBufferId); - - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(3, GL_FLOAT, sizeof(VertexElement), 0); - - glEnableClientState(GL_NORMAL_ARRAY); - glNormalPointer(GL_FLOAT, sizeof(VertexElement), (const GLvoid*)12); - - glEnableClientState(GL_COLOR_ARRAY); - glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(VertexElement), (const GLvoid*)24); - - glBindBuffer(GL_ARRAY_BUFFER, 0); - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _triBufferId); - glDrawElements(GL_TRIANGLES, 3 * _triElementCount, GL_UNSIGNED_INT, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - - glDisable(GL_CULL_FACE); -} - -unsigned long PrimitiveRenderer::vGetMemoryUsage() { - return _cpuMemoryUsage; -} - -unsigned long PrimitiveRenderer::vGetMemoryUsageGPU() { - return _gpuMemoryUsage; -} diff --git a/interface/src/voxels/PrimitiveRenderer.h b/interface/src/voxels/PrimitiveRenderer.h deleted file mode 100644 index 06dac119b0..0000000000 --- a/interface/src/voxels/PrimitiveRenderer.h +++ /dev/null @@ -1,503 +0,0 @@ -// -// PrimitiveRenderer.h -// interface/src/voxels -// -// Created by Norman Craft. -// 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_PrimitiveRenderer_h -#define hifi_PrimitiveRenderer_h - -#include -#include -#include - -/// Vertex element structure. -/// Using the array of structures approach to specifying -/// vertex data to GL cuts down on the calls to glBufferSubData -/// -typedef - struct __VertexElement { - struct __position { - float x; - float y; - float z; - } position; - struct __normal { - float x; - float y; - float z; - } normal; - struct __color { - unsigned char r; - unsigned char g; - unsigned char b; - unsigned char a; - } color; - } VertexElement; - -/// Triangle element index structure. -/// Specify the vertex indices of the triangle and its element index. -/// -typedef - struct __TriElement { - int indices[3]; - int id; - - } TriElement; - -/// Vertex element list container. -/// -typedef QVector VertexElementList; - -/// Vertex element index list container. -/// -typedef QVector VertexElementIndexList; - -/// Triangle element list container -/// -typedef QVector TriElementList; - -/// -/// @class Primitive -/// Primitive Interface class. -/// Abstract class for accessing vertex and tri elements of geometric primitives -/// -/// -class Primitive { -public: - virtual ~Primitive(); - - // API methods go here - - /// Vertex element accessor. - /// @return A list of vertex elements of the primitive - /// - const VertexElementList& vertexElements() const; - - /// Vertex element index accessor. - /// @return A list of vertex element indices of the primitive - /// - VertexElementIndexList& vertexElementIndices(); - - /// Tri element accessor. - /// @return A list of tri elements of the primitive - /// - TriElementList& triElements(); - - /// Release vertex elements. - /// - void releaseVertexElements(); - - /// Get memory usage. - /// - unsigned long getMemoryUsage(); - -protected: - /// Default constructor prohibited to API user, restricted to service implementer. - /// - Primitive(); - -private: - /// Copy constructor prohibited. - /// - Primitive( - const Primitive& copy - ); - - // SPI methods are defined here - - /// Vertex element accessor. - /// Service implementer to provide private override for this method - /// in derived class - /// - virtual const VertexElementList& vVertexElements() const = 0; - - /// Vertex element index accessor. - /// Service implementer to provide private override for this method - /// in derived class - /// - virtual VertexElementIndexList& vVertexElementIndices() = 0; - - /// Tri element accessor. - /// Service implementer to provide private override for this method - /// in derived class - /// - virtual TriElementList& vTriElements() = 0; - - /// Release vertex elements. - /// Service implementer to provide private override for this method - /// in derived class - /// - virtual void vReleaseVertexElements() = 0; - - /// Get memory usage. - /// Service implementer to provide private override for this method - /// in derived class - /// - virtual unsigned long vGetMemoryUsage() = 0; - -}; - - -/// -/// @class Cube -/// Class for accessing the vertex and triangle elements of a cube -/// -class Cube: public Primitive { -public: - /// Configuration dependency injection constructor. - /// - Cube( - float x, ///< Cube location on X-axis - float y, ///< Cube location on Y-axis - float z, ///< Cube location on Z-axis - float s, ///< Cube size - unsigned char r, ///< Cube red color component - unsigned char g, ///< Cube green color component - unsigned char b, ///< Cube blue color component - unsigned char faces ///< Bitmask of faces of cube excluded from construction - ); - - ~Cube(); - -private: - /// Copy constructor prohibited. - /// - Cube ( - const Cube& cube - ); - - /// Cube initialization - /// - void init( - float x, ///< Cube location on X-axis - float y, ///< Cube location on Y-axis - float z, ///< Cube location on Z-axis - float s, ///< Cube size - unsigned char r, ///< Cube red color component - unsigned char g, ///< Cube green color component - unsigned char b, ///< Cube blue color component - unsigned char faceExclusions ///< Bitmask of faces of cube excluded from construction - ); - - /// Cube termination - /// - void terminate(); - - /// Initialize cube's vertex list - /// - void initializeVertices( - float x, ///< Cube location on X-axis - float y, ///< Cube location on Y-axis - float z, ///< Cube location on Z-axis - float s, ///< Cube size - unsigned char r, ///< Cube red color component - unsigned char g, ///< Cube green color component - unsigned char b, ///< Cube blue color component - unsigned char faceExclusions ///< Bitmask of faces of cube excluded from construction - ); - - /// Terminate cube's vertex list - /// - void terminateVertices(); - - /// Initialize cube's triangle list - /// - void initializeTris( - unsigned char faceExclusions - ); - - /// Terminate cube's triangle list - /// - void terminateTris(); - - // SPI virtual override methods go here - - const VertexElementList& vVertexElements() const; - VertexElementIndexList& vVertexElementIndices(); - TriElementList& vTriElements(); - void vReleaseVertexElements(); - unsigned long vGetMemoryUsage(); - -private: - VertexElementList _vertices; ///< Vertex element list - VertexElementIndexList _vertexIndices; ///< Vertex element index list - TriElementList _tris; ///< Tri element list - - unsigned long _cpuMemoryUsage; ///< Memory allocation of object - - static const int _sNumFacesPerCube = 6; ///< Number of faces per cube - static const int _sNumVerticesPerCube = 24; ///< Number of vertices per cube - static unsigned char _sFaceIndexToHalfSpaceMask[6]; ///< index to bitmask map - static float _sVertexIndexToConstructionVector[24][3]; ///< Vertex index to construction vector map - static float _sVertexIndexToNormalVector[6][3]; ///< Vertex index to normal vector map - -}; - - -/// -/// @class Renderer -/// GL renderer interface class. -/// Abstract class for rendering geometric primitives in GL -/// -class Renderer { -public: - virtual ~Renderer(); - - // API methods go here - - /// Add primitive to renderer database. - /// - int add( - Primitive* primitive ///< Primitive instance to be added - ); - - /// Remove primitive from renderer database. - /// - void remove( - int id ///< Primitive id to be removed - ); - - /// Clear all primitives from renderer database - /// - void release(); - - /// Render primitive database. - /// The render method assumes appropriate GL context and state has - /// already been provided for - /// - void render(); - - /// Get memory usage. - /// - unsigned long getMemoryUsage(); - - /// Get GPU memory usage. - /// - unsigned long getMemoryUsageGPU(); - -protected: - /// Default constructor prohibited to API user, restricted to service implementer. - /// - Renderer(); - -private: - /// Copy constructor prohibited. - /// - Renderer( - const Renderer& copy - ); - - // SPI methods are defined here - - /// Add primitive to renderer database. - /// Service implementer to provide private override for this method - /// in derived class - /// @return Primitive id - /// - virtual int vAdd( - Primitive* primitive ///< Primitive instance to be added - ) = 0; - - /// Remove primitive from renderer database. - /// Service implementer to provide private override for this method - /// in derived class - /// - virtual void vRemove( - int id ///< Primitive id - ) = 0; - - /// Clear all primitives from renderer database - /// Service implementer to provide private override for this method - /// in derived class - /// - virtual void vRelease() = 0; - - /// Render primitive database. - /// Service implementer to provide private virtual override for this method - /// in derived class - /// - virtual void vRender() = 0; - - /// Get memory usage. - /// - virtual unsigned long vGetMemoryUsage() = 0; - - /// Get GPU memory usage. - /// - virtual unsigned long vGetMemoryUsageGPU() = 0; - -}; - -/// -/// @class PrimitiveRenderer -/// Renderer implementation class for the rendering of geometric primitives -/// using GL element array and GL array buffers -/// -class PrimitiveRenderer : public Renderer { -public: - /// Configuration dependency injection constructor. - /// - PrimitiveRenderer( - int maxCount ///< Max count - ); - - ~PrimitiveRenderer(); - -private: - /// Default constructor prohibited. - /// - PrimitiveRenderer(); - - /// Copy constructor prohibited. - /// - PrimitiveRenderer( - const PrimitiveRenderer& renderer - ); - - void init(); - void terminate(); - - /// Allocate and initialize GL buffers. - /// - void initializeGL(); - - /// Terminate and deallocate GL buffers. - /// - void terminateGL(); - - void initializeBookkeeping(); - void terminateBookkeeping(); - - /// Construct the elements of the faces of the primitive. - /// - void constructElements( - Primitive* primitive ///< Primitive instance - ); - - /// Deconstruct the elements of the faces of the primitive. - /// - void deconstructElements( - Primitive* primitive ///< Primitive instance - ); - - /// Deconstruct the triangle element from the GL buffer. - /// - void deconstructTriElement( - int idx ///< Triangle element index - ); - - /// Deconstruct the vertex element from the GL buffer. - /// - void deconstructVertexElement( - int idx ///< Vertex element index - ); - - /// Transfer the vertex element to the GL buffer. - /// - void transferVertexElement( - int idx, ///< Vertex element index - VertexElement *vertex ///< Vertex element instance - ); - - /// Transfer the triangle element to the GL buffer. - /// - void transferTriElement( - int idx, ///< Triangle element index - int tri[3] ///< Triangle element data - ); - - /// Get available primitive index. - /// Get an available primitive index from either the recycling - /// queue or incrementing the counter - /// - int getAvailablePrimitiveIndex(); - - /// Get available vertex element index. - /// Get an available vertex element index from either the recycling - /// queue or incrementing the counter - /// - int getAvailableVertexElementIndex(); - - /// Get available triangle element index. - /// Get an available triangle element index from either the elements - /// scheduled for deconstruction queue, the recycling - /// queue or incrementing the counter - /// - int getAvailableTriElementIndex(); - - // SPI virtual override methods go here - - /// Add primitive to renderer database. - /// - int vAdd( - Primitive* primitive ///< Primitive instance to be added - ); - - /// Remove primitive from renderer database. - /// - void vRemove( - int id ///< Primitive id to be removed - ); - - /// Clear all primitives from renderer database - /// - void vRelease(); - - /// Render triangle database. - /// - void vRender(); - - /// Get memory usage. - /// - unsigned long vGetMemoryUsage(); - - /// Get gpu memory usage. - /// - unsigned long vGetMemoryUsageGPU(); - -private: - - int _maxCount; ///< Maximum count of tris - - // GL related parameters - - GLuint _triBufferId; ///< GL element array buffer id - GLuint _vertexBufferId; ///< GL vertex array buffer id - - // Book keeping parameters - - int _vertexElementCount; ///< Count of vertices - int _maxVertexElementCount; ///< Max count of vertices - - int _triElementCount; ///< Count of triangles - int _maxTriElementCount; ///< Max count of triangles - - QVector _primitives; ///< Vector of primitive - int _primitiveCount; ///< Count of primitives - - QStack _availablePrimitiveIndex; ///< Queue of primitive indices available - QStack _availableVertexElementIndex; ///< Queue of vertex element indices available - QStack _availableTriElementIndex; ///< Queue of triangle element indices available - QStack _deconstructTriElementIndex; ///< Queue of triangle element indices requiring deletion from GL - QStack _constructPrimitiveIndex; ///< Queue of primitives requiring addition to GL - - QMutex _guard; - - // Statistics parameters, not necessary for proper operation - - unsigned long _gpuMemoryUsage; ///< GPU memory used by this instance - unsigned long _cpuMemoryUsage; ///< CPU memory used by this instance - - - static const int _sIndicesPerTri = 3; - static const int _sBytesPerTriElement = sizeof(GLint) * _sIndicesPerTri; -}; - - -#endif // hifi_PrimitiveRenderer_h diff --git a/interface/src/voxels/VoxelSystem.cpp b/interface/src/voxels/VoxelSystem.cpp index 8fbaf65f37..2f4fd3f0fa 100644 --- a/interface/src/voxels/VoxelSystem.cpp +++ b/interface/src/voxels/VoxelSystem.cpp @@ -68,10 +68,6 @@ VoxelSystem::VoxelSystem(float treeScale, int maxVoxels, VoxelTree* tree) _initialized(false), _writeArraysLock(QReadWriteLock::Recursive), _readArraysLock(QReadWriteLock::Recursive), - _inOcclusions(false), - _showCulledSharedFaces(false), - _usePrimitiveRenderer(false), - _renderer(0), _drawHaze(false), _farHazeDistance(300.0f), _hazeColor(grayColor) @@ -112,7 +108,7 @@ VoxelSystem::VoxelSystem(float treeScale, int maxVoxels, VoxelTree* tree) void VoxelSystem::elementDeleted(OctreeElement* element) { VoxelTreeElement* voxel = (VoxelTreeElement*)element; if (voxel->getVoxelSystem() == this) { - if ((_voxelsInWriteArrays != 0) || _usePrimitiveRenderer) { + if ((_voxelsInWriteArrays != 0)) { forceRemoveNodeFromArrays(voxel); } else { if (Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings)) { @@ -288,9 +284,6 @@ void VoxelSystem::cleanupVoxelMemory() { _readColorsArray = NULL; _writeColorsArray = NULL; - delete _renderer; - _renderer = 0; - delete[] _writeVoxelDirtyArray; delete[] _readVoxelDirtyArray; _writeVoxelDirtyArray = _readVoxelDirtyArray = NULL; @@ -384,8 +377,6 @@ void VoxelSystem::initVoxelMemory() { Application::resourcesPath() + "shaders/voxel.frag"); _program.link(); } - _renderer = new PrimitiveRenderer(_maxVoxels); - _initialized = true; _writeArraysLock.unlock(); @@ -511,10 +502,6 @@ void VoxelSystem::setupNewVoxelsForDrawing() { _callsToTreesToArrays++; if (_writeRenderFullVBO) { - if (_usePrimitiveRenderer) { - _renderer->release(); - clearAllNodesBufferIndex(); - } clearFreeBufferIndexes(); } _voxelsUpdated = newTreeToArrays(_tree->getRoot()); @@ -525,24 +512,17 @@ void VoxelSystem::setupNewVoxelsForDrawing() { _voxelsUpdated = 0; } - if (_usePrimitiveRenderer) { - if (_voxelsUpdated) { - _voxelsDirty=true; - } - } else { - // lock on the buffer write lock so we can't modify the data when the GPU is reading it - _readArraysLock.lockForWrite(); - - if (_voxelsUpdated) { - _voxelsDirty=true; - } - - // copy the newly written data to the arrays designated for reading, only does something if _voxelsDirty && _voxelsUpdated - copyWrittenDataToReadArrays(didWriteFullVBO); - _readArraysLock.unlock(); + // lock on the buffer write lock so we can't modify the data when the GPU is reading it + _readArraysLock.lockForWrite(); + if (_voxelsUpdated) { + _voxelsDirty=true; } + // copy the newly written data to the arrays designated for reading, only does something if _voxelsDirty && _voxelsUpdated + copyWrittenDataToReadArrays(didWriteFullVBO); + _readArraysLock.unlock(); + quint64 end = usecTimestampNow(); int elapsedmsec = (end - start) / 1000; _setupNewVoxelsForDrawingLastFinished = end; @@ -569,26 +549,22 @@ void VoxelSystem::setupNewVoxelsForDrawingSingleNode(bool allowBailEarly) { return; // bail early, it hasn't been long enough since the last time we ran } - if (_usePrimitiveRenderer) { - _voxelsDirty = true; // if we got this far, then we can assume some voxels are dirty - _voxelsUpdated = 0; - } else { - // lock on the buffer write lock so we can't modify the data when the GPU is reading it - { - PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), - "setupNewVoxelsForDrawingSingleNode()... _bufferWriteLock.lock();" ); - _readArraysLock.lockForWrite(); - } - - _voxelsDirty = true; // if we got this far, then we can assume some voxels are dirty - - // copy the newly written data to the arrays designated for reading, only does something if _voxelsDirty && _voxelsUpdated - copyWrittenDataToReadArrays(_writeRenderFullVBO); - - // after... - _voxelsUpdated = 0; - _readArraysLock.unlock(); + // lock on the buffer write lock so we can't modify the data when the GPU is reading it + { + PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), + "setupNewVoxelsForDrawingSingleNode()... _bufferWriteLock.lock();" ); + _readArraysLock.lockForWrite(); } + + _voxelsDirty = true; // if we got this far, then we can assume some voxels are dirty + + // copy the newly written data to the arrays designated for reading, only does something if _voxelsDirty && _voxelsUpdated + copyWrittenDataToReadArrays(_writeRenderFullVBO); + + // after... + _voxelsUpdated = 0; + _readArraysLock.unlock(); + quint64 end = usecTimestampNow(); int elapsedmsec = (end - start) / 1000; _setupNewVoxelsForDrawingLastFinished = end; @@ -862,22 +838,13 @@ int VoxelSystem::forceRemoveNodeFromArrays(VoxelTreeElement* node) { return 0; } - if (_usePrimitiveRenderer) { - if (node->isKnownBufferIndex()) { - int primitiveIndex = node->getBufferIndex(); - _renderer->remove(primitiveIndex); - node->setBufferIndex(GLBUFFER_INDEX_UNKNOWN); - return 1; - } - } else { - // if the node is not in the VBOs then we have nothing to do! - if (node->isKnownBufferIndex()) { - // If this node has not yet been written to the array, then add it to the end of the array. - glBufferIndex nodeIndex = node->getBufferIndex(); - node->setBufferIndex(GLBUFFER_INDEX_UNKNOWN); - freeBufferIndex(nodeIndex); // NOTE: This will make the node invisible! - return 1; // updated! - } + // if the node is not in the VBOs then we have nothing to do! + if (node->isKnownBufferIndex()) { + // If this node has not yet been written to the array, then add it to the end of the array. + glBufferIndex nodeIndex = node->getBufferIndex(); + node->setBufferIndex(GLBUFFER_INDEX_UNKNOWN); + freeBufferIndex(nodeIndex); // NOTE: This will make the node invisible! + return 1; // updated! } return 0; // not-updated } @@ -909,43 +876,17 @@ int VoxelSystem::updateNodeInArrays(VoxelTreeElement* node, bool reuseIndex, boo float voxelScale = node->getScale(); nodeColor const & color = node->getColor(); - if (_usePrimitiveRenderer) { - if (node->isKnownBufferIndex()) { - int primitiveIndex = node->getBufferIndex(); - _renderer->remove(primitiveIndex); - node->setBufferIndex(GLBUFFER_INDEX_UNKNOWN); - } else { - node->setVoxelSystem(this); - } - unsigned char occlusions; - if (_showCulledSharedFaces) { - occlusions = ~node->getInteriorOcclusions(); - } else { - occlusions = node->getInteriorOcclusions(); - } - if (occlusions != OctreeElement::HalfSpace::All) { - Cube* cube = new Cube( - startVertex.x, startVertex.y, startVertex.z, voxelScale, - color[RED_INDEX], color[GREEN_INDEX], color[BLUE_INDEX], - occlusions); - if (cube) { - int primitiveIndex = _renderer->add(cube); - node->setBufferIndex(primitiveIndex); - } - } + glBufferIndex nodeIndex = GLBUFFER_INDEX_UNKNOWN; + if (reuseIndex && node->isKnownBufferIndex()) { + nodeIndex = node->getBufferIndex(); } else { - glBufferIndex nodeIndex = GLBUFFER_INDEX_UNKNOWN; - if (reuseIndex && node->isKnownBufferIndex()) { - nodeIndex = node->getBufferIndex(); - } else { - nodeIndex = getNextBufferIndex(); - node->setBufferIndex(nodeIndex); - node->setVoxelSystem(this); - } - - // populate the array with points for the 8 vertices and RGB color for each added vertex - updateArraysDetails(nodeIndex, startVertex, voxelScale, node->getColor()); + nodeIndex = getNextBufferIndex(); + node->setBufferIndex(nodeIndex); + node->setVoxelSystem(this); } + + // populate the array with points for the 8 vertices and RGB color for each added vertex + updateArraysDetails(nodeIndex, startVertex, voxelScale, node->getColor()); return 1; // updated! } else { // If we shouldn't render, and we're in reuseIndex mode, then free our index, this only operates @@ -1072,24 +1013,22 @@ void VoxelSystem::updateVBOs() { }; // would like to include _callsToTreesToArrays PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), buffer); - if (! _usePrimitiveRenderer) { - if (_voxelsDirty) { - - // attempt to lock the read arrays, to for copying from them to the actual GPU VBOs. - // if we fail to get the lock, that's ok, our VBOs will update on the next frame... - const int WAIT_FOR_LOCK_IN_MS = 5; - if (_readArraysLock.tryLockForRead(WAIT_FOR_LOCK_IN_MS)) { - if (_readRenderFullVBO) { - updateFullVBOs(); - } else { - updatePartialVBOs(); - } - _voxelsDirty = false; - _readRenderFullVBO = false; - _readArraysLock.unlock(); + if (_voxelsDirty) { + + // attempt to lock the read arrays, to for copying from them to the actual GPU VBOs. + // if we fail to get the lock, that's ok, our VBOs will update on the next frame... + const int WAIT_FOR_LOCK_IN_MS = 5; + if (_readArraysLock.tryLockForRead(WAIT_FOR_LOCK_IN_MS)) { + if (_readRenderFullVBO) { + updateFullVBOs(); } else { - qDebug() << "updateVBOs().... couldn't get _readArraysLock.tryLockForRead()"; + updatePartialVBOs(); } + _voxelsDirty = false; + _readRenderFullVBO = false; + _readArraysLock.unlock(); + } else { + qDebug() << "updateVBOs().... couldn't get _readArraysLock.tryLockForRead()"; } } _callsToTreesToArrays = 0; // clear it @@ -1143,11 +1082,11 @@ void VoxelSystem::render() { updateVBOs(); - if (!_usePrimitiveRenderer) { - if (_drawHaze) { - glEnable(GL_FOG); - } + if (_drawHaze) { + glEnable(GL_FOG); + } + { PerformanceWarning warn(showWarnings, "render().. TRIANGLES..."); { @@ -1223,16 +1162,10 @@ void VoxelSystem::render() { glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); } - - if (_drawHaze) { - glDisable(GL_FOG); - } } - else { - applyScaleAndBindProgram(texture); - _renderer->render(); - removeScaleAndReleaseProgram(texture); - + + if (_drawHaze) { + glDisable(GL_FOG); } } @@ -1275,12 +1208,6 @@ void VoxelSystem::killLocalVoxels() { _tree->getRoot()->setVoxelSystem(voxelSystem); _tree->unlock(); clearFreeBufferIndexes(); - if (_usePrimitiveRenderer) { - if (_renderer) { - _renderer->release(); - } - clearAllNodesBufferIndex(); - } _voxelsInReadArrays = 0; // do we need to do this? setupNewVoxelsForDrawing(); } @@ -1308,178 +1235,6 @@ void VoxelSystem::clearAllNodesBufferIndex() { } } -bool VoxelSystem::inspectForInteriorOcclusionsOperation(OctreeElement* element, void* extraData) { - _nodeCount++; - VoxelTreeElement* voxel = (VoxelTreeElement*)element; - - // Nothing to do at the leaf level - if (voxel->isLeaf()) { - return false; - } - - // Bit mask of occluded shared faces indexed by child - unsigned char occludedSharedFace[NUMBER_OF_CHILDREN] = { 0, 0, 0, 0, 0, 0, 0, 0 }; - - // Traverse all pair combinations of children - for (int i = NUMBER_OF_CHILDREN; --i >= 0; ) { - - VoxelTreeElement* childA = voxel->getChildAtIndex(i); - if (childA) { - - // Get the child A's occluding faces, for a leaf that will be - // all six voxel faces, and for a non leaf, that will be - // all faces which are completely covered by four child octants. - unsigned char exteriorOcclusionsA = childA->getExteriorOcclusions(); - - for (int j = i; --j >= 0; ) { - - VoxelTreeElement* childB = voxel->getChildAtIndex(j); - if (childB) { - - // Get child B's occluding faces - unsigned char exteriorOcclusionsB = childB->getExteriorOcclusions(); - - // Determine the shared halfspace partition between siblings A and B, - // i.e., near/far, left/right, or top/bottom - unsigned char partitionA = _sOctantIndexToSharedBitMask[i][j] & - exteriorOcclusionsA; - unsigned char partitionB = _sOctantIndexToSharedBitMask[i][j] & - exteriorOcclusionsB; - - // Determine which face of each sibling is occluded. - - // The _sOctantIndexToBitMask is a partition occupancy mask. For - // example, if the near-left-top (NLT) and near-left-bottom (NLB) child voxels - // exist, the shared partition is top-bottom (TB), and thus the occluded - // shared face of the NLT voxel is its bottom face. - occludedSharedFace[i] |= (partitionB & _sOctantIndexToBitMask[i]); - occludedSharedFace[j] |= (partitionA & _sOctantIndexToBitMask[j]); - } - } - // Exchange bit pairs, left to right, vice versa, etc. - occludedSharedFace[i] = _sSwizzledOcclusionBits[occludedSharedFace[i]]; - // Combine this voxel's interior excluded shared face only to those children which are coincident - // with the excluded face. - occludedSharedFace[i] |= (voxel->getInteriorOcclusions() & _sOctantIndexToBitMask[i]); - - // Inform the child - childA->setInteriorOcclusions(occludedSharedFace[i]); - if (occludedSharedFace[i] != OctreeElement::HalfSpace::None) { - //const glm::vec3& v = voxel->getCorner(); - //float s = voxel->getScale(); - - //qDebug("Child %d of voxel at %f %f %f size: %f has %02x occlusions", i, v.x, v.y, v.z, s, occludedSharedFace[i]); - } - } - } - return true; -} - -bool VoxelSystem::inspectForExteriorOcclusionsOperation(OctreeElement* element, void* extraData) { - _nodeCount++; - VoxelTreeElement* voxel = (VoxelTreeElement*)element; - - // Nothing to do at the leaf level - if (voxel->isLeaf()) { - // By definition the the exterior faces of a leaf voxel are - // always occluders. - voxel->setExteriorOcclusions(OctreeElement::HalfSpace::All); - // And the sibling occluders - voxel->setInteriorOcclusions(OctreeElement::HalfSpace::None); - return false; - } else { - voxel->setExteriorOcclusions(OctreeElement::HalfSpace::None); - voxel->setInteriorOcclusions(OctreeElement::HalfSpace::None); - } - - // Count of exterior occluding faces of this voxel element indexed - // by half space partition - unsigned int exteriorOcclusionsCt[6] = { 0, 0, 0, 0, 0, 0 }; - - // Traverse all children - for (int i = NUMBER_OF_CHILDREN; --i >= 0; ) { - - VoxelTreeElement* child = voxel->getChildAtIndex(i); - if (child) { - - // Get the child's occluding faces, for a leaf, that will be - // all six voxel faces, and for a non leaf, that will be - // all faces which are completely covered by four child octants. - unsigned char exteriorOcclusionsOfChild = child->getExteriorOcclusions(); - exteriorOcclusionsOfChild &= _sOctantIndexToBitMask[i]; - - for (int j = 6; --j >= 0; ) { - - // Determine if the halfspace partition indexed by 1 << j is - // present in the exterior occlusions of the child. - unsigned char partition = exteriorOcclusionsOfChild & (1 << j); - - if (partition) { - exteriorOcclusionsCt[j]++; - } - } - } - } - { - // Derive the exterior occlusions of the voxel elements from the exclusions - // of its children - unsigned char exteriorOcclusions = OctreeElement::HalfSpace::None; - for (int i = 6; --i >= 0; ) { - if (exteriorOcclusionsCt[i] == _sNumOctantsPerHemiVoxel) { - - // Exactly four octants qualify for full exterior occlusion - exteriorOcclusions |= (1 << i); - } - } - - // Inform the voxel element - voxel->setExteriorOcclusions(exteriorOcclusions); - - if (exteriorOcclusions == OctreeElement::HalfSpace::All) { - //const glm::vec3& v = voxel->getCorner(); - //float s = voxel->getScale(); - - //qDebug("Completely occupied voxel at %f %f %f size: %f", v.x, v.y, v.z, s); - - // All of the exterior faces of this voxel element are - // occluders, which means that this element is completely - // occupied. Hence, the subtree from this node could be - // pruned and replaced by a leaf voxel, if the visible - // properties of the children are the same - - } else if (exteriorOcclusions != OctreeElement::HalfSpace::None) { - //const glm::vec3& v = voxel->getCorner(); - //float s = voxel->getScale(); - - //qDebug("Partially occupied voxel at %f %f %f size: %f with %02x", v.x, v.y, v.z, s, exteriorOcclusions); - } - } - return true; -} - -void VoxelSystem::inspectForOcclusions() { - - if (_inOcclusions) { - return; - } - _inOcclusions = true; - _nodeCount = 0; - - bool showDebugDetails = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); - PerformanceWarning warn(showDebugDetails, "inspectForOcclusions()"); - - _tree->lockForRead(); - _tree->recurseTreeWithPostOperation(inspectForExteriorOcclusionsOperation); - _nodeCount = 0; - _tree->recurseTreeWithOperation(inspectForInteriorOcclusionsOperation); - _tree->unlock(); - - if (showDebugDetails) { - qDebug("inspecting all occlusions of %d nodes", _nodeCount); - } - _inOcclusions = false; -} - bool VoxelSystem::forceRedrawEntireTreeOperation(OctreeElement* element, void* extraData) { _nodeCount++; element->setDirtyBit(); @@ -1904,170 +1659,3 @@ void VoxelSystem::bindPerlinModulateProgram() { } } -// Swizzle value of bit pairs of the value of index -unsigned short VoxelSystem::_sSwizzledOcclusionBits[64] = { - 0x0000, // 00000000 - 0x0002, // 00000001 - 0x0001, // 00000010 - 0x0003, // 00000011 - 0x0008, // 00000100 - 0x000a, // 00000101 - 0x0009, // 00000110 - 0x000b, // 00000111 - 0x0004, // 00001000 - 0x0006, // 00001001 - 0x0005, // 00001010 - 0x0007, // 00001011 - 0x000c, // 00001100 - 0x000e, // 00001101 - 0x000d, // 00001110 - 0x000f, // 00001111 - 0x0020, // 00010000 - 0x0022, // 00010001 - 0x0021, // 00010010 - 0x0023, // 00010011 - 0x0028, // 00010100 - 0x002a, // 00010101 - 0x0029, // 00010110 - 0x002b, // 00010111 - 0x0024, // 00011000 - 0x0026, // 00011001 - 0x0025, // 00011010 - 0x0027, // 00011011 - 0x002c, // 00011100 - 0x002e, // 00011101 - 0x002d, // 00011110 - 0x002f, // 00011111 - 0x0010, // 00100000 - 0x0012, // 00100001 - 0x0011, // 00100010 - 0x0013, // 00100011 - 0x0018, // 00100100 - 0x001a, // 00100101 - 0x0019, // 00100110 - 0x001b, // 00100111 - 0x0014, // 00101000 - 0x0016, // 00101001 - 0x0015, // 00101010 - 0x0017, // 00101011 - 0x001c, // 00101100 - 0x001e, // 00101101 - 0x001d, // 00101110 - 0x001f, // 00101111 - 0x0030, // 00110000 - 0x0032, // 00110001 - 0x0031, // 00110010 - 0x0033, // 00110011 - 0x0038, // 00110100 - 0x003a, // 00110101 - 0x0039, // 00110110 - 0x003b, // 00110111 - 0x0034, // 00111000 - 0x0036, // 00111001 - 0x0035, // 00111010 - 0x0037, // 00111011 - 0x003c, // 00111100 - 0x003e, // 00111101 - 0x003d, // 00111110 - 0x003f, // 00111111 -}; - -// Octant bitmask array indexed by octant. The mask value indicates the octant's halfspace partitioning. The index -// value corresponds to the voxel's octal code derived in "pointToVoxel" in SharedUtil.cpp, which, BTW, does *not* -// correspond to the "ChildIndex" enum value in OctreeElement.h -unsigned char VoxelSystem::_sOctantIndexToBitMask[8] = { - OctreeElement::HalfSpace::Bottom | OctreeElement::HalfSpace::Left | OctreeElement::HalfSpace::Near, - OctreeElement::HalfSpace::Bottom | OctreeElement::HalfSpace::Left | OctreeElement::HalfSpace::Far, - OctreeElement::HalfSpace::Top | OctreeElement::HalfSpace::Left | OctreeElement::HalfSpace::Near, - OctreeElement::HalfSpace::Top | OctreeElement::HalfSpace::Left | OctreeElement::HalfSpace::Far, - OctreeElement::HalfSpace::Bottom | OctreeElement::HalfSpace::Right | OctreeElement::HalfSpace::Near, - OctreeElement::HalfSpace::Bottom | OctreeElement::HalfSpace::Right | OctreeElement::HalfSpace::Far, - OctreeElement::HalfSpace::Top | OctreeElement::HalfSpace::Right | OctreeElement::HalfSpace::Near, - OctreeElement::HalfSpace::Top | OctreeElement::HalfSpace::Right | OctreeElement::HalfSpace::Far, -}; - -// Two dimensional array map indexed by octant row and column. The mask value -// indicates the two faces shared by the octants -unsigned char VoxelSystem::_sOctantIndexToSharedBitMask[8][8] = { - { // Index 0: Bottom-Left-Near - 0, // Bottom-Left-Near - OctreeElement::HalfSpace::Near | OctreeElement::HalfSpace::Far, // Bottom-Left-Far - OctreeElement::HalfSpace::Bottom | OctreeElement::HalfSpace::Top, // Top-Left-Near - 0, // Top-Left-Far - OctreeElement::HalfSpace::Right | OctreeElement::HalfSpace::Left, // Bottom-Right-Near - 0, // Bottom-Right-Far - 0, // Top-Right-Near - 0, // Top-Right-Far - }, - { // Index 1: Bottom-Left-Far - OctreeElement::HalfSpace::Near | OctreeElement::HalfSpace::Far, // Bottom-Left-Near - 0, // Bottom-Left-Far - 0, // Top-Left-Near - OctreeElement::HalfSpace::Bottom | OctreeElement::HalfSpace::Top, // Top-Left-Far - 0, // Bottom-Right-Near - OctreeElement::HalfSpace::Right | OctreeElement::HalfSpace::Left, // Bottom-Right-Far - 0, // Top-Right-Near - 0, // Top-Right-Far - }, - { // Index 2: Top-Left-Near - OctreeElement::HalfSpace::Bottom | OctreeElement::HalfSpace::Top, // Bottom-Left-Near - 0, // Bottom-Left-Far - 0, // Top-Left-Near - OctreeElement::HalfSpace::Near | OctreeElement::HalfSpace::Far, // Top-Left-Far - 0, // Bottom-Right-Near - 0, // Bottom-Right-Far - OctreeElement::HalfSpace::Right | OctreeElement::HalfSpace::Left, // Top-Right-Near - 0, // Top-Right-Far - }, - { // Index 3: Top-Left-Far - 0, // Bottom-Left-Near - OctreeElement::HalfSpace::Bottom | OctreeElement::HalfSpace::Top, // Bottom-Left-Far - OctreeElement::HalfSpace::Near | OctreeElement::HalfSpace::Far, // Top-Left-Near - 0, // Top-Left-Far - 0, // Bottom-Right-Near - 0, // Bottom-Right-Far - 0, // Top-Right-Near - OctreeElement::HalfSpace::Right | OctreeElement::HalfSpace::Left, // Top-Right-Far - }, - { // Index 4: Bottom-Right-Near - OctreeElement::HalfSpace::Right | OctreeElement::HalfSpace::Left, // Bottom-Left-Near - 0, // Bottom-Left-Far - 0, // Top-Left-Near - 0, // Top-Left-Far - 0, // Bottom-Right-Near - OctreeElement::HalfSpace::Near | OctreeElement::HalfSpace::Far, // Bottom-Right-Far - OctreeElement::HalfSpace::Bottom | OctreeElement::HalfSpace::Top, // Top-Right-Near - 0, // Top-Right-Far - }, - { // Index 5: Bottom-Right-Far - 0, // Bottom-Left-Near - OctreeElement::HalfSpace::Right | OctreeElement::HalfSpace::Left, // Bottom-Left-Far - 0, // Top-Left-Near - 0, // Top-Left-Far - OctreeElement::HalfSpace::Near | OctreeElement::HalfSpace::Far, // Bottom-Right-Near - 0, // Bottom-Right-Far - 0, // Top-Right-Near - OctreeElement::HalfSpace::Bottom | OctreeElement::HalfSpace::Top, // Top-Right-Far - }, - { // Index 6: Top-Right-Near - 0, // Bottom-Left-Near - 0, // Bottom-Left-Far - OctreeElement::HalfSpace::Right | OctreeElement::HalfSpace::Left, // Top-Left-Near - 0, // Top-Left-Far - OctreeElement::HalfSpace::Bottom | OctreeElement::HalfSpace::Top, // Bottom-Right-Near - 0, // Bottom-Right-Far - 0, // Top-Right-Near - OctreeElement::HalfSpace::Near | OctreeElement::HalfSpace::Far, // Top-Right-Far - }, - { // Index 7: Top-Right-Far - 0, // Bottom-Left-Near - 0, // Bottom-Left-Far - 0, // Top-Left-Near - OctreeElement::HalfSpace::Right | OctreeElement::HalfSpace::Left, // Top-Left-Far - 0, // Bottom-Right-Near - OctreeElement::HalfSpace::Bottom | OctreeElement::HalfSpace::Top, // Bottom-Right-Far - OctreeElement::HalfSpace::Near | OctreeElement::HalfSpace::Far, // Top-Right-Near - 0, // Top-Right-Far - }, -}; - diff --git a/interface/src/voxels/VoxelSystem.h b/interface/src/voxels/VoxelSystem.h index 4f4c624e15..b6413a0f68 100644 --- a/interface/src/voxels/VoxelSystem.h +++ b/interface/src/voxels/VoxelSystem.h @@ -25,7 +25,6 @@ #include "Camera.h" #include "Util.h" #include "world.h" -#include "PrimitiveRenderer.h" class ProgramObject; @@ -71,7 +70,6 @@ public: void killLocalVoxels(); virtual void hideOutOfView(bool forceFullFrustum = false); - void inspectForOcclusions(); bool hasViewChanged(); bool isViewChanging(); @@ -129,8 +127,6 @@ private: static bool killSourceVoxelsOperation(OctreeElement* element, void* extraData); static bool forceRedrawEntireTreeOperation(OctreeElement* element, void* extraData); static bool clearAllNodesBufferIndexOperation(OctreeElement* element, void* extraData); - static bool inspectForExteriorOcclusionsOperation(OctreeElement* element, void* extraData); - static bool inspectForInteriorOcclusionsOperation(OctreeElement* element, void* extraData); static bool hideOutOfViewOperation(OctreeElement* element, void* extraData); static bool hideAllSubTreeOperation(OctreeElement* element, void* extraData); static bool showAllSubTreeOperation(OctreeElement* element, void* extraData); @@ -241,17 +237,6 @@ private: float _lastKnownVoxelSizeScale; int _lastKnownBoundaryLevelAdjust; - bool _inOcclusions; - bool _showCulledSharedFaces; ///< Flag visibility of culled faces - bool _usePrimitiveRenderer; ///< Flag primitive renderer for use - PrimitiveRenderer* _renderer; ///< Voxel renderer - - static const unsigned int _sNumOctantsPerHemiVoxel = 4; - static int _sCorrectedChildIndex[8]; - static unsigned short _sSwizzledOcclusionBits[64]; ///< Swizzle value of bit pairs of the value of index - static unsigned char _sOctantIndexToBitMask[8]; ///< Map octant index to partition mask - static unsigned char _sOctantIndexToSharedBitMask[8][8]; ///< Map octant indices to shared partition mask - // haze bool _drawHaze; float _farHazeDistance; From 7611354df67ce4bed4f164c24687a2cef50c526f Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 11 Dec 2014 14:43:58 -0800 Subject: [PATCH 348/502] Fix for normal maps on skinned models. --- interface/src/renderer/Model.cpp | 133 ++++++++----------------------- interface/src/renderer/Model.h | 4 +- 2 files changed, 35 insertions(+), 102 deletions(-) diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 71f5129a1e..fd54f67377 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -134,38 +134,21 @@ void Model::setOffset(const glm::vec3& offset) { _snappedToRegistrationPoint = false; } -void Model::initProgram(ProgramObject& program, Model::Locations& locations, int specularTextureUnit) { +void Model::initProgram(ProgramObject& program, Model::Locations& locations, bool link) { + if (link) { + program.bindAttributeLocation("tangent", gpu::Stream::TANGENT); + program.bindAttributeLocation("texcoord1", gpu::Stream::TEXCOORD1); + program.link(); + } program.bind(); -#ifdef Q_OS_MAC - - // HACK: Assign explicitely the attribute channel to avoid a bug on Yosemite - - glBindAttribLocation(program.programId(), 4, "tangent"); - - glLinkProgram(program.programId()); - -#endif - - - - glBindAttribLocation(program.programId(), gpu::Stream::TANGENT, "tangent"); - - glBindAttribLocation(program.programId(), gpu::Stream::TEXCOORD1, "texcoord1"); - - glLinkProgram(program.programId()); - locations.tangent = program.attributeLocation("tangent"); locations.alphaThreshold = program.uniformLocation("alphaThreshold"); - locations.texcoordMatrices = program.uniformLocation("texcoordMatrices"); - locations.emissiveParams = program.uniformLocation("emissiveParams"); - program.setUniformValue("diffuseMap", 0); - program.setUniformValue("normalMap", 1); int loc = program.uniformLocation("specularMap"); @@ -184,50 +167,22 @@ void Model::initProgram(ProgramObject& program, Model::Locations& locations, int locations.emissiveTextureUnit = -1; } - if (!program.isLinked()) { - program.release(); - } - program.release(); - } - - -void Model::initSkinProgram(ProgramObject& program, Model::SkinLocations& locations, int specularTextureUnit) { - - initProgram(program, locations, specularTextureUnit); - - - -#ifdef Q_OS_MAC - - // HACK: Assign explicitely the attribute channel to avoid a bug on Yosemite - - glBindAttribLocation(program.programId(), 5, "clusterIndices"); - - glBindAttribLocation(program.programId(), 6, "clusterWeights"); - - glLinkProgram(program.programId()); - -#endif - - // HACK: Assign explicitely the attribute channel to avoid a bug on Yosemite - - glBindAttribLocation(program.programId(), gpu::Stream::SKIN_CLUSTER_INDEX, "clusterIndices"); - - glBindAttribLocation(program.programId(), gpu::Stream::SKIN_CLUSTER_WEIGHT, "clusterWeights"); - - glLinkProgram(program.programId()); +void Model::initSkinProgram(ProgramObject& program, Model::SkinLocations& locations) { + program.bindAttributeLocation("tangent", gpu::Stream::TANGENT); + program.bindAttributeLocation("texcoord1", gpu::Stream::TEXCOORD1); + program.bindAttributeLocation("clusterIndices", gpu::Stream::SKIN_CLUSTER_INDEX); + program.bindAttributeLocation("clusterWeights", gpu::Stream::SKIN_CLUSTER_WEIGHT); + program.link(); + + initProgram(program, locations, false); program.bind(); - locations.clusterMatrices = program.uniformLocation("clusterMatrices"); - - - + locations.clusterMatrices = program.uniformLocation("clusterMatrices"); locations.clusterIndices = program.attributeLocation("clusterIndices"); - locations.clusterWeights = program.attributeLocation("clusterWeights"); program.release(); @@ -269,7 +224,6 @@ void Model::init() { if (!_program.isLinked()) { _program.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/model.vert"); _program.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + "shaders/model.frag"); - _program.link(); initProgram(_program, _locations); @@ -277,116 +231,101 @@ void Model::init() { Application::resourcesPath() + "shaders/model_normal_map.vert"); _normalMapProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + "shaders/model_normal_map.frag"); - _normalMapProgram.link(); - + initProgram(_normalMapProgram, _normalMapLocations); _specularMapProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/model.vert"); _specularMapProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + "shaders/model_specular_map.frag"); - _specularMapProgram.link(); - + initProgram(_specularMapProgram, _specularMapLocations); _normalSpecularMapProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/model_normal_map.vert"); _normalSpecularMapProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + "shaders/model_normal_specular_map.frag"); - _normalSpecularMapProgram.link(); - - initProgram(_normalSpecularMapProgram, _normalSpecularMapLocations, 2); + + initProgram(_normalSpecularMapProgram, _normalSpecularMapLocations); _translucentProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/model.vert"); _translucentProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + "shaders/model_translucent.frag"); - _translucentProgram.link(); - + initProgram(_translucentProgram, _translucentLocations); // Lightmap _lightmapProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/model_lightmap.vert"); _lightmapProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + "shaders/model_lightmap.frag"); - _lightmapProgram.link(); - + initProgram(_lightmapProgram, _lightmapLocations); _lightmapNormalMapProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/model_lightmap_normal_map.vert"); _lightmapNormalMapProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + "shaders/model_lightmap_normal_map.frag"); - _lightmapNormalMapProgram.link(); - + initProgram(_lightmapNormalMapProgram, _lightmapNormalMapLocations); _lightmapSpecularMapProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/model_lightmap.vert"); _lightmapSpecularMapProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + "shaders/model_lightmap_specular_map.frag"); - _lightmapSpecularMapProgram.link(); - + initProgram(_lightmapSpecularMapProgram, _lightmapSpecularMapLocations); _lightmapNormalSpecularMapProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/model_lightmap_normal_map.vert"); _lightmapNormalSpecularMapProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + "shaders/model_lightmap_normal_specular_map.frag"); - _lightmapNormalSpecularMapProgram.link(); - - initProgram(_lightmapNormalSpecularMapProgram, _lightmapNormalSpecularMapLocations, 2); + + initProgram(_lightmapNormalSpecularMapProgram, _lightmapNormalSpecularMapLocations); // end lightmap _shadowProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/model_shadow.vert"); _shadowProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + "shaders/model_shadow.frag"); - _shadowProgram.link(); - + _skinProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/skin_model.vert"); _skinProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + "shaders/model.frag"); - _skinProgram.link(); - + initSkinProgram(_skinProgram, _skinLocations); _skinNormalMapProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/skin_model_normal_map.vert"); _skinNormalMapProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + "shaders/model_normal_map.frag"); - _skinNormalMapProgram.link(); - + initSkinProgram(_skinNormalMapProgram, _skinNormalMapLocations); _skinSpecularMapProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/skin_model.vert"); _skinSpecularMapProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + "shaders/model_specular_map.frag"); - _skinSpecularMapProgram.link(); - + initSkinProgram(_skinSpecularMapProgram, _skinSpecularMapLocations); _skinNormalSpecularMapProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/skin_model_normal_map.vert"); _skinNormalSpecularMapProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + "shaders/model_normal_specular_map.frag"); - _skinNormalSpecularMapProgram.link(); - - initSkinProgram(_skinNormalSpecularMapProgram, _skinNormalSpecularMapLocations, 2); + + initSkinProgram(_skinNormalSpecularMapProgram, _skinNormalSpecularMapLocations); _skinShadowProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/skin_model_shadow.vert"); _skinShadowProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + "shaders/model_shadow.frag"); - _skinShadowProgram.link(); - + initSkinProgram(_skinShadowProgram, _skinShadowLocations); _skinTranslucentProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/skin_model.vert"); _skinTranslucentProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + "shaders/model_translucent.frag"); - _skinTranslucentProgram.link(); - + initSkinProgram(_skinTranslucentProgram, _skinTranslucentLocations); } } @@ -600,8 +539,6 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g if (modelFrameBox.findRayIntersection(modelFrameOrigin, modelFrameDirection, distance, face)) { float bestDistance = std::numeric_limits::max(); - float bestTriangleDistance = std::numeric_limits::max(); - bool someTriangleHit = false; float distanceToSubMesh; BoxFace subMeshFace; @@ -615,7 +552,6 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g if (subMeshBox.findRayIntersection(origin, direction, distanceToSubMesh, subMeshFace)) { if (distanceToSubMesh < bestDistance) { if (pickAgainstTriangles) { - someTriangleHit = false; if (!_calculatedMeshTrianglesValid) { recalculateMeshBoxes(pickAgainstTriangles); } @@ -628,9 +564,6 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g float thisTriangleDistance; if (findRayTriangleIntersection(origin, direction, triangle, thisTriangleDistance)) { if (thisTriangleDistance < bestDistance) { - bestTriangleDistance = thisTriangleDistance; - someTriangleHit = true; - bestDistance = thisTriangleDistance; intersectedSomething = true; face = subMeshFace; diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 43b04b7a46..e875c8f06c 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -347,7 +347,7 @@ private: static Locations _lightmapSpecularMapLocations; static Locations _lightmapNormalSpecularMapLocations; - static void initProgram(ProgramObject& program, Locations& locations, int specularTextureUnit = 1); + static void initProgram(ProgramObject& program, Locations& locations, bool link = true); class SkinLocations : public Locations { public: @@ -363,7 +363,7 @@ private: static SkinLocations _skinShadowLocations; static SkinLocations _skinTranslucentLocations; - static void initSkinProgram(ProgramObject& program, SkinLocations& locations, int specularTextureUnit = 1); + static void initSkinProgram(ProgramObject& program, SkinLocations& locations); QVector _calculatedMeshBoxes; // world coordinate AABoxes for all sub mesh boxes bool _calculatedMeshBoxesValid; From 0813d53bee3433367b83680c33d0262bea351fee Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 11 Dec 2014 15:17:22 -0800 Subject: [PATCH 349/502] CR feedback --- interface/src/Application.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 19055ab61b..9b65469243 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -372,7 +372,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : _glWidget->setMouseTracking(true); _toolWindow = new ToolWindow(); - qDebug() << "_toolWindow:" << _toolWindow; _toolWindow->setWindowFlags(_toolWindow->windowFlags() | Qt::WindowStaysOnTopHint); _toolWindow->setWindowTitle("Tools"); From df66a0049bbbd302e4190ff1411ef3017d68f952 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 11 Dec 2014 15:33:46 -0800 Subject: [PATCH 350/502] Don't hide mouse when over a widget --- interface/src/Application.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 32d4557c66..7f10e83b02 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2284,13 +2284,14 @@ void Application::updateCursor(float deltaTime) { PerformanceWarning warn(showWarnings, "Application::updateCursor()"); bool hideMouse = false; - bool underMouse = _glWidget->underMouse(); + bool underMouse = QGuiApplication::topLevelAt(QCursor::pos()) == + Application::getInstance()->getWindow()->windowHandle(); static const int HIDE_CURSOR_TIMEOUT = 3 * USECS_PER_SECOND; // 3 second int elapsed = usecTimestampNow() - _lastMouseMove; - if ((elapsed > HIDE_CURSOR_TIMEOUT && underMouse) || + if ((elapsed > HIDE_CURSOR_TIMEOUT) || (OculusManager::isConnected() && Menu::getInstance()->isOptionChecked(MenuOption::EnableVRMode))) { - hideMouse = true; + hideMouse = underMouse; } setCursorVisible(!hideMouse); From fe8937e37ed762802cfaa3b9933682b52ffa92ba Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 11 Dec 2014 21:31:08 -0800 Subject: [PATCH 351/502] Make lasers able to emanate from index finger tips --- interface/src/avatar/Avatar.cpp | 93 +++++++++++++++++----------- interface/src/avatar/MyAvatar.h | 9 --- libraries/avatars/src/AvatarData.cpp | 11 +++- libraries/avatars/src/AvatarData.h | 6 ++ 4 files changed, 71 insertions(+), 48 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index c680c75056..74043b2339 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -277,43 +277,64 @@ void Avatar::render(const glm::vec3& cameraPosition, RenderMode renderMode, bool // render pointing lasers glm::vec3 laserColor = glm::vec3(1.0f, 0.0f, 1.0f); float laserLength = 50.0f; - if (_handState == HAND_STATE_LEFT_POINTING || - _handState == HAND_STATE_BOTH_POINTING) { - int leftIndex = _skeletonModel.getLeftHandJointIndex(); - glm::vec3 leftPosition; - glm::quat leftRotation; - _skeletonModel.getJointPositionInWorldFrame(leftIndex, leftPosition); - _skeletonModel.getJointRotationInWorldFrame(leftIndex, leftRotation); - glPushMatrix(); { - glTranslatef(leftPosition.x, leftPosition.y, leftPosition.z); - float angle = glm::degrees(glm::angle(leftRotation)); - glm::vec3 axis = glm::axis(leftRotation); - glRotatef(angle, axis.x, axis.y, axis.z); - glBegin(GL_LINES); - glColor3f(laserColor.x, laserColor.y, laserColor.z); - glVertex3f(0.0f, 0.0f, 0.0f); - glVertex3f(0.0f, laserLength, 0.0f); - glEnd(); - } glPopMatrix(); + glm::vec3 position; + glm::quat rotation; + bool havePosition, haveRotation; + + if (_handState & LEFT_HAND_POINTING_FLAG) { + + if (_handState & IS_FINGER_POINTING_FLAG) { + int leftIndexTip = getJointIndex("LeftHandIndex4"); + int leftIndexTipJoint = getJointIndex("LeftHandIndex3"); + havePosition = _skeletonModel.getJointPositionInWorldFrame(leftIndexTip, position); + haveRotation = _skeletonModel.getJointRotationInWorldFrame(leftIndexTipJoint, rotation); + } else { + int leftHand = _skeletonModel.getLeftHandJointIndex(); + havePosition = _skeletonModel.getJointPositionInWorldFrame(leftHand, position); + haveRotation = _skeletonModel.getJointRotationInWorldFrame(leftHand, rotation); + } + + if (havePosition && haveRotation) { + glPushMatrix(); { + glTranslatef(position.x, position.y, position.z); + float angle = glm::degrees(glm::angle(rotation)); + glm::vec3 axis = glm::axis(rotation); + glRotatef(angle, axis.x, axis.y, axis.z); + glBegin(GL_LINES); + glColor3f(laserColor.x, laserColor.y, laserColor.z); + glVertex3f(0.0f, 0.0f, 0.0f); + glVertex3f(0.0f, laserLength, 0.0f); + glEnd(); + } glPopMatrix(); + } } - if (_handState == HAND_STATE_RIGHT_POINTING || - _handState == HAND_STATE_BOTH_POINTING) { - int rightIndex = _skeletonModel.getRightHandJointIndex(); - glm::vec3 rightPosition; - glm::quat rightRotation; - _skeletonModel.getJointPositionInWorldFrame(rightIndex, rightPosition); - _skeletonModel.getJointRotationInWorldFrame(rightIndex, rightRotation); - glPushMatrix(); { - glTranslatef(rightPosition.x, rightPosition.y, rightPosition.z); - float angle = glm::degrees(glm::angle(rightRotation)); - glm::vec3 axis = glm::axis(rightRotation); - glRotatef(angle, axis.x, axis.y, axis.z); - glBegin(GL_LINES); - glColor3f(laserColor.x, laserColor.y, laserColor.z); - glVertex3f(0.0f, 0.0f, 0.0f); - glVertex3f(0.0f, laserLength, 0.0f); - glEnd(); - } glPopMatrix(); + + if (_handState & RIGHT_HAND_POINTING_FLAG) { + + if (_handState & IS_FINGER_POINTING_FLAG) { + int rightIndexTip = getJointIndex("RightHandIndex4"); + int rightIndexTipJoint = getJointIndex("RightHandIndex3"); + havePosition = _skeletonModel.getJointPositionInWorldFrame(rightIndexTip, position); + haveRotation = _skeletonModel.getJointRotationInWorldFrame(rightIndexTipJoint, rotation); + } else { + int rightHand = _skeletonModel.getRightHandJointIndex(); + havePosition = _skeletonModel.getJointPositionInWorldFrame(rightHand, position); + haveRotation = _skeletonModel.getJointRotationInWorldFrame(rightHand, rotation); + } + + if (havePosition && haveRotation) { + glPushMatrix(); { + glTranslatef(position.x, position.y, position.z); + float angle = glm::degrees(glm::angle(rotation)); + glm::vec3 axis = glm::axis(rotation); + glRotatef(angle, axis.x, axis.y, axis.z); + glBegin(GL_LINES); + glColor3f(laserColor.x, laserColor.y, laserColor.z); + glVertex3f(0.0f, 0.0f, 0.0f); + glVertex3f(0.0f, laserLength, 0.0f); + glEnd(); + } glPopMatrix(); + } } } diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 12ad4474c9..7bf6d057da 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -21,15 +21,6 @@ class ModelItemID; -enum AvatarHandState -{ - HAND_STATE_NULL = 0, - HAND_STATE_LEFT_POINTING, - HAND_STATE_RIGHT_POINTING, - HAND_STATE_BOTH_POINTING, - NUM_HAND_STATES -}; - class MyAvatar : public Avatar { Q_OBJECT Q_PROPERTY(bool shouldRenderLocally READ getShouldRenderLocally WRITE setShouldRenderLocally) diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 95432bc81a..d22d1c5a0a 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -188,7 +188,11 @@ QByteArray AvatarData::toByteArray() { // key state setSemiNibbleAt(bitItems,KEY_STATE_START_BIT,_keyState); // hand state - setSemiNibbleAt(bitItems,HAND_STATE_START_BIT,_handState); + bool isFingerPointing = _handState & IS_FINGER_POINTING_FLAG; + setSemiNibbleAt(bitItems, HAND_STATE_START_BIT, _handState & ~IS_FINGER_POINTING_FLAG); + if (isFingerPointing) { + setAtBit(bitItems, HAND_STATE_FINGER_POINTING_BIT); + } // faceshift state if (_headData->_isFaceshiftConnected) { setAtBit(bitItems, IS_FACESHIFT_CONNECTED); @@ -439,8 +443,9 @@ int AvatarData::parseDataAtOffset(const QByteArray& packet, int offset) { // key state, stored as a semi-nibble in the bitItems _keyState = (KeyState)getSemiNibbleAt(bitItems,KEY_STATE_START_BIT); - // hand state, stored as a semi-nibble in the bitItems - _handState = getSemiNibbleAt(bitItems,HAND_STATE_START_BIT); + // hand state, stored as a semi-nibble plus a bit in the bitItems + _handState = getSemiNibbleAt(bitItems, HAND_STATE_START_BIT) + + oneAtBit(bitItems, HAND_STATE_FINGER_POINTING_BIT) ? IS_FINGER_POINTING_FLAG : 0; _headData->_isFaceshiftConnected = oneAtBit(bitItems, IS_FACESHIFT_CONNECTED); _isChatCirclingEnabled = oneAtBit(bitItems, IS_CHAT_CIRCLING_ENABLED); diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index d590f95bfd..55b35377c0 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -82,6 +82,12 @@ const int HAND_STATE_START_BIT = 2; // 3rd and 4th bits const int IS_FACESHIFT_CONNECTED = 4; // 5th bit const int IS_CHAT_CIRCLING_ENABLED = 5; // 6th bit const int HAS_REFERENTIAL = 6; // 7th bit +const int HAND_STATE_FINGER_POINTING_BIT = 7; // 8th bit + +const char HAND_STATE_NULL = 0; +const char LEFT_HAND_POINTING_FLAG = 1; +const char RIGHT_HAND_POINTING_FLAG = 2; +const char IS_FINGER_POINTING_FLAG = 4; static const float MAX_AVATAR_SCALE = 1000.0f; static const float MIN_AVATAR_SCALE = .005f; From 1ab91296162bceab354ace56bf76cf5099015d5f Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 11 Dec 2014 21:31:23 -0800 Subject: [PATCH 352/502] Update laserPointer.js to detect pointing with Leap Motion or similar --- examples/laserPointer.js | 90 +++++++++++++++++++++++++++++++++++----- 1 file changed, 80 insertions(+), 10 deletions(-) diff --git a/examples/laserPointer.js b/examples/laserPointer.js index bedafe6a18..156e9ba298 100644 --- a/examples/laserPointer.js +++ b/examples/laserPointer.js @@ -5,19 +5,89 @@ // Created by Clément Brisset on 7/18/14. // Copyright 2014 High Fidelity, Inc. // +// If using Hydra controllers, pulling the triggers makes laser pointers emanate from the respective hands. +// If using a Leap Motion or similar to control your avatar's hands and fingers, pointing with your index fingers makes +// laser pointers emanate from the respective index fingers. +// // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -var LEFT = 0; -var RIGHT = 1; -var LEFT_HAND_FLAG = 1; -var RIGHT_HAND_FLAG = 2; +var laserPointer = (function () { -function update() { - var state = ((Controller.getTriggerValue(LEFT) > 0.9) ? LEFT_HAND_FLAG : 0) + - ((Controller.getTriggerValue(RIGHT) > 0.9) ? RIGHT_HAND_FLAG : 0); - MyAvatar.setHandState(state); -} + var NUM_FINGERs = 4, // Excluding thumb + fingers = [ + [ "LeftHandIndex", "LeftHandMiddle", "LeftHandRing", "LeftHandPinky" ], + [ "RightHandIndex", "RightHandMiddle", "RightHandRing", "RightHandPinky" ] + ]; -Script.update.connect(update); \ No newline at end of file + function isHandPointing(hand) { + var MINIMUM_TRIGGER_PULL = 0.9; + return Controller.getTriggerValue(hand) > MINIMUM_TRIGGER_PULL; + } + + function isFingerPointing(hand) { + // Index finger is pointing if final two bones of middle, ring, and pinky fingers are > 90 degrees w.r.t. index finger + + var pointing, + indexDirection, + otherDirection, + f; + + pointing = true; + + indexDirection = Vec3.subtract( + MyAvatar.getJointPosition(fingers[hand][0] + "4"), + MyAvatar.getJointPosition(fingers[hand][0] + "2") + ); + + for (f = 1; f < NUM_FINGERs; f += 1) { + otherDirection = Vec3.subtract( + MyAvatar.getJointPosition(fingers[hand][f] + "4"), + MyAvatar.getJointPosition(fingers[hand][f] + "2") + ); + pointing = pointing && Vec3.dot(indexDirection, otherDirection) < 0; + } + + return pointing; + } + + function update() { + var LEFT_HAND = 0, + RIGHT_HAND = 1, + LEFT_HAND_POINTING_FLAG = 1, + RIGHT_HAND_POINTING_FLAG = 2, + FINGER_POINTING_FLAG = 4, + handState; + + handState = 0; + + if (isHandPointing(LEFT_HAND)) { + handState += LEFT_HAND_POINTING_FLAG; + } + if (isHandPointing(RIGHT_HAND)) { + handState += RIGHT_HAND_POINTING_FLAG; + } + + if (handState === 0) { + if (isFingerPointing(LEFT_HAND)) { + handState += LEFT_HAND_POINTING_FLAG; + } + if (isFingerPointing(RIGHT_HAND)) { + handState += RIGHT_HAND_POINTING_FLAG; + } + if (handState !== 0) { + handState += FINGER_POINTING_FLAG; + } + } + + MyAvatar.setHandState(handState); + } + + return { + update: update + }; + +}()); + +Script.update.connect(laserPointer.update); From 20b880ca09833a60f13172207d0587524b47e821 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 11 Dec 2014 23:07:05 -0800 Subject: [PATCH 353/502] Fix avatar hand state decoding for finger laser --- libraries/avatars/src/AvatarData.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index d22d1c5a0a..01f84ca246 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -445,7 +445,7 @@ int AvatarData::parseDataAtOffset(const QByteArray& packet, int offset) { _keyState = (KeyState)getSemiNibbleAt(bitItems,KEY_STATE_START_BIT); // hand state, stored as a semi-nibble plus a bit in the bitItems _handState = getSemiNibbleAt(bitItems, HAND_STATE_START_BIT) - + oneAtBit(bitItems, HAND_STATE_FINGER_POINTING_BIT) ? IS_FINGER_POINTING_FLAG : 0; + + (oneAtBit(bitItems, HAND_STATE_FINGER_POINTING_BIT) ? IS_FINGER_POINTING_FLAG : 0); _headData->_isFaceshiftConnected = oneAtBit(bitItems, IS_FACESHIFT_CONNECTED); _isChatCirclingEnabled = oneAtBit(bitItems, IS_CHAT_CIRCLING_ENABLED); From 687072f19cf716305842151540d9aaa26f50a8ad Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 12 Dec 2014 09:47:15 -0800 Subject: [PATCH 354/502] fix for domain failed reconnect after disconnect --- libraries/networking/src/DomainHandler.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/networking/src/DomainHandler.cpp b/libraries/networking/src/DomainHandler.cpp index d64752dce0..6091b0cdd2 100644 --- a/libraries/networking/src/DomainHandler.cpp +++ b/libraries/networking/src/DomainHandler.cpp @@ -73,6 +73,7 @@ void DomainHandler::hardReset() { qDebug() << "Hard reset in NodeList DomainHandler."; _iceDomainID = QUuid(); + _iceServerSockAddr = HifiSockAddr(); _hostname = QString(); _sockAddr.setAddress(QHostAddress::Null); } From c1c5991ac50032a2429f57488bbe09b0c445d4ce Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Fri, 12 Dec 2014 12:07:48 -0800 Subject: [PATCH 355/502] Fix for distorted replaced textures. --- interface/src/MetavoxelSystem.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/interface/src/MetavoxelSystem.cpp b/interface/src/MetavoxelSystem.cpp index 87060d7dfa..002acec9ed 100644 --- a/interface/src/MetavoxelSystem.cpp +++ b/interface/src/MetavoxelSystem.cpp @@ -2188,13 +2188,15 @@ void HeightfieldNodeRenderer::render(const HeightfieldNodePointer& node, const g bufferPair.second.release(); } if (_heightTextureID == 0) { + // we use non-aligned data for the various layers + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glGenTextures(1, &_heightTextureID); glBindTexture(GL_TEXTURE_2D, _heightTextureID); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); const QVector& heightContents = node->getHeight()->getContents(); glTexImage2D(GL_TEXTURE_2D, 0, GL_R16, width, height, 0, GL_RED, GL_UNSIGNED_SHORT, heightContents.constData()); @@ -2241,6 +2243,9 @@ void HeightfieldNodeRenderer::render(const HeightfieldNodePointer& node, const g glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, 1, 1, 0, GL_RED, GL_UNSIGNED_BYTE, &ZERO_VALUE); } glBindTexture(GL_TEXTURE_2D, 0); + + // restore the default alignment; it's what Qt uses for image storage + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); } if (cursor) { From b8737ad5257058b6edea3f1fa17514b6a0bec2a4 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 12 Dec 2014 15:26:07 -0800 Subject: [PATCH 356/502] Update 'f' focus to only work when something is selected --- examples/editEntities.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/examples/editEntities.js b/examples/editEntities.js index e9f42bf74c..fc48cf22b5 100644 --- a/examples/editEntities.js +++ b/examples/editEntities.js @@ -839,9 +839,11 @@ Controller.keyReleaseEvent.connect(function (event) { selectionDisplay.toggleSpaceMode(); } else if (event.text == "f") { if (isActive) { - cameraManager.focus(selectionManager.worldPosition, - selectionManager.worldDimensions, - Menu.isOptionChecked(MENU_EASE_ON_FOCUS)); + if (selectionManager.hasSelection()) { + cameraManager.focus(selectionManager.worldPosition, + selectionManager.worldDimensions, + Menu.isOptionChecked(MENU_EASE_ON_FOCUS)); + } } } else if (event.text == '[') { if (isActive) { From d1f5bf2e3cdf9c68229dded470df12adc90140e9 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 12 Dec 2014 15:27:30 -0800 Subject: [PATCH 357/502] Add rotation to properties window --- examples/editEntities.js | 5 +++++ examples/html/entityProperties.html | 23 +++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/examples/editEntities.js b/examples/editEntities.js index fc48cf22b5..980f38f2cc 100644 --- a/examples/editEntities.js +++ b/examples/editEntities.js @@ -1004,6 +1004,7 @@ PropertiesTool = function(opts) { }; if (selectionManager.hasSelection()) { data.properties = Entities.getEntityProperties(selectionManager.selections[0]); + data.properties.rotation = Quat.safeEulerAngles(data.properties.rotation); } webView.eventBridge.emitScriptEvent(JSON.stringify(data)); }); @@ -1012,6 +1013,10 @@ PropertiesTool = function(opts) { print(data); data = JSON.parse(data); if (data.type == "update") { + if (data.properties.rotation !== undefined) { + var rotation = data.properties.rotation; + data.properties.rotation = Quat.fromPitchYawRollDegrees(rotation.x, rotation.y, rotation.z); + } Entities.editEntity(selectionManager.selections[0], data.properties); selectionManager._update(); } diff --git a/examples/html/entityProperties.html b/examples/html/entityProperties.html index 17eb0ad88f..d30aac72ee 100644 --- a/examples/html/entityProperties.html +++ b/examples/html/entityProperties.html @@ -85,6 +85,10 @@ var elRegistrationY = document.getElementById("property-reg-y"); var elRegistrationZ = document.getElementById("property-reg-z"); + var elRotationX = document.getElementById("property-rot-x"); + var elRotationY = document.getElementById("property-rot-y"); + var elRotationZ = document.getElementById("property-rot-z"); + var elLinearVelocityX = document.getElementById("property-lvel-x"); var elLinearVelocityY = document.getElementById("property-lvel-y"); var elLinearVelocityZ = document.getElementById("property-lvel-z"); @@ -181,6 +185,10 @@ elRegistrationY.value = properties.registrationPoint.y.toFixed(2); elRegistrationZ.value = properties.registrationPoint.z.toFixed(2); + elRotationX.value = properties.rotation.x.toFixed(2); + elRotationY.value = properties.rotation.y.toFixed(2); + elRotationZ.value = properties.rotation.z.toFixed(2); + elLinearVelocityX.value = properties.velocity.x.toFixed(2); elLinearVelocityY.value = properties.velocity.y.toFixed(2); elLinearVelocityZ.value = properties.velocity.z.toFixed(2); @@ -302,6 +310,12 @@ elRegistrationY.addEventListener('change', registrationChangeFunction); elRegistrationZ.addEventListener('change', registrationChangeFunction); + var rotationChangeFunction = createEmitVec3PropertyUpdateFunction( + 'rotation', elRotationX, elRotationY, elRotationZ); + elRotationX.addEventListener('change', rotationChangeFunction); + elRotationY.addEventListener('change', rotationChangeFunction); + elRotationZ.addEventListener('change', rotationChangeFunction); + var velocityChangeFunction = createEmitVec3PropertyUpdateFunction( 'velocity', elLinearVelocityX, elLinearVelocityY, elLinearVelocityZ); elLinearVelocityX.addEventListener('change', velocityChangeFunction); @@ -486,6 +500,15 @@ + + Rotation + +
Pitch
+
Yaw
+
Roll
+ + + Linear Velocity From 1a90a810379dd1ad196af9aeafa3792b89fa5d91 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 12 Dec 2014 15:27:56 -0800 Subject: [PATCH 358/502] Add id to properties window --- examples/editEntities.js | 1 + examples/html/entityProperties.html | 11 +++++++++++ examples/html/style.css | 11 +++++++++++ 3 files changed, 23 insertions(+) diff --git a/examples/editEntities.js b/examples/editEntities.js index 980f38f2cc..ea6496d4f5 100644 --- a/examples/editEntities.js +++ b/examples/editEntities.js @@ -1003,6 +1003,7 @@ PropertiesTool = function(opts) { type: 'update', }; if (selectionManager.hasSelection()) { + data.id = selectionManager.selections[0].id; data.properties = Entities.getEntityProperties(selectionManager.selections[0]); data.properties.rotation = Quat.safeEulerAngles(data.properties.rotation); } diff --git a/examples/html/entityProperties.html b/examples/html/entityProperties.html index d30aac72ee..a34f7ce13f 100644 --- a/examples/html/entityProperties.html +++ b/examples/html/entityProperties.html @@ -70,6 +70,7 @@ }; function loaded() { + var elID = document.getElementById("property-id"); var elType = document.getElementById("property-type"); var elLocked = document.getElementById("property-locked"); var elVisible = document.getElementById("property-visible"); @@ -160,6 +161,8 @@ } else { var properties = data.properties; + elID.innerHTML = data.id; + elType.innerHTML = properties.type; elLocked.checked = properties.locked; @@ -451,6 +454,14 @@ + + + ID + + + + + Type diff --git a/examples/html/style.css b/examples/html/style.css index 424933e14e..aa23cf97ab 100644 --- a/examples/html/style.css +++ b/examples/html/style.css @@ -17,6 +17,17 @@ body { user-select: none; } +.selectable { + -webkit-touch-callout: text; + -webkit-user-select: text; + -khtml-user-select: text; + -moz-user-select: text; + -ms-user-select: text; + user-select: text; + + cursor: text; +} + .color-box { display: inline-block; width: 20px; From a5cbc9b3e2fa3aa8e3544d30dc66529c4cc785f3 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 12 Dec 2014 15:28:22 -0800 Subject: [PATCH 359/502] Fix properties window to work with undo/redo --- examples/editEntities.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/editEntities.js b/examples/editEntities.js index ea6496d4f5..b671e45d7c 100644 --- a/examples/editEntities.js +++ b/examples/editEntities.js @@ -1014,11 +1014,13 @@ PropertiesTool = function(opts) { print(data); data = JSON.parse(data); if (data.type == "update") { + selectionManager.saveProperties(); if (data.properties.rotation !== undefined) { var rotation = data.properties.rotation; data.properties.rotation = Quat.fromPitchYawRollDegrees(rotation.x, rotation.y, rotation.z); } Entities.editEntity(selectionManager.selections[0], data.properties); + pushCommandForSelections(); selectionManager._update(); } }); From 33b4c614eae17ad3ef7c54a821e929f2ffb0ee52 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 12 Dec 2014 15:28:57 -0800 Subject: [PATCH 360/502] Add buttons for moving selection to grid and resetting to natural dimensions --- examples/editEntities.js | 48 +++++++++++++++++++++++++++++ examples/html/entityProperties.html | 29 +++++++++++++++++ 2 files changed, 77 insertions(+) diff --git a/examples/editEntities.js b/examples/editEntities.js index b671e45d7c..3f133ac0b2 100644 --- a/examples/editEntities.js +++ b/examples/editEntities.js @@ -1022,6 +1022,54 @@ PropertiesTool = function(opts) { Entities.editEntity(selectionManager.selections[0], data.properties); pushCommandForSelections(); selectionManager._update(); + } else if (data.type == "action") { + if (data.action == "moveSelectionToGrid") { + if (!selectionManager.hasSelection()) { + return; + } + selectionManager.saveProperties(); + var dY = grid.getOrigin().y - (selectionManager.worldPosition.y - selectionManager.worldDimensions.y / 2), + var diff = { x: 0, y: dY, z: 0 }; + for (var i = 0; i < SelectionManager.selections.length; i++) { + var properties = SelectionManager.savedProperties[SelectionManager.selections[i].id]; + var newPosition = Vec3.sum(properties.position, diff); + Entities.editEntity(SelectionManager.selections[i], { + position: newPosition, + }); + } + pushCommandForSelections(); + selectionManager._update(); + } else if (data.action == "moveAllToGrid") { + if (!selectionManager.hasSelection()) { + return; + } + selectionManager.saveProperties(); + for (var i = 0; i < SelectionManager.selections.length; i++) { + var properties = SelectionManager.savedProperties[SelectionManager.selections[i].id]; + var bottomY = properties.boundingBox.center.y - properties.boundingBox.dimensions.y / 2; + var dY = grid.getOrigin().y - bottomY; + var diff = { x: 0, y: dY, z: 0 }; + var newPosition = Vec3.sum(properties.position, diff); + Entities.editEntity(SelectionManager.selections[i], { + position: newPosition, + }); + } + pushCommandForSelections(); + selectionManager._update(); + } else if (data.action == "resetToNaturalDimensions") { + if (!selectionManager.hasSelection()) { + return; + } + selectionManager.saveProperties(); + for (var i = 0; i < SelectionManager.selections.length; i++) { + var properties = SelectionManager.savedProperties[SelectionManager.selections[i].id]; + Entities.editEntity(SelectionManager.selections[i], { + dimensions: properties.naturalDimensions, + }); + } + pushCommandForSelections(); + selectionManager._update(); + } } }); diff --git a/examples/html/entityProperties.html b/examples/html/entityProperties.html index a34f7ce13f..48804d475a 100644 --- a/examples/html/entityProperties.html +++ b/examples/html/entityProperties.html @@ -77,10 +77,13 @@ var elPositionX = document.getElementById("property-pos-x"); var elPositionY = document.getElementById("property-pos-y"); var elPositionZ = document.getElementById("property-pos-z"); + var elMoveSelectionToGrid = document.getElementById("move-selection-to-grid"); + var elMoveAllToGrid = document.getElementById("move-all-to-grid"); var elDimensionsX = document.getElementById("property-dim-x"); var elDimensionsY = document.getElementById("property-dim-y"); var elDimensionsZ = document.getElementById("property-dim-z"); + var elResetToNaturalDimensions = document.getElementById("reset-to-natural-dimensions"); var elRegistrationX = document.getElementById("property-reg-x"); var elRegistrationY = document.getElementById("property-reg-y"); @@ -398,6 +401,25 @@ elTextBackgroundColorGreen.addEventListener('change', textBackgroundColorChangeFunction); elTextBackgroundColorBlue.addEventListener('change', textBackgroundColorChangeFunction); + elMoveSelectionToGrid.addEventListener("click", function() { + EventBridge.emitWebEvent(JSON.stringify({ + type: "action", + action: "moveSelectionToGrid", + })); + }); + elMoveAllToGrid.addEventListener("click", function() { + EventBridge.emitWebEvent(JSON.stringify({ + type: "action", + action: "moveAllToGrid", + })); + }); + elResetToNaturalDimensions.addEventListener("click", function() { + EventBridge.emitWebEvent(JSON.stringify({ + type: "action", + action: "resetToNaturalDimensions", + })); + }); + var resizing = false; var startX = 0; @@ -490,6 +512,10 @@
X
Y
Z
+
+ + +
@@ -508,6 +534,9 @@
X
Y
Z
+
+ +
From dde9b92dbd4a02d630f171a7f1d72dea36236a88 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 12 Dec 2014 15:31:54 -0800 Subject: [PATCH 361/502] Update SelectionManager -> selectionManager --- examples/editEntities.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/examples/editEntities.js b/examples/editEntities.js index 3f133ac0b2..c2f2ad4086 100644 --- a/examples/editEntities.js +++ b/examples/editEntities.js @@ -1030,10 +1030,10 @@ PropertiesTool = function(opts) { selectionManager.saveProperties(); var dY = grid.getOrigin().y - (selectionManager.worldPosition.y - selectionManager.worldDimensions.y / 2), var diff = { x: 0, y: dY, z: 0 }; - for (var i = 0; i < SelectionManager.selections.length; i++) { - var properties = SelectionManager.savedProperties[SelectionManager.selections[i].id]; + for (var i = 0; i < selectionManager.selections.length; i++) { + var properties = selectionManager.savedProperties[selectionManager.selections[i].id]; var newPosition = Vec3.sum(properties.position, diff); - Entities.editEntity(SelectionManager.selections[i], { + Entities.editEntity(selectionManager.selections[i], { position: newPosition, }); } @@ -1044,13 +1044,13 @@ PropertiesTool = function(opts) { return; } selectionManager.saveProperties(); - for (var i = 0; i < SelectionManager.selections.length; i++) { - var properties = SelectionManager.savedProperties[SelectionManager.selections[i].id]; + for (var i = 0; i < selectionManager.selections.length; i++) { + var properties = selectionManager.savedProperties[selectionManager.selections[i].id]; var bottomY = properties.boundingBox.center.y - properties.boundingBox.dimensions.y / 2; var dY = grid.getOrigin().y - bottomY; var diff = { x: 0, y: dY, z: 0 }; var newPosition = Vec3.sum(properties.position, diff); - Entities.editEntity(SelectionManager.selections[i], { + Entities.editEntity(selectionManager.selections[i], { position: newPosition, }); } @@ -1061,9 +1061,9 @@ PropertiesTool = function(opts) { return; } selectionManager.saveProperties(); - for (var i = 0; i < SelectionManager.selections.length; i++) { - var properties = SelectionManager.savedProperties[SelectionManager.selections[i].id]; - Entities.editEntity(SelectionManager.selections[i], { + for (var i = 0; i < selectionManager.selections.length; i++) { + var properties = selectionManager.savedProperties[selectionManager.selections[i].id]; + Entities.editEntity(selectionManager.selections[i], { dimensions: properties.naturalDimensions, }); } From 2fab404f7fee8c04a0fe3ce2e8a117cb00a57b37 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 12 Dec 2014 15:35:39 -0800 Subject: [PATCH 362/502] Reorganize selectionManager selection checking --- examples/editEntities.js | 79 +++++++++++++++++++--------------------- 1 file changed, 38 insertions(+), 41 deletions(-) diff --git a/examples/editEntities.js b/examples/editEntities.js index c2f2ad4086..0b5c089c07 100644 --- a/examples/editEntities.js +++ b/examples/editEntities.js @@ -1024,51 +1024,48 @@ PropertiesTool = function(opts) { selectionManager._update(); } else if (data.type == "action") { if (data.action == "moveSelectionToGrid") { - if (!selectionManager.hasSelection()) { - return; - } - selectionManager.saveProperties(); - var dY = grid.getOrigin().y - (selectionManager.worldPosition.y - selectionManager.worldDimensions.y / 2), - var diff = { x: 0, y: dY, z: 0 }; - for (var i = 0; i < selectionManager.selections.length; i++) { - var properties = selectionManager.savedProperties[selectionManager.selections[i].id]; - var newPosition = Vec3.sum(properties.position, diff); - Entities.editEntity(selectionManager.selections[i], { - position: newPosition, - }); - } - pushCommandForSelections(); - selectionManager._update(); - } else if (data.action == "moveAllToGrid") { - if (!selectionManager.hasSelection()) { - return; - } - selectionManager.saveProperties(); - for (var i = 0; i < selectionManager.selections.length; i++) { - var properties = selectionManager.savedProperties[selectionManager.selections[i].id]; - var bottomY = properties.boundingBox.center.y - properties.boundingBox.dimensions.y / 2; - var dY = grid.getOrigin().y - bottomY; + if (selectionManager.hasSelection()) { + selectionManager.saveProperties(); + var dY = grid.getOrigin().y - (selectionManager.worldPosition.y - selectionManager.worldDimensions.y / 2), var diff = { x: 0, y: dY, z: 0 }; - var newPosition = Vec3.sum(properties.position, diff); - Entities.editEntity(selectionManager.selections[i], { - position: newPosition, - }); + for (var i = 0; i < selectionManager.selections.length; i++) { + var properties = selectionManager.savedProperties[selectionManager.selections[i].id]; + var newPosition = Vec3.sum(properties.position, diff); + Entities.editEntity(selectionManager.selections[i], { + position: newPosition, + }); + } + pushCommandForSelections(); + selectionManager._update(); + } + } else if (data.action == "moveAllToGrid") { + if (selectionManager.hasSelection()) { + selectionManager.saveProperties(); + for (var i = 0; i < selectionManager.selections.length; i++) { + var properties = selectionManager.savedProperties[selectionManager.selections[i].id]; + var bottomY = properties.boundingBox.center.y - properties.boundingBox.dimensions.y / 2; + var dY = grid.getOrigin().y - bottomY; + var diff = { x: 0, y: dY, z: 0 }; + var newPosition = Vec3.sum(properties.position, diff); + Entities.editEntity(selectionManager.selections[i], { + position: newPosition, + }); + } + pushCommandForSelections(); + selectionManager._update(); } - pushCommandForSelections(); - selectionManager._update(); } else if (data.action == "resetToNaturalDimensions") { - if (!selectionManager.hasSelection()) { - return; + if (selectionManager.hasSelection()) { + selectionManager.saveProperties(); + for (var i = 0; i < selectionManager.selections.length; i++) { + var properties = selectionManager.savedProperties[selectionManager.selections[i].id]; + Entities.editEntity(selectionManager.selections[i], { + dimensions: properties.naturalDimensions, + }); + } + pushCommandForSelections(); + selectionManager._update(); } - selectionManager.saveProperties(); - for (var i = 0; i < selectionManager.selections.length; i++) { - var properties = selectionManager.savedProperties[selectionManager.selections[i].id]; - Entities.editEntity(selectionManager.selections[i], { - dimensions: properties.naturalDimensions, - }); - } - pushCommandForSelections(); - selectionManager._update(); } } }); From a9223f58879f2afbb3cef72ffc4181b24a61dbb2 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 12 Dec 2014 15:45:31 -0800 Subject: [PATCH 363/502] Remove text from label --- examples/html/entityProperties.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/html/entityProperties.html b/examples/html/entityProperties.html index 48804d475a..4e22637ad6 100644 --- a/examples/html/entityProperties.html +++ b/examples/html/entityProperties.html @@ -481,7 +481,7 @@ ID - + From 14cda00ebc46ba02f68bbbd3ae111059d1ccac9c Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 12 Dec 2014 20:52:41 -0800 Subject: [PATCH 364/502] First implementation of the DependencyManager --- libraries/shared/src/DependencyManager.cpp | 33 +++++++++++++ libraries/shared/src/DependencyManager.h | 55 ++++++++++++++++++++++ 2 files changed, 88 insertions(+) create mode 100644 libraries/shared/src/DependencyManager.cpp create mode 100644 libraries/shared/src/DependencyManager.h diff --git a/libraries/shared/src/DependencyManager.cpp b/libraries/shared/src/DependencyManager.cpp new file mode 100644 index 0000000000..b4b3061317 --- /dev/null +++ b/libraries/shared/src/DependencyManager.cpp @@ -0,0 +1,33 @@ +// +// DependencyManager.cpp +// +// +// Created by Clément Brisset on 12/10/14. +// 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 "DependencyManager.h" + +DependencyManager& DependencyManager::getInstance() { + static DependencyManager instance; + return instance; +} + +DependencyManager::DependencyManager() { + // Guard against request of ourself + // We could set the value to this, but since it doesn't make sense to access + // the DependencyManager instance from the outside let's set it to NULL + _instanceHash.insert(typeid(DependencyManager).name(), NULL); +} + +DependencyManager::~DependencyManager() { + foreach (Dependency* instance, _instanceHash) { + if (instance) { + instance->deleteInstance(); + } + } + _instanceHash.clear(); +} \ No newline at end of file diff --git a/libraries/shared/src/DependencyManager.h b/libraries/shared/src/DependencyManager.h new file mode 100644 index 0000000000..690058cab4 --- /dev/null +++ b/libraries/shared/src/DependencyManager.h @@ -0,0 +1,55 @@ +// +// DependencyManager.h +// +// +// Created by Clément Brisset on 12/10/14. +// 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_DependencyManager_h +#define hifi_DependencyManager_h + +#include +#include + +#include + +class DependencyManager { +public: + template + static T* get(); + + class Dependency { + virtual void deleteInstance() = 0; + friend DependencyManager; + }; +private: + static DependencyManager& getInstance(); + DependencyManager(); + ~DependencyManager(); + + typedef QHash InstanceHash; + static InstanceHash& getInstanceHash() { return getInstance()._instanceHash; } + InstanceHash _instanceHash; +}; + +template +T* DependencyManager::get() { + const QString& typeId = typeid(T).name(); + + // Search the hash for global instance + Dependency* instance = getInstanceHash().value(typeId, NULL); + if (instance) { + return dynamic_cast(instance); + } + + // Found no instance in hash so we create one. + T* newInstance = new T(); + getInstanceHash().insert(typeId, dynamic_cast(newInstance)); + return newInstance; +} + +#endif // hifi_DependencyManager_h \ No newline at end of file From 50fd52377ff72e63c038a2b5aff908b855f7c026 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 12 Dec 2014 21:10:45 -0800 Subject: [PATCH 365/502] Couple improvements to the dependency manager --- libraries/shared/src/DependencyManager.cpp | 9 +-------- libraries/shared/src/DependencyManager.h | 14 +++++++++++--- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/libraries/shared/src/DependencyManager.cpp b/libraries/shared/src/DependencyManager.cpp index b4b3061317..41cb405ac7 100644 --- a/libraries/shared/src/DependencyManager.cpp +++ b/libraries/shared/src/DependencyManager.cpp @@ -16,17 +16,10 @@ DependencyManager& DependencyManager::getInstance() { return instance; } -DependencyManager::DependencyManager() { - // Guard against request of ourself - // We could set the value to this, but since it doesn't make sense to access - // the DependencyManager instance from the outside let's set it to NULL - _instanceHash.insert(typeid(DependencyManager).name(), NULL); -} - DependencyManager::~DependencyManager() { foreach (Dependency* instance, _instanceHash) { if (instance) { - instance->deleteInstance(); + delete instance; } } _instanceHash.clear(); diff --git a/libraries/shared/src/DependencyManager.h b/libraries/shared/src/DependencyManager.h index 690058cab4..2a81941b8a 100644 --- a/libraries/shared/src/DependencyManager.h +++ b/libraries/shared/src/DependencyManager.h @@ -19,16 +19,24 @@ class DependencyManager { public: + // Only accessible method. + // usage: T* instance = DependencyManager::get(); template static T* get(); + // Any class T in the DependencyManager needs to subclass Dependency + // They also need to have protected constructor(s) and virtual destructor + // As well as declare DependencyManager a friend class class Dependency { - virtual void deleteInstance() = 0; + protected: + Dependency() {} + virtual ~Dependency() {} // Ensure the proper destruction of the object friend DependencyManager; }; + private: static DependencyManager& getInstance(); - DependencyManager(); + DependencyManager() {} ~DependencyManager(); typedef QHash InstanceHash; @@ -52,4 +60,4 @@ T* DependencyManager::get() { return newInstance; } -#endif // hifi_DependencyManager_h \ No newline at end of file +#endif // hifi_DependencyManager_h From 9aea2843ac89fbeae4a0463bc8e7d4c3f23691c2 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 12 Dec 2014 21:20:26 -0800 Subject: [PATCH 366/502] Remove pointer check --- libraries/shared/src/DependencyManager.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/libraries/shared/src/DependencyManager.cpp b/libraries/shared/src/DependencyManager.cpp index 41cb405ac7..c858cb7059 100644 --- a/libraries/shared/src/DependencyManager.cpp +++ b/libraries/shared/src/DependencyManager.cpp @@ -18,9 +18,7 @@ DependencyManager& DependencyManager::getInstance() { DependencyManager::~DependencyManager() { foreach (Dependency* instance, _instanceHash) { - if (instance) { - delete instance; - } + delete instance; } _instanceHash.clear(); } \ No newline at end of file From d28e274876491a7e0f5f4c05254294e9179c5cf7 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sat, 13 Dec 2014 07:43:40 -0800 Subject: [PATCH 367/502] fix warning --- interface/src/Application.h | 2 ++ interface/src/voxels/VoxelSystem.cpp | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/interface/src/Application.h b/interface/src/Application.h index f82b14b47e..1b51b99e77 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -12,6 +12,8 @@ #ifndef hifi_Application_h #define hifi_Application_h +// testing + #include #include diff --git a/interface/src/voxels/VoxelSystem.cpp b/interface/src/voxels/VoxelSystem.cpp index 2f4fd3f0fa..67f3d585ea 100644 --- a/interface/src/voxels/VoxelSystem.cpp +++ b/interface/src/voxels/VoxelSystem.cpp @@ -874,7 +874,6 @@ int VoxelSystem::updateNodeInArrays(VoxelTreeElement* node, bool reuseIndex, boo if (node->getShouldRender()) { glm::vec3 startVertex = node->getCorner(); float voxelScale = node->getScale(); - nodeColor const & color = node->getColor(); glBufferIndex nodeIndex = GLBUFFER_INDEX_UNKNOWN; if (reuseIndex && node->isKnownBufferIndex()) { From 31db2188cb0f77060b070c0a485b05887dc84101 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sat, 13 Dec 2014 07:58:13 -0800 Subject: [PATCH 368/502] remove test comment --- interface/src/Application.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/interface/src/Application.h b/interface/src/Application.h index 1b51b99e77..f82b14b47e 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -12,8 +12,6 @@ #ifndef hifi_Application_h #define hifi_Application_h -// testing - #include #include From ad2dee5eaab5afa8e684d7e3274697a005567e8e Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Sun, 14 Dec 2014 16:26:08 -0800 Subject: [PATCH 369/502] Switched devices to DependencyManager for Faceshift --- interface/src/devices/FaceTracker.h | 2 +- interface/src/devices/Faceshift.h | 3 +++ interface/src/devices/Visage.cpp | 9 +++++---- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/interface/src/devices/FaceTracker.h b/interface/src/devices/FaceTracker.h index 459f38cafc..75954871e5 100644 --- a/interface/src/devices/FaceTracker.h +++ b/interface/src/devices/FaceTracker.h @@ -23,8 +23,8 @@ class FaceTracker : public QObject { Q_OBJECT public: - FaceTracker(); + virtual ~FaceTracker() {} const glm::vec3& getHeadTranslation() const { return _headTranslation; } const glm::quat& getHeadRotation() const { return _headRotation; } diff --git a/interface/src/devices/Faceshift.h b/interface/src/devices/Faceshift.h index 3b4092c099..618a8fb975 100644 --- a/interface/src/devices/Faceshift.h +++ b/interface/src/devices/Faceshift.h @@ -19,6 +19,8 @@ #include #endif +#include + #include "FaceTracker.h" /// Handles interaction with the Faceshift software, which provides head position/orientation and facial features. @@ -27,6 +29,7 @@ class Faceshift : public FaceTracker { public: Faceshift(); + virtual ~Faceshift() {} void init(); diff --git a/interface/src/devices/Visage.cpp b/interface/src/devices/Visage.cpp index 9c7416c219..38dcdb4ce6 100644 --- a/interface/src/devices/Visage.cpp +++ b/interface/src/devices/Visage.cpp @@ -11,11 +11,12 @@ #include + +#include +#include #include #include -#include - #include "Application.h" #include "Visage.h" @@ -119,7 +120,7 @@ static const QMultiHash >& getActionUnitNameMap() const float TRANSLATION_SCALE = 20.0f; void Visage::init() { - connect(Application::getInstance()->getFaceshift(), SIGNAL(connectionStateChanged()), SLOT(updateEnabled())); + connect(DependencyManager::get(), SIGNAL(connectionStateChanged()), SLOT(updateEnabled())); updateEnabled(); } @@ -171,7 +172,7 @@ void Visage::reset() { void Visage::updateEnabled() { setEnabled(Menu::getInstance()->isOptionChecked(MenuOption::Visage) && !(Menu::getInstance()->isOptionChecked(MenuOption::Faceshift) && - Application::getInstance()->getFaceshift()->isConnectedOrConnecting())); + DependencyManager::get()->isConnectedOrConnecting())); } void Visage::setEnabled(bool enabled) { From 1d9e53e227026dfe685e082be3e2262a81724585 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Sun, 14 Dec 2014 16:28:28 -0800 Subject: [PATCH 370/502] Switched avatar to DependencyManager for Faceshift --- interface/src/avatar/Head.cpp | 17 +++++++++-------- interface/src/avatar/MyAvatar.cpp | 4 ++-- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index 660ebfcbb3..4b1e9e358c 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -10,6 +10,7 @@ #include +#include #include #include "Application.h" @@ -196,14 +197,14 @@ void Head::simulate(float deltaTime, bool isMine, bool billboard) { _mouth2 = glm::mix(_audioJawOpen * MMMM_POWER, _mouth2, MMMM_PERIOD + randFloat() * MMMM_RANDOM_PERIOD); _mouth4 = glm::mix(_audioJawOpen, _mouth4, SMILE_PERIOD + randFloat() * SMILE_RANDOM_PERIOD); - Application::getInstance()->getFaceshift()->updateFakeCoefficients(_leftEyeBlink, - _rightEyeBlink, - _browAudioLift, - _audioJawOpen, - _mouth2, - _mouth3, - _mouth4, - _blendshapeCoefficients); + DependencyManager::get()->updateFakeCoefficients(_leftEyeBlink, + _rightEyeBlink, + _browAudioLift, + _audioJawOpen, + _mouth2, + _mouth3, + _mouth4, + _blendshapeCoefficients); } else { _saccade = glm::vec3(); } diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 32053ea076..17cda19980 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -421,8 +422,7 @@ void MyAvatar::render(const glm::vec3& cameraPosition, RenderMode renderMode, bo } void MyAvatar::renderHeadMouse(int screenWidth, int screenHeight) const { - - Faceshift* faceshift = Application::getInstance()->getFaceshift(); + Faceshift* faceshift = DependencyManager::get(); float pixelsPerDegree = screenHeight / Menu::getInstance()->getFieldOfView(); From 39a19a297ffd27fa92082ff389a6831c27e80cd5 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Sun, 14 Dec 2014 16:31:03 -0800 Subject: [PATCH 371/502] Switched menu to DependencyManager for Faceshift --- interface/src/Menu.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 5e35f08e95..ec9b93e072 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -31,9 +31,10 @@ #include #include -#include +#include #include #include +#include #include "Application.h" #include "AccountManager.h" @@ -432,7 +433,7 @@ Menu::Menu() : MenuOption::Faceshift, 0, true, - appInstance->getFaceshift(), + DependencyManager::get(), SLOT(setTCPEnabled(bool))); #endif #ifdef HAVE_VISAGE From 1db3592d4c593a595fe1a5905f94fb2c6c0b0271 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Sun, 14 Dec 2014 19:56:42 -0800 Subject: [PATCH 372/502] Switched meFaceshifto DependencyManager for Faceshift --- interface/src/Application.cpp | 17 ++++++++++------- interface/src/Application.h | 4 +--- interface/src/devices/Faceshift.h | 2 +- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 7a0e61240a..8a13ef650d 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -55,6 +55,7 @@ #include #include #include +#include #include #include #include @@ -1690,8 +1691,10 @@ int Application::getMouseDragStartedY() const { } FaceTracker* Application::getActiveFaceTracker() { + Faceshift* faceshift = DependencyManager::get(); + return (_dde.isActive() ? static_cast(&_dde) : - (_faceshift.isActive() ? static_cast(&_faceshift) : + (faceshift->isActive() ? static_cast(faceshift) : (_visage.isActive() ? static_cast(&_visage) : NULL))); } @@ -1976,7 +1979,7 @@ void Application::init() { #endif // initialize our face trackers after loading the menu settings - _faceshift.init(); + DependencyManager::get()->init(); _visage.init(); Leapmotion::init(); @@ -2101,13 +2104,13 @@ void Application::updateMouseRay() { void Application::updateFaceshift() { bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); PerformanceWarning warn(showWarnings, "Application::updateFaceshift()"); - + Faceshift* faceshift = DependencyManager::get(); // Update faceshift - _faceshift.update(); + faceshift->update(); // Copy angular velocity if measured by faceshift, to the head - if (_faceshift.isActive()) { - _myAvatar->getHead()->setAngularVelocity(_faceshift.getHeadAngularVelocity()); + if (faceshift->isActive()) { + _myAvatar->getHead()->setAngularVelocity(faceshift->getHeadAngularVelocity()); } } @@ -3549,7 +3552,7 @@ void Application::deleteVoxelAt(const VoxelDetail& voxel) { } void Application::resetSensors() { - _faceshift.reset(); + DependencyManager::get()->reset(); _visage.reset(); _dde.reset(); diff --git a/interface/src/Application.h b/interface/src/Application.h index f82b14b47e..61ae317713 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -220,8 +220,7 @@ public: int getMouseDragStartedY() const; int getTrueMouseDragStartedX() const { return _mouseDragStartedX; } int getTrueMouseDragStartedY() const { return _mouseDragStartedY; } - bool getLastMouseMoveWasSimulated() const { return _lastMouseMoveWasSimulated;; } - Faceshift* getFaceshift() { return &_faceshift; } + bool getLastMouseMoveWasSimulated() const { return _lastMouseMoveWasSimulated; } Visage* getVisage() { return &_visage; } DdeFaceTracker* getDDE() { return &_dde; } FaceTracker* getActiveFaceTracker(); @@ -532,7 +531,6 @@ private: AvatarManager _avatarManager; MyAvatar* _myAvatar; // TODO: move this and relevant code to AvatarManager (or MyAvatar as the case may be) - Faceshift _faceshift; Visage _visage; DdeFaceTracker _dde; diff --git a/interface/src/devices/Faceshift.h b/interface/src/devices/Faceshift.h index 618a8fb975..83be51c7fa 100644 --- a/interface/src/devices/Faceshift.h +++ b/interface/src/devices/Faceshift.h @@ -24,7 +24,7 @@ #include "FaceTracker.h" /// Handles interaction with the Faceshift software, which provides head position/orientation and facial features. -class Faceshift : public FaceTracker { +class Faceshift : public FaceTracker, public DependencyManager::Dependency { Q_OBJECT public: From e40961df12f4edeee6c69250bfa9e9e8da09f37d Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Sun, 14 Dec 2014 21:34:27 -0800 Subject: [PATCH 373/502] Checking that T is in fact derived from Dependency --- libraries/shared/src/DependencyManager.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libraries/shared/src/DependencyManager.h b/libraries/shared/src/DependencyManager.h index 2a81941b8a..87c7c7b4a6 100644 --- a/libraries/shared/src/DependencyManager.h +++ b/libraries/shared/src/DependencyManager.h @@ -16,6 +16,7 @@ #include #include +#include class DependencyManager { public: @@ -56,7 +57,9 @@ T* DependencyManager::get() { // Found no instance in hash so we create one. T* newInstance = new T(); - getInstanceHash().insert(typeId, dynamic_cast(newInstance)); + instance = dynamic_cast(newInstance); + assert(instance != NULL); // If this triggers, check that T is derived from Dependency + getInstanceHash().insert(typeId, instance); return newInstance; } From 65094f21654e1ddd78232c20d9c0e8ff1e0985dd Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Sun, 14 Dec 2014 21:47:08 -0800 Subject: [PATCH 374/502] Update headers --- interface/src/Application.cpp | 1 + interface/src/Application.h | 1 - interface/src/Menu.cpp | 1 + interface/src/avatar/Head.cpp | 1 + interface/src/devices/Faceshift.cpp | 1 - interface/src/devices/Visage.cpp | 1 + 6 files changed, 4 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 8a13ef650d..3706206f1f 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -77,6 +77,7 @@ #include "ModelUploader.h" #include "Util.h" +#include "devices/Faceshift.h" #include "devices/Leapmotion.h" #include "devices/MIDIManager.h" #include "devices/OculusManager.h" diff --git a/interface/src/Application.h b/interface/src/Application.h index 61ae317713..d1d15d22a9 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -54,7 +54,6 @@ #include "avatar/Avatar.h" #include "avatar/AvatarManager.h" #include "avatar/MyAvatar.h" -#include "devices/Faceshift.h" #include "devices/PrioVR.h" #include "devices/SixenseManager.h" #include "devices/Visage.h" diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index ec9b93e072..c08df2b2c5 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -38,6 +38,7 @@ #include "Application.h" #include "AccountManager.h" +#include "devices/Faceshift.h" #include "Menu.h" #include "scripting/LocationScriptingInterface.h" #include "scripting/MenuScriptingInterface.h" diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index 4b1e9e358c..a16cdd9270 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -11,6 +11,7 @@ #include #include +#include #include #include "Application.h" diff --git a/interface/src/devices/Faceshift.cpp b/interface/src/devices/Faceshift.cpp index fb74f416a9..5c1bbfe709 100644 --- a/interface/src/devices/Faceshift.cpp +++ b/interface/src/devices/Faceshift.cpp @@ -14,7 +14,6 @@ #include #include -#include "Application.h" #include "Faceshift.h" #include "Menu.h" #include "Util.h" diff --git a/interface/src/devices/Visage.cpp b/interface/src/devices/Visage.cpp index 38dcdb4ce6..51b927df75 100644 --- a/interface/src/devices/Visage.cpp +++ b/interface/src/devices/Visage.cpp @@ -18,6 +18,7 @@ #include #include "Application.h" +#include "Faceshift.h" #include "Visage.h" // this has to go after our normal includes, because its definition of HANDLE conflicts with Qt's From 738f23f326a0e1d9ac353aeaef8c6c769d542166 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Sun, 14 Dec 2014 22:30:13 -0800 Subject: [PATCH 375/502] Moved visage and dde over to DependencyManager --- interface/src/Application.cpp | 18 +++++++++++------- interface/src/Application.h | 8 +------- interface/src/Menu.cpp | 5 +++-- interface/src/avatar/Head.cpp | 11 +++++++---- interface/src/devices/DdeFaceTracker.h | 13 ++++++++----- interface/src/devices/Faceshift.h | 6 +++--- interface/src/devices/Visage.h | 11 ++++++----- 7 files changed, 39 insertions(+), 33 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 3706206f1f..fbe55071e4 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -77,11 +77,13 @@ #include "ModelUploader.h" #include "Util.h" +#include "devices/DdeFaceTracker.h" #include "devices/Faceshift.h" #include "devices/Leapmotion.h" #include "devices/MIDIManager.h" #include "devices/OculusManager.h" #include "devices/TV3DManager.h" +#include "devices/Visage.h" #include "renderer/ProgramObject.h" #include "gpu/Batch.h" @@ -1693,10 +1695,12 @@ int Application::getMouseDragStartedY() const { FaceTracker* Application::getActiveFaceTracker() { Faceshift* faceshift = DependencyManager::get(); + Visage* visage = DependencyManager::get(); + DdeFaceTracker* dde = DependencyManager::get(); - return (_dde.isActive() ? static_cast(&_dde) : + return (dde->isActive() ? static_cast(dde) : (faceshift->isActive() ? static_cast(faceshift) : - (_visage.isActive() ? static_cast(&_visage) : NULL))); + (visage->isActive() ? static_cast(visage) : NULL))); } struct SendVoxelsOperationArgs { @@ -1981,7 +1985,7 @@ void Application::init() { // initialize our face trackers after loading the menu settings DependencyManager::get()->init(); - _visage.init(); + DependencyManager::get()->init(); Leapmotion::init(); @@ -2120,7 +2124,7 @@ void Application::updateVisage() { PerformanceWarning warn(showWarnings, "Application::updateVisage()"); // Update Visage - _visage.update(); + DependencyManager::get()->update(); } void Application::updateDDE() { @@ -2128,7 +2132,7 @@ void Application::updateDDE() { PerformanceWarning warn(showWarnings, "Application::updateDDE()"); // Update Cara - _dde.update(); + DependencyManager::get()->update(); } void Application::updateMyAvatarLookAtPosition() { @@ -3554,8 +3558,8 @@ void Application::deleteVoxelAt(const VoxelDetail& voxel) { void Application::resetSensors() { DependencyManager::get()->reset(); - _visage.reset(); - _dde.reset(); + DependencyManager::get()->reset(); + DependencyManager::get()->reset(); OculusManager::reset(); diff --git a/interface/src/Application.h b/interface/src/Application.h index d1d15d22a9..833f1374ce 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -56,8 +56,6 @@ #include "avatar/MyAvatar.h" #include "devices/PrioVR.h" #include "devices/SixenseManager.h" -#include "devices/Visage.h" -#include "devices/DdeFaceTracker.h" #include "entities/EntityTreeRenderer.h" #include "renderer/AmbientOcclusionEffect.h" #include "renderer/DeferredLightingEffect.h" @@ -99,6 +97,7 @@ class QMouseEvent; class QSettings; class QWheelEvent; +class FaceTracker; class Node; class ProgramObject; @@ -220,8 +219,6 @@ public: int getTrueMouseDragStartedX() const { return _mouseDragStartedX; } int getTrueMouseDragStartedY() const { return _mouseDragStartedY; } bool getLastMouseMoveWasSimulated() const { return _lastMouseMoveWasSimulated; } - Visage* getVisage() { return &_visage; } - DdeFaceTracker* getDDE() { return &_dde; } FaceTracker* getActiveFaceTracker(); PrioVR* getPrioVR() { return &_prioVR; } BandwidthMeter* getBandwidthMeter() { return &_bandwidthMeter; } @@ -530,9 +527,6 @@ private: AvatarManager _avatarManager; MyAvatar* _myAvatar; // TODO: move this and relevant code to AvatarManager (or MyAvatar as the case may be) - Visage _visage; - DdeFaceTracker _dde; - PrioVR _prioVR; Camera _myCamera; // My view onto the world diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index c08df2b2c5..6c2c3966fc 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -39,6 +39,8 @@ #include "Application.h" #include "AccountManager.h" #include "devices/Faceshift.h" +#include "devices/OculusManager.h" +#include "devices/Visage.h" #include "Menu.h" #include "scripting/LocationScriptingInterface.h" #include "scripting/MenuScriptingInterface.h" @@ -51,7 +53,6 @@ #include "ui/ModelsBrowser.h" #include "ui/LoginDialog.h" #include "ui/NodeBounds.h" -#include "devices/OculusManager.h" Menu* Menu::_instance = NULL; @@ -439,7 +440,7 @@ Menu::Menu() : #endif #ifdef HAVE_VISAGE addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::Visage, 0, false, - appInstance->getVisage(), SLOT(updateEnabled())); + DependencyManager::get(), SLOT(updateEnabled())); #endif addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::RenderSkeletonCollisionShapes); diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index a16cdd9270..42b3c968e1 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -12,6 +12,7 @@ #include #include +#include #include #include "Application.h" @@ -77,11 +78,13 @@ void Head::simulate(float deltaTime, bool isMine, bool billboard) { // Only use face trackers when not playing back a recording. if (!myAvatar->isPlaying()) { FaceTracker* faceTracker = Application::getInstance()->getActiveFaceTracker(); - if ((_isFaceshiftConnected = faceTracker)) { + DdeFaceTracker* dde = DependencyManager::get(); + Faceshift* faceshift = DependencyManager::get(); + + if ((_isFaceshiftConnected = (faceshift == faceTracker))) { _blendshapeCoefficients = faceTracker->getBlendshapeCoefficients(); - _isFaceshiftConnected = true; - } else if (Application::getInstance()->getDDE()->isActive()) { - faceTracker = Application::getInstance()->getDDE(); + } else if (dde->isActive()) { + faceTracker = dde; _blendshapeCoefficients = faceTracker->getBlendshapeCoefficients(); } } diff --git a/interface/src/devices/DdeFaceTracker.h b/interface/src/devices/DdeFaceTracker.h index 68d9e7d487..d80aa043e4 100644 --- a/interface/src/devices/DdeFaceTracker.h +++ b/interface/src/devices/DdeFaceTracker.h @@ -14,16 +14,14 @@ #include +#include + #include "FaceTracker.h" -class DdeFaceTracker : public FaceTracker { +class DdeFaceTracker : public FaceTracker, public DependencyManager::Dependency { Q_OBJECT public: - DdeFaceTracker(); - DdeFaceTracker(const QHostAddress& host, quint16 port); - ~DdeFaceTracker(); - //initialization void init(); void reset(); @@ -57,6 +55,11 @@ private slots: void socketStateChanged(QAbstractSocket::SocketState socketState); private: + DdeFaceTracker(); + DdeFaceTracker(const QHostAddress& host, quint16 port); + ~DdeFaceTracker(); + friend DependencyManager; + float getBlendshapeCoefficient(int index) const; void decodePacket(const QByteArray& buffer); diff --git a/interface/src/devices/Faceshift.h b/interface/src/devices/Faceshift.h index 83be51c7fa..3cca8f2bb1 100644 --- a/interface/src/devices/Faceshift.h +++ b/interface/src/devices/Faceshift.h @@ -28,9 +28,6 @@ class Faceshift : public FaceTracker, public DependencyManager::Dependency { Q_OBJECT public: - Faceshift(); - virtual ~Faceshift() {} - void init(); bool isConnectedOrConnecting() const; @@ -90,6 +87,9 @@ private slots: void readFromSocket(); private: + Faceshift(); + virtual ~Faceshift() {} + friend DependencyManager; float getBlendshapeCoefficient(int index) const; diff --git a/interface/src/devices/Visage.h b/interface/src/devices/Visage.h index 33e2f0a7e1..73edddc4d7 100644 --- a/interface/src/devices/Visage.h +++ b/interface/src/devices/Visage.h @@ -16,6 +16,8 @@ #include #include +#include + #include "FaceTracker.h" namespace VisageSDK { @@ -24,14 +26,10 @@ namespace VisageSDK { } /// Handles input from the Visage webcam feature tracking software. -class Visage : public FaceTracker { +class Visage : public FaceTracker, public DependencyManager::Dependency { Q_OBJECT public: - - Visage(); - virtual ~Visage(); - void init(); bool isActive() const { return _active; } @@ -44,6 +42,9 @@ public slots: void updateEnabled(); private: + Visage(); + virtual ~Visage(); + friend DependencyManager; #ifdef HAVE_VISAGE VisageSDK::VisageTracker2* _tracker; From e253b8afa4cd83ef5dd89ad38d6634ce742aa9ea Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 12 Dec 2014 14:18:23 -0800 Subject: [PATCH 376/502] move TextureCache out of interface and Application --- interface/CMakeLists.txt | 2 +- interface/src/Application.cpp | 15 ++++++++----- interface/src/Application.h | 11 ++++++---- interface/src/MetavoxelSystem.h | 2 +- interface/src/avatar/Avatar.cpp | 2 +- interface/src/renderer/GeometryCache.h | 2 +- interface/src/renderer/Model.h | 2 +- interface/src/ui/overlays/BillboardOverlay.h | 3 ++- .../render-utils/src}/TextureCache.cpp | 22 +++++++++++++++---- .../render-utils/src}/TextureCache.h | 8 ++++++- 10 files changed, 49 insertions(+), 20 deletions(-) rename {interface/src/renderer => libraries/render-utils/src}/TextureCache.cpp (98%) rename {interface/src/renderer => libraries/render-utils/src}/TextureCache.h (97%) diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 38dd02c655..ffc401ba63 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -107,7 +107,7 @@ endif() add_executable(${TARGET_NAME} MACOSX_BUNDLE ${INTERFACE_SRCS} ${QM}) # link required hifi libraries -link_hifi_libraries(shared octree voxels gpu fbx metavoxels networking entities avatars audio animation script-engine physics) +link_hifi_libraries(shared octree voxels gpu fbx metavoxels networking entities avatars audio animation script-engine physics render-utils) # find any optional and required libraries find_package(ZLIB REQUIRED) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index fbe55071e4..0c1d2c3b9f 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -177,6 +177,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : _touchAvgY(0.0f), _isTouchPressed(false), _mousePressed(false), + _textureCache(NULL), _audio(), _enableProcessVoxelsThread(true), _octreeProcessor(), @@ -194,6 +195,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : _isVSyncOn(true), _aboutToQuit(false) { + _textureCache = TextureCache::getInstance(); // read the ApplicationInfo.ini file for Name/Version/Domain information QSettings applicationInfo(Application::resourcesPath() + "info/ApplicationInfo.ini", QSettings::IniFormat); @@ -621,10 +623,10 @@ void Application::paintGL() { // Set the desired FBO texture size. If it hasn't changed, this does nothing. // Otherwise, it must rebuild the FBOs if (OculusManager::isConnected()) { - _textureCache.setFrameBufferSize(OculusManager::getRenderTargetSize()); + _textureCache->setFrameBufferSize(OculusManager::getRenderTargetSize()); } else { QSize fbSize = _glWidget->getDeviceSize() * getRenderResolutionScale(); - _textureCache.setFrameBufferSize(fbSize); + _textureCache->setFrameBufferSize(fbSize); } glEnable(GL_LINE_SMOOTH); @@ -2042,6 +2044,9 @@ void Application::init() { // save settings when avatar changes connect(_myAvatar, &MyAvatar::transformChanged, this, &Application::bumpSettings); + + // make sure our texture cache knows about window size changes + _textureCache->associateWithWidget(getGLWidget()); } void Application::closeMirrorView() { @@ -2772,7 +2777,7 @@ glm::vec3 Application::getSunDirection() { void Application::updateShadowMap() { PerformanceTimer perfTimer("shadowMap"); - QOpenGLFramebufferObject* fbo = _textureCache.getShadowFramebufferObject(); + QOpenGLFramebufferObject* fbo = _textureCache->getShadowFramebufferObject(); fbo->bind(); glEnable(GL_DEPTH_TEST); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -2937,7 +2942,7 @@ void Application::setupWorldLight() { } QImage Application::renderAvatarBillboard() { - _textureCache.getPrimaryFramebufferObject()->bind(); + _textureCache->getPrimaryFramebufferObject()->bind(); // the "glow" here causes an alpha of one Glower glower; @@ -2948,7 +2953,7 @@ QImage Application::renderAvatarBillboard() { QImage image(BILLBOARD_SIZE, BILLBOARD_SIZE, QImage::Format_ARGB32); glReadPixels(0, 0, BILLBOARD_SIZE, BILLBOARD_SIZE, GL_BGRA, GL_UNSIGNED_BYTE, image.bits()); - _textureCache.getPrimaryFramebufferObject()->release(); + _textureCache->getPrimaryFramebufferObject()->release(); return image; } diff --git a/interface/src/Application.h b/interface/src/Application.h index 833f1374ce..99184e990d 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -12,6 +12,9 @@ #ifndef hifi_Application_h #define hifi_Application_h +// include this before QGLWidget, which includes an earlier version of OpenGL +#include "InterfaceConfig.h" + #include #include @@ -34,9 +37,10 @@ #include #include #include +#include #include #include -#include +#include #include #include @@ -61,7 +65,6 @@ #include "renderer/DeferredLightingEffect.h" #include "renderer/GeometryCache.h" #include "renderer/GlowEffect.h" -#include "renderer/TextureCache.h" #include "scripting/ControllerScriptingInterface.h" #include "ui/BandwidthDialog.h" #include "ui/BandwidthMeter.h" @@ -251,7 +254,7 @@ public: GeometryCache* getGeometryCache() { return &_geometryCache; } AnimationCache* getAnimationCache() { return &_animationCache; } - TextureCache* getTextureCache() { return &_textureCache; } + TextureCache* getTextureCache() { return _textureCache; } DeferredLightingEffect* getDeferredLightingEffect() { return &_deferredLightingEffect; } GlowEffect* getGlowEffect() { return &_glowEffect; } ControllerScriptingInterface* getControllerScriptingInterface() { return &_controllerScriptingInterface; } @@ -571,7 +574,7 @@ private: GeometryCache _geometryCache; AnimationCache _animationCache; - TextureCache _textureCache; + TextureCache* _textureCache; DeferredLightingEffect _deferredLightingEffect; GlowEffect _glowEffect; diff --git a/interface/src/MetavoxelSystem.h b/interface/src/MetavoxelSystem.h index 2ebf7e1146..0c0f9b49b7 100644 --- a/interface/src/MetavoxelSystem.h +++ b/interface/src/MetavoxelSystem.h @@ -20,9 +20,9 @@ #include #include +#include #include "renderer/ProgramObject.h" -#include "renderer/TextureCache.h" class HeightfieldBaseLayerBatch; class HeightfieldSplatBatch; diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index c680c75056..e4ea33a180 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include "Application.h" #include "Avatar.h" @@ -36,7 +37,6 @@ #include "Recorder.h" #include "world.h" #include "devices/OculusManager.h" -#include "renderer/TextureCache.h" #include "ui/TextRenderer.h" using namespace std; diff --git a/interface/src/renderer/GeometryCache.h b/interface/src/renderer/GeometryCache.h index 6faad93fe4..2d06953eb5 100644 --- a/interface/src/renderer/GeometryCache.h +++ b/interface/src/renderer/GeometryCache.h @@ -13,7 +13,7 @@ #define hifi_GeometryCache_h // include this before QOpenGLBuffer, which includes an earlier version of OpenGL -#include "InterfaceConfig.h" +#include #include #include diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index e875c8f06c..74b227083f 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -21,13 +21,13 @@ #include #include #include +#include #include "AnimationHandle.h" #include "GeometryCache.h" #include "InterfaceConfig.h" #include "JointState.h" #include "ProgramObject.h" -#include "TextureCache.h" class QScriptEngine; diff --git a/interface/src/ui/overlays/BillboardOverlay.h b/interface/src/ui/overlays/BillboardOverlay.h index 03daef934d..dcb8ab8b0c 100644 --- a/interface/src/ui/overlays/BillboardOverlay.h +++ b/interface/src/ui/overlays/BillboardOverlay.h @@ -15,8 +15,9 @@ #include #include +#include + #include "Base3DOverlay.h" -#include "../../renderer/TextureCache.h" class BillboardOverlay : public Base3DOverlay { Q_OBJECT diff --git a/interface/src/renderer/TextureCache.cpp b/libraries/render-utils/src/TextureCache.cpp similarity index 98% rename from interface/src/renderer/TextureCache.cpp rename to libraries/render-utils/src/TextureCache.cpp index f40f0e3faf..11ccd4b797 100644 --- a/interface/src/renderer/TextureCache.cpp +++ b/libraries/render-utils/src/TextureCache.cpp @@ -10,20 +10,26 @@ // // include this before QGLWidget, which includes an earlier version of OpenGL -#include "InterfaceConfig.h" +#include #include #include #include +#include #include #include #include #include -#include "Application.h" #include "TextureCache.h" +TextureCache* TextureCache::getInstance() { + static TextureCache instance; + return &instance; +} + + TextureCache::TextureCache() : _permutationNormalTextureID(0), _whiteTextureID(0), @@ -35,7 +41,8 @@ TextureCache::TextureCache() : _secondaryFramebufferObject(NULL), _tertiaryFramebufferObject(NULL), _shadowFramebufferObject(NULL), - _frameBufferSize(100, 100) + _frameBufferSize(100, 100), + _associatedWidget(NULL) { } @@ -350,9 +357,16 @@ QSharedPointer TextureCache::createResource(const QUrl& url, &Resource::allReferencesCleared); } +void TextureCache::associateWithWidget(QGLWidget* widget) { + if (_associatedWidget) { + _associatedWidget->removeEventFilter(this); + } + _associatedWidget = widget; + _associatedWidget->installEventFilter(this); +} + QOpenGLFramebufferObject* TextureCache::createFramebufferObject() { QOpenGLFramebufferObject* fbo = new QOpenGLFramebufferObject(_frameBufferSize); - Application::getInstance()->getGLWidget()->installEventFilter(this); glBindTexture(GL_TEXTURE_2D, fbo->texture()); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); diff --git a/interface/src/renderer/TextureCache.h b/libraries/render-utils/src/TextureCache.h similarity index 97% rename from interface/src/renderer/TextureCache.h rename to libraries/render-utils/src/TextureCache.h index 66734da9cd..3808485135 100644 --- a/interface/src/renderer/TextureCache.h +++ b/libraries/render-utils/src/TextureCache.h @@ -14,10 +14,11 @@ #include #include +#include #include -#include "InterfaceConfig.h" +#include class QOpenGLFramebufferObject; @@ -32,10 +33,14 @@ class TextureCache : public ResourceCache { Q_OBJECT public: + + static TextureCache* getInstance(); TextureCache(); virtual ~TextureCache(); + void associateWithWidget(QGLWidget* widget); + /// Sets the desired texture resolution for the framebuffer objects. void setFrameBufferSize(QSize frameBufferSize); const QSize& getFrameBufferSize() const { return _frameBufferSize; } @@ -115,6 +120,7 @@ private: GLuint _shadowDepthTextureID; QSize _frameBufferSize; + QGLWidget* _associatedWidget; }; /// A simple object wrapper for an OpenGL texture. From 2df4c017f1083c54a2fa00e199456b4813192f27 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 12 Dec 2014 14:56:27 -0800 Subject: [PATCH 377/502] move GeometryCache out of application and remove dependency on Model --- interface/src/Application.h | 2 +- interface/src/renderer/Model.cpp | 44 ++++++++++++++- interface/src/renderer/Model.h | 25 ++++++++- .../render-utils/src}/GeometryCache.cpp | 55 +++++-------------- .../render-utils/src}/GeometryCache.h | 12 ---- 5 files changed, 81 insertions(+), 57 deletions(-) rename {interface/src/renderer => libraries/render-utils/src}/GeometryCache.cpp (95%) rename {interface/src/renderer => libraries/render-utils/src}/GeometryCache.h (92%) diff --git a/interface/src/Application.h b/interface/src/Application.h index 99184e990d..5b97c1301f 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -35,6 +35,7 @@ #include #include +#include #include #include #include @@ -63,7 +64,6 @@ #include "entities/EntityTreeRenderer.h" #include "renderer/AmbientOcclusionEffect.h" #include "renderer/DeferredLightingEffect.h" -#include "renderer/GeometryCache.h" #include "renderer/GlowEffect.h" #include "scripting/ControllerScriptingInterface.h" #include "ui/BandwidthDialog.h" diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index fd54f67377..c0295fd9b5 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -1149,7 +1149,7 @@ void Blender::run() { } } // post the result to the geometry cache, which will dispatch to the model if still alive - QMetaObject::invokeMethod(Application::getInstance()->getGeometryCache(), "setBlendedVertices", + QMetaObject::invokeMethod(ModelBlender::getInstance(), "setBlendedVertices", Q_ARG(const QPointer&, _model), Q_ARG(int, _blendNumber), Q_ARG(const QWeakPointer&, _geometry), Q_ARG(const QVector&, vertices), Q_ARG(const QVector&, normals)); @@ -1312,7 +1312,7 @@ void Model::simulateInternal(float deltaTime) { // post the blender if we're not currently waiting for one to finish if (geometry.hasBlendedMeshes() && _blendshapeCoefficients != _blendedBlendshapeCoefficients) { _blendedBlendshapeCoefficients = _blendshapeCoefficients; - Application::getInstance()->getGeometryCache()->noteRequiresBlend(this); + ModelBlender::getInstance()->noteRequiresBlend(this); } } @@ -2544,3 +2544,43 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod return meshPartsRendered; } + +ModelBlender* ModelBlender::getInstance() { + static ModelBlender instance; + return &instance; +} + +ModelBlender::ModelBlender() : + _pendingBlenders(0) { +} + +ModelBlender::~ModelBlender() { +} + +void ModelBlender::noteRequiresBlend(Model* model) { + if (_pendingBlenders < QThread::idealThreadCount()) { + if (model->maybeStartBlender()) { + _pendingBlenders++; + } + return; + } + if (!_modelsRequiringBlends.contains(model)) { + _modelsRequiringBlends.append(model); + } +} + +void ModelBlender::setBlendedVertices(const QPointer& model, int blendNumber, + const QWeakPointer& geometry, const QVector& vertices, const QVector& normals) { + if (!model.isNull()) { + model->setBlendedVertices(blendNumber, geometry, vertices, normals); + } + _pendingBlenders--; + while (!_modelsRequiringBlends.isEmpty()) { + Model* nextModel = _modelsRequiringBlends.takeFirst(); + if (nextModel && nextModel->maybeStartBlender()) { + _pendingBlenders++; + return; + } + } +} + diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 74b227083f..d74f95095d 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -453,12 +453,35 @@ private: static int renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args); - }; Q_DECLARE_METATYPE(QPointer) Q_DECLARE_METATYPE(QWeakPointer) Q_DECLARE_METATYPE(QVector) +/// Handle management of pending models that need blending +class ModelBlender : public QObject { + Q_OBJECT + +public: + + static ModelBlender* getInstance(); + + ModelBlender(); + virtual ~ModelBlender(); + + + /// Adds the specified model to the list requiring vertex blends. + void noteRequiresBlend(Model* model); + +public slots: + void setBlendedVertices(const QPointer& model, int blendNumber, const QWeakPointer& geometry, + const QVector& vertices, const QVector& normals); + +private: + QList > _modelsRequiringBlends; + int _pendingBlenders; +}; + #endif // hifi_Model_h diff --git a/interface/src/renderer/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp similarity index 95% rename from interface/src/renderer/GeometryCache.cpp rename to libraries/render-utils/src/GeometryCache.cpp index d753901243..6e0c40c28d 100644 --- a/interface/src/renderer/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -15,13 +15,13 @@ #include #include -#include "Application.h" -#include "GeometryCache.h" -#include "Model.h" -#include "world.h" +#include -GeometryCache::GeometryCache() : - _pendingBlenders(0) { +#include "TextureCache.h" + +#include "GeometryCache.h" + +GeometryCache::GeometryCache() { } GeometryCache::~GeometryCache() { @@ -505,33 +505,6 @@ QSharedPointer GeometryCache::getGeometry(const QUrl& url, cons return getResource(url, fallback, delayLoad).staticCast(); } -void GeometryCache::noteRequiresBlend(Model* model) { - if (_pendingBlenders < QThread::idealThreadCount()) { - if (model->maybeStartBlender()) { - _pendingBlenders++; - } - return; - } - if (!_modelsRequiringBlends.contains(model)) { - _modelsRequiringBlends.append(model); - } -} - -void GeometryCache::setBlendedVertices(const QPointer& model, int blendNumber, - const QWeakPointer& geometry, const QVector& vertices, const QVector& normals) { - if (!model.isNull()) { - model->setBlendedVertices(blendNumber, geometry, vertices, normals); - } - _pendingBlenders--; - while (!_modelsRequiringBlends.isEmpty()) { - Model* nextModel = _modelsRequiringBlends.takeFirst(); - if (nextModel && nextModel->maybeStartBlender()) { - _pendingBlenders++; - return; - } - } -} - QSharedPointer GeometryCache::createResource(const QUrl& url, const QSharedPointer& fallback, bool delayLoad, const void* extra) { QSharedPointer geometry(new NetworkGeometry(url, fallback.staticCast(), delayLoad), @@ -732,19 +705,19 @@ void NetworkGeometry::setTextureWithNameToURL(const QString& name, const QUrl& u QSharedPointer matchingTexture = QSharedPointer(); if (part.diffuseTextureName == name) { part.diffuseTexture = - Application::getInstance()->getTextureCache()->getTexture(url, DEFAULT_TEXTURE, + TextureCache::getInstance()->getTexture(url, DEFAULT_TEXTURE, _geometry.meshes[i].isEye, QByteArray()); part.diffuseTexture->setLoadPriorities(_loadPriorities); } else if (part.normalTextureName == name) { - part.normalTexture = Application::getInstance()->getTextureCache()->getTexture(url, DEFAULT_TEXTURE, + part.normalTexture = TextureCache::getInstance()->getTexture(url, DEFAULT_TEXTURE, false, QByteArray()); part.normalTexture->setLoadPriorities(_loadPriorities); } else if (part.specularTextureName == name) { - part.specularTexture = Application::getInstance()->getTextureCache()->getTexture(url, DEFAULT_TEXTURE, + part.specularTexture = TextureCache::getInstance()->getTexture(url, DEFAULT_TEXTURE, false, QByteArray()); part.specularTexture->setLoadPriorities(_loadPriorities); } else if (part.emissiveTextureName == name) { - part.emissiveTexture = Application::getInstance()->getTextureCache()->getTexture(url, DEFAULT_TEXTURE, + part.emissiveTexture = TextureCache::getInstance()->getTexture(url, DEFAULT_TEXTURE, false, QByteArray()); part.emissiveTexture->setLoadPriorities(_loadPriorities); } @@ -945,28 +918,28 @@ void NetworkGeometry::setGeometry(const FBXGeometry& geometry) { foreach (const FBXMeshPart& part, mesh.parts) { NetworkMeshPart networkPart; if (!part.diffuseTexture.filename.isEmpty()) { - networkPart.diffuseTexture = Application::getInstance()->getTextureCache()->getTexture( + networkPart.diffuseTexture = TextureCache::getInstance()->getTexture( _textureBase.resolved(QUrl(part.diffuseTexture.filename)), DEFAULT_TEXTURE, mesh.isEye, part.diffuseTexture.content); networkPart.diffuseTextureName = part.diffuseTexture.name; networkPart.diffuseTexture->setLoadPriorities(_loadPriorities); } if (!part.normalTexture.filename.isEmpty()) { - networkPart.normalTexture = Application::getInstance()->getTextureCache()->getTexture( + networkPart.normalTexture = TextureCache::getInstance()->getTexture( _textureBase.resolved(QUrl(part.normalTexture.filename)), NORMAL_TEXTURE, false, part.normalTexture.content); networkPart.normalTextureName = part.normalTexture.name; networkPart.normalTexture->setLoadPriorities(_loadPriorities); } if (!part.specularTexture.filename.isEmpty()) { - networkPart.specularTexture = Application::getInstance()->getTextureCache()->getTexture( + networkPart.specularTexture = TextureCache::getInstance()->getTexture( _textureBase.resolved(QUrl(part.specularTexture.filename)), SPECULAR_TEXTURE, false, part.specularTexture.content); networkPart.specularTextureName = part.specularTexture.name; networkPart.specularTexture->setLoadPriorities(_loadPriorities); } if (!part.emissiveTexture.filename.isEmpty()) { - networkPart.emissiveTexture = Application::getInstance()->getTextureCache()->getTexture( + networkPart.emissiveTexture = TextureCache::getInstance()->getTexture( _textureBase.resolved(QUrl(part.emissiveTexture.filename)), EMISSIVE_TEXTURE, false, part.emissiveTexture.content); networkPart.emissiveTextureName = part.emissiveTexture.name; diff --git a/interface/src/renderer/GeometryCache.h b/libraries/render-utils/src/GeometryCache.h similarity index 92% rename from interface/src/renderer/GeometryCache.h rename to libraries/render-utils/src/GeometryCache.h index 2d06953eb5..9fe6a7d5a2 100644 --- a/interface/src/renderer/GeometryCache.h +++ b/libraries/render-utils/src/GeometryCache.h @@ -26,7 +26,6 @@ #include "gpu/Stream.h" -class Model; class NetworkGeometry; class NetworkMesh; class NetworkTexture; @@ -52,14 +51,6 @@ public: /// \param delayLoad if true, don't load the geometry immediately; wait until load is first requested QSharedPointer getGeometry(const QUrl& url, const QUrl& fallback = QUrl(), bool delayLoad = false); - /// Adds the specified model to the list requiring vertex blends. - void noteRequiresBlend(Model* model); - -public slots: - - void setBlendedVertices(const QPointer& model, int blendNumber, const QWeakPointer& geometry, - const QVector& vertices, const QVector& normals); - protected: virtual QSharedPointer createResource(const QUrl& url, @@ -78,9 +69,6 @@ private: QHash _gridBuffers; QHash > _networkGeometry; - - QList > _modelsRequiringBlends; - int _pendingBlenders; }; /// Geometry loaded from the network. From e9ea6b20ce0bd5904af864da058a16d5ef7f7305 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 12 Dec 2014 15:29:42 -0800 Subject: [PATCH 378/502] use TextureCache::getInstance() instead of Application::getInstance()->getTextureCache() --- interface/src/Application.cpp | 2 +- interface/src/MetavoxelSystem.cpp | 18 +++++++-------- interface/src/ModelUploader.cpp | 2 +- interface/src/devices/OculusManager.cpp | 6 ++--- .../src/renderer/AmbientOcclusionEffect.cpp | 6 ++--- .../src/renderer/DeferredLightingEffect.cpp | 22 +++++++++---------- interface/src/renderer/GlowEffect.cpp | 14 ++++++------ interface/src/renderer/Model.cpp | 20 ++++++++--------- interface/src/ui/MetavoxelEditor.cpp | 2 +- interface/src/voxels/VoxelSystem.cpp | 6 ++--- 10 files changed, 49 insertions(+), 49 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 0c1d2c3b9f..eaaeb0534f 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -716,7 +716,7 @@ void Application::paintGL() { _glowEffect.prepare(); // Viewport is assigned to the size of the framebuffer - QSize size = Application::getInstance()->getTextureCache()->getPrimaryFramebufferObject()->size(); + QSize size = TextureCache::getInstance()->getPrimaryFramebufferObject()->size(); glViewport(0, 0, size.width(), size.height()); glMatrixMode(GL_MODELVIEW); diff --git a/interface/src/MetavoxelSystem.cpp b/interface/src/MetavoxelSystem.cpp index 002acec9ed..2e3e9796f3 100644 --- a/interface/src/MetavoxelSystem.cpp +++ b/interface/src/MetavoxelSystem.cpp @@ -205,7 +205,7 @@ void MetavoxelSystem::render() { glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); - Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, true); + TextureCache::getInstance()->setPrimaryDrawBuffers(true, true); glDisable(GL_BLEND); glEnable(GL_CULL_FACE); @@ -251,7 +251,7 @@ void MetavoxelSystem::render() { glPopMatrix(); } - Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, false); + TextureCache::getInstance()->setPrimaryDrawBuffers(true, false); _baseHeightfieldProgram.release(); @@ -348,7 +348,7 @@ void MetavoxelSystem::render() { } if (!_voxelBaseBatches.isEmpty()) { - Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, true); + TextureCache::getInstance()->setPrimaryDrawBuffers(true, true); glEnableClientState(GL_VERTEX_ARRAY); glDisable(GL_BLEND); @@ -383,7 +383,7 @@ void MetavoxelSystem::render() { glDisable(GL_ALPHA_TEST); glEnable(GL_BLEND); - Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, false); + TextureCache::getInstance()->setPrimaryDrawBuffers(true, false); if (!_voxelSplatBatches.isEmpty()) { glDepthFunc(GL_LEQUAL); @@ -463,7 +463,7 @@ void MetavoxelSystem::render() { } if (!_hermiteBatches.isEmpty() && Menu::getInstance()->isOptionChecked(MenuOption::DisplayHermiteData)) { - Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, true); + TextureCache::getInstance()->setPrimaryDrawBuffers(true, true); glEnableClientState(GL_VERTEX_ARRAY); @@ -486,7 +486,7 @@ void MetavoxelSystem::render() { glDisableClientState(GL_VERTEX_ARRAY); - Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, false); + TextureCache::getInstance()->setPrimaryDrawBuffers(true, false); } _hermiteBatches.clear(); @@ -797,7 +797,7 @@ void MetavoxelSystem::applyMaterialEdit(const MetavoxelEditMessage& message, boo Q_ARG(bool, reliable)); return; } - QSharedPointer texture = Application::getInstance()->getTextureCache()->getTexture( + QSharedPointer texture = TextureCache::getInstance()->getTexture( material->getDiffuse(), SPLAT_TEXTURE); if (texture->isLoaded()) { MetavoxelEditMessage newMessage = message; @@ -1180,7 +1180,7 @@ void VoxelBuffer::render(bool cursor) { for (int i = 0; i < _materials.size(); i++) { const SharedObjectPointer material = _materials.at(i); if (material) { - _networkTextures[i] = Application::getInstance()->getTextureCache()->getTexture( + _networkTextures[i] = TextureCache::getInstance()->getTexture( static_cast(material.data())->getDiffuse(), SPLAT_TEXTURE); } } @@ -2234,7 +2234,7 @@ void HeightfieldNodeRenderer::render(const HeightfieldNodePointer& node, const g for (int i = 0; i < materials.size(); i++) { const SharedObjectPointer& material = materials.at(i); if (material) { - _networkTextures[i] = Application::getInstance()->getTextureCache()->getTexture( + _networkTextures[i] = TextureCache::getInstance()->getTexture( static_cast(material.data())->getDiffuse(), SPLAT_TEXTURE); } } diff --git a/interface/src/ModelUploader.cpp b/interface/src/ModelUploader.cpp index d9e8ed0c40..6c167ca59a 100644 --- a/interface/src/ModelUploader.cpp +++ b/interface/src/ModelUploader.cpp @@ -473,7 +473,7 @@ void ModelUploader::processCheck() { QMessageBox::Ok); Application::getInstance()->getGeometryCache()->refresh(_url); foreach (const QByteArray& filename, _textureFilenames) { - Application::getInstance()->getTextureCache()->refresh(_textureBase + filename); + TextureCache::getInstance()->refresh(_textureBase + filename); } deleteLater(); break; diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index dfec98c358..0eb0c732c9 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -449,7 +449,7 @@ void OculusManager::display(const glm::quat &bodyOrientation, const glm::vec3 &p if (Menu::getInstance()->isOptionChecked(MenuOption::EnableGlowEffect)) { Application::getInstance()->getGlowEffect()->prepare(); } else { - Application::getInstance()->getTextureCache()->getPrimaryFramebufferObject()->bind(); + TextureCache::getInstance()->getPrimaryFramebufferObject()->bind(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } @@ -555,8 +555,8 @@ void OculusManager::display(const glm::quat &bodyOrientation, const glm::vec3 &p QOpenGLFramebufferObject* fbo = Application::getInstance()->getGlowEffect()->render(true); glBindTexture(GL_TEXTURE_2D, fbo->texture()); } else { - Application::getInstance()->getTextureCache()->getPrimaryFramebufferObject()->release(); - glBindTexture(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getPrimaryFramebufferObject()->texture()); + TextureCache::getInstance()->getPrimaryFramebufferObject()->release(); + glBindTexture(GL_TEXTURE_2D, TextureCache::getInstance()->getPrimaryFramebufferObject()->texture()); } // restore our normal viewport diff --git a/interface/src/renderer/AmbientOcclusionEffect.cpp b/interface/src/renderer/AmbientOcclusionEffect.cpp index f75ed7e8c3..9ef0fa2d82 100644 --- a/interface/src/renderer/AmbientOcclusionEffect.cpp +++ b/interface/src/renderer/AmbientOcclusionEffect.cpp @@ -98,7 +98,7 @@ void AmbientOcclusionEffect::render() { glDisable(GL_DEPTH_TEST); glDepthMask(GL_FALSE); - glBindTexture(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getPrimaryDepthTextureID()); + glBindTexture(GL_TEXTURE_2D, TextureCache::getInstance()->getPrimaryDepthTextureID()); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, _rotationTextureID); @@ -116,7 +116,7 @@ void AmbientOcclusionEffect::render() { glGetIntegerv(GL_VIEWPORT, viewport); const int VIEWPORT_X_INDEX = 0; const int VIEWPORT_WIDTH_INDEX = 2; - QOpenGLFramebufferObject* primaryFBO = Application::getInstance()->getTextureCache()->getPrimaryFramebufferObject(); + QOpenGLFramebufferObject* primaryFBO = TextureCache::getInstance()->getPrimaryFramebufferObject(); float sMin = viewport[VIEWPORT_X_INDEX] / (float)primaryFBO->width(); float sWidth = viewport[VIEWPORT_WIDTH_INDEX] / (float)primaryFBO->width(); @@ -141,7 +141,7 @@ void AmbientOcclusionEffect::render() { glActiveTexture(GL_TEXTURE0); // now render secondary to primary with 4x4 blur - Application::getInstance()->getTextureCache()->getPrimaryFramebufferObject()->bind(); + TextureCache::getInstance()->getPrimaryFramebufferObject()->bind(); glEnable(GL_BLEND); glBlendFuncSeparate(GL_ZERO, GL_SRC_COLOR, GL_ZERO, GL_ONE); diff --git a/interface/src/renderer/DeferredLightingEffect.cpp b/interface/src/renderer/DeferredLightingEffect.cpp index be4e457131..7c3436b2bc 100644 --- a/interface/src/renderer/DeferredLightingEffect.cpp +++ b/interface/src/renderer/DeferredLightingEffect.cpp @@ -37,7 +37,7 @@ void DeferredLightingEffect::init() { } void DeferredLightingEffect::bindSimpleProgram() { - Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, true, true); + TextureCache::getInstance()->setPrimaryDrawBuffers(true, true, true); _simpleProgram.bind(); _simpleProgram.setUniformValue(_glowIntensityLocation, Application::getInstance()->getGlowEffect()->getIntensity()); glDisable(GL_BLEND); @@ -46,7 +46,7 @@ void DeferredLightingEffect::bindSimpleProgram() { void DeferredLightingEffect::releaseSimpleProgram() { glEnable(GL_BLEND); _simpleProgram.release(); - Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, false, false); + TextureCache::getInstance()->setPrimaryDrawBuffers(true, false, false); } void DeferredLightingEffect::renderSolidSphere(float radius, int slices, int stacks) { @@ -117,15 +117,15 @@ void DeferredLightingEffect::addSpotLight(const glm::vec3& position, float radiu void DeferredLightingEffect::prepare() { // clear the normal and specular buffers - Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(false, true, false); + TextureCache::getInstance()->setPrimaryDrawBuffers(false, true, false); glClear(GL_COLOR_BUFFER_BIT); - Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(false, false, true); + TextureCache::getInstance()->setPrimaryDrawBuffers(false, false, true); // clearing to zero alpha for specular causes problems on my Nvidia card; clear to lowest non-zero value instead const float MAX_SPECULAR_EXPONENT = 128.0f; glClearColor(0.0f, 0.0f, 0.0f, 1.0f / MAX_SPECULAR_EXPONENT); glClear(GL_COLOR_BUFFER_BIT); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); - Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, false, false); + TextureCache::getInstance()->setPrimaryDrawBuffers(true, false, false); } void DeferredLightingEffect::render() { @@ -138,7 +138,7 @@ void DeferredLightingEffect::render() { glDisable(GL_COLOR_MATERIAL); glDepthMask(false); - QOpenGLFramebufferObject* primaryFBO = Application::getInstance()->getTextureCache()->getPrimaryFramebufferObject(); + QOpenGLFramebufferObject* primaryFBO = TextureCache::getInstance()->getPrimaryFramebufferObject(); primaryFBO->release(); QOpenGLFramebufferObject* freeFBO = Application::getInstance()->getGlowEffect()->getFreeFramebufferObject(); @@ -148,13 +148,13 @@ void DeferredLightingEffect::render() { glBindTexture(GL_TEXTURE_2D, primaryFBO->texture()); glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getPrimaryNormalTextureID()); + glBindTexture(GL_TEXTURE_2D, TextureCache::getInstance()->getPrimaryNormalTextureID()); glActiveTexture(GL_TEXTURE2); - glBindTexture(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getPrimarySpecularTextureID()); + glBindTexture(GL_TEXTURE_2D, TextureCache::getInstance()->getPrimarySpecularTextureID()); glActiveTexture(GL_TEXTURE3); - glBindTexture(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getPrimaryDepthTextureID()); + glBindTexture(GL_TEXTURE_2D, TextureCache::getInstance()->getPrimaryDepthTextureID()); // get the viewport side (left, right, both) int viewport[4]; @@ -173,7 +173,7 @@ void DeferredLightingEffect::render() { bool shadowsEnabled = Menu::getInstance()->getShadowsEnabled(); if (shadowsEnabled) { glActiveTexture(GL_TEXTURE4); - glBindTexture(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getShadowDepthTextureID()); + glBindTexture(GL_TEXTURE_2D, TextureCache::getInstance()->getShadowDepthTextureID()); program = &_directionalLightShadowMap; locations = &_directionalLightShadowMapLocations; @@ -188,7 +188,7 @@ void DeferredLightingEffect::render() { program->bind(); } program->setUniformValue(locations->shadowScale, - 1.0f / Application::getInstance()->getTextureCache()->getShadowFramebufferObject()->width()); + 1.0f / TextureCache::getInstance()->getShadowFramebufferObject()->width()); } else { program->bind(); diff --git a/interface/src/renderer/GlowEffect.cpp b/interface/src/renderer/GlowEffect.cpp index 9e9c1f2ed5..8a9d957234 100644 --- a/interface/src/renderer/GlowEffect.cpp +++ b/interface/src/renderer/GlowEffect.cpp @@ -41,8 +41,8 @@ GlowEffect::~GlowEffect() { QOpenGLFramebufferObject* GlowEffect::getFreeFramebufferObject() const { return (_isOddFrame ? - Application::getInstance()->getTextureCache()->getSecondaryFramebufferObject(): - Application::getInstance()->getTextureCache()->getTertiaryFramebufferObject()); + TextureCache::getInstance()->getSecondaryFramebufferObject(): + TextureCache::getInstance()->getTertiaryFramebufferObject()); } static ProgramObject* createProgram(const QString& name) { @@ -88,7 +88,7 @@ void GlowEffect::init() { } void GlowEffect::prepare() { - Application::getInstance()->getTextureCache()->getPrimaryFramebufferObject()->bind(); + TextureCache::getInstance()->getPrimaryFramebufferObject()->bind(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); _isEmpty = true; @@ -122,7 +122,7 @@ static void maybeRelease(QOpenGLFramebufferObject* fbo) { QOpenGLFramebufferObject* GlowEffect::render(bool toTexture) { PerformanceTimer perfTimer("glowEffect"); - QOpenGLFramebufferObject* primaryFBO = Application::getInstance()->getTextureCache()->getPrimaryFramebufferObject(); + QOpenGLFramebufferObject* primaryFBO = TextureCache::getInstance()->getPrimaryFramebufferObject(); primaryFBO->release(); glBindTexture(GL_TEXTURE_2D, primaryFBO->texture()); @@ -138,7 +138,7 @@ QOpenGLFramebufferObject* GlowEffect::render(bool toTexture) { glDepthMask(GL_FALSE); QOpenGLFramebufferObject* destFBO = toTexture ? - Application::getInstance()->getTextureCache()->getSecondaryFramebufferObject() : NULL; + TextureCache::getInstance()->getSecondaryFramebufferObject() : NULL; if (!Menu::getInstance()->isOptionChecked(MenuOption::EnableGlowEffect) || _isEmpty) { // copy the primary to the screen if (destFBO && QOpenGLFramebufferObject::hasOpenGLFramebufferBlit()) { @@ -160,9 +160,9 @@ QOpenGLFramebufferObject* GlowEffect::render(bool toTexture) { } else { // diffuse into the secondary/tertiary (alternating between frames) QOpenGLFramebufferObject* oldDiffusedFBO = - Application::getInstance()->getTextureCache()->getSecondaryFramebufferObject(); + TextureCache::getInstance()->getSecondaryFramebufferObject(); QOpenGLFramebufferObject* newDiffusedFBO = - Application::getInstance()->getTextureCache()->getTertiaryFramebufferObject(); + TextureCache::getInstance()->getTertiaryFramebufferObject(); if (_isOddFrame) { qSwap(oldDiffusedFBO, newDiffusedFBO); } diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index c0295fd9b5..bea94c019f 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -749,7 +749,7 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) { } - /*Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers( + /*TextureCache::getInstance()->setPrimaryDrawBuffers( mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE, mode == DEFAULT_RENDER_MODE || mode == NORMAL_RENDER_MODE, mode == DEFAULT_RENDER_MODE); @@ -789,7 +789,7 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) { opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, true, false, args); // render translucent meshes afterwards - //Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(false, true, true); + //TextureCache::getInstance()->setPrimaryDrawBuffers(false, true, true); { GLenum buffers[2]; int bufferCount = 0; @@ -814,7 +814,7 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) { GLBATCH(glDepthMask)(false); GLBATCH(glDepthFunc)(GL_LEQUAL); - //Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true); + //TextureCache::getInstance()->setPrimaryDrawBuffers(true); { GLenum buffers[1]; int bufferCount = 0; @@ -1705,7 +1705,7 @@ void Model::endScene(RenderMode mode, RenderArgs* args) { } - /*Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers( + /*TextureCache::getInstance()->setPrimaryDrawBuffers( mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE, mode == DEFAULT_RENDER_MODE || mode == NORMAL_RENDER_MODE, mode == DEFAULT_RENDER_MODE); @@ -1745,7 +1745,7 @@ void Model::endScene(RenderMode mode, RenderArgs* args) { opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, true, false, args); // render translucent meshes afterwards - //Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(false, true, true); + //TextureCache::getInstance()->setPrimaryDrawBuffers(false, true, true); { GLenum buffers[2]; int bufferCount = 0; @@ -1770,7 +1770,7 @@ void Model::endScene(RenderMode mode, RenderArgs* args) { GLBATCH(glDepthMask)(false); GLBATCH(glDepthFunc)(GL_LEQUAL); - //Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true); + //TextureCache::getInstance()->setPrimaryDrawBuffers(true); { GLenum buffers[1]; int bufferCount = 0; @@ -2446,7 +2446,7 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod if (showDiffuse && diffuseMap) { GLBATCH(glBindTexture)(GL_TEXTURE_2D, diffuseMap->getID()); } else { - GLBATCH(glBindTexture)(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getWhiteTextureID()); + GLBATCH(glBindTexture)(GL_TEXTURE_2D, TextureCache::getInstance()->getWhiteTextureID()); } if (locations->texcoordMatrices >= 0) { @@ -2464,7 +2464,7 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod GLBATCH(glActiveTexture)(GL_TEXTURE1); Texture* normalMap = networkPart.normalTexture.data(); GLBATCH(glBindTexture)(GL_TEXTURE_2D, !normalMap ? - Application::getInstance()->getTextureCache()->getBlueTextureID() : normalMap->getID()); + TextureCache::getInstance()->getBlueTextureID() : normalMap->getID()); GLBATCH(glActiveTexture)(GL_TEXTURE0); } @@ -2472,7 +2472,7 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod GLBATCH(glActiveTexture)(GL_TEXTURE0 + locations->specularTextureUnit); Texture* specularMap = networkPart.specularTexture.data(); GLBATCH(glBindTexture)(GL_TEXTURE_2D, !specularMap ? - Application::getInstance()->getTextureCache()->getWhiteTextureID() : specularMap->getID()); + TextureCache::getInstance()->getWhiteTextureID() : specularMap->getID()); GLBATCH(glActiveTexture)(GL_TEXTURE0); } @@ -2493,7 +2493,7 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod GLBATCH(glActiveTexture)(GL_TEXTURE0 + locations->emissiveTextureUnit); Texture* emissiveMap = networkPart.emissiveTexture.data(); GLBATCH(glBindTexture)(GL_TEXTURE_2D, !emissiveMap ? - Application::getInstance()->getTextureCache()->getWhiteTextureID() : emissiveMap->getID()); + TextureCache::getInstance()->getWhiteTextureID() : emissiveMap->getID()); GLBATCH(glActiveTexture)(GL_TEXTURE0); } diff --git a/interface/src/ui/MetavoxelEditor.cpp b/interface/src/ui/MetavoxelEditor.cpp index 97c4c08b41..bc20def66f 100644 --- a/interface/src/ui/MetavoxelEditor.cpp +++ b/interface/src/ui/MetavoxelEditor.cpp @@ -916,7 +916,7 @@ void MaterialControl::updateTexture() { _texture.clear(); return; } - _texture = Application::getInstance()->getTextureCache()->getTexture(material->getDiffuse(), SPLAT_TEXTURE); + _texture = TextureCache::getInstance()->getTexture(material->getDiffuse(), SPLAT_TEXTURE); if (_texture) { if (_texture->isLoaded()) { textureLoaded(); diff --git a/interface/src/voxels/VoxelSystem.cpp b/interface/src/voxels/VoxelSystem.cpp index 67f3d585ea..3a50c07a71 100644 --- a/interface/src/voxels/VoxelSystem.cpp +++ b/interface/src/voxels/VoxelSystem.cpp @@ -1171,7 +1171,7 @@ void VoxelSystem::render() { void VoxelSystem::applyScaleAndBindProgram(bool texture) { if (texture) { bindPerlinModulateProgram(); - glBindTexture(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getPermutationNormalTextureID()); + glBindTexture(GL_TEXTURE_2D, TextureCache::getInstance()->getPermutationNormalTextureID()); } else { _program.bind(); } @@ -1179,7 +1179,7 @@ void VoxelSystem::applyScaleAndBindProgram(bool texture) { glPushMatrix(); glScalef(_treeScale, _treeScale, _treeScale); - Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, true); + TextureCache::getInstance()->setPrimaryDrawBuffers(true, true); } void VoxelSystem::removeScaleAndReleaseProgram(bool texture) { @@ -1193,7 +1193,7 @@ void VoxelSystem::removeScaleAndReleaseProgram(bool texture) { _program.release(); } - Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, false); + TextureCache::getInstance()->setPrimaryDrawBuffers(true, false); } int VoxelSystem::_nodeCount = 0; From 4ac673fe63befe2f478ed6547decbf1bfb73126f Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 12 Dec 2014 15:44:54 -0800 Subject: [PATCH 379/502] more render util cleanup --- interface/src/Application.cpp | 6 +++--- interface/src/Application.h | 3 --- interface/src/Environment.cpp | 2 +- interface/src/ModelUploader.cpp | 2 +- interface/src/Util.cpp | 8 ++++---- interface/src/avatar/Avatar.cpp | 4 ++-- interface/src/avatar/Hand.cpp | 4 ++-- interface/src/avatar/MyAvatar.cpp | 4 ++-- interface/src/avatar/SkeletonModel.cpp | 14 +++++++------- interface/src/renderer/DeferredLightingEffect.cpp | 8 ++++---- interface/src/renderer/Model.cpp | 2 +- interface/src/ui/MetavoxelEditor.cpp | 2 +- interface/src/ui/overlays/Grid3DOverlay.cpp | 4 ++-- interface/src/ui/overlays/Sphere3DOverlay.cpp | 2 +- libraries/render-utils/src/GeometryCache.cpp | 5 +++++ libraries/render-utils/src/GeometryCache.h | 2 ++ 16 files changed, 38 insertions(+), 34 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index eaaeb0534f..c45267010b 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3083,7 +3083,7 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly, RenderAr // draw a red sphere float originSphereRadius = 0.05f; glColor3f(1,0,0); - _geometryCache.renderSphere(originSphereRadius, 15, 15); + GeometryCache::getInstance()->renderSphere(originSphereRadius, 15, 15); // Draw voxels if (Menu::getInstance()->isOptionChecked(MenuOption::Voxels)) { @@ -3304,12 +3304,12 @@ void Application::renderRearViewMirror(const QRect& region, bool billboard) { // set the bounds of rear mirror view if (billboard) { - QSize size = getTextureCache()->getFrameBufferSize(); + QSize size = TextureCache::getInstance()->getFrameBufferSize(); glViewport(region.x(), size.height() - region.y() - region.height(), region.width(), region.height()); glScissor(region.x(), size.height() - region.y() - region.height(), region.width(), region.height()); } else { // if not rendering the billboard, the region is in device independent coordinates; must convert to device - QSize size = getTextureCache()->getFrameBufferSize(); + QSize size = TextureCache::getInstance()->getFrameBufferSize(); float ratio = QApplication::desktop()->windowHandle()->devicePixelRatio() * getRenderResolutionScale(); int x = region.x() * ratio, y = region.y() * ratio, width = region.width() * ratio, height = region.height() * ratio; glViewport(x, size.height() - y - height, width, height); diff --git a/interface/src/Application.h b/interface/src/Application.h index 5b97c1301f..c3979086bc 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -252,9 +252,7 @@ public: ToolWindow* getToolWindow() { return _toolWindow ; } - GeometryCache* getGeometryCache() { return &_geometryCache; } AnimationCache* getAnimationCache() { return &_animationCache; } - TextureCache* getTextureCache() { return _textureCache; } DeferredLightingEffect* getDeferredLightingEffect() { return &_deferredLightingEffect; } GlowEffect* getGlowEffect() { return &_glowEffect; } ControllerScriptingInterface* getControllerScriptingInterface() { return &_controllerScriptingInterface; } @@ -572,7 +570,6 @@ private: QSet _keysPressed; - GeometryCache _geometryCache; AnimationCache _animationCache; TextureCache* _textureCache; diff --git a/interface/src/Environment.cpp b/interface/src/Environment.cpp index 0ce43ecdaa..a754b63eec 100644 --- a/interface/src/Environment.cpp +++ b/interface/src/Environment.cpp @@ -261,7 +261,7 @@ void Environment::renderAtmosphere(Camera& camera, const EnvironmentData& data) glDepthMask(GL_FALSE); glDisable(GL_DEPTH_TEST); - Application::getInstance()->getGeometryCache()->renderSphere(1.0f, 100, 50); //Draw a unit sphere + GeometryCache::getInstance()->renderSphere(1.0f, 100, 50); //Draw a unit sphere glDepthMask(GL_TRUE); program->release(); diff --git a/interface/src/ModelUploader.cpp b/interface/src/ModelUploader.cpp index 6c167ca59a..ee38a2c094 100644 --- a/interface/src/ModelUploader.cpp +++ b/interface/src/ModelUploader.cpp @@ -471,7 +471,7 @@ void ModelUploader::processCheck() { QString("ModelUploader::processCheck()"), QString("Your model is now available in the browser."), QMessageBox::Ok); - Application::getInstance()->getGeometryCache()->refresh(_url); + GeometryCache::getInstance()->refresh(_url); foreach (const QByteArray& filename, _textureFilenames) { TextureCache::getInstance()->refresh(_textureBase + filename); } diff --git a/interface/src/Util.cpp b/interface/src/Util.cpp index c4f2ec8468..256e437e21 100644 --- a/interface/src/Util.cpp +++ b/interface/src/Util.cpp @@ -71,22 +71,22 @@ void renderWorldBox() { glPushMatrix(); glTranslatef(MARKER_DISTANCE, 0, 0); glColor3fv(red); - Application::getInstance()->getGeometryCache()->renderSphere(MARKER_RADIUS, 10, 10); + GeometryCache::getInstance()->renderSphere(MARKER_RADIUS, 10, 10); glPopMatrix(); glPushMatrix(); glTranslatef(0, MARKER_DISTANCE, 0); glColor3fv(green); - Application::getInstance()->getGeometryCache()->renderSphere(MARKER_RADIUS, 10, 10); + GeometryCache::getInstance()->renderSphere(MARKER_RADIUS, 10, 10); glPopMatrix(); glPushMatrix(); glTranslatef(0, 0, MARKER_DISTANCE); glColor3fv(blue); - Application::getInstance()->getGeometryCache()->renderSphere(MARKER_RADIUS, 10, 10); + GeometryCache::getInstance()->renderSphere(MARKER_RADIUS, 10, 10); glPopMatrix(); glPushMatrix(); glColor3fv(gray); glTranslatef(MARKER_DISTANCE, 0, MARKER_DISTANCE); - Application::getInstance()->getGeometryCache()->renderSphere(MARKER_RADIUS, 10, 10); + GeometryCache::getInstance()->renderSphere(MARKER_RADIUS, 10, 10); glPopMatrix(); } diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index e4ea33a180..d4ec5ddb1f 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -394,7 +394,7 @@ void Avatar::render(const glm::vec3& cameraPosition, RenderMode renderMode, bool } else { glTranslatef(_position.x, getDisplayNamePosition().y + LOOK_AT_INDICATOR_OFFSET, _position.z); } - Application::getInstance()->getGeometryCache()->renderSphere(LOOK_AT_INDICATOR_RADIUS, 15, 15); + GeometryCache::getInstance()->renderSphere(LOOK_AT_INDICATOR_RADIUS, 15, 15); glPopMatrix(); } } @@ -422,7 +422,7 @@ void Avatar::render(const glm::vec3& cameraPosition, RenderMode renderMode, bool glPushMatrix(); glTranslatef(_position.x, _position.y, _position.z); glScalef(height, height, height); - Application::getInstance()->getGeometryCache()->renderSphere(sphereRadius, 15, 15); + GeometryCache::getInstance()->renderSphere(sphereRadius, 15, 15); glPopMatrix(); } diff --git a/interface/src/avatar/Hand.cpp b/interface/src/avatar/Hand.cpp index 148abc3546..fef4ac2fac 100644 --- a/interface/src/avatar/Hand.cpp +++ b/interface/src/avatar/Hand.cpp @@ -114,7 +114,7 @@ void Hand::render(bool isMine, Model::RenderMode renderMode) { glPushMatrix(); glTranslatef(position.x, position.y, position.z); glColor3f(0.0f, 1.0f, 0.0f); - Application::getInstance()->getGeometryCache()->renderSphere(PALM_COLLISION_RADIUS * _owningAvatar->getScale(), 10, 10); + GeometryCache::getInstance()->renderSphere(PALM_COLLISION_RADIUS * _owningAvatar->getScale(), 10, 10); glPopMatrix(); } } @@ -179,7 +179,7 @@ void Hand::renderHandTargets(bool isMine) { Avatar::renderJointConnectingCone(root, offsetFromPalm, PALM_DISK_RADIUS, 0.0f); glPushMatrix(); glTranslatef(root.x, root.y, root.z); - Application::getInstance()->getGeometryCache()->renderSphere(PALM_BALL_RADIUS, 20.0f, 20.0f); + GeometryCache::getInstance()->renderSphere(PALM_BALL_RADIUS, 20.0f, 20.0f); glPopMatrix(); } } diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 17cda19980..255e79ebcd 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -394,7 +394,7 @@ void MyAvatar::renderDebugBodyPoints() { glPushMatrix(); glColor4f(0, 1, 0, .5f); glTranslatef(position.x, position.y, position.z); - Application::getInstance()->getGeometryCache()->renderSphere(0.2f, 10.0f, 10.0f); + GeometryCache::getInstance()->renderSphere(0.2f, 10.0f, 10.0f); glPopMatrix(); // Head Sphere @@ -402,7 +402,7 @@ void MyAvatar::renderDebugBodyPoints() { glPushMatrix(); glColor4f(0, 1, 0, .5f); glTranslatef(position.x, position.y, position.z); - Application::getInstance()->getGeometryCache()->renderSphere(0.15f, 10.0f, 10.0f); + GeometryCache::getInstance()->renderSphere(0.15f, 10.0f, 10.0f); glPopMatrix(); } diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 911ebb7412..9bc2b627be 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -561,9 +561,9 @@ void SkeletonModel::renderRagdoll() { glTranslatef(position.x, position.y, position.z); // draw each point as a yellow hexagon with black border glColor4f(0.0f, 0.0f, 0.0f, alpha); - Application::getInstance()->getGeometryCache()->renderSphere(radius2, BALL_SUBDIVISIONS, BALL_SUBDIVISIONS); + GeometryCache::getInstance()->renderSphere(radius2, BALL_SUBDIVISIONS, BALL_SUBDIVISIONS); glColor4f(1.0f, 1.0f, 0.0f, alpha); - Application::getInstance()->getGeometryCache()->renderSphere(radius1, BALL_SUBDIVISIONS, BALL_SUBDIVISIONS); + GeometryCache::getInstance()->renderSphere(radius1, BALL_SUBDIVISIONS, BALL_SUBDIVISIONS); glPopMatrix(); } glPopMatrix(); @@ -913,7 +913,7 @@ void SkeletonModel::renderBoundingCollisionShapes(float alpha) { endPoint = endPoint - _translation; glTranslatef(endPoint.x, endPoint.y, endPoint.z); glColor4f(0.6f, 0.6f, 0.8f, alpha); - Application::getInstance()->getGeometryCache()->renderSphere(_boundingShape.getRadius(), BALL_SUBDIVISIONS, BALL_SUBDIVISIONS); + GeometryCache::getInstance()->renderSphere(_boundingShape.getRadius(), BALL_SUBDIVISIONS, BALL_SUBDIVISIONS); // draw a yellow sphere at the capsule startpoint glm::vec3 startPoint; @@ -922,7 +922,7 @@ void SkeletonModel::renderBoundingCollisionShapes(float alpha) { glm::vec3 axis = endPoint - startPoint; glTranslatef(-axis.x, -axis.y, -axis.z); glColor4f(0.8f, 0.8f, 0.6f, alpha); - Application::getInstance()->getGeometryCache()->renderSphere(_boundingShape.getRadius(), BALL_SUBDIVISIONS, BALL_SUBDIVISIONS); + GeometryCache::getInstance()->renderSphere(_boundingShape.getRadius(), BALL_SUBDIVISIONS, BALL_SUBDIVISIONS); // draw a green cylinder between the two points glm::vec3 origin(0.0f); @@ -955,7 +955,7 @@ void SkeletonModel::renderJointCollisionShapes(float alpha) { glTranslatef(position.x, position.y, position.z); // draw a grey sphere at shape position glColor4f(0.75f, 0.75f, 0.75f, alpha); - Application::getInstance()->getGeometryCache()->renderSphere(shape->getBoundingRadius(), BALL_SUBDIVISIONS, BALL_SUBDIVISIONS); + GeometryCache::getInstance()->renderSphere(shape->getBoundingRadius(), BALL_SUBDIVISIONS, BALL_SUBDIVISIONS); } else if (shape->getType() == CAPSULE_SHAPE) { CapsuleShape* capsule = static_cast(shape); @@ -965,7 +965,7 @@ void SkeletonModel::renderJointCollisionShapes(float alpha) { endPoint = endPoint - simulationTranslation; glTranslatef(endPoint.x, endPoint.y, endPoint.z); glColor4f(0.6f, 0.6f, 0.8f, alpha); - Application::getInstance()->getGeometryCache()->renderSphere(capsule->getRadius(), BALL_SUBDIVISIONS, BALL_SUBDIVISIONS); + GeometryCache::getInstance()->renderSphere(capsule->getRadius(), BALL_SUBDIVISIONS, BALL_SUBDIVISIONS); // draw a yellow sphere at the capsule startpoint glm::vec3 startPoint; @@ -974,7 +974,7 @@ void SkeletonModel::renderJointCollisionShapes(float alpha) { glm::vec3 axis = endPoint - startPoint; glTranslatef(-axis.x, -axis.y, -axis.z); glColor4f(0.8f, 0.8f, 0.6f, alpha); - Application::getInstance()->getGeometryCache()->renderSphere(capsule->getRadius(), BALL_SUBDIVISIONS, BALL_SUBDIVISIONS); + GeometryCache::getInstance()->renderSphere(capsule->getRadius(), BALL_SUBDIVISIONS, BALL_SUBDIVISIONS); // draw a green cylinder between the two points glm::vec3 origin(0.0f); diff --git a/interface/src/renderer/DeferredLightingEffect.cpp b/interface/src/renderer/DeferredLightingEffect.cpp index 7c3436b2bc..42da3e0b08 100644 --- a/interface/src/renderer/DeferredLightingEffect.cpp +++ b/interface/src/renderer/DeferredLightingEffect.cpp @@ -51,7 +51,7 @@ void DeferredLightingEffect::releaseSimpleProgram() { void DeferredLightingEffect::renderSolidSphere(float radius, int slices, int stacks) { bindSimpleProgram(); - Application::getInstance()->getGeometryCache()->renderSphere(radius, slices, stacks); + GeometryCache::getInstance()->renderSphere(radius, slices, stacks); releaseSimpleProgram(); } @@ -75,7 +75,7 @@ void DeferredLightingEffect::renderWireCube(float size) { void DeferredLightingEffect::renderSolidCone(float base, float height, int slices, int stacks) { bindSimpleProgram(); - Application::getInstance()->getGeometryCache()->renderCone(base, height, slices, stacks); + GeometryCache::getInstance()->renderCone(base, height, slices, stacks); releaseSimpleProgram(); } @@ -270,7 +270,7 @@ void DeferredLightingEffect::render() { } else { glTranslatef(light.position.x, light.position.y, light.position.z); - Application::getInstance()->getGeometryCache()->renderSphere(expandedRadius, 32, 32); + GeometryCache::getInstance()->renderSphere(expandedRadius, 32, 32); } glPopMatrix(); @@ -323,7 +323,7 @@ void DeferredLightingEffect::render() { glm::vec3 axis = glm::axis(spotRotation); glRotatef(glm::degrees(glm::angle(spotRotation)), axis.x, axis.y, axis.z); glTranslatef(0.0f, 0.0f, -light.radius * (1.0f + SCALE_EXPANSION * 0.5f)); - Application::getInstance()->getGeometryCache()->renderCone(expandedRadius * glm::tan(light.cutoff), + GeometryCache::getInstance()->renderCone(expandedRadius * glm::tan(light.cutoff), expandedRadius, 32, 1); } diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index bea94c019f..45c80852ad 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -997,7 +997,7 @@ void Model::setURL(const QUrl& url, const QUrl& fallback, bool retainCurrent, bo _url = url; // if so instructed, keep the current geometry until the new one is loaded - _nextBaseGeometry = _nextGeometry = Application::getInstance()->getGeometryCache()->getGeometry(url, fallback, delayLoad); + _nextBaseGeometry = _nextGeometry = GeometryCache::getInstance()->getGeometry(url, fallback, delayLoad); _nextLODHysteresis = NetworkGeometry::NO_HYSTERESIS; if (!retainCurrent || !isActive() || _nextGeometry->isLoaded()) { applyNextGeometry(); diff --git a/interface/src/ui/MetavoxelEditor.cpp b/interface/src/ui/MetavoxelEditor.cpp index bc20def66f..dde181c571 100644 --- a/interface/src/ui/MetavoxelEditor.cpp +++ b/interface/src/ui/MetavoxelEditor.cpp @@ -353,7 +353,7 @@ void MetavoxelEditor::render() { _gridProgram.bind(); - Application::getInstance()->getGeometryCache()->renderGrid(GRID_DIVISIONS, GRID_DIVISIONS); + GeometryCache::getInstance()->renderGrid(GRID_DIVISIONS, GRID_DIVISIONS); _gridProgram.release(); diff --git a/interface/src/ui/overlays/Grid3DOverlay.cpp b/interface/src/ui/overlays/Grid3DOverlay.cpp index 4bf0d9ce93..67dd0b8e21 100644 --- a/interface/src/ui/overlays/Grid3DOverlay.cpp +++ b/interface/src/ui/overlays/Grid3DOverlay.cpp @@ -87,7 +87,7 @@ void Grid3DOverlay::render(RenderArgs* args) { float scale = MINOR_GRID_DIVISIONS * spacing; glScalef(scale, scale, scale); - Application::getInstance()->getGeometryCache()->renderGrid(MINOR_GRID_DIVISIONS, MINOR_GRID_DIVISIONS); + GeometryCache::getInstance()->renderGrid(MINOR_GRID_DIVISIONS, MINOR_GRID_DIVISIONS); } glPopMatrix(); @@ -102,7 +102,7 @@ void Grid3DOverlay::render(RenderArgs* args) { float scale = MAJOR_GRID_DIVISIONS * spacing; glScalef(scale, scale, scale); - Application::getInstance()->getGeometryCache()->renderGrid(MAJOR_GRID_DIVISIONS, MAJOR_GRID_DIVISIONS); + GeometryCache::getInstance()->renderGrid(MAJOR_GRID_DIVISIONS, MAJOR_GRID_DIVISIONS); } glPopMatrix(); diff --git a/interface/src/ui/overlays/Sphere3DOverlay.cpp b/interface/src/ui/overlays/Sphere3DOverlay.cpp index 34064675e5..b9aeb5145a 100644 --- a/interface/src/ui/overlays/Sphere3DOverlay.cpp +++ b/interface/src/ui/overlays/Sphere3DOverlay.cpp @@ -63,7 +63,7 @@ void Sphere3DOverlay::render(RenderArgs* args) { glScalef(dimensions.x, dimensions.y, dimensions.z); //Application::getInstance()->getDeferredLightingEffect()->renderSolidCube(1.0f); if (_isSolid) { - Application::getInstance()->getGeometryCache()->renderSphere(1.0f, SLICES, SLICES); + GeometryCache::getInstance()->renderSphere(1.0f, SLICES, SLICES); } else { glutWireSphere(1.0f, SLICES, SLICES); } diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index 6e0c40c28d..416148ab20 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -21,6 +21,11 @@ #include "GeometryCache.h" +GeometryCache* GeometryCache::getInstance() { + static GeometryCache instance; + return &instance; +} + GeometryCache::GeometryCache() { } diff --git a/libraries/render-utils/src/GeometryCache.h b/libraries/render-utils/src/GeometryCache.h index 9fe6a7d5a2..f50dc8ccd9 100644 --- a/libraries/render-utils/src/GeometryCache.h +++ b/libraries/render-utils/src/GeometryCache.h @@ -35,6 +35,8 @@ class GeometryCache : public ResourceCache { Q_OBJECT public: + + static GeometryCache* getInstance(); GeometryCache(); virtual ~GeometryCache(); From 3de3540ebea88247d5b9d5a32a89ff42e68425ac Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 15 Dec 2014 08:37:33 -0800 Subject: [PATCH 380/502] move back into interface for now --- interface/CMakeLists.txt | 2 +- interface/src/Application.h | 4 ++-- interface/src/MetavoxelSystem.h | 2 +- interface/src/avatar/Avatar.cpp | 2 +- .../src => interface/src/renderer}/GeometryCache.cpp | 0 .../src => interface/src/renderer}/GeometryCache.h | 0 interface/src/renderer/Model.h | 2 +- .../src => interface/src/renderer}/TextureCache.cpp | 0 .../src => interface/src/renderer}/TextureCache.h | 0 interface/src/ui/overlays/BillboardOverlay.h | 3 +-- 10 files changed, 7 insertions(+), 8 deletions(-) rename {libraries/render-utils/src => interface/src/renderer}/GeometryCache.cpp (100%) rename {libraries/render-utils/src => interface/src/renderer}/GeometryCache.h (100%) rename {libraries/render-utils/src => interface/src/renderer}/TextureCache.cpp (100%) rename {libraries/render-utils/src => interface/src/renderer}/TextureCache.h (100%) diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index ffc401ba63..38dd02c655 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -107,7 +107,7 @@ endif() add_executable(${TARGET_NAME} MACOSX_BUNDLE ${INTERFACE_SRCS} ${QM}) # link required hifi libraries -link_hifi_libraries(shared octree voxels gpu fbx metavoxels networking entities avatars audio animation script-engine physics render-utils) +link_hifi_libraries(shared octree voxels gpu fbx metavoxels networking entities avatars audio animation script-engine physics) # find any optional and required libraries find_package(ZLIB REQUIRED) diff --git a/interface/src/Application.h b/interface/src/Application.h index c3979086bc..afb476ce97 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -35,13 +35,11 @@ #include #include -#include #include #include #include #include #include -#include #include #include @@ -64,7 +62,9 @@ #include "entities/EntityTreeRenderer.h" #include "renderer/AmbientOcclusionEffect.h" #include "renderer/DeferredLightingEffect.h" +#include "renderer/GeometryCache.h" #include "renderer/GlowEffect.h" +#include "renderer/TextureCache.h" #include "scripting/ControllerScriptingInterface.h" #include "ui/BandwidthDialog.h" #include "ui/BandwidthMeter.h" diff --git a/interface/src/MetavoxelSystem.h b/interface/src/MetavoxelSystem.h index 0c0f9b49b7..2ebf7e1146 100644 --- a/interface/src/MetavoxelSystem.h +++ b/interface/src/MetavoxelSystem.h @@ -20,9 +20,9 @@ #include #include -#include #include "renderer/ProgramObject.h" +#include "renderer/TextureCache.h" class HeightfieldBaseLayerBatch; class HeightfieldSplatBatch; diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index d4ec5ddb1f..0edf59290f 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -25,7 +25,6 @@ #include #include #include -#include #include "Application.h" #include "Avatar.h" @@ -37,6 +36,7 @@ #include "Recorder.h" #include "world.h" #include "devices/OculusManager.h" +#include "renderer/TextureCache.h" #include "ui/TextRenderer.h" using namespace std; diff --git a/libraries/render-utils/src/GeometryCache.cpp b/interface/src/renderer/GeometryCache.cpp similarity index 100% rename from libraries/render-utils/src/GeometryCache.cpp rename to interface/src/renderer/GeometryCache.cpp diff --git a/libraries/render-utils/src/GeometryCache.h b/interface/src/renderer/GeometryCache.h similarity index 100% rename from libraries/render-utils/src/GeometryCache.h rename to interface/src/renderer/GeometryCache.h diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index d74f95095d..e95b2472ba 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -21,13 +21,13 @@ #include #include #include -#include #include "AnimationHandle.h" #include "GeometryCache.h" #include "InterfaceConfig.h" #include "JointState.h" #include "ProgramObject.h" +#include "TextureCache.h" class QScriptEngine; diff --git a/libraries/render-utils/src/TextureCache.cpp b/interface/src/renderer/TextureCache.cpp similarity index 100% rename from libraries/render-utils/src/TextureCache.cpp rename to interface/src/renderer/TextureCache.cpp diff --git a/libraries/render-utils/src/TextureCache.h b/interface/src/renderer/TextureCache.h similarity index 100% rename from libraries/render-utils/src/TextureCache.h rename to interface/src/renderer/TextureCache.h diff --git a/interface/src/ui/overlays/BillboardOverlay.h b/interface/src/ui/overlays/BillboardOverlay.h index dcb8ab8b0c..c095a544b7 100644 --- a/interface/src/ui/overlays/BillboardOverlay.h +++ b/interface/src/ui/overlays/BillboardOverlay.h @@ -15,9 +15,8 @@ #include #include -#include - #include "Base3DOverlay.h" +#include "renderer/TextureCache.h" class BillboardOverlay : public Base3DOverlay { Q_OBJECT From ca39c79df45cd350656999a181e0ab22fb394721 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 15 Dec 2014 08:50:36 -0800 Subject: [PATCH 381/502] unix compile --- interface/src/renderer/GeometryCache.cpp | 6 ++++-- interface/src/renderer/TextureCache.cpp | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/interface/src/renderer/GeometryCache.cpp b/interface/src/renderer/GeometryCache.cpp index 416148ab20..5cb544135c 100644 --- a/interface/src/renderer/GeometryCache.cpp +++ b/interface/src/renderer/GeometryCache.cpp @@ -9,6 +9,9 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +// include this before QOpenGLBuffer, which includes an earlier version of OpenGL +#include + #include #include @@ -17,9 +20,8 @@ #include -#include "TextureCache.h" - #include "GeometryCache.h" +#include "TextureCache.h" GeometryCache* GeometryCache::getInstance() { static GeometryCache instance; diff --git a/interface/src/renderer/TextureCache.cpp b/interface/src/renderer/TextureCache.cpp index 11ccd4b797..e4c55db58b 100644 --- a/interface/src/renderer/TextureCache.cpp +++ b/interface/src/renderer/TextureCache.cpp @@ -10,6 +10,7 @@ // // include this before QGLWidget, which includes an earlier version of OpenGL +#include #include #include From 7d1081473eb0fdd69336b29c2856ca5a6bf6fe3c Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 15 Dec 2014 09:42:35 -0800 Subject: [PATCH 382/502] remove _textureCache --- interface/src/Application.cpp | 15 ++++++--------- interface/src/Application.h | 1 - 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c45267010b..1ec177163d 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -177,7 +177,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : _touchAvgY(0.0f), _isTouchPressed(false), _mousePressed(false), - _textureCache(NULL), _audio(), _enableProcessVoxelsThread(true), _octreeProcessor(), @@ -195,8 +194,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : _isVSyncOn(true), _aboutToQuit(false) { - _textureCache = TextureCache::getInstance(); - // read the ApplicationInfo.ini file for Name/Version/Domain information QSettings applicationInfo(Application::resourcesPath() + "info/ApplicationInfo.ini", QSettings::IniFormat); @@ -623,10 +620,10 @@ void Application::paintGL() { // Set the desired FBO texture size. If it hasn't changed, this does nothing. // Otherwise, it must rebuild the FBOs if (OculusManager::isConnected()) { - _textureCache->setFrameBufferSize(OculusManager::getRenderTargetSize()); + TextureCache::getInstance()->setFrameBufferSize(OculusManager::getRenderTargetSize()); } else { QSize fbSize = _glWidget->getDeviceSize() * getRenderResolutionScale(); - _textureCache->setFrameBufferSize(fbSize); + TextureCache::getInstance()->setFrameBufferSize(fbSize); } glEnable(GL_LINE_SMOOTH); @@ -2046,7 +2043,7 @@ void Application::init() { connect(_myAvatar, &MyAvatar::transformChanged, this, &Application::bumpSettings); // make sure our texture cache knows about window size changes - _textureCache->associateWithWidget(getGLWidget()); + TextureCache::getInstance()->associateWithWidget(getGLWidget()); } void Application::closeMirrorView() { @@ -2777,7 +2774,7 @@ glm::vec3 Application::getSunDirection() { void Application::updateShadowMap() { PerformanceTimer perfTimer("shadowMap"); - QOpenGLFramebufferObject* fbo = _textureCache->getShadowFramebufferObject(); + QOpenGLFramebufferObject* fbo = TextureCache::getInstance()->getShadowFramebufferObject(); fbo->bind(); glEnable(GL_DEPTH_TEST); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -2942,7 +2939,7 @@ void Application::setupWorldLight() { } QImage Application::renderAvatarBillboard() { - _textureCache->getPrimaryFramebufferObject()->bind(); + TextureCache::getInstance()->getPrimaryFramebufferObject()->bind(); // the "glow" here causes an alpha of one Glower glower; @@ -2953,7 +2950,7 @@ QImage Application::renderAvatarBillboard() { QImage image(BILLBOARD_SIZE, BILLBOARD_SIZE, QImage::Format_ARGB32); glReadPixels(0, 0, BILLBOARD_SIZE, BILLBOARD_SIZE, GL_BGRA, GL_UNSIGNED_BYTE, image.bits()); - _textureCache->getPrimaryFramebufferObject()->release(); + TextureCache::getInstance()->getPrimaryFramebufferObject()->release(); return image; } diff --git a/interface/src/Application.h b/interface/src/Application.h index afb476ce97..fe5c466e0e 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -571,7 +571,6 @@ private: AnimationCache _animationCache; - TextureCache* _textureCache; DeferredLightingEffect _deferredLightingEffect; GlowEffect _glowEffect; From a688f48bf7678f6e2563ccafa677465c8e3dd1f4 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 15 Dec 2014 10:02:01 -0800 Subject: [PATCH 383/502] indicate that user should run tbbvars for FindTBB --- BUILD.md | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/BUILD.md b/BUILD.md index e1d920b8df..f676c29a9d 100644 --- a/BUILD.md +++ b/BUILD.md @@ -5,6 +5,7 @@ Dependencies * [glm](http://glm.g-truc.net/0.9.5/index.html) ~> 0.9.5.2 * [OpenSSL](https://www.openssl.org/related/binaries.html) ~> 1.0.1g * IMPORTANT: OpenSSL 1.0.1g is critical to avoid a security vulnerability. +* [Intel Threading Building Blocks](https://www.threadingbuildingblocks.org/) ~> 4.3 #####Linux only * [freeglut](http://freeglut.sourceforge.net/) ~> 2.8.0 @@ -55,7 +56,7 @@ In the examples below the variable $NAME would be replaced by the name of the de UNIX === -In general, as long as external dependencies are placed in OS standard locations, CMake will successfully find them during its run. When possible, you may choose to install depencies from your package manager of choice, or from source. +In general, as long as external dependencies are placed in OS standard locations, CMake will successfully find them during its run. When possible, you may choose to install depencies from your package manager of choice, or from source. ####Linux Should you choose not to install Qt5 via a package manager that handles dependencies for you, you may be missing some Qt5 dependencies. On Ubuntu, for example, the following additional packages are required: @@ -67,7 +68,7 @@ Should you choose not to install Qt5 via a package manager that handles dependen [Homebrew](http://brew.sh/) is an excellent package manager for OS X. It makes install of all hifi dependencies very simple. brew tap highfidelity/homebrew-formulas - brew install cmake glm openssl + brew install cmake glm openssl tbb brew install highfidelity/formulas/qt5 brew link qt5 --force @@ -173,6 +174,9 @@ The recommended route for CMake to find the external dependencies is to place al -> bin -> include -> lib + -> tbb + -> include + -> lib -> zlib -> include -> lib @@ -202,6 +206,12 @@ 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. +#### Intel Threading Building Blocks (TBB) + +Download the stable release for Windows from the [Intel Threading Building Blocks website](https://www.threadingbuildingblocks.org/). By default, TBB will install to Program Files. You may also choose to install it to %HIFI_LIB_DIR%\TBB. + +You must run `tbbvars.bat` so that the find module included with this project will be able to find TBB no matter where you installed it. `tbbvars.bat` is located in the 'bin' folder of your TBB install. For a default installation on a 64-bit architechture, tbbvars can be found at `C:/Program Files (x86)/Intel/TBB/bin/tbbvars.bat`. + #### Zlib Download the compiled DLL from the [zlib website](http://www.zlib.net/). Extract to %HIFI_LIB_DIR%\zlib. From ce6334535b3b0ce6206f80b05483aa8449398316 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 15 Dec 2014 10:08:48 -0800 Subject: [PATCH 384/502] add info for TBB to Linux section --- BUILD.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/BUILD.md b/BUILD.md index f676c29a9d..522e994ea4 100644 --- a/BUILD.md +++ b/BUILD.md @@ -63,6 +63,12 @@ Should you choose not to install Qt5 via a package manager that handles dependen libasound2 libxmu-dev libxi-dev freeglut3-dev libasound2-dev libjack-dev +##### Intel Threading Building Blocks (TBB) + +Install Intel TBB from your package manager of choice, or from source (available at the [TBB Website](https://www.threadingbuildingblocks.org/)). + +You must run `tbbvars` so that the find module included with this project will be able to find the correct version of TBB. `tbbvars` is located in the 'bin' folder of your TBB install. + ####OS X #####Package Managers [Homebrew](http://brew.sh/) is an excellent package manager for OS X. It makes install of all hifi dependencies very simple. From d65f435e2832bc044379266cdce5425e634732c4 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 15 Dec 2014 10:10:31 -0800 Subject: [PATCH 385/502] change Qt version referenced in build guide --- BUILD.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/BUILD.md b/BUILD.md index 522e994ea4..b884b5588e 100644 --- a/BUILD.md +++ b/BUILD.md @@ -1,7 +1,7 @@ Dependencies === * [cmake](http://www.cmake.org/cmake/resources/software.html) ~> 2.8.12.2 -* [Qt](http://qt-project.org/downloads) ~> 5.2.0 +* [Qt](http://qt-project.org/downloads) ~> 5.3.0 * [glm](http://glm.g-truc.net/0.9.5/index.html) ~> 0.9.5.2 * [OpenSSL](https://www.openssl.org/related/binaries.html) ~> 1.0.1g * IMPORTANT: OpenSSL 1.0.1g is critical to avoid a security vulnerability. @@ -80,7 +80,7 @@ You must run `tbbvars` so that the find module included with this project will b We have a [homebrew formulas repository](https://github.com/highfidelity/homebrew-formulas) that you can use/tap to install some of the dependencies. In the code block above qt5 is installed from a formula in this repository. -*Our [qt5 homebrew formula](https://raw.github.com/highfidelity/homebrew-formulas/master/qt5.rb) is for a patched version of Qt 5.2.0 stable that removes wireless network scanning that can reduce real-time audio performance. We recommended you use this formula to install Qt.* +*Our [qt5 homebrew formula](https://raw.github.com/highfidelity/homebrew-formulas/master/qt5.rb) is for a patched version of Qt 5.3.x stable that removes wireless network scanning that can reduce real-time audio performance. We recommended you use this formula to install Qt.* #####Xcode If Xcode is your editor of choice, you can ask CMake to generate Xcode project files instead of Unix Makefiles. From 6b39783de7ae579191d927e6ecf27542fb955a10 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 15 Dec 2014 10:12:04 -0800 Subject: [PATCH 386/502] revert out the InterfaceConfig.h changes --- interface/src/Application.h | 3 --- interface/src/renderer/GeometryCache.h | 2 +- interface/src/renderer/TextureCache.cpp | 2 +- interface/src/renderer/TextureCache.h | 2 +- interface/src/voxels/VoxelSystem.cpp | 2 +- 5 files changed, 4 insertions(+), 7 deletions(-) diff --git a/interface/src/Application.h b/interface/src/Application.h index fe5c466e0e..d4a681f060 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -12,9 +12,6 @@ #ifndef hifi_Application_h #define hifi_Application_h -// include this before QGLWidget, which includes an earlier version of OpenGL -#include "InterfaceConfig.h" - #include #include diff --git a/interface/src/renderer/GeometryCache.h b/interface/src/renderer/GeometryCache.h index f50dc8ccd9..1eb9dcbc6a 100644 --- a/interface/src/renderer/GeometryCache.h +++ b/interface/src/renderer/GeometryCache.h @@ -13,7 +13,7 @@ #define hifi_GeometryCache_h // include this before QOpenGLBuffer, which includes an earlier version of OpenGL -#include +#include "InterfaceConfig.h" #include #include diff --git a/interface/src/renderer/TextureCache.cpp b/interface/src/renderer/TextureCache.cpp index e4c55db58b..4d246a4c9c 100644 --- a/interface/src/renderer/TextureCache.cpp +++ b/interface/src/renderer/TextureCache.cpp @@ -10,7 +10,7 @@ // // include this before QGLWidget, which includes an earlier version of OpenGL -#include +#include "InterfaceConfig.h" #include #include diff --git a/interface/src/renderer/TextureCache.h b/interface/src/renderer/TextureCache.h index 3808485135..3cbfaced49 100644 --- a/interface/src/renderer/TextureCache.h +++ b/interface/src/renderer/TextureCache.h @@ -18,7 +18,7 @@ #include -#include +#include "InterfaceConfig.h" class QOpenGLFramebufferObject; diff --git a/interface/src/voxels/VoxelSystem.cpp b/interface/src/voxels/VoxelSystem.cpp index 3a50c07a71..82384ce9a4 100644 --- a/interface/src/voxels/VoxelSystem.cpp +++ b/interface/src/voxels/VoxelSystem.cpp @@ -9,6 +9,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include // include this first #include #include @@ -24,7 +25,6 @@ #include #include "Application.h" -#include "InterfaceConfig.h" #include "Menu.h" #include "renderer/ProgramObject.h" #include "VoxelConstants.h" From c6b033fa0e5b4edc87afa4c367b9d1633299fea4 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 15 Dec 2014 10:12:55 -0800 Subject: [PATCH 387/502] revert out the InterfaceConfig.h changes --- interface/src/voxels/VoxelSystem.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/interface/src/voxels/VoxelSystem.cpp b/interface/src/voxels/VoxelSystem.cpp index 82384ce9a4..6fd477d8f3 100644 --- a/interface/src/voxels/VoxelSystem.cpp +++ b/interface/src/voxels/VoxelSystem.cpp @@ -9,8 +9,6 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include // include this first - #include #include #include // to load voxels from file @@ -25,6 +23,7 @@ #include #include "Application.h" +#include "InterfaceConfig.h" #include "Menu.h" #include "renderer/ProgramObject.h" #include "VoxelConstants.h" From 5ad4a57e3dedd7ab8a72c15827fd23944ed994be Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 15 Dec 2014 10:19:06 -0800 Subject: [PATCH 388/502] add OS specific build files --- BUILD.md | 240 ++----------------------------------------------- BUILD_LINUX.md | 18 ++++ BUILD_OSX.md | 22 +++++ BUILD_WIN.md | 180 +++++++++++++++++++++++++++++++++++++ 4 files changed, 228 insertions(+), 232 deletions(-) create mode 100644 BUILD_LINUX.md create mode 100644 BUILD_OSX.md create mode 100644 BUILD_WIN.md diff --git a/BUILD.md b/BUILD.md index b884b5588e..867e515209 100644 --- a/BUILD.md +++ b/BUILD.md @@ -1,5 +1,5 @@ -Dependencies -=== +###Dependencies + * [cmake](http://www.cmake.org/cmake/resources/software.html) ~> 2.8.12.2 * [Qt](http://qt-project.org/downloads) ~> 5.3.0 * [glm](http://glm.g-truc.net/0.9.5/index.html) ~> 0.9.5.2 @@ -7,28 +7,18 @@ Dependencies * IMPORTANT: OpenSSL 1.0.1g is critical to avoid a security vulnerability. * [Intel Threading Building Blocks](https://www.threadingbuildingblocks.org/) ~> 4.3 -#####Linux only -* [freeglut](http://freeglut.sourceforge.net/) ~> 2.8.0 -* [zLib](http://www.zlib.net/) ~> 1.2.8 - -#####Windows only -* [GLEW](http://glew.sourceforge.net/) ~> 1.10.0 -* [freeglut MSVC](http://www.transmissionzero.co.uk/software/freeglut-devel/) ~> 2.8.1 -* [zLib](http://www.zlib.net/) ~> 1.2.8 - -CMake -=== +###CMake Hifi uses CMake to generate build files and project files for your platform. ####Qt In order for CMake to find the Qt5 find modules, you will need to set an ENV variable pointing to your Qt installation. -For example, a Qt5 5.2.0 installation to /usr/local/qt5 would require that QT_CMAKE_PREFIX_PATH be set with the following command. This can either be entered directly into your shell session before you build or in your shell profile (e.g.: ~/.bash_profile, ~/.bashrc, ~/.zshrc - this depends on your shell and environment). +For example, a Qt5 5.3.2 installation to /usr/local/qt5 would require that QT_CMAKE_PREFIX_PATH be set with the following command. This can either be entered directly into your shell session before you build or in your shell profile (e.g.: ~/.bash_profile, ~/.bashrc, ~/.zshrc - this depends on your shell and environment). The path it needs to be set to will depend on where and how Qt5 was installed. e.g. - export QT_CMAKE_PREFIX_PATH=/usr/local/qt/5.2.0/clang_64/lib/cmake/ - export QT_CMAKE_PREFIX_PATH=/usr/local/Cellar/qt5/5.2.1/lib/cmake + export QT_CMAKE_PREFIX_PATH=/usr/local/qt/5.3.2/clang_64/lib/cmake/ + export QT_CMAKE_PREFIX_PATH=/usr/local/Cellar/qt5/5.3.2/lib/cmake export QT_CMAKE_PREFIX_PATH=/usr/local/opt/qt5/lib/cmake ####Generating build files @@ -54,221 +44,7 @@ In the examples below the variable $NAME would be replaced by the name of the de * $NAME_ROOT_DIR - set this variable in your ENV * HIFI_LIB_DIR - set this variable in your ENV to your High Fidelity lib folder, should contain a folder '$name' -UNIX -=== -In general, as long as external dependencies are placed in OS standard locations, CMake will successfully find them during its run. When possible, you may choose to install depencies from your package manager of choice, or from source. - -####Linux -Should you choose not to install Qt5 via a package manager that handles dependencies for you, you may be missing some Qt5 dependencies. On Ubuntu, for example, the following additional packages are required: - - libasound2 libxmu-dev libxi-dev freeglut3-dev libasound2-dev libjack-dev - -##### Intel Threading Building Blocks (TBB) - -Install Intel TBB from your package manager of choice, or from source (available at the [TBB Website](https://www.threadingbuildingblocks.org/)). - -You must run `tbbvars` so that the find module included with this project will be able to find the correct version of TBB. `tbbvars` is located in the 'bin' folder of your TBB install. - -####OS X -#####Package Managers -[Homebrew](http://brew.sh/) is an excellent package manager for OS X. It makes install of all hifi dependencies very simple. - - brew tap highfidelity/homebrew-formulas - brew install cmake glm openssl tbb - brew install highfidelity/formulas/qt5 - brew link qt5 --force - -We have a [homebrew formulas repository](https://github.com/highfidelity/homebrew-formulas) that you can use/tap to install some of the dependencies. In the code block above qt5 is installed from a formula in this repository. - -*Our [qt5 homebrew formula](https://raw.github.com/highfidelity/homebrew-formulas/master/qt5.rb) is for a patched version of Qt 5.3.x stable that removes wireless network scanning that can reduce real-time audio performance. We recommended you use this formula to install Qt.* - -#####Xcode -If Xcode is your editor of choice, you can ask CMake to generate Xcode project files instead of Unix Makefiles. - - cmake .. -GXcode - -After running cmake, you will have the make files or Xcode project file necessary to build all of the components. Open the hifi.xcodeproj file, choose ALL_BUILD from the Product > Scheme menu (or target drop down), and click Run. - -If the build completes successfully, you will have built targets for all components located in the `build/${target_name}/Debug` directories. - -Windows -=== -####Visual Studio - -Currently building on Windows has been tested using the following compilers: -* Visual Studio C++ 2010 Express -* Visual Studio 2013 - -(If anyone can test using Visual Studio 2013 Express then please update this document) - -#####Windows SDK 7.1 - -If using Visual Studio 2010, or using Visual Studio 2013 but building as a Visual Studio 2010 project, you need [Microsoft Windows SDK for Windows 7 and .NET Framework 4](http://www.microsoft.com/en-us/download/details.aspx?id=8279). - -NOTE: If using Visual Studio C++ 2010 Express, you need to follow a specific install order. See below before installing the Windows SDK. - -######Windows SDK 8.1 - -If using Visual Studio 2013 and building as a Visual Studio 2013 project you need the Windows 8 SDK which you should already have as part of installing Visual Studio 2013. You should be able to see it at `C:\Program Files (x86)\Windows Kits\8.1\Lib\winv6.3\um\x86`. - -#####Visual Studio C++ 2010 Express - -Visual Studio C++ 2010 Express can be downloaded [here](http://www.visualstudio.com/en-us/downloads#d-2010-express). - -The following patches/service packs are also required: -* [VS2010 SP1](http://www.microsoft.com/en-us/download/details.aspx?id=23691) -* [VS2010 SP1 Compiler Update](http://www.microsoft.com/en-us/download/details.aspx?id=4422) - -IMPORTANT: Use the following install order: -Visual Studio C++ 2010 Express -Windows SDK 7.1 -VS2010 SP1 -VS2010 SP1 Compiler Update - -If you get an error while installing the VS2010 SP1 Compiler update saying that you don't have the Windows SDK installed, then uninstall all of the above and start again in the correct order. - -Some of the build instructions will ask you to start a Visual Studio Command Prompt. You should have a shortcut in your Start menu called "Open Visual Studio Command Prompt (2010)" which will do so. - -#####Visual Studio 2013 - -You can use the Community or Professional editions of Visual Studio 2013. - -You can start a Visual Studio 2013 command prompt using the shortcut provided in the Visual Studio Tools folder installed as part of Visual Studio 2013. - -Or you can start a regular command prompt and then run: - - "%VS120COMNTOOLS%\vsvars32.bat" - -If you experience issues building interface on Visual Studio 2013, try generating the build files with Visual Studio 2010 instead. To do so, download Visual Studio 2010 and run `cmake .. -G "Visual Studio 10"` (Assuming running from %HIFI_DIR%\build). - -####Qt -You can use the online installer or the offline installer. If you use the offline installer, be sure to select the "OpenGL" version. - -NOTE: Qt does not support 64-bit builds on Windows 7, so you must use the 32-bit version of libraries for interface.exe to run. The 32-bit version of the static library is the one linked by our CMake find modules. - -* Download the online installer [here](http://qt-project.org/downloads) - * When it asks you to select components, ONLY select the following: - * Qt > Qt 5.2.0 > **msvc2010 32-bit OpenGL** - -* Download the offline installer [here](http://download.qt-project.org/official_releases/qt/5.2/5.2.0/qt-windows-opensource-5.2.0-msvc2010_opengl-x86-offline.exe) - -Once Qt is installed, you need to manually configure the following: -* Make sure the Qt runtime DLLs are loadable. You must do this before you attempt to build because some tools for the build depend on Qt. E.g., add to the PATH: `Qt\5.2.0\msvc2010_opengl\bin\`. -* Set the QT_CMAKE_PREFIX_PATH environment variable to your `Qt\5.2.0\msvc2010_opengl` directory. - -If building as a Visual Studio 2013 project, download and configure the msvc2013 version of Qt instead. - -####External Libraries - -CMake will need to know where the headers and libraries for required external dependencies are. - -The recommended route for CMake to find the external dependencies is to place all of the dependencies in one folder and set one ENV variable - HIFI_LIB_DIR. That ENV variable should point to a directory with the following structure: - - root_lib_dir - -> freeglut - -> bin - -> include - -> lib - -> glew - -> bin - -> include - -> lib - -> glm - -> glm - -> glm.hpp - -> openssl - -> bin - -> include - -> lib - -> tbb - -> include - -> lib - -> zlib - -> include - -> lib - -> test - -For many of the external libraries where precompiled binaries are readily available you should be able to simply copy the extracted folder that you get from the download links provided at the top of the guide. Otherwise you may need to build from source and install the built product to this directory. The `root_lib_dir` in the above example can be wherever you choose on your system - as long as the environment variable HIFI_LIB_DIR is set to it. From here on, whenever you see %HIFI_LIB_DIR% you should substitute the directory that you chose. - -As with the Qt libraries, you will need to make sure that directories containing DLL'S are in your path. Where possible, you can use static builds of the external dependencies to avoid this requirement. - -#### OpenSSL - -QT will use OpenSSL if it's available, but it doesn't install it, so you must install it separately. - -Your system may already have several versions of the OpenSSL DLL's (ssleay32.dll, libeay32.dll) lying around, but they may be the wrong version. If these DLL's are in the PATH then QT will try to use them, and if they're the wrong version then you will see the following errors in the console: - - QSslSocket: cannot resolve TLSv1_1_client_method - QSslSocket: cannot resolve TLSv1_2_client_method - QSslSocket: cannot resolve TLSv1_1_server_method - QSslSocket: cannot resolve TLSv1_2_server_method - QSslSocket: cannot resolve SSL_select_next_proto - QSslSocket: cannot resolve SSL_CTX_set_next_proto_select_cb - QSslSocket: cannot resolve SSL_get0_next_proto_negotiated - -To prevent these problems, install OpenSSL yourself. Download the following binary packages [from this website](http://slproweb.com/products/Win32OpenSSL.html): -* Visual C++ 2008 Redistributables -* Win32 OpenSSL v1.0.1h - -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. - -#### Intel Threading Building Blocks (TBB) - -Download the stable release for Windows from the [Intel Threading Building Blocks website](https://www.threadingbuildingblocks.org/). By default, TBB will install to Program Files. You may also choose to install it to %HIFI_LIB_DIR%\TBB. - -You must run `tbbvars.bat` so that the find module included with this project will be able to find TBB no matter where you installed it. `tbbvars.bat` is located in the 'bin' folder of your TBB install. For a default installation on a 64-bit architechture, tbbvars can be found at `C:/Program Files (x86)/Intel/TBB/bin/tbbvars.bat`. - -#### Zlib - -Download the compiled DLL from the [zlib website](http://www.zlib.net/). Extract to %HIFI_LIB_DIR%\zlib. - -Add the following environment variables (remember to substitute your own directory for %HIFI_LIB_DIR%): - - ZLIB_LIBRARY=%HIFI_LIB_DIR%\zlib\lib\zdll.lib - ZLIB_INCLUDE_DIR=%HIFI_LIB_DIR%\zlib\include - -Add to the PATH: `%HIFI_LIB_DIR%\zlib` - -Important! This should be added at the beginning of the path, not the end. That's because your -system likely has many copies of zlib1.dll, and you want High Fidelity to use the correct version. If High Fidelity picks up the wrong zlib1.dll then it might be unable to use it, and that would cause it to fail to start, showing only the cryptic error "The application was unable to start correctly: 0xc0000022". - -#### freeglut - -Download the binary package: `freeglut-MSVC-2.8.1-1.mp.zip`. Extract to %HIFI_LIB_DIR%\freeglut. - -Add to the PATH: `%HIFI_LIB_DIR%\freeglut\bin` - -#### GLEW - -Download the binary package: `glew-1.10.0-win32.zip`. Extract to %HIFI_LIB_DIR%\glew (you'll need to rename the default directory name). - -Add to the PATH: `%HIFI_LIB_DIR%\glew\bin\Release\Win32` - -#### GLM - -This package contains only headers, so there's nothing to add to the PATH. - -Be careful with glm. For the folder other libraries would normally call 'include', the folder containing the headers, glm opts to use 'glm'. You will have a glm folder nested inside the top-level glm folder. - -#### Build High Fidelity using Visual Studio -Follow the same build steps from the CMake section, but pass a different generator to CMake. - - cmake .. -DZLIB_LIBRARY=%ZLIB_LIBRARY% -DZLIB_INCLUDE_DIR=%ZLIB_INCLUDE_DIR% -G "Visual Studio 10" - -If you're using Visual Studio 2013 then pass "Visual Studio 12" instead of "Visual Studio 10" (yes, 12, not 13). - -Open %HIFI_DIR%\build\hifi.sln and compile. - -####Running Interface -If you need to debug Interface, you can run interface from within Visual Studio (see the section below). You can also run Interface by launching it from command line or File Explorer from %HIFI_DIR%\build\interface\Debug\interface.exe - -####Debugging Interface -* In the Solution Explorer, right click interface and click Set as StartUp Project -* Set the "Working Directory" for the Interface debugging sessions to the Debug output directory so that your application can load resources. Do this: right click interface and click Properties, choose Debugging from Configuration Properties, set Working Directory to .\Debug -* Now you can run and debug interface through Visual Studio - -Optional Components -=== +###Optional Components ####QXmpp @@ -276,7 +52,7 @@ You can find QXmpp [here](https://github.com/qxmpp-project/qxmpp). The inclusion OS X users who tap our [homebrew formulas repository](https://github.com/highfidelity/homebrew-formulas) can install QXmpp via homebrew - `brew install highfidelity/formulas/qxmpp`. -#### Devices +####Devices You can support external input/output devices such as Leap Motion, Faceplus, Faceshift, PrioVR, MIDI, Razr Hydra and more by adding each individual SDK in the visible building path. Refer to the readme file available in each device folder in [interface/external/](interface/external) for the detailed explanation of the requirements to use the device. diff --git a/BUILD_LINUX.md b/BUILD_LINUX.md new file mode 100644 index 0000000000..17f7268131 --- /dev/null +++ b/BUILD_LINUX.md @@ -0,0 +1,18 @@ +Please read the [general build guide](BUILD.md) for information on dependencies required for all platforms. Only Linux specific instructions are found in this file. + +####Linux Specific Dependencies +* [freeglut](http://freeglut.sourceforge.net/) ~> 2.8.0 +* [zLib](http://www.zlib.net/) ~> 1.2.8 + +In general, as long as external dependencies are placed in OS standard locations, CMake will successfully find them during its run. When possible, you may choose to install depencies from your package manager of choice, or from source. + +####Qt5 Dependencies +Should you choose not to install Qt5 via a package manager that handles dependencies for you, you may be missing some Qt5 dependencies. On Ubuntu, for example, the following additional packages are required: + + libasound2 libxmu-dev libxi-dev freeglut3-dev libasound2-dev libjack-dev + +#### Intel Threading Building Blocks (TBB) + +Install Intel TBB from your package manager of choice, or from source (available at the [TBB Website](https://www.threadingbuildingblocks.org/)). + +You must run `tbbvars` so that the find module included with this project will be able to find the correct version of TBB. `tbbvars` is located in the 'bin' folder of your TBB install. \ No newline at end of file diff --git a/BUILD_OSX.md b/BUILD_OSX.md new file mode 100644 index 0000000000..977a27a781 --- /dev/null +++ b/BUILD_OSX.md @@ -0,0 +1,22 @@ +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. + + brew tap highfidelity/homebrew-formulas + brew install cmake glm openssl tbb + brew install highfidelity/formulas/qt5 + brew link qt5 --force + +We have a [homebrew formulas repository](https://github.com/highfidelity/homebrew-formulas) that you can use/tap to install some of the dependencies. In the code block above qt5 is installed from a formula in this repository. + +*Our [qt5 homebrew formula](https://raw.github.com/highfidelity/homebrew-formulas/master/qt5.rb) is for a patched version of Qt 5.3.x stable that removes wireless network scanning that can reduce real-time audio performance. We recommended you use this formula to install Qt.* + +####Xcode +If Xcode is your editor of choice, you can ask CMake to generate Xcode project files instead of Unix Makefiles. + + cmake .. -GXcode + +After running cmake, you will have the make files or Xcode project file necessary to build all of the components. Open the hifi.xcodeproj file, choose ALL_BUILD from the Product > Scheme menu (or target drop down), and click Run. + +If the build completes successfully, you will have built targets for all components located in the `build/${target_name}/Debug` directories. diff --git a/BUILD_WIN.md b/BUILD_WIN.md new file mode 100644 index 0000000000..458aeca53a --- /dev/null +++ b/BUILD_WIN.md @@ -0,0 +1,180 @@ +Please read the [general build guide](BUILD.md) for information on dependencies required for all platforms. Only Windows specific instructions are found in this file. + +####Windows Dependencies +* [GLEW](http://glew.sourceforge.net/) ~> 1.10.0 +* [freeglut MSVC](http://www.transmissionzero.co.uk/software/freeglut-devel/) ~> 2.8.1 +* [zLib](http://www.zlib.net/) ~> 1.2.8 + +####Visual Studio + +Currently building on Windows has been tested using the following compilers: +* Visual Studio C++ 2010 Express +* Visual Studio 2013 + +(If anyone can test using Visual Studio 2013 Express then please update this document) + +#####Windows SDK 7.1 + +If using Visual Studio 2010, or using Visual Studio 2013 but building as a Visual Studio 2010 project, you need [Microsoft Windows SDK for Windows 7 and .NET Framework 4](http://www.microsoft.com/en-us/download/details.aspx?id=8279). + +NOTE: If using Visual Studio C++ 2010 Express, you need to follow a specific install order. See below before installing the Windows SDK. + +######Windows SDK 8.1 + +If using Visual Studio 2013 and building as a Visual Studio 2013 project you need the Windows 8 SDK which you should already have as part of installing Visual Studio 2013. You should be able to see it at `C:\Program Files (x86)\Windows Kits\8.1\Lib\winv6.3\um\x86`. + +#####Visual Studio C++ 2010 Express + +Visual Studio C++ 2010 Express can be downloaded [here](http://www.visualstudio.com/en-us/downloads#d-2010-express). + +The following patches/service packs are also required: +* [VS2010 SP1](http://www.microsoft.com/en-us/download/details.aspx?id=23691) +* [VS2010 SP1 Compiler Update](http://www.microsoft.com/en-us/download/details.aspx?id=4422) + +IMPORTANT: Use the following install order: +Visual Studio C++ 2010 Express +Windows SDK 7.1 +VS2010 SP1 +VS2010 SP1 Compiler Update + +If you get an error while installing the VS2010 SP1 Compiler update saying that you don't have the Windows SDK installed, then uninstall all of the above and start again in the correct order. + +Some of the build instructions will ask you to start a Visual Studio Command Prompt. You should have a shortcut in your Start menu called "Open Visual Studio Command Prompt (2010)" which will do so. + +#####Visual Studio 2013 + +You can use the Community or Professional editions of Visual Studio 2013. + +You can start a Visual Studio 2013 command prompt using the shortcut provided in the Visual Studio Tools folder installed as part of Visual Studio 2013. + +Or you can start a regular command prompt and then run: + + "%VS120COMNTOOLS%\vsvars32.bat" + +If you experience issues building interface on Visual Studio 2013, try generating the build files with Visual Studio 2010 instead. To do so, download Visual Studio 2010 and run `cmake .. -G "Visual Studio 10"` (Assuming running from %HIFI_DIR%\build). + +####Qt +You can use the online installer or the offline installer. If you use the offline installer, be sure to select the "OpenGL" version. + +NOTE: Qt does not support 64-bit builds on Windows 7, so you must use the 32-bit version of libraries for interface.exe to run. The 32-bit version of the static library is the one linked by our CMake find modules. + +* Download the online installer [here](http://qt-project.org/downloads) + * When it asks you to select components, ONLY select the following: + * Qt > Qt 5.2.0 > **msvc2010 32-bit OpenGL** + +* Download the offline installer [here](http://download.qt-project.org/official_releases/qt/5.2/5.2.0/qt-windows-opensource-5.2.0-msvc2010_opengl-x86-offline.exe) + +Once Qt is installed, you need to manually configure the following: +* Make sure the Qt runtime DLLs are loadable. You must do this before you attempt to build because some tools for the build depend on Qt. E.g., add to the PATH: `Qt\5.2.0\msvc2010_opengl\bin\`. +* Set the QT_CMAKE_PREFIX_PATH environment variable to your `Qt\5.2.0\msvc2010_opengl` directory. + +If building as a Visual Studio 2013 project, download and configure the msvc2013 version of Qt instead. + +####External Libraries + +CMake will need to know where the headers and libraries for required external dependencies are. + +The recommended route for CMake to find the external dependencies is to place all of the dependencies in one folder and set one ENV variable - HIFI_LIB_DIR. That ENV variable should point to a directory with the following structure: + + root_lib_dir + -> freeglut + -> bin + -> include + -> lib + -> glew + -> bin + -> include + -> lib + -> glm + -> glm + -> glm.hpp + -> openssl + -> bin + -> include + -> lib + -> tbb + -> include + -> lib + -> zlib + -> include + -> lib + -> test + +For many of the external libraries where precompiled binaries are readily available you should be able to simply copy the extracted folder that you get from the download links provided at the top of the guide. Otherwise you may need to build from source and install the built product to this directory. The `root_lib_dir` in the above example can be wherever you choose on your system - as long as the environment variable HIFI_LIB_DIR is set to it. From here on, whenever you see %HIFI_LIB_DIR% you should substitute the directory that you chose. + +As with the Qt libraries, you will need to make sure that directories containing DLL'S are in your path. Where possible, you can use static builds of the external dependencies to avoid this requirement. + +#### OpenSSL + +QT will use OpenSSL if it's available, but it doesn't install it, so you must install it separately. + +Your system may already have several versions of the OpenSSL DLL's (ssleay32.dll, libeay32.dll) lying around, but they may be the wrong version. If these DLL's are in the PATH then QT will try to use them, and if they're the wrong version then you will see the following errors in the console: + + QSslSocket: cannot resolve TLSv1_1_client_method + QSslSocket: cannot resolve TLSv1_2_client_method + QSslSocket: cannot resolve TLSv1_1_server_method + QSslSocket: cannot resolve TLSv1_2_server_method + QSslSocket: cannot resolve SSL_select_next_proto + QSslSocket: cannot resolve SSL_CTX_set_next_proto_select_cb + QSslSocket: cannot resolve SSL_get0_next_proto_negotiated + +To prevent these problems, install OpenSSL yourself. Download the following binary packages [from this website](http://slproweb.com/products/Win32OpenSSL.html): +* Visual C++ 2008 Redistributables +* Win32 OpenSSL v1.0.1h + +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. + +#### Intel Threading Building Blocks (TBB) + +Download the stable release for Windows from the [Intel Threading Building Blocks website](https://www.threadingbuildingblocks.org/). By default, TBB will install to Program Files. You may also choose to install it to %HIFI_LIB_DIR%\TBB. + +You must run `tbbvars.bat` so that the find module included with this project will be able to find TBB no matter where you installed it. `tbbvars.bat` is located in the 'bin' folder of your TBB install. For a default installation on a 64-bit architechture, tbbvars can be found at `C:/Program Files (x86)/Intel/TBB/bin/tbbvars.bat`. + +#### Zlib + +Download the compiled DLL from the [zlib website](http://www.zlib.net/). Extract to %HIFI_LIB_DIR%\zlib. + +Add the following environment variables (remember to substitute your own directory for %HIFI_LIB_DIR%): + + ZLIB_LIBRARY=%HIFI_LIB_DIR%\zlib\lib\zdll.lib + ZLIB_INCLUDE_DIR=%HIFI_LIB_DIR%\zlib\include + +Add to the PATH: `%HIFI_LIB_DIR%\zlib` + +Important! This should be added at the beginning of the path, not the end. That's because your +system likely has many copies of zlib1.dll, and you want High Fidelity to use the correct version. If High Fidelity picks up the wrong zlib1.dll then it might be unable to use it, and that would cause it to fail to start, showing only the cryptic error "The application was unable to start correctly: 0xc0000022". + +#### freeglut + +Download the binary package: `freeglut-MSVC-2.8.1-1.mp.zip`. Extract to %HIFI_LIB_DIR%\freeglut. + +Add to the PATH: `%HIFI_LIB_DIR%\freeglut\bin` + +#### GLEW + +Download the binary package: `glew-1.10.0-win32.zip`. Extract to %HIFI_LIB_DIR%\glew (you'll need to rename the default directory name). + +Add to the PATH: `%HIFI_LIB_DIR%\glew\bin\Release\Win32` + +#### GLM + +This package contains only headers, so there's nothing to add to the PATH. + +Be careful with glm. For the folder other libraries would normally call 'include', the folder containing the headers, glm opts to use 'glm'. You will have a glm folder nested inside the top-level glm folder. + +#### Build High Fidelity using Visual Studio +Follow the same build steps from the CMake section, but pass a different generator to CMake. + + cmake .. -DZLIB_LIBRARY=%ZLIB_LIBRARY% -DZLIB_INCLUDE_DIR=%ZLIB_INCLUDE_DIR% -G "Visual Studio 10" + +If you're using Visual Studio 2013 then pass "Visual Studio 12" instead of "Visual Studio 10" (yes, 12, not 13). + +Open %HIFI_DIR%\build\hifi.sln and compile. + +####Running Interface +If you need to debug Interface, you can run interface from within Visual Studio (see the section below). You can also run Interface by launching it from command line or File Explorer from %HIFI_DIR%\build\interface\Debug\interface.exe + +####Debugging Interface +* In the Solution Explorer, right click interface and click Set as StartUp Project +* Set the "Working Directory" for the Interface debugging sessions to the Debug output directory so that your application can load resources. Do this: right click interface and click Properties, choose Debugging from Configuration Properties, set Working Directory to .\Debug +* Now you can run and debug interface through Visual Studio From a87fb0fe5e4906c7581ed2947ee2679ab00b0c61 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 15 Dec 2014 10:21:31 -0800 Subject: [PATCH 389/502] link to OS build guides from main guide --- BUILD.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/BUILD.md b/BUILD.md index 867e515209..0a897aa193 100644 --- a/BUILD.md +++ b/BUILD.md @@ -7,6 +7,11 @@ * IMPORTANT: OpenSSL 1.0.1g is critical to avoid a security vulnerability. * [Intel Threading Building Blocks](https://www.threadingbuildingblocks.org/) ~> 4.3 +### OS Specific Build Guides +* [BUILD_OSX.md](BUILD_OSX.md) - additional instructions for OS X. +* [BUILD_LINUX.md](BUILD_LINUX.md) - additional instructions for Linux. +* [BUILD_WIN.md](BUILD_WIN.md) - additional instructions for Windows. + ###CMake Hifi uses CMake to generate build files and project files for your platform. From bba48a61f99671ae7372e0d2542e095dad787ec0 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 15 Dec 2014 10:22:58 -0800 Subject: [PATCH 390/502] cleanup formatting of build guides --- BUILD_LINUX.md | 6 +++--- BUILD_OSX.md | 4 ++-- BUILD_WIN.md | 34 +++++++++++++++++----------------- 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/BUILD_LINUX.md b/BUILD_LINUX.md index 17f7268131..eb4dcd9255 100644 --- a/BUILD_LINUX.md +++ b/BUILD_LINUX.md @@ -1,17 +1,17 @@ Please read the [general build guide](BUILD.md) for information on dependencies required for all platforms. Only Linux specific instructions are found in this file. -####Linux Specific Dependencies +###Linux Specific Dependencies * [freeglut](http://freeglut.sourceforge.net/) ~> 2.8.0 * [zLib](http://www.zlib.net/) ~> 1.2.8 In general, as long as external dependencies are placed in OS standard locations, CMake will successfully find them during its run. When possible, you may choose to install depencies from your package manager of choice, or from source. -####Qt5 Dependencies +###Qt5 Dependencies Should you choose not to install Qt5 via a package manager that handles dependencies for you, you may be missing some Qt5 dependencies. On Ubuntu, for example, the following additional packages are required: libasound2 libxmu-dev libxi-dev freeglut3-dev libasound2-dev libjack-dev -#### Intel Threading Building Blocks (TBB) +###Intel Threading Building Blocks (TBB) Install Intel TBB from your package manager of choice, or from source (available at the [TBB Website](https://www.threadingbuildingblocks.org/)). diff --git a/BUILD_OSX.md b/BUILD_OSX.md index 977a27a781..1eeaed1c13 100644 --- a/BUILD_OSX.md +++ b/BUILD_OSX.md @@ -1,6 +1,6 @@ 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 [Homebrew](http://brew.sh/) is an excellent package manager for OS X. It makes install of all hifi dependencies very simple. brew tap highfidelity/homebrew-formulas @@ -12,7 +12,7 @@ We have a [homebrew formulas repository](https://github.com/highfidelity/homebre *Our [qt5 homebrew formula](https://raw.github.com/highfidelity/homebrew-formulas/master/qt5.rb) is for a patched version of Qt 5.3.x stable that removes wireless network scanning that can reduce real-time audio performance. We recommended you use this formula to install Qt.* -####Xcode +###Xcode If Xcode is your editor of choice, you can ask CMake to generate Xcode project files instead of Unix Makefiles. cmake .. -GXcode diff --git a/BUILD_WIN.md b/BUILD_WIN.md index 458aeca53a..5685370dc3 100644 --- a/BUILD_WIN.md +++ b/BUILD_WIN.md @@ -1,11 +1,11 @@ Please read the [general build guide](BUILD.md) for information on dependencies required for all platforms. Only Windows specific instructions are found in this file. -####Windows Dependencies +###Windows Dependencies * [GLEW](http://glew.sourceforge.net/) ~> 1.10.0 * [freeglut MSVC](http://www.transmissionzero.co.uk/software/freeglut-devel/) ~> 2.8.1 * [zLib](http://www.zlib.net/) ~> 1.2.8 -####Visual Studio +###Visual Studio Currently building on Windows has been tested using the following compilers: * Visual Studio C++ 2010 Express @@ -13,17 +13,17 @@ Currently building on Windows has been tested using the following compilers: (If anyone can test using Visual Studio 2013 Express then please update this document) -#####Windows SDK 7.1 +####Windows SDK 7.1 If using Visual Studio 2010, or using Visual Studio 2013 but building as a Visual Studio 2010 project, you need [Microsoft Windows SDK for Windows 7 and .NET Framework 4](http://www.microsoft.com/en-us/download/details.aspx?id=8279). NOTE: If using Visual Studio C++ 2010 Express, you need to follow a specific install order. See below before installing the Windows SDK. -######Windows SDK 8.1 +#####Windows SDK 8.1 If using Visual Studio 2013 and building as a Visual Studio 2013 project you need the Windows 8 SDK which you should already have as part of installing Visual Studio 2013. You should be able to see it at `C:\Program Files (x86)\Windows Kits\8.1\Lib\winv6.3\um\x86`. -#####Visual Studio C++ 2010 Express +####Visual Studio C++ 2010 Express Visual Studio C++ 2010 Express can be downloaded [here](http://www.visualstudio.com/en-us/downloads#d-2010-express). @@ -41,7 +41,7 @@ If you get an error while installing the VS2010 SP1 Compiler update saying that Some of the build instructions will ask you to start a Visual Studio Command Prompt. You should have a shortcut in your Start menu called "Open Visual Studio Command Prompt (2010)" which will do so. -#####Visual Studio 2013 +####Visual Studio 2013 You can use the Community or Professional editions of Visual Studio 2013. @@ -53,7 +53,7 @@ Or you can start a regular command prompt and then run: If you experience issues building interface on Visual Studio 2013, try generating the build files with Visual Studio 2010 instead. To do so, download Visual Studio 2010 and run `cmake .. -G "Visual Studio 10"` (Assuming running from %HIFI_DIR%\build). -####Qt +###Qt You can use the online installer or the offline installer. If you use the offline installer, be sure to select the "OpenGL" version. NOTE: Qt does not support 64-bit builds on Windows 7, so you must use the 32-bit version of libraries for interface.exe to run. The 32-bit version of the static library is the one linked by our CMake find modules. @@ -70,7 +70,7 @@ Once Qt is installed, you need to manually configure the following: If building as a Visual Studio 2013 project, download and configure the msvc2013 version of Qt instead. -####External Libraries +###External Libraries CMake will need to know where the headers and libraries for required external dependencies are. @@ -104,7 +104,7 @@ For many of the external libraries where precompiled binaries are readily availa As with the Qt libraries, you will need to make sure that directories containing DLL'S are in your path. Where possible, you can use static builds of the external dependencies to avoid this requirement. -#### OpenSSL +###OpenSSL QT will use OpenSSL if it's available, but it doesn't install it, so you must install it separately. @@ -124,13 +124,13 @@ 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. -#### Intel Threading Building Blocks (TBB) +###Intel Threading Building Blocks (TBB) Download the stable release for Windows from the [Intel Threading Building Blocks website](https://www.threadingbuildingblocks.org/). By default, TBB will install to Program Files. You may also choose to install it to %HIFI_LIB_DIR%\TBB. You must run `tbbvars.bat` so that the find module included with this project will be able to find TBB no matter where you installed it. `tbbvars.bat` is located in the 'bin' folder of your TBB install. For a default installation on a 64-bit architechture, tbbvars can be found at `C:/Program Files (x86)/Intel/TBB/bin/tbbvars.bat`. -#### Zlib +###Zlib Download the compiled DLL from the [zlib website](http://www.zlib.net/). Extract to %HIFI_LIB_DIR%\zlib. @@ -144,25 +144,25 @@ Add to the PATH: `%HIFI_LIB_DIR%\zlib` Important! This should be added at the beginning of the path, not the end. That's because your system likely has many copies of zlib1.dll, and you want High Fidelity to use the correct version. If High Fidelity picks up the wrong zlib1.dll then it might be unable to use it, and that would cause it to fail to start, showing only the cryptic error "The application was unable to start correctly: 0xc0000022". -#### freeglut +###freeglut Download the binary package: `freeglut-MSVC-2.8.1-1.mp.zip`. Extract to %HIFI_LIB_DIR%\freeglut. Add to the PATH: `%HIFI_LIB_DIR%\freeglut\bin` -#### GLEW +###GLEW Download the binary package: `glew-1.10.0-win32.zip`. Extract to %HIFI_LIB_DIR%\glew (you'll need to rename the default directory name). Add to the PATH: `%HIFI_LIB_DIR%\glew\bin\Release\Win32` -#### GLM +###GLM This package contains only headers, so there's nothing to add to the PATH. Be careful with glm. For the folder other libraries would normally call 'include', the folder containing the headers, glm opts to use 'glm'. You will have a glm folder nested inside the top-level glm folder. -#### Build High Fidelity using Visual Studio +###Build High Fidelity using Visual Studio Follow the same build steps from the CMake section, but pass a different generator to CMake. cmake .. -DZLIB_LIBRARY=%ZLIB_LIBRARY% -DZLIB_INCLUDE_DIR=%ZLIB_INCLUDE_DIR% -G "Visual Studio 10" @@ -171,10 +171,10 @@ If you're using Visual Studio 2013 then pass "Visual Studio 12" instead of "Visu Open %HIFI_DIR%\build\hifi.sln and compile. -####Running Interface +###Running Interface If you need to debug Interface, you can run interface from within Visual Studio (see the section below). You can also run Interface by launching it from command line or File Explorer from %HIFI_DIR%\build\interface\Debug\interface.exe -####Debugging Interface +###Debugging Interface * In the Solution Explorer, right click interface and click Set as StartUp Project * Set the "Working Directory" for the Interface debugging sessions to the Debug output directory so that your application can load resources. Do this: right click interface and click Properties, choose Debugging from Configuration Properties, set Working Directory to .\Debug * Now you can run and debug interface through Visual Studio From 7d75d2d1bfe76f46b0fa3685ca56461853ffa670 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 15 Dec 2014 10:34:16 -0800 Subject: [PATCH 391/502] make TextureCache work with DependancyManager --- interface/src/Application.cpp | 18 +++++++-------- interface/src/MetavoxelSystem.cpp | 18 +++++++-------- interface/src/ModelUploader.cpp | 2 +- interface/src/devices/OculusManager.cpp | 6 ++--- .../src/renderer/AmbientOcclusionEffect.cpp | 6 ++--- .../src/renderer/DeferredLightingEffect.cpp | 22 +++++++++---------- interface/src/renderer/GeometryCache.cpp | 16 +++++++------- interface/src/renderer/GlowEffect.cpp | 14 ++++++------ interface/src/renderer/Model.cpp | 20 ++++++++--------- interface/src/renderer/TextureCache.cpp | 6 ----- interface/src/renderer/TextureCache.h | 12 +++++----- interface/src/ui/MetavoxelEditor.cpp | 2 +- interface/src/voxels/VoxelSystem.cpp | 6 ++--- 13 files changed, 70 insertions(+), 78 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 1ec177163d..105e3e087c 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -620,10 +620,10 @@ void Application::paintGL() { // Set the desired FBO texture size. If it hasn't changed, this does nothing. // Otherwise, it must rebuild the FBOs if (OculusManager::isConnected()) { - TextureCache::getInstance()->setFrameBufferSize(OculusManager::getRenderTargetSize()); + DependencyManager::get()->setFrameBufferSize(OculusManager::getRenderTargetSize()); } else { QSize fbSize = _glWidget->getDeviceSize() * getRenderResolutionScale(); - TextureCache::getInstance()->setFrameBufferSize(fbSize); + DependencyManager::get()->setFrameBufferSize(fbSize); } glEnable(GL_LINE_SMOOTH); @@ -713,7 +713,7 @@ void Application::paintGL() { _glowEffect.prepare(); // Viewport is assigned to the size of the framebuffer - QSize size = TextureCache::getInstance()->getPrimaryFramebufferObject()->size(); + QSize size = DependencyManager::get()->getPrimaryFramebufferObject()->size(); glViewport(0, 0, size.width(), size.height()); glMatrixMode(GL_MODELVIEW); @@ -2043,7 +2043,7 @@ void Application::init() { connect(_myAvatar, &MyAvatar::transformChanged, this, &Application::bumpSettings); // make sure our texture cache knows about window size changes - TextureCache::getInstance()->associateWithWidget(getGLWidget()); + DependencyManager::get()->associateWithWidget(getGLWidget()); } void Application::closeMirrorView() { @@ -2774,7 +2774,7 @@ glm::vec3 Application::getSunDirection() { void Application::updateShadowMap() { PerformanceTimer perfTimer("shadowMap"); - QOpenGLFramebufferObject* fbo = TextureCache::getInstance()->getShadowFramebufferObject(); + QOpenGLFramebufferObject* fbo = DependencyManager::get()->getShadowFramebufferObject(); fbo->bind(); glEnable(GL_DEPTH_TEST); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -2939,7 +2939,7 @@ void Application::setupWorldLight() { } QImage Application::renderAvatarBillboard() { - TextureCache::getInstance()->getPrimaryFramebufferObject()->bind(); + DependencyManager::get()->getPrimaryFramebufferObject()->bind(); // the "glow" here causes an alpha of one Glower glower; @@ -2950,7 +2950,7 @@ QImage Application::renderAvatarBillboard() { QImage image(BILLBOARD_SIZE, BILLBOARD_SIZE, QImage::Format_ARGB32); glReadPixels(0, 0, BILLBOARD_SIZE, BILLBOARD_SIZE, GL_BGRA, GL_UNSIGNED_BYTE, image.bits()); - TextureCache::getInstance()->getPrimaryFramebufferObject()->release(); + DependencyManager::get()->getPrimaryFramebufferObject()->release(); return image; } @@ -3301,12 +3301,12 @@ void Application::renderRearViewMirror(const QRect& region, bool billboard) { // set the bounds of rear mirror view if (billboard) { - QSize size = TextureCache::getInstance()->getFrameBufferSize(); + QSize size = DependencyManager::get()->getFrameBufferSize(); glViewport(region.x(), size.height() - region.y() - region.height(), region.width(), region.height()); glScissor(region.x(), size.height() - region.y() - region.height(), region.width(), region.height()); } else { // if not rendering the billboard, the region is in device independent coordinates; must convert to device - QSize size = TextureCache::getInstance()->getFrameBufferSize(); + QSize size = DependencyManager::get()->getFrameBufferSize(); float ratio = QApplication::desktop()->windowHandle()->devicePixelRatio() * getRenderResolutionScale(); int x = region.x() * ratio, y = region.y() * ratio, width = region.width() * ratio, height = region.height() * ratio; glViewport(x, size.height() - y - height, width, height); diff --git a/interface/src/MetavoxelSystem.cpp b/interface/src/MetavoxelSystem.cpp index 2e3e9796f3..a61f6e41d7 100644 --- a/interface/src/MetavoxelSystem.cpp +++ b/interface/src/MetavoxelSystem.cpp @@ -205,7 +205,7 @@ void MetavoxelSystem::render() { glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); - TextureCache::getInstance()->setPrimaryDrawBuffers(true, true); + DependencyManager::get()->setPrimaryDrawBuffers(true, true); glDisable(GL_BLEND); glEnable(GL_CULL_FACE); @@ -251,7 +251,7 @@ void MetavoxelSystem::render() { glPopMatrix(); } - TextureCache::getInstance()->setPrimaryDrawBuffers(true, false); + DependencyManager::get()->setPrimaryDrawBuffers(true, false); _baseHeightfieldProgram.release(); @@ -348,7 +348,7 @@ void MetavoxelSystem::render() { } if (!_voxelBaseBatches.isEmpty()) { - TextureCache::getInstance()->setPrimaryDrawBuffers(true, true); + DependencyManager::get()->setPrimaryDrawBuffers(true, true); glEnableClientState(GL_VERTEX_ARRAY); glDisable(GL_BLEND); @@ -383,7 +383,7 @@ void MetavoxelSystem::render() { glDisable(GL_ALPHA_TEST); glEnable(GL_BLEND); - TextureCache::getInstance()->setPrimaryDrawBuffers(true, false); + DependencyManager::get()->setPrimaryDrawBuffers(true, false); if (!_voxelSplatBatches.isEmpty()) { glDepthFunc(GL_LEQUAL); @@ -463,7 +463,7 @@ void MetavoxelSystem::render() { } if (!_hermiteBatches.isEmpty() && Menu::getInstance()->isOptionChecked(MenuOption::DisplayHermiteData)) { - TextureCache::getInstance()->setPrimaryDrawBuffers(true, true); + DependencyManager::get()->setPrimaryDrawBuffers(true, true); glEnableClientState(GL_VERTEX_ARRAY); @@ -486,7 +486,7 @@ void MetavoxelSystem::render() { glDisableClientState(GL_VERTEX_ARRAY); - TextureCache::getInstance()->setPrimaryDrawBuffers(true, false); + DependencyManager::get()->setPrimaryDrawBuffers(true, false); } _hermiteBatches.clear(); @@ -797,7 +797,7 @@ void MetavoxelSystem::applyMaterialEdit(const MetavoxelEditMessage& message, boo Q_ARG(bool, reliable)); return; } - QSharedPointer texture = TextureCache::getInstance()->getTexture( + QSharedPointer texture = DependencyManager::get()->getTexture( material->getDiffuse(), SPLAT_TEXTURE); if (texture->isLoaded()) { MetavoxelEditMessage newMessage = message; @@ -1180,7 +1180,7 @@ void VoxelBuffer::render(bool cursor) { for (int i = 0; i < _materials.size(); i++) { const SharedObjectPointer material = _materials.at(i); if (material) { - _networkTextures[i] = TextureCache::getInstance()->getTexture( + _networkTextures[i] = DependencyManager::get()->getTexture( static_cast(material.data())->getDiffuse(), SPLAT_TEXTURE); } } @@ -2234,7 +2234,7 @@ void HeightfieldNodeRenderer::render(const HeightfieldNodePointer& node, const g for (int i = 0; i < materials.size(); i++) { const SharedObjectPointer& material = materials.at(i); if (material) { - _networkTextures[i] = TextureCache::getInstance()->getTexture( + _networkTextures[i] = DependencyManager::get()->getTexture( static_cast(material.data())->getDiffuse(), SPLAT_TEXTURE); } } diff --git a/interface/src/ModelUploader.cpp b/interface/src/ModelUploader.cpp index ee38a2c094..c3b6ba74c3 100644 --- a/interface/src/ModelUploader.cpp +++ b/interface/src/ModelUploader.cpp @@ -473,7 +473,7 @@ void ModelUploader::processCheck() { QMessageBox::Ok); GeometryCache::getInstance()->refresh(_url); foreach (const QByteArray& filename, _textureFilenames) { - TextureCache::getInstance()->refresh(_textureBase + filename); + DependencyManager::get()->refresh(_textureBase + filename); } deleteLater(); break; diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index 0eb0c732c9..d27ab09876 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -449,7 +449,7 @@ void OculusManager::display(const glm::quat &bodyOrientation, const glm::vec3 &p if (Menu::getInstance()->isOptionChecked(MenuOption::EnableGlowEffect)) { Application::getInstance()->getGlowEffect()->prepare(); } else { - TextureCache::getInstance()->getPrimaryFramebufferObject()->bind(); + DependencyManager::get()->getPrimaryFramebufferObject()->bind(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } @@ -555,8 +555,8 @@ void OculusManager::display(const glm::quat &bodyOrientation, const glm::vec3 &p QOpenGLFramebufferObject* fbo = Application::getInstance()->getGlowEffect()->render(true); glBindTexture(GL_TEXTURE_2D, fbo->texture()); } else { - TextureCache::getInstance()->getPrimaryFramebufferObject()->release(); - glBindTexture(GL_TEXTURE_2D, TextureCache::getInstance()->getPrimaryFramebufferObject()->texture()); + DependencyManager::get()->getPrimaryFramebufferObject()->release(); + glBindTexture(GL_TEXTURE_2D, DependencyManager::get()->getPrimaryFramebufferObject()->texture()); } // restore our normal viewport diff --git a/interface/src/renderer/AmbientOcclusionEffect.cpp b/interface/src/renderer/AmbientOcclusionEffect.cpp index 9ef0fa2d82..3354f715cb 100644 --- a/interface/src/renderer/AmbientOcclusionEffect.cpp +++ b/interface/src/renderer/AmbientOcclusionEffect.cpp @@ -98,7 +98,7 @@ void AmbientOcclusionEffect::render() { glDisable(GL_DEPTH_TEST); glDepthMask(GL_FALSE); - glBindTexture(GL_TEXTURE_2D, TextureCache::getInstance()->getPrimaryDepthTextureID()); + glBindTexture(GL_TEXTURE_2D, DependencyManager::get()->getPrimaryDepthTextureID()); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, _rotationTextureID); @@ -116,7 +116,7 @@ void AmbientOcclusionEffect::render() { glGetIntegerv(GL_VIEWPORT, viewport); const int VIEWPORT_X_INDEX = 0; const int VIEWPORT_WIDTH_INDEX = 2; - QOpenGLFramebufferObject* primaryFBO = TextureCache::getInstance()->getPrimaryFramebufferObject(); + QOpenGLFramebufferObject* primaryFBO = DependencyManager::get()->getPrimaryFramebufferObject(); float sMin = viewport[VIEWPORT_X_INDEX] / (float)primaryFBO->width(); float sWidth = viewport[VIEWPORT_WIDTH_INDEX] / (float)primaryFBO->width(); @@ -141,7 +141,7 @@ void AmbientOcclusionEffect::render() { glActiveTexture(GL_TEXTURE0); // now render secondary to primary with 4x4 blur - TextureCache::getInstance()->getPrimaryFramebufferObject()->bind(); + DependencyManager::get()->getPrimaryFramebufferObject()->bind(); glEnable(GL_BLEND); glBlendFuncSeparate(GL_ZERO, GL_SRC_COLOR, GL_ZERO, GL_ONE); diff --git a/interface/src/renderer/DeferredLightingEffect.cpp b/interface/src/renderer/DeferredLightingEffect.cpp index 42da3e0b08..facec197a7 100644 --- a/interface/src/renderer/DeferredLightingEffect.cpp +++ b/interface/src/renderer/DeferredLightingEffect.cpp @@ -37,7 +37,7 @@ void DeferredLightingEffect::init() { } void DeferredLightingEffect::bindSimpleProgram() { - TextureCache::getInstance()->setPrimaryDrawBuffers(true, true, true); + DependencyManager::get()->setPrimaryDrawBuffers(true, true, true); _simpleProgram.bind(); _simpleProgram.setUniformValue(_glowIntensityLocation, Application::getInstance()->getGlowEffect()->getIntensity()); glDisable(GL_BLEND); @@ -46,7 +46,7 @@ void DeferredLightingEffect::bindSimpleProgram() { void DeferredLightingEffect::releaseSimpleProgram() { glEnable(GL_BLEND); _simpleProgram.release(); - TextureCache::getInstance()->setPrimaryDrawBuffers(true, false, false); + DependencyManager::get()->setPrimaryDrawBuffers(true, false, false); } void DeferredLightingEffect::renderSolidSphere(float radius, int slices, int stacks) { @@ -117,15 +117,15 @@ void DeferredLightingEffect::addSpotLight(const glm::vec3& position, float radiu void DeferredLightingEffect::prepare() { // clear the normal and specular buffers - TextureCache::getInstance()->setPrimaryDrawBuffers(false, true, false); + DependencyManager::get()->setPrimaryDrawBuffers(false, true, false); glClear(GL_COLOR_BUFFER_BIT); - TextureCache::getInstance()->setPrimaryDrawBuffers(false, false, true); + DependencyManager::get()->setPrimaryDrawBuffers(false, false, true); // clearing to zero alpha for specular causes problems on my Nvidia card; clear to lowest non-zero value instead const float MAX_SPECULAR_EXPONENT = 128.0f; glClearColor(0.0f, 0.0f, 0.0f, 1.0f / MAX_SPECULAR_EXPONENT); glClear(GL_COLOR_BUFFER_BIT); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); - TextureCache::getInstance()->setPrimaryDrawBuffers(true, false, false); + DependencyManager::get()->setPrimaryDrawBuffers(true, false, false); } void DeferredLightingEffect::render() { @@ -138,7 +138,7 @@ void DeferredLightingEffect::render() { glDisable(GL_COLOR_MATERIAL); glDepthMask(false); - QOpenGLFramebufferObject* primaryFBO = TextureCache::getInstance()->getPrimaryFramebufferObject(); + QOpenGLFramebufferObject* primaryFBO = DependencyManager::get()->getPrimaryFramebufferObject(); primaryFBO->release(); QOpenGLFramebufferObject* freeFBO = Application::getInstance()->getGlowEffect()->getFreeFramebufferObject(); @@ -148,13 +148,13 @@ void DeferredLightingEffect::render() { glBindTexture(GL_TEXTURE_2D, primaryFBO->texture()); glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, TextureCache::getInstance()->getPrimaryNormalTextureID()); + glBindTexture(GL_TEXTURE_2D, DependencyManager::get()->getPrimaryNormalTextureID()); glActiveTexture(GL_TEXTURE2); - glBindTexture(GL_TEXTURE_2D, TextureCache::getInstance()->getPrimarySpecularTextureID()); + glBindTexture(GL_TEXTURE_2D, DependencyManager::get()->getPrimarySpecularTextureID()); glActiveTexture(GL_TEXTURE3); - glBindTexture(GL_TEXTURE_2D, TextureCache::getInstance()->getPrimaryDepthTextureID()); + glBindTexture(GL_TEXTURE_2D, DependencyManager::get()->getPrimaryDepthTextureID()); // get the viewport side (left, right, both) int viewport[4]; @@ -173,7 +173,7 @@ void DeferredLightingEffect::render() { bool shadowsEnabled = Menu::getInstance()->getShadowsEnabled(); if (shadowsEnabled) { glActiveTexture(GL_TEXTURE4); - glBindTexture(GL_TEXTURE_2D, TextureCache::getInstance()->getShadowDepthTextureID()); + glBindTexture(GL_TEXTURE_2D, DependencyManager::get()->getShadowDepthTextureID()); program = &_directionalLightShadowMap; locations = &_directionalLightShadowMapLocations; @@ -188,7 +188,7 @@ void DeferredLightingEffect::render() { program->bind(); } program->setUniformValue(locations->shadowScale, - 1.0f / TextureCache::getInstance()->getShadowFramebufferObject()->width()); + 1.0f / DependencyManager::get()->getShadowFramebufferObject()->width()); } else { program->bind(); diff --git a/interface/src/renderer/GeometryCache.cpp b/interface/src/renderer/GeometryCache.cpp index 5cb544135c..048d3d0444 100644 --- a/interface/src/renderer/GeometryCache.cpp +++ b/interface/src/renderer/GeometryCache.cpp @@ -712,19 +712,19 @@ void NetworkGeometry::setTextureWithNameToURL(const QString& name, const QUrl& u QSharedPointer matchingTexture = QSharedPointer(); if (part.diffuseTextureName == name) { part.diffuseTexture = - TextureCache::getInstance()->getTexture(url, DEFAULT_TEXTURE, + DependencyManager::get()->getTexture(url, DEFAULT_TEXTURE, _geometry.meshes[i].isEye, QByteArray()); part.diffuseTexture->setLoadPriorities(_loadPriorities); } else if (part.normalTextureName == name) { - part.normalTexture = TextureCache::getInstance()->getTexture(url, DEFAULT_TEXTURE, + part.normalTexture = DependencyManager::get()->getTexture(url, DEFAULT_TEXTURE, false, QByteArray()); part.normalTexture->setLoadPriorities(_loadPriorities); } else if (part.specularTextureName == name) { - part.specularTexture = TextureCache::getInstance()->getTexture(url, DEFAULT_TEXTURE, + part.specularTexture = DependencyManager::get()->getTexture(url, DEFAULT_TEXTURE, false, QByteArray()); part.specularTexture->setLoadPriorities(_loadPriorities); } else if (part.emissiveTextureName == name) { - part.emissiveTexture = TextureCache::getInstance()->getTexture(url, DEFAULT_TEXTURE, + part.emissiveTexture = DependencyManager::get()->getTexture(url, DEFAULT_TEXTURE, false, QByteArray()); part.emissiveTexture->setLoadPriorities(_loadPriorities); } @@ -925,28 +925,28 @@ void NetworkGeometry::setGeometry(const FBXGeometry& geometry) { foreach (const FBXMeshPart& part, mesh.parts) { NetworkMeshPart networkPart; if (!part.diffuseTexture.filename.isEmpty()) { - networkPart.diffuseTexture = TextureCache::getInstance()->getTexture( + networkPart.diffuseTexture = DependencyManager::get()->getTexture( _textureBase.resolved(QUrl(part.diffuseTexture.filename)), DEFAULT_TEXTURE, mesh.isEye, part.diffuseTexture.content); networkPart.diffuseTextureName = part.diffuseTexture.name; networkPart.diffuseTexture->setLoadPriorities(_loadPriorities); } if (!part.normalTexture.filename.isEmpty()) { - networkPart.normalTexture = TextureCache::getInstance()->getTexture( + networkPart.normalTexture = DependencyManager::get()->getTexture( _textureBase.resolved(QUrl(part.normalTexture.filename)), NORMAL_TEXTURE, false, part.normalTexture.content); networkPart.normalTextureName = part.normalTexture.name; networkPart.normalTexture->setLoadPriorities(_loadPriorities); } if (!part.specularTexture.filename.isEmpty()) { - networkPart.specularTexture = TextureCache::getInstance()->getTexture( + networkPart.specularTexture = DependencyManager::get()->getTexture( _textureBase.resolved(QUrl(part.specularTexture.filename)), SPECULAR_TEXTURE, false, part.specularTexture.content); networkPart.specularTextureName = part.specularTexture.name; networkPart.specularTexture->setLoadPriorities(_loadPriorities); } if (!part.emissiveTexture.filename.isEmpty()) { - networkPart.emissiveTexture = TextureCache::getInstance()->getTexture( + networkPart.emissiveTexture = DependencyManager::get()->getTexture( _textureBase.resolved(QUrl(part.emissiveTexture.filename)), EMISSIVE_TEXTURE, false, part.emissiveTexture.content); networkPart.emissiveTextureName = part.emissiveTexture.name; diff --git a/interface/src/renderer/GlowEffect.cpp b/interface/src/renderer/GlowEffect.cpp index 8a9d957234..e6bbdb2ba1 100644 --- a/interface/src/renderer/GlowEffect.cpp +++ b/interface/src/renderer/GlowEffect.cpp @@ -41,8 +41,8 @@ GlowEffect::~GlowEffect() { QOpenGLFramebufferObject* GlowEffect::getFreeFramebufferObject() const { return (_isOddFrame ? - TextureCache::getInstance()->getSecondaryFramebufferObject(): - TextureCache::getInstance()->getTertiaryFramebufferObject()); + DependencyManager::get()->getSecondaryFramebufferObject(): + DependencyManager::get()->getTertiaryFramebufferObject()); } static ProgramObject* createProgram(const QString& name) { @@ -88,7 +88,7 @@ void GlowEffect::init() { } void GlowEffect::prepare() { - TextureCache::getInstance()->getPrimaryFramebufferObject()->bind(); + DependencyManager::get()->getPrimaryFramebufferObject()->bind(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); _isEmpty = true; @@ -122,7 +122,7 @@ static void maybeRelease(QOpenGLFramebufferObject* fbo) { QOpenGLFramebufferObject* GlowEffect::render(bool toTexture) { PerformanceTimer perfTimer("glowEffect"); - QOpenGLFramebufferObject* primaryFBO = TextureCache::getInstance()->getPrimaryFramebufferObject(); + QOpenGLFramebufferObject* primaryFBO = DependencyManager::get()->getPrimaryFramebufferObject(); primaryFBO->release(); glBindTexture(GL_TEXTURE_2D, primaryFBO->texture()); @@ -138,7 +138,7 @@ QOpenGLFramebufferObject* GlowEffect::render(bool toTexture) { glDepthMask(GL_FALSE); QOpenGLFramebufferObject* destFBO = toTexture ? - TextureCache::getInstance()->getSecondaryFramebufferObject() : NULL; + DependencyManager::get()->getSecondaryFramebufferObject() : NULL; if (!Menu::getInstance()->isOptionChecked(MenuOption::EnableGlowEffect) || _isEmpty) { // copy the primary to the screen if (destFBO && QOpenGLFramebufferObject::hasOpenGLFramebufferBlit()) { @@ -160,9 +160,9 @@ QOpenGLFramebufferObject* GlowEffect::render(bool toTexture) { } else { // diffuse into the secondary/tertiary (alternating between frames) QOpenGLFramebufferObject* oldDiffusedFBO = - TextureCache::getInstance()->getSecondaryFramebufferObject(); + DependencyManager::get()->getSecondaryFramebufferObject(); QOpenGLFramebufferObject* newDiffusedFBO = - TextureCache::getInstance()->getTertiaryFramebufferObject(); + DependencyManager::get()->getTertiaryFramebufferObject(); if (_isOddFrame) { qSwap(oldDiffusedFBO, newDiffusedFBO); } diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 45c80852ad..7004b277ca 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -749,7 +749,7 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) { } - /*TextureCache::getInstance()->setPrimaryDrawBuffers( + /*DependencyManager::get()->setPrimaryDrawBuffers( mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE, mode == DEFAULT_RENDER_MODE || mode == NORMAL_RENDER_MODE, mode == DEFAULT_RENDER_MODE); @@ -789,7 +789,7 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) { opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, true, false, args); // render translucent meshes afterwards - //TextureCache::getInstance()->setPrimaryDrawBuffers(false, true, true); + //DependencyManager::get()->setPrimaryDrawBuffers(false, true, true); { GLenum buffers[2]; int bufferCount = 0; @@ -814,7 +814,7 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) { GLBATCH(glDepthMask)(false); GLBATCH(glDepthFunc)(GL_LEQUAL); - //TextureCache::getInstance()->setPrimaryDrawBuffers(true); + //DependencyManager::get()->setPrimaryDrawBuffers(true); { GLenum buffers[1]; int bufferCount = 0; @@ -1705,7 +1705,7 @@ void Model::endScene(RenderMode mode, RenderArgs* args) { } - /*TextureCache::getInstance()->setPrimaryDrawBuffers( + /*DependencyManager::get()->setPrimaryDrawBuffers( mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE, mode == DEFAULT_RENDER_MODE || mode == NORMAL_RENDER_MODE, mode == DEFAULT_RENDER_MODE); @@ -1745,7 +1745,7 @@ void Model::endScene(RenderMode mode, RenderArgs* args) { opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, true, false, args); // render translucent meshes afterwards - //TextureCache::getInstance()->setPrimaryDrawBuffers(false, true, true); + //DependencyManager::get()->setPrimaryDrawBuffers(false, true, true); { GLenum buffers[2]; int bufferCount = 0; @@ -1770,7 +1770,7 @@ void Model::endScene(RenderMode mode, RenderArgs* args) { GLBATCH(glDepthMask)(false); GLBATCH(glDepthFunc)(GL_LEQUAL); - //TextureCache::getInstance()->setPrimaryDrawBuffers(true); + //DependencyManager::get()->setPrimaryDrawBuffers(true); { GLenum buffers[1]; int bufferCount = 0; @@ -2446,7 +2446,7 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod if (showDiffuse && diffuseMap) { GLBATCH(glBindTexture)(GL_TEXTURE_2D, diffuseMap->getID()); } else { - GLBATCH(glBindTexture)(GL_TEXTURE_2D, TextureCache::getInstance()->getWhiteTextureID()); + GLBATCH(glBindTexture)(GL_TEXTURE_2D, DependencyManager::get()->getWhiteTextureID()); } if (locations->texcoordMatrices >= 0) { @@ -2464,7 +2464,7 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod GLBATCH(glActiveTexture)(GL_TEXTURE1); Texture* normalMap = networkPart.normalTexture.data(); GLBATCH(glBindTexture)(GL_TEXTURE_2D, !normalMap ? - TextureCache::getInstance()->getBlueTextureID() : normalMap->getID()); + DependencyManager::get()->getBlueTextureID() : normalMap->getID()); GLBATCH(glActiveTexture)(GL_TEXTURE0); } @@ -2472,7 +2472,7 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod GLBATCH(glActiveTexture)(GL_TEXTURE0 + locations->specularTextureUnit); Texture* specularMap = networkPart.specularTexture.data(); GLBATCH(glBindTexture)(GL_TEXTURE_2D, !specularMap ? - TextureCache::getInstance()->getWhiteTextureID() : specularMap->getID()); + DependencyManager::get()->getWhiteTextureID() : specularMap->getID()); GLBATCH(glActiveTexture)(GL_TEXTURE0); } @@ -2493,7 +2493,7 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod GLBATCH(glActiveTexture)(GL_TEXTURE0 + locations->emissiveTextureUnit); Texture* emissiveMap = networkPart.emissiveTexture.data(); GLBATCH(glBindTexture)(GL_TEXTURE_2D, !emissiveMap ? - TextureCache::getInstance()->getWhiteTextureID() : emissiveMap->getID()); + DependencyManager::get()->getWhiteTextureID() : emissiveMap->getID()); GLBATCH(glActiveTexture)(GL_TEXTURE0); } diff --git a/interface/src/renderer/TextureCache.cpp b/interface/src/renderer/TextureCache.cpp index 4d246a4c9c..123a8a5384 100644 --- a/interface/src/renderer/TextureCache.cpp +++ b/interface/src/renderer/TextureCache.cpp @@ -25,12 +25,6 @@ #include "TextureCache.h" -TextureCache* TextureCache::getInstance() { - static TextureCache instance; - return &instance; -} - - TextureCache::TextureCache() : _permutationNormalTextureID(0), _whiteTextureID(0), diff --git a/interface/src/renderer/TextureCache.h b/interface/src/renderer/TextureCache.h index 3cbfaced49..2bdfda3217 100644 --- a/interface/src/renderer/TextureCache.h +++ b/interface/src/renderer/TextureCache.h @@ -16,6 +16,7 @@ #include #include +#include #include #include "InterfaceConfig.h" @@ -29,16 +30,11 @@ typedef QSharedPointer NetworkTexturePointer; enum TextureType { DEFAULT_TEXTURE, NORMAL_TEXTURE, SPECULAR_TEXTURE, EMISSIVE_TEXTURE, SPLAT_TEXTURE }; /// Stores cached textures, including render-to-texture targets. -class TextureCache : public ResourceCache { +class TextureCache : public ResourceCache, public DependencyManager::Dependency { Q_OBJECT public: - static TextureCache* getInstance(); - - TextureCache(); - virtual ~TextureCache(); - void associateWithWidget(QGLWidget* widget); /// Sets the desired texture resolution for the framebuffer objects. @@ -98,7 +94,9 @@ protected: const QSharedPointer& fallback, bool delayLoad, const void* extra); private: - + TextureCache(); + virtual ~TextureCache(); + friend class DependencyManager; friend class DilatableNetworkTexture; QOpenGLFramebufferObject* createFramebufferObject(); diff --git a/interface/src/ui/MetavoxelEditor.cpp b/interface/src/ui/MetavoxelEditor.cpp index dde181c571..1ca81f3d95 100644 --- a/interface/src/ui/MetavoxelEditor.cpp +++ b/interface/src/ui/MetavoxelEditor.cpp @@ -916,7 +916,7 @@ void MaterialControl::updateTexture() { _texture.clear(); return; } - _texture = TextureCache::getInstance()->getTexture(material->getDiffuse(), SPLAT_TEXTURE); + _texture = DependencyManager::get()->getTexture(material->getDiffuse(), SPLAT_TEXTURE); if (_texture) { if (_texture->isLoaded()) { textureLoaded(); diff --git a/interface/src/voxels/VoxelSystem.cpp b/interface/src/voxels/VoxelSystem.cpp index 6fd477d8f3..357bfe9c3e 100644 --- a/interface/src/voxels/VoxelSystem.cpp +++ b/interface/src/voxels/VoxelSystem.cpp @@ -1170,7 +1170,7 @@ void VoxelSystem::render() { void VoxelSystem::applyScaleAndBindProgram(bool texture) { if (texture) { bindPerlinModulateProgram(); - glBindTexture(GL_TEXTURE_2D, TextureCache::getInstance()->getPermutationNormalTextureID()); + glBindTexture(GL_TEXTURE_2D, DependencyManager::get()->getPermutationNormalTextureID()); } else { _program.bind(); } @@ -1178,7 +1178,7 @@ void VoxelSystem::applyScaleAndBindProgram(bool texture) { glPushMatrix(); glScalef(_treeScale, _treeScale, _treeScale); - TextureCache::getInstance()->setPrimaryDrawBuffers(true, true); + DependencyManager::get()->setPrimaryDrawBuffers(true, true); } void VoxelSystem::removeScaleAndReleaseProgram(bool texture) { @@ -1192,7 +1192,7 @@ void VoxelSystem::removeScaleAndReleaseProgram(bool texture) { _program.release(); } - TextureCache::getInstance()->setPrimaryDrawBuffers(true, false); + DependencyManager::get()->setPrimaryDrawBuffers(true, false); } int VoxelSystem::_nodeCount = 0; From e0a017e963fd290822b7bef9c8360e2d5ec1033f Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 15 Dec 2014 10:49:34 -0800 Subject: [PATCH 392/502] make GeometryCache work with DependancyManager --- interface/src/Application.cpp | 2 +- interface/src/Environment.cpp | 2 +- interface/src/ModelUploader.cpp | 2 +- interface/src/Util.cpp | 8 ++++---- interface/src/avatar/Avatar.cpp | 4 ++-- interface/src/avatar/Hand.cpp | 4 ++-- interface/src/avatar/MyAvatar.cpp | 4 ++-- interface/src/avatar/SkeletonModel.cpp | 14 +++++++------- interface/src/renderer/DeferredLightingEffect.cpp | 8 ++++---- interface/src/renderer/GeometryCache.cpp | 5 ----- interface/src/renderer/GeometryCache.h | 12 +++++------- interface/src/renderer/Model.cpp | 2 +- interface/src/ui/MetavoxelEditor.cpp | 2 +- interface/src/ui/overlays/Grid3DOverlay.cpp | 4 ++-- interface/src/ui/overlays/Sphere3DOverlay.cpp | 2 +- 15 files changed, 34 insertions(+), 41 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 105e3e087c..766424ef4b 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3080,7 +3080,7 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly, RenderAr // draw a red sphere float originSphereRadius = 0.05f; glColor3f(1,0,0); - GeometryCache::getInstance()->renderSphere(originSphereRadius, 15, 15); + DependencyManager::get()->renderSphere(originSphereRadius, 15, 15); // Draw voxels if (Menu::getInstance()->isOptionChecked(MenuOption::Voxels)) { diff --git a/interface/src/Environment.cpp b/interface/src/Environment.cpp index a754b63eec..fa8f18ac3f 100644 --- a/interface/src/Environment.cpp +++ b/interface/src/Environment.cpp @@ -261,7 +261,7 @@ void Environment::renderAtmosphere(Camera& camera, const EnvironmentData& data) glDepthMask(GL_FALSE); glDisable(GL_DEPTH_TEST); - GeometryCache::getInstance()->renderSphere(1.0f, 100, 50); //Draw a unit sphere + DependencyManager::get()->renderSphere(1.0f, 100, 50); //Draw a unit sphere glDepthMask(GL_TRUE); program->release(); diff --git a/interface/src/ModelUploader.cpp b/interface/src/ModelUploader.cpp index c3b6ba74c3..b22457f847 100644 --- a/interface/src/ModelUploader.cpp +++ b/interface/src/ModelUploader.cpp @@ -471,7 +471,7 @@ void ModelUploader::processCheck() { QString("ModelUploader::processCheck()"), QString("Your model is now available in the browser."), QMessageBox::Ok); - GeometryCache::getInstance()->refresh(_url); + DependencyManager::get()->refresh(_url); foreach (const QByteArray& filename, _textureFilenames) { DependencyManager::get()->refresh(_textureBase + filename); } diff --git a/interface/src/Util.cpp b/interface/src/Util.cpp index 256e437e21..d93c8a26ad 100644 --- a/interface/src/Util.cpp +++ b/interface/src/Util.cpp @@ -71,22 +71,22 @@ void renderWorldBox() { glPushMatrix(); glTranslatef(MARKER_DISTANCE, 0, 0); glColor3fv(red); - GeometryCache::getInstance()->renderSphere(MARKER_RADIUS, 10, 10); + DependencyManager::get()->renderSphere(MARKER_RADIUS, 10, 10); glPopMatrix(); glPushMatrix(); glTranslatef(0, MARKER_DISTANCE, 0); glColor3fv(green); - GeometryCache::getInstance()->renderSphere(MARKER_RADIUS, 10, 10); + DependencyManager::get()->renderSphere(MARKER_RADIUS, 10, 10); glPopMatrix(); glPushMatrix(); glTranslatef(0, 0, MARKER_DISTANCE); glColor3fv(blue); - GeometryCache::getInstance()->renderSphere(MARKER_RADIUS, 10, 10); + DependencyManager::get()->renderSphere(MARKER_RADIUS, 10, 10); glPopMatrix(); glPushMatrix(); glColor3fv(gray); glTranslatef(MARKER_DISTANCE, 0, MARKER_DISTANCE); - GeometryCache::getInstance()->renderSphere(MARKER_RADIUS, 10, 10); + DependencyManager::get()->renderSphere(MARKER_RADIUS, 10, 10); glPopMatrix(); } diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 0edf59290f..49a6f436df 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -394,7 +394,7 @@ void Avatar::render(const glm::vec3& cameraPosition, RenderMode renderMode, bool } else { glTranslatef(_position.x, getDisplayNamePosition().y + LOOK_AT_INDICATOR_OFFSET, _position.z); } - GeometryCache::getInstance()->renderSphere(LOOK_AT_INDICATOR_RADIUS, 15, 15); + DependencyManager::get()->renderSphere(LOOK_AT_INDICATOR_RADIUS, 15, 15); glPopMatrix(); } } @@ -422,7 +422,7 @@ void Avatar::render(const glm::vec3& cameraPosition, RenderMode renderMode, bool glPushMatrix(); glTranslatef(_position.x, _position.y, _position.z); glScalef(height, height, height); - GeometryCache::getInstance()->renderSphere(sphereRadius, 15, 15); + DependencyManager::get()->renderSphere(sphereRadius, 15, 15); glPopMatrix(); } diff --git a/interface/src/avatar/Hand.cpp b/interface/src/avatar/Hand.cpp index fef4ac2fac..9d1ee52fde 100644 --- a/interface/src/avatar/Hand.cpp +++ b/interface/src/avatar/Hand.cpp @@ -114,7 +114,7 @@ void Hand::render(bool isMine, Model::RenderMode renderMode) { glPushMatrix(); glTranslatef(position.x, position.y, position.z); glColor3f(0.0f, 1.0f, 0.0f); - GeometryCache::getInstance()->renderSphere(PALM_COLLISION_RADIUS * _owningAvatar->getScale(), 10, 10); + DependencyManager::get()->renderSphere(PALM_COLLISION_RADIUS * _owningAvatar->getScale(), 10, 10); glPopMatrix(); } } @@ -179,7 +179,7 @@ void Hand::renderHandTargets(bool isMine) { Avatar::renderJointConnectingCone(root, offsetFromPalm, PALM_DISK_RADIUS, 0.0f); glPushMatrix(); glTranslatef(root.x, root.y, root.z); - GeometryCache::getInstance()->renderSphere(PALM_BALL_RADIUS, 20.0f, 20.0f); + DependencyManager::get()->renderSphere(PALM_BALL_RADIUS, 20.0f, 20.0f); glPopMatrix(); } } diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 255e79ebcd..057b1f1fc6 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -394,7 +394,7 @@ void MyAvatar::renderDebugBodyPoints() { glPushMatrix(); glColor4f(0, 1, 0, .5f); glTranslatef(position.x, position.y, position.z); - GeometryCache::getInstance()->renderSphere(0.2f, 10.0f, 10.0f); + DependencyManager::get()->renderSphere(0.2f, 10.0f, 10.0f); glPopMatrix(); // Head Sphere @@ -402,7 +402,7 @@ void MyAvatar::renderDebugBodyPoints() { glPushMatrix(); glColor4f(0, 1, 0, .5f); glTranslatef(position.x, position.y, position.z); - GeometryCache::getInstance()->renderSphere(0.15f, 10.0f, 10.0f); + DependencyManager::get()->renderSphere(0.15f, 10.0f, 10.0f); glPopMatrix(); } diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 9bc2b627be..f71c9318aa 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -561,9 +561,9 @@ void SkeletonModel::renderRagdoll() { glTranslatef(position.x, position.y, position.z); // draw each point as a yellow hexagon with black border glColor4f(0.0f, 0.0f, 0.0f, alpha); - GeometryCache::getInstance()->renderSphere(radius2, BALL_SUBDIVISIONS, BALL_SUBDIVISIONS); + DependencyManager::get()->renderSphere(radius2, BALL_SUBDIVISIONS, BALL_SUBDIVISIONS); glColor4f(1.0f, 1.0f, 0.0f, alpha); - GeometryCache::getInstance()->renderSphere(radius1, BALL_SUBDIVISIONS, BALL_SUBDIVISIONS); + DependencyManager::get()->renderSphere(radius1, BALL_SUBDIVISIONS, BALL_SUBDIVISIONS); glPopMatrix(); } glPopMatrix(); @@ -913,7 +913,7 @@ void SkeletonModel::renderBoundingCollisionShapes(float alpha) { endPoint = endPoint - _translation; glTranslatef(endPoint.x, endPoint.y, endPoint.z); glColor4f(0.6f, 0.6f, 0.8f, alpha); - GeometryCache::getInstance()->renderSphere(_boundingShape.getRadius(), BALL_SUBDIVISIONS, BALL_SUBDIVISIONS); + DependencyManager::get()->renderSphere(_boundingShape.getRadius(), BALL_SUBDIVISIONS, BALL_SUBDIVISIONS); // draw a yellow sphere at the capsule startpoint glm::vec3 startPoint; @@ -922,7 +922,7 @@ void SkeletonModel::renderBoundingCollisionShapes(float alpha) { glm::vec3 axis = endPoint - startPoint; glTranslatef(-axis.x, -axis.y, -axis.z); glColor4f(0.8f, 0.8f, 0.6f, alpha); - GeometryCache::getInstance()->renderSphere(_boundingShape.getRadius(), BALL_SUBDIVISIONS, BALL_SUBDIVISIONS); + DependencyManager::get()->renderSphere(_boundingShape.getRadius(), BALL_SUBDIVISIONS, BALL_SUBDIVISIONS); // draw a green cylinder between the two points glm::vec3 origin(0.0f); @@ -955,7 +955,7 @@ void SkeletonModel::renderJointCollisionShapes(float alpha) { glTranslatef(position.x, position.y, position.z); // draw a grey sphere at shape position glColor4f(0.75f, 0.75f, 0.75f, alpha); - GeometryCache::getInstance()->renderSphere(shape->getBoundingRadius(), BALL_SUBDIVISIONS, BALL_SUBDIVISIONS); + DependencyManager::get()->renderSphere(shape->getBoundingRadius(), BALL_SUBDIVISIONS, BALL_SUBDIVISIONS); } else if (shape->getType() == CAPSULE_SHAPE) { CapsuleShape* capsule = static_cast(shape); @@ -965,7 +965,7 @@ void SkeletonModel::renderJointCollisionShapes(float alpha) { endPoint = endPoint - simulationTranslation; glTranslatef(endPoint.x, endPoint.y, endPoint.z); glColor4f(0.6f, 0.6f, 0.8f, alpha); - GeometryCache::getInstance()->renderSphere(capsule->getRadius(), BALL_SUBDIVISIONS, BALL_SUBDIVISIONS); + DependencyManager::get()->renderSphere(capsule->getRadius(), BALL_SUBDIVISIONS, BALL_SUBDIVISIONS); // draw a yellow sphere at the capsule startpoint glm::vec3 startPoint; @@ -974,7 +974,7 @@ void SkeletonModel::renderJointCollisionShapes(float alpha) { glm::vec3 axis = endPoint - startPoint; glTranslatef(-axis.x, -axis.y, -axis.z); glColor4f(0.8f, 0.8f, 0.6f, alpha); - GeometryCache::getInstance()->renderSphere(capsule->getRadius(), BALL_SUBDIVISIONS, BALL_SUBDIVISIONS); + DependencyManager::get()->renderSphere(capsule->getRadius(), BALL_SUBDIVISIONS, BALL_SUBDIVISIONS); // draw a green cylinder between the two points glm::vec3 origin(0.0f); diff --git a/interface/src/renderer/DeferredLightingEffect.cpp b/interface/src/renderer/DeferredLightingEffect.cpp index facec197a7..75af4647e4 100644 --- a/interface/src/renderer/DeferredLightingEffect.cpp +++ b/interface/src/renderer/DeferredLightingEffect.cpp @@ -51,7 +51,7 @@ void DeferredLightingEffect::releaseSimpleProgram() { void DeferredLightingEffect::renderSolidSphere(float radius, int slices, int stacks) { bindSimpleProgram(); - GeometryCache::getInstance()->renderSphere(radius, slices, stacks); + DependencyManager::get()->renderSphere(radius, slices, stacks); releaseSimpleProgram(); } @@ -75,7 +75,7 @@ void DeferredLightingEffect::renderWireCube(float size) { void DeferredLightingEffect::renderSolidCone(float base, float height, int slices, int stacks) { bindSimpleProgram(); - GeometryCache::getInstance()->renderCone(base, height, slices, stacks); + DependencyManager::get()->renderCone(base, height, slices, stacks); releaseSimpleProgram(); } @@ -270,7 +270,7 @@ void DeferredLightingEffect::render() { } else { glTranslatef(light.position.x, light.position.y, light.position.z); - GeometryCache::getInstance()->renderSphere(expandedRadius, 32, 32); + DependencyManager::get()->renderSphere(expandedRadius, 32, 32); } glPopMatrix(); @@ -323,7 +323,7 @@ void DeferredLightingEffect::render() { glm::vec3 axis = glm::axis(spotRotation); glRotatef(glm::degrees(glm::angle(spotRotation)), axis.x, axis.y, axis.z); glTranslatef(0.0f, 0.0f, -light.radius * (1.0f + SCALE_EXPANSION * 0.5f)); - GeometryCache::getInstance()->renderCone(expandedRadius * glm::tan(light.cutoff), + DependencyManager::get()->renderCone(expandedRadius * glm::tan(light.cutoff), expandedRadius, 32, 1); } diff --git a/interface/src/renderer/GeometryCache.cpp b/interface/src/renderer/GeometryCache.cpp index 048d3d0444..534911ff46 100644 --- a/interface/src/renderer/GeometryCache.cpp +++ b/interface/src/renderer/GeometryCache.cpp @@ -23,11 +23,6 @@ #include "GeometryCache.h" #include "TextureCache.h" -GeometryCache* GeometryCache::getInstance() { - static GeometryCache instance; - return &instance; -} - GeometryCache::GeometryCache() { } diff --git a/interface/src/renderer/GeometryCache.h b/interface/src/renderer/GeometryCache.h index 1eb9dcbc6a..2d813ece09 100644 --- a/interface/src/renderer/GeometryCache.h +++ b/interface/src/renderer/GeometryCache.h @@ -18,6 +18,7 @@ #include #include +#include #include #include @@ -31,16 +32,10 @@ class NetworkMesh; class NetworkTexture; /// Stores cached geometry. -class GeometryCache : public ResourceCache { +class GeometryCache : public ResourceCache, public DependencyManager::Dependency { Q_OBJECT public: - - static GeometryCache* getInstance(); - - GeometryCache(); - virtual ~GeometryCache(); - void renderHemisphere(int slices, int stacks); void renderSphere(float radius, int slices, int stacks); void renderSquare(int xDivisions, int yDivisions); @@ -59,6 +54,9 @@ protected: const QSharedPointer& fallback, bool delayLoad, const void* extra); private: + GeometryCache(); + virtual ~GeometryCache(); + friend class DependencyManager; typedef QPair IntPair; typedef QPair VerticesIndices; diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 7004b277ca..0ab3f82fda 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -997,7 +997,7 @@ void Model::setURL(const QUrl& url, const QUrl& fallback, bool retainCurrent, bo _url = url; // if so instructed, keep the current geometry until the new one is loaded - _nextBaseGeometry = _nextGeometry = GeometryCache::getInstance()->getGeometry(url, fallback, delayLoad); + _nextBaseGeometry = _nextGeometry = DependencyManager::get()->getGeometry(url, fallback, delayLoad); _nextLODHysteresis = NetworkGeometry::NO_HYSTERESIS; if (!retainCurrent || !isActive() || _nextGeometry->isLoaded()) { applyNextGeometry(); diff --git a/interface/src/ui/MetavoxelEditor.cpp b/interface/src/ui/MetavoxelEditor.cpp index 1ca81f3d95..158532e19a 100644 --- a/interface/src/ui/MetavoxelEditor.cpp +++ b/interface/src/ui/MetavoxelEditor.cpp @@ -353,7 +353,7 @@ void MetavoxelEditor::render() { _gridProgram.bind(); - GeometryCache::getInstance()->renderGrid(GRID_DIVISIONS, GRID_DIVISIONS); + DependencyManager::get()->renderGrid(GRID_DIVISIONS, GRID_DIVISIONS); _gridProgram.release(); diff --git a/interface/src/ui/overlays/Grid3DOverlay.cpp b/interface/src/ui/overlays/Grid3DOverlay.cpp index 67dd0b8e21..d1086ae534 100644 --- a/interface/src/ui/overlays/Grid3DOverlay.cpp +++ b/interface/src/ui/overlays/Grid3DOverlay.cpp @@ -87,7 +87,7 @@ void Grid3DOverlay::render(RenderArgs* args) { float scale = MINOR_GRID_DIVISIONS * spacing; glScalef(scale, scale, scale); - GeometryCache::getInstance()->renderGrid(MINOR_GRID_DIVISIONS, MINOR_GRID_DIVISIONS); + DependencyManager::get()->renderGrid(MINOR_GRID_DIVISIONS, MINOR_GRID_DIVISIONS); } glPopMatrix(); @@ -102,7 +102,7 @@ void Grid3DOverlay::render(RenderArgs* args) { float scale = MAJOR_GRID_DIVISIONS * spacing; glScalef(scale, scale, scale); - GeometryCache::getInstance()->renderGrid(MAJOR_GRID_DIVISIONS, MAJOR_GRID_DIVISIONS); + DependencyManager::get()->renderGrid(MAJOR_GRID_DIVISIONS, MAJOR_GRID_DIVISIONS); } glPopMatrix(); diff --git a/interface/src/ui/overlays/Sphere3DOverlay.cpp b/interface/src/ui/overlays/Sphere3DOverlay.cpp index b9aeb5145a..ded1b3917c 100644 --- a/interface/src/ui/overlays/Sphere3DOverlay.cpp +++ b/interface/src/ui/overlays/Sphere3DOverlay.cpp @@ -63,7 +63,7 @@ void Sphere3DOverlay::render(RenderArgs* args) { glScalef(dimensions.x, dimensions.y, dimensions.z); //Application::getInstance()->getDeferredLightingEffect()->renderSolidCube(1.0f); if (_isSolid) { - GeometryCache::getInstance()->renderSphere(1.0f, SLICES, SLICES); + DependencyManager::get()->renderSphere(1.0f, SLICES, SLICES); } else { glutWireSphere(1.0f, SLICES, SLICES); } From 049cb25f07c3c4d52f5ef9238f5ae36956c9227e Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 15 Dec 2014 10:56:29 -0800 Subject: [PATCH 393/502] make ModelBlender work with DependancyManager --- interface/src/renderer/Model.cpp | 9 ++------- interface/src/renderer/Model.h | 13 ++++++------- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 0ab3f82fda..62170efeed 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -1149,7 +1149,7 @@ void Blender::run() { } } // post the result to the geometry cache, which will dispatch to the model if still alive - QMetaObject::invokeMethod(ModelBlender::getInstance(), "setBlendedVertices", + QMetaObject::invokeMethod(DependencyManager::get(), "setBlendedVertices", Q_ARG(const QPointer&, _model), Q_ARG(int, _blendNumber), Q_ARG(const QWeakPointer&, _geometry), Q_ARG(const QVector&, vertices), Q_ARG(const QVector&, normals)); @@ -1312,7 +1312,7 @@ void Model::simulateInternal(float deltaTime) { // post the blender if we're not currently waiting for one to finish if (geometry.hasBlendedMeshes() && _blendshapeCoefficients != _blendedBlendshapeCoefficients) { _blendedBlendshapeCoefficients = _blendshapeCoefficients; - ModelBlender::getInstance()->noteRequiresBlend(this); + DependencyManager::get()->noteRequiresBlend(this); } } @@ -2545,11 +2545,6 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod return meshPartsRendered; } -ModelBlender* ModelBlender::getInstance() { - static ModelBlender instance; - return &instance; -} - ModelBlender::ModelBlender() : _pendingBlenders(0) { } diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index e95b2472ba..9b609de1d0 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -19,6 +19,7 @@ #include "Transform.h" #include #include +#include #include #include @@ -460,17 +461,11 @@ Q_DECLARE_METATYPE(QWeakPointer) Q_DECLARE_METATYPE(QVector) /// Handle management of pending models that need blending -class ModelBlender : public QObject { +class ModelBlender : public QObject, public DependencyManager::Dependency { Q_OBJECT public: - static ModelBlender* getInstance(); - - ModelBlender(); - virtual ~ModelBlender(); - - /// Adds the specified model to the list requiring vertex blends. void noteRequiresBlend(Model* model); @@ -479,6 +474,10 @@ public slots: const QVector& vertices, const QVector& normals); private: + ModelBlender(); + virtual ~ModelBlender(); + friend class DependencyManager; + QList > _modelsRequiringBlends; int _pendingBlenders; }; From 25df784f433c49c8c51df5c2e0b4f13c0470563d Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 15 Dec 2014 10:56:42 -0800 Subject: [PATCH 394/502] Headers cleanup --- interface/src/Application.cpp | 1 + interface/src/Application.h | 20 ++++--------------- interface/src/GLCanvas.cpp | 2 +- interface/src/Menu.cpp | 1 + interface/src/entities/EntityTreeRenderer.h | 3 +++ .../scripting/WindowScriptingInterface.cpp | 1 + interface/src/ui/AddressBarDialog.cpp | 1 + interface/src/ui/AnimationsDialog.cpp | 1 + interface/src/ui/AttachmentsDialog.cpp | 1 + interface/src/ui/ChatWindow.cpp | 4 +++- interface/src/ui/HMDToolsDialog.cpp | 1 + interface/src/ui/MetavoxelEditor.cpp | 1 + interface/src/ui/PreferencesDialog.cpp | 1 + interface/src/ui/ToolWindow.cpp | 1 + 14 files changed, 21 insertions(+), 18 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index fbe55071e4..d0abc47b85 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -61,6 +61,7 @@ #include #include #include +#include #include #include #include diff --git a/interface/src/Application.h b/interface/src/Application.h index 833f1374ce..c2136f1c57 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -12,35 +12,21 @@ #ifndef hifi_Application_h #define hifi_Application_h -#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 "MainWindow.h" #include "Audio.h" #include "Camera.h" #include "DatagramProcessor.h" @@ -89,17 +75,19 @@ #include "UndoStackScriptingInterface.h" -class QAction; -class QActionGroup; class QGLWidget; class QKeyEvent; class QMouseEvent; class QSettings; +class QSystemTrayIcon; +class QTouchEvent; class QWheelEvent; class FaceTracker; +class MainWindow; class Node; class ProgramObject; +class ScriptEngine; static const float NODE_ADDED_RED = 0.0f; static const float NODE_ADDED_GREEN = 1.0f; diff --git a/interface/src/GLCanvas.cpp b/interface/src/GLCanvas.cpp index cec3f62b7d..10090de51a 100644 --- a/interface/src/GLCanvas.cpp +++ b/interface/src/GLCanvas.cpp @@ -9,13 +9,13 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include #include #include #include #include "Application.h" #include "GLCanvas.h" +#include "MainWindow.h" #include "devices/OculusManager.h" const int MSECS_PER_FRAME_WHEN_THROTTLED = 66; diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 6c2c3966fc..14327bd51a 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include diff --git a/interface/src/entities/EntityTreeRenderer.h b/interface/src/entities/EntityTreeRenderer.h index a8695db36d..3d79358536 100644 --- a/interface/src/entities/EntityTreeRenderer.h +++ b/interface/src/entities/EntityTreeRenderer.h @@ -17,6 +17,7 @@ #include #include // for RayToEntityIntersectionResult +#include #include #include #include @@ -27,6 +28,8 @@ #include "renderer/Model.h" +class ScriptEngine; + class EntityScriptDetails { public: QString scriptText; diff --git a/interface/src/scripting/WindowScriptingInterface.cpp b/interface/src/scripting/WindowScriptingInterface.cpp index 591ae87560..d69b1d0ba1 100644 --- a/interface/src/scripting/WindowScriptingInterface.cpp +++ b/interface/src/scripting/WindowScriptingInterface.cpp @@ -17,6 +17,7 @@ #include #include "Application.h" +#include "MainWindow.h" #include "Menu.h" #include "ui/ModelsBrowser.h" diff --git a/interface/src/ui/AddressBarDialog.cpp b/interface/src/ui/AddressBarDialog.cpp index dbc29be71a..3fc915e073 100644 --- a/interface/src/ui/AddressBarDialog.cpp +++ b/interface/src/ui/AddressBarDialog.cpp @@ -12,6 +12,7 @@ #include "AddressBarDialog.h" #include "AddressManager.h" #include "Application.h" +#include "MainWindow.h" const QString ADDRESSBAR_GO_BUTTON_ICON = "images/address-bar-submit.svg"; const QString ADDRESSBAR_GO_BUTTON_ACTIVE_ICON = "images/address-bar-submit-active.svg"; diff --git a/interface/src/ui/AnimationsDialog.cpp b/interface/src/ui/AnimationsDialog.cpp index c5ab826ebb..65e7cadc77 100644 --- a/interface/src/ui/AnimationsDialog.cpp +++ b/interface/src/ui/AnimationsDialog.cpp @@ -22,6 +22,7 @@ #include "AnimationsDialog.h" #include "Application.h" +#include "MainWindow.h" AnimationsDialog::AnimationsDialog() : QDialog(Application::getInstance()->getWindow()) { diff --git a/interface/src/ui/AttachmentsDialog.cpp b/interface/src/ui/AttachmentsDialog.cpp index 44dd2452e6..1209af580d 100644 --- a/interface/src/ui/AttachmentsDialog.cpp +++ b/interface/src/ui/AttachmentsDialog.cpp @@ -20,6 +20,7 @@ #include "Application.h" #include "AttachmentsDialog.h" +#include "MainWindow.h" AttachmentsDialog::AttachmentsDialog() : QDialog(Application::getInstance()->getWindow()) { diff --git a/interface/src/ui/ChatWindow.cpp b/interface/src/ui/ChatWindow.cpp index 747b4ae68d..61ce9f88fc 100644 --- a/interface/src/ui/ChatWindow.cpp +++ b/interface/src/ui/ChatWindow.cpp @@ -16,6 +16,8 @@ #include #include #include +#include "qtimespan.h" + #include #include @@ -23,7 +25,7 @@ #include "Application.h" #include "ChatMessageArea.h" #include "FlowLayout.h" -#include "qtimespan.h" +#include "MainWindow.h" #include "UIUtil.h" #include "XmppClient.h" diff --git a/interface/src/ui/HMDToolsDialog.cpp b/interface/src/ui/HMDToolsDialog.cpp index ab84980d80..23d6d5df2f 100644 --- a/interface/src/ui/HMDToolsDialog.cpp +++ b/interface/src/ui/HMDToolsDialog.cpp @@ -21,6 +21,7 @@ #include +#include "MainWindow.h" #include "Menu.h" #include "devices/OculusManager.h" #include "ui/HMDToolsDialog.h" diff --git a/interface/src/ui/MetavoxelEditor.cpp b/interface/src/ui/MetavoxelEditor.cpp index 97c4c08b41..46f69b0452 100644 --- a/interface/src/ui/MetavoxelEditor.cpp +++ b/interface/src/ui/MetavoxelEditor.cpp @@ -37,6 +37,7 @@ #include #include "Application.h" +#include "MainWindow.h" #include "MetavoxelEditor.h" using namespace std; diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index 61cc9718b3..318dce977a 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -11,6 +11,7 @@ #include "Application.h" +#include "MainWindow.h" #include "Menu.h" #include "ModelsBrowser.h" #include "PreferencesDialog.h" diff --git a/interface/src/ui/ToolWindow.cpp b/interface/src/ui/ToolWindow.cpp index da1d2c68f4..8774bffc36 100644 --- a/interface/src/ui/ToolWindow.cpp +++ b/interface/src/ui/ToolWindow.cpp @@ -10,6 +10,7 @@ // #include "Application.h" +#include "MainWindow.h" #include "ToolWindow.h" #include "UIUtil.h" From 9b37967bedcfb6b9d714d6a5257b91dfb482c9d0 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 15 Dec 2014 11:23:25 -0800 Subject: [PATCH 395/502] changes to instructions for TBB, remove MSVC2010 --- BUILD_LINUX.md | 2 +- BUILD_WIN.md | 45 +++++++++------------------------------------ 2 files changed, 10 insertions(+), 37 deletions(-) diff --git a/BUILD_LINUX.md b/BUILD_LINUX.md index eb4dcd9255..7b6c8f2176 100644 --- a/BUILD_LINUX.md +++ b/BUILD_LINUX.md @@ -15,4 +15,4 @@ Should you choose not to install Qt5 via a package manager that handles dependen Install Intel TBB from your package manager of choice, or from source (available at the [TBB Website](https://www.threadingbuildingblocks.org/)). -You must run `tbbvars` so that the find module included with this project will be able to find the correct version of TBB. `tbbvars` is located in the 'bin' folder of your TBB install. \ No newline at end of file +You must run `tbbvars` before running cmake that the find module included with this project will be able to find the correct version of TBB. `tbbvars` is located in the 'bin' folder of your TBB install. \ No newline at end of file diff --git a/BUILD_WIN.md b/BUILD_WIN.md index 5685370dc3..4e773e3323 100644 --- a/BUILD_WIN.md +++ b/BUILD_WIN.md @@ -8,39 +8,10 @@ Please read the [general build guide](BUILD.md) for information on dependencies ###Visual Studio Currently building on Windows has been tested using the following compilers: -* Visual Studio C++ 2010 Express * Visual Studio 2013 (If anyone can test using Visual Studio 2013 Express then please update this document) -####Windows SDK 7.1 - -If using Visual Studio 2010, or using Visual Studio 2013 but building as a Visual Studio 2010 project, you need [Microsoft Windows SDK for Windows 7 and .NET Framework 4](http://www.microsoft.com/en-us/download/details.aspx?id=8279). - -NOTE: If using Visual Studio C++ 2010 Express, you need to follow a specific install order. See below before installing the Windows SDK. - -#####Windows SDK 8.1 - -If using Visual Studio 2013 and building as a Visual Studio 2013 project you need the Windows 8 SDK which you should already have as part of installing Visual Studio 2013. You should be able to see it at `C:\Program Files (x86)\Windows Kits\8.1\Lib\winv6.3\um\x86`. - -####Visual Studio C++ 2010 Express - -Visual Studio C++ 2010 Express can be downloaded [here](http://www.visualstudio.com/en-us/downloads#d-2010-express). - -The following patches/service packs are also required: -* [VS2010 SP1](http://www.microsoft.com/en-us/download/details.aspx?id=23691) -* [VS2010 SP1 Compiler Update](http://www.microsoft.com/en-us/download/details.aspx?id=4422) - -IMPORTANT: Use the following install order: -Visual Studio C++ 2010 Express -Windows SDK 7.1 -VS2010 SP1 -VS2010 SP1 Compiler Update - -If you get an error while installing the VS2010 SP1 Compiler update saying that you don't have the Windows SDK installed, then uninstall all of the above and start again in the correct order. - -Some of the build instructions will ask you to start a Visual Studio Command Prompt. You should have a shortcut in your Start menu called "Open Visual Studio Command Prompt (2010)" which will do so. - ####Visual Studio 2013 You can use the Community or Professional editions of Visual Studio 2013. @@ -53,6 +24,10 @@ Or you can start a regular command prompt and then run: If you experience issues building interface on Visual Studio 2013, try generating the build files with Visual Studio 2010 instead. To do so, download Visual Studio 2010 and run `cmake .. -G "Visual Studio 10"` (Assuming running from %HIFI_DIR%\build). +#####Windows SDK 8.1 + +If using Visual Studio 2013 and building as a Visual Studio 2013 project you need the Windows 8 SDK which you should already have as part of installing Visual Studio 2013. You should be able to see it at `C:\Program Files (x86)\Windows Kits\8.1\Lib\winv6.3\um\x86`. + ###Qt You can use the online installer or the offline installer. If you use the offline installer, be sure to select the "OpenGL" version. @@ -60,15 +35,13 @@ NOTE: Qt does not support 64-bit builds on Windows 7, so you must use the 32-bit * Download the online installer [here](http://qt-project.org/downloads) * When it asks you to select components, ONLY select the following: - * Qt > Qt 5.2.0 > **msvc2010 32-bit OpenGL** + * Qt > Qt 5.3.2 > **msvc2013 32-bit OpenGL** -* Download the offline installer [here](http://download.qt-project.org/official_releases/qt/5.2/5.2.0/qt-windows-opensource-5.2.0-msvc2010_opengl-x86-offline.exe) +* Download the offline installer [here](http://download.qt-project.org/official_releases/qt/5.3/5.3.2/qt-opensource-windows-x86-msvc2013_opengl-5.3.2.exe) Once Qt is installed, you need to manually configure the following: -* Make sure the Qt runtime DLLs are loadable. You must do this before you attempt to build because some tools for the build depend on Qt. E.g., add to the PATH: `Qt\5.2.0\msvc2010_opengl\bin\`. -* Set the QT_CMAKE_PREFIX_PATH environment variable to your `Qt\5.2.0\msvc2010_opengl` directory. - -If building as a Visual Studio 2013 project, download and configure the msvc2013 version of Qt instead. +* Make sure the Qt runtime DLLs are loadable. You must do this before you attempt to build because some tools for the build depend on Qt. E.g., add to the PATH: `Qt\5.3.2\msvc2013_opengl\bin\`. +* Set the QT_CMAKE_PREFIX_PATH environment variable to your `Qt\5.3.2\msvc2013_opengl` directory. ###External Libraries @@ -128,7 +101,7 @@ Install OpenSSL into the Windows system directory, to make sure that QT uses the Download the stable release for Windows from the [Intel Threading Building Blocks website](https://www.threadingbuildingblocks.org/). By default, TBB will install to Program Files. You may also choose to install it to %HIFI_LIB_DIR%\TBB. -You must run `tbbvars.bat` so that the find module included with this project will be able to find TBB no matter where you installed it. `tbbvars.bat` is located in the 'bin' folder of your TBB install. For a default installation on a 64-bit architechture, tbbvars can be found at `C:/Program Files (x86)/Intel/TBB/bin/tbbvars.bat`. +You must run `tbbvars.bat` before running cmake so that the find module included with this project will be able to find TBB no matter where you installed it. `tbbvars.bat` is located in the 'bin' folder of your TBB install. For a default installation on a 64-bit architechture, tbbvars can be found at `C:/Program Files (x86)/Intel/TBB/bin/tbbvars.bat`. ###Zlib From ee919643000130e573ed921a9f9c15f576687497 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 15 Dec 2014 11:25:17 -0800 Subject: [PATCH 396/502] clarify that TBB can be installed wherever --- BUILD_WIN.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BUILD_WIN.md b/BUILD_WIN.md index 4e773e3323..e84b2ad811 100644 --- a/BUILD_WIN.md +++ b/BUILD_WIN.md @@ -99,7 +99,7 @@ Install OpenSSL into the Windows system directory, to make sure that QT uses the ###Intel Threading Building Blocks (TBB) -Download the stable release for Windows from the [Intel Threading Building Blocks website](https://www.threadingbuildingblocks.org/). By default, TBB will install to Program Files. You may also choose to install it to %HIFI_LIB_DIR%\TBB. +Download the stable release for Windows from the [Intel Threading Building Blocks website](https://www.threadingbuildingblocks.org/). By default, TBB will install to Program Files. You can choose to install it wherever you like, including %HIFI_LIB_DIR%. You must run `tbbvars.bat` before running cmake so that the find module included with this project will be able to find TBB no matter where you installed it. `tbbvars.bat` is located in the 'bin' folder of your TBB install. For a default installation on a 64-bit architechture, tbbvars can be found at `C:/Program Files (x86)/Intel/TBB/bin/tbbvars.bat`. From 36f23fe4be78ad51a0fd41758ca8b9a9dac07501 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 15 Dec 2014 11:26:06 -0800 Subject: [PATCH 397/502] fix Qt path in Generating build files --- BUILD.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BUILD.md b/BUILD.md index 0a897aa193..0fdb822f25 100644 --- a/BUILD.md +++ b/BUILD.md @@ -38,7 +38,7 @@ Any variables that need to be set for CMake to find dependencies can be set as E For example, to pass the QT_CMAKE_PREFIX_PATH variable during build file generation: - cmake .. -DQT_CMAKE_PREFIX_PATH=/usr/local/qt/5.2.1/lib/cmake + cmake .. -DQT_CMAKE_PREFIX_PATH=/usr/local/qt/5.3.2/lib/cmake ####Finding Dependencies You can point our [Cmake find modules](cmake/modules/) to the correct version of dependencies by setting one of the three following variables to the location of the correct version of the dependency. From aac44953cbf0b3db0eb36509ccbcd17633f22369 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 15 Dec 2014 11:27:31 -0800 Subject: [PATCH 398/502] fix generator passed to cmake for windows build --- BUILD_WIN.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/BUILD_WIN.md b/BUILD_WIN.md index e84b2ad811..030c2f92a8 100644 --- a/BUILD_WIN.md +++ b/BUILD_WIN.md @@ -138,9 +138,7 @@ Be careful with glm. For the folder other libraries would normally call 'include ###Build High Fidelity using Visual Studio Follow the same build steps from the CMake section, but pass a different generator to CMake. - cmake .. -DZLIB_LIBRARY=%ZLIB_LIBRARY% -DZLIB_INCLUDE_DIR=%ZLIB_INCLUDE_DIR% -G "Visual Studio 10" - -If you're using Visual Studio 2013 then pass "Visual Studio 12" instead of "Visual Studio 10" (yes, 12, not 13). + cmake .. -DZLIB_LIBRARY=%ZLIB_LIBRARY% -DZLIB_INCLUDE_DIR=%ZLIB_INCLUDE_DIR% -G "Visual Studio 12" Open %HIFI_DIR%\build\hifi.sln and compile. From ea08d7bb2300560da764e1c53d6c659a5a775ccd Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 15 Dec 2014 11:28:43 -0800 Subject: [PATCH 399/502] remove block recommending VS2010 project file --- BUILD_WIN.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/BUILD_WIN.md b/BUILD_WIN.md index 030c2f92a8..bf7d421715 100644 --- a/BUILD_WIN.md +++ b/BUILD_WIN.md @@ -22,8 +22,6 @@ Or you can start a regular command prompt and then run: "%VS120COMNTOOLS%\vsvars32.bat" -If you experience issues building interface on Visual Studio 2013, try generating the build files with Visual Studio 2010 instead. To do so, download Visual Studio 2010 and run `cmake .. -G "Visual Studio 10"` (Assuming running from %HIFI_DIR%\build). - #####Windows SDK 8.1 If using Visual Studio 2013 and building as a Visual Studio 2013 project you need the Windows 8 SDK which you should already have as part of installing Visual Studio 2013. You should be able to see it at `C:\Program Files (x86)\Windows Kits\8.1\Lib\winv6.3\um\x86`. From 90c1132dd553bb10e221cdb569efc005ca975f42 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 15 Dec 2014 11:28:57 -0800 Subject: [PATCH 400/502] reduce calls to DependencyManager::get<> where possible --- interface/src/Util.cpp | 9 +++++---- interface/src/avatar/SkeletonModel.cpp | 18 +++++++++++------- .../src/renderer/DeferredLightingEffect.cpp | 8 +++++--- 3 files changed, 21 insertions(+), 14 deletions(-) diff --git a/interface/src/Util.cpp b/interface/src/Util.cpp index d93c8a26ad..6d40726f14 100644 --- a/interface/src/Util.cpp +++ b/interface/src/Util.cpp @@ -71,22 +71,23 @@ void renderWorldBox() { glPushMatrix(); glTranslatef(MARKER_DISTANCE, 0, 0); glColor3fv(red); - DependencyManager::get()->renderSphere(MARKER_RADIUS, 10, 10); + GeometryCache* geometryCache = DependencyManager::get(); + geometryCache->renderSphere(MARKER_RADIUS, 10, 10); glPopMatrix(); glPushMatrix(); glTranslatef(0, MARKER_DISTANCE, 0); glColor3fv(green); - DependencyManager::get()->renderSphere(MARKER_RADIUS, 10, 10); + geometryCache->renderSphere(MARKER_RADIUS, 10, 10); glPopMatrix(); glPushMatrix(); glTranslatef(0, 0, MARKER_DISTANCE); glColor3fv(blue); - DependencyManager::get()->renderSphere(MARKER_RADIUS, 10, 10); + geometryCache->renderSphere(MARKER_RADIUS, 10, 10); glPopMatrix(); glPushMatrix(); glColor3fv(gray); glTranslatef(MARKER_DISTANCE, 0, MARKER_DISTANCE); - DependencyManager::get()->renderSphere(MARKER_RADIUS, 10, 10); + geometryCache->renderSphere(MARKER_RADIUS, 10, 10); glPopMatrix(); } diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index f71c9318aa..42c74db143 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -554,6 +554,7 @@ void SkeletonModel::renderRagdoll() { float radius1 = 0.008f; float radius2 = 0.01f; glm::vec3 simulationTranslation = _ragdoll->getTranslationInSimulationFrame(); + GeometryCache* geometryCache = DependencyManager::get(); for (int i = 0; i < numPoints; ++i) { glPushMatrix(); // NOTE: ragdollPoints are in simulation-frame but we want them to be model-relative @@ -561,9 +562,9 @@ void SkeletonModel::renderRagdoll() { glTranslatef(position.x, position.y, position.z); // draw each point as a yellow hexagon with black border glColor4f(0.0f, 0.0f, 0.0f, alpha); - DependencyManager::get()->renderSphere(radius2, BALL_SUBDIVISIONS, BALL_SUBDIVISIONS); + geometryCache->renderSphere(radius2, BALL_SUBDIVISIONS, BALL_SUBDIVISIONS); glColor4f(1.0f, 1.0f, 0.0f, alpha); - DependencyManager::get()->renderSphere(radius1, BALL_SUBDIVISIONS, BALL_SUBDIVISIONS); + geometryCache->renderSphere(radius1, BALL_SUBDIVISIONS, BALL_SUBDIVISIONS); glPopMatrix(); } glPopMatrix(); @@ -913,7 +914,8 @@ void SkeletonModel::renderBoundingCollisionShapes(float alpha) { endPoint = endPoint - _translation; glTranslatef(endPoint.x, endPoint.y, endPoint.z); glColor4f(0.6f, 0.6f, 0.8f, alpha); - DependencyManager::get()->renderSphere(_boundingShape.getRadius(), BALL_SUBDIVISIONS, BALL_SUBDIVISIONS); + GeometryCache* geometryCache = DependencyManager::get(); + geometryCache->renderSphere(_boundingShape.getRadius(), BALL_SUBDIVISIONS, BALL_SUBDIVISIONS); // draw a yellow sphere at the capsule startpoint glm::vec3 startPoint; @@ -922,7 +924,7 @@ void SkeletonModel::renderBoundingCollisionShapes(float alpha) { glm::vec3 axis = endPoint - startPoint; glTranslatef(-axis.x, -axis.y, -axis.z); glColor4f(0.8f, 0.8f, 0.6f, alpha); - DependencyManager::get()->renderSphere(_boundingShape.getRadius(), BALL_SUBDIVISIONS, BALL_SUBDIVISIONS); + geometryCache->renderSphere(_boundingShape.getRadius(), BALL_SUBDIVISIONS, BALL_SUBDIVISIONS); // draw a green cylinder between the two points glm::vec3 origin(0.0f); @@ -948,6 +950,8 @@ void SkeletonModel::renderJointCollisionShapes(float alpha) { continue; } + GeometryCache* geometryCache = DependencyManager::get(); + glPushMatrix(); // shapes are stored in simulation-frame but we want position to be model-relative if (shape->getType() == SPHERE_SHAPE) { @@ -955,7 +959,7 @@ void SkeletonModel::renderJointCollisionShapes(float alpha) { glTranslatef(position.x, position.y, position.z); // draw a grey sphere at shape position glColor4f(0.75f, 0.75f, 0.75f, alpha); - DependencyManager::get()->renderSphere(shape->getBoundingRadius(), BALL_SUBDIVISIONS, BALL_SUBDIVISIONS); + geometryCache->renderSphere(shape->getBoundingRadius(), BALL_SUBDIVISIONS, BALL_SUBDIVISIONS); } else if (shape->getType() == CAPSULE_SHAPE) { CapsuleShape* capsule = static_cast(shape); @@ -965,7 +969,7 @@ void SkeletonModel::renderJointCollisionShapes(float alpha) { endPoint = endPoint - simulationTranslation; glTranslatef(endPoint.x, endPoint.y, endPoint.z); glColor4f(0.6f, 0.6f, 0.8f, alpha); - DependencyManager::get()->renderSphere(capsule->getRadius(), BALL_SUBDIVISIONS, BALL_SUBDIVISIONS); + geometryCache->renderSphere(capsule->getRadius(), BALL_SUBDIVISIONS, BALL_SUBDIVISIONS); // draw a yellow sphere at the capsule startpoint glm::vec3 startPoint; @@ -974,7 +978,7 @@ void SkeletonModel::renderJointCollisionShapes(float alpha) { glm::vec3 axis = endPoint - startPoint; glTranslatef(-axis.x, -axis.y, -axis.z); glColor4f(0.8f, 0.8f, 0.6f, alpha); - DependencyManager::get()->renderSphere(capsule->getRadius(), BALL_SUBDIVISIONS, BALL_SUBDIVISIONS); + geometryCache->renderSphere(capsule->getRadius(), BALL_SUBDIVISIONS, BALL_SUBDIVISIONS); // draw a green cylinder between the two points glm::vec3 origin(0.0f); diff --git a/interface/src/renderer/DeferredLightingEffect.cpp b/interface/src/renderer/DeferredLightingEffect.cpp index 75af4647e4..e40193c8c3 100644 --- a/interface/src/renderer/DeferredLightingEffect.cpp +++ b/interface/src/renderer/DeferredLightingEffect.cpp @@ -234,6 +234,8 @@ void DeferredLightingEffect::render() { const glm::vec3& eyePoint = Application::getInstance()->getDisplayViewFrustum()->getPosition(); float nearRadius = glm::distance(eyePoint, Application::getInstance()->getDisplayViewFrustum()->getNearTopLeft()); + + GeometryCache* geometryCache = DependencyManager::get(); if (!_pointLights.isEmpty()) { _pointLight.bind(); @@ -241,7 +243,7 @@ void DeferredLightingEffect::render() { _pointLight.setUniformValue(_pointLightLocations.depthScale, depthScale); _pointLight.setUniformValue(_pointLightLocations.depthTexCoordOffset, depthTexCoordOffsetS, depthTexCoordOffsetT); _pointLight.setUniformValue(_pointLightLocations.depthTexCoordScale, depthTexCoordScaleS, depthTexCoordScaleT); - + foreach (const PointLight& light, _pointLights) { _pointLight.setUniformValue(_pointLightLocations.radius, light.radius); glLightfv(GL_LIGHT1, GL_AMBIENT, (const GLfloat*)&light.ambient); @@ -270,7 +272,7 @@ void DeferredLightingEffect::render() { } else { glTranslatef(light.position.x, light.position.y, light.position.z); - DependencyManager::get()->renderSphere(expandedRadius, 32, 32); + geometryCache->renderSphere(expandedRadius, 32, 32); } glPopMatrix(); @@ -323,7 +325,7 @@ void DeferredLightingEffect::render() { glm::vec3 axis = glm::axis(spotRotation); glRotatef(glm::degrees(glm::angle(spotRotation)), axis.x, axis.y, axis.z); glTranslatef(0.0f, 0.0f, -light.radius * (1.0f + SCALE_EXPANSION * 0.5f)); - DependencyManager::get()->renderCone(expandedRadius * glm::tan(light.cutoff), + geometryCache->renderCone(expandedRadius * glm::tan(light.cutoff), expandedRadius, 32, 1); } From c18c45a40152f5dd326a78323c8dfe7b1577dffb Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 15 Dec 2014 11:30:17 -0800 Subject: [PATCH 401/502] bump glm dependency version --- BUILD.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BUILD.md b/BUILD.md index 0fdb822f25..6613786903 100644 --- a/BUILD.md +++ b/BUILD.md @@ -2,7 +2,7 @@ * [cmake](http://www.cmake.org/cmake/resources/software.html) ~> 2.8.12.2 * [Qt](http://qt-project.org/downloads) ~> 5.3.0 -* [glm](http://glm.g-truc.net/0.9.5/index.html) ~> 0.9.5.2 +* [glm](http://glm.g-truc.net/0.9.5/index.html) ~> 0.9.5.4 * [OpenSSL](https://www.openssl.org/related/binaries.html) ~> 1.0.1g * IMPORTANT: OpenSSL 1.0.1g is critical to avoid a security vulnerability. * [Intel Threading Building Blocks](https://www.threadingbuildingblocks.org/) ~> 4.3 From 3bc132154906013d13e9f4e90e069afa68d738a0 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 15 Dec 2014 11:40:17 -0800 Subject: [PATCH 402/502] reduce calls to DependencyManager::get<> where possible --- interface/src/MetavoxelSystem.cpp | 6 ++++-- .../src/renderer/DeferredLightingEffect.cpp | 21 +++++++++++-------- interface/src/renderer/GeometryCache.cpp | 19 ++++++++++------- interface/src/renderer/GlowEffect.cpp | 9 ++++---- interface/src/renderer/Model.cpp | 11 +++++----- 5 files changed, 38 insertions(+), 28 deletions(-) diff --git a/interface/src/MetavoxelSystem.cpp b/interface/src/MetavoxelSystem.cpp index a61f6e41d7..84ccf0f406 100644 --- a/interface/src/MetavoxelSystem.cpp +++ b/interface/src/MetavoxelSystem.cpp @@ -1177,10 +1177,11 @@ void VoxelBuffer::render(bool cursor) { if (!_materials.isEmpty()) { _networkTextures.resize(_materials.size()); + TextureCache* textureCache = DependencyManager::get(); for (int i = 0; i < _materials.size(); i++) { const SharedObjectPointer material = _materials.at(i); if (material) { - _networkTextures[i] = DependencyManager::get()->getTexture( + _networkTextures[i] = textureCache->getTexture( static_cast(material.data())->getDiffuse(), SPLAT_TEXTURE); } } @@ -2231,10 +2232,11 @@ void HeightfieldNodeRenderer::render(const HeightfieldNodePointer& node, const g const QVector& materials = node->getMaterial()->getMaterials(); _networkTextures.resize(materials.size()); + TextureCache* textureCache = DependencyManager::get(); for (int i = 0; i < materials.size(); i++) { const SharedObjectPointer& material = materials.at(i); if (material) { - _networkTextures[i] = DependencyManager::get()->getTexture( + _networkTextures[i] = textureCache->getTexture( static_cast(material.data())->getDiffuse(), SPLAT_TEXTURE); } } diff --git a/interface/src/renderer/DeferredLightingEffect.cpp b/interface/src/renderer/DeferredLightingEffect.cpp index e40193c8c3..22ac5d82b6 100644 --- a/interface/src/renderer/DeferredLightingEffect.cpp +++ b/interface/src/renderer/DeferredLightingEffect.cpp @@ -117,15 +117,16 @@ void DeferredLightingEffect::addSpotLight(const glm::vec3& position, float radiu void DeferredLightingEffect::prepare() { // clear the normal and specular buffers - DependencyManager::get()->setPrimaryDrawBuffers(false, true, false); + TextureCache* textureCache = DependencyManager::get(); + textureCache->setPrimaryDrawBuffers(false, true, false); glClear(GL_COLOR_BUFFER_BIT); - DependencyManager::get()->setPrimaryDrawBuffers(false, false, true); + textureCache->setPrimaryDrawBuffers(false, false, true); // clearing to zero alpha for specular causes problems on my Nvidia card; clear to lowest non-zero value instead const float MAX_SPECULAR_EXPONENT = 128.0f; glClearColor(0.0f, 0.0f, 0.0f, 1.0f / MAX_SPECULAR_EXPONENT); glClear(GL_COLOR_BUFFER_BIT); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); - DependencyManager::get()->setPrimaryDrawBuffers(true, false, false); + textureCache->setPrimaryDrawBuffers(true, false, false); } void DeferredLightingEffect::render() { @@ -137,8 +138,10 @@ void DeferredLightingEffect::render() { glDisable(GL_DEPTH_TEST); glDisable(GL_COLOR_MATERIAL); glDepthMask(false); + + TextureCache* textureCache = DependencyManager::get(); - QOpenGLFramebufferObject* primaryFBO = DependencyManager::get()->getPrimaryFramebufferObject(); + QOpenGLFramebufferObject* primaryFBO = textureCache->getPrimaryFramebufferObject(); primaryFBO->release(); QOpenGLFramebufferObject* freeFBO = Application::getInstance()->getGlowEffect()->getFreeFramebufferObject(); @@ -148,13 +151,13 @@ void DeferredLightingEffect::render() { glBindTexture(GL_TEXTURE_2D, primaryFBO->texture()); glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, DependencyManager::get()->getPrimaryNormalTextureID()); + glBindTexture(GL_TEXTURE_2D, textureCache->getPrimaryNormalTextureID()); glActiveTexture(GL_TEXTURE2); - glBindTexture(GL_TEXTURE_2D, DependencyManager::get()->getPrimarySpecularTextureID()); + glBindTexture(GL_TEXTURE_2D, textureCache->getPrimarySpecularTextureID()); glActiveTexture(GL_TEXTURE3); - glBindTexture(GL_TEXTURE_2D, DependencyManager::get()->getPrimaryDepthTextureID()); + glBindTexture(GL_TEXTURE_2D, textureCache->getPrimaryDepthTextureID()); // get the viewport side (left, right, both) int viewport[4]; @@ -173,7 +176,7 @@ void DeferredLightingEffect::render() { bool shadowsEnabled = Menu::getInstance()->getShadowsEnabled(); if (shadowsEnabled) { glActiveTexture(GL_TEXTURE4); - glBindTexture(GL_TEXTURE_2D, DependencyManager::get()->getShadowDepthTextureID()); + glBindTexture(GL_TEXTURE_2D, textureCache->getShadowDepthTextureID()); program = &_directionalLightShadowMap; locations = &_directionalLightShadowMapLocations; @@ -188,7 +191,7 @@ void DeferredLightingEffect::render() { program->bind(); } program->setUniformValue(locations->shadowScale, - 1.0f / DependencyManager::get()->getShadowFramebufferObject()->width()); + 1.0f / textureCache->getShadowFramebufferObject()->width()); } else { program->bind(); diff --git a/interface/src/renderer/GeometryCache.cpp b/interface/src/renderer/GeometryCache.cpp index 534911ff46..974a542b0e 100644 --- a/interface/src/renderer/GeometryCache.cpp +++ b/interface/src/renderer/GeometryCache.cpp @@ -699,6 +699,7 @@ void NetworkGeometry::clearLoadPriority(const QPointer& owner) { void NetworkGeometry::setTextureWithNameToURL(const QString& name, const QUrl& url) { if (_meshes.size() > 0) { + TextureCache* textureCache = DependencyManager::get(); for (int i = 0; i < _meshes.size(); i++) { NetworkMesh& mesh = _meshes[i]; for (int j = 0; j < mesh.parts.size(); j++) { @@ -707,19 +708,19 @@ void NetworkGeometry::setTextureWithNameToURL(const QString& name, const QUrl& u QSharedPointer matchingTexture = QSharedPointer(); if (part.diffuseTextureName == name) { part.diffuseTexture = - DependencyManager::get()->getTexture(url, DEFAULT_TEXTURE, + textureCache->getTexture(url, DEFAULT_TEXTURE, _geometry.meshes[i].isEye, QByteArray()); part.diffuseTexture->setLoadPriorities(_loadPriorities); } else if (part.normalTextureName == name) { - part.normalTexture = DependencyManager::get()->getTexture(url, DEFAULT_TEXTURE, + part.normalTexture = textureCache->getTexture(url, DEFAULT_TEXTURE, false, QByteArray()); part.normalTexture->setLoadPriorities(_loadPriorities); } else if (part.specularTextureName == name) { - part.specularTexture = DependencyManager::get()->getTexture(url, DEFAULT_TEXTURE, + part.specularTexture = textureCache->getTexture(url, DEFAULT_TEXTURE, false, QByteArray()); part.specularTexture->setLoadPriorities(_loadPriorities); } else if (part.emissiveTextureName == name) { - part.emissiveTexture = DependencyManager::get()->getTexture(url, DEFAULT_TEXTURE, + part.emissiveTexture = textureCache->getTexture(url, DEFAULT_TEXTURE, false, QByteArray()); part.emissiveTexture->setLoadPriorities(_loadPriorities); } @@ -912,6 +913,8 @@ void NetworkGeometry::reinsert() { void NetworkGeometry::setGeometry(const FBXGeometry& geometry) { _geometry = geometry; + + TextureCache* textureCache = DependencyManager::get(); foreach (const FBXMesh& mesh, _geometry.meshes) { NetworkMesh networkMesh; @@ -920,28 +923,28 @@ void NetworkGeometry::setGeometry(const FBXGeometry& geometry) { foreach (const FBXMeshPart& part, mesh.parts) { NetworkMeshPart networkPart; if (!part.diffuseTexture.filename.isEmpty()) { - networkPart.diffuseTexture = DependencyManager::get()->getTexture( + networkPart.diffuseTexture = textureCache->getTexture( _textureBase.resolved(QUrl(part.diffuseTexture.filename)), DEFAULT_TEXTURE, mesh.isEye, part.diffuseTexture.content); networkPart.diffuseTextureName = part.diffuseTexture.name; networkPart.diffuseTexture->setLoadPriorities(_loadPriorities); } if (!part.normalTexture.filename.isEmpty()) { - networkPart.normalTexture = DependencyManager::get()->getTexture( + networkPart.normalTexture = textureCache->getTexture( _textureBase.resolved(QUrl(part.normalTexture.filename)), NORMAL_TEXTURE, false, part.normalTexture.content); networkPart.normalTextureName = part.normalTexture.name; networkPart.normalTexture->setLoadPriorities(_loadPriorities); } if (!part.specularTexture.filename.isEmpty()) { - networkPart.specularTexture = DependencyManager::get()->getTexture( + networkPart.specularTexture = textureCache->getTexture( _textureBase.resolved(QUrl(part.specularTexture.filename)), SPECULAR_TEXTURE, false, part.specularTexture.content); networkPart.specularTextureName = part.specularTexture.name; networkPart.specularTexture->setLoadPriorities(_loadPriorities); } if (!part.emissiveTexture.filename.isEmpty()) { - networkPart.emissiveTexture = DependencyManager::get()->getTexture( + networkPart.emissiveTexture = textureCache->getTexture( _textureBase.resolved(QUrl(part.emissiveTexture.filename)), EMISSIVE_TEXTURE, false, part.emissiveTexture.content); networkPart.emissiveTextureName = part.emissiveTexture.name; diff --git a/interface/src/renderer/GlowEffect.cpp b/interface/src/renderer/GlowEffect.cpp index e6bbdb2ba1..b6896eeaad 100644 --- a/interface/src/renderer/GlowEffect.cpp +++ b/interface/src/renderer/GlowEffect.cpp @@ -122,7 +122,8 @@ static void maybeRelease(QOpenGLFramebufferObject* fbo) { QOpenGLFramebufferObject* GlowEffect::render(bool toTexture) { PerformanceTimer perfTimer("glowEffect"); - QOpenGLFramebufferObject* primaryFBO = DependencyManager::get()->getPrimaryFramebufferObject(); + TextureCache* textureCache = DependencyManager::get(); + QOpenGLFramebufferObject* primaryFBO = textureCache->getPrimaryFramebufferObject(); primaryFBO->release(); glBindTexture(GL_TEXTURE_2D, primaryFBO->texture()); @@ -138,7 +139,7 @@ QOpenGLFramebufferObject* GlowEffect::render(bool toTexture) { glDepthMask(GL_FALSE); QOpenGLFramebufferObject* destFBO = toTexture ? - DependencyManager::get()->getSecondaryFramebufferObject() : NULL; + textureCache->getSecondaryFramebufferObject() : NULL; if (!Menu::getInstance()->isOptionChecked(MenuOption::EnableGlowEffect) || _isEmpty) { // copy the primary to the screen if (destFBO && QOpenGLFramebufferObject::hasOpenGLFramebufferBlit()) { @@ -160,9 +161,9 @@ QOpenGLFramebufferObject* GlowEffect::render(bool toTexture) { } else { // diffuse into the secondary/tertiary (alternating between frames) QOpenGLFramebufferObject* oldDiffusedFBO = - DependencyManager::get()->getSecondaryFramebufferObject(); + textureCache->getSecondaryFramebufferObject(); QOpenGLFramebufferObject* newDiffusedFBO = - DependencyManager::get()->getTertiaryFramebufferObject(); + textureCache->getTertiaryFramebufferObject(); if (_isOddFrame) { qSwap(oldDiffusedFBO, newDiffusedFBO); } diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 62170efeed..2a6988a984 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -2324,7 +2324,8 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod bool dontCullOutOfViewMeshParts = Menu::getInstance()->isOptionChecked(MenuOption::DontCullOutOfViewMeshParts); bool cullTooSmallMeshParts = !Menu::getInstance()->isOptionChecked(MenuOption::DontCullTooSmallMeshParts); bool dontReduceMaterialSwitches = Menu::getInstance()->isOptionChecked(MenuOption::DontReduceMaterialSwitches); - + + TextureCache* textureCache = DependencyManager::get(); QString lastMaterialID; int meshPartsRendered = 0; updateVisibleJointStates(); @@ -2446,7 +2447,7 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod if (showDiffuse && diffuseMap) { GLBATCH(glBindTexture)(GL_TEXTURE_2D, diffuseMap->getID()); } else { - GLBATCH(glBindTexture)(GL_TEXTURE_2D, DependencyManager::get()->getWhiteTextureID()); + GLBATCH(glBindTexture)(GL_TEXTURE_2D, textureCache->getWhiteTextureID()); } if (locations->texcoordMatrices >= 0) { @@ -2464,7 +2465,7 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod GLBATCH(glActiveTexture)(GL_TEXTURE1); Texture* normalMap = networkPart.normalTexture.data(); GLBATCH(glBindTexture)(GL_TEXTURE_2D, !normalMap ? - DependencyManager::get()->getBlueTextureID() : normalMap->getID()); + textureCache->getBlueTextureID() : normalMap->getID()); GLBATCH(glActiveTexture)(GL_TEXTURE0); } @@ -2472,7 +2473,7 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod GLBATCH(glActiveTexture)(GL_TEXTURE0 + locations->specularTextureUnit); Texture* specularMap = networkPart.specularTexture.data(); GLBATCH(glBindTexture)(GL_TEXTURE_2D, !specularMap ? - DependencyManager::get()->getWhiteTextureID() : specularMap->getID()); + textureCache->getWhiteTextureID() : specularMap->getID()); GLBATCH(glActiveTexture)(GL_TEXTURE0); } @@ -2493,7 +2494,7 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod GLBATCH(glActiveTexture)(GL_TEXTURE0 + locations->emissiveTextureUnit); Texture* emissiveMap = networkPart.emissiveTexture.data(); GLBATCH(glBindTexture)(GL_TEXTURE_2D, !emissiveMap ? - DependencyManager::get()->getWhiteTextureID() : emissiveMap->getID()); + textureCache->getWhiteTextureID() : emissiveMap->getID()); GLBATCH(glActiveTexture)(GL_TEXTURE0); } From 94cf8b33841a6a9ffbaaf9b973d1bb803626600c Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 15 Dec 2014 11:43:30 -0800 Subject: [PATCH 403/502] reduce calls to DependencyManager::get<> where possible --- interface/src/ModelUploader.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/interface/src/ModelUploader.cpp b/interface/src/ModelUploader.cpp index b22457f847..6f582d60eb 100644 --- a/interface/src/ModelUploader.cpp +++ b/interface/src/ModelUploader.cpp @@ -466,17 +466,19 @@ void ModelUploader::processCheck() { _timer.stop(); switch (reply->error()) { - case QNetworkReply::NoError: + case QNetworkReply::NoError: { QMessageBox::information(NULL, QString("ModelUploader::processCheck()"), QString("Your model is now available in the browser."), QMessageBox::Ok); DependencyManager::get()->refresh(_url); + TextureCache* textureCache = DependencyManager::get(); foreach (const QByteArray& filename, _textureFilenames) { - DependencyManager::get()->refresh(_textureBase + filename); + textureCache->refresh(_textureBase + filename); } deleteLater(); break; + } case QNetworkReply::ContentNotFoundError: if (--_numberOfChecks) { _timer.start(TIMEOUT); From 28f2dc62ea20806b99d2a172148ee75091b7f459 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 15 Dec 2014 11:49:01 -0800 Subject: [PATCH 404/502] add windowshacks.h to GPUConfig.h and move it to shared --- libraries/gpu/src/gpu/GPUConfig.h | 1 + {interface => libraries/shared}/src/windowshacks.h | 0 2 files changed, 1 insertion(+) rename {interface => libraries/shared}/src/windowshacks.h (100%) diff --git a/libraries/gpu/src/gpu/GPUConfig.h b/libraries/gpu/src/gpu/GPUConfig.h index 393a476182..c399f51b66 100644 --- a/libraries/gpu/src/gpu/GPUConfig.h +++ b/libraries/gpu/src/gpu/GPUConfig.h @@ -19,6 +19,7 @@ #include #elif defined(WIN32) +#include #include #include diff --git a/interface/src/windowshacks.h b/libraries/shared/src/windowshacks.h similarity index 100% rename from interface/src/windowshacks.h rename to libraries/shared/src/windowshacks.h From fa8b7020b0ed48556a8cbc2100599c8326903e08 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 15 Dec 2014 11:48:24 -0800 Subject: [PATCH 405/502] repairs to MetavoxelSystem after reset to upstream --- interface/src/MetavoxelSystem.cpp | 349 +++++++++++++++--------------- 1 file changed, 175 insertions(+), 174 deletions(-) diff --git a/interface/src/MetavoxelSystem.cpp b/interface/src/MetavoxelSystem.cpp index c047b8591b..b15ea0b488 100644 --- a/interface/src/MetavoxelSystem.cpp +++ b/interface/src/MetavoxelSystem.cpp @@ -40,13 +40,13 @@ REGISTER_META_OBJECT(StaticModelRenderer) REGISTER_META_OBJECT(HeightfieldRenderer) MetavoxelSystem::NetworkSimulation::NetworkSimulation(float dropRate, float repeatRate, - int minimumDelay, int maximumDelay, int bandwidthLimit) : -dropRate(dropRate), -repeatRate(repeatRate), -minimumDelay(minimumDelay), -maximumDelay(maximumDelay), -bandwidthLimit(bandwidthLimit) { -} + int minimumDelay, int maximumDelay, int bandwidthLimit) : + dropRate(dropRate), + repeatRate(repeatRate), + minimumDelay(minimumDelay), + maximumDelay(maximumDelay), + bandwidthLimit(bandwidthLimit) { +} MetavoxelSystem::~MetavoxelSystem() { // kill the updater before we delete our network simulation objects @@ -59,14 +59,14 @@ void MetavoxelSystem::init() { MetavoxelClientManager::init(); _voxelBufferAttribute = AttributeRegistry::getInstance()->registerAttribute( - new BufferDataAttribute("voxelBuffer")); + new BufferDataAttribute("voxelBuffer")); _voxelBufferAttribute->setLODThresholdMultiplier( - AttributeRegistry::getInstance()->getVoxelColorAttribute()->getLODThresholdMultiplier()); - + AttributeRegistry::getInstance()->getVoxelColorAttribute()->getLODThresholdMultiplier()); + _baseHeightfieldProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + - "shaders/metavoxel_heightfield_base.vert"); + "shaders/metavoxel_heightfield_base.vert"); _baseHeightfieldProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + - "shaders/metavoxel_heightfield_base.frag"); + "shaders/metavoxel_heightfield_base.frag"); _baseHeightfieldProgram.link(); _baseHeightfieldProgram.bind(); @@ -79,9 +79,9 @@ void MetavoxelSystem::init() { loadSplatProgram("heightfield", _splatHeightfieldProgram, _splatHeightfieldLocations); _heightfieldCursorProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + - "shaders/metavoxel_heightfield_cursor.vert"); + "shaders/metavoxel_heightfield_cursor.vert"); _heightfieldCursorProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + - "shaders/metavoxel_cursor.frag"); + "shaders/metavoxel_cursor.frag"); _heightfieldCursorProgram.link(); _heightfieldCursorProgram.bind(); @@ -89,17 +89,17 @@ void MetavoxelSystem::init() { _heightfieldCursorProgram.release(); _baseVoxelProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + - "shaders/metavoxel_voxel_base.vert"); + "shaders/metavoxel_voxel_base.vert"); _baseVoxelProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + - "shaders/metavoxel_voxel_base.frag"); + "shaders/metavoxel_voxel_base.frag"); _baseVoxelProgram.link(); loadSplatProgram("voxel", _splatVoxelProgram, _splatVoxelLocations); _voxelCursorProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + - "shaders/metavoxel_voxel_cursor.vert"); + "shaders/metavoxel_voxel_cursor.vert"); _voxelCursorProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + - "shaders/metavoxel_cursor.frag"); + "shaders/metavoxel_cursor.frag"); _voxelCursorProgram.link(); } @@ -124,16 +124,16 @@ public: SimulateVisitor(float deltaTime, const MetavoxelLOD& lod); virtual int visit(MetavoxelInfo& info); - + private: float _deltaTime; }; SimulateVisitor::SimulateVisitor(float deltaTime, const MetavoxelLOD& lod) : -MetavoxelVisitor(QVector() << AttributeRegistry::getInstance()->getRendererAttribute(), - QVector(), lod), -_deltaTime(deltaTime) { + MetavoxelVisitor(QVector() << AttributeRegistry::getInstance()->getRendererAttribute(), + QVector(), lod), + _deltaTime(deltaTime) { } int SimulateVisitor::visit(MetavoxelInfo& info) { @@ -141,7 +141,7 @@ int SimulateVisitor::visit(MetavoxelInfo& info) { return DEFAULT_ORDER; } static_cast(info.inputValues.at(0).getInlineValue< - SharedObjectPointer>().data())->getImplementation()->simulate(*_data, _deltaTime, info, _lod); + SharedObjectPointer>().data())->getImplementation()->simulate(*_data, _deltaTime, info, _lod); return STOP_RECURSION; } @@ -152,7 +152,7 @@ void MetavoxelSystem::simulate(float deltaTime) { const float DEFAULT_LOD_THRESHOLD = 0.01f; _lod = MetavoxelLOD(Application::getInstance()->getCamera()->getPosition(), DEFAULT_LOD_THRESHOLD); } - + SimulateVisitor simulateVisitor(deltaTime, getLOD()); guideToAugmented(simulateVisitor); } @@ -166,8 +166,8 @@ public: }; RenderVisitor::RenderVisitor(const MetavoxelLOD& lod) : -MetavoxelVisitor(QVector() << AttributeRegistry::getInstance()->getRendererAttribute(), - QVector(), lod) { + MetavoxelVisitor(QVector() << AttributeRegistry::getInstance()->getRendererAttribute(), + QVector(), lod) { } int RenderVisitor::visit(MetavoxelInfo& info) { @@ -175,7 +175,7 @@ int RenderVisitor::visit(MetavoxelInfo& info) { return DEFAULT_ORDER; } static_cast(info.inputValues.at(0).getInlineValue< - SharedObjectPointer>().data())->getImplementation()->render(*_data, info, _lod); + SharedObjectPointer>().data())->getImplementation()->render(*_data, info, _lod); return STOP_RECURSION; } @@ -195,18 +195,18 @@ void MetavoxelSystem::render() { // update the frustum ViewFrustum* viewFrustum = Application::getInstance()->getDisplayViewFrustum(); _frustum.set(viewFrustum->getFarTopLeft(), viewFrustum->getFarTopRight(), viewFrustum->getFarBottomLeft(), - viewFrustum->getFarBottomRight(), viewFrustum->getNearTopLeft(), viewFrustum->getNearTopRight(), - viewFrustum->getNearBottomLeft(), viewFrustum->getNearBottomRight()); - + viewFrustum->getFarBottomRight(), viewFrustum->getNearTopLeft(), viewFrustum->getNearTopRight(), + viewFrustum->getNearBottomLeft(), viewFrustum->getNearBottomRight()); + RenderVisitor renderVisitor(getLOD()); guideToAugmented(renderVisitor, true); if (!_heightfieldBaseBatches.isEmpty()) { glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); - + Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, true); - + glDisable(GL_BLEND); glEnable(GL_CULL_FACE); glEnable(GL_ALPHA_TEST); @@ -225,7 +225,7 @@ void MetavoxelSystem::render() { batch.vertexBuffer->bind(); batch.indexBuffer->bind(); - + HeightfieldPoint* point = 0; glVertexPointer(3, GL_FLOAT, sizeof(HeightfieldPoint), &point->vertex); glTexCoordPointer(2, GL_FLOAT, sizeof(HeightfieldPoint), &point->textureCoord); @@ -234,7 +234,7 @@ void MetavoxelSystem::render() { _baseHeightfieldProgram.setUniform(_baseHeightScaleLocation, batch.heightScale); _baseHeightfieldProgram.setUniform(_baseColorScaleLocation, batch.colorScale); - + glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, batch.colorTextureID); @@ -244,10 +244,10 @@ void MetavoxelSystem::render() { glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, 0); - + batch.vertexBuffer->release(); batch.indexBuffer->release(); - + glPopMatrix(); } @@ -275,7 +275,7 @@ void MetavoxelSystem::render() { batch.vertexBuffer->bind(); batch.indexBuffer->bind(); - + HeightfieldPoint* point = 0; glVertexPointer(3, GL_FLOAT, sizeof(HeightfieldPoint), &point->vertex); glTexCoordPointer(2, GL_FLOAT, sizeof(HeightfieldPoint), &point->textureCoord); @@ -283,7 +283,7 @@ void MetavoxelSystem::render() { glBindTexture(GL_TEXTURE_2D, batch.heightTextureID); _splatHeightfieldProgram.setUniformValue(_splatHeightfieldLocations.heightScale, - batch.heightScale.x, batch.heightScale.y); + batch.heightScale.x, batch.heightScale.y); _splatHeightfieldProgram.setUniform(_splatHeightfieldLocations.textureScale, batch.textureScale); _splatHeightfieldProgram.setUniform(_splatHeightfieldLocations.splatTextureOffset, batch.splatTextureOffset); @@ -291,18 +291,18 @@ void MetavoxelSystem::render() { _splatHeightfieldProgram.setUniform(_splatHeightfieldLocations.splatTextureScalesS, batch.splatTextureScalesS); _splatHeightfieldProgram.setUniform(_splatHeightfieldLocations.splatTextureScalesT, batch.splatTextureScalesT); _splatHeightfieldProgram.setUniformValue( - _splatHeightfieldLocations.textureValueMinima, - (batch.materialIndex + 1) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP, - (batch.materialIndex + 2) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP, - (batch.materialIndex + 3) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP, - (batch.materialIndex + 4) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP); + _splatHeightfieldLocations.textureValueMinima, + (batch.materialIndex + 1) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP, + (batch.materialIndex + 2) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP, + (batch.materialIndex + 3) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP, + (batch.materialIndex + 4) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP); _splatHeightfieldProgram.setUniformValue( - _splatHeightfieldLocations.textureValueMaxima, - (batch.materialIndex + 1) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP, - (batch.materialIndex + 2) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP, - (batch.materialIndex + 3) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP, - (batch.materialIndex + 4) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP); - + _splatHeightfieldLocations.textureValueMaxima, + (batch.materialIndex + 1) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP, + (batch.materialIndex + 2) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP, + (batch.materialIndex + 3) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP, + (batch.materialIndex + 4) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP); + glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, batch.materialTextureID); @@ -312,22 +312,22 @@ void MetavoxelSystem::render() { } glDrawRangeElements(GL_TRIANGLES, 0, batch.vertexCount - 1, batch.indexCount, GL_UNSIGNED_INT, 0); - + for (int i = 0; i < SPLAT_COUNT; i++) { glActiveTexture(GL_TEXTURE0 + SPLAT_TEXTURE_UNITS[i]); glBindTexture(GL_TEXTURE_2D, 0); } - + glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, 0); - + glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, 0); - + batch.vertexBuffer->release(); batch.indexBuffer->release(); - glPopMatrix(); + glPopMatrix(); } _splatHeightfieldProgram.release(); @@ -341,15 +341,15 @@ void MetavoxelSystem::render() { glDisable(GL_CULL_FACE); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glDisableClientState(GL_VERTEX_ARRAY); _heightfieldBaseBatches.clear(); } if (!_voxelBaseBatches.isEmpty()) { Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, true); - + glEnableClientState(GL_VERTEX_ARRAY); glDisable(GL_BLEND); glEnable(GL_CULL_FACE); @@ -360,7 +360,7 @@ void MetavoxelSystem::render() { glEnableClientState(GL_COLOR_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); - + _baseVoxelProgram.bind(); foreach (const VoxelBatch& batch, _voxelBaseBatches) { @@ -379,10 +379,10 @@ void MetavoxelSystem::render() { } _baseVoxelProgram.release(); - + glDisable(GL_ALPHA_TEST); glEnable(GL_BLEND); - + Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, false); if (!_voxelSplatBatches.isEmpty()) { @@ -406,25 +406,25 @@ void MetavoxelSystem::render() { glNormalPointer(GL_BYTE, sizeof(VoxelPoint), &point->normal); _splatVoxelProgram.setAttributeBuffer(_splatVoxelLocations.materials, - GL_UNSIGNED_BYTE, (qint64)&point->materials, SPLAT_COUNT, sizeof(VoxelPoint)); + GL_UNSIGNED_BYTE, (qint64)&point->materials, SPLAT_COUNT, sizeof(VoxelPoint)); _splatVoxelProgram.setAttributeBuffer(_splatVoxelLocations.materialWeights, - GL_UNSIGNED_BYTE, (qint64)&point->materialWeights, SPLAT_COUNT, sizeof(VoxelPoint)); + GL_UNSIGNED_BYTE, (qint64)&point->materialWeights, SPLAT_COUNT, sizeof(VoxelPoint)); const float QUARTER_STEP = 0.25f * EIGHT_BIT_MAXIMUM_RECIPROCAL; _splatVoxelProgram.setUniform(_splatVoxelLocations.splatTextureScalesS, batch.splatTextureScalesS); _splatVoxelProgram.setUniform(_splatVoxelLocations.splatTextureScalesT, batch.splatTextureScalesT); _splatVoxelProgram.setUniformValue( - _splatVoxelLocations.textureValueMinima, - (batch.materialIndex + 1) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP, - (batch.materialIndex + 2) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP, - (batch.materialIndex + 3) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP, - (batch.materialIndex + 4) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP); + _splatVoxelLocations.textureValueMinima, + (batch.materialIndex + 1) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP, + (batch.materialIndex + 2) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP, + (batch.materialIndex + 3) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP, + (batch.materialIndex + 4) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP); _splatVoxelProgram.setUniformValue( - _splatVoxelLocations.textureValueMaxima, - (batch.materialIndex + 1) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP, - (batch.materialIndex + 2) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP, - (batch.materialIndex + 3) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP, - (batch.materialIndex + 4) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP); + _splatVoxelLocations.textureValueMaxima, + (batch.materialIndex + 1) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP, + (batch.materialIndex + 2) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP, + (batch.materialIndex + 3) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP, + (batch.materialIndex + 4) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP); for (int i = 0; i < SPLAT_COUNT; i++) { glActiveTexture(GL_TEXTURE0 + SPLAT_TEXTURE_UNITS[i]); @@ -437,9 +437,9 @@ void MetavoxelSystem::render() { glActiveTexture(GL_TEXTURE0 + SPLAT_TEXTURE_UNITS[i]); glBindTexture(GL_TEXTURE_2D, 0); } - + glActiveTexture(GL_TEXTURE0); - + batch.vertexBuffer->release(); batch.indexBuffer->release(); } @@ -517,10 +517,10 @@ public: }; RayVoxelIntersectionVisitor::RayVoxelIntersectionVisitor(const glm::vec3& origin, - const glm::vec3& direction, const MetavoxelLOD& lod) : -RayIntersectionVisitor(origin, direction, QVector() << - Application::getInstance()->getMetavoxels()->getVoxelBufferAttribute(), QVector(), lod), -intersectionDistance(FLT_MAX) { + const glm::vec3& direction, const MetavoxelLOD& lod) : + RayIntersectionVisitor(origin, direction, QVector() << + Application::getInstance()->getMetavoxels()->getVoxelBufferAttribute(), QVector(), lod), + intersectionDistance(FLT_MAX) { } int RayVoxelIntersectionVisitor::visit(MetavoxelInfo& info, float distance) { @@ -528,7 +528,7 @@ int RayVoxelIntersectionVisitor::visit(MetavoxelInfo& info, float distance) { return _order; } const VoxelBuffer* buffer = static_cast( - info.inputValues.at(0).getInlineValue().data()); + info.inputValues.at(0).getInlineValue().data()); if (!buffer) { return STOP_RECURSION; } @@ -630,7 +630,7 @@ public: virtual bool visit(Spanner* spanner); virtual int visit(MetavoxelInfo& info); - + private: Box _bounds; @@ -693,17 +693,17 @@ class BufferCursorRenderVisitor : public MetavoxelVisitor { public: BufferCursorRenderVisitor(const AttributePointer& attribute, const Box& bounds); - + virtual int visit(MetavoxelInfo& info); - + private: Box _bounds; }; BufferCursorRenderVisitor::BufferCursorRenderVisitor(const AttributePointer& attribute, const Box& bounds) : -MetavoxelVisitor(QVector() << attribute), -_bounds(bounds) { + MetavoxelVisitor(QVector() << attribute), + _bounds(bounds) { } int BufferCursorRenderVisitor::visit(MetavoxelInfo& info) { @@ -766,11 +766,11 @@ void MetavoxelSystem::renderVoxelCursor(const glm::vec3& position, float radius) class MaterialEditApplier : public SignalHandler { public: - + MaterialEditApplier(const MetavoxelEditMessage& message, const QSharedPointer texture); virtual void handle(); - + protected: MetavoxelEditMessage _message; @@ -778,8 +778,8 @@ protected: }; MaterialEditApplier::MaterialEditApplier(const MetavoxelEditMessage& message, const QSharedPointer texture) : -_message(message), -_texture(texture) { + _message(message), + _texture(texture) { } void MaterialEditApplier::handle() { @@ -794,16 +794,16 @@ void MetavoxelSystem::applyMaterialEdit(const MetavoxelEditMessage& message, boo if (material && material->getDiffuse().isValid()) { if (QThread::currentThread() != thread()) { QMetaObject::invokeMethod(this, "applyMaterialEdit", Q_ARG(const MetavoxelEditMessage&, message), - Q_ARG(bool, reliable)); + Q_ARG(bool, reliable)); return; } QSharedPointer texture = Application::getInstance()->getTextureCache()->getTexture( - material->getDiffuse(), SPLAT_TEXTURE); + material->getDiffuse(), SPLAT_TEXTURE); if (texture->isLoaded()) { MetavoxelEditMessage newMessage = message; static_cast(newMessage.edit.data())->averageColor = texture->getAverageColor(); - applyEdit(newMessage, true); - + applyEdit(newMessage, true); + } else { MaterialEditApplier* applier = new MaterialEditApplier(message, texture); connect(texture.data(), &Resource::loaded, applier, &SignalHandler::handle); @@ -818,7 +818,7 @@ MetavoxelClient* MetavoxelSystem::createClient(const SharedNodePointer& node) { } void MetavoxelSystem::guideToAugmented(MetavoxelVisitor& visitor, bool render) { - NodeList::getInstance()->eachNode([&visitor, &render](const SharedNodePointer& node) { + NodeList::getInstance()->eachNode([&visitor, &render](const SharedNodePointer& node){ if (node->getType() == NodeType::MetavoxelServer) { QMutexLocker locker(&node->getMutex()); MetavoxelSystemClient* client = static_cast(node->getLinkedData()); @@ -837,9 +837,9 @@ void MetavoxelSystem::guideToAugmented(MetavoxelVisitor& visitor, bool render) { void MetavoxelSystem::loadSplatProgram(const char* type, ProgramObject& program, SplatLocations& locations) { program.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + - "shaders/metavoxel_" + type + "_splat.vert"); + "shaders/metavoxel_" + type + "_splat.vert"); program.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + - "shaders/metavoxel_" + type + "_splat.frag"); + "shaders/metavoxel_" + type + "_splat.frag"); program.link(); program.bind(); @@ -859,8 +859,8 @@ void MetavoxelSystem::loadSplatProgram(const char* type, ProgramObject& program, } Throttle::Throttle() : -_limit(INT_MAX), -_total(0) { + _limit(INT_MAX), + _total(0) { } bool Throttle::shouldThrottle(int bytes) { @@ -881,7 +881,7 @@ bool Throttle::shouldThrottle(int bytes) { } MetavoxelSystemClient::MetavoxelSystemClient(const SharedNodePointer& node, MetavoxelUpdater* updater) : -MetavoxelClient(node, updater) { + MetavoxelClient(node, updater) { } void MetavoxelSystemClient::setAugmentedData(const MetavoxelData& data) { @@ -898,11 +898,11 @@ class ReceiveDelayer : public QObject { public: ReceiveDelayer(const SharedNodePointer& node, const QByteArray& packet); - + protected: - + virtual void timerEvent(QTimerEvent* event); - + private: SharedNodePointer _node; @@ -910,8 +910,8 @@ private: }; ReceiveDelayer::ReceiveDelayer(const SharedNodePointer& node, const QByteArray& packet) : -_node(node), -_packet(packet) { + _node(node), + _packet(packet) { } void ReceiveDelayer::timerEvent(QTimerEvent* event) { @@ -956,16 +956,16 @@ public: AugmentVisitor(const MetavoxelLOD& lod, const MetavoxelData& previousData); virtual int visit(MetavoxelInfo& info); - + private: const MetavoxelData& _previousData; }; AugmentVisitor::AugmentVisitor(const MetavoxelLOD& lod, const MetavoxelData& previousData) : -MetavoxelVisitor(QVector() << AttributeRegistry::getInstance()->getRendererAttribute(), - QVector(), lod), -_previousData(previousData) { + MetavoxelVisitor(QVector() << AttributeRegistry::getInstance()->getRendererAttribute(), + QVector(), lod), + _previousData(previousData) { } int AugmentVisitor::visit(MetavoxelInfo& info) { @@ -973,7 +973,7 @@ int AugmentVisitor::visit(MetavoxelInfo& info) { return DEFAULT_ORDER; } static_cast(info.inputValues.at(0).getInlineValue< - SharedObjectPointer>().data())->getImplementation()->augment(*_data, _previousData, info, _lod); + SharedObjectPointer>().data())->getImplementation()->augment(*_data, _previousData, info, _lod); return STOP_RECURSION; } @@ -981,10 +981,10 @@ class Augmenter : public QRunnable { public: Augmenter(const SharedNodePointer& node, const MetavoxelData& data, - const MetavoxelData& previousData, const MetavoxelLOD& lod); + const MetavoxelData& previousData, const MetavoxelLOD& lod); virtual void run(); - + private: QWeakPointer _node; @@ -994,11 +994,11 @@ private: }; Augmenter::Augmenter(const SharedNodePointer& node, const MetavoxelData& data, - const MetavoxelData& previousData, const MetavoxelLOD& lod) : -_node(node), -_data(data), -_previousData(previousData), -_lod(lod) { + const MetavoxelData& previousData, const MetavoxelLOD& lod) : + _node(node), + _data(data), + _previousData(previousData), + _lod(lod) { } void Augmenter::run() { @@ -1016,7 +1016,7 @@ void MetavoxelSystemClient::refreshVoxelData() { // make it look as if all the colors have changed MetavoxelData oldData = getAugmentedData(); oldData.touch(AttributeRegistry::getInstance()->getVoxelColorAttribute()); - + QThreadPool::globalInstance()->start(new Augmenter(_node, _data, oldData, _remoteDataLOD)); } @@ -1029,9 +1029,9 @@ class SendDelayer : public QObject { public: SendDelayer(const SharedNodePointer& node, const QByteArray& data); - + virtual void timerEvent(QTimerEvent* event); - + private: SharedNodePointer _node; @@ -1039,8 +1039,8 @@ private: }; SendDelayer::SendDelayer(const SharedNodePointer& node, const QByteArray& data) : -_node(node), -_data(data.constData(), data.size()) { + _node(node), + _data(data.constData(), data.size()) { } void SendDelayer::timerEvent(QTimerEvent* event) { @@ -1083,21 +1083,21 @@ void VoxelPoint::setNormal(const glm::vec3& normal) { } VoxelBuffer::VoxelBuffer(const QVector& vertices, const QVector& indices, const QVector& hermite, - const QMultiHash& quadIndices, int size, const QVector& materials) : -_vertices(vertices), -_indices(indices), -_hermite(hermite), -_quadIndices(quadIndices), -_size(size), -_vertexCount(vertices.size()), -_indexCount(indices.size()), -_hermiteCount(hermite.size()), -_indexBuffer(QOpenGLBuffer::IndexBuffer), -_materials(materials) { + const QMultiHash& quadIndices, int size, const QVector& materials) : + _vertices(vertices), + _indices(indices), + _hermite(hermite), + _quadIndices(quadIndices), + _size(size), + _vertexCount(vertices.size()), + _indexCount(indices.size()), + _hermiteCount(hermite.size()), + _indexBuffer(QOpenGLBuffer::IndexBuffer), + _materials(materials) { } bool VoxelBuffer::findFirstRayIntersection(const glm::vec3& entry, const glm::vec3& origin, - const glm::vec3& direction, float& distance) const { + const glm::vec3& direction, float& distance) const { float highest = _size - 1.0f; glm::vec3 position = entry * highest; glm::vec3 floors = glm::floor(position); @@ -1105,14 +1105,14 @@ bool VoxelBuffer::findFirstRayIntersection(const glm::vec3& entry, const glm::ve int x = qMin((int)floors.x, max), y = qMin((int)floors.y, max), z = qMin((int)floors.z, max); forever { for (QMultiHash::const_iterator it = _quadIndices.constFind(qRgb(x + 1, y + 1, z + 1)); - it != _quadIndices.constEnd(); it++) { + it != _quadIndices.constEnd(); it++) { const int* indices = _indices.constData() + *it; if (findRayTriangleIntersection(origin, direction, _vertices.at(indices[0]).vertex, - _vertices.at(indices[1]).vertex, _vertices.at(indices[2]).vertex, distance) || + _vertices.at(indices[1]).vertex, _vertices.at(indices[2]).vertex, distance) || findRayTriangleIntersection(origin, direction, _vertices.at(indices[0]).vertex, - _vertices.at(indices[2]).vertex, _vertices.at(indices[3]).vertex, distance)) { - return true; - } + _vertices.at(indices[2]).vertex, _vertices.at(indices[3]).vertex, distance)) { + return true; + } } float xDistance = FLT_MAX, yDistance = FLT_MAX, zDistance = FLT_MAX; if (direction.x > 0.0f) { @@ -1181,7 +1181,7 @@ void VoxelBuffer::render(bool cursor) { const SharedObjectPointer material = _materials.at(i); if (material) { _networkTextures[i] = Application::getInstance()->getTextureCache()->getTexture( - static_cast(material.data())->getDiffuse(), SPLAT_TEXTURE); + static_cast(material.data())->getDiffuse(), SPLAT_TEXTURE); } } } @@ -1216,7 +1216,7 @@ void VoxelBuffer::render(bool cursor) { splatBatch.indexBuffer = &_indexBuffer; splatBatch.vertexCount = _vertexCount; splatBatch.indexCount = _indexCount; - + for (int i = 0; i < _materials.size(); i += SPLAT_COUNT) { for (int j = 0; j < SPLAT_COUNT; j++) { int index = i + j; @@ -1227,7 +1227,7 @@ void VoxelBuffer::render(bool cursor) { splatBatch.splatTextureScalesS[j] = 1.0f / material->getScaleS(); splatBatch.splatTextureScalesT[j] = 1.0f / material->getScaleT(); splatBatch.splatTextureIDs[j] = texture->getID(); - + } else { splatBatch.splatTextureIDs[j] = 0; } @@ -1256,7 +1256,7 @@ void VoxelBuffer::render(bool cursor) { } BufferDataAttribute::BufferDataAttribute(const QString& name) : -InlineAttribute(name) { + InlineAttribute(name) { } bool BufferDataAttribute::merge(void*& parent, void* children[], bool postRead) const { @@ -1278,17 +1278,17 @@ DefaultMetavoxelRendererImplementation::DefaultMetavoxelRendererImplementation() class VoxelAugmentVisitor : public MetavoxelVisitor { public: - + VoxelAugmentVisitor(const MetavoxelLOD& lod); virtual int visit(MetavoxelInfo& info); }; VoxelAugmentVisitor::VoxelAugmentVisitor(const MetavoxelLOD& lod) : -MetavoxelVisitor(QVector() << AttributeRegistry::getInstance()->getVoxelColorAttribute() << - AttributeRegistry::getInstance()->getVoxelMaterialAttribute() << - AttributeRegistry::getInstance()->getVoxelHermiteAttribute(), QVector() << - Application::getInstance()->getMetavoxels()->getVoxelBufferAttribute(), lod) { + MetavoxelVisitor(QVector() << AttributeRegistry::getInstance()->getVoxelColorAttribute() << + AttributeRegistry::getInstance()->getVoxelMaterialAttribute() << + AttributeRegistry::getInstance()->getVoxelHermiteAttribute(), QVector() << + Application::getInstance()->getMetavoxels()->getVoxelBufferAttribute(), lod) { } class EdgeCrossing { @@ -1446,9 +1446,9 @@ int VoxelAugmentVisitor::visit(MetavoxelInfo& info) { // its properties (color, material, normal) if one is present; as before, boundary edges are excluded int clampedX = qMax(x - 1, 0), clampedY = qMax(y - 1, 0), clampedZ = qMax(z - 1, 0); const QRgb* hermiteBase = hermiteData + clampedZ * hermiteArea + clampedY * hermiteStride + - clampedX * VoxelHermiteData::EDGE_COUNT; + clampedX * VoxelHermiteData::EDGE_COUNT; const char* materialBase = materialData ? - (materialData + clampedZ * area + clampedY * size + clampedX) : NULL; + (materialData + clampedZ * area + clampedY * size + clampedX) : NULL; int crossingCount = 0; if (middleX) { if (alpha0 != alpha1) { @@ -1650,7 +1650,7 @@ int VoxelAugmentVisitor::visit(MetavoxelInfo& info) { if (displayHermite) { glm::vec3 start = info.minimum + (glm::vec3(clampedX, clampedY, clampedZ) + - crossing.point) * scale; + crossing.point) * scale; hermiteSegments.append(start); hermiteSegments.append(start + crossing.normal * scale); } @@ -1710,18 +1710,18 @@ int VoxelAugmentVisitor::visit(MetavoxelInfo& info) { for (int i = 0; i < MAX_ITERATIONS; i++) { glm::vec3 offDiagonals = glm::abs(glm::vec3(d[1][0], d[2][0], d[2][1])); int largestIndex = (offDiagonals[0] > offDiagonals[1]) ? (offDiagonals[0] > offDiagonals[2] ? 0 : 2) : - (offDiagonals[1] > offDiagonals[2] ? 1 : 2); + (offDiagonals[1] > offDiagonals[2] ? 1 : 2); const float DESIRED_PRECISION = 0.00001f; if (offDiagonals[largestIndex] < DESIRED_PRECISION) { break; } int largestJ = (largestIndex == 2) ? 1 : 0; - int largestI = (largestIndex == 0) ? 1 : 2; + int largestI = (largestIndex == 0) ? 1 : 2; float sjj = d[largestJ][largestJ]; float sii = d[largestI][largestI]; float angle = glm::atan(2.0f * d[largestJ][largestI], sjj - sii) / 2.0f; glm::quat rotation = glm::angleAxis(angle, largestIndex == 0 ? glm::vec3(0.0f, 0.0f, -1.0f) : - (largestIndex == 1 ? glm::vec3(0.0f, 1.0f, 0.0f) : glm::vec3(-1.0f, 0.0f, 0.0f))); + (largestIndex == 1 ? glm::vec3(0.0f, 1.0f, 0.0f) : glm::vec3(-1.0f, 0.0f, 0.0f))); combinedRotation = glm::normalize(rotation * combinedRotation); glm::mat3 matrix = glm::mat3_cast(combinedRotation); d = matrix * ata * glm::transpose(matrix); @@ -1735,7 +1735,7 @@ int VoxelAugmentVisitor::visit(MetavoxelInfo& info) { // compute the pseudo-inverse, ataplus, and use to find the minimizing solution glm::mat3 u = glm::mat3_cast(combinedRotation); - glm::mat3 ataplus = glm::transpose(u) * d * u; + glm::mat3 ataplus = glm::transpose(u) * d * u; glm::vec3 solution = (ataplus * atrans * b) + center; // make sure it doesn't fall beyond the cell boundaries @@ -1774,7 +1774,7 @@ int VoxelAugmentVisitor::visit(MetavoxelInfo& info) { const glm::vec3& first = vertices.at(index.indices[0]).vertex; glm::vec3 normal = glm::cross(vertices.at(index1.indices[0]).vertex - first, - vertices.at(index3.indices[0]).vertex - first); + vertices.at(index3.indices[0]).vertex - first); if (alpha0 == 0) { // quad faces negative x indices.append(index3.getClosestIndex(normal = -normal, vertices)); @@ -1800,7 +1800,7 @@ int VoxelAugmentVisitor::visit(MetavoxelInfo& info) { const glm::vec3& first = vertices.at(index.indices[0]).vertex; glm::vec3 normal = glm::cross(vertices.at(index3.indices[0]).vertex - first, - vertices.at(index1.indices[0]).vertex - first); + vertices.at(index1.indices[0]).vertex - first); if (alpha0 == 0) { // quad faces negative y indices.append(index1.getClosestIndex(normal = -normal, vertices)); @@ -1826,7 +1826,7 @@ int VoxelAugmentVisitor::visit(MetavoxelInfo& info) { const glm::vec3& first = vertices.at(index.indices[0]).vertex; glm::vec3 normal = glm::cross(vertices.at(index1.indices[0]).vertex - first, - vertices.at(index3.indices[0]).vertex - first); + vertices.at(index3.indices[0]).vertex - first); if (alpha0 == 0) { // quad faces negative z indices.append(index3.getClosestIndex(normal = -normal, vertices)); @@ -1861,7 +1861,7 @@ int VoxelAugmentVisitor::visit(MetavoxelInfo& info) { } } buffer = new VoxelBuffer(vertices, indices, hermiteSegments, quadIndices, size, - material ? material->getMaterials() : QVector()); + material ? material->getMaterials() : QVector()); } BufferDataPointer pointer(buffer); info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline(pointer)); @@ -1869,14 +1869,14 @@ int VoxelAugmentVisitor::visit(MetavoxelInfo& info) { } void DefaultMetavoxelRendererImplementation::augment(MetavoxelData& data, const MetavoxelData& previous, - MetavoxelInfo& info, const MetavoxelLOD& lod) { + MetavoxelInfo& info, const MetavoxelLOD& lod) { // copy the previous buffers MetavoxelData expandedPrevious = previous; while (expandedPrevious.getSize() < data.getSize()) { expandedPrevious.expand(); } const AttributePointer& voxelBufferAttribute = - Application::getInstance()->getMetavoxels()->getVoxelBufferAttribute(); + Application::getInstance()->getMetavoxels()->getVoxelBufferAttribute(); MetavoxelNode* root = expandedPrevious.getRoot(voxelBufferAttribute); if (root) { data.setRoot(voxelBufferAttribute, root); @@ -1892,16 +1892,16 @@ public: SpannerSimulateVisitor(float deltaTime, const MetavoxelLOD& lod); virtual bool visit(Spanner* spanner); - + private: float _deltaTime; }; SpannerSimulateVisitor::SpannerSimulateVisitor(float deltaTime, const MetavoxelLOD& lod) : -SpannerVisitor(QVector() << AttributeRegistry::getInstance()->getSpannersAttribute(), - QVector(), QVector(), lod), -_deltaTime(deltaTime) { + SpannerVisitor(QVector() << AttributeRegistry::getInstance()->getSpannersAttribute(), + QVector(), QVector(), lod), + _deltaTime(deltaTime) { } bool SpannerSimulateVisitor::visit(Spanner* spanner) { @@ -1910,7 +1910,7 @@ bool SpannerSimulateVisitor::visit(Spanner* spanner) { } void DefaultMetavoxelRendererImplementation::simulate(MetavoxelData& data, float deltaTime, - MetavoxelInfo& info, const MetavoxelLOD& lod) { + MetavoxelInfo& info, const MetavoxelLOD& lod) { SpannerSimulateVisitor spannerSimulateVisitor(deltaTime, lod); data.guide(spannerSimulateVisitor); } @@ -1921,7 +1921,7 @@ public: BufferRenderVisitor(const AttributePointer& attribute); virtual int visit(MetavoxelInfo& info); - + private: int _order; @@ -1929,15 +1929,15 @@ private: }; BufferRenderVisitor::BufferRenderVisitor(const AttributePointer& attribute) : -MetavoxelVisitor(QVector() << attribute), -_order(encodeOrder(Application::getInstance()->getDisplayViewFrustum()->getDirection())), -_containmentDepth(INT_MAX) { + MetavoxelVisitor(QVector() << attribute), + _order(encodeOrder(Application::getInstance()->getDisplayViewFrustum()->getDirection())), + _containmentDepth(INT_MAX) { } int BufferRenderVisitor::visit(MetavoxelInfo& info) { if (_containmentDepth >= _depth) { Frustum::IntersectionType intersection = Application::getInstance()->getMetavoxels()->getFrustum().getIntersectionType( - info.getBounds()); + info.getBounds()); if (intersection == Frustum::NO_INTERSECTION) { return STOP_RECURSION; } @@ -2007,12 +2007,12 @@ void CuboidRenderer::render(const MetavoxelLOD& lod, bool contained, bool cursor } StaticModelRenderer::StaticModelRenderer() : -_model(new Model(this)) { + _model(new Model(this)) { } void StaticModelRenderer::init(Spanner* spanner) { SpannerRenderer::init(spanner); - + _model->init(); StaticModel* staticModel = static_cast(spanner); @@ -2035,7 +2035,7 @@ void StaticModelRenderer::simulate(float deltaTime) { bounds = Box(extents.minimum, extents.maximum); } static_cast(_spanner)->setBounds(glm::translate(_model->getTranslation()) * - glm::mat4_cast(_model->getRotation()) * glm::scale(_model->getScale()) * bounds); + glm::mat4_cast(_model->getRotation()) * glm::scale(_model->getScale()) * bounds); _model->simulate(deltaTime); } @@ -2251,7 +2251,7 @@ void HeightfieldNodeRenderer::render(const HeightfieldNodePointer& node, const g if (cursor) { bufferPair.first.bind(); bufferPair.second.bind(); - + glPushMatrix(); glTranslatef(translation.x, translation.y, translation.z); glm::vec3 axis = glm::axis(rotation); @@ -2286,7 +2286,7 @@ void HeightfieldNodeRenderer::render(const HeightfieldNodePointer& node, const g baseBatch.heightScale = glm::vec4(1.0f / width, 1.0f / height, (innerWidth - 1) / -2.0f, (innerHeight - 1) / -2.0f); baseBatch.colorTextureID = _colorTextureID; baseBatch.colorScale = glm::vec2((float)width / innerWidth, (float)height / innerHeight); - Application::getInstance()->getMetavoxels()->addHeightfieldBaseBatch(baseBatch); + Application::getInstance()->getMetavoxels()->addHeightfieldBaseBatch(baseBatch); if (!_networkTextures.isEmpty()) { HeightfieldSplatBatch splatBatch; @@ -2331,3 +2331,4 @@ void HeightfieldNodeRenderer::render(const HeightfieldNodePointer& node, const g } QHash HeightfieldNodeRenderer::_bufferPairs; + From 68430e1346ea1f6014c19cff445b2984a1a697a7 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 15 Dec 2014 11:54:33 -0800 Subject: [PATCH 406/502] Moved GLCanvas to DependencyManager --- interface/src/Application.cpp | 76 ++++++++++++++++++++--------------- interface/src/Application.h | 31 +++++++------- interface/src/GLCanvas.h | 10 ++++- 3 files changed, 68 insertions(+), 49 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index d0abc47b85..eaafcd0eac 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -146,7 +146,6 @@ QString& Application::resourcesPath() { Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : QApplication(argc, argv), _window(new MainWindow(desktop())), - _glWidget(new GLCanvas()), _toolWindow(NULL), _nodeThread(new QThread(this)), _datagramProcessor(), @@ -195,7 +194,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : _isVSyncOn(true), _aboutToQuit(false) { - + GLCanvas* glCanvas = DependencyManager::get(); + // read the ApplicationInfo.ini file for Name/Version/Domain information QSettings applicationInfo(Application::resourcesPath() + "info/ApplicationInfo.ini", QSettings::IniFormat); @@ -365,16 +365,16 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : ResourceCache::setRequestLimit(3); - _window->setCentralWidget(_glWidget); + _window->setCentralWidget(glCanvas); restoreSizeAndPosition(); _window->setVisible(true); - _glWidget->setFocusPolicy(Qt::StrongFocus); - _glWidget->setFocus(); + glCanvas->setFocusPolicy(Qt::StrongFocus); + glCanvas->setFocus(); // enable mouse tracking; otherwise, we only get drag events - _glWidget->setMouseTracking(true); + glCanvas->setMouseTracking(true); _toolWindow = new ToolWindow(); _toolWindow->setWindowFlags(_toolWindow->windowFlags() | Qt::WindowStaysOnTopHint); @@ -393,7 +393,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : checkVersion(); - _overlays.init(_glWidget); // do this before scripts load + _overlays.init(glCanvas); // do this before scripts load LocalVoxelsList::getInstance()->addPersistantTree(DOMAIN_TREE_NAME, _voxels.getTree()); LocalVoxelsList::getInstance()->addPersistantTree(CLIPBOARD_TREE_NAME, &_clipboard); @@ -483,8 +483,6 @@ Application::~Application() { Menu::getInstance()->deleteLater(); _myAvatar = NULL; - - delete _glWidget; } void Application::saveSettings() { @@ -624,7 +622,7 @@ void Application::paintGL() { if (OculusManager::isConnected()) { _textureCache.setFrameBufferSize(OculusManager::getRenderTargetSize()); } else { - QSize fbSize = _glWidget->getDeviceSize() * getRenderResolutionScale(); + QSize fbSize = DependencyManager::get()->getDeviceSize() * getRenderResolutionScale(); _textureCache.setFrameBufferSize(fbSize); } @@ -1048,7 +1046,8 @@ void Application::keyPressEvent(QKeyEvent* event) { if (isShifted) { _viewFrustum.setFocalLength(_viewFrustum.getFocalLength() - 0.1f); if (TV3DManager::isConnected()) { - TV3DManager::configureCamera(_myCamera, _glWidget->getDeviceWidth(), _glWidget->getDeviceHeight()); + GLCanvas* glCanvas = DependencyManager::get(); + TV3DManager::configureCamera(_myCamera, glCanvas->getDeviceWidth(), glCanvas->getDeviceHeight()); } } else { _myCamera.setEyeOffsetPosition(_myCamera.getEyeOffsetPosition() + glm::vec3(-0.001, 0, 0)); @@ -1060,7 +1059,8 @@ void Application::keyPressEvent(QKeyEvent* event) { if (isShifted) { _viewFrustum.setFocalLength(_viewFrustum.getFocalLength() + 0.1f); if (TV3DManager::isConnected()) { - TV3DManager::configureCamera(_myCamera, _glWidget->getDeviceWidth(), _glWidget->getDeviceHeight()); + GLCanvas* glCanvas = DependencyManager::get(); + TV3DManager::configureCamera(_myCamera, glCanvas->getDeviceWidth(), glCanvas->getDeviceHeight()); } } else { @@ -1506,7 +1506,7 @@ void Application::idle() { { PerformanceTimer perfTimer("updateGL"); PerformanceWarning warn(showWarnings, "Application::idle()... updateGL()"); - _glWidget->updateGL(); + DependencyManager::get()->updateGL(); } { PerformanceTimer perfTimer("rest"); @@ -1532,13 +1532,14 @@ void Application::idle() { void Application::checkBandwidthMeterClick() { // ... to be called upon button release + GLCanvas* glCanvas = DependencyManager::get(); if (Menu::getInstance()->isOptionChecked(MenuOption::Bandwidth) && Menu::getInstance()->isOptionChecked(MenuOption::Stats) && Menu::getInstance()->isOptionChecked(MenuOption::UserInterface) && glm::compMax(glm::abs(glm::ivec2(getMouseX() - getMouseDragStartedX(), getMouseY() - getMouseDragStartedY()))) <= BANDWIDTH_METER_CLICK_MAX_DRAG_LENGTH - && _bandwidthMeter.isWithinArea(getMouseX(), getMouseY(), _glWidget->width(), _glWidget->height())) { + && _bandwidthMeter.isWithinArea(getMouseX(), getMouseY(), glCanvas->width(), glCanvas->height())) { // The bandwidth meter is visible, the click didn't get dragged too far and // we actually hit the bandwidth meter @@ -1567,7 +1568,8 @@ void Application::setFullscreen(bool fullscreen) { } void Application::setEnable3DTVMode(bool enable3DTVMode) { - resizeGL(_glWidget->getDeviceWidth(),_glWidget->getDeviceHeight()); + GLCanvas* glCanvas = DependencyManager::get(); + resizeGL(glCanvas->getDeviceWidth(), glCanvas->getDeviceHeight()); } void Application::setEnableVRMode(bool enableVRMode) { @@ -1592,7 +1594,8 @@ void Application::setEnableVRMode(bool enableVRMode) { _myCamera.setHmdRotation(glm::quat()); } - resizeGL(_glWidget->getDeviceWidth(), _glWidget->getDeviceHeight()); + GLCanvas* glCanvas = DependencyManager::get(); + resizeGL(glCanvas->getDeviceWidth(), glCanvas->getDeviceHeight()); } void Application::setRenderVoxels(bool voxelRender) { @@ -1654,8 +1657,9 @@ glm::vec3 Application::getMouseVoxelWorldCoordinates(const VoxelDetail& mouseVox bool Application::mouseOnScreen() const { if (OculusManager::isConnected()) { - return getMouseX() >= 0 && getMouseX() <= _glWidget->getDeviceWidth() && - getMouseY() >= 0 && getMouseY() <= _glWidget->getDeviceHeight(); + GLCanvas* glCanvas = DependencyManager::get(); + return getMouseX() >= 0 && getMouseX() <= glCanvas->getDeviceWidth() && + getMouseY() >= 0 && getMouseY() <= glCanvas->getDeviceHeight(); } return true; } @@ -1774,7 +1778,8 @@ void Application::exportVoxels(const VoxelDetail& sourceVoxel) { QString desktopLocation = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation); QString suggestedName = desktopLocation.append("/voxels.svo"); - QString fileNameString = QFileDialog::getSaveFileName(_glWidget, tr("Export Voxels"), suggestedName, + QString fileNameString = QFileDialog::getSaveFileName(DependencyManager::get(), + tr("Export Voxels"), suggestedName, tr("Sparse Voxel Octree Files (*.svo)")); QByteArray fileNameAscii = fileNameString.toLocal8Bit(); const char* fileName = fileNameAscii.data(); @@ -2029,9 +2034,9 @@ void Application::init() { _metavoxels.init(); - _audio.init(_glWidget); - - _rearMirrorTools = new RearMirrorTools(_glWidget, _mirrorViewRect, _settings); + GLCanvas* glCanvas = DependencyManager::get(); + _audio.init(glCanvas); + _rearMirrorTools = new RearMirrorTools(glCanvas, _mirrorViewRect, _settings); connect(_rearMirrorTools, SIGNAL(closeView()), SLOT(closeMirrorView())); connect(_rearMirrorTools, SIGNAL(restoreView()), SLOT(restoreMirrorView())); @@ -2913,8 +2918,9 @@ void Application::updateShadowMap() { } fbo->release(); - - glViewport(0, 0, _glWidget->getDeviceWidth(), _glWidget->getDeviceHeight()); + + GLCanvas* glCanvas = DependencyManager::get(); + glViewport(0, 0, glCanvas->getDeviceWidth(), glCanvas->getDeviceHeight()); } const GLfloat WORLD_AMBIENT_COLOR[] = { 0.525f, 0.525f, 0.6f }; @@ -2944,7 +2950,9 @@ QImage Application::renderAvatarBillboard() { Glower glower; const int BILLBOARD_SIZE = 64; - renderRearViewMirror(QRect(0, _glWidget->getDeviceHeight() - BILLBOARD_SIZE, BILLBOARD_SIZE, BILLBOARD_SIZE), true); + renderRearViewMirror(QRect(0, DependencyManager::get()->getDeviceHeight() - BILLBOARD_SIZE, + BILLBOARD_SIZE, BILLBOARD_SIZE), + true); QImage image(BILLBOARD_SIZE, BILLBOARD_SIZE, QImage::Format_ARGB32); glReadPixels(0, 0, BILLBOARD_SIZE, BILLBOARD_SIZE, GL_BGRA, GL_UNSIGNED_BYTE, image.bits()); @@ -3239,8 +3247,9 @@ void Application::computeOffAxisFrustum(float& left, float& right, float& bottom } glm::vec2 Application::getScaledScreenPoint(glm::vec2 projectedPoint) { - float horizontalScale = _glWidget->getDeviceWidth() / 2.0f; - float verticalScale = _glWidget->getDeviceHeight() / 2.0f; + GLCanvas* glCanvas = DependencyManager::get(); + float horizontalScale = glCanvas->getDeviceWidth() / 2.0f; + float verticalScale = glCanvas->getDeviceHeight() / 2.0f; // -1,-1 is 0,windowHeight // 1,1 is windowWidth,0 @@ -3259,7 +3268,7 @@ glm::vec2 Application::getScaledScreenPoint(glm::vec2 projectedPoint) { // -1,-1 1,-1 glm::vec2 screenPoint((projectedPoint.x + 1.0) * horizontalScale, - ((projectedPoint.y + 1.0) * -verticalScale) + _glWidget->getDeviceHeight()); + ((projectedPoint.y + 1.0) * -verticalScale) + glCanvas->getDeviceHeight()); return screenPoint; } @@ -3570,7 +3579,7 @@ void Application::resetSensors() { QScreen* currentScreen = _window->windowHandle()->screen(); QWindow* mainWindow = _window->windowHandle(); QPoint windowCenter = mainWindow->geometry().center(); - _glWidget->cursor().setPos(currentScreen, windowCenter); + DependencyManager::get()->cursor().setPos(currentScreen, windowCenter); _myAvatar->reset(); @@ -4251,7 +4260,8 @@ void Application::setPreviousScriptLocation(const QString& previousScriptLocatio void Application::loadDialog() { - QString fileNameString = QFileDialog::getOpenFileName(_glWidget, tr("Open Script"), + QString fileNameString = QFileDialog::getOpenFileName(DependencyManager::get(), + tr("Open Script"), getPreviousScriptLocation(), tr("JavaScript Files (*.js)")); if (!fileNameString.isEmpty()) { @@ -4287,7 +4297,7 @@ void Application::loadScriptURLDialog() { void Application::toggleLogDialog() { if (! _logDialog) { - _logDialog = new LogDialog(_glWidget, getLogger()); + _logDialog = new LogDialog(DependencyManager::get(), getLogger()); } if (_logDialog->isVisible()) { @@ -4347,7 +4357,7 @@ void Application::parseVersionXml() { } if (!shouldSkipVersion(latestVersion) && applicationVersion() != latestVersion) { - new UpdateDialog(_glWidget, releaseNotes, latestVersion, downloadUrl); + new UpdateDialog(DependencyManager::get(), releaseNotes, latestVersion, downloadUrl); } sender->deleteLater(); } @@ -4380,7 +4390,7 @@ void Application::takeSnapshot() { } if (!_snapshotShareDialog) { - _snapshotShareDialog = new SnapshotShareDialog(fileName, _glWidget); + _snapshotShareDialog = new SnapshotShareDialog(fileName, DependencyManager::get()); } _snapshotShareDialog->show(); } diff --git a/interface/src/Application.h b/interface/src/Application.h index c2136f1c57..cddaeaad15 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -171,46 +171,50 @@ public: void removeVoxel(glm::vec3 position, float scale); glm::vec3 getMouseVoxelWorldCoordinates(const VoxelDetail& mouseVoxel); + bool isThrottleRendering() const { return DependencyManager::get()->isThrottleRendering(); } - GLCanvas* getGLWidget() { return _glWidget; } - bool isThrottleRendering() const { return _glWidget->isThrottleRendering(); } + GLCanvas* getGLWidget() { return DependencyManager::get(); } // TODO: remove MyAvatar* getAvatar() { return _myAvatar; } Audio* getAudio() { return &_audio; } Camera* getCamera() { return &_myCamera; } ViewFrustum* getViewFrustum() { return &_viewFrustum; } ViewFrustum* getDisplayViewFrustum() { return &_displayViewFrustum; } ViewFrustum* getShadowViewFrustum() { return &_shadowViewFrustum; } - VoxelImporter* getVoxelImporter() { return &_voxelImporter; } VoxelSystem* getVoxels() { return &_voxels; } - VoxelTree* getVoxelTree() { return _voxels.getTree(); } const OctreePacketProcessor& getOctreePacketProcessor() const { return _octreeProcessor; } MetavoxelSystem* getMetavoxels() { return &_metavoxels; } EntityTreeRenderer* getEntities() { return &_entities; } - bool getImportSucceded() { return _importSucceded; } VoxelSystem* getSharedVoxelSystem() { return &_sharedVoxelSystem; } + Environment* getEnvironment() { return &_environment; } + PrioVR* getPrioVR() { return &_prioVR; } + QUndoStack* getUndoStack() { return &_undoStack; } + MainWindow* getWindow() { return _window; } + + VoxelImporter* getVoxelImporter() { return &_voxelImporter; } VoxelTree* getClipboard() { return &_clipboard; } EntityTree* getEntityClipboard() { return &_entityClipboard; } EntityTreeRenderer* getEntityClipboardRenderer() { return &_entityClipboardRenderer; } - Environment* getEnvironment() { return &_environment; } + VoxelTree* getVoxelTree() { return _voxels.getTree(); } + bool getImportSucceded() { return _importSucceded; } + bool isMousePressed() const { return _mousePressed; } - bool isMouseHidden() const { return _glWidget->cursor().shape() == Qt::BlankCursor; } + bool isMouseHidden() const { return DependencyManager::get()->cursor().shape() == Qt::BlankCursor; } void setCursorVisible(bool visible); const glm::vec3& getMouseRayOrigin() const { return _mouseRayOrigin; } const glm::vec3& getMouseRayDirection() const { return _mouseRayDirection; } bool mouseOnScreen() const; int getMouseX() const; int getMouseY() const; - int getTrueMouseX() const { return _glWidget->mapFromGlobal(QCursor::pos()).x(); } - int getTrueMouseY() const { return _glWidget->mapFromGlobal(QCursor::pos()).y(); } + int getTrueMouseX() const { return DependencyManager::get()->mapFromGlobal(QCursor::pos()).x(); } + int getTrueMouseY() const { return DependencyManager::get()->mapFromGlobal(QCursor::pos()).y(); } int getMouseDragStartedX() const; int getMouseDragStartedY() const; int getTrueMouseDragStartedX() const { return _mouseDragStartedX; } int getTrueMouseDragStartedY() const { return _mouseDragStartedY; } bool getLastMouseMoveWasSimulated() const { return _lastMouseMoveWasSimulated; } + FaceTracker* getActiveFaceTracker(); - PrioVR* getPrioVR() { return &_prioVR; } BandwidthMeter* getBandwidthMeter() { return &_bandwidthMeter; } - QUndoStack* getUndoStack() { return &_undoStack; } QSystemTrayIcon* getTrayIcon() { return _trayIcon; } ApplicationOverlay& getApplicationOverlay() { return _applicationOverlay; } Overlays& getOverlays() { return _overlays; } @@ -230,7 +234,6 @@ public: void saveSettings(); - MainWindow* getWindow() { return _window; } NodeToOctreeSceneStats* getOcteeSceneStats() { return &_octreeServerSceneStats; } void lockOctreeSceneStats() { _octreeSceneStatsLock.lockForRead(); } void unlockOctreeSceneStats() { _octreeSceneStatsLock.unlock(); } @@ -278,7 +281,8 @@ public: FileLogger* getLogger() { return _logger; } - glm::vec2 getViewportDimensions() const { return glm::vec2(_glWidget->getDeviceWidth(), _glWidget->getDeviceHeight()); } + glm::vec2 getViewportDimensions() const { return glm::vec2(DependencyManager::get()->getDeviceWidth(), + DependencyManager::get()->getDeviceHeight()); } NodeToJurisdictionMap& getVoxelServerJurisdictions() { return _voxelServerJurisdictions; } NodeToJurisdictionMap& getEntityServerJurisdictions() { return _entityServerJurisdictions; } void pasteVoxelsToOctalCode(const unsigned char* octalCodeDestination); @@ -456,7 +460,6 @@ private: int sendNackPackets(); MainWindow* _window; - GLCanvas* _glWidget; // our GLCanvas has a couple extra features ToolWindow* _toolWindow; diff --git a/interface/src/GLCanvas.h b/interface/src/GLCanvas.h index 0d381fa0bf..2b1cd3539d 100644 --- a/interface/src/GLCanvas.h +++ b/interface/src/GLCanvas.h @@ -15,11 +15,12 @@ #include #include +#include + /// customized canvas that simply forwards requests/events to the singleton application -class GLCanvas : public QGLWidget { +class GLCanvas : public QGLWidget, public DependencyManager::Dependency { Q_OBJECT public: - GLCanvas(); bool isThrottleRendering() const; int getDeviceWidth() const; @@ -56,6 +57,11 @@ private slots: void activeChanged(Qt::ApplicationState state); void throttleRender(); bool eventFilter(QObject*, QEvent* event); + +private: + GLCanvas(); + ~GLCanvas(); + friend class DependencyManager; }; #endif // hifi_GLCanvas_h From 4e7368b643a36f6bddc9ebcd3a7af93c895d6f2d Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 15 Dec 2014 12:09:30 -0800 Subject: [PATCH 407/502] more windows hackery --- libraries/shared/src/windowshacks.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libraries/shared/src/windowshacks.h b/libraries/shared/src/windowshacks.h index fcd2f5a7f2..3fd9d29fb3 100644 --- a/libraries/shared/src/windowshacks.h +++ b/libraries/shared/src/windowshacks.h @@ -15,6 +15,11 @@ #define hifi_windowshacks_h #ifdef WIN32 +// apparently needed to get M_PI and other defines from cmath/math.h +#define _USE_MATH_DEFINES +// needed to make sure windows doesn't go to crazy with its defines +#define WINDOWS_LEAN_AND_MEAN + #undef NOMINMAX #include From 95d820ee8b1265c50391a72f9f2110b407037218 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 15 Dec 2014 12:16:01 -0800 Subject: [PATCH 408/502] more windows hackery --- libraries/shared/src/windowshacks.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/shared/src/windowshacks.h b/libraries/shared/src/windowshacks.h index 3fd9d29fb3..e7397b29ee 100644 --- a/libraries/shared/src/windowshacks.h +++ b/libraries/shared/src/windowshacks.h @@ -20,7 +20,7 @@ // needed to make sure windows doesn't go to crazy with its defines #define WINDOWS_LEAN_AND_MEAN -#undef NOMINMAX +//#undef NOMINMAX #include inline double roundf(double value) { From 0b95403949d86d27b217e4bd2facd0af9b06dee2 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 15 Dec 2014 12:25:20 -0800 Subject: [PATCH 409/502] cleanup the windows hackery a little --- libraries/shared/src/windowshacks.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/libraries/shared/src/windowshacks.h b/libraries/shared/src/windowshacks.h index e7397b29ee..67c6f8be0c 100644 --- a/libraries/shared/src/windowshacks.h +++ b/libraries/shared/src/windowshacks.h @@ -15,12 +15,6 @@ #define hifi_windowshacks_h #ifdef WIN32 -// apparently needed to get M_PI and other defines from cmath/math.h -#define _USE_MATH_DEFINES -// needed to make sure windows doesn't go to crazy with its defines -#define WINDOWS_LEAN_AND_MEAN - -//#undef NOMINMAX #include inline double roundf(double value) { From a92b65b0e9d871d91b38a356b63890c27870bec7 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 15 Dec 2014 12:42:04 -0800 Subject: [PATCH 410/502] now lets see if this works --- interface/src/renderer/GeometryCache.h | 2 +- interface/src/renderer/TextureCache.cpp | 2 +- interface/src/renderer/TextureCache.h | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/interface/src/renderer/GeometryCache.h b/interface/src/renderer/GeometryCache.h index 2d813ece09..22857125af 100644 --- a/interface/src/renderer/GeometryCache.h +++ b/interface/src/renderer/GeometryCache.h @@ -13,7 +13,7 @@ #define hifi_GeometryCache_h // include this before QOpenGLBuffer, which includes an earlier version of OpenGL -#include "InterfaceConfig.h" +#include #include #include diff --git a/interface/src/renderer/TextureCache.cpp b/interface/src/renderer/TextureCache.cpp index 123a8a5384..1591f5cb26 100644 --- a/interface/src/renderer/TextureCache.cpp +++ b/interface/src/renderer/TextureCache.cpp @@ -10,7 +10,7 @@ // // include this before QGLWidget, which includes an earlier version of OpenGL -#include "InterfaceConfig.h" +#include #include #include diff --git a/interface/src/renderer/TextureCache.h b/interface/src/renderer/TextureCache.h index 2bdfda3217..56e29bc5fb 100644 --- a/interface/src/renderer/TextureCache.h +++ b/interface/src/renderer/TextureCache.h @@ -12,6 +12,8 @@ #ifndef hifi_TextureCache_h #define hifi_TextureCache_h +#include + #include #include #include @@ -19,8 +21,6 @@ #include #include -#include "InterfaceConfig.h" - class QOpenGLFramebufferObject; class NetworkTexture; From bf5147cd918bb9392cd57452c8e52fb58ab4fc88 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 15 Dec 2014 12:56:32 -0800 Subject: [PATCH 411/502] fix qt modules to link in LinkSharedDependencies --- cmake/macros/LinkSharedDependencies.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/macros/LinkSharedDependencies.cmake b/cmake/macros/LinkSharedDependencies.cmake index a73f57dc1d..afd25db0d7 100644 --- a/cmake/macros/LinkSharedDependencies.cmake +++ b/cmake/macros/LinkSharedDependencies.cmake @@ -25,7 +25,7 @@ macro(LINK_SHARED_DEPENDENCIES) endif () # we've already linked our Qt modules, but we need to bubble them up to parents - list(APPEND ${TARGET_NAME}_LIBRARIES_TO_LINK "${${TARGET}_QT_MODULES_TO_LINK}") + list(APPEND ${TARGET_NAME}_LIBRARIES_TO_LINK "${${TARGET_NAME}_QT_MODULES_TO_LINK}") # set the property on this target so it can be retreived by targets linking to us set_target_properties(${TARGET_NAME} PROPERTIES DEPENDENCY_LIBRARIES "${${TARGET_NAME}_LIBRARIES_TO_LINK}") From 7b973453b42bab53ee0a2cef396f3f9a94a22de1 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 15 Dec 2014 13:14:16 -0800 Subject: [PATCH 412/502] move TextureCache to library --- interface/CMakeLists.txt | 2 +- interface/src/Application.h | 4 +- interface/src/MetavoxelSystem.h | 2 +- interface/src/avatar/Avatar.cpp | 4 +- interface/src/renderer/GeometryCache.cpp | 2 +- interface/src/renderer/Model.h | 2 +- interface/src/ui/UpdateDialog.cpp | 2 +- interface/src/ui/overlays/BillboardOverlay.h | 3 +- libraries/render-utils/CMakeLists.txt | 46 +++++++++++++++++++ .../render-utils/src}/TextureCache.cpp | 0 .../render-utils/src}/TextureCache.h | 0 11 files changed, 59 insertions(+), 8 deletions(-) create mode 100644 libraries/render-utils/CMakeLists.txt rename {interface/src/renderer => libraries/render-utils/src}/TextureCache.cpp (100%) rename {interface/src/renderer => libraries/render-utils/src}/TextureCache.h (100%) diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 38dd02c655..ffc401ba63 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -107,7 +107,7 @@ endif() add_executable(${TARGET_NAME} MACOSX_BUNDLE ${INTERFACE_SRCS} ${QM}) # link required hifi libraries -link_hifi_libraries(shared octree voxels gpu fbx metavoxels networking entities avatars audio animation script-engine physics) +link_hifi_libraries(shared octree voxels gpu fbx metavoxels networking entities avatars audio animation script-engine physics render-utils) # find any optional and required libraries find_package(ZLIB REQUIRED) diff --git a/interface/src/Application.h b/interface/src/Application.h index d4a681f060..5a693ac21e 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -15,6 +15,8 @@ #include #include +#include + #include #include #include @@ -37,6 +39,7 @@ #include #include #include +#include #include #include @@ -61,7 +64,6 @@ #include "renderer/DeferredLightingEffect.h" #include "renderer/GeometryCache.h" #include "renderer/GlowEffect.h" -#include "renderer/TextureCache.h" #include "scripting/ControllerScriptingInterface.h" #include "ui/BandwidthDialog.h" #include "ui/BandwidthMeter.h" diff --git a/interface/src/MetavoxelSystem.h b/interface/src/MetavoxelSystem.h index 2ebf7e1146..0c0f9b49b7 100644 --- a/interface/src/MetavoxelSystem.h +++ b/interface/src/MetavoxelSystem.h @@ -20,9 +20,9 @@ #include #include +#include #include "renderer/ProgramObject.h" -#include "renderer/TextureCache.h" class HeightfieldBaseLayerBatch; class HeightfieldSplatBatch; diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 49a6f436df..39fc522852 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -11,6 +11,8 @@ #include +#include + #include #include @@ -25,6 +27,7 @@ #include #include #include +#include #include "Application.h" #include "Avatar.h" @@ -36,7 +39,6 @@ #include "Recorder.h" #include "world.h" #include "devices/OculusManager.h" -#include "renderer/TextureCache.h" #include "ui/TextRenderer.h" using namespace std; diff --git a/interface/src/renderer/GeometryCache.cpp b/interface/src/renderer/GeometryCache.cpp index 974a542b0e..4eae148259 100644 --- a/interface/src/renderer/GeometryCache.cpp +++ b/interface/src/renderer/GeometryCache.cpp @@ -19,9 +19,9 @@ #include #include +#include #include "GeometryCache.h" -#include "TextureCache.h" GeometryCache::GeometryCache() { } diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 9b609de1d0..334730b23b 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -22,13 +22,13 @@ #include #include #include +#include #include "AnimationHandle.h" #include "GeometryCache.h" #include "InterfaceConfig.h" #include "JointState.h" #include "ProgramObject.h" -#include "TextureCache.h" class QScriptEngine; diff --git a/interface/src/ui/UpdateDialog.cpp b/interface/src/ui/UpdateDialog.cpp index 33024586be..bd02ca910a 100644 --- a/interface/src/ui/UpdateDialog.cpp +++ b/interface/src/ui/UpdateDialog.cpp @@ -8,10 +8,10 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "Application.h" // HACK ATTACK WARNING: for windows build to work, we need this ahead of QtGui #include #include "ui_updateDialog.h" +#include "Application.h" #include "UpdateDialog.h" diff --git a/interface/src/ui/overlays/BillboardOverlay.h b/interface/src/ui/overlays/BillboardOverlay.h index c095a544b7..dcb8ab8b0c 100644 --- a/interface/src/ui/overlays/BillboardOverlay.h +++ b/interface/src/ui/overlays/BillboardOverlay.h @@ -15,8 +15,9 @@ #include #include +#include + #include "Base3DOverlay.h" -#include "renderer/TextureCache.h" class BillboardOverlay : public Base3DOverlay { Q_OBJECT diff --git a/libraries/render-utils/CMakeLists.txt b/libraries/render-utils/CMakeLists.txt new file mode 100644 index 0000000000..dea83a12a4 --- /dev/null +++ b/libraries/render-utils/CMakeLists.txt @@ -0,0 +1,46 @@ +set(TARGET_NAME render-utils) + +# use setup_hifi_library macro to setup our project and link appropriate Qt modules +setup_hifi_library(Widgets OpenGL Network) + +include_glm() + +link_hifi_libraries(shared gpu) +if (APPLE) + # link in required OS X frameworks and include the right GL headers + find_library(OpenGL OpenGL) + + target_link_libraries(${TARGET_NAME} ${OpenGL}) + +else (APPLE) + find_package(OpenGL REQUIRED) + + if (${OPENGL_INCLUDE_DIR}) + include_directories(SYSTEM "${OPENGL_INCLUDE_DIR}") + endif () + + #target_link_libraries(${TARGET_NAME} "${OPENGL_LIBRARY}") + + # link target to external libraries + if (WIN32) + find_package(GLEW REQUIRED) + include_directories(${GLEW_INCLUDE_DIRS}) + + # we're using static GLEW, so define GLEW_STATIC + add_definitions(-DGLEW_STATIC) + + #target_link_libraries(${TARGET_NAME} "${GLEW_LIBRARIES}" "${NSIGHT_LIBRARIES}" opengl32.lib) + + # try to find the Nsight package and add it to the build if we find it + #find_package(NSIGHT) + #if (NSIGHT_FOUND) + # include_directories(${NSIGHT_INCLUDE_DIRS}) + # add_definitions(-DNSIGHT_FOUND) + # #target_link_libraries(${TARGET_NAME} "${NSIGHT_LIBRARIES}") + #endif () + + endif() +endif (APPLE) + +# call macro to link our dependencies and bubble them up via a property on our target +link_shared_dependencies() diff --git a/interface/src/renderer/TextureCache.cpp b/libraries/render-utils/src/TextureCache.cpp similarity index 100% rename from interface/src/renderer/TextureCache.cpp rename to libraries/render-utils/src/TextureCache.cpp diff --git a/interface/src/renderer/TextureCache.h b/libraries/render-utils/src/TextureCache.h similarity index 100% rename from interface/src/renderer/TextureCache.h rename to libraries/render-utils/src/TextureCache.h From ea6d6e9f7265048ec21376215869f87e11a71ddd Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 15 Dec 2014 13:26:27 -0800 Subject: [PATCH 413/502] windows build hackery --- interface/src/ui/UpdateDialog.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/interface/src/ui/UpdateDialog.cpp b/interface/src/ui/UpdateDialog.cpp index bd02ca910a..4c75a10f1d 100644 --- a/interface/src/ui/UpdateDialog.cpp +++ b/interface/src/ui/UpdateDialog.cpp @@ -8,6 +8,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include + #include #include "ui_updateDialog.h" From dee8f69722587765f505965cb050b0ad8ee2f93b Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 15 Dec 2014 13:33:47 -0800 Subject: [PATCH 414/502] windows build hackery --- interface/src/voxels/VoxelSystem.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/interface/src/voxels/VoxelSystem.cpp b/interface/src/voxels/VoxelSystem.cpp index 357bfe9c3e..61ec4d6e6c 100644 --- a/interface/src/voxels/VoxelSystem.cpp +++ b/interface/src/voxels/VoxelSystem.cpp @@ -14,6 +14,8 @@ #include // to load voxels from file #include // to load voxels from file +#include + #include #include #include @@ -23,7 +25,6 @@ #include #include "Application.h" -#include "InterfaceConfig.h" #include "Menu.h" #include "renderer/ProgramObject.h" #include "VoxelConstants.h" From 4d8d6d602a269679aae5bf73e41103f8986c58b4 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 15 Dec 2014 13:56:21 -0800 Subject: [PATCH 415/502] simplify the FindTBB module for set envs --- BUILD_LINUX.md | 8 +- BUILD_OSX.md | 2 +- BUILD_WIN.md | 6 - cmake/modules/FindTBB.cmake | 328 +++++++----------------------------- 4 files changed, 62 insertions(+), 282 deletions(-) diff --git a/BUILD_LINUX.md b/BUILD_LINUX.md index 7b6c8f2176..08945716ae 100644 --- a/BUILD_LINUX.md +++ b/BUILD_LINUX.md @@ -9,10 +9,4 @@ In general, as long as external dependencies are placed in OS standard locations ###Qt5 Dependencies Should you choose not to install Qt5 via a package manager that handles dependencies for you, you may be missing some Qt5 dependencies. On Ubuntu, for example, the following additional packages are required: - libasound2 libxmu-dev libxi-dev freeglut3-dev libasound2-dev libjack-dev - -###Intel Threading Building Blocks (TBB) - -Install Intel TBB from your package manager of choice, or from source (available at the [TBB Website](https://www.threadingbuildingblocks.org/)). - -You must run `tbbvars` before running cmake that the find module included with this project will be able to find the correct version of TBB. `tbbvars` is located in the 'bin' folder of your TBB install. \ No newline at end of file + libasound2 libxmu-dev libxi-dev freeglut3-dev libasound2-dev libjack-dev \ No newline at end of file diff --git a/BUILD_OSX.md b/BUILD_OSX.md index 1eeaed1c13..cd947f2af4 100644 --- a/BUILD_OSX.md +++ b/BUILD_OSX.md @@ -19,4 +19,4 @@ If Xcode is your editor of choice, you can ask CMake to generate Xcode project f After running cmake, you will have the make files or Xcode project file necessary to build all of the components. Open the hifi.xcodeproj file, choose ALL_BUILD from the Product > Scheme menu (or target drop down), and click Run. -If the build completes successfully, you will have built targets for all components located in the `build/${target_name}/Debug` directories. +If the build completes successfully, you will have built targets for all components located in the `build/${target_name}/Debug` directories. \ No newline at end of file diff --git a/BUILD_WIN.md b/BUILD_WIN.md index bf7d421715..b90396b757 100644 --- a/BUILD_WIN.md +++ b/BUILD_WIN.md @@ -95,12 +95,6 @@ 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. -###Intel Threading Building Blocks (TBB) - -Download the stable release for Windows from the [Intel Threading Building Blocks website](https://www.threadingbuildingblocks.org/). By default, TBB will install to Program Files. You can choose to install it wherever you like, including %HIFI_LIB_DIR%. - -You must run `tbbvars.bat` before running cmake so that the find module included with this project will be able to find TBB no matter where you installed it. `tbbvars.bat` is located in the 'bin' folder of your TBB install. For a default installation on a 64-bit architechture, tbbvars can be found at `C:/Program Files (x86)/Intel/TBB/bin/tbbvars.bat`. - ###Zlib Download the compiled DLL from the [zlib website](http://www.zlib.net/). Extract to %HIFI_LIB_DIR%\zlib. diff --git a/cmake/modules/FindTBB.cmake b/cmake/modules/FindTBB.cmake index e5ca100391..c6c1890a09 100644 --- a/cmake/modules/FindTBB.cmake +++ b/cmake/modules/FindTBB.cmake @@ -1,283 +1,75 @@ -# Locate Intel Threading Building Blocks include paths and libraries -# FindTBB.cmake can be found at https://code.google.com/p/findtbb/ -# Written by Hannes Hofmann -# Improvements by Gino van den Bergen , -# Florian Uhlig , -# Jiri Marsik - -# The MIT License +# +# FindTBB.cmake +# +# Try to find the Intel Threading Building Blocks library # -# Copyright (c) 2011 Hannes Hofmann +# You can provide a TBB_ROOT_DIR which contains lib and include directories # -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: +# Once done this will define # -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. +# TBB_FOUND - system was able to find TBB +# TBB_INCLUDE_DIRS - the TBB include directory +# TBB_LIBRARIES - link this to use TBB # -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. - -# GvdB: This module uses the environment variable TBB_ARCH_PLATFORM which defines architecture and compiler. -# e.g. "ia32/vc8" or "em64t/cc4.1.0_libc2.4_kernel2.6.16.21" -# TBB_ARCH_PLATFORM is set by the build script tbbvars[.bat|.sh|.csh], which can be found -# in the TBB installation directory (TBB_INSTALL_DIR). +# Created on 12/14/2014 by Stephen Birarda +# Copyright 2014 High Fidelity, Inc. # -# GvdB: Mac OS X distribution places libraries directly in lib directory. -# -# For backwards compatibility, you may explicitely set the CMake variables TBB_ARCHITECTURE and TBB_COMPILER. -# TBB_ARCHITECTURE [ ia32 | em64t | itanium ] -# which architecture to use -# TBB_COMPILER e.g. vc9 or cc3.2.3_libc2.3.2_kernel2.4.21 or cc4.0.1_os10.4.9 -# which compiler to use (detected automatically on Windows) +# Distributed under the Apache License, Version 2.0. +# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +# -# This module respects -# TBB_INSTALL_DIR or $ENV{TBB21_INSTALL_DIR} or $ENV{TBB_INSTALL_DIR} +include("${MACRO_DIR}/HifiLibrarySearchHints.cmake") +hifi_library_search_hints("tbb") -# This module defines -# TBB_INCLUDE_DIRS, where to find task_scheduler_init.h, etc. -# TBB_LIBRARY_DIRS, where to find libtbb, libtbbmalloc -# TBB_DEBUG_LIBRARY_DIRS, where to find libtbb_debug, libtbbmalloc_debug -# TBB_INSTALL_DIR, the base TBB install directory -# TBB_LIBRARIES, the libraries to link against to use TBB. -# TBB_DEBUG_LIBRARIES, the libraries to link against to use TBB with debug symbols. -# TBB_FOUND, If false, don't try to use TBB. -# TBB_INTERFACE_VERSION, as defined in tbb/tbb_stddef.h +find_path(TBB_INCLUDE_DIRS tbb/tbb.h PATH_SUFFIXES include HINTS ${TBB_SEARCH_DIRS}) +set(_TBB_LIB_NAME "tbb") +set(_TBB_LIB_MALLOC_NAME "${_TBB_LIB_NAME}malloc") -if (WIN32) - # has em64t/vc8 em64t/vc9 - # has ia32/vc7.1 ia32/vc8 ia32/vc9 - set(_TBB_DEFAULT_INSTALL_DIR "C:/Program Files/Intel/TBB" "C:/Program Files (x86)/Intel/TBB") - set(_TBB_LIB_NAME "tbb") - set(_TBB_LIB_MALLOC_NAME "${_TBB_LIB_NAME}malloc") - set(_TBB_LIB_DEBUG_NAME "${_TBB_LIB_NAME}_debug") - set(_TBB_LIB_MALLOC_DEBUG_NAME "${_TBB_LIB_MALLOC_NAME}_debug") - if (MSVC71) - set (_TBB_COMPILER "vc7.1") - endif(MSVC71) - if (MSVC80) - set(_TBB_COMPILER "vc8") - endif(MSVC80) - if (MSVC90) - set(_TBB_COMPILER "vc9") - endif(MSVC90) - if(MSVC10) - set(_TBB_COMPILER "vc10") - endif(MSVC10) - # Todo: add other Windows compilers such as ICL. - set(_TBB_ARCHITECTURE ${TBB_ARCHITECTURE}) -endif (WIN32) +if (APPLE) + set(_TBB_LIB_DIR "lib/libc++") +elseif (UNIX) + if(CMAKE_SIZEOF_VOID_P EQUAL 8) + set(_TBB_ARCH_DIR "intel64") + else() + set(_TBB_ARCH_DIR "ia32") + endif() + + execute_process( + COMMAND ${CMAKE_C_COMPILER} -dumpversion + OUTPUT_VARIABLE GCC_VERSION + ) + + if (GCC_VERSION VERSION_GREATER 4.4 OR GCC_VERSION VERSION_EQUAL 4.4) + set(_TBB_LIB_DIR "${_TBB_ARCH_DIR}/gcc4.4") + elseif (GCC_VERSION VERSION_GREATER 4.1 OR GCC_VERSION VERSION_EQUAL 4.1) + set(_TBB_LIB_DIR "${_TBB_ARCH_DIR}/gcc4.1") + else () + message(FATAL_ERROR "Could not find a compatible version of Threading Building Blocks library for your compiler.") + endif () + +elseif (WIN32) + if (CMAKE_CL_64) + set(_TBB_ARCH_DIR "intel64") + else() + set(_TBB_ARCH_DIR "ia32") + endif() + + set(_TBB_LIB_DIR "${_TBB_ARCH_DIR}/vc12") +endif () -if (UNIX) - if (APPLE) - # MAC - set(_TBB_DEFAULT_INSTALL_DIR "/Library/Frameworks/Intel_TBB.framework/Versions") - # libs: libtbb.dylib, libtbbmalloc.dylib, *_debug - set(_TBB_LIB_NAME "tbb") - set(_TBB_LIB_MALLOC_NAME "${_TBB_LIB_NAME}malloc") - set(_TBB_LIB_DEBUG_NAME "${_TBB_LIB_NAME}_debug") - set(_TBB_LIB_MALLOC_DEBUG_NAME "${_TBB_LIB_MALLOC_NAME}_debug") - # default flavor on apple: ia32/cc4.0.1_os10.4.9 - # Jiri: There is no reason to presume there is only one flavor and - # that user's setting of variables should be ignored. - if(NOT TBB_COMPILER) - set(_TBB_COMPILER "cc4.0.1_os10.4.9") - elseif (NOT TBB_COMPILER) - set(_TBB_COMPILER ${TBB_COMPILER}) - endif(NOT TBB_COMPILER) - if(NOT TBB_ARCHITECTURE) - set(_TBB_ARCHITECTURE "ia32") - elseif(NOT TBB_ARCHITECTURE) - set(_TBB_ARCHITECTURE ${TBB_ARCHITECTURE}) - endif(NOT TBB_ARCHITECTURE) - else (APPLE) - # LINUX - set(_TBB_DEFAULT_INSTALL_DIR "/opt/intel/tbb" "/usr/local/include" "/usr/include") - set(_TBB_LIB_NAME "tbb") - set(_TBB_LIB_MALLOC_NAME "${_TBB_LIB_NAME}malloc") - set(_TBB_LIB_DEBUG_NAME "${_TBB_LIB_NAME}_debug") - set(_TBB_LIB_MALLOC_DEBUG_NAME "${_TBB_LIB_MALLOC_NAME}_debug") - # has em64t/cc3.2.3_libc2.3.2_kernel2.4.21 em64t/cc3.3.3_libc2.3.3_kernel2.6.5 em64t/cc3.4.3_libc2.3.4_kernel2.6.9 em64t/cc4.1.0_libc2.4_kernel2.6.16.21 - # has ia32/* - # has itanium/* - set(_TBB_COMPILER ${TBB_COMPILER}) - set(_TBB_ARCHITECTURE ${TBB_ARCHITECTURE}) - endif (APPLE) -endif (UNIX) +find_library(TBB_LIBRARY_DEBUG NAMES ${_TBB_LIB_NAME}_debug PATH_SUFFIXES ${_TBB_LIB_DIR} HINTS ${TBB_SEARCH_DIRS}) +find_library(TBB_LIBRARY_RELEASE NAMES ${_TBB_LIB_NAME} PATH_SUFFIXES ${_TBB_LIB_DIR} HINTS ${TBB_SEARCH_DIRS}) -if (CMAKE_SYSTEM MATCHES "SunOS.*") -# SUN -# not yet supported -# has em64t/cc3.4.3_kernel5.10 -# has ia32/* -endif (CMAKE_SYSTEM MATCHES "SunOS.*") +find_library(TBB_MALLOC_LIBRARY_DEBUG NAMES ${_TBB_LIB_MALLOC_NAME}_debug PATH_SUFFIXES ${_TBB_LIB_DIR} HINTS ${TBB_SEARCH_DIRS}) +find_library(TBB_MALLOC_LIBRARY_RELEASE NAMES ${_TBB_LIB_MALLOC_NAME} PATH_SUFFIXES ${_TBB_LIB_DIR} HINTS ${TBB_SEARCH_DIRS}) +include(SelectLibraryConfigurations) +include(FindPackageHandleStandardArgs) -#-- Clear the public variables -set (TBB_FOUND "NO") +select_library_configurations(TBB) +select_library_configurations(TBB_MALLOC) +find_package_handle_standard_args(TBB DEFAULT_MSG TBB_LIBRARY TBB_MALLOC_LIBRARY TBB_INCLUDE_DIRS) -#-- Find TBB install dir and set ${_TBB_INSTALL_DIR} and cached ${TBB_INSTALL_DIR} -# first: use CMake variable TBB_INSTALL_DIR -if (TBB_INSTALL_DIR) - set (_TBB_INSTALL_DIR ${TBB_INSTALL_DIR}) -endif (TBB_INSTALL_DIR) -# second: use environment variable -if (NOT _TBB_INSTALL_DIR) - if (NOT "$ENV{TBB_INSTALL_DIR}" STREQUAL "") - set (_TBB_INSTALL_DIR $ENV{TBB_INSTALL_DIR}) - endif (NOT "$ENV{TBB_INSTALL_DIR}" STREQUAL "") - # Intel recommends setting TBB21_INSTALL_DIR - if (NOT "$ENV{TBB21_INSTALL_DIR}" STREQUAL "") - set (_TBB_INSTALL_DIR $ENV{TBB21_INSTALL_DIR}) - endif (NOT "$ENV{TBB21_INSTALL_DIR}" STREQUAL "") - if (NOT "$ENV{TBB22_INSTALL_DIR}" STREQUAL "") - set (_TBB_INSTALL_DIR $ENV{TBB22_INSTALL_DIR}) - endif (NOT "$ENV{TBB22_INSTALL_DIR}" STREQUAL "") - if (NOT "$ENV{TBB30_INSTALL_DIR}" STREQUAL "") - set (_TBB_INSTALL_DIR $ENV{TBB30_INSTALL_DIR}) - endif (NOT "$ENV{TBB30_INSTALL_DIR}" STREQUAL "") -endif (NOT _TBB_INSTALL_DIR) -# third: try to find path automatically -if (NOT _TBB_INSTALL_DIR) - if (_TBB_DEFAULT_INSTALL_DIR) - set (_TBB_INSTALL_DIR ${_TBB_DEFAULT_INSTALL_DIR}) - endif (_TBB_DEFAULT_INSTALL_DIR) -endif (NOT _TBB_INSTALL_DIR) -# sanity check -if (NOT _TBB_INSTALL_DIR) - message ("ERROR: Unable to find Intel TBB install directory. ${_TBB_INSTALL_DIR}") -else (NOT _TBB_INSTALL_DIR) -# finally: set the cached CMake variable TBB_INSTALL_DIR -if (NOT TBB_INSTALL_DIR) - set (TBB_INSTALL_DIR ${_TBB_INSTALL_DIR} CACHE PATH "Intel TBB install directory") - mark_as_advanced(TBB_INSTALL_DIR) -endif (NOT TBB_INSTALL_DIR) - - -#-- A macro to rewrite the paths of the library. This is necessary, because -# find_library() always found the em64t/vc9 version of the TBB libs -macro(TBB_CORRECT_LIB_DIR var_name) -# if (NOT "${_TBB_ARCHITECTURE}" STREQUAL "em64t") - string(REPLACE em64t "${_TBB_ARCHITECTURE}" ${var_name} ${${var_name}}) -# endif (NOT "${_TBB_ARCHITECTURE}" STREQUAL "em64t") - string(REPLACE ia32 "${_TBB_ARCHITECTURE}" ${var_name} ${${var_name}}) - string(REPLACE vc7.1 "${_TBB_COMPILER}" ${var_name} ${${var_name}}) - string(REPLACE vc8 "${_TBB_COMPILER}" ${var_name} ${${var_name}}) - string(REPLACE vc9 "${_TBB_COMPILER}" ${var_name} ${${var_name}}) - string(REPLACE vc10 "${_TBB_COMPILER}" ${var_name} ${${var_name}}) -endmacro(TBB_CORRECT_LIB_DIR var_content) - - -#-- Look for include directory and set ${TBB_INCLUDE_DIR} -set (TBB_INC_SEARCH_DIR ${_TBB_INSTALL_DIR}/include) -# Jiri: tbbvars now sets the CPATH environment variable to the directory -# containing the headers. -find_path(TBB_INCLUDE_DIR - tbb/task_scheduler_init.h - PATHS ${TBB_INC_SEARCH_DIR} ENV CPATH -) -mark_as_advanced(TBB_INCLUDE_DIR) - - -#-- Look for libraries -# GvdB: $ENV{TBB_ARCH_PLATFORM} is set by the build script tbbvars[.bat|.sh|.csh] -if (NOT $ENV{TBB_ARCH_PLATFORM} STREQUAL "") - set (_TBB_LIBRARY_DIR - ${_TBB_INSTALL_DIR}/lib/$ENV{TBB_ARCH_PLATFORM} - ${_TBB_INSTALL_DIR}/$ENV{TBB_ARCH_PLATFORM}/lib - ) -endif (NOT $ENV{TBB_ARCH_PLATFORM} STREQUAL "") -# Jiri: This block isn't mutually exclusive with the previous one -# (hence no else), instead I test if the user really specified -# the variables in question. -if ((NOT ${TBB_ARCHITECTURE} STREQUAL "") AND (NOT ${TBB_COMPILER} STREQUAL "")) - # HH: deprecated - message(STATUS "[Warning] FindTBB.cmake: The use of TBB_ARCHITECTURE and TBB_COMPILER is deprecated and may not be supported in future versions. Please set \$ENV{TBB_ARCH_PLATFORM} (using tbbvars.[bat|csh|sh]).") - # Jiri: It doesn't hurt to look in more places, so I store the hints from - # ENV{TBB_ARCH_PLATFORM} and the TBB_ARCHITECTURE and TBB_COMPILER - # variables and search them both. - set (_TBB_LIBRARY_DIR "${_TBB_INSTALL_DIR}/${_TBB_ARCHITECTURE}/${_TBB_COMPILER}/lib" ${_TBB_LIBRARY_DIR}) -endif ((NOT ${TBB_ARCHITECTURE} STREQUAL "") AND (NOT ${TBB_COMPILER} STREQUAL "")) - -# GvdB: Mac OS X distribution places libraries directly in lib directory. -list(APPEND _TBB_LIBRARY_DIR ${_TBB_INSTALL_DIR}/lib) - -# Jiri: No reason not to check the default paths. From recent versions, -# tbbvars has started exporting the LIBRARY_PATH and LD_LIBRARY_PATH -# variables, which now point to the directories of the lib files. -# It all makes more sense to use the ${_TBB_LIBRARY_DIR} as a HINTS -# argument instead of the implicit PATHS as it isn't hard-coded -# but computed by system introspection. Searching the LIBRARY_PATH -# and LD_LIBRARY_PATH environment variables is now even more important -# that tbbvars doesn't export TBB_ARCH_PLATFORM and it facilitates -# the use of TBB built from sources. -find_library(TBB_LIBRARY ${_TBB_LIB_NAME} HINTS ${_TBB_LIBRARY_DIR} - PATHS ENV LIBRARY_PATH ENV LD_LIBRARY_PATH) -find_library(TBB_MALLOC_LIBRARY ${_TBB_LIB_MALLOC_NAME} HINTS ${_TBB_LIBRARY_DIR} - PATHS ENV LIBRARY_PATH ENV LD_LIBRARY_PATH) - -#Extract path from TBB_LIBRARY name -get_filename_component(TBB_LIBRARY_DIR ${TBB_LIBRARY} PATH) - -#TBB_CORRECT_LIB_DIR(TBB_LIBRARY) -#TBB_CORRECT_LIB_DIR(TBB_MALLOC_LIBRARY) -mark_as_advanced(TBB_LIBRARY TBB_MALLOC_LIBRARY) - -#-- Look for debug libraries -# Jiri: Changed the same way as for the release libraries. -find_library(TBB_LIBRARY_DEBUG ${_TBB_LIB_DEBUG_NAME} HINTS ${_TBB_LIBRARY_DIR} - PATHS ENV LIBRARY_PATH ENV LD_LIBRARY_PATH) -find_library(TBB_MALLOC_LIBRARY_DEBUG ${_TBB_LIB_MALLOC_DEBUG_NAME} HINTS ${_TBB_LIBRARY_DIR} - PATHS ENV LIBRARY_PATH ENV LD_LIBRARY_PATH) - -# Jiri: Self-built TBB stores the debug libraries in a separate directory. -# Extract path from TBB_LIBRARY_DEBUG name -get_filename_component(TBB_LIBRARY_DEBUG_DIR ${TBB_LIBRARY_DEBUG} PATH) - -#TBB_CORRECT_LIB_DIR(TBB_LIBRARY_DEBUG) -#TBB_CORRECT_LIB_DIR(TBB_MALLOC_LIBRARY_DEBUG) -mark_as_advanced(TBB_LIBRARY_DEBUG TBB_MALLOC_LIBRARY_DEBUG) - - -if (TBB_INCLUDE_DIR) - if (TBB_LIBRARY) - set (TBB_FOUND "YES") - set (TBB_LIBRARIES ${TBB_LIBRARY} ${TBB_MALLOC_LIBRARY} ${TBB_LIBRARIES}) - set (TBB_DEBUG_LIBRARIES ${TBB_LIBRARY_DEBUG} ${TBB_MALLOC_LIBRARY_DEBUG} ${TBB_DEBUG_LIBRARIES}) - set (TBB_INCLUDE_DIRS ${TBB_INCLUDE_DIR} CACHE PATH "TBB include directory" FORCE) - set (TBB_LIBRARY_DIRS ${TBB_LIBRARY_DIR} CACHE PATH "TBB library directory" FORCE) - # Jiri: Self-built TBB stores the debug libraries in a separate directory. - set (TBB_DEBUG_LIBRARY_DIRS ${TBB_LIBRARY_DEBUG_DIR} CACHE PATH "TBB debug library directory" FORCE) - mark_as_advanced(TBB_INCLUDE_DIRS TBB_LIBRARY_DIRS TBB_DEBUG_LIBRARY_DIRS TBB_LIBRARIES TBB_DEBUG_LIBRARIES) - message(STATUS "Found Intel TBB") - endif (TBB_LIBRARY) -endif (TBB_INCLUDE_DIR) - -if (NOT TBB_FOUND) - message("ERROR: Intel TBB NOT found!") - message(STATUS "Looked for Threading Building Blocks in ${_TBB_INSTALL_DIR}") - # do only throw fatal, if this pkg is REQUIRED - if (TBB_FIND_REQUIRED) - message(FATAL_ERROR "Could NOT find TBB library.") - endif (TBB_FIND_REQUIRED) -endif (NOT TBB_FOUND) - -endif (NOT _TBB_INSTALL_DIR) - -if (TBB_FOUND) - set(TBB_INTERFACE_VERSION 0) - FILE(READ "${TBB_INCLUDE_DIRS}/tbb/tbb_stddef.h" _TBB_VERSION_CONTENTS) - STRING(REGEX REPLACE ".*#define TBB_INTERFACE_VERSION ([0-9]+).*" "\\1" TBB_INTERFACE_VERSION "${_TBB_VERSION_CONTENTS}") - set(TBB_INTERFACE_VERSION "${TBB_INTERFACE_VERSION}") -endif (TBB_FOUND) +set(TBB_LIBRARIES ${TBB_LIBRARY} ${TBB_MALLOC_LIBRARY}) From e8ea45efdef2820f32c775a3b7caf3848a76639a Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 15 Dec 2014 13:59:51 -0800 Subject: [PATCH 416/502] clarify TBB find for windows --- BUILD_WIN.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/BUILD_WIN.md b/BUILD_WIN.md index b90396b757..ad143ef56a 100644 --- a/BUILD_WIN.md +++ b/BUILD_WIN.md @@ -95,6 +95,12 @@ 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. +###Intel Threading Building Blocks (TBB) + +Download the zip from the [TBB website](https://www.threadingbuildingblocks.org/). + +We recommend you extract it to %HIFI_LIB_DIR%\tbb. This will help our FindTBB cmake module find what it needs. You can place it wherever you like on your machine if you specify TBB_ROOT_DIR as an environment variable or a variable passed when cmake is run. + ###Zlib Download the compiled DLL from the [zlib website](http://www.zlib.net/). Extract to %HIFI_LIB_DIR%\zlib. From 49cacd85bd3abdce2524027ad83382bfbc110bff Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 15 Dec 2014 14:00:41 -0800 Subject: [PATCH 417/502] move GeometryCache to library --- interface/src/Application.h | 2 +- interface/src/renderer/Model.h | 4 ++-- libraries/render-utils/CMakeLists.txt | 2 +- .../renderer => libraries/render-utils/src}/GeometryCache.cpp | 2 +- .../renderer => libraries/render-utils/src}/GeometryCache.h | 0 5 files changed, 5 insertions(+), 5 deletions(-) rename {interface/src/renderer => libraries/render-utils/src}/GeometryCache.cpp (99%) rename {interface/src/renderer => libraries/render-utils/src}/GeometryCache.h (100%) diff --git a/interface/src/Application.h b/interface/src/Application.h index 5a693ac21e..64ef0970d7 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -34,6 +34,7 @@ #include #include +#include #include #include #include @@ -62,7 +63,6 @@ #include "entities/EntityTreeRenderer.h" #include "renderer/AmbientOcclusionEffect.h" #include "renderer/DeferredLightingEffect.h" -#include "renderer/GeometryCache.h" #include "renderer/GlowEffect.h" #include "scripting/ControllerScriptingInterface.h" #include "ui/BandwidthDialog.h" diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 334730b23b..c061bd85ac 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -16,16 +16,16 @@ #include #include -#include "Transform.h" #include #include #include +#include #include #include #include +#include #include "AnimationHandle.h" -#include "GeometryCache.h" #include "InterfaceConfig.h" #include "JointState.h" #include "ProgramObject.h" diff --git a/libraries/render-utils/CMakeLists.txt b/libraries/render-utils/CMakeLists.txt index dea83a12a4..bde26ea5ca 100644 --- a/libraries/render-utils/CMakeLists.txt +++ b/libraries/render-utils/CMakeLists.txt @@ -1,7 +1,7 @@ set(TARGET_NAME render-utils) # use setup_hifi_library macro to setup our project and link appropriate Qt modules -setup_hifi_library(Widgets OpenGL Network) +setup_hifi_library(Widgets OpenGL Network Script) include_glm() diff --git a/interface/src/renderer/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp similarity index 99% rename from interface/src/renderer/GeometryCache.cpp rename to libraries/render-utils/src/GeometryCache.cpp index 4eae148259..54239f1678 100644 --- a/interface/src/renderer/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -19,8 +19,8 @@ #include #include -#include +#include "TextureCache.h" #include "GeometryCache.h" GeometryCache::GeometryCache() { diff --git a/interface/src/renderer/GeometryCache.h b/libraries/render-utils/src/GeometryCache.h similarity index 100% rename from interface/src/renderer/GeometryCache.h rename to libraries/render-utils/src/GeometryCache.h From f63aa44d019ab38866192625a92fb4a2c952970c Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 15 Dec 2014 14:02:55 -0800 Subject: [PATCH 418/502] add lib to lib dirs for win and linux --- cmake/modules/FindTBB.cmake | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmake/modules/FindTBB.cmake b/cmake/modules/FindTBB.cmake index c6c1890a09..bce667b7d4 100644 --- a/cmake/modules/FindTBB.cmake +++ b/cmake/modules/FindTBB.cmake @@ -41,9 +41,9 @@ elseif (UNIX) ) if (GCC_VERSION VERSION_GREATER 4.4 OR GCC_VERSION VERSION_EQUAL 4.4) - set(_TBB_LIB_DIR "${_TBB_ARCH_DIR}/gcc4.4") + set(_TBB_LIB_DIR "lib/${_TBB_ARCH_DIR}/gcc4.4") elseif (GCC_VERSION VERSION_GREATER 4.1 OR GCC_VERSION VERSION_EQUAL 4.1) - set(_TBB_LIB_DIR "${_TBB_ARCH_DIR}/gcc4.1") + set(_TBB_LIB_DIR "lib/${_TBB_ARCH_DIR}/gcc4.1") else () message(FATAL_ERROR "Could not find a compatible version of Threading Building Blocks library for your compiler.") endif () @@ -55,7 +55,7 @@ elseif (WIN32) set(_TBB_ARCH_DIR "ia32") endif() - set(_TBB_LIB_DIR "${_TBB_ARCH_DIR}/vc12") + set(_TBB_LIB_DIR "lib/${_TBB_ARCH_DIR}/vc12") endif () find_library(TBB_LIBRARY_DEBUG NAMES ${_TBB_LIB_NAME}_debug PATH_SUFFIXES ${_TBB_LIB_DIR} HINTS ${TBB_SEARCH_DIRS}) From a3cc578fd15cd752689aab985c8141c137e20220 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 15 Dec 2014 14:08:23 -0800 Subject: [PATCH 419/502] use libc++ for C++11 in APPLE builds --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index f6e3f5c42c..7a6118bb87 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,6 +49,7 @@ endif() if (APPLE) set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LANGUAGE_STANDARD "c++0x") set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY "libc++") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --stdlib=libc++") endif () if (NOT QT_CMAKE_PREFIX_PATH) From df7e115556357717cf449fa37a91c97df54fb059 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 15 Dec 2014 14:21:22 -0800 Subject: [PATCH 420/502] move ProgramObject to libraries --- interface/src/Application.cpp | 2 +- interface/src/Environment.cpp | 2 +- interface/src/MetavoxelSystem.h | 3 +-- interface/src/avatar/Hand.cpp | 2 +- interface/src/devices/OculusManager.h | 3 ++- interface/src/renderer/AmbientOcclusionEffect.cpp | 2 +- interface/src/renderer/DeferredLightingEffect.h | 3 +-- interface/src/renderer/GlowEffect.cpp | 2 +- interface/src/renderer/Model.h | 2 +- interface/src/starfield/Config.h | 3 ++- interface/src/ui/MetavoxelEditor.h | 3 ++- interface/src/ui/overlays/Grid3DOverlay.h | 4 ++-- interface/src/voxels/VoxelSystem.cpp | 2 +- .../renderer => libraries/render-utils/src}/ProgramObject.cpp | 3 ++- .../renderer => libraries/render-utils/src}/ProgramObject.h | 0 15 files changed, 19 insertions(+), 17 deletions(-) rename {interface/src/renderer => libraries/render-utils/src}/ProgramObject.cpp (99%) rename {interface/src/renderer => libraries/render-utils/src}/ProgramObject.h (100%) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 766424ef4b..990f05d0de 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -66,6 +66,7 @@ #include #include #include +#include #include #include #include @@ -85,7 +86,6 @@ #include "devices/TV3DManager.h" #include "devices/Visage.h" -#include "renderer/ProgramObject.h" #include "gpu/Batch.h" #include "gpu/GLBackend.h" diff --git a/interface/src/Environment.cpp b/interface/src/Environment.cpp index fa8f18ac3f..c482095494 100644 --- a/interface/src/Environment.cpp +++ b/interface/src/Environment.cpp @@ -17,11 +17,11 @@ #include #include +#include #include #include "Application.h" #include "Camera.h" -#include "renderer/ProgramObject.h" #include "world.h" #include "Environment.h" diff --git a/interface/src/MetavoxelSystem.h b/interface/src/MetavoxelSystem.h index 0c0f9b49b7..a21cd2c1a4 100644 --- a/interface/src/MetavoxelSystem.h +++ b/interface/src/MetavoxelSystem.h @@ -20,10 +20,9 @@ #include #include +#include #include -#include "renderer/ProgramObject.h" - class HeightfieldBaseLayerBatch; class HeightfieldSplatBatch; class HermiteBatch; diff --git a/interface/src/avatar/Hand.cpp b/interface/src/avatar/Hand.cpp index 9d1ee52fde..9d7626266d 100644 --- a/interface/src/avatar/Hand.cpp +++ b/interface/src/avatar/Hand.cpp @@ -13,13 +13,13 @@ #include #include +#include #include "Application.h" #include "Avatar.h" #include "Hand.h" #include "Menu.h" #include "Util.h" -#include "renderer/ProgramObject.h" using namespace std; diff --git a/interface/src/devices/OculusManager.h b/interface/src/devices/OculusManager.h index 2e0354f61a..d9700d9530 100644 --- a/interface/src/devices/OculusManager.h +++ b/interface/src/devices/OculusManager.h @@ -17,7 +17,8 @@ #include #endif -#include "renderer/ProgramObject.h" +#include + #include "ui/overlays/Text3DOverlay.h" const float DEFAULT_OCULUS_UI_ANGULAR_SIZE = 72.0f; diff --git a/interface/src/renderer/AmbientOcclusionEffect.cpp b/interface/src/renderer/AmbientOcclusionEffect.cpp index 3354f715cb..415b850abd 100644 --- a/interface/src/renderer/AmbientOcclusionEffect.cpp +++ b/interface/src/renderer/AmbientOcclusionEffect.cpp @@ -16,10 +16,10 @@ #include +#include #include #include "Application.h" -#include "ProgramObject.h" #include "RenderUtil.h" #include "AmbientOcclusionEffect.h" diff --git a/interface/src/renderer/DeferredLightingEffect.h b/interface/src/renderer/DeferredLightingEffect.h index ce8b2b9759..effcea27d2 100644 --- a/interface/src/renderer/DeferredLightingEffect.h +++ b/interface/src/renderer/DeferredLightingEffect.h @@ -14,10 +14,9 @@ #include +#include #include -#include "ProgramObject.h" - class PostLightingRenderable; /// Handles deferred lighting for the bits that require it (voxels, metavoxels...) diff --git a/interface/src/renderer/GlowEffect.cpp b/interface/src/renderer/GlowEffect.cpp index b6896eeaad..77d002dc89 100644 --- a/interface/src/renderer/GlowEffect.cpp +++ b/interface/src/renderer/GlowEffect.cpp @@ -15,10 +15,10 @@ #include #include +#include #include "Application.h" #include "GlowEffect.h" -#include "ProgramObject.h" #include "RenderUtil.h" GlowEffect::GlowEffect() diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index c061bd85ac..1f0a571872 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -22,13 +22,13 @@ #include #include #include +#include #include #include #include "AnimationHandle.h" #include "InterfaceConfig.h" #include "JointState.h" -#include "ProgramObject.h" class QScriptEngine; diff --git a/interface/src/starfield/Config.h b/interface/src/starfield/Config.h index 7777c5207b..00f827dad7 100644 --- a/interface/src/starfield/Config.h +++ b/interface/src/starfield/Config.h @@ -13,7 +13,6 @@ #define hifi_Config_h #include "InterfaceConfig.h" -#include "renderer/ProgramObject.h" #include #include @@ -35,6 +34,8 @@ #include #include +#include + #include "AngleUtil.h" #include "Radix2InplaceSort.h" #include "Radix2IntegerScanner.h" diff --git a/interface/src/ui/MetavoxelEditor.h b/interface/src/ui/MetavoxelEditor.h index c154d7bc59..391b01270a 100644 --- a/interface/src/ui/MetavoxelEditor.h +++ b/interface/src/ui/MetavoxelEditor.h @@ -15,8 +15,9 @@ #include #include +#include + #include "MetavoxelSystem.h" -#include "renderer/ProgramObject.h" class QColorEditor; class QComboBox; diff --git a/interface/src/ui/overlays/Grid3DOverlay.h b/interface/src/ui/overlays/Grid3DOverlay.h index b162ff3d74..d6c85a10ee 100644 --- a/interface/src/ui/overlays/Grid3DOverlay.h +++ b/interface/src/ui/overlays/Grid3DOverlay.h @@ -18,12 +18,12 @@ #include #include + +#include #include #include "Base3DOverlay.h" -#include "renderer/ProgramObject.h" - class Grid3DOverlay : public Base3DOverlay { Q_OBJECT diff --git a/interface/src/voxels/VoxelSystem.cpp b/interface/src/voxels/VoxelSystem.cpp index 61ec4d6e6c..064cead160 100644 --- a/interface/src/voxels/VoxelSystem.cpp +++ b/interface/src/voxels/VoxelSystem.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -26,7 +27,6 @@ #include "Application.h" #include "Menu.h" -#include "renderer/ProgramObject.h" #include "VoxelConstants.h" #include "VoxelSystem.h" diff --git a/interface/src/renderer/ProgramObject.cpp b/libraries/render-utils/src/ProgramObject.cpp similarity index 99% rename from interface/src/renderer/ProgramObject.cpp rename to libraries/render-utils/src/ProgramObject.cpp index ff2b1cc11e..56fd48bff7 100644 --- a/interface/src/renderer/ProgramObject.cpp +++ b/libraries/render-utils/src/ProgramObject.cpp @@ -9,9 +9,10 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "ProgramObject.h" #include +#include "ProgramObject.h" + ProgramObject::ProgramObject(QObject* parent) : QGLShaderProgram(parent) { } diff --git a/interface/src/renderer/ProgramObject.h b/libraries/render-utils/src/ProgramObject.h similarity index 100% rename from interface/src/renderer/ProgramObject.h rename to libraries/render-utils/src/ProgramObject.h From f802e99a24c89c34a5003caf7c90625019adff59 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 15 Dec 2014 14:32:33 -0800 Subject: [PATCH 421/502] windows build hackery --- interface/src/renderer/Model.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 1f0a571872..c79a6c2efd 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -12,6 +12,8 @@ #ifndef hifi_Model_h #define hifi_Model_h +#include + #include #include #include @@ -27,7 +29,6 @@ #include #include "AnimationHandle.h" -#include "InterfaceConfig.h" #include "JointState.h" class QScriptEngine; From bc78beb05fcea9ce536a0fabc5c88078cbb12439 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 15 Dec 2014 14:41:15 -0800 Subject: [PATCH 422/502] windows build hackery --- interface/src/avatar/ModelReferential.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/interface/src/avatar/ModelReferential.cpp b/interface/src/avatar/ModelReferential.cpp index df6e272da7..d37879c6e1 100644 --- a/interface/src/avatar/ModelReferential.cpp +++ b/interface/src/avatar/ModelReferential.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include // hack to get windows to build + #include #include From 0c14b0f8fc9acfbc6ce68a139b149d9f6dbd8f1b Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 15 Dec 2014 14:47:26 -0800 Subject: [PATCH 423/502] windows build hackery --- interface/src/avatar/Hand.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/interface/src/avatar/Hand.cpp b/interface/src/avatar/Hand.cpp index 9d7626266d..91d59ae2fa 100644 --- a/interface/src/avatar/Hand.cpp +++ b/interface/src/avatar/Hand.cpp @@ -8,6 +8,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include // hack to get windows to build + #include #include From 753dc07cdd61039ad2d87ef78002d95e9f3b605a Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 15 Dec 2014 14:58:47 -0800 Subject: [PATCH 424/502] cleanup windows hackery --- interface/src/avatar/ModelReferential.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/interface/src/avatar/ModelReferential.cpp b/interface/src/avatar/ModelReferential.cpp index d37879c6e1..df6e272da7 100644 --- a/interface/src/avatar/ModelReferential.cpp +++ b/interface/src/avatar/ModelReferential.cpp @@ -9,8 +9,6 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include // hack to get windows to build - #include #include From bfcc78c57d7fa4a9c19f514c079e5b05bcda6f06 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 15 Dec 2014 15:20:18 -0800 Subject: [PATCH 425/502] replaced Application::resourcesPath() with PathUtils::resourcesPath() --- interface/src/Application.cpp | 16 ++--- interface/src/Application.h | 1 - interface/src/Audio.cpp | 7 +- interface/src/Environment.cpp | 3 +- interface/src/Menu.cpp | 3 +- interface/src/MetavoxelSystem.cpp | 21 +++--- interface/src/avatar/Avatar.cpp | 5 +- interface/src/devices/OculusManager.cpp | 5 +- interface/src/devices/Visage.cpp | 7 +- .../src/renderer/AmbientOcclusionEffect.cpp | 9 +-- .../src/renderer/DeferredLightingEffect.cpp | 10 +-- interface/src/renderer/GlowEffect.cpp | 3 +- interface/src/renderer/Model.cpp | 65 ++++++++++--------- interface/src/ui/AddressBarDialog.cpp | 10 +-- interface/src/ui/ApplicationOverlay.cpp | 6 +- interface/src/ui/ChatWindow.cpp | 7 +- interface/src/ui/FramelessDialog.cpp | 8 ++- interface/src/ui/InfoView.cpp | 9 ++- interface/src/ui/JSConsole.cpp | 9 +-- interface/src/ui/LogDialog.cpp | 6 +- interface/src/ui/LoginDialog.cpp | 7 +- interface/src/ui/MetavoxelEditor.cpp | 3 +- interface/src/ui/RearMirrorTools.cpp | 11 ++-- interface/src/ui/RunningScriptsWidget.cpp | 4 +- interface/src/ui/VoxelImportDialog.cpp | 22 ++++--- interface/src/ui/overlays/Grid3DOverlay.cpp | 5 +- interface/src/voxels/VoxelSystem.cpp | 9 +-- libraries/shared/src/PathUtils.cpp | 25 +++++++ libraries/shared/src/PathUtils.h | 22 +++++++ 29 files changed, 194 insertions(+), 124 deletions(-) create mode 100644 libraries/shared/src/PathUtils.cpp create mode 100644 libraries/shared/src/PathUtils.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 990f05d0de..76247d1d9d 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -65,6 +65,7 @@ #include #include #include +#include #include #include #include @@ -133,15 +134,6 @@ void messageHandler(QtMsgType type, const QMessageLogContext& context, const QSt } } -QString& Application::resourcesPath() { -#ifdef Q_OS_MAC - static QString staticResourcePath = QCoreApplication::applicationDirPath() + "/../Resources/"; -#else - static QString staticResourcePath = QCoreApplication::applicationDirPath() + "/resources/"; -#endif - return staticResourcePath; -} - Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : QApplication(argc, argv), _window(new MainWindow(desktop())), @@ -195,7 +187,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : _aboutToQuit(false) { // read the ApplicationInfo.ini file for Name/Version/Domain information - QSettings applicationInfo(Application::resourcesPath() + "info/ApplicationInfo.ini", QSettings::IniFormat); + QSettings applicationInfo(PathUtils::resourcesPath() + "info/ApplicationInfo.ini", QSettings::IniFormat); // set the associated application properties applicationInfo.beginGroup("INFO"); @@ -213,7 +205,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : _applicationStartupTime = startup_time; - QFontDatabase::addApplicationFont(Application::resourcesPath() + "styles/Inconsolata.otf"); + QFontDatabase::addApplicationFont(PathUtils::resourcesPath() + "styles/Inconsolata.otf"); _window->setWindowTitle("Interface"); qInstallMessageHandler(messageHandler); @@ -4369,7 +4361,7 @@ void Application::skipVersion(QString latestVersion) { void Application::takeSnapshot() { QMediaPlayer* player = new QMediaPlayer(); - QFileInfo inf = QFileInfo(Application::resourcesPath() + "sounds/snap.wav"); + QFileInfo inf = QFileInfo(PathUtils::resourcesPath() + "sounds/snap.wav"); player->setMedia(QUrl::fromLocalFile(inf.absoluteFilePath())); player->play(); diff --git a/interface/src/Application.h b/interface/src/Application.h index 64ef0970d7..0e1feafb7e 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -138,7 +138,6 @@ class Application : public QApplication { public: static Application* getInstance() { return static_cast(QCoreApplication::instance()); } - static QString& resourcesPath(); static const glm::vec3& getPositionForPath() { return getInstance()->_myAvatar->getPosition(); } static glm::quat getOrientationForPath() { return getInstance()->_myAvatar->getOrientation(); } diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index 101d16d3ba..74ee9736a7 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -140,9 +141,9 @@ Audio::Audio(QObject* parent) : } void Audio::init(QGLWidget *parent) { - _micTextureId = parent->bindTexture(QImage(Application::resourcesPath() + "images/mic.svg")); - _muteTextureId = parent->bindTexture(QImage(Application::resourcesPath() + "images/mic-mute.svg")); - _boxTextureId = parent->bindTexture(QImage(Application::resourcesPath() + "images/audio-box.svg")); + _micTextureId = parent->bindTexture(QImage(PathUtils::resourcesPath() + "images/mic.svg")); + _muteTextureId = parent->bindTexture(QImage(PathUtils::resourcesPath() + "images/mic-mute.svg")); + _boxTextureId = parent->bindTexture(QImage(PathUtils::resourcesPath() + "images/audio-box.svg")); } void Audio::reset() { diff --git a/interface/src/Environment.cpp b/interface/src/Environment.cpp index c482095494..1fd3c7a73c 100644 --- a/interface/src/Environment.cpp +++ b/interface/src/Environment.cpp @@ -17,6 +17,7 @@ #include #include +#include #include #include @@ -188,7 +189,7 @@ int Environment::parseData(const HifiSockAddr& senderAddress, const QByteArray& ProgramObject* Environment::createSkyProgram(const char* from, int* locations) { ProgramObject* program = new ProgramObject(); - QByteArray prefix = QString(Application::resourcesPath() + "/shaders/SkyFrom" + from).toUtf8(); + QByteArray prefix = QString(PathUtils::resourcesPath() + "/shaders/SkyFrom" + from).toUtf8(); program->addShaderFromSourceFile(QGLShader::Vertex, prefix + ".vert"); program->addShaderFromSourceFile(QGLShader::Fragment, prefix + ".frag"); program->link(); diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 6c2c3966fc..fbb23504b0 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -246,7 +247,7 @@ Menu::Menu() : connect(&xmppClient, &QXmppClient::connected, this, &Menu::toggleChat); connect(&xmppClient, &QXmppClient::disconnected, this, &Menu::toggleChat); - QDir::setCurrent(Application::resourcesPath()); + QDir::setCurrent(PathUtils::resourcesPath()); // init chat window to listen chat _chatWindow = new ChatWindow(Application::getInstance()->getWindow()); #endif diff --git a/interface/src/MetavoxelSystem.cpp b/interface/src/MetavoxelSystem.cpp index 84ccf0f406..372c5214f7 100644 --- a/interface/src/MetavoxelSystem.cpp +++ b/interface/src/MetavoxelSystem.cpp @@ -26,6 +26,7 @@ #include #include +#include #include #include "Application.h" @@ -63,9 +64,9 @@ void MetavoxelSystem::init() { _voxelBufferAttribute->setLODThresholdMultiplier( AttributeRegistry::getInstance()->getVoxelColorAttribute()->getLODThresholdMultiplier()); - _baseHeightfieldProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + + _baseHeightfieldProgram.addShaderFromSourceFile(QGLShader::Vertex, PathUtils::resourcesPath() + "shaders/metavoxel_heightfield_base.vert"); - _baseHeightfieldProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + + _baseHeightfieldProgram.addShaderFromSourceFile(QGLShader::Fragment, PathUtils::resourcesPath() + "shaders/metavoxel_heightfield_base.frag"); _baseHeightfieldProgram.link(); @@ -78,9 +79,9 @@ void MetavoxelSystem::init() { loadSplatProgram("heightfield", _splatHeightfieldProgram, _splatHeightfieldLocations); - _heightfieldCursorProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + + _heightfieldCursorProgram.addShaderFromSourceFile(QGLShader::Vertex, PathUtils::resourcesPath() + "shaders/metavoxel_heightfield_cursor.vert"); - _heightfieldCursorProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + + _heightfieldCursorProgram.addShaderFromSourceFile(QGLShader::Fragment, PathUtils::resourcesPath() + "shaders/metavoxel_cursor.frag"); _heightfieldCursorProgram.link(); @@ -88,17 +89,17 @@ void MetavoxelSystem::init() { _heightfieldCursorProgram.setUniformValue("heightMap", 0); _heightfieldCursorProgram.release(); - _baseVoxelProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + + _baseVoxelProgram.addShaderFromSourceFile(QGLShader::Vertex, PathUtils::resourcesPath() + "shaders/metavoxel_voxel_base.vert"); - _baseVoxelProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + + _baseVoxelProgram.addShaderFromSourceFile(QGLShader::Fragment, PathUtils::resourcesPath() + "shaders/metavoxel_voxel_base.frag"); _baseVoxelProgram.link(); loadSplatProgram("voxel", _splatVoxelProgram, _splatVoxelLocations); - _voxelCursorProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + + _voxelCursorProgram.addShaderFromSourceFile(QGLShader::Vertex, PathUtils::resourcesPath() + "shaders/metavoxel_voxel_cursor.vert"); - _voxelCursorProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + + _voxelCursorProgram.addShaderFromSourceFile(QGLShader::Fragment, PathUtils::resourcesPath() + "shaders/metavoxel_cursor.frag"); _voxelCursorProgram.link(); } @@ -836,9 +837,9 @@ void MetavoxelSystem::guideToAugmented(MetavoxelVisitor& visitor, bool render) { } void MetavoxelSystem::loadSplatProgram(const char* type, ProgramObject& program, SplatLocations& locations) { - program.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + + program.addShaderFromSourceFile(QGLShader::Vertex, PathUtils::resourcesPath() + "shaders/metavoxel_" + type + "_splat.vert"); - program.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + + program.addShaderFromSourceFile(QGLShader::Fragment, PathUtils::resourcesPath() + "shaders/metavoxel_" + type + "_splat.frag"); program.link(); diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 39fc522852..e0896364f6 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -915,13 +916,13 @@ void Avatar::scaleVectorRelativeToPosition(glm::vec3 &positionToScale) const { void Avatar::setFaceModelURL(const QUrl& faceModelURL) { AvatarData::setFaceModelURL(faceModelURL); - const QUrl DEFAULT_FACE_MODEL_URL = QUrl::fromLocalFile(Application::resourcesPath() + "meshes/defaultAvatar_head.fst"); + const QUrl DEFAULT_FACE_MODEL_URL = QUrl::fromLocalFile(PathUtils::resourcesPath() + "meshes/defaultAvatar_head.fst"); getHead()->getFaceModel().setURL(_faceModelURL, DEFAULT_FACE_MODEL_URL, true, !isMyAvatar()); } void Avatar::setSkeletonModelURL(const QUrl& skeletonModelURL) { AvatarData::setSkeletonModelURL(skeletonModelURL); - const QUrl DEFAULT_SKELETON_MODEL_URL = QUrl::fromLocalFile(Application::resourcesPath() + "meshes/defaultAvatar_body.fst"); + const QUrl DEFAULT_SKELETON_MODEL_URL = QUrl::fromLocalFile(PathUtils::resourcesPath() + "meshes/defaultAvatar_body.fst"); _skeletonModel.setURL(_skeletonModelURL, DEFAULT_SKELETON_MODEL_URL, true, !isMyAvatar()); } diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index d27ab09876..7f5c2cd668 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -21,6 +21,7 @@ #include +#include #include #include @@ -136,8 +137,8 @@ void OculusManager::connect() { if (!_programInitialized) { // Shader program _programInitialized = true; - _program.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/oculus.vert"); - _program.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + "shaders/oculus.frag"); + _program.addShaderFromSourceFile(QGLShader::Vertex, PathUtils::resourcesPath() + "shaders/oculus.vert"); + _program.addShaderFromSourceFile(QGLShader::Fragment, PathUtils::resourcesPath() + "shaders/oculus.frag"); _program.link(); // Uniforms diff --git a/interface/src/devices/Visage.cpp b/interface/src/devices/Visage.cpp index 51b927df75..189ad90e12 100644 --- a/interface/src/devices/Visage.cpp +++ b/interface/src/devices/Visage.cpp @@ -14,6 +14,7 @@ #include #include +#include #include #include @@ -45,12 +46,12 @@ Visage::Visage() : #ifdef HAVE_VISAGE #ifdef WIN32 - QByteArray licensePath = Application::resourcesPath().toLatin1() + "visage"; + QByteArray licensePath = PathUtils::resourcesPath().toLatin1() + "visage"; #else - QByteArray licensePath = Application::resourcesPath().toLatin1() + "visage/license.vlc"; + QByteArray licensePath = PathUtils::resourcesPath().toLatin1() + "visage/license.vlc"; #endif initializeLicenseManager(licensePath.data()); - _tracker = new VisageTracker2(Application::resourcesPath().toLatin1() + "visage/tracker.cfg"); + _tracker = new VisageTracker2(PathUtils::resourcesPath().toLatin1() + "visage/tracker.cfg"); _data = new FaceData(); #endif } diff --git a/interface/src/renderer/AmbientOcclusionEffect.cpp b/interface/src/renderer/AmbientOcclusionEffect.cpp index 415b850abd..08ad6703e6 100644 --- a/interface/src/renderer/AmbientOcclusionEffect.cpp +++ b/interface/src/renderer/AmbientOcclusionEffect.cpp @@ -16,6 +16,7 @@ #include +#include #include #include @@ -30,9 +31,9 @@ const int ROTATION_HEIGHT = 4; void AmbientOcclusionEffect::init() { _occlusionProgram = new ProgramObject(); - _occlusionProgram->addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + _occlusionProgram->addShaderFromSourceFile(QGLShader::Vertex, PathUtils::resourcesPath() + "shaders/ambient_occlusion.vert"); - _occlusionProgram->addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + _occlusionProgram->addShaderFromSourceFile(QGLShader::Fragment, PathUtils::resourcesPath() + "shaders/ambient_occlusion.frag"); _occlusionProgram->link(); @@ -82,8 +83,8 @@ void AmbientOcclusionEffect::init() { glBindTexture(GL_TEXTURE_2D, 0); _blurProgram = new ProgramObject(); - _blurProgram->addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/ambient_occlusion.vert"); - _blurProgram->addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + "shaders/occlusion_blur.frag"); + _blurProgram->addShaderFromSourceFile(QGLShader::Vertex, PathUtils::resourcesPath() + "shaders/ambient_occlusion.vert"); + _blurProgram->addShaderFromSourceFile(QGLShader::Fragment, PathUtils::resourcesPath() + "shaders/occlusion_blur.frag"); _blurProgram->link(); _blurProgram->bind(); diff --git a/interface/src/renderer/DeferredLightingEffect.cpp b/interface/src/renderer/DeferredLightingEffect.cpp index 22ac5d82b6..79b89d03f9 100644 --- a/interface/src/renderer/DeferredLightingEffect.cpp +++ b/interface/src/renderer/DeferredLightingEffect.cpp @@ -14,13 +14,15 @@ #include +#include + #include "Application.h" #include "DeferredLightingEffect.h" #include "RenderUtil.h" void DeferredLightingEffect::init() { - _simpleProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/simple.vert"); - _simpleProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + "shaders/simple.frag"); + _simpleProgram.addShaderFromSourceFile(QGLShader::Vertex, PathUtils::resourcesPath() + "shaders/simple.vert"); + _simpleProgram.addShaderFromSourceFile(QGLShader::Fragment, PathUtils::resourcesPath() + "shaders/simple.frag"); _simpleProgram.link(); _simpleProgram.bind(); @@ -394,9 +396,9 @@ void DeferredLightingEffect::render() { } void DeferredLightingEffect::loadLightProgram(const char* name, bool limited, ProgramObject& program, LightLocations& locations) { - program.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + + program.addShaderFromSourceFile(QGLShader::Vertex, PathUtils::resourcesPath() + (limited ? "shaders/deferred_light_limited.vert" : "shaders/deferred_light.vert")); - program.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + name); + program.addShaderFromSourceFile(QGLShader::Fragment, PathUtils::resourcesPath() + name); program.link(); program.bind(); diff --git a/interface/src/renderer/GlowEffect.cpp b/interface/src/renderer/GlowEffect.cpp index 77d002dc89..a53c9f878b 100644 --- a/interface/src/renderer/GlowEffect.cpp +++ b/interface/src/renderer/GlowEffect.cpp @@ -14,6 +14,7 @@ #include +#include #include #include @@ -47,7 +48,7 @@ QOpenGLFramebufferObject* GlowEffect::getFreeFramebufferObject() const { static ProgramObject* createProgram(const QString& name) { ProgramObject* program = new ProgramObject(); - program->addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + "shaders/" + name + ".frag"); + program->addShaderFromSourceFile(QGLShader::Fragment, PathUtils::resourcesPath() + "shaders/" + name + ".frag"); program->link(); program->bind(); diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 2a6988a984..71f0fb24f3 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -222,109 +223,109 @@ void Model::initJointTransforms() { void Model::init() { if (!_program.isLinked()) { - _program.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/model.vert"); - _program.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + "shaders/model.frag"); + _program.addShaderFromSourceFile(QGLShader::Vertex, PathUtils::resourcesPath() + "shaders/model.vert"); + _program.addShaderFromSourceFile(QGLShader::Fragment, PathUtils::resourcesPath() + "shaders/model.frag"); initProgram(_program, _locations); _normalMapProgram.addShaderFromSourceFile(QGLShader::Vertex, - Application::resourcesPath() + "shaders/model_normal_map.vert"); + PathUtils::resourcesPath() + "shaders/model_normal_map.vert"); _normalMapProgram.addShaderFromSourceFile(QGLShader::Fragment, - Application::resourcesPath() + "shaders/model_normal_map.frag"); + PathUtils::resourcesPath() + "shaders/model_normal_map.frag"); initProgram(_normalMapProgram, _normalMapLocations); _specularMapProgram.addShaderFromSourceFile(QGLShader::Vertex, - Application::resourcesPath() + "shaders/model.vert"); + PathUtils::resourcesPath() + "shaders/model.vert"); _specularMapProgram.addShaderFromSourceFile(QGLShader::Fragment, - Application::resourcesPath() + "shaders/model_specular_map.frag"); + PathUtils::resourcesPath() + "shaders/model_specular_map.frag"); initProgram(_specularMapProgram, _specularMapLocations); _normalSpecularMapProgram.addShaderFromSourceFile(QGLShader::Vertex, - Application::resourcesPath() + "shaders/model_normal_map.vert"); + PathUtils::resourcesPath() + "shaders/model_normal_map.vert"); _normalSpecularMapProgram.addShaderFromSourceFile(QGLShader::Fragment, - Application::resourcesPath() + "shaders/model_normal_specular_map.frag"); + PathUtils::resourcesPath() + "shaders/model_normal_specular_map.frag"); initProgram(_normalSpecularMapProgram, _normalSpecularMapLocations); _translucentProgram.addShaderFromSourceFile(QGLShader::Vertex, - Application::resourcesPath() + "shaders/model.vert"); + PathUtils::resourcesPath() + "shaders/model.vert"); _translucentProgram.addShaderFromSourceFile(QGLShader::Fragment, - Application::resourcesPath() + "shaders/model_translucent.frag"); + PathUtils::resourcesPath() + "shaders/model_translucent.frag"); initProgram(_translucentProgram, _translucentLocations); // Lightmap - _lightmapProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/model_lightmap.vert"); - _lightmapProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + "shaders/model_lightmap.frag"); + _lightmapProgram.addShaderFromSourceFile(QGLShader::Vertex, PathUtils::resourcesPath() + "shaders/model_lightmap.vert"); + _lightmapProgram.addShaderFromSourceFile(QGLShader::Fragment, PathUtils::resourcesPath() + "shaders/model_lightmap.frag"); initProgram(_lightmapProgram, _lightmapLocations); _lightmapNormalMapProgram.addShaderFromSourceFile(QGLShader::Vertex, - Application::resourcesPath() + "shaders/model_lightmap_normal_map.vert"); + PathUtils::resourcesPath() + "shaders/model_lightmap_normal_map.vert"); _lightmapNormalMapProgram.addShaderFromSourceFile(QGLShader::Fragment, - Application::resourcesPath() + "shaders/model_lightmap_normal_map.frag"); + PathUtils::resourcesPath() + "shaders/model_lightmap_normal_map.frag"); initProgram(_lightmapNormalMapProgram, _lightmapNormalMapLocations); _lightmapSpecularMapProgram.addShaderFromSourceFile(QGLShader::Vertex, - Application::resourcesPath() + "shaders/model_lightmap.vert"); + PathUtils::resourcesPath() + "shaders/model_lightmap.vert"); _lightmapSpecularMapProgram.addShaderFromSourceFile(QGLShader::Fragment, - Application::resourcesPath() + "shaders/model_lightmap_specular_map.frag"); + PathUtils::resourcesPath() + "shaders/model_lightmap_specular_map.frag"); initProgram(_lightmapSpecularMapProgram, _lightmapSpecularMapLocations); _lightmapNormalSpecularMapProgram.addShaderFromSourceFile(QGLShader::Vertex, - Application::resourcesPath() + "shaders/model_lightmap_normal_map.vert"); + PathUtils::resourcesPath() + "shaders/model_lightmap_normal_map.vert"); _lightmapNormalSpecularMapProgram.addShaderFromSourceFile(QGLShader::Fragment, - Application::resourcesPath() + "shaders/model_lightmap_normal_specular_map.frag"); + PathUtils::resourcesPath() + "shaders/model_lightmap_normal_specular_map.frag"); initProgram(_lightmapNormalSpecularMapProgram, _lightmapNormalSpecularMapLocations); // end lightmap - _shadowProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/model_shadow.vert"); + _shadowProgram.addShaderFromSourceFile(QGLShader::Vertex, PathUtils::resourcesPath() + "shaders/model_shadow.vert"); _shadowProgram.addShaderFromSourceFile(QGLShader::Fragment, - Application::resourcesPath() + "shaders/model_shadow.frag"); + PathUtils::resourcesPath() + "shaders/model_shadow.frag"); - _skinProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/skin_model.vert"); - _skinProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + "shaders/model.frag"); + _skinProgram.addShaderFromSourceFile(QGLShader::Vertex, PathUtils::resourcesPath() + "shaders/skin_model.vert"); + _skinProgram.addShaderFromSourceFile(QGLShader::Fragment, PathUtils::resourcesPath() + "shaders/model.frag"); initSkinProgram(_skinProgram, _skinLocations); _skinNormalMapProgram.addShaderFromSourceFile(QGLShader::Vertex, - Application::resourcesPath() + "shaders/skin_model_normal_map.vert"); + PathUtils::resourcesPath() + "shaders/skin_model_normal_map.vert"); _skinNormalMapProgram.addShaderFromSourceFile(QGLShader::Fragment, - Application::resourcesPath() + "shaders/model_normal_map.frag"); + PathUtils::resourcesPath() + "shaders/model_normal_map.frag"); initSkinProgram(_skinNormalMapProgram, _skinNormalMapLocations); _skinSpecularMapProgram.addShaderFromSourceFile(QGLShader::Vertex, - Application::resourcesPath() + "shaders/skin_model.vert"); + PathUtils::resourcesPath() + "shaders/skin_model.vert"); _skinSpecularMapProgram.addShaderFromSourceFile(QGLShader::Fragment, - Application::resourcesPath() + "shaders/model_specular_map.frag"); + PathUtils::resourcesPath() + "shaders/model_specular_map.frag"); initSkinProgram(_skinSpecularMapProgram, _skinSpecularMapLocations); _skinNormalSpecularMapProgram.addShaderFromSourceFile(QGLShader::Vertex, - Application::resourcesPath() + "shaders/skin_model_normal_map.vert"); + PathUtils::resourcesPath() + "shaders/skin_model_normal_map.vert"); _skinNormalSpecularMapProgram.addShaderFromSourceFile(QGLShader::Fragment, - Application::resourcesPath() + "shaders/model_normal_specular_map.frag"); + PathUtils::resourcesPath() + "shaders/model_normal_specular_map.frag"); initSkinProgram(_skinNormalSpecularMapProgram, _skinNormalSpecularMapLocations); _skinShadowProgram.addShaderFromSourceFile(QGLShader::Vertex, - Application::resourcesPath() + "shaders/skin_model_shadow.vert"); + PathUtils::resourcesPath() + "shaders/skin_model_shadow.vert"); _skinShadowProgram.addShaderFromSourceFile(QGLShader::Fragment, - Application::resourcesPath() + "shaders/model_shadow.frag"); + PathUtils::resourcesPath() + "shaders/model_shadow.frag"); initSkinProgram(_skinShadowProgram, _skinShadowLocations); _skinTranslucentProgram.addShaderFromSourceFile(QGLShader::Vertex, - Application::resourcesPath() + "shaders/skin_model.vert"); + PathUtils::resourcesPath() + "shaders/skin_model.vert"); _skinTranslucentProgram.addShaderFromSourceFile(QGLShader::Fragment, - Application::resourcesPath() + "shaders/model_translucent.frag"); + PathUtils::resourcesPath() + "shaders/model_translucent.frag"); initSkinProgram(_skinTranslucentProgram, _skinTranslucentLocations); } diff --git a/interface/src/ui/AddressBarDialog.cpp b/interface/src/ui/AddressBarDialog.cpp index dbc29be71a..32161b018f 100644 --- a/interface/src/ui/AddressBarDialog.cpp +++ b/interface/src/ui/AddressBarDialog.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include + #include "AddressBarDialog.h" #include "AddressManager.h" #include "Application.h" @@ -82,7 +84,7 @@ void AddressBarDialog::setupUI() { _goButton->setSizePolicy(sizePolicy); _goButton->setMinimumSize(QSize(GO_BUTTON_SIZE, GO_BUTTON_SIZE)); _goButton->setMaximumSize(QSize(GO_BUTTON_SIZE, GO_BUTTON_SIZE)); - _goButton->setIcon(QIcon(Application::resourcesPath() + ADDRESSBAR_GO_BUTTON_ICON)); + _goButton->setIcon(QIcon(PathUtils::resourcesPath() + ADDRESSBAR_GO_BUTTON_ICON)); _goButton->setIconSize(QSize(GO_BUTTON_SIZE, GO_BUTTON_SIZE)); _goButton->setDefault(true); _goButton->setFlat(true); @@ -99,7 +101,7 @@ void AddressBarDialog::setupUI() { _closeButton->setSizePolicy(sizePolicy); _closeButton->setMinimumSize(QSize(CLOSE_BUTTON_SIZE, CLOSE_BUTTON_SIZE)); _closeButton->setMaximumSize(QSize(CLOSE_BUTTON_SIZE, CLOSE_BUTTON_SIZE)); - QIcon icon(Application::resourcesPath() + CLOSE_BUTTON_ICON); + QIcon icon(PathUtils::resourcesPath() + CLOSE_BUTTON_ICON); _closeButton->setIcon(icon); _closeButton->setIconSize(QSize(CLOSE_BUTTON_SIZE, CLOSE_BUTTON_SIZE)); _closeButton->setFlat(true); @@ -112,7 +114,7 @@ void AddressBarDialog::setupUI() { } void AddressBarDialog::showEvent(QShowEvent* event) { - _goButton->setIcon(QIcon(Application::resourcesPath() + ADDRESSBAR_GO_BUTTON_ICON)); + _goButton->setIcon(QIcon(PathUtils::resourcesPath() + ADDRESSBAR_GO_BUTTON_ICON)); _addressLineEdit->setText(QString()); _addressLineEdit->setFocus(); FramelessDialog::showEvent(event); @@ -120,7 +122,7 @@ void AddressBarDialog::showEvent(QShowEvent* event) { void AddressBarDialog::accept() { if (!_addressLineEdit->text().isEmpty()) { - _goButton->setIcon(QIcon(Application::resourcesPath() + ADDRESSBAR_GO_BUTTON_ACTIVE_ICON)); + _goButton->setIcon(QIcon(PathUtils::resourcesPath() + ADDRESSBAR_GO_BUTTON_ACTIVE_ICON)); AddressManager& addressManager = AddressManager::getInstance(); connect(&addressManager, &AddressManager::lookupResultsFinished, this, &QDialog::hide); addressManager.handleLookupString(_addressLineEdit->text()); diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index f4e0c9769d..32fffd3d40 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -12,6 +12,8 @@ #include "InterfaceConfig.h" #include + +#include #include #include "Application.h" @@ -379,7 +381,7 @@ void ApplicationOverlay::displayOverlayTexture3DTV(Camera& whichCamera, float as glEnd(); if (_crosshairTexture == 0) { - _crosshairTexture = Application::getInstance()->getGLWidget()->bindTexture(QImage(Application::resourcesPath() + "images/sixense-reticle.png")); + _crosshairTexture = Application::getInstance()->getGLWidget()->bindTexture(QImage(PathUtils::resourcesPath() + "images/sixense-reticle.png")); } //draw the mouse pointer @@ -513,7 +515,7 @@ void ApplicationOverlay::renderPointers() { //lazily load crosshair texture if (_crosshairTexture == 0) { - _crosshairTexture = Application::getInstance()->getGLWidget()->bindTexture(QImage(Application::resourcesPath() + "images/sixense-reticle.png")); + _crosshairTexture = Application::getInstance()->getGLWidget()->bindTexture(QImage(PathUtils::resourcesPath() + "images/sixense-reticle.png")); } glEnable(GL_TEXTURE_2D); diff --git a/interface/src/ui/ChatWindow.cpp b/interface/src/ui/ChatWindow.cpp index 747b4ae68d..22ceb0d367 100644 --- a/interface/src/ui/ChatWindow.cpp +++ b/interface/src/ui/ChatWindow.cpp @@ -19,6 +19,7 @@ #include #include +#include #include "Application.h" #include "ChatMessageArea.h" @@ -92,9 +93,9 @@ ChatWindow::ChatWindow(QWidget* parent) : connect(&_trayIcon, SIGNAL(messageClicked()), this, SLOT(notificationClicked())); #endif // HAVE_QXMPP - QDir mentionSoundsDir(Application::resourcesPath() + mentionSoundsPath); + QDir mentionSoundsDir(PathUtils::resourcesPath() + mentionSoundsPath); _mentionSounds = mentionSoundsDir.entryList(QDir::Files); - _trayIcon.setIcon(QIcon( Application::resourcesPath() + "/images/hifi-logo.svg")); + _trayIcon.setIcon(QIcon( PathUtils::resourcesPath() + "/images/hifi-logo.svg")); } ChatWindow::~ChatWindow() { @@ -385,7 +386,7 @@ void ChatWindow::messageReceived(const QXmppMessage& message) { if (_effectPlayer.state() != QMediaPlayer::PlayingState) { // get random sound - QFileInfo inf = QFileInfo(Application::resourcesPath() + + QFileInfo inf = QFileInfo(PathUtils::resourcesPath() + mentionSoundsPath + _mentionSounds.at(rand() % _mentionSounds.size())); _effectPlayer.setMedia(QUrl::fromLocalFile(inf.absoluteFilePath())); diff --git a/interface/src/ui/FramelessDialog.cpp b/interface/src/ui/FramelessDialog.cpp index 280354d974..bae6217083 100644 --- a/interface/src/ui/FramelessDialog.cpp +++ b/interface/src/ui/FramelessDialog.cpp @@ -12,6 +12,8 @@ #include #include +#include + #include "Application.h" #include "FramelessDialog.h" #include "Menu.h" @@ -80,10 +82,10 @@ bool FramelessDialog::eventFilter(QObject* sender, QEvent* event) { } void FramelessDialog::setStyleSheetFile(const QString& fileName) { - QFile globalStyleSheet(Application::resourcesPath() + "styles/global.qss"); - QFile styleSheet(Application::resourcesPath() + fileName); + QFile globalStyleSheet(PathUtils::resourcesPath() + "styles/global.qss"); + QFile styleSheet(PathUtils::resourcesPath() + fileName); if (styleSheet.open(QIODevice::ReadOnly) && globalStyleSheet.open(QIODevice::ReadOnly) ) { - QDir::setCurrent(Application::resourcesPath()); + QDir::setCurrent(PathUtils::resourcesPath()); setStyleSheet(globalStyleSheet.readAll() + styleSheet.readAll()); } } diff --git a/interface/src/ui/InfoView.cpp b/interface/src/ui/InfoView.cpp index f306514e80..0c04e07841 100644 --- a/interface/src/ui/InfoView.cpp +++ b/interface/src/ui/InfoView.cpp @@ -9,14 +9,17 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "InfoView.h" #include -#include "Application.h" #include #include #include +#include + +#include "Application.h" +#include "InfoView.h" + #define SETTINGS_VERSION_KEY "info-version" #define MAX_DIALOG_HEIGHT_RATIO 0.9 @@ -25,7 +28,7 @@ InfoView::InfoView(bool forced, QString path) : { setWindowFlags(Qt::WindowStaysOnTopHint | Qt::CustomizeWindowHint | Qt::WindowCloseButtonHint); - QString absPath = QFileInfo(Application::resourcesPath() + path).absoluteFilePath(); + QString absPath = QFileInfo(PathUtils::resourcesPath() + path).absoluteFilePath(); QUrl url = QUrl::fromLocalFile(absPath); load(url); diff --git a/interface/src/ui/JSConsole.cpp b/interface/src/ui/JSConsole.cpp index 8dbece41f0..700781df69 100644 --- a/interface/src/ui/JSConsole.cpp +++ b/interface/src/ui/JSConsole.cpp @@ -13,10 +13,11 @@ #include #include -#include "Application.h" -#include "ScriptHighlighting.h" +#include +#include "Application.h" #include "JSConsole.h" +#include "ScriptHighlighting.h" const int NO_CURRENT_HISTORY_COMMAND = -1; const int MAX_HISTORY_SIZE = 64; @@ -41,9 +42,9 @@ JSConsole::JSConsole(QWidget* parent, ScriptEngine* scriptEngine) : _ui->promptTextEdit->setWordWrapMode(QTextOption::NoWrap); _ui->promptTextEdit->installEventFilter(this); - QFile styleSheet(Application::resourcesPath() + "styles/console.qss"); + QFile styleSheet(PathUtils::resourcesPath() + "styles/console.qss"); if (styleSheet.open(QIODevice::ReadOnly)) { - QDir::setCurrent(Application::resourcesPath()); + QDir::setCurrent(PathUtils::resourcesPath()); setStyleSheet(styleSheet.readAll()); } diff --git a/interface/src/ui/LogDialog.cpp b/interface/src/ui/LogDialog.cpp index 7136ed2d25..a1a52f1d77 100644 --- a/interface/src/ui/LogDialog.cpp +++ b/interface/src/ui/LogDialog.cpp @@ -15,10 +15,10 @@ #include #include +#include #include #include "Application.h" - #include "ui/LogDialog.h" const int TOP_BAR_HEIGHT = 46; @@ -44,9 +44,9 @@ LogDialog::LogDialog(QWidget* parent, AbstractLoggerInterface* logger) : QDialog setWindowTitle("Log"); setAttribute(Qt::WA_DeleteOnClose); - QFile styleSheet(Application::resourcesPath() + "styles/log_dialog.qss"); + QFile styleSheet(PathUtils::resourcesPath() + "styles/log_dialog.qss"); if (styleSheet.open(QIODevice::ReadOnly)) { - QDir::setCurrent(Application::resourcesPath()); + QDir::setCurrent(PathUtils::resourcesPath()); setStyleSheet(styleSheet.readAll()); } diff --git a/interface/src/ui/LoginDialog.cpp b/interface/src/ui/LoginDialog.cpp index b3d8cb1e53..298efa6b1a 100644 --- a/interface/src/ui/LoginDialog.cpp +++ b/interface/src/ui/LoginDialog.cpp @@ -14,11 +14,12 @@ #include #include +#include + #include "Application.h" #include "Menu.h" #include "AccountManager.h" #include "ui_loginDialog.h" - #include "LoginDialog.h" const QString FORGOT_PASSWORD_URL = "https://data.highfidelity.io/users/password/new"; @@ -30,8 +31,8 @@ LoginDialog::LoginDialog(QWidget* parent) : _ui->setupUi(this); _ui->errorLabel->hide(); _ui->emailLineEdit->setFocus(); - _ui->logoLabel->setPixmap(QPixmap(Application::resourcesPath() + "images/hifi-logo.svg")); - _ui->loginButton->setIcon(QIcon(Application::resourcesPath() + "images/login.svg")); + _ui->logoLabel->setPixmap(QPixmap(PathUtils::resourcesPath() + "images/hifi-logo.svg")); + _ui->loginButton->setIcon(QIcon(PathUtils::resourcesPath() + "images/login.svg")); _ui->infoLabel->setVisible(false); _ui->errorLabel->setVisible(false); diff --git a/interface/src/ui/MetavoxelEditor.cpp b/interface/src/ui/MetavoxelEditor.cpp index 158532e19a..1a85e84b72 100644 --- a/interface/src/ui/MetavoxelEditor.cpp +++ b/interface/src/ui/MetavoxelEditor.cpp @@ -35,6 +35,7 @@ #include #include #include +#include #include "Application.h" #include "MetavoxelEditor.h" @@ -145,7 +146,7 @@ MetavoxelEditor::MetavoxelEditor() : return; } - _gridProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + "shaders/grid.frag"); + _gridProgram.addShaderFromSourceFile(QGLShader::Fragment, PathUtils::resourcesPath() + "shaders/grid.frag"); _gridProgram.link(); } diff --git a/interface/src/ui/RearMirrorTools.cpp b/interface/src/ui/RearMirrorTools.cpp index fb6ef63647..fd3fc34adb 100644 --- a/interface/src/ui/RearMirrorTools.cpp +++ b/interface/src/ui/RearMirrorTools.cpp @@ -13,12 +13,13 @@ #include +#include #include #include "Application.h" +#include "RearMirrorTools.h" #include "Util.h" -#include "RearMirrorTools.h" const char SETTINGS_GROUP_NAME[] = "Rear View Tools"; const char ZOOM_LEVEL_SETTINGS[] = "ZoomLevel"; @@ -32,13 +33,13 @@ RearMirrorTools::RearMirrorTools(QGLWidget* parent, QRect& bounds, QSettings* se _fullScreen(false) { _zoomLevel = HEAD; - _closeTextureId = _parent->bindTexture(QImage(Application::resourcesPath() + "images/close.svg")); + _closeTextureId = _parent->bindTexture(QImage(PathUtils::resourcesPath() + "images/close.svg")); // Disabled for now https://worklist.net/19548 - // _resetTextureId = _parent->bindTexture(QImage(Application::resourcesPath() + "images/reset.png")); + // _resetTextureId = _parent->bindTexture(QImage(PathUtils::resourcesPath() + "images/reset.png")); - _zoomHeadTextureId = _parent->bindTexture(QImage(Application::resourcesPath() + "images/plus.svg")); - _zoomBodyTextureId = _parent->bindTexture(QImage(Application::resourcesPath() + "images/minus.svg")); + _zoomHeadTextureId = _parent->bindTexture(QImage(PathUtils::resourcesPath() + "images/plus.svg")); + _zoomBodyTextureId = _parent->bindTexture(QImage(PathUtils::resourcesPath() + "images/minus.svg")); _shrinkIconRect = QRect(ICON_PADDING, ICON_PADDING, ICON_SIZE, ICON_SIZE); _closeIconRect = QRect(_bounds.left() + ICON_PADDING, _bounds.top() + ICON_PADDING, ICON_SIZE, ICON_SIZE); diff --git a/interface/src/ui/RunningScriptsWidget.cpp b/interface/src/ui/RunningScriptsWidget.cpp index cfd7428482..57c0532777 100644 --- a/interface/src/ui/RunningScriptsWidget.cpp +++ b/interface/src/ui/RunningScriptsWidget.cpp @@ -21,6 +21,8 @@ #include #include +#include + #include "Application.h" #include "Menu.h" #include "ScriptsModel.h" @@ -109,7 +111,7 @@ void RunningScriptsWidget::setRunningScripts(const QStringList& list) { QPushButton* closeButton = new QPushButton(row); closeButton->setFlat(true); closeButton->setIcon( - QIcon(QPixmap(Application::resourcesPath() + "images/kill-script.svg").scaledToHeight(CLOSE_ICON_HEIGHT))); + QIcon(QPixmap(PathUtils::resourcesPath() + "images/kill-script.svg").scaledToHeight(CLOSE_ICON_HEIGHT))); closeButton->setSizePolicy(QSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred)); closeButton->setStyleSheet("border: 0;"); closeButton->setCursor(Qt::PointingHandCursor); diff --git a/interface/src/ui/VoxelImportDialog.cpp b/interface/src/ui/VoxelImportDialog.cpp index 2d1b71ba7f..930fed133d 100644 --- a/interface/src/ui/VoxelImportDialog.cpp +++ b/interface/src/ui/VoxelImportDialog.cpp @@ -18,6 +18,8 @@ #include #include +#include + #include "Application.h" #include "VoxelImportDialog.h" @@ -64,7 +66,7 @@ QIcon HiFiIconProvider::icon(QFileIconProvider::IconType type) const { break; } - return QIcon(Application::resourcesPath() + "icons/" + typeString + ".svg"); + return QIcon(PathUtils::resourcesPath() + "icons/" + typeString + ".svg"); } QIcon HiFiIconProvider::icon(const QFileInfo &info) const { @@ -72,21 +74,21 @@ QIcon HiFiIconProvider::icon(const QFileInfo &info) const { if (info.isDir()) { if (info.absoluteFilePath() == QDir::homePath()) { - return QIcon(Application::resourcesPath() + "icons/home.svg"); + return QIcon(PathUtils::resourcesPath() + "icons/home.svg"); } else if (info.absoluteFilePath() == QStandardPaths::writableLocation(QStandardPaths::DesktopLocation)) { - return QIcon(Application::resourcesPath() + "icons/desktop.svg"); + return QIcon(PathUtils::resourcesPath() + "icons/desktop.svg"); } else if (info.absoluteFilePath() == QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation)) { - return QIcon(Application::resourcesPath() + "icons/documents.svg"); + return QIcon(PathUtils::resourcesPath() + "icons/documents.svg"); } - return QIcon(Application::resourcesPath() + "icons/folder.svg"); + return QIcon(PathUtils::resourcesPath() + "icons/folder.svg"); } - QFileInfo iconFile(Application::resourcesPath() + "icons/" + iconsMap[ext]); + QFileInfo iconFile(PathUtils::resourcesPath() + "icons/" + iconsMap[ext]); if (iconFile.exists() && iconFile.isFile()) { return QIcon(iconFile.filePath()); } - return QIcon(Application::resourcesPath() + "icons/file.svg"); + return QIcon(PathUtils::resourcesPath() + "icons/file.svg"); } QString HiFiIconProvider::type(const QFileInfo &info) const { @@ -307,16 +309,16 @@ void VoxelImportDialog::setLayout() { widget = findChild("treeView"); widget->setAttribute(Qt::WA_MacShowFocusRect, false); - QFile styleSheet(Application::resourcesPath() + "styles/import_dialog.qss"); + QFile styleSheet(PathUtils::resourcesPath() + "styles/import_dialog.qss"); if (styleSheet.open(QIODevice::ReadOnly)) { - QDir::setCurrent(Application::resourcesPath()); + QDir::setCurrent(PathUtils::resourcesPath()); setStyleSheet(styleSheet.readAll()); } } void VoxelImportDialog::setImportTypes() { - QFile config(Application::resourcesPath() + "config/config.json"); + QFile config(PathUtils::resourcesPath() + "config/config.json"); config.open(QFile::ReadOnly | QFile::Text); QJsonDocument document = QJsonDocument::fromJson(config.readAll()); if (!document.isNull() && !document.isEmpty()) { diff --git a/interface/src/ui/overlays/Grid3DOverlay.cpp b/interface/src/ui/overlays/Grid3DOverlay.cpp index d1086ae534..953a288cb6 100644 --- a/interface/src/ui/overlays/Grid3DOverlay.cpp +++ b/interface/src/ui/overlays/Grid3DOverlay.cpp @@ -9,9 +9,10 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "Grid3DOverlay.h" +#include #include "Application.h" +#include "Grid3DOverlay.h" ProgramObject Grid3DOverlay::_gridProgram; @@ -36,7 +37,7 @@ void Grid3DOverlay::render(RenderArgs* args) { } if (!_gridProgram.isLinked()) { - if (!_gridProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + "shaders/grid.frag")) { + if (!_gridProgram.addShaderFromSourceFile(QGLShader::Fragment, PathUtils::resourcesPath() + "shaders/grid.frag")) { qDebug() << "Failed to compile: " + _gridProgram.log(); return; } diff --git a/interface/src/voxels/VoxelSystem.cpp b/interface/src/voxels/VoxelSystem.cpp index 064cead160..114b6ba481 100644 --- a/interface/src/voxels/VoxelSystem.cpp +++ b/interface/src/voxels/VoxelSystem.cpp @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -372,9 +373,9 @@ void VoxelSystem::initVoxelMemory() { // create our simple fragment shader if we're the first system to init if (!_program.isLinked()) { _program.addShaderFromSourceFile(QGLShader::Vertex, - Application::resourcesPath() + "shaders/voxel.vert"); + PathUtils::resourcesPath() + "shaders/voxel.vert"); _program.addShaderFromSourceFile(QGLShader::Fragment, - Application::resourcesPath() + "shaders/voxel.frag"); + PathUtils::resourcesPath() + "shaders/voxel.frag"); _program.link(); } _initialized = true; @@ -1645,9 +1646,9 @@ unsigned long VoxelSystem::getVoxelMemoryUsageGPU() { void VoxelSystem::bindPerlinModulateProgram() { if (!_perlinModulateProgram.isLinked()) { _perlinModulateProgram.addShaderFromSourceFile(QGLShader::Vertex, - Application::resourcesPath() + "shaders/perlin_modulate.vert"); + PathUtils::resourcesPath() + "shaders/perlin_modulate.vert"); _perlinModulateProgram.addShaderFromSourceFile(QGLShader::Fragment, - Application::resourcesPath() + "shaders/perlin_modulate.frag"); + PathUtils::resourcesPath() + "shaders/perlin_modulate.frag"); _perlinModulateProgram.link(); _perlinModulateProgram.bind(); diff --git a/libraries/shared/src/PathUtils.cpp b/libraries/shared/src/PathUtils.cpp new file mode 100644 index 0000000000..0b99f22228 --- /dev/null +++ b/libraries/shared/src/PathUtils.cpp @@ -0,0 +1,25 @@ +// +// PathUtils.cpp +// libraries/shared/src +// +// Created by Brad Hefta-Gaub on 12/15/14. +// 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 "PathUtils.h" + + +QString& PathUtils::resourcesPath() { +#ifdef Q_OS_MAC + static QString staticResourcePath = QCoreApplication::applicationDirPath() + "/../Resources/"; +#else + static QString staticResourcePath = QCoreApplication::applicationDirPath() + "/resources/"; +#endif + return staticResourcePath; +} diff --git a/libraries/shared/src/PathUtils.h b/libraries/shared/src/PathUtils.h new file mode 100644 index 0000000000..71cabc727d --- /dev/null +++ b/libraries/shared/src/PathUtils.h @@ -0,0 +1,22 @@ +// +// PathUtils.h +// libraries/shared/src +// +// Created by Brad Hefta-Gaub on 12/15/14. +// 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_PathUtils_h +#define hifi_PathUtils_h + + +#include + +namespace PathUtils { + QString& resourcesPath(); +} + +#endif // hifi_PathUtils_h \ No newline at end of file From 50c1e9fb4037cd9f225177ff9e6e5603c11c4776 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Mon, 15 Dec 2014 22:41:35 -0800 Subject: [PATCH 426/502] Fixes for missing audio device. --- interface/src/Audio.cpp | 7 ++++++- libraries/audio/src/AudioRingBuffer.h | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index 101d16d3ba..bf176e0415 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -450,7 +450,9 @@ void Audio::start() { qDebug() << "Unable to set up audio output because of a problem with output format."; } - _inputFrameBuffer.initialize( _inputFormat.channelCount(), _audioInput->bufferSize() * 8 ); + if (_audioInput) { + _inputFrameBuffer.initialize( _inputFormat.channelCount(), _audioInput->bufferSize() * 8 ); + } _inputGain.initialize(); _sourceGain.initialize(); _noiseSource.initialize(); @@ -1935,6 +1937,9 @@ int Audio::calculateNumberOfFrameSamples(int numBytes) const { } float Audio::getAudioOutputMsecsUnplayed() const { + if (!_audioOutput) { + return 0.0f; + } int bytesAudioOutputUnplayed = _audioOutput->bufferSize() - _audioOutput->bytesFree(); float msecsAudioOutputUnplayed = bytesAudioOutputUnplayed / (float)_outputFormat.bytesForDuration(USECS_PER_MSEC); return msecsAudioOutputUnplayed; diff --git a/libraries/audio/src/AudioRingBuffer.h b/libraries/audio/src/AudioRingBuffer.h index f033ffa80f..9239527df3 100644 --- a/libraries/audio/src/AudioRingBuffer.h +++ b/libraries/audio/src/AudioRingBuffer.h @@ -62,7 +62,7 @@ public: float getNextOutputFrameLoudness() const; int samplesAvailable() const; - int framesAvailable() const { return samplesAvailable() / _numFrameSamples; } + int framesAvailable() const { return (_numFrameSamples == 0) ? 0 : samplesAvailable() / _numFrameSamples; } int getNumFrameSamples() const { return _numFrameSamples; } From b1d1cfee44420bc9f14a2749ca746a10389b3aaa Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 15 Dec 2014 15:29:05 -0800 Subject: [PATCH 427/502] cmake cleanup --- libraries/render-utils/CMakeLists.txt | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/libraries/render-utils/CMakeLists.txt b/libraries/render-utils/CMakeLists.txt index bde26ea5ca..eb96e7c5ec 100644 --- a/libraries/render-utils/CMakeLists.txt +++ b/libraries/render-utils/CMakeLists.txt @@ -10,7 +10,7 @@ if (APPLE) # link in required OS X frameworks and include the right GL headers find_library(OpenGL OpenGL) - target_link_libraries(${TARGET_NAME} ${OpenGL}) + #target_link_libraries(${TARGET_NAME} ${OpenGL}) else (APPLE) find_package(OpenGL REQUIRED) @@ -19,8 +19,6 @@ else (APPLE) include_directories(SYSTEM "${OPENGL_INCLUDE_DIR}") endif () - #target_link_libraries(${TARGET_NAME} "${OPENGL_LIBRARY}") - # link target to external libraries if (WIN32) find_package(GLEW REQUIRED) @@ -28,17 +26,6 @@ else (APPLE) # we're using static GLEW, so define GLEW_STATIC add_definitions(-DGLEW_STATIC) - - #target_link_libraries(${TARGET_NAME} "${GLEW_LIBRARIES}" "${NSIGHT_LIBRARIES}" opengl32.lib) - - # try to find the Nsight package and add it to the build if we find it - #find_package(NSIGHT) - #if (NSIGHT_FOUND) - # include_directories(${NSIGHT_INCLUDE_DIRS}) - # add_definitions(-DNSIGHT_FOUND) - # #target_link_libraries(${TARGET_NAME} "${NSIGHT_LIBRARIES}") - #endif () - endif() endif (APPLE) From e5e2eb4e8ae0adc3df0ed238596f30f126b442c1 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 15 Dec 2014 16:20:52 -0800 Subject: [PATCH 428/502] Moved GLCanvas in DM and DM to QSharedPointers --- interface/src/Application.cpp | 54 ++++++----- interface/src/Application.h | 1 - interface/src/Camera.cpp | 6 +- interface/src/Menu.cpp | 18 ++-- interface/src/avatar/Head.cpp | 7 +- interface/src/avatar/MyAvatar.cpp | 2 +- interface/src/devices/DdeFaceTracker.h | 4 +- interface/src/devices/Faceshift.h | 4 +- interface/src/devices/OculusManager.cpp | 8 +- interface/src/devices/PrioVR.cpp | 7 +- interface/src/devices/SixenseManager.cpp | 8 +- interface/src/devices/TV3DManager.cpp | 11 ++- interface/src/devices/Visage.cpp | 2 +- interface/src/devices/Visage.h | 4 +- interface/src/renderer/GlowEffect.cpp | 10 +- interface/src/renderer/TextureCache.cpp | 2 +- .../ControllerScriptingInterface.cpp | 6 +- .../scripting/WindowScriptingInterface.cpp | 2 +- interface/src/ui/ApplicationOverlay.cpp | 97 ++++++++++--------- interface/src/ui/MetavoxelEditor.cpp | 2 +- .../src/ui/MetavoxelNetworkSimulator.cpp | 2 +- interface/src/ui/PreferencesDialog.cpp | 7 +- interface/src/ui/Snapshot.cpp | 5 +- interface/src/ui/Stats.cpp | 20 ++-- 24 files changed, 143 insertions(+), 146 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index eaafcd0eac..4c9fdcaf0f 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -194,7 +194,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : _isVSyncOn(true), _aboutToQuit(false) { - GLCanvas* glCanvas = DependencyManager::get(); + QSharedPointer glCanvas = DependencyManager::get(); // read the ApplicationInfo.ini file for Name/Version/Domain information QSettings applicationInfo(Application::resourcesPath() + "info/ApplicationInfo.ini", QSettings::IniFormat); @@ -365,7 +365,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : ResourceCache::setRequestLimit(3); - _window->setCentralWidget(glCanvas); + _window->setCentralWidget(glCanvas.data()); restoreSizeAndPosition(); @@ -393,7 +393,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : checkVersion(); - _overlays.init(glCanvas); // do this before scripts load + _overlays.init(glCanvas.data()); // do this before scripts load LocalVoxelsList::getInstance()->addPersistantTree(DOMAIN_TREE_NAME, _voxels.getTree()); LocalVoxelsList::getInstance()->addPersistantTree(CLIPBOARD_TREE_NAME, &_clipboard); @@ -442,6 +442,8 @@ void Application::aboutToQuit() { } Application::~Application() { + DependencyManager::get()->setParent(NULL); + _entities.getTree()->setSimulation(NULL); qInstallMessageHandler(NULL); @@ -1046,7 +1048,7 @@ void Application::keyPressEvent(QKeyEvent* event) { if (isShifted) { _viewFrustum.setFocalLength(_viewFrustum.getFocalLength() - 0.1f); if (TV3DManager::isConnected()) { - GLCanvas* glCanvas = DependencyManager::get(); + QSharedPointer glCanvas = DependencyManager::get(); TV3DManager::configureCamera(_myCamera, glCanvas->getDeviceWidth(), glCanvas->getDeviceHeight()); } } else { @@ -1059,7 +1061,7 @@ void Application::keyPressEvent(QKeyEvent* event) { if (isShifted) { _viewFrustum.setFocalLength(_viewFrustum.getFocalLength() + 0.1f); if (TV3DManager::isConnected()) { - GLCanvas* glCanvas = DependencyManager::get(); + QSharedPointer glCanvas = DependencyManager::get(); TV3DManager::configureCamera(_myCamera, glCanvas->getDeviceWidth(), glCanvas->getDeviceHeight()); } @@ -1532,7 +1534,7 @@ void Application::idle() { void Application::checkBandwidthMeterClick() { // ... to be called upon button release - GLCanvas* glCanvas = DependencyManager::get(); + QSharedPointer glCanvas = DependencyManager::get(); if (Menu::getInstance()->isOptionChecked(MenuOption::Bandwidth) && Menu::getInstance()->isOptionChecked(MenuOption::Stats) && Menu::getInstance()->isOptionChecked(MenuOption::UserInterface) && @@ -1568,7 +1570,7 @@ void Application::setFullscreen(bool fullscreen) { } void Application::setEnable3DTVMode(bool enable3DTVMode) { - GLCanvas* glCanvas = DependencyManager::get(); + QSharedPointer glCanvas = DependencyManager::get(); resizeGL(glCanvas->getDeviceWidth(), glCanvas->getDeviceHeight()); } @@ -1594,7 +1596,7 @@ void Application::setEnableVRMode(bool enableVRMode) { _myCamera.setHmdRotation(glm::quat()); } - GLCanvas* glCanvas = DependencyManager::get(); + QSharedPointer glCanvas = DependencyManager::get(); resizeGL(glCanvas->getDeviceWidth(), glCanvas->getDeviceHeight()); } @@ -1657,7 +1659,7 @@ glm::vec3 Application::getMouseVoxelWorldCoordinates(const VoxelDetail& mouseVox bool Application::mouseOnScreen() const { if (OculusManager::isConnected()) { - GLCanvas* glCanvas = DependencyManager::get(); + QSharedPointer glCanvas = DependencyManager::get(); return getMouseX() >= 0 && getMouseX() <= glCanvas->getDeviceWidth() && getMouseY() >= 0 && getMouseY() <= glCanvas->getDeviceHeight(); } @@ -1699,13 +1701,13 @@ int Application::getMouseDragStartedY() const { } FaceTracker* Application::getActiveFaceTracker() { - Faceshift* faceshift = DependencyManager::get(); - Visage* visage = DependencyManager::get(); - DdeFaceTracker* dde = DependencyManager::get(); + QSharedPointer faceshift = DependencyManager::get(); + QSharedPointer visage = DependencyManager::get(); + QSharedPointer dde = DependencyManager::get(); - return (dde->isActive() ? static_cast(dde) : - (faceshift->isActive() ? static_cast(faceshift) : - (visage->isActive() ? static_cast(visage) : NULL))); + return (dde->isActive() ? static_cast(dde.data()) : + (faceshift->isActive() ? static_cast(faceshift.data()) : + (visage->isActive() ? static_cast(visage.data()) : NULL))); } struct SendVoxelsOperationArgs { @@ -1778,7 +1780,7 @@ void Application::exportVoxels(const VoxelDetail& sourceVoxel) { QString desktopLocation = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation); QString suggestedName = desktopLocation.append("/voxels.svo"); - QString fileNameString = QFileDialog::getSaveFileName(DependencyManager::get(), + QString fileNameString = QFileDialog::getSaveFileName(DependencyManager::get().data(), tr("Export Voxels"), suggestedName, tr("Sparse Voxel Octree Files (*.svo)")); QByteArray fileNameAscii = fileNameString.toLocal8Bit(); @@ -2034,9 +2036,9 @@ void Application::init() { _metavoxels.init(); - GLCanvas* glCanvas = DependencyManager::get(); - _audio.init(glCanvas); - _rearMirrorTools = new RearMirrorTools(glCanvas, _mirrorViewRect, _settings); + QSharedPointer glCanvas = DependencyManager::get(); + _audio.init(glCanvas.data()); + _rearMirrorTools = new RearMirrorTools(glCanvas.data(), _mirrorViewRect, _settings); connect(_rearMirrorTools, SIGNAL(closeView()), SLOT(closeMirrorView())); connect(_rearMirrorTools, SIGNAL(restoreView()), SLOT(restoreMirrorView())); @@ -2115,7 +2117,7 @@ void Application::updateMouseRay() { void Application::updateFaceshift() { bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); PerformanceWarning warn(showWarnings, "Application::updateFaceshift()"); - Faceshift* faceshift = DependencyManager::get(); + Faceshift* faceshift = DependencyManager::get().data(); // Update faceshift faceshift->update(); @@ -2919,7 +2921,7 @@ void Application::updateShadowMap() { fbo->release(); - GLCanvas* glCanvas = DependencyManager::get(); + QSharedPointer glCanvas = DependencyManager::get(); glViewport(0, 0, glCanvas->getDeviceWidth(), glCanvas->getDeviceHeight()); } @@ -3247,7 +3249,7 @@ void Application::computeOffAxisFrustum(float& left, float& right, float& bottom } glm::vec2 Application::getScaledScreenPoint(glm::vec2 projectedPoint) { - GLCanvas* glCanvas = DependencyManager::get(); + QSharedPointer glCanvas = DependencyManager::get(); float horizontalScale = glCanvas->getDeviceWidth() / 2.0f; float verticalScale = glCanvas->getDeviceHeight() / 2.0f; @@ -4260,7 +4262,7 @@ void Application::setPreviousScriptLocation(const QString& previousScriptLocatio void Application::loadDialog() { - QString fileNameString = QFileDialog::getOpenFileName(DependencyManager::get(), + QString fileNameString = QFileDialog::getOpenFileName(DependencyManager::get().data(), tr("Open Script"), getPreviousScriptLocation(), tr("JavaScript Files (*.js)")); @@ -4297,7 +4299,7 @@ void Application::loadScriptURLDialog() { void Application::toggleLogDialog() { if (! _logDialog) { - _logDialog = new LogDialog(DependencyManager::get(), getLogger()); + _logDialog = new LogDialog(DependencyManager::get().data(), getLogger()); } if (_logDialog->isVisible()) { @@ -4357,7 +4359,7 @@ void Application::parseVersionXml() { } if (!shouldSkipVersion(latestVersion) && applicationVersion() != latestVersion) { - new UpdateDialog(DependencyManager::get(), releaseNotes, latestVersion, downloadUrl); + new UpdateDialog(DependencyManager::get().data(), releaseNotes, latestVersion, downloadUrl); } sender->deleteLater(); } @@ -4390,7 +4392,7 @@ void Application::takeSnapshot() { } if (!_snapshotShareDialog) { - _snapshotShareDialog = new SnapshotShareDialog(fileName, DependencyManager::get()); + _snapshotShareDialog = new SnapshotShareDialog(fileName, DependencyManager::get().data()); } _snapshotShareDialog->show(); } diff --git a/interface/src/Application.h b/interface/src/Application.h index cddaeaad15..31f6d7d50a 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -173,7 +173,6 @@ public: glm::vec3 getMouseVoxelWorldCoordinates(const VoxelDetail& mouseVoxel); bool isThrottleRendering() const { return DependencyManager::get()->isThrottleRendering(); } - GLCanvas* getGLWidget() { return DependencyManager::get(); } // TODO: remove MyAvatar* getAvatar() { return _myAvatar; } Audio* getAudio() { return &_audio; } Camera* getCamera() { return &_myCamera; } diff --git a/interface/src/Camera.cpp b/interface/src/Camera.cpp index d069afb96a..181f783af1 100644 --- a/interface/src/Camera.cpp +++ b/interface/src/Camera.cpp @@ -95,10 +95,8 @@ void Camera::setFarClip(float f) { } PickRay Camera::computePickRay(float x, float y) { - float screenWidth = Application::getInstance()->getGLWidget()->width(); - float screenHeight = Application::getInstance()->getGLWidget()->height(); - - return computeViewPickRay(x / screenWidth, y / screenHeight); + QSharedPointer glCanvas = DependencyManager::get(); + return computeViewPickRay(x / glCanvas->width(), y / glCanvas->height()); } PickRay Camera::computeViewPickRay(float xRatio, float yRatio) { diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 14327bd51a..501da725e4 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -436,12 +436,12 @@ Menu::Menu() : MenuOption::Faceshift, 0, true, - DependencyManager::get(), + DependencyManager::get().data(), SLOT(setTCPEnabled(bool))); #endif #ifdef HAVE_VISAGE addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::Visage, 0, false, - DependencyManager::get(), SLOT(updateEnabled())); + DependencyManager::get().data(), SLOT(updateEnabled())); #endif addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::RenderSkeletonCollisionShapes); @@ -1050,11 +1050,11 @@ void Menu::bumpSettings() { void sendFakeEnterEvent() { QPoint lastCursorPosition = QCursor::pos(); - QGLWidget* glWidget = Application::getInstance()->getGLWidget(); + QSharedPointer glCanvas = DependencyManager::get(); - QPoint windowPosition = glWidget->mapFromGlobal(lastCursorPosition); + QPoint windowPosition = glCanvas->mapFromGlobal(lastCursorPosition); QEnterEvent enterEvent = QEnterEvent(windowPosition, windowPosition, lastCursorPosition); - QCoreApplication::sendEvent(glWidget, &enterEvent); + QCoreApplication::sendEvent(glCanvas.data(), &enterEvent); } const float DIALOG_RATIO_OF_WINDOW = 0.30f; @@ -1302,7 +1302,7 @@ void Menu::toggleLoginMenuItem() { void Menu::bandwidthDetails() { if (! _bandwidthDialog) { - _bandwidthDialog = new BandwidthDialog(Application::getInstance()->getGLWidget(), + _bandwidthDialog = new BandwidthDialog(DependencyManager::get().data(), Application::getInstance()->getBandwidthMeter()); connect(_bandwidthDialog, SIGNAL(closed()), SLOT(bandwidthDetailsClosed())); @@ -1413,7 +1413,7 @@ void Menu::bandwidthDetailsClosed() { void Menu::octreeStatsDetails() { if (!_octreeStatsDialog) { - _octreeStatsDialog = new OctreeStatsDialog(Application::getInstance()->getGLWidget(), + _octreeStatsDialog = new OctreeStatsDialog(DependencyManager::get().data(), Application::getInstance()->getOcteeSceneStats()); connect(_octreeStatsDialog, SIGNAL(closed()), SLOT(octreeStatsDetailsClosed())); _octreeStatsDialog->show(); @@ -1597,7 +1597,7 @@ bool Menu::shouldRenderMesh(float largestDimension, float distanceToCamera) { void Menu::lodTools() { if (!_lodToolsDialog) { - _lodToolsDialog = new LodToolsDialog(Application::getInstance()->getGLWidget()); + _lodToolsDialog = new LodToolsDialog(DependencyManager::get().data()); connect(_lodToolsDialog, SIGNAL(closed()), SLOT(lodToolsClosed())); _lodToolsDialog->show(); if (_hmdToolsDialog) { @@ -1617,7 +1617,7 @@ void Menu::lodToolsClosed() { void Menu::hmdTools(bool showTools) { if (showTools) { if (!_hmdToolsDialog) { - _hmdToolsDialog = new HMDToolsDialog(Application::getInstance()->getGLWidget()); + _hmdToolsDialog = new HMDToolsDialog(DependencyManager::get().data()); connect(_hmdToolsDialog, SIGNAL(closed()), SLOT(hmdToolsClosed())); } _hmdToolsDialog->show(); diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index 42b3c968e1..150b67eb13 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -71,20 +71,19 @@ void Head::reset() { } void Head::simulate(float deltaTime, bool isMine, bool billboard) { - if (isMine) { MyAvatar* myAvatar = static_cast(_owningAvatar); // Only use face trackers when not playing back a recording. if (!myAvatar->isPlaying()) { FaceTracker* faceTracker = Application::getInstance()->getActiveFaceTracker(); - DdeFaceTracker* dde = DependencyManager::get(); - Faceshift* faceshift = DependencyManager::get(); + QSharedPointer dde = DependencyManager::get(); + QSharedPointer faceshift = DependencyManager::get(); if ((_isFaceshiftConnected = (faceshift == faceTracker))) { _blendshapeCoefficients = faceTracker->getBlendshapeCoefficients(); } else if (dde->isActive()) { - faceTracker = dde; + faceTracker = dde.data(); _blendshapeCoefficients = faceTracker->getBlendshapeCoefficients(); } } diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 17cda19980..a546560ffd 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -422,7 +422,7 @@ void MyAvatar::render(const glm::vec3& cameraPosition, RenderMode renderMode, bo } void MyAvatar::renderHeadMouse(int screenWidth, int screenHeight) const { - Faceshift* faceshift = DependencyManager::get(); + QSharedPointer faceshift = DependencyManager::get(); float pixelsPerDegree = screenHeight / Menu::getInstance()->getFieldOfView(); diff --git a/interface/src/devices/DdeFaceTracker.h b/interface/src/devices/DdeFaceTracker.h index d80aa043e4..5ae17729d4 100644 --- a/interface/src/devices/DdeFaceTracker.h +++ b/interface/src/devices/DdeFaceTracker.h @@ -18,8 +18,9 @@ #include "FaceTracker.h" -class DdeFaceTracker : public FaceTracker, public DependencyManager::Dependency { +class DdeFaceTracker : public FaceTracker { Q_OBJECT + SINGLETON_DEPENDENCY public: //initialization @@ -58,7 +59,6 @@ private: DdeFaceTracker(); DdeFaceTracker(const QHostAddress& host, quint16 port); ~DdeFaceTracker(); - friend DependencyManager; float getBlendshapeCoefficient(int index) const; void decodePacket(const QByteArray& buffer); diff --git a/interface/src/devices/Faceshift.h b/interface/src/devices/Faceshift.h index 3cca8f2bb1..73971db49d 100644 --- a/interface/src/devices/Faceshift.h +++ b/interface/src/devices/Faceshift.h @@ -24,8 +24,9 @@ #include "FaceTracker.h" /// Handles interaction with the Faceshift software, which provides head position/orientation and facial features. -class Faceshift : public FaceTracker, public DependencyManager::Dependency { +class Faceshift : public FaceTracker { Q_OBJECT + SINGLETON_DEPENDENCY public: void init(); @@ -89,7 +90,6 @@ private slots: private: Faceshift(); virtual ~Faceshift() {} - friend DependencyManager; float getBlendshapeCoefficient(int index) const; diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index dfec98c358..99515cb7a9 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -560,8 +560,8 @@ void OculusManager::display(const glm::quat &bodyOrientation, const glm::vec3 &p } // restore our normal viewport - glViewport(0, 0, Application::getInstance()->getGLWidget()->getDeviceWidth(), - Application::getInstance()->getGLWidget()->getDeviceHeight()); + QSharedPointer glCanvas = DependencyManager::get(); + glViewport(0, 0, glCanvas->getDeviceWidth(), glCanvas->getDeviceHeight()); glMatrixMode(GL_PROJECTION); glPopMatrix(); @@ -579,8 +579,8 @@ void OculusManager::display(const glm::quat &bodyOrientation, const glm::vec3 &p void OculusManager::renderDistortionMesh(ovrPosef eyeRenderPose[ovrEye_Count]) { glLoadIdentity(); - gluOrtho2D(0, Application::getInstance()->getGLWidget()->getDeviceWidth(), 0, - Application::getInstance()->getGLWidget()->getDeviceHeight()); + QSharedPointer glCanvas = DependencyManager::get(); + gluOrtho2D(0, glCanvas->getDeviceWidth(), 0, glCanvas->getDeviceHeight()); glDisable(GL_DEPTH_TEST); diff --git a/interface/src/devices/PrioVR.cpp b/interface/src/devices/PrioVR.cpp index d3e985d259..ab7c317c37 100644 --- a/interface/src/devices/PrioVR.cpp +++ b/interface/src/devices/PrioVR.cpp @@ -215,8 +215,9 @@ void PrioVR::renderCalibrationCountdown() { static TextRenderer* textRenderer = TextRenderer::getInstance(MONO_FONT_FAMILY, 18, QFont::Bold, false, TextRenderer::OUTLINE_EFFECT, 2); QByteArray text = "Assume T-Pose in " + QByteArray::number(secondsRemaining) + "..."; - textRenderer->draw((Application::getInstance()->getGLWidget()->width() - - textRenderer->computeWidth(text.constData())) / 2, Application::getInstance()->getGLWidget()->height() / 2, - text); + QSharedPointer glCanvas = DependencyManager::get(); + textRenderer->draw((glCanvas->width() - textRenderer->computeWidth(text.constData())) / 2, + glCanvas->height() / 2, + text); #endif } diff --git a/interface/src/devices/SixenseManager.cpp b/interface/src/devices/SixenseManager.cpp index 7a555eb902..73e4f53289 100644 --- a/interface/src/devices/SixenseManager.cpp +++ b/interface/src/devices/SixenseManager.cpp @@ -461,7 +461,7 @@ void SixenseManager::updateCalibration(const sixenseControllerData* controllers) void SixenseManager::emulateMouse(PalmData* palm, int index) { Application* application = Application::getInstance(); MyAvatar* avatar = application->getAvatar(); - GLCanvas* widget = application->getGLWidget(); + QSharedPointer glCanvas = DependencyManager::get(); QPoint pos; Qt::MouseButton bumperButton; @@ -489,10 +489,10 @@ void SixenseManager::emulateMouse(PalmData* palm, int index) { float yAngle = 0.5f - ((atan2(direction.z, direction.y) + M_PI_2)); // Get the pixel range over which the xAngle and yAngle are scaled - float cursorRange = widget->width() * getCursorPixelRangeMult(); + float cursorRange = glCanvas->width() * getCursorPixelRangeMult(); - pos.setX(widget->width() / 2.0f + cursorRange * xAngle); - pos.setY(widget->height() / 2.0f + cursorRange * yAngle); + pos.setX(glCanvas->width() / 2.0f + cursorRange * xAngle); + pos.setY(glCanvas->height() / 2.0f + cursorRange * yAngle); } diff --git a/interface/src/devices/TV3DManager.cpp b/interface/src/devices/TV3DManager.cpp index d7d7353b24..5c891224a8 100644 --- a/interface/src/devices/TV3DManager.cpp +++ b/interface/src/devices/TV3DManager.cpp @@ -33,10 +33,10 @@ bool TV3DManager::isConnected() { } void TV3DManager::connect() { - Application* app = Application::getInstance(); - int width = app->getGLWidget()->getDeviceWidth(); - int height = app->getGLWidget()->getDeviceHeight(); - Camera& camera = *app->getCamera(); + QSharedPointer glCanvas = DependencyManager::get(); + int width = glCanvas->getDeviceWidth(); + int height = glCanvas->getDeviceHeight(); + Camera& camera = *Application::getInstance()->getCamera(); configureCamera(camera, width, height); } @@ -91,7 +91,8 @@ void TV3DManager::display(Camera& whichCamera) { // left eye portal int portalX = 0; int portalY = 0; - QSize deviceSize = Application::getInstance()->getGLWidget()->getDeviceSize() * + QSharedPointer glCanvas = DependencyManager::get(); + QSize deviceSize = glCanvas->getDeviceSize() * Application::getInstance()->getRenderResolutionScale(); int portalW = deviceSize.width() / 2; int portalH = deviceSize.height(); diff --git a/interface/src/devices/Visage.cpp b/interface/src/devices/Visage.cpp index 51b927df75..a810b1a258 100644 --- a/interface/src/devices/Visage.cpp +++ b/interface/src/devices/Visage.cpp @@ -121,7 +121,7 @@ static const QMultiHash >& getActionUnitNameMap() const float TRANSLATION_SCALE = 20.0f; void Visage::init() { - connect(DependencyManager::get(), SIGNAL(connectionStateChanged()), SLOT(updateEnabled())); + connect(DependencyManager::get().data(), SIGNAL(connectionStateChanged()), SLOT(updateEnabled())); updateEnabled(); } diff --git a/interface/src/devices/Visage.h b/interface/src/devices/Visage.h index 73edddc4d7..38e337aada 100644 --- a/interface/src/devices/Visage.h +++ b/interface/src/devices/Visage.h @@ -26,8 +26,9 @@ namespace VisageSDK { } /// Handles input from the Visage webcam feature tracking software. -class Visage : public FaceTracker, public DependencyManager::Dependency { +class Visage : public FaceTracker { Q_OBJECT + SINGLETON_DEPENDENCY public: void init(); @@ -44,7 +45,6 @@ public slots: private: Visage(); virtual ~Visage(); - friend DependencyManager; #ifdef HAVE_VISAGE VisageSDK::VisageTracker2* _tracker; diff --git a/interface/src/renderer/GlowEffect.cpp b/interface/src/renderer/GlowEffect.cpp index 9e9c1f2ed5..a760889eff 100644 --- a/interface/src/renderer/GlowEffect.cpp +++ b/interface/src/renderer/GlowEffect.cpp @@ -139,15 +139,15 @@ QOpenGLFramebufferObject* GlowEffect::render(bool toTexture) { QOpenGLFramebufferObject* destFBO = toTexture ? Application::getInstance()->getTextureCache()->getSecondaryFramebufferObject() : NULL; + QSharedPointer glCanvas = DependencyManager::get(); if (!Menu::getInstance()->isOptionChecked(MenuOption::EnableGlowEffect) || _isEmpty) { // copy the primary to the screen if (destFBO && QOpenGLFramebufferObject::hasOpenGLFramebufferBlit()) { - QOpenGLFramebufferObject::blitFramebuffer(destFBO, primaryFBO); + QOpenGLFramebufferObject::blitFramebuffer(destFBO, primaryFBO); } else { maybeBind(destFBO); if (!destFBO) { - glViewport(0, 0, Application::getInstance()->getGLWidget()->getDeviceWidth(), - Application::getInstance()->getGLWidget()->getDeviceHeight()); + glViewport(0, 0, glCanvas->getDeviceWidth(), glCanvas->getDeviceHeight()); } glEnable(GL_TEXTURE_2D); glDisable(GL_LIGHTING); @@ -194,9 +194,7 @@ QOpenGLFramebufferObject* GlowEffect::render(bool toTexture) { } maybeBind(destFBO); if (!destFBO) { - glViewport(0, 0, - Application::getInstance()->getGLWidget()->getDeviceWidth(), - Application::getInstance()->getGLWidget()->getDeviceHeight()); + glViewport(0, 0, glCanvas->getDeviceWidth(), glCanvas->getDeviceHeight()); } _addSeparateProgram->bind(); renderFullscreenQuad(); diff --git a/interface/src/renderer/TextureCache.cpp b/interface/src/renderer/TextureCache.cpp index f40f0e3faf..ec07d22647 100644 --- a/interface/src/renderer/TextureCache.cpp +++ b/interface/src/renderer/TextureCache.cpp @@ -352,7 +352,7 @@ QSharedPointer TextureCache::createResource(const QUrl& url, QOpenGLFramebufferObject* TextureCache::createFramebufferObject() { QOpenGLFramebufferObject* fbo = new QOpenGLFramebufferObject(_frameBufferSize); - Application::getInstance()->getGLWidget()->installEventFilter(this); + DependencyManager::get()->installEventFilter(this); glBindTexture(GL_TEXTURE_2D, fbo->texture()); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); diff --git a/interface/src/scripting/ControllerScriptingInterface.cpp b/interface/src/scripting/ControllerScriptingInterface.cpp index bcfe844668..a562236a92 100644 --- a/interface/src/scripting/ControllerScriptingInterface.cpp +++ b/interface/src/scripting/ControllerScriptingInterface.cpp @@ -267,9 +267,9 @@ void ControllerScriptingInterface::releaseJoystick(int joystickIndex) { } } -glm::vec2 ControllerScriptingInterface::getViewportDimensions() const { - GLCanvas* widget = Application::getInstance()->getGLWidget(); - return glm::vec2(widget->width(), widget->height()); +glm::vec2 ControllerScriptingInterface::getViewportDimensions() const { + QSharedPointer glCanvas = DependencyManager::get(); + return glm::vec2(glCanvas->width(), glCanvas->height()); } AbstractInputController* ControllerScriptingInterface::createInputController(const QString& deviceName, const QString& tracker) { diff --git a/interface/src/scripting/WindowScriptingInterface.cpp b/interface/src/scripting/WindowScriptingInterface.cpp index d69b1d0ba1..d84fc97cd8 100644 --- a/interface/src/scripting/WindowScriptingInterface.cpp +++ b/interface/src/scripting/WindowScriptingInterface.cpp @@ -40,7 +40,7 @@ WebWindowClass* WindowScriptingInterface::doCreateWebWindow(const QString& title } QScriptValue WindowScriptingInterface::hasFocus() { - return Application::getInstance()->getGLWidget()->hasFocus(); + return DependencyManager::get()->hasFocus(); } void WindowScriptingInterface::setCursorVisible(bool visible) { diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index f4e0c9769d..c95dc08e79 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -145,11 +145,11 @@ void ApplicationOverlay::renderOverlay(bool renderToTexture) { PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "ApplicationOverlay::displayOverlay()"); Application* application = Application::getInstance(); Overlays& overlays = application->getOverlays(); - GLCanvas* glWidget = application->getGLWidget(); + QSharedPointer glCanvas = DependencyManager::get(); MyAvatar* myAvatar = application->getAvatar(); _textureFov = glm::radians(Menu::getInstance()->getOculusUIAngularSize()); - _textureAspectRatio = (float)application->getGLWidget()->getDeviceWidth() / (float)application->getGLWidget()->getDeviceHeight(); + _textureAspectRatio = (float)glCanvas->getDeviceWidth() / (float)glCanvas->getDeviceHeight(); //Handle fading and deactivation/activation of UI if (Menu::getInstance()->isOptionChecked(MenuOption::UserInterface)) { @@ -178,12 +178,12 @@ void ApplicationOverlay::renderOverlay(bool renderToTexture) { glPushMatrix(); { glLoadIdentity(); - gluOrtho2D(0, glWidget->width(), glWidget->height(), 0); + gluOrtho2D(0, glCanvas->width(), glCanvas->height(), 0); renderAudioMeter(); if (Menu::getInstance()->isOptionChecked(MenuOption::HeadMouse)) { - myAvatar->renderHeadMouse(glWidget->width(), glWidget->height()); + myAvatar->renderHeadMouse(glCanvas->width(), glCanvas->height()); } renderStatsAndLogs(); @@ -213,7 +213,7 @@ void ApplicationOverlay::displayOverlayTexture() { if (_alpha == 0.0f) { return; } - GLCanvas* glWidget = Application::getInstance()->getGLWidget(); + QSharedPointer glCanvas = DependencyManager::get(); glEnable(GL_TEXTURE_2D); glActiveTexture(GL_TEXTURE0); @@ -222,16 +222,16 @@ void ApplicationOverlay::displayOverlayTexture() { glMatrixMode(GL_PROJECTION); glPushMatrix(); { glLoadIdentity(); - gluOrtho2D(0, glWidget->getDeviceWidth(), glWidget->getDeviceHeight(), 0); + gluOrtho2D(0, glCanvas->getDeviceWidth(), glCanvas->getDeviceHeight(), 0); glDisable(GL_DEPTH_TEST); glDisable(GL_LIGHTING); glEnable(GL_BLEND); glBegin(GL_QUADS); { glColor4f(1.0f, 1.0f, 1.0f, _alpha); - glTexCoord2f(0, 0); glVertex2i(0, glWidget->getDeviceHeight()); - glTexCoord2f(1, 0); glVertex2i(glWidget->getDeviceWidth(), glWidget->getDeviceHeight()); - glTexCoord2f(1, 1); glVertex2i(glWidget->getDeviceWidth(), 0); + glTexCoord2f(0, 0); glVertex2i(0, glCanvas->getDeviceHeight()); + glTexCoord2f(1, 0); glVertex2i(glCanvas->getDeviceWidth(), glCanvas->getDeviceHeight()); + glTexCoord2f(1, 1); glVertex2i(glCanvas->getDeviceWidth(), 0); glTexCoord2f(0, 1); glVertex2i(0, 0); } glEnd(); } glPopMatrix(); @@ -378,18 +378,19 @@ void ApplicationOverlay::displayOverlayTexture3DTV(Camera& whichCamera, float as glEnd(); + QSharedPointer glCanvas = DependencyManager::get(); if (_crosshairTexture == 0) { - _crosshairTexture = Application::getInstance()->getGLWidget()->bindTexture(QImage(Application::resourcesPath() + "images/sixense-reticle.png")); + _crosshairTexture = glCanvas->bindTexture(QImage(Application::resourcesPath() + "images/sixense-reticle.png")); } //draw the mouse pointer glBindTexture(GL_TEXTURE_2D, _crosshairTexture); - const float reticleSize = 40.0f / application->getGLWidget()->width() * quadWidth; + const float reticleSize = 40.0f / glCanvas->width() * quadWidth; x -= reticleSize / 2.0f; y += reticleSize / 2.0f; - const float mouseX = (application->getMouseX() / (float)application->getGLWidget()->width()) * quadWidth; - const float mouseY = (1.0 - (application->getMouseY() / (float)application->getGLWidget()->height())) * quadHeight; + const float mouseX = (application->getMouseX() / (float)glCanvas->width()) * quadWidth; + const float mouseY = (1.0 - (application->getMouseY() / (float)glCanvas->height())) * quadHeight; glBegin(GL_QUADS); @@ -431,7 +432,7 @@ void ApplicationOverlay::computeOculusPickRay(float x, float y, glm::vec3& origi //Caculate the click location using one of the sixense controllers. Scale is not applied QPoint ApplicationOverlay::getPalmClickLocation(const PalmData *palm) const { Application* application = Application::getInstance(); - GLCanvas* glWidget = application->getGLWidget(); + QSharedPointer glCanvas = DependencyManager::get(); MyAvatar* myAvatar = application->getAvatar(); glm::vec3 tip = myAvatar->getLaserPointerTipPosition(palm); @@ -462,8 +463,8 @@ QPoint ApplicationOverlay::getPalmClickLocation(const PalmData *palm) const { float u = asin(collisionPos.x) / (_textureFov)+0.5f; float v = 1.0 - (asin(collisionPos.y) / (_textureFov)+0.5f); - rv.setX(u * glWidget->width()); - rv.setY(v * glWidget->height()); + rv.setX(u * glCanvas->width()); + rv.setY(v * glCanvas->height()); } } else { //if they did not click on the overlay, just set the coords to INT_MAX @@ -480,8 +481,8 @@ QPoint ApplicationOverlay::getPalmClickLocation(const PalmData *palm) const { ndcSpacePos = glm::vec3(clipSpacePos) / clipSpacePos.w; } - rv.setX(((ndcSpacePos.x + 1.0) / 2.0) * glWidget->width()); - rv.setY((1.0 - ((ndcSpacePos.y + 1.0) / 2.0)) * glWidget->height()); + rv.setX(((ndcSpacePos.x + 1.0) / 2.0) * glCanvas->width()); + rv.setY((1.0 - ((ndcSpacePos.y + 1.0) / 2.0)) * glCanvas->height()); } return rv; } @@ -510,10 +511,11 @@ bool ApplicationOverlay::calculateRayUICollisionPoint(const glm::vec3& position, //Renders optional pointers void ApplicationOverlay::renderPointers() { Application* application = Application::getInstance(); + QSharedPointer glCanvas = DependencyManager::get(); //lazily load crosshair texture if (_crosshairTexture == 0) { - _crosshairTexture = Application::getInstance()->getGLWidget()->bindTexture(QImage(Application::resourcesPath() + "images/sixense-reticle.png")); + _crosshairTexture = glCanvas->bindTexture(QImage(Application::resourcesPath() + "images/sixense-reticle.png")); } glEnable(GL_TEXTURE_2D); @@ -536,7 +538,7 @@ void ApplicationOverlay::renderPointers() { glm::vec2 screenPos = sphericalToScreen(glm::vec2(yaw, -pitch)); position = QPoint(screenPos.x, screenPos.y); - application->getGLWidget()->cursor().setPos(application->getGLWidget()->mapToGlobal(position)); + glCanvas->cursor().setPos(glCanvas->mapToGlobal(position)); } _reticlePosition[MOUSE] = position; @@ -557,7 +559,7 @@ void ApplicationOverlay::renderPointers() { void ApplicationOverlay::renderControllerPointers() { Application* application = Application::getInstance(); - GLCanvas* glWidget = application->getGLWidget(); + QSharedPointer glCanvas = DependencyManager::get(); MyAvatar* myAvatar = application->getAvatar(); //Static variables used for storing controller state @@ -635,14 +637,14 @@ void ApplicationOverlay::renderControllerPointers() { float yAngle = 0.5f - ((atan2(direction.z, direction.y) + M_PI_2)); // Get the pixel range over which the xAngle and yAngle are scaled - float cursorRange = glWidget->width() * SixenseManager::getInstance().getCursorPixelRangeMult(); + float cursorRange = glCanvas->width() * SixenseManager::getInstance().getCursorPixelRangeMult(); - mouseX = (glWidget->width() / 2.0f + cursorRange * xAngle); - mouseY = (glWidget->height() / 2.0f + cursorRange * yAngle); + mouseX = (glCanvas->width() / 2.0f + cursorRange * xAngle); + mouseY = (glCanvas->height() / 2.0f + cursorRange * yAngle); } //If the cursor is out of the screen then don't render it - if (mouseX < 0 || mouseX >= glWidget->width() || mouseY < 0 || mouseY >= glWidget->height()) { + if (mouseX < 0 || mouseX >= glCanvas->width() || mouseY < 0 || mouseY >= glCanvas->height()) { _reticleActive[index] = false; continue; } @@ -702,11 +704,10 @@ void ApplicationOverlay::renderPointersOculus(const glm::vec3& eyePos) { //Renders a small magnification of the currently bound texture at the coordinates void ApplicationOverlay::renderMagnifier(glm::vec2 magPos, float sizeMult, bool showBorder) const { - Application* application = Application::getInstance(); - GLCanvas* glWidget = application->getGLWidget(); + QSharedPointer glCanvas = DependencyManager::get(); - const int widgetWidth = glWidget->width(); - const int widgetHeight = glWidget->height(); + const int widgetWidth = glCanvas->width(); + const int widgetHeight = glCanvas->height(); const float halfWidth = (MAGNIFY_WIDTH / _textureAspectRatio) * sizeMult / 2.0f; const float halfHeight = MAGNIFY_HEIGHT * sizeMult / 2.0f; @@ -760,8 +761,8 @@ void ApplicationOverlay::renderMagnifier(glm::vec2 magPos, float sizeMult, bool void ApplicationOverlay::renderAudioMeter() { Application* application = Application::getInstance(); - - GLCanvas* glWidget = application->getGLWidget(); + + QSharedPointer glCanvas = DependencyManager::get(); Audio* audio = application->getAudio(); // Display a single screen-size quad to create an alpha blended 'collision' flash @@ -769,7 +770,7 @@ void ApplicationOverlay::renderAudioMeter() { float collisionSoundMagnitude = audio->getCollisionSoundMagnitude(); const float VISIBLE_COLLISION_SOUND_MAGNITUDE = 0.5f; if (collisionSoundMagnitude > VISIBLE_COLLISION_SOUND_MAGNITUDE) { - renderCollisionOverlay(glWidget->width(), glWidget->height(), + renderCollisionOverlay(glCanvas->width(), glCanvas->height(), audio->getCollisionSoundMagnitude()); } } @@ -823,14 +824,14 @@ void ApplicationOverlay::renderAudioMeter() { if ((audio->getTimeSinceLastClip() > 0.0f) && (audio->getTimeSinceLastClip() < CLIPPING_INDICATOR_TIME)) { const float MAX_MAGNITUDE = 0.7f; float magnitude = MAX_MAGNITUDE * (1 - audio->getTimeSinceLastClip() / CLIPPING_INDICATOR_TIME); - renderCollisionOverlay(glWidget->width(), glWidget->height(), magnitude, 1.0f); + renderCollisionOverlay(glCanvas->width(), glCanvas->height(), magnitude, 1.0f); } audio->renderToolBox(MIRROR_VIEW_LEFT_PADDING + AUDIO_METER_GAP, audioMeterY, boxed); - audio->renderScope(glWidget->width(), glWidget->height()); + audio->renderScope(glCanvas->width(), glCanvas->height()); - audio->renderStats(WHITE_TEXT, glWidget->width(), glWidget->height()); + audio->renderStats(WHITE_TEXT, glCanvas->width(), glCanvas->height()); glBegin(GL_QUADS); if (isClipping) { @@ -891,8 +892,8 @@ void ApplicationOverlay::renderAudioMeter() { void ApplicationOverlay::renderStatsAndLogs() { Application* application = Application::getInstance(); - - GLCanvas* glWidget = application->getGLWidget(); + + QSharedPointer glCanvas = DependencyManager::get(); const OctreePacketProcessor& octreePacketProcessor = application->getOctreePacketProcessor(); BandwidthMeter* bandwidthMeter = application->getBandwidthMeter(); NodeBounds& nodeBoundsDisplay = application->getNodeBoundsDisplay(); @@ -910,8 +911,8 @@ void ApplicationOverlay::renderStatsAndLogs() { application->getPacketsPerSecond(), application->getBytesPerSecond(), voxelPacketsToProcess); // Bandwidth meter if (Menu::getInstance()->isOptionChecked(MenuOption::Bandwidth)) { - Stats::drawBackground(0x33333399, glWidget->width() - 296, glWidget->height() - 68, 296, 68); - bandwidthMeter->render(glWidget->width(), glWidget->height()); + Stats::drawBackground(0x33333399, glCanvas->width() - 296, glCanvas->height() - 68, 296, 68); + bandwidthMeter->render(glCanvas->width(), glCanvas->height()); } } @@ -924,7 +925,7 @@ void ApplicationOverlay::renderStatsAndLogs() { (Menu::getInstance()->isOptionChecked(MenuOption::Stats) && Menu::getInstance()->isOptionChecked(MenuOption::Bandwidth)) ? 80 : 20; - drawText(glWidget->width() - 100, glWidget->height() - timerBottom, + drawText(glCanvas->width() - 100, glCanvas->height() - timerBottom, 0.30f, 0.0f, 0, frameTimer, WHITE_TEXT); } nodeBoundsDisplay.drawOverlay(); @@ -934,9 +935,9 @@ void ApplicationOverlay::renderDomainConnectionStatusBorder() { NodeList* nodeList = NodeList::getInstance(); if (nodeList && !nodeList->getDomainHandler().isConnected()) { - GLCanvas* glWidget = Application::getInstance()->getGLWidget(); - int right = glWidget->width(); - int bottom = glWidget->height(); + QSharedPointer glCanvas = DependencyManager::get(); + int right = glCanvas->width(); + int bottom = glCanvas->height(); glColor3f(CONNECTION_STATUS_BORDER_COLOR[0], CONNECTION_STATUS_BORDER_COLOR[1], @@ -1071,7 +1072,7 @@ void ApplicationOverlay::TexturedHemisphere::cleanupVBO() { } void ApplicationOverlay::TexturedHemisphere::buildFramebufferObject() { - QSize size = Application::getInstance()->getGLWidget()->getDeviceSize(); + QSize size = DependencyManager::get()->getDeviceSize(); if (_framebufferObject != NULL && size == _framebufferObject->size()) { // Already build return; @@ -1122,7 +1123,7 @@ void ApplicationOverlay::TexturedHemisphere::render() { glm::vec2 ApplicationOverlay::screenToSpherical(glm::vec2 screenPos) const { - QSize screenSize = Application::getInstance()->getGLWidget()->getDeviceSize(); + QSize screenSize = DependencyManager::get()->getDeviceSize(); float yaw = -(screenPos.x / screenSize.width() - 0.5f) * MOUSE_YAW_RANGE; float pitch = (screenPos.y / screenSize.height() - 0.5f) * MOUSE_PITCH_RANGE; @@ -1130,7 +1131,7 @@ glm::vec2 ApplicationOverlay::screenToSpherical(glm::vec2 screenPos) const { } glm::vec2 ApplicationOverlay::sphericalToScreen(glm::vec2 sphericalPos) const { - QSize screenSize = Application::getInstance()->getGLWidget()->getDeviceSize(); + QSize screenSize = DependencyManager::get()->getDeviceSize(); float x = (-sphericalPos.x / MOUSE_YAW_RANGE + 0.5f) * screenSize.width(); float y = (sphericalPos.y / MOUSE_PITCH_RANGE + 0.5f) * screenSize.height(); @@ -1138,7 +1139,7 @@ glm::vec2 ApplicationOverlay::sphericalToScreen(glm::vec2 sphericalPos) const { } glm::vec2 ApplicationOverlay::sphericalToOverlay(glm::vec2 sphericalPos) const { - QSize screenSize = Application::getInstance()->getGLWidget()->getDeviceSize(); + QSize screenSize = DependencyManager::get()->getDeviceSize(); float x = (-sphericalPos.x / (_textureFov * _textureAspectRatio) + 0.5f) * screenSize.width(); float y = (sphericalPos.y / _textureFov + 0.5f) * screenSize.height(); @@ -1146,7 +1147,7 @@ glm::vec2 ApplicationOverlay::sphericalToOverlay(glm::vec2 sphericalPos) const { } glm::vec2 ApplicationOverlay::overlayToSpherical(glm::vec2 overlayPos) const { - QSize screenSize = Application::getInstance()->getGLWidget()->getDeviceSize(); + QSize screenSize = DependencyManager::get()->getDeviceSize(); float yaw = -(overlayPos.x / screenSize.width() - 0.5f) * _textureFov * _textureAspectRatio; float pitch = (overlayPos.y / screenSize.height() - 0.5f) * _textureFov; diff --git a/interface/src/ui/MetavoxelEditor.cpp b/interface/src/ui/MetavoxelEditor.cpp index 46f69b0452..75f2ebf97f 100644 --- a/interface/src/ui/MetavoxelEditor.cpp +++ b/interface/src/ui/MetavoxelEditor.cpp @@ -138,7 +138,7 @@ MetavoxelEditor::MetavoxelEditor() : connect(Application::getInstance()->getMetavoxels(), &MetavoxelSystem::rendering, this, &MetavoxelEditor::renderPreview); - Application::getInstance()->getGLWidget()->installEventFilter(this); + DependencyManager::get()->installEventFilter(this); show(); diff --git a/interface/src/ui/MetavoxelNetworkSimulator.cpp b/interface/src/ui/MetavoxelNetworkSimulator.cpp index aabee97636..7185524d6f 100644 --- a/interface/src/ui/MetavoxelNetworkSimulator.cpp +++ b/interface/src/ui/MetavoxelNetworkSimulator.cpp @@ -21,7 +21,7 @@ const int BYTES_PER_KILOBYTE = 1024; MetavoxelNetworkSimulator::MetavoxelNetworkSimulator() : - QWidget(Application::getInstance()->getGLWidget(), Qt::Dialog) { + QWidget(DependencyManager::get().data(), Qt::Dialog) { setWindowTitle("Metavoxel Network Simulator"); setAttribute(Qt::WA_DeleteOnClose); diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index 318dce977a..d39266e0fd 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -215,8 +215,8 @@ void PreferencesDialog::savePreferences() { myAvatar->setClampedTargetScale(ui.avatarScaleSpin->value()); Application::getInstance()->getVoxels()->setMaxVoxels(ui.maxVoxelsSpin->value()); - Application::getInstance()->resizeGL(Application::getInstance()->getGLWidget()->width(), - Application::getInstance()->getGLWidget()->height()); + QSharedPointer glCanvas = DependencyManager::get(); + Application::getInstance()->resizeGL(glCanvas->width(), glCanvas->height()); Menu::getInstance()->setRealWorldFieldOfView(ui.realWorldFieldOfViewSpin->value()); @@ -248,8 +248,7 @@ void PreferencesDialog::savePreferences() { Menu::getInstance()->setReceivedAudioStreamSettings(streamSettings); Application::getInstance()->getAudio()->setReceivedAudioStreamSettings(streamSettings); - Application::getInstance()->resizeGL(Application::getInstance()->getGLWidget()->width(), - Application::getInstance()->getGLWidget()->height()); + Application::getInstance()->resizeGL(glCanvas->width(), glCanvas->height()); Application::getInstance()->bumpSettings(); } diff --git a/interface/src/ui/Snapshot.cpp b/interface/src/ui/Snapshot.cpp index d68920a5f5..ddd2b93805 100644 --- a/interface/src/ui/Snapshot.cpp +++ b/interface/src/ui/Snapshot.cpp @@ -83,9 +83,8 @@ QTemporaryFile* Snapshot::saveTempSnapshot() { } QFile* Snapshot::savedFileForSnapshot(bool isTemporary) { - - QGLWidget* widget = Application::getInstance()->getGLWidget(); - QImage shot = widget->grabFrameBuffer(); + QSharedPointer glCanvas = DependencyManager::get(); + QImage shot = glCanvas->grabFrameBuffer(); Avatar* avatar = Application::getInstance()->getAvatar(); diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index 9abb3d1b78..2581866c70 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -56,8 +56,8 @@ Stats::Stats(): _metavoxelReceiveProgress(0), _metavoxelReceiveTotal(0) { - GLCanvas* glWidget = Application::getInstance()->getGLWidget(); - resetWidth(glWidget->width(), 0); + QSharedPointer glCanvas = DependencyManager::get(); + resetWidth(glCanvas->width(), 0); } void Stats::toggleExpanded() { @@ -67,7 +67,7 @@ void Stats::toggleExpanded() { // called on mouse click release // check for clicks over stats in order to expand or contract them void Stats::checkClick(int mouseX, int mouseY, int mouseDragStartedX, int mouseDragStartedY, int horizontalOffset) { - GLCanvas* glWidget = Application::getInstance()->getGLWidget(); + QSharedPointer glCanvas = DependencyManager::get(); if (0 != glm::compMax(glm::abs(glm::ivec2(mouseX - mouseDragStartedX, mouseY - mouseDragStartedY)))) { // not worried about dragging on stats @@ -114,7 +114,7 @@ void Stats::checkClick(int mouseX, int mouseY, int mouseDragStartedX, int mouseD // top-right stats click lines = _expanded ? 11 : 3; statsHeight = lines * STATS_PELS_PER_LINE + 10; - statsWidth = glWidget->width() - statsX; + statsWidth = glCanvas->width() - statsX; if (mouseX > statsX && mouseX < statsX + statsWidth && mouseY > statsY && mouseY < statsY + statsHeight) { toggleExpanded(); return; @@ -122,8 +122,8 @@ void Stats::checkClick(int mouseX, int mouseY, int mouseDragStartedX, int mouseD } void Stats::resetWidth(int width, int horizontalOffset) { - GLCanvas* glWidget = Application::getInstance()->getGLWidget(); - int extraSpace = glWidget->width() - horizontalOffset -2 + QSharedPointer glCanvas = DependencyManager::get(); + int extraSpace = glCanvas->width() - horizontalOffset -2 - STATS_GENERAL_MIN_WIDTH - (Menu::getInstance()->isOptionChecked(MenuOption::TestPing) ? STATS_PING_MIN_WIDTH -1 : 0) - STATS_GEO_MIN_WIDTH @@ -147,7 +147,7 @@ void Stats::resetWidth(int width, int horizontalOffset) { _pingStatsWidth += (int) extraSpace / panels; } _geoStatsWidth += (int) extraSpace / panels; - _voxelStatsWidth += glWidget->width() - (_generalStatsWidth + _pingStatsWidth + _geoStatsWidth + 3); + _voxelStatsWidth += glCanvas->width() - (_generalStatsWidth + _pingStatsWidth + _geoStatsWidth + 3); } } @@ -198,7 +198,7 @@ void Stats::display( int bytesPerSecond, int voxelPacketsToProcess) { - GLCanvas* glWidget = Application::getInstance()->getGLWidget(); + QSharedPointer glCanvas = DependencyManager::get(); unsigned int backgroundColor = 0x33333399; int verticalOffset = 0, lines = 0; @@ -210,7 +210,7 @@ void Stats::display( std::stringstream voxelStats; if (_lastHorizontalOffset != horizontalOffset) { - resetWidth(glWidget->width(), horizontalOffset); + resetWidth(glCanvas->width(), horizontalOffset); _lastHorizontalOffset = horizontalOffset; } @@ -478,7 +478,7 @@ void Stats::display( lines = _expanded ? 14 : 3; - drawBackground(backgroundColor, horizontalOffset, 0, glWidget->width() - horizontalOffset, + drawBackground(backgroundColor, horizontalOffset, 0, glCanvas->width() - horizontalOffset, lines * STATS_PELS_PER_LINE + 10); horizontalOffset += 5; From 892141fe14f485c55e3c17738eec5d66a197d39b Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Mon, 15 Dec 2014 16:36:26 -0800 Subject: [PATCH 429/502] Fix for crash on exit due to cache references' not being cleared. --- libraries/networking/src/ResourceCache.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/libraries/networking/src/ResourceCache.cpp b/libraries/networking/src/ResourceCache.cpp index 097ede23d0..5bb327fe63 100644 --- a/libraries/networking/src/ResourceCache.cpp +++ b/libraries/networking/src/ResourceCache.cpp @@ -28,9 +28,13 @@ ResourceCache::ResourceCache(QObject* parent) : } ResourceCache::~ResourceCache() { - // make sure our unused resources know we're out of commission - foreach (const QSharedPointer& resource, _unusedResources) { - resource->setCache(NULL); + // the unused resources may themselves reference resources that will be added to the unused + // list on destruction, so keep clearing until there are no references left + while (!_unusedResources.isEmpty()) { + foreach (const QSharedPointer& resource, _unusedResources) { + resource->setCache(NULL); + } + _unusedResources.clear(); } } From e53833b3060fe5094ef8d0c2a066820026088602 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 15 Dec 2014 17:29:48 -0800 Subject: [PATCH 430/502] make GlowEffect support DependencyManager --- interface/src/Application.cpp | 10 +++++--- interface/src/Application.h | 3 --- interface/src/avatar/Avatar.cpp | 1 + interface/src/avatar/AvatarManager.cpp | 3 ++- interface/src/avatar/Head.cpp | 5 ++-- interface/src/devices/OculusManager.cpp | 5 ++-- interface/src/devices/TV3DManager.cpp | 5 ++-- interface/src/entities/EntityTreeRenderer.cpp | 2 ++ .../src/renderer/AmbientOcclusionEffect.cpp | 3 ++- .../src/renderer/DeferredLightingEffect.cpp | 5 ++-- interface/src/renderer/GlowEffect.cpp | 24 ++++++++++++------- interface/src/renderer/GlowEffect.h | 17 +++++++++---- interface/src/renderer/Model.cpp | 5 +++- .../src/ui/overlays/LocalModelsOverlay.cpp | 1 + .../src/ui/overlays/LocalVoxelsOverlay.cpp | 1 + interface/src/ui/overlays/ModelOverlay.cpp | 1 + interface/src/voxels/VoxelFade.cpp | 5 ++-- 17 files changed, 64 insertions(+), 32 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 76247d1d9d..4bc4b0d339 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -90,6 +90,8 @@ #include "gpu/Batch.h" #include "gpu/GLBackend.h" +#include "renderer/GlowEffect.h" + #include "scripting/AccountScriptingInterface.h" #include "scripting/AudioDeviceScriptingInterface.h" #include "scripting/ClipboardScriptingInterface.h" @@ -702,7 +704,7 @@ void Application::paintGL() { TV3DManager::display(*whichCamera); } else { - _glowEffect.prepare(); + DependencyManager::get()->prepare(); // Viewport is assigned to the size of the framebuffer QSize size = DependencyManager::get()->getPrimaryFramebufferObject()->size(); @@ -721,7 +723,7 @@ void Application::paintGL() { renderRearViewMirror(_mirrorViewRect); } - _glowEffect.render(); + DependencyManager::get()->render(); { PerformanceTimer perfTimer("renderOverlay"); @@ -1913,7 +1915,6 @@ void Application::init() { _environment.init(); _deferredLightingEffect.init(); - _glowEffect.init(); _ambientOcclusionEffect.init(); // TODO: move _myAvatar out of Application. Move relevant code to MyAvataar or AvatarManager @@ -2036,6 +2037,9 @@ void Application::init() { // make sure our texture cache knows about window size changes DependencyManager::get()->associateWithWidget(getGLWidget()); + + // initialize the GlowEffect with our widget + DependencyManager::get()->init(getGLWidget()); } void Application::closeMirrorView() { diff --git a/interface/src/Application.h b/interface/src/Application.h index 0e1feafb7e..716d67c661 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -63,7 +63,6 @@ #include "entities/EntityTreeRenderer.h" #include "renderer/AmbientOcclusionEffect.h" #include "renderer/DeferredLightingEffect.h" -#include "renderer/GlowEffect.h" #include "scripting/ControllerScriptingInterface.h" #include "ui/BandwidthDialog.h" #include "ui/BandwidthMeter.h" @@ -252,7 +251,6 @@ public: AnimationCache* getAnimationCache() { return &_animationCache; } DeferredLightingEffect* getDeferredLightingEffect() { return &_deferredLightingEffect; } - GlowEffect* getGlowEffect() { return &_glowEffect; } ControllerScriptingInterface* getControllerScriptingInterface() { return &_controllerScriptingInterface; } AvatarManager& getAvatarManager() { return _avatarManager; } @@ -571,7 +569,6 @@ private: AnimationCache _animationCache; DeferredLightingEffect _deferredLightingEffect; - GlowEffect _glowEffect; AmbientOcclusionEffect _ambientOcclusionEffect; Audio _audio; diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index e0896364f6..83de09c4f5 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -40,6 +40,7 @@ #include "Recorder.h" #include "world.h" #include "devices/OculusManager.h" +#include "renderer/GlowEffect.h" #include "ui/TextRenderer.h" using namespace std; diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index ca6a6db4a7..2de272bb29 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -21,10 +21,11 @@ #include "Application.h" #include "Avatar.h" +#include "AvatarManager.h" #include "Menu.h" #include "MyAvatar.h" -#include "AvatarManager.h" +#include "renderer/GlowEffect.h" // We add _myAvatar into the hash with all the other AvatarData, and we use the default NULL QUid as the key. const QUuid MY_AVATAR_KEY; // NULL key diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index 42b3c968e1..fb20ccdbde 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -22,6 +22,7 @@ #include "Menu.h" #include "Util.h" #include "devices/OculusManager.h" +#include "renderer/GlowEffect.h" using namespace std; @@ -331,7 +332,7 @@ void Head::addLeanDeltas(float sideways, float forward) { void Head::renderLookatVectors(glm::vec3 leftEyePosition, glm::vec3 rightEyePosition, glm::vec3 lookatPosition) { - Application::getInstance()->getGlowEffect()->begin(); + DependencyManager::get()->begin(); glLineWidth(2.0); glBegin(GL_LINES); @@ -345,7 +346,7 @@ void Head::renderLookatVectors(glm::vec3 leftEyePosition, glm::vec3 rightEyePosi glVertex3f(lookatPosition.x, lookatPosition.y, lookatPosition.z); glEnd(); - Application::getInstance()->getGlowEffect()->end(); + DependencyManager::get()->end(); } diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index 7f5c2cd668..b000d6436b 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -26,6 +26,7 @@ #include #include "Application.h" +#include "renderer/GlowEffect.h" #ifdef HAVE_LIBOVR @@ -448,7 +449,7 @@ void OculusManager::display(const glm::quat &bodyOrientation, const glm::vec3 &p //Bind our framebuffer object. If we are rendering the glow effect, we let the glow effect shader take care of it if (Menu::getInstance()->isOptionChecked(MenuOption::EnableGlowEffect)) { - Application::getInstance()->getGlowEffect()->prepare(); + DependencyManager::get()->prepare(); } else { DependencyManager::get()->getPrimaryFramebufferObject()->bind(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -553,7 +554,7 @@ void OculusManager::display(const glm::quat &bodyOrientation, const glm::vec3 &p //Bind the output texture from the glow shader. If glow effect is disabled, we just grab the texture if (Menu::getInstance()->isOptionChecked(MenuOption::EnableGlowEffect)) { - QOpenGLFramebufferObject* fbo = Application::getInstance()->getGlowEffect()->render(true); + QOpenGLFramebufferObject* fbo = DependencyManager::get()->render(true); glBindTexture(GL_TEXTURE_2D, fbo->texture()); } else { DependencyManager::get()->getPrimaryFramebufferObject()->release(); diff --git a/interface/src/devices/TV3DManager.cpp b/interface/src/devices/TV3DManager.cpp index d7d7353b24..b756ccf41e 100644 --- a/interface/src/devices/TV3DManager.cpp +++ b/interface/src/devices/TV3DManager.cpp @@ -19,6 +19,7 @@ #include "TV3DManager.h" #include "Menu.h" +#include "renderer/GlowEffect.h" int TV3DManager::_screenWidth = 1; int TV3DManager::_screenHeight = 1; @@ -103,7 +104,7 @@ void TV3DManager::display(Camera& whichCamera) { applicationOverlay.renderOverlay(true); const bool displayOverlays = Menu::getInstance()->isOptionChecked(MenuOption::UserInterface); - Application::getInstance()->getGlowEffect()->prepare(); + DependencyManager::get()->prepare(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -169,7 +170,7 @@ void TV3DManager::display(Camera& whichCamera) { // reset the viewport to how we started glViewport(0, 0, deviceSize.width(), deviceSize.height()); - Application::getInstance()->getGlowEffect()->render(); + DependencyManager::get()->render(); } void TV3DManager::overrideOffAxisFrustum(float& left, float& right, float& bottom, float& top, float& nearVal, diff --git a/interface/src/entities/EntityTreeRenderer.cpp b/interface/src/entities/EntityTreeRenderer.cpp index 2c2b81fa3a..aca111e731 100644 --- a/interface/src/entities/EntityTreeRenderer.cpp +++ b/interface/src/entities/EntityTreeRenderer.cpp @@ -36,6 +36,8 @@ #include "RenderableSphereEntityItem.h" #include "RenderableTextEntityItem.h" +#include "renderer/GlowEffect.h" + QThread* EntityTreeRenderer::getMainThread() { return Application::getInstance()->getEntities()->thread(); diff --git a/interface/src/renderer/AmbientOcclusionEffect.cpp b/interface/src/renderer/AmbientOcclusionEffect.cpp index 08ad6703e6..c5aa193024 100644 --- a/interface/src/renderer/AmbientOcclusionEffect.cpp +++ b/interface/src/renderer/AmbientOcclusionEffect.cpp @@ -24,6 +24,7 @@ #include "RenderUtil.h" #include "AmbientOcclusionEffect.h" +#include "renderer/GlowEffect.h" const int ROTATION_WIDTH = 4; const int ROTATION_HEIGHT = 4; @@ -105,7 +106,7 @@ void AmbientOcclusionEffect::render() { glBindTexture(GL_TEXTURE_2D, _rotationTextureID); // render with the occlusion shader to the secondary/tertiary buffer - QOpenGLFramebufferObject* freeFBO = Application::getInstance()->getGlowEffect()->getFreeFramebufferObject(); + QOpenGLFramebufferObject* freeFBO = DependencyManager::get()->getFreeFramebufferObject(); freeFBO->bind(); float left, right, bottom, top, nearVal, farVal; diff --git a/interface/src/renderer/DeferredLightingEffect.cpp b/interface/src/renderer/DeferredLightingEffect.cpp index 79b89d03f9..b365307a44 100644 --- a/interface/src/renderer/DeferredLightingEffect.cpp +++ b/interface/src/renderer/DeferredLightingEffect.cpp @@ -19,6 +19,7 @@ #include "Application.h" #include "DeferredLightingEffect.h" #include "RenderUtil.h" +#include "renderer/GlowEffect.h" void DeferredLightingEffect::init() { _simpleProgram.addShaderFromSourceFile(QGLShader::Vertex, PathUtils::resourcesPath() + "shaders/simple.vert"); @@ -41,7 +42,7 @@ void DeferredLightingEffect::init() { void DeferredLightingEffect::bindSimpleProgram() { DependencyManager::get()->setPrimaryDrawBuffers(true, true, true); _simpleProgram.bind(); - _simpleProgram.setUniformValue(_glowIntensityLocation, Application::getInstance()->getGlowEffect()->getIntensity()); + _simpleProgram.setUniformValue(_glowIntensityLocation, DependencyManager::get()->getIntensity()); glDisable(GL_BLEND); } @@ -146,7 +147,7 @@ void DeferredLightingEffect::render() { QOpenGLFramebufferObject* primaryFBO = textureCache->getPrimaryFramebufferObject(); primaryFBO->release(); - QOpenGLFramebufferObject* freeFBO = Application::getInstance()->getGlowEffect()->getFreeFramebufferObject(); + QOpenGLFramebufferObject* freeFBO = DependencyManager::get()->getFreeFramebufferObject(); freeFBO->bind(); glClear(GL_COLOR_BUFFER_BIT); diff --git a/interface/src/renderer/GlowEffect.cpp b/interface/src/renderer/GlowEffect.cpp index a53c9f878b..4ec0a994b7 100644 --- a/interface/src/renderer/GlowEffect.cpp +++ b/interface/src/renderer/GlowEffect.cpp @@ -13,6 +13,7 @@ #include "InterfaceConfig.h" #include +#include #include #include @@ -58,7 +59,7 @@ static ProgramObject* createProgram(const QString& name) { return program; } -void GlowEffect::init() { +void GlowEffect::init(QGLWidget* widget) { if (_initialized) { qDebug("[ERROR] GlowEffeect is already initialized."); return; @@ -86,8 +87,18 @@ void GlowEffect::init() { _diffusionScaleLocation = _diffuseProgram->uniformLocation("diffusionScale"); _initialized = true; + _widget = widget; } +int GlowEffect::getDeviceWidth() const { + return _widget->width() * (_widget->windowHandle() ? _widget->windowHandle()->devicePixelRatio() : 1.0f); +} + +int GlowEffect::getDeviceHeight() const { + return _widget->height() * (_widget->windowHandle() ? _widget->windowHandle()->devicePixelRatio() : 1.0f); +} + + void GlowEffect::prepare() { DependencyManager::get()->getPrimaryFramebufferObject()->bind(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -148,8 +159,7 @@ QOpenGLFramebufferObject* GlowEffect::render(bool toTexture) { } else { maybeBind(destFBO); if (!destFBO) { - glViewport(0, 0, Application::getInstance()->getGLWidget()->getDeviceWidth(), - Application::getInstance()->getGLWidget()->getDeviceHeight()); + glViewport(0, 0, getDeviceWidth(), getDeviceHeight()); } glEnable(GL_TEXTURE_2D); glDisable(GL_LIGHTING); @@ -196,9 +206,7 @@ QOpenGLFramebufferObject* GlowEffect::render(bool toTexture) { } maybeBind(destFBO); if (!destFBO) { - glViewport(0, 0, - Application::getInstance()->getGLWidget()->getDeviceWidth(), - Application::getInstance()->getGLWidget()->getDeviceHeight()); + glViewport(0, 0, getDeviceWidth(), getDeviceHeight()); } _addSeparateProgram->bind(); renderFullscreenQuad(); @@ -226,10 +234,10 @@ QOpenGLFramebufferObject* GlowEffect::render(bool toTexture) { } Glower::Glower(float amount) { - Application::getInstance()->getGlowEffect()->begin(amount); + DependencyManager::get()->begin(amount); } Glower::~Glower() { - Application::getInstance()->getGlowEffect()->end(); + DependencyManager::get()->end(); } diff --git a/interface/src/renderer/GlowEffect.h b/interface/src/renderer/GlowEffect.h index f02774accc..42863019f3 100644 --- a/interface/src/renderer/GlowEffect.h +++ b/interface/src/renderer/GlowEffect.h @@ -15,23 +15,23 @@ #include #include +#include + class QOpenGLFramebufferObject; class ProgramObject; /// A generic full screen glow effect. -class GlowEffect : public QObject { +class GlowEffect : public QObject, public DependencyManager::Dependency { Q_OBJECT public: - GlowEffect(); - ~GlowEffect(); - + /// Returns a pointer to the framebuffer object that the glow effect is *not* using for persistent state /// (either the secondary or the tertiary). QOpenGLFramebufferObject* getFreeFramebufferObject() const; - void init(); + void init(QGLWidget* widget); /// Prepares the glow effect for rendering the current frame. To be called before rendering the scene. void prepare(); @@ -52,6 +52,12 @@ public: QOpenGLFramebufferObject* render(bool toTexture = false); private: + GlowEffect(); + virtual ~GlowEffect(); + friend class DependencyManager; + + int getDeviceWidth() const; + int getDeviceHeight() const; bool _initialized; @@ -69,6 +75,7 @@ private: float _intensity; QStack _intensityStack; + QGLWidget* _widget; }; /// RAII-style glow handler. Applies glow when in scope. diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 71f0fb24f3..3e1784b680 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -33,6 +33,8 @@ #define GLBATCH( call ) batch._##call //#define GLBATCH( call ) call +#include "renderer/GlowEffect.h" + using namespace std; static int modelPointerTypeId = qRegisterMetaType >(); @@ -2327,6 +2329,7 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod bool dontReduceMaterialSwitches = Menu::getInstance()->isOptionChecked(MenuOption::DontReduceMaterialSwitches); TextureCache* textureCache = DependencyManager::get(); + GlowEffect* glowEffect = DependencyManager::get(); QString lastMaterialID; int meshPartsRendered = 0; updateVisibleJointStates(); @@ -2431,7 +2434,7 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod glm::vec4 diffuse = glm::vec4(part.diffuseColor, part.opacity); if (!(translucent && alphaThreshold == 0.0f)) { - GLBATCH(glAlphaFunc)(GL_EQUAL, diffuse.a = Application::getInstance()->getGlowEffect()->getIntensity()); + GLBATCH(glAlphaFunc)(GL_EQUAL, diffuse.a = glowEffect->getIntensity()); } glm::vec4 specular = glm::vec4(part.specularColor, 1.0f); GLBATCH(glMaterialfv)(GL_FRONT, GL_AMBIENT, (const float*)&diffuse); diff --git a/interface/src/ui/overlays/LocalModelsOverlay.cpp b/interface/src/ui/overlays/LocalModelsOverlay.cpp index d8555c85ba..d2af86e43b 100644 --- a/interface/src/ui/overlays/LocalModelsOverlay.cpp +++ b/interface/src/ui/overlays/LocalModelsOverlay.cpp @@ -12,6 +12,7 @@ #include "Application.h" #include "LocalModelsOverlay.h" +#include "renderer/GlowEffect.h" LocalModelsOverlay::LocalModelsOverlay(EntityTreeRenderer* entityTreeRenderer) : Volume3DOverlay(), diff --git a/interface/src/ui/overlays/LocalVoxelsOverlay.cpp b/interface/src/ui/overlays/LocalVoxelsOverlay.cpp index 9cb3df8bf3..b49320c087 100644 --- a/interface/src/ui/overlays/LocalVoxelsOverlay.cpp +++ b/interface/src/ui/overlays/LocalVoxelsOverlay.cpp @@ -18,6 +18,7 @@ #include #include "LocalVoxelsOverlay.h" +#include "renderer/GlowEffect.h" #include "voxels/VoxelSystem.h" QMap LocalVoxelsOverlay::_voxelSystemMap; diff --git a/interface/src/ui/overlays/ModelOverlay.cpp b/interface/src/ui/overlays/ModelOverlay.cpp index ecce137f4d..58fe0ec899 100644 --- a/interface/src/ui/overlays/ModelOverlay.cpp +++ b/interface/src/ui/overlays/ModelOverlay.cpp @@ -11,6 +11,7 @@ #include "../../Menu.h" #include "ModelOverlay.h" +#include "renderer/GlowEffect.h" ModelOverlay::ModelOverlay() : _model(), diff --git a/interface/src/voxels/VoxelFade.cpp b/interface/src/voxels/VoxelFade.cpp index c720717d7c..918cafe9c6 100644 --- a/interface/src/voxels/VoxelFade.cpp +++ b/interface/src/voxels/VoxelFade.cpp @@ -15,6 +15,7 @@ #include "Application.h" #include "VoxelFade.h" +#include "renderer/GlowEffect.h" const float VoxelFade::FADE_OUT_START = 0.5f; const float VoxelFade::FADE_OUT_END = 0.05f; @@ -36,7 +37,7 @@ VoxelFade::VoxelFade(FadeDirection direction, float red, float green, float blue } void VoxelFade::render() { - Application::getInstance()->getGlowEffect()->begin(); + DependencyManager::get()->begin(); glDisable(GL_LIGHTING); glPushMatrix(); @@ -52,7 +53,7 @@ void VoxelFade::render() { glEnable(GL_LIGHTING); - Application::getInstance()->getGlowEffect()->end(); + DependencyManager::get()->end(); opacity *= (direction == FADE_OUT) ? FADE_OUT_STEP : FADE_IN_STEP; } From 37abe8e89c48e7ffdfb23402721accedbe89e671 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 15 Dec 2014 17:35:26 -0800 Subject: [PATCH 431/502] move RenderUtils.cpp/h to libraries --- interface/src/renderer/AmbientOcclusionEffect.cpp | 2 +- interface/src/renderer/DeferredLightingEffect.cpp | 2 +- interface/src/renderer/GlowEffect.cpp | 5 +++-- .../renderer => libraries/render-utils/src}/RenderUtil.cpp | 2 +- .../src/renderer => libraries/render-utils/src}/RenderUtil.h | 0 5 files changed, 6 insertions(+), 5 deletions(-) rename {interface/src/renderer => libraries/render-utils/src}/RenderUtil.cpp (95%) rename {interface/src/renderer => libraries/render-utils/src}/RenderUtil.h (100%) diff --git a/interface/src/renderer/AmbientOcclusionEffect.cpp b/interface/src/renderer/AmbientOcclusionEffect.cpp index c5aa193024..9c89eae75e 100644 --- a/interface/src/renderer/AmbientOcclusionEffect.cpp +++ b/interface/src/renderer/AmbientOcclusionEffect.cpp @@ -18,10 +18,10 @@ #include #include +#include #include #include "Application.h" -#include "RenderUtil.h" #include "AmbientOcclusionEffect.h" #include "renderer/GlowEffect.h" diff --git a/interface/src/renderer/DeferredLightingEffect.cpp b/interface/src/renderer/DeferredLightingEffect.cpp index b365307a44..ae0743e2a6 100644 --- a/interface/src/renderer/DeferredLightingEffect.cpp +++ b/interface/src/renderer/DeferredLightingEffect.cpp @@ -15,10 +15,10 @@ #include #include +#include #include "Application.h" #include "DeferredLightingEffect.h" -#include "RenderUtil.h" #include "renderer/GlowEffect.h" void DeferredLightingEffect::init() { diff --git a/interface/src/renderer/GlowEffect.cpp b/interface/src/renderer/GlowEffect.cpp index 4ec0a994b7..ee5642e654 100644 --- a/interface/src/renderer/GlowEffect.cpp +++ b/interface/src/renderer/GlowEffect.cpp @@ -18,10 +18,11 @@ #include #include #include +#include +#include -#include "Application.h" +#include "Menu.h" #include "GlowEffect.h" -#include "RenderUtil.h" GlowEffect::GlowEffect() : _initialized(false), diff --git a/interface/src/renderer/RenderUtil.cpp b/libraries/render-utils/src/RenderUtil.cpp similarity index 95% rename from interface/src/renderer/RenderUtil.cpp rename to libraries/render-utils/src/RenderUtil.cpp index c2f05d373e..d70c972c87 100644 --- a/interface/src/renderer/RenderUtil.cpp +++ b/libraries/render-utils/src/RenderUtil.cpp @@ -9,7 +9,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "InterfaceConfig.h" +#include #include "RenderUtil.h" void renderFullscreenQuad(float sMin, float sMax, float tMin, float tMax) { diff --git a/interface/src/renderer/RenderUtil.h b/libraries/render-utils/src/RenderUtil.h similarity index 100% rename from interface/src/renderer/RenderUtil.h rename to libraries/render-utils/src/RenderUtil.h From e52338d25c0cb9b9e046d106895026cf708f45f5 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 15 Dec 2014 17:38:57 -0800 Subject: [PATCH 432/502] get rid of InterfaceConfig.h in GlowEffect --- interface/src/renderer/GlowEffect.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/renderer/GlowEffect.cpp b/interface/src/renderer/GlowEffect.cpp index ee5642e654..7ad553decf 100644 --- a/interface/src/renderer/GlowEffect.cpp +++ b/interface/src/renderer/GlowEffect.cpp @@ -10,7 +10,7 @@ // // include this before QOpenGLFramebufferObject, which includes an earlier version of OpenGL -#include "InterfaceConfig.h" +#include #include #include From 4eef4c2438ec0018b3fc01fdecaff248ac359089 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 15 Dec 2014 18:52:40 -0800 Subject: [PATCH 433/502] move RenderUtils.cpp/h to libraries --- interface/src/MetavoxelSystem.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/interface/src/MetavoxelSystem.cpp b/interface/src/MetavoxelSystem.cpp index 372c5214f7..824f1e3313 100644 --- a/interface/src/MetavoxelSystem.cpp +++ b/interface/src/MetavoxelSystem.cpp @@ -32,7 +32,6 @@ #include "Application.h" #include "MetavoxelSystem.h" #include "renderer/Model.h" -#include "renderer/RenderUtil.h" REGISTER_META_OBJECT(DefaultMetavoxelRendererImplementation) REGISTER_META_OBJECT(SphereRenderer) From 8f3d23c5b32208581b8067ed34435b2fe214d969 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 15 Dec 2014 19:06:54 -0800 Subject: [PATCH 434/502] remove Menu dependency from GlowEffect --- interface/src/Application.cpp | 2 +- interface/src/Menu.cpp | 4 +++- interface/src/renderer/GlowEffect.cpp | 14 ++++++++++---- interface/src/renderer/GlowEffect.h | 6 +++++- 4 files changed, 19 insertions(+), 7 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 4bc4b0d339..834587a26a 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2039,7 +2039,7 @@ void Application::init() { DependencyManager::get()->associateWithWidget(getGLWidget()); // initialize the GlowEffect with our widget - DependencyManager::get()->init(getGLWidget()); + DependencyManager::get()->init(getGLWidget(), Menu::getInstance()->isOptionChecked(MenuOption::EnableGlowEffect)); } void Application::closeMirrorView() { diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index fbb23504b0..55a1254e3f 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -54,6 +54,7 @@ #include "ui/ModelsBrowser.h" #include "ui/LoginDialog.h" #include "ui/NodeBounds.h" +#include "renderer/GlowEffect.h" Menu* Menu::_instance = NULL; @@ -425,7 +426,8 @@ Menu::Menu() : true, appInstance, SLOT(setRenderVoxels(bool))); - addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::EnableGlowEffect, 0, true); + addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::EnableGlowEffect, 0, true, + DependencyManager::get(), SLOT(toggleGlowEffect(bool))); addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Wireframe, Qt::ALT | Qt::Key_W, false); addActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::LodTools, Qt::SHIFT | Qt::Key_L, this, SLOT(lodTools())); diff --git a/interface/src/renderer/GlowEffect.cpp b/interface/src/renderer/GlowEffect.cpp index 7ad553decf..13513c140b 100644 --- a/interface/src/renderer/GlowEffect.cpp +++ b/interface/src/renderer/GlowEffect.cpp @@ -21,14 +21,15 @@ #include #include -#include "Menu.h" #include "GlowEffect.h" GlowEffect::GlowEffect() : _initialized(false), _isOddFrame(false), _isFirstFrame(true), - _intensity(0.0f) { + _intensity(0.0f), + _widget(NULL), + _enabled(false) { } GlowEffect::~GlowEffect() { @@ -60,7 +61,7 @@ static ProgramObject* createProgram(const QString& name) { return program; } -void GlowEffect::init(QGLWidget* widget) { +void GlowEffect::init(QGLWidget* widget, bool enabled) { if (_initialized) { qDebug("[ERROR] GlowEffeect is already initialized."); return; @@ -89,6 +90,7 @@ void GlowEffect::init(QGLWidget* widget) { _initialized = true; _widget = widget; + _enabled = enabled; } int GlowEffect::getDeviceWidth() const { @@ -153,7 +155,7 @@ QOpenGLFramebufferObject* GlowEffect::render(bool toTexture) { QOpenGLFramebufferObject* destFBO = toTexture ? textureCache->getSecondaryFramebufferObject() : NULL; - if (!Menu::getInstance()->isOptionChecked(MenuOption::EnableGlowEffect) || _isEmpty) { + if (!_enabled || _isEmpty) { // copy the primary to the screen if (destFBO && QOpenGLFramebufferObject::hasOpenGLFramebufferBlit()) { QOpenGLFramebufferObject::blitFramebuffer(destFBO, primaryFBO); @@ -234,6 +236,10 @@ QOpenGLFramebufferObject* GlowEffect::render(bool toTexture) { return destFBO; } +void GlowEffect::toggleGlowEffect(bool enabled) { + _enabled = enabled; +} + Glower::Glower(float amount) { DependencyManager::get()->begin(amount); } diff --git a/interface/src/renderer/GlowEffect.h b/interface/src/renderer/GlowEffect.h index 42863019f3..d27f32c244 100644 --- a/interface/src/renderer/GlowEffect.h +++ b/interface/src/renderer/GlowEffect.h @@ -31,7 +31,7 @@ public: /// (either the secondary or the tertiary). QOpenGLFramebufferObject* getFreeFramebufferObject() const; - void init(QGLWidget* widget); + void init(QGLWidget* widget, bool enabled); /// Prepares the glow effect for rendering the current frame. To be called before rendering the scene. void prepare(); @@ -51,6 +51,9 @@ public: /// \return the framebuffer object to which we rendered, or NULL if to the frame buffer QOpenGLFramebufferObject* render(bool toTexture = false); +public slots: + void toggleGlowEffect(bool enabled); + private: GlowEffect(); virtual ~GlowEffect(); @@ -76,6 +79,7 @@ private: float _intensity; QStack _intensityStack; QGLWidget* _widget; + bool _enabled; }; /// RAII-style glow handler. Applies glow when in scope. From 41c135c4e5618cefc74ddc97382166d1a9123d99 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 15 Dec 2014 19:19:21 -0800 Subject: [PATCH 435/502] move GlowEffect to libraries --- interface/src/Application.cpp | 2 +- interface/src/Menu.cpp | 3 +-- interface/src/avatar/Avatar.cpp | 2 +- interface/src/avatar/AvatarManager.cpp | 2 +- interface/src/avatar/Head.cpp | 6 +++--- interface/src/devices/OculusManager.cpp | 2 +- interface/src/devices/TV3DManager.cpp | 3 ++- interface/src/entities/EntityTreeRenderer.cpp | 5 +---- interface/src/renderer/AmbientOcclusionEffect.cpp | 2 +- interface/src/renderer/DeferredLightingEffect.cpp | 2 +- interface/src/renderer/Model.cpp | 3 +-- interface/src/ui/overlays/Circle3DOverlay.cpp | 2 +- interface/src/ui/overlays/Cube3DOverlay.cpp | 3 ++- interface/src/ui/overlays/Line3DOverlay.cpp | 3 ++- interface/src/ui/overlays/LocalModelsOverlay.cpp | 3 ++- interface/src/ui/overlays/LocalVoxelsOverlay.cpp | 4 ++-- interface/src/ui/overlays/ModelOverlay.cpp | 4 +++- interface/src/ui/overlays/Rectangle3DOverlay.cpp | 3 ++- interface/src/ui/overlays/Sphere3DOverlay.cpp | 3 ++- interface/src/voxels/VoxelFade.cpp | 2 +- .../render-utils/src}/GlowEffect.cpp | 8 +++++--- .../renderer => libraries/render-utils/src}/GlowEffect.h | 1 + 22 files changed, 37 insertions(+), 31 deletions(-) rename {interface/src/renderer => libraries/render-utils/src}/GlowEffect.cpp (98%) rename {interface/src/renderer => libraries/render-utils/src}/GlowEffect.h (99%) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 834587a26a..f3ac53c33b 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -57,6 +57,7 @@ #include #include #include +#include #include #include #include @@ -90,7 +91,6 @@ #include "gpu/Batch.h" #include "gpu/GLBackend.h" -#include "renderer/GlowEffect.h" #include "scripting/AccountScriptingInterface.h" #include "scripting/AudioDeviceScriptingInterface.h" diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 55a1254e3f..80fdec5202 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -54,8 +55,6 @@ #include "ui/ModelsBrowser.h" #include "ui/LoginDialog.h" #include "ui/NodeBounds.h" -#include "renderer/GlowEffect.h" - Menu* Menu::_instance = NULL; diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 83de09c4f5..4b7c5dfdf3 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -40,7 +41,6 @@ #include "Recorder.h" #include "world.h" #include "devices/OculusManager.h" -#include "renderer/GlowEffect.h" #include "ui/TextRenderer.h" using namespace std; diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 2de272bb29..8c13dd3c54 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -15,6 +15,7 @@ #include +#include #include #include #include @@ -25,7 +26,6 @@ #include "Menu.h" #include "MyAvatar.h" -#include "renderer/GlowEffect.h" // We add _myAvatar into the hash with all the other AvatarData, and we use the default NULL QUid as the key. const QUuid MY_AVATAR_KEY; // NULL key diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index fb20ccdbde..5d84c2d939 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -11,8 +11,7 @@ #include #include -#include -#include +#include #include #include "Application.h" @@ -21,8 +20,9 @@ #include "Head.h" #include "Menu.h" #include "Util.h" +#include "devices/DdeFaceTracker.h" +#include "devices/Faceshift.h" #include "devices/OculusManager.h" -#include "renderer/GlowEffect.h" using namespace std; diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index b000d6436b..96615112dd 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -21,12 +21,12 @@ #include +#include #include #include #include #include "Application.h" -#include "renderer/GlowEffect.h" #ifdef HAVE_LIBOVR diff --git a/interface/src/devices/TV3DManager.cpp b/interface/src/devices/TV3DManager.cpp index b756ccf41e..f665765d70 100644 --- a/interface/src/devices/TV3DManager.cpp +++ b/interface/src/devices/TV3DManager.cpp @@ -15,11 +15,12 @@ #include +#include + #include "Application.h" #include "TV3DManager.h" #include "Menu.h" -#include "renderer/GlowEffect.h" int TV3DManager::_screenWidth = 1; int TV3DManager::_screenHeight = 1; diff --git a/interface/src/entities/EntityTreeRenderer.cpp b/interface/src/entities/EntityTreeRenderer.cpp index aca111e731..59b3f697c8 100644 --- a/interface/src/entities/EntityTreeRenderer.cpp +++ b/interface/src/entities/EntityTreeRenderer.cpp @@ -18,6 +18,7 @@ #include "InterfaceConfig.h" #include +#include #include #include #include @@ -36,15 +37,11 @@ #include "RenderableSphereEntityItem.h" #include "RenderableTextEntityItem.h" -#include "renderer/GlowEffect.h" - QThread* EntityTreeRenderer::getMainThread() { return Application::getInstance()->getEntities()->thread(); } - - EntityTreeRenderer::EntityTreeRenderer(bool wantScripts) : OctreeRenderer(), _wantScripts(wantScripts), diff --git a/interface/src/renderer/AmbientOcclusionEffect.cpp b/interface/src/renderer/AmbientOcclusionEffect.cpp index 9c89eae75e..bcae662085 100644 --- a/interface/src/renderer/AmbientOcclusionEffect.cpp +++ b/interface/src/renderer/AmbientOcclusionEffect.cpp @@ -16,6 +16,7 @@ #include +#include #include #include #include @@ -24,7 +25,6 @@ #include "Application.h" #include "AmbientOcclusionEffect.h" -#include "renderer/GlowEffect.h" const int ROTATION_WIDTH = 4; const int ROTATION_HEIGHT = 4; diff --git a/interface/src/renderer/DeferredLightingEffect.cpp b/interface/src/renderer/DeferredLightingEffect.cpp index ae0743e2a6..18a93aa042 100644 --- a/interface/src/renderer/DeferredLightingEffect.cpp +++ b/interface/src/renderer/DeferredLightingEffect.cpp @@ -14,12 +14,12 @@ #include +#include #include #include #include "Application.h" #include "DeferredLightingEffect.h" -#include "renderer/GlowEffect.h" void DeferredLightingEffect::init() { _simpleProgram.addShaderFromSourceFile(QGLShader::Vertex, PathUtils::resourcesPath() + "shaders/simple.vert"); diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 3e1784b680..877f43a563 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -33,8 +34,6 @@ #define GLBATCH( call ) batch._##call //#define GLBATCH( call ) call -#include "renderer/GlowEffect.h" - using namespace std; static int modelPointerTypeId = qRegisterMetaType >(); diff --git a/interface/src/ui/overlays/Circle3DOverlay.cpp b/interface/src/ui/overlays/Circle3DOverlay.cpp index 68d589d20b..32ae7f0a07 100644 --- a/interface/src/ui/overlays/Circle3DOverlay.cpp +++ b/interface/src/ui/overlays/Circle3DOverlay.cpp @@ -12,11 +12,11 @@ #include "InterfaceConfig.h" #include +#include #include #include #include "Circle3DOverlay.h" -#include "renderer/GlowEffect.h" Circle3DOverlay::Circle3DOverlay() : _startAt(0.0f), diff --git a/interface/src/ui/overlays/Cube3DOverlay.cpp b/interface/src/ui/overlays/Cube3DOverlay.cpp index 8e37dedd77..f518c309a1 100644 --- a/interface/src/ui/overlays/Cube3DOverlay.cpp +++ b/interface/src/ui/overlays/Cube3DOverlay.cpp @@ -12,12 +12,13 @@ #include "InterfaceConfig.h" #include + +#include #include #include #include "Application.h" #include "Cube3DOverlay.h" -#include "renderer/GlowEffect.h" Cube3DOverlay::Cube3DOverlay() : _borderSize(0) { } diff --git a/interface/src/ui/overlays/Line3DOverlay.cpp b/interface/src/ui/overlays/Line3DOverlay.cpp index ae67bf9d92..4facd779de 100644 --- a/interface/src/ui/overlays/Line3DOverlay.cpp +++ b/interface/src/ui/overlays/Line3DOverlay.cpp @@ -11,8 +11,9 @@ // include this before QGLWidget, which includes an earlier version of OpenGL #include "InterfaceConfig.h" +#include + #include "Line3DOverlay.h" -#include "renderer/GlowEffect.h" Line3DOverlay::Line3DOverlay() { diff --git a/interface/src/ui/overlays/LocalModelsOverlay.cpp b/interface/src/ui/overlays/LocalModelsOverlay.cpp index d2af86e43b..e6fae4ff3d 100644 --- a/interface/src/ui/overlays/LocalModelsOverlay.cpp +++ b/interface/src/ui/overlays/LocalModelsOverlay.cpp @@ -9,10 +9,11 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include + #include "Application.h" #include "LocalModelsOverlay.h" -#include "renderer/GlowEffect.h" LocalModelsOverlay::LocalModelsOverlay(EntityTreeRenderer* entityTreeRenderer) : Volume3DOverlay(), diff --git a/interface/src/ui/overlays/LocalVoxelsOverlay.cpp b/interface/src/ui/overlays/LocalVoxelsOverlay.cpp index b49320c087..b3dac02468 100644 --- a/interface/src/ui/overlays/LocalVoxelsOverlay.cpp +++ b/interface/src/ui/overlays/LocalVoxelsOverlay.cpp @@ -15,10 +15,10 @@ #include #include -#include +#include +#include "Application.h" #include "LocalVoxelsOverlay.h" -#include "renderer/GlowEffect.h" #include "voxels/VoxelSystem.h" QMap LocalVoxelsOverlay::_voxelSystemMap; diff --git a/interface/src/ui/overlays/ModelOverlay.cpp b/interface/src/ui/overlays/ModelOverlay.cpp index 58fe0ec899..58d42598f2 100644 --- a/interface/src/ui/overlays/ModelOverlay.cpp +++ b/interface/src/ui/overlays/ModelOverlay.cpp @@ -8,10 +8,12 @@ // 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 "../../Menu.h" #include "ModelOverlay.h" -#include "renderer/GlowEffect.h" ModelOverlay::ModelOverlay() : _model(), diff --git a/interface/src/ui/overlays/Rectangle3DOverlay.cpp b/interface/src/ui/overlays/Rectangle3DOverlay.cpp index bcca759cd4..8e8c17743d 100644 --- a/interface/src/ui/overlays/Rectangle3DOverlay.cpp +++ b/interface/src/ui/overlays/Rectangle3DOverlay.cpp @@ -12,10 +12,11 @@ #include "InterfaceConfig.h" #include + +#include #include #include "Rectangle3DOverlay.h" -#include "renderer/GlowEffect.h" Rectangle3DOverlay::Rectangle3DOverlay() { } diff --git a/interface/src/ui/overlays/Sphere3DOverlay.cpp b/interface/src/ui/overlays/Sphere3DOverlay.cpp index ded1b3917c..eb95672399 100644 --- a/interface/src/ui/overlays/Sphere3DOverlay.cpp +++ b/interface/src/ui/overlays/Sphere3DOverlay.cpp @@ -12,11 +12,12 @@ #include "InterfaceConfig.h" #include + +#include #include #include "Sphere3DOverlay.h" #include "Application.h" -#include "renderer/GlowEffect.h" Sphere3DOverlay::Sphere3DOverlay() { } diff --git a/interface/src/voxels/VoxelFade.cpp b/interface/src/voxels/VoxelFade.cpp index 918cafe9c6..367090291c 100644 --- a/interface/src/voxels/VoxelFade.cpp +++ b/interface/src/voxels/VoxelFade.cpp @@ -11,11 +11,11 @@ #include "InterfaceConfig.h" +#include #include #include "Application.h" #include "VoxelFade.h" -#include "renderer/GlowEffect.h" const float VoxelFade::FADE_OUT_START = 0.5f; const float VoxelFade::FADE_OUT_END = 0.05f; diff --git a/interface/src/renderer/GlowEffect.cpp b/libraries/render-utils/src/GlowEffect.cpp similarity index 98% rename from interface/src/renderer/GlowEffect.cpp rename to libraries/render-utils/src/GlowEffect.cpp index 13513c140b..174436d155 100644 --- a/interface/src/renderer/GlowEffect.cpp +++ b/libraries/render-utils/src/GlowEffect.cpp @@ -12,16 +12,18 @@ // include this before QOpenGLFramebufferObject, which includes an earlier version of OpenGL #include +#include #include #include #include #include -#include -#include -#include #include "GlowEffect.h" +#include "ProgramObject.h" +#include "RenderUtil.h" +#include "TextureCache.h" + GlowEffect::GlowEffect() : _initialized(false), diff --git a/interface/src/renderer/GlowEffect.h b/libraries/render-utils/src/GlowEffect.h similarity index 99% rename from interface/src/renderer/GlowEffect.h rename to libraries/render-utils/src/GlowEffect.h index d27f32c244..3ad1577d14 100644 --- a/interface/src/renderer/GlowEffect.h +++ b/libraries/render-utils/src/GlowEffect.h @@ -13,6 +13,7 @@ #define hifi_GlowEffect_h #include +#include #include #include From fac6ff572ba3da1d53b39f2858be1c5153e3e8e7 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 15 Dec 2014 19:29:53 -0800 Subject: [PATCH 436/502] see if this works --- libraries/render-utils/src/GlowEffect.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libraries/render-utils/src/GlowEffect.h b/libraries/render-utils/src/GlowEffect.h index 3ad1577d14..cc3e6e5867 100644 --- a/libraries/render-utils/src/GlowEffect.h +++ b/libraries/render-utils/src/GlowEffect.h @@ -12,6 +12,8 @@ #ifndef hifi_GlowEffect_h #define hifi_GlowEffect_h +#include + #include #include #include From 02737a4ec402f8b97e07a08fca86b15c978996a0 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 15 Dec 2014 19:38:30 -0800 Subject: [PATCH 437/502] move JointState to libraries --- interface/src/avatar/SkeletonRagdoll.h | 3 +- interface/src/renderer/Model.h | 2 +- libraries/render-utils/src/JointState.cpp | 281 ++++++++++++++++++++++ libraries/render-utils/src/JointState.h | 129 ++++++++++ 4 files changed, 412 insertions(+), 3 deletions(-) create mode 100644 libraries/render-utils/src/JointState.cpp create mode 100644 libraries/render-utils/src/JointState.h diff --git a/interface/src/avatar/SkeletonRagdoll.h b/interface/src/avatar/SkeletonRagdoll.h index ae9bec9116..2f8ce1f712 100644 --- a/interface/src/avatar/SkeletonRagdoll.h +++ b/interface/src/avatar/SkeletonRagdoll.h @@ -14,10 +14,9 @@ #include +#include #include -#include "../renderer/JointState.h" - class MuscleConstraint; class Model; diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index c79a6c2efd..8000e7385b 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -23,13 +23,13 @@ #include #include #include +#include #include #include #include #include #include "AnimationHandle.h" -#include "JointState.h" class QScriptEngine; diff --git a/libraries/render-utils/src/JointState.cpp b/libraries/render-utils/src/JointState.cpp new file mode 100644 index 0000000000..96561758da --- /dev/null +++ b/libraries/render-utils/src/JointState.cpp @@ -0,0 +1,281 @@ +// +// JointState.cpp +// interface/src/renderer +// +// Created by Andrzej Kapolka on 10/18/13. +// Copyright 2013 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 "JointState.h" + +JointState::JointState() : + _animationPriority(0.0f), + _transformChanged(true), + _rotationIsValid(false), + _positionInParentFrame(0.0f), + _distanceToParent(0.0f), + _fbxJoint(NULL), + _constraint(NULL) { +} + +JointState::JointState(const JointState& other) : _constraint(NULL) { + _transformChanged = other._transformChanged; + _transform = other._transform; + _rotationIsValid = other._rotationIsValid; + _rotation = other._rotation; + _rotationInConstrainedFrame = other._rotationInConstrainedFrame; + _positionInParentFrame = other._positionInParentFrame; + _distanceToParent = other._distanceToParent; + _animationPriority = other._animationPriority; + _fbxJoint = other._fbxJoint; + // DO NOT copy _constraint +} + +JointState::~JointState() { + delete _constraint; + _constraint = NULL; + if (_constraint) { + delete _constraint; + _constraint = NULL; + } +} + +glm::quat JointState::getRotation() const { + if (!_rotationIsValid) { + const_cast(this)->_rotation = extractRotation(_transform); + const_cast(this)->_rotationIsValid = true; + } + + return _rotation; +} + +void JointState::setFBXJoint(const FBXJoint* joint) { + assert(joint != NULL); + _rotationInConstrainedFrame = joint->rotation; + _transformChanged = true; + _rotationIsValid = false; + + // NOTE: JointState does not own the FBXJoint to which it points. + _fbxJoint = joint; + if (_constraint) { + delete _constraint; + _constraint = NULL; + } +} + +void JointState::buildConstraint() { + if (_constraint) { + delete _constraint; + _constraint = NULL; + } + if (glm::distance2(glm::vec3(-PI), _fbxJoint->rotationMin) > EPSILON || + glm::distance2(glm::vec3(PI), _fbxJoint->rotationMax) > EPSILON ) { + // this joint has rotation constraints + _constraint = AngularConstraint::newAngularConstraint(_fbxJoint->rotationMin, _fbxJoint->rotationMax); + } +} + +void JointState::copyState(const JointState& state) { + _animationPriority = state._animationPriority; + _transformChanged = state._transformChanged; + _transform = state._transform; + _rotationIsValid = state._rotationIsValid; + _rotation = state._rotation; + _rotationInConstrainedFrame = state._rotationInConstrainedFrame; + _positionInParentFrame = state._positionInParentFrame; + _distanceToParent = state._distanceToParent; + + _visibleTransform = state._visibleTransform; + _visibleRotation = extractRotation(_visibleTransform); + _visibleRotationInConstrainedFrame = state._visibleRotationInConstrainedFrame; + // DO NOT copy _fbxJoint or _constraint +} + +void JointState::initTransform(const glm::mat4& parentTransform) { + computeTransform(parentTransform); + _positionInParentFrame = glm::inverse(extractRotation(parentTransform)) * (extractTranslation(_transform) - extractTranslation(parentTransform)); + _distanceToParent = glm::length(_positionInParentFrame); +} + +void JointState::computeTransform(const glm::mat4& parentTransform, bool parentTransformChanged, bool synchronousRotationCompute) { + if (!parentTransformChanged && !_transformChanged) { + return; + } + + glm::quat rotationInParentFrame = _fbxJoint->preRotation * _rotationInConstrainedFrame * _fbxJoint->postRotation; + glm::mat4 transformInParentFrame = _fbxJoint->preTransform * glm::mat4_cast(rotationInParentFrame) * _fbxJoint->postTransform; + glm::mat4 newTransform = parentTransform * glm::translate(_fbxJoint->translation) * transformInParentFrame; + + if (newTransform != _transform) { + _transform = newTransform; + _transformChanged = true; + _rotationIsValid = false; + } +} + +void JointState::computeVisibleTransform(const glm::mat4& parentTransform) { + glm::quat rotationInParentFrame = _fbxJoint->preRotation * _visibleRotationInConstrainedFrame * _fbxJoint->postRotation; + glm::mat4 transformInParentFrame = _fbxJoint->preTransform * glm::mat4_cast(rotationInParentFrame) * _fbxJoint->postTransform; + _visibleTransform = parentTransform * glm::translate(_fbxJoint->translation) * transformInParentFrame; + _visibleRotation = extractRotation(_visibleTransform); +} + +glm::quat JointState::getRotationInBindFrame() const { + return getRotation() * _fbxJoint->inverseBindRotation; +} + +glm::quat JointState::getRotationInParentFrame() const { + return _fbxJoint->preRotation * _rotationInConstrainedFrame * _fbxJoint->postRotation; +} + +glm::quat JointState::getVisibleRotationInParentFrame() const { + return _fbxJoint->preRotation * _visibleRotationInConstrainedFrame * _fbxJoint->postRotation; +} + +void JointState::restoreRotation(float fraction, float priority) { + assert(_fbxJoint != NULL); + if (priority == _animationPriority || _animationPriority == 0.0f) { + setRotationInConstrainedFrameInternal(safeMix(_rotationInConstrainedFrame, _fbxJoint->rotation, fraction)); + _animationPriority = 0.0f; + } +} + +void JointState::setRotationInBindFrame(const glm::quat& rotation, float priority, bool constrain) { + // rotation is from bind- to model-frame + assert(_fbxJoint != NULL); + if (priority >= _animationPriority) { + glm::quat targetRotation = _rotationInConstrainedFrame * glm::inverse(getRotation()) * rotation * glm::inverse(_fbxJoint->inverseBindRotation); + if (constrain && _constraint) { + _constraint->softClamp(targetRotation, _rotationInConstrainedFrame, 0.5f); + } + setRotationInConstrainedFrameInternal(targetRotation); + _animationPriority = priority; + } +} + +void JointState::clearTransformTranslation() { + _transform[3][0] = 0.0f; + _transform[3][1] = 0.0f; + _transform[3][2] = 0.0f; + _transformChanged = true; + _visibleTransform[3][0] = 0.0f; + _visibleTransform[3][1] = 0.0f; + _visibleTransform[3][2] = 0.0f; +} + +void JointState::applyRotationDelta(const glm::quat& delta, bool constrain, float priority) { + // NOTE: delta is in model-frame + assert(_fbxJoint != NULL); + if (priority < _animationPriority || delta.null) { + return; + } + _animationPriority = priority; + glm::quat targetRotation = _rotationInConstrainedFrame * glm::inverse(getRotation()) * delta * getRotation(); + if (!constrain || _constraint == NULL) { + // no constraints + _rotationInConstrainedFrame = targetRotation; + _transformChanged = true; + + _rotation = delta * getRotation(); + return; + } + setRotationInConstrainedFrameInternal(targetRotation); +} + +/// Applies delta rotation to joint but mixes a little bit of the default pose as well. +/// This helps keep an IK solution stable. +void JointState::mixRotationDelta(const glm::quat& delta, float mixFactor, float priority) { + // NOTE: delta is in model-frame + assert(_fbxJoint != NULL); + if (priority < _animationPriority) { + return; + } + _animationPriority = priority; + glm::quat targetRotation = _rotationInConstrainedFrame * glm::inverse(getRotation()) * delta * getRotation(); + if (mixFactor > 0.0f && mixFactor <= 1.0f) { + targetRotation = safeMix(targetRotation, _fbxJoint->rotation, mixFactor); + } + if (_constraint) { + _constraint->softClamp(targetRotation, _rotationInConstrainedFrame, 0.5f); + } + setRotationInConstrainedFrameInternal(targetRotation); +} + +void JointState::mixVisibleRotationDelta(const glm::quat& delta, float mixFactor) { + // NOTE: delta is in model-frame + assert(_fbxJoint != NULL); + glm::quat targetRotation = _visibleRotationInConstrainedFrame * glm::inverse(_visibleRotation) * delta * _visibleRotation; + if (mixFactor > 0.0f && mixFactor <= 1.0f) { + //targetRotation = safeMix(targetRotation, _fbxJoint->rotation, mixFactor); + targetRotation = safeMix(targetRotation, _rotationInConstrainedFrame, mixFactor); + } + setVisibleRotationInConstrainedFrame(targetRotation); +} + +glm::quat JointState::computeParentRotation() const { + // R = Rp * Rpre * r * Rpost + // Rp = R * (Rpre * r * Rpost)^ + return getRotation() * glm::inverse(_fbxJoint->preRotation * _rotationInConstrainedFrame * _fbxJoint->postRotation); +} + +glm::quat JointState::computeVisibleParentRotation() const { + return _visibleRotation * glm::inverse(_fbxJoint->preRotation * _visibleRotationInConstrainedFrame * _fbxJoint->postRotation); +} + +void JointState::setRotationInConstrainedFrame(glm::quat targetRotation, float priority, bool constrain) { + if (priority >= _animationPriority || _animationPriority == 0.0f) { + if (constrain && _constraint) { + _constraint->softClamp(targetRotation, _rotationInConstrainedFrame, 0.5f); + } + setRotationInConstrainedFrameInternal(targetRotation); + _animationPriority = priority; + } +} + +void JointState::setRotationInConstrainedFrameInternal(const glm::quat& targetRotation) { + glm::quat parentRotation = computeParentRotation(); + _rotationInConstrainedFrame = targetRotation; + _transformChanged = true; + // R' = Rp * Rpre * r' * Rpost + _rotation = parentRotation * _fbxJoint->preRotation * _rotationInConstrainedFrame * _fbxJoint->postRotation; +} + +void JointState::setVisibleRotationInConstrainedFrame(const glm::quat& targetRotation) { + glm::quat parentRotation = computeVisibleParentRotation(); + _visibleRotationInConstrainedFrame = targetRotation; + _visibleRotation = parentRotation * _fbxJoint->preRotation * _visibleRotationInConstrainedFrame * _fbxJoint->postRotation; +} + +const bool JointState::rotationIsDefault(const glm::quat& rotation, float tolerance) const { + glm::quat defaultRotation = _fbxJoint->rotation; + return glm::abs(rotation.x - defaultRotation.x) < tolerance && + glm::abs(rotation.y - defaultRotation.y) < tolerance && + glm::abs(rotation.z - defaultRotation.z) < tolerance && + glm::abs(rotation.w - defaultRotation.w) < tolerance; +} + +glm::quat JointState::getDefaultRotationInParentFrame() const { + // NOTE: the result is constant and could be cached in the FBXJoint + return _fbxJoint->preRotation * _fbxJoint->rotation * _fbxJoint->postRotation; +} + +const glm::vec3& JointState::getDefaultTranslationInConstrainedFrame() const { + assert(_fbxJoint != NULL); + return _fbxJoint->translation; +} + +void JointState::slaveVisibleTransform() { + _visibleTransform = _transform; + _visibleRotation = getRotation(); + _visibleRotationInConstrainedFrame = _rotationInConstrainedFrame; +} diff --git a/libraries/render-utils/src/JointState.h b/libraries/render-utils/src/JointState.h new file mode 100644 index 0000000000..b502083463 --- /dev/null +++ b/libraries/render-utils/src/JointState.h @@ -0,0 +1,129 @@ +// +// JointState.h +// interface/src/renderer +// +// Created by Andrzej Kapolka on 10/18/13. +// Copyright 2013 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_JointState_h +#define hifi_JointState_h + +#include +#include +#include + +#include +#include + +const float DEFAULT_PRIORITY = 3.0f; + +class AngularConstraint; + +class JointState { +public: + JointState(); + JointState(const JointState& other); + ~JointState(); + + void setFBXJoint(const FBXJoint* joint); + const FBXJoint& getFBXJoint() const { return *_fbxJoint; } + + void buildConstraint(); + void copyState(const JointState& state); + + void initTransform(const glm::mat4& parentTransform); + // if synchronousRotationCompute is true, then _transform is still computed synchronously, + // but _rotation will be asynchronously extracted + void computeTransform(const glm::mat4& parentTransform, bool parentTransformChanged = true, bool synchronousRotationCompute = false); + + void computeVisibleTransform(const glm::mat4& parentTransform); + const glm::mat4& getVisibleTransform() const { return _visibleTransform; } + glm::quat getVisibleRotation() const { return _visibleRotation; } + glm::vec3 getVisiblePosition() const { return extractTranslation(_visibleTransform); } + + const glm::mat4& getTransform() const { return _transform; } + void resetTransformChanged() { _transformChanged = false; } + bool getTransformChanged() const { return _transformChanged; } + + glm::quat getRotation() const; + glm::vec3 getPosition() const { return extractTranslation(_transform); } + + /// \return rotation from bind to model frame + glm::quat getRotationInBindFrame() const; + + glm::quat getRotationInParentFrame() const; + glm::quat getVisibleRotationInParentFrame() const; + const glm::vec3& getPositionInParentFrame() const { return _positionInParentFrame; } + float getDistanceToParent() const { return _distanceToParent; } + + int getParentIndex() const { return _fbxJoint->parentIndex; } + + /// \param delta is in the model-frame + void applyRotationDelta(const glm::quat& delta, bool constrain = true, float priority = 1.0f); + + /// Applies delta rotation to joint but mixes a little bit of the default pose as well. + /// This helps keep an IK solution stable. + /// \param delta rotation change in model-frame + /// \param mixFactor fraction in range [0,1] of how much default pose to blend in (0 is none, 1 is all) + /// \param priority priority level of this animation blend + void mixRotationDelta(const glm::quat& delta, float mixFactor, float priority = 1.0f); + void mixVisibleRotationDelta(const glm::quat& delta, float mixFactor); + + /// Blends a fraciton of default pose into joint rotation. + /// \param fraction fraction in range [0,1] of how much default pose to blend in (0 is none, 1 is all) + /// \param priority priority level of this animation blend + void restoreRotation(float fraction, float priority); + + /// \param rotation is from bind- to model-frame + /// computes and sets new _rotationInConstrainedFrame + /// NOTE: the JointState's model-frame transform/rotation are NOT updated! + void setRotationInBindFrame(const glm::quat& rotation, float priority, bool constrain = false); + + void setRotationInConstrainedFrame(glm::quat targetRotation, float priority, bool constrain = false); + void setVisibleRotationInConstrainedFrame(const glm::quat& targetRotation); + const glm::quat& getRotationInConstrainedFrame() const { return _rotationInConstrainedFrame; } + const glm::quat& getVisibleRotationInConstrainedFrame() const { return _visibleRotationInConstrainedFrame; } + + const bool rotationIsDefault(const glm::quat& rotation, float tolerance = EPSILON) const; + + glm::quat getDefaultRotationInParentFrame() const; + const glm::vec3& getDefaultTranslationInConstrainedFrame() const; + + + void clearTransformTranslation(); + + void slaveVisibleTransform(); + + float _animationPriority; // the priority of the animation affecting this joint + + /// \return parent model-frame rotation + // (used to keep _rotation consistent when modifying _rotationInWorldFrame directly) + glm::quat computeParentRotation() const; + glm::quat computeVisibleParentRotation() const; + +private: + void setRotationInConstrainedFrameInternal(const glm::quat& targetRotation); + /// debug helper function + void loadBindRotation(); + + bool _transformChanged; + glm::mat4 _transform; // joint- to model-frame + bool _rotationIsValid; + glm::quat _rotation; // joint- to model-frame + glm::quat _rotationInConstrainedFrame; // rotation in frame where angular constraints would be applied + glm::vec3 _positionInParentFrame; // only changes when the Model is scaled + float _distanceToParent; + + glm::mat4 _visibleTransform; + glm::quat _visibleRotation; + glm::quat _visibleRotationInConstrainedFrame; + + const FBXJoint* _fbxJoint; // JointState does NOT own its FBXJoint + AngularConstraint* _constraint; // JointState owns its AngularConstraint +}; + +#endif // hifi_JointState_h From 660bf2720e0ffbd6971e3699ef7fa7efd7293ee0 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 15 Dec 2014 19:48:15 -0800 Subject: [PATCH 438/502] convert AnimationCache to DependencyManager --- .../src/avatars/ScriptableAvatar.cpp | 2 +- interface/src/Application.cpp | 2 +- interface/src/Application.h | 3 --- interface/src/renderer/AnimationHandle.cpp | 4 ++-- libraries/animation/src/AnimationCache.h | 17 +++++++++-------- libraries/entities/src/ModelEntityItem.cpp | 3 +-- libraries/script-engine/src/ScriptEngine.cpp | 3 +-- libraries/script-engine/src/ScriptEngine.h | 2 -- 8 files changed, 15 insertions(+), 21 deletions(-) diff --git a/assignment-client/src/avatars/ScriptableAvatar.cpp b/assignment-client/src/avatars/ScriptableAvatar.cpp index 0f721ac98c..e2f0449216 100644 --- a/assignment-client/src/avatars/ScriptableAvatar.cpp +++ b/assignment-client/src/avatars/ScriptableAvatar.cpp @@ -28,7 +28,7 @@ void ScriptableAvatar::startAnimation(const QString& url, float fps, float prior Q_ARG(float, lastFrame), Q_ARG(const QStringList&, maskedJoints)); return; } - _animation = _scriptEngine->getAnimationCache()->getAnimation(url); + _animation = DependencyManager::get()->getAnimation(url); _animationDetails = AnimationDetails("", QUrl(url), fps, 0, loop, hold, false, firstFrame, lastFrame, true, firstFrame); _maskedJoints = maskedJoints; } diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index f3ac53c33b..5f0f4a700a 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4003,7 +4003,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri scriptEngine->registerGlobalObject("Menu", MenuScriptingInterface::getInstance()); scriptEngine->registerGlobalObject("Settings", SettingsScriptingInterface::getInstance()); scriptEngine->registerGlobalObject("AudioDevice", AudioDeviceScriptingInterface::getInstance()); - scriptEngine->registerGlobalObject("AnimationCache", &_animationCache); + scriptEngine->registerGlobalObject("AnimationCache", DependencyManager::get()); scriptEngine->registerGlobalObject("SoundCache", &SoundCache::getInstance()); scriptEngine->registerGlobalObject("Account", AccountScriptingInterface::getInstance()); scriptEngine->registerGlobalObject("Metavoxels", &_metavoxels); diff --git a/interface/src/Application.h b/interface/src/Application.h index 716d67c661..992d8d31d3 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -249,7 +249,6 @@ public: ToolWindow* getToolWindow() { return _toolWindow ; } - AnimationCache* getAnimationCache() { return &_animationCache; } DeferredLightingEffect* getDeferredLightingEffect() { return &_deferredLightingEffect; } ControllerScriptingInterface* getControllerScriptingInterface() { return &_controllerScriptingInterface; } @@ -566,8 +565,6 @@ private: QSet _keysPressed; - AnimationCache _animationCache; - DeferredLightingEffect _deferredLightingEffect; AmbientOcclusionEffect _ambientOcclusionEffect; diff --git a/interface/src/renderer/AnimationHandle.cpp b/interface/src/renderer/AnimationHandle.cpp index 89c265875b..30edf97a33 100644 --- a/interface/src/renderer/AnimationHandle.cpp +++ b/interface/src/renderer/AnimationHandle.cpp @@ -10,11 +10,11 @@ // #include "AnimationHandle.h" -#include "Application.h" +#include "Model.h" void AnimationHandle::setURL(const QUrl& url) { if (_url != url) { - _animation = Application::getInstance()->getAnimationCache()->getAnimation(_url = url); + _animation = DependencyManager::get()->getAnimation(_url = url); _jointMappings.clear(); } } diff --git a/libraries/animation/src/AnimationCache.h b/libraries/animation/src/AnimationCache.h index 8a9e371cb0..5f3f305461 100644 --- a/libraries/animation/src/AnimationCache.h +++ b/libraries/animation/src/AnimationCache.h @@ -15,30 +15,31 @@ #include #include -#include - +#include #include +#include class Animation; typedef QSharedPointer AnimationPointer; /// Scriptable interface for FBX animation loading. -class AnimationCache : public ResourceCache { +class AnimationCache : public ResourceCache, public DependencyManager::Dependency { Q_OBJECT public: - - AnimationCache(QObject* parent = NULL); - Q_INVOKABLE AnimationPointer getAnimation(const QString& url) { return getAnimation(QUrl(url)); } - Q_INVOKABLE AnimationPointer getAnimation(const QUrl& url); protected: virtual QSharedPointer createResource(const QUrl& url, - const QSharedPointer& fallback, bool delayLoad, const void* extra); + const QSharedPointer& fallback, bool delayLoad, const void* extra); +private: + AnimationCache(QObject* parent = NULL); + virtual ~AnimationCache() { } + friend class DependencyManager; + }; Q_DECLARE_METATYPE(AnimationPointer) diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index b9bf75178f..b14248b3bc 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -285,7 +285,6 @@ void ModelEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBit QMap ModelEntityItem::_loadedAnimations; // TODO: improve cleanup by leveraging the AnimationPointer(s) -AnimationCache ModelEntityItem::_animationCache; // This class/instance will cleanup the animations once unloaded. class EntityAnimationsBookkeeper { @@ -309,7 +308,7 @@ Animation* ModelEntityItem::getAnimation(const QString& url) { // if we don't already have this model then create it and initialize it if (_loadedAnimations.find(url) == _loadedAnimations.end()) { - animation = _animationCache.getAnimation(url); + animation = DependencyManager::get()->getAnimation(url); _loadedAnimations[url] = animation; } else { animation = _loadedAnimations[url]; diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 70c536e116..ec5f2bc0e7 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -94,7 +94,6 @@ ScriptEngine::ScriptEngine(const QString& scriptContents, const QString& fileNam _quatLibrary(), _vec3Library(), _uuidLibrary(), - _animationCache(this), _isUserLoaded(false), _arrayBufferClass(new ArrayBufferClass(this)) { @@ -256,7 +255,7 @@ void ScriptEngine::init() { registerGlobalObject("Quat", &_quatLibrary); registerGlobalObject("Vec3", &_vec3Library); registerGlobalObject("Uuid", &_uuidLibrary); - registerGlobalObject("AnimationCache", &_animationCache); + registerGlobalObject("AnimationCache", DependencyManager::get()); registerGlobalObject("Voxels", &_voxelsScriptingInterface); diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index fd28e98cab..3b074d7c73 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -51,7 +51,6 @@ public: static EntityScriptingInterface* getEntityScriptingInterface() { return &_entityScriptingInterface; } ArrayBufferClass* getArrayBufferClass() { return _arrayBufferClass; } - AnimationCache* getAnimationCache() { return &_animationCache; } /// sets the script contents, will return false if failed, will fail if script is already running bool setScriptContents(const QString& scriptContents, const QString& fileNameString = QString("")); @@ -149,7 +148,6 @@ private: Quat _quatLibrary; Vec3 _vec3Library; ScriptUUID _uuidLibrary; - AnimationCache _animationCache; bool _isUserLoaded; ArrayBufferClass* _arrayBufferClass; From 5cba44fd5b3d52fc2774c410b605388c19a139e0 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 15 Dec 2014 19:49:16 -0800 Subject: [PATCH 439/502] moved JointState --- interface/src/renderer/JointState.cpp | 281 -------------------------- interface/src/renderer/JointState.h | 129 ------------ 2 files changed, 410 deletions(-) delete mode 100644 interface/src/renderer/JointState.cpp delete mode 100644 interface/src/renderer/JointState.h diff --git a/interface/src/renderer/JointState.cpp b/interface/src/renderer/JointState.cpp deleted file mode 100644 index 96561758da..0000000000 --- a/interface/src/renderer/JointState.cpp +++ /dev/null @@ -1,281 +0,0 @@ -// -// JointState.cpp -// interface/src/renderer -// -// Created by Andrzej Kapolka on 10/18/13. -// Copyright 2013 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 "JointState.h" - -JointState::JointState() : - _animationPriority(0.0f), - _transformChanged(true), - _rotationIsValid(false), - _positionInParentFrame(0.0f), - _distanceToParent(0.0f), - _fbxJoint(NULL), - _constraint(NULL) { -} - -JointState::JointState(const JointState& other) : _constraint(NULL) { - _transformChanged = other._transformChanged; - _transform = other._transform; - _rotationIsValid = other._rotationIsValid; - _rotation = other._rotation; - _rotationInConstrainedFrame = other._rotationInConstrainedFrame; - _positionInParentFrame = other._positionInParentFrame; - _distanceToParent = other._distanceToParent; - _animationPriority = other._animationPriority; - _fbxJoint = other._fbxJoint; - // DO NOT copy _constraint -} - -JointState::~JointState() { - delete _constraint; - _constraint = NULL; - if (_constraint) { - delete _constraint; - _constraint = NULL; - } -} - -glm::quat JointState::getRotation() const { - if (!_rotationIsValid) { - const_cast(this)->_rotation = extractRotation(_transform); - const_cast(this)->_rotationIsValid = true; - } - - return _rotation; -} - -void JointState::setFBXJoint(const FBXJoint* joint) { - assert(joint != NULL); - _rotationInConstrainedFrame = joint->rotation; - _transformChanged = true; - _rotationIsValid = false; - - // NOTE: JointState does not own the FBXJoint to which it points. - _fbxJoint = joint; - if (_constraint) { - delete _constraint; - _constraint = NULL; - } -} - -void JointState::buildConstraint() { - if (_constraint) { - delete _constraint; - _constraint = NULL; - } - if (glm::distance2(glm::vec3(-PI), _fbxJoint->rotationMin) > EPSILON || - glm::distance2(glm::vec3(PI), _fbxJoint->rotationMax) > EPSILON ) { - // this joint has rotation constraints - _constraint = AngularConstraint::newAngularConstraint(_fbxJoint->rotationMin, _fbxJoint->rotationMax); - } -} - -void JointState::copyState(const JointState& state) { - _animationPriority = state._animationPriority; - _transformChanged = state._transformChanged; - _transform = state._transform; - _rotationIsValid = state._rotationIsValid; - _rotation = state._rotation; - _rotationInConstrainedFrame = state._rotationInConstrainedFrame; - _positionInParentFrame = state._positionInParentFrame; - _distanceToParent = state._distanceToParent; - - _visibleTransform = state._visibleTransform; - _visibleRotation = extractRotation(_visibleTransform); - _visibleRotationInConstrainedFrame = state._visibleRotationInConstrainedFrame; - // DO NOT copy _fbxJoint or _constraint -} - -void JointState::initTransform(const glm::mat4& parentTransform) { - computeTransform(parentTransform); - _positionInParentFrame = glm::inverse(extractRotation(parentTransform)) * (extractTranslation(_transform) - extractTranslation(parentTransform)); - _distanceToParent = glm::length(_positionInParentFrame); -} - -void JointState::computeTransform(const glm::mat4& parentTransform, bool parentTransformChanged, bool synchronousRotationCompute) { - if (!parentTransformChanged && !_transformChanged) { - return; - } - - glm::quat rotationInParentFrame = _fbxJoint->preRotation * _rotationInConstrainedFrame * _fbxJoint->postRotation; - glm::mat4 transformInParentFrame = _fbxJoint->preTransform * glm::mat4_cast(rotationInParentFrame) * _fbxJoint->postTransform; - glm::mat4 newTransform = parentTransform * glm::translate(_fbxJoint->translation) * transformInParentFrame; - - if (newTransform != _transform) { - _transform = newTransform; - _transformChanged = true; - _rotationIsValid = false; - } -} - -void JointState::computeVisibleTransform(const glm::mat4& parentTransform) { - glm::quat rotationInParentFrame = _fbxJoint->preRotation * _visibleRotationInConstrainedFrame * _fbxJoint->postRotation; - glm::mat4 transformInParentFrame = _fbxJoint->preTransform * glm::mat4_cast(rotationInParentFrame) * _fbxJoint->postTransform; - _visibleTransform = parentTransform * glm::translate(_fbxJoint->translation) * transformInParentFrame; - _visibleRotation = extractRotation(_visibleTransform); -} - -glm::quat JointState::getRotationInBindFrame() const { - return getRotation() * _fbxJoint->inverseBindRotation; -} - -glm::quat JointState::getRotationInParentFrame() const { - return _fbxJoint->preRotation * _rotationInConstrainedFrame * _fbxJoint->postRotation; -} - -glm::quat JointState::getVisibleRotationInParentFrame() const { - return _fbxJoint->preRotation * _visibleRotationInConstrainedFrame * _fbxJoint->postRotation; -} - -void JointState::restoreRotation(float fraction, float priority) { - assert(_fbxJoint != NULL); - if (priority == _animationPriority || _animationPriority == 0.0f) { - setRotationInConstrainedFrameInternal(safeMix(_rotationInConstrainedFrame, _fbxJoint->rotation, fraction)); - _animationPriority = 0.0f; - } -} - -void JointState::setRotationInBindFrame(const glm::quat& rotation, float priority, bool constrain) { - // rotation is from bind- to model-frame - assert(_fbxJoint != NULL); - if (priority >= _animationPriority) { - glm::quat targetRotation = _rotationInConstrainedFrame * glm::inverse(getRotation()) * rotation * glm::inverse(_fbxJoint->inverseBindRotation); - if (constrain && _constraint) { - _constraint->softClamp(targetRotation, _rotationInConstrainedFrame, 0.5f); - } - setRotationInConstrainedFrameInternal(targetRotation); - _animationPriority = priority; - } -} - -void JointState::clearTransformTranslation() { - _transform[3][0] = 0.0f; - _transform[3][1] = 0.0f; - _transform[3][2] = 0.0f; - _transformChanged = true; - _visibleTransform[3][0] = 0.0f; - _visibleTransform[3][1] = 0.0f; - _visibleTransform[3][2] = 0.0f; -} - -void JointState::applyRotationDelta(const glm::quat& delta, bool constrain, float priority) { - // NOTE: delta is in model-frame - assert(_fbxJoint != NULL); - if (priority < _animationPriority || delta.null) { - return; - } - _animationPriority = priority; - glm::quat targetRotation = _rotationInConstrainedFrame * glm::inverse(getRotation()) * delta * getRotation(); - if (!constrain || _constraint == NULL) { - // no constraints - _rotationInConstrainedFrame = targetRotation; - _transformChanged = true; - - _rotation = delta * getRotation(); - return; - } - setRotationInConstrainedFrameInternal(targetRotation); -} - -/// Applies delta rotation to joint but mixes a little bit of the default pose as well. -/// This helps keep an IK solution stable. -void JointState::mixRotationDelta(const glm::quat& delta, float mixFactor, float priority) { - // NOTE: delta is in model-frame - assert(_fbxJoint != NULL); - if (priority < _animationPriority) { - return; - } - _animationPriority = priority; - glm::quat targetRotation = _rotationInConstrainedFrame * glm::inverse(getRotation()) * delta * getRotation(); - if (mixFactor > 0.0f && mixFactor <= 1.0f) { - targetRotation = safeMix(targetRotation, _fbxJoint->rotation, mixFactor); - } - if (_constraint) { - _constraint->softClamp(targetRotation, _rotationInConstrainedFrame, 0.5f); - } - setRotationInConstrainedFrameInternal(targetRotation); -} - -void JointState::mixVisibleRotationDelta(const glm::quat& delta, float mixFactor) { - // NOTE: delta is in model-frame - assert(_fbxJoint != NULL); - glm::quat targetRotation = _visibleRotationInConstrainedFrame * glm::inverse(_visibleRotation) * delta * _visibleRotation; - if (mixFactor > 0.0f && mixFactor <= 1.0f) { - //targetRotation = safeMix(targetRotation, _fbxJoint->rotation, mixFactor); - targetRotation = safeMix(targetRotation, _rotationInConstrainedFrame, mixFactor); - } - setVisibleRotationInConstrainedFrame(targetRotation); -} - -glm::quat JointState::computeParentRotation() const { - // R = Rp * Rpre * r * Rpost - // Rp = R * (Rpre * r * Rpost)^ - return getRotation() * glm::inverse(_fbxJoint->preRotation * _rotationInConstrainedFrame * _fbxJoint->postRotation); -} - -glm::quat JointState::computeVisibleParentRotation() const { - return _visibleRotation * glm::inverse(_fbxJoint->preRotation * _visibleRotationInConstrainedFrame * _fbxJoint->postRotation); -} - -void JointState::setRotationInConstrainedFrame(glm::quat targetRotation, float priority, bool constrain) { - if (priority >= _animationPriority || _animationPriority == 0.0f) { - if (constrain && _constraint) { - _constraint->softClamp(targetRotation, _rotationInConstrainedFrame, 0.5f); - } - setRotationInConstrainedFrameInternal(targetRotation); - _animationPriority = priority; - } -} - -void JointState::setRotationInConstrainedFrameInternal(const glm::quat& targetRotation) { - glm::quat parentRotation = computeParentRotation(); - _rotationInConstrainedFrame = targetRotation; - _transformChanged = true; - // R' = Rp * Rpre * r' * Rpost - _rotation = parentRotation * _fbxJoint->preRotation * _rotationInConstrainedFrame * _fbxJoint->postRotation; -} - -void JointState::setVisibleRotationInConstrainedFrame(const glm::quat& targetRotation) { - glm::quat parentRotation = computeVisibleParentRotation(); - _visibleRotationInConstrainedFrame = targetRotation; - _visibleRotation = parentRotation * _fbxJoint->preRotation * _visibleRotationInConstrainedFrame * _fbxJoint->postRotation; -} - -const bool JointState::rotationIsDefault(const glm::quat& rotation, float tolerance) const { - glm::quat defaultRotation = _fbxJoint->rotation; - return glm::abs(rotation.x - defaultRotation.x) < tolerance && - glm::abs(rotation.y - defaultRotation.y) < tolerance && - glm::abs(rotation.z - defaultRotation.z) < tolerance && - glm::abs(rotation.w - defaultRotation.w) < tolerance; -} - -glm::quat JointState::getDefaultRotationInParentFrame() const { - // NOTE: the result is constant and could be cached in the FBXJoint - return _fbxJoint->preRotation * _fbxJoint->rotation * _fbxJoint->postRotation; -} - -const glm::vec3& JointState::getDefaultTranslationInConstrainedFrame() const { - assert(_fbxJoint != NULL); - return _fbxJoint->translation; -} - -void JointState::slaveVisibleTransform() { - _visibleTransform = _transform; - _visibleRotation = getRotation(); - _visibleRotationInConstrainedFrame = _rotationInConstrainedFrame; -} diff --git a/interface/src/renderer/JointState.h b/interface/src/renderer/JointState.h deleted file mode 100644 index b502083463..0000000000 --- a/interface/src/renderer/JointState.h +++ /dev/null @@ -1,129 +0,0 @@ -// -// JointState.h -// interface/src/renderer -// -// Created by Andrzej Kapolka on 10/18/13. -// Copyright 2013 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_JointState_h -#define hifi_JointState_h - -#include -#include -#include - -#include -#include - -const float DEFAULT_PRIORITY = 3.0f; - -class AngularConstraint; - -class JointState { -public: - JointState(); - JointState(const JointState& other); - ~JointState(); - - void setFBXJoint(const FBXJoint* joint); - const FBXJoint& getFBXJoint() const { return *_fbxJoint; } - - void buildConstraint(); - void copyState(const JointState& state); - - void initTransform(const glm::mat4& parentTransform); - // if synchronousRotationCompute is true, then _transform is still computed synchronously, - // but _rotation will be asynchronously extracted - void computeTransform(const glm::mat4& parentTransform, bool parentTransformChanged = true, bool synchronousRotationCompute = false); - - void computeVisibleTransform(const glm::mat4& parentTransform); - const glm::mat4& getVisibleTransform() const { return _visibleTransform; } - glm::quat getVisibleRotation() const { return _visibleRotation; } - glm::vec3 getVisiblePosition() const { return extractTranslation(_visibleTransform); } - - const glm::mat4& getTransform() const { return _transform; } - void resetTransformChanged() { _transformChanged = false; } - bool getTransformChanged() const { return _transformChanged; } - - glm::quat getRotation() const; - glm::vec3 getPosition() const { return extractTranslation(_transform); } - - /// \return rotation from bind to model frame - glm::quat getRotationInBindFrame() const; - - glm::quat getRotationInParentFrame() const; - glm::quat getVisibleRotationInParentFrame() const; - const glm::vec3& getPositionInParentFrame() const { return _positionInParentFrame; } - float getDistanceToParent() const { return _distanceToParent; } - - int getParentIndex() const { return _fbxJoint->parentIndex; } - - /// \param delta is in the model-frame - void applyRotationDelta(const glm::quat& delta, bool constrain = true, float priority = 1.0f); - - /// Applies delta rotation to joint but mixes a little bit of the default pose as well. - /// This helps keep an IK solution stable. - /// \param delta rotation change in model-frame - /// \param mixFactor fraction in range [0,1] of how much default pose to blend in (0 is none, 1 is all) - /// \param priority priority level of this animation blend - void mixRotationDelta(const glm::quat& delta, float mixFactor, float priority = 1.0f); - void mixVisibleRotationDelta(const glm::quat& delta, float mixFactor); - - /// Blends a fraciton of default pose into joint rotation. - /// \param fraction fraction in range [0,1] of how much default pose to blend in (0 is none, 1 is all) - /// \param priority priority level of this animation blend - void restoreRotation(float fraction, float priority); - - /// \param rotation is from bind- to model-frame - /// computes and sets new _rotationInConstrainedFrame - /// NOTE: the JointState's model-frame transform/rotation are NOT updated! - void setRotationInBindFrame(const glm::quat& rotation, float priority, bool constrain = false); - - void setRotationInConstrainedFrame(glm::quat targetRotation, float priority, bool constrain = false); - void setVisibleRotationInConstrainedFrame(const glm::quat& targetRotation); - const glm::quat& getRotationInConstrainedFrame() const { return _rotationInConstrainedFrame; } - const glm::quat& getVisibleRotationInConstrainedFrame() const { return _visibleRotationInConstrainedFrame; } - - const bool rotationIsDefault(const glm::quat& rotation, float tolerance = EPSILON) const; - - glm::quat getDefaultRotationInParentFrame() const; - const glm::vec3& getDefaultTranslationInConstrainedFrame() const; - - - void clearTransformTranslation(); - - void slaveVisibleTransform(); - - float _animationPriority; // the priority of the animation affecting this joint - - /// \return parent model-frame rotation - // (used to keep _rotation consistent when modifying _rotationInWorldFrame directly) - glm::quat computeParentRotation() const; - glm::quat computeVisibleParentRotation() const; - -private: - void setRotationInConstrainedFrameInternal(const glm::quat& targetRotation); - /// debug helper function - void loadBindRotation(); - - bool _transformChanged; - glm::mat4 _transform; // joint- to model-frame - bool _rotationIsValid; - glm::quat _rotation; // joint- to model-frame - glm::quat _rotationInConstrainedFrame; // rotation in frame where angular constraints would be applied - glm::vec3 _positionInParentFrame; // only changes when the Model is scaled - float _distanceToParent; - - glm::mat4 _visibleTransform; - glm::quat _visibleRotation; - glm::quat _visibleRotationInConstrainedFrame; - - const FBXJoint* _fbxJoint; // JointState does NOT own its FBXJoint - AngularConstraint* _constraint; // JointState owns its AngularConstraint -}; - -#endif // hifi_JointState_h From cd95f7bd23a0d43088cbefdbd442ce63341bc185 Mon Sep 17 00:00:00 2001 From: DaveDubUK Date: Tue, 16 Dec 2014 13:20:11 +0000 Subject: [PATCH 440/502] Window.nonBlockingForm active status was not being tested correctly. Was causing unexpected fail on second attempt to show form --- interface/src/scripting/WindowScriptingInterface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/scripting/WindowScriptingInterface.cpp b/interface/src/scripting/WindowScriptingInterface.cpp index 591ae87560..bbb4e695e7 100644 --- a/interface/src/scripting/WindowScriptingInterface.cpp +++ b/interface/src/scripting/WindowScriptingInterface.cpp @@ -200,7 +200,7 @@ void WindowScriptingInterface::showNonBlockingForm(const QString& title, QScript } // what should we do if someone calls us while we still think we have a dialog showing??? - if (_editDialog) { + if (_nonBlockingFormActive) { qDebug() << "Show Non-Blocking Form called when form already active."; return; } From 9493440d323f65b33f5c60d28fd9b75dd3a91959 Mon Sep 17 00:00:00 2001 From: DaveDubUK Date: Tue, 16 Dec 2014 13:33:10 +0000 Subject: [PATCH 441/502] Window.nonBlockingForm-fix --- interface/src/scripting/WindowScriptingInterface.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/interface/src/scripting/WindowScriptingInterface.cpp b/interface/src/scripting/WindowScriptingInterface.cpp index bbb4e695e7..fa6de82bfe 100644 --- a/interface/src/scripting/WindowScriptingInterface.cpp +++ b/interface/src/scripting/WindowScriptingInterface.cpp @@ -201,6 +201,7 @@ void WindowScriptingInterface::showNonBlockingForm(const QString& title, QScript // what should we do if someone calls us while we still think we have a dialog showing??? if (_nonBlockingFormActive) { + qDebug() << "Show Non-Blocking Form called when form already active."; return; } From 7ab9dfbfe1ab1cf8010cf50a4035d04c111e3e04 Mon Sep 17 00:00:00 2001 From: DaveDubUK Date: Tue, 16 Dec 2014 14:48:28 +0000 Subject: [PATCH 442/502] Window.nonBlockingForm-fix --- interface/src/scripting/WindowScriptingInterface.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/interface/src/scripting/WindowScriptingInterface.cpp b/interface/src/scripting/WindowScriptingInterface.cpp index fa6de82bfe..bbb4e695e7 100644 --- a/interface/src/scripting/WindowScriptingInterface.cpp +++ b/interface/src/scripting/WindowScriptingInterface.cpp @@ -201,7 +201,6 @@ void WindowScriptingInterface::showNonBlockingForm(const QString& title, QScript // what should we do if someone calls us while we still think we have a dialog showing??? if (_nonBlockingFormActive) { - qDebug() << "Show Non-Blocking Form called when form already active."; return; } From 4d79a08533534458491c110db6eadd21968c0397 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 16 Dec 2014 10:32:03 -0800 Subject: [PATCH 443/502] remove Application dependencies from AmbientOcclusion and DeferredLightingEffect --- interface/src/Application.cpp | 12 +++++-- interface/src/Application.h | 11 ++++-- .../src/renderer/AmbientOcclusionEffect.cpp | 9 +++-- .../src/renderer/AmbientOcclusionEffect.h | 6 ++-- .../src/renderer/DeferredLightingEffect.cpp | 23 ++++++------ .../src/renderer/DeferredLightingEffect.h | 5 ++- .../render-utils/src/ViewStateInterface.h | 36 +++++++++++++++++++ 7 files changed, 78 insertions(+), 24 deletions(-) create mode 100644 libraries/render-utils/src/ViewStateInterface.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 5f0f4a700a..57b3b57224 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1914,8 +1914,8 @@ void Application::init() { _environment.init(); - _deferredLightingEffect.init(); - _ambientOcclusionEffect.init(); + _deferredLightingEffect.init(this); + _ambientOcclusionEffect.init(this); // TODO: move _myAvatar out of Application. Move relevant code to MyAvataar or AvatarManager _avatarManager.init(); @@ -3235,6 +3235,14 @@ void Application::computeOffAxisFrustum(float& left, float& right, float& bottom } } +bool Application::getShadowsEnabled() { + return Menu::getInstance()->getShadowsEnabled(); +} + +bool Application::getCascadeShadowsEnabled() { + return Menu::getInstance()->isOptionChecked(MenuOption::CascadedShadows); +} + glm::vec2 Application::getScaledScreenPoint(glm::vec2 projectedPoint) { float horizontalScale = _glWidget->getDeviceWidth() / 2.0f; float verticalScale = _glWidget->getDeviceHeight() / 2.0f; diff --git a/interface/src/Application.h b/interface/src/Application.h index 992d8d31d3..9ca363254a 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -42,6 +42,7 @@ #include #include #include +#include #include #include "MainWindow.h" @@ -128,7 +129,7 @@ static const quint64 TOO_LONG_SINCE_LAST_SEND_DOWNSTREAM_AUDIO_STATS = 1 * USECS static const QString INFO_HELP_PATH = "html/interface-welcome-allsvg.html"; static const QString INFO_EDIT_ENTITIES_PATH = "html/edit-entities-commands.html"; -class Application : public QApplication { +class Application : public QApplication, public ViewStateInterface { Q_OBJECT friend class OctreePacketProcessor; @@ -276,12 +277,16 @@ public: void getModelViewMatrix(glm::dmat4* modelViewMatrix); void getProjectionMatrix(glm::dmat4* projectionMatrix); - const glm::vec3& getShadowDistances() const { return _shadowDistances; } + virtual const glm::vec3& getShadowDistances() const { return _shadowDistances; } /// Computes the off-axis frustum parameters for the view frustum, taking mirroring into account. - void computeOffAxisFrustum(float& left, float& right, float& bottom, float& top, float& nearVal, + virtual void computeOffAxisFrustum(float& left, float& right, float& bottom, float& top, float& nearVal, float& farVal, glm::vec4& nearClipPlane, glm::vec4& farClipPlane) const; + virtual ViewFrustum* getCurrentViewFrustum() { return getDisplayViewFrustum(); } + virtual bool getShadowsEnabled(); + virtual bool getCascadeShadowsEnabled(); + NodeBounds& getNodeBoundsDisplay() { return _nodeBoundsDisplay; } FileLogger* getLogger() { return _logger; } diff --git a/interface/src/renderer/AmbientOcclusionEffect.cpp b/interface/src/renderer/AmbientOcclusionEffect.cpp index bcae662085..4362d21645 100644 --- a/interface/src/renderer/AmbientOcclusionEffect.cpp +++ b/interface/src/renderer/AmbientOcclusionEffect.cpp @@ -21,15 +21,15 @@ #include #include #include - -#include "Application.h" +#include #include "AmbientOcclusionEffect.h" const int ROTATION_WIDTH = 4; const int ROTATION_HEIGHT = 4; -void AmbientOcclusionEffect::init() { +void AmbientOcclusionEffect::init(ViewStateInterface* viewState) { + _viewState = viewState; // we will use this for view state services _occlusionProgram = new ProgramObject(); _occlusionProgram->addShaderFromSourceFile(QGLShader::Vertex, PathUtils::resourcesPath() @@ -111,8 +111,7 @@ void AmbientOcclusionEffect::render() { float left, right, bottom, top, nearVal, farVal; glm::vec4 nearClipPlane, farClipPlane; - Application::getInstance()->computeOffAxisFrustum( - left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane); + _viewState->computeOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane); int viewport[4]; glGetIntegerv(GL_VIEWPORT, viewport); diff --git a/interface/src/renderer/AmbientOcclusionEffect.h b/interface/src/renderer/AmbientOcclusionEffect.h index 3b22c7629a..444b76a3c9 100644 --- a/interface/src/renderer/AmbientOcclusionEffect.h +++ b/interface/src/renderer/AmbientOcclusionEffect.h @@ -12,6 +12,8 @@ #ifndef hifi_AmbientOcclusionEffect_h #define hifi_AmbientOcclusionEffect_h +#include + class ProgramObject; /// A screen space ambient occlusion effect. See John Chapman's tutorial at @@ -19,8 +21,7 @@ class ProgramObject; class AmbientOcclusionEffect { public: - void init(); - + void init(ViewStateInterface* viewState); void render(); private: @@ -38,6 +39,7 @@ private: int _blurScaleLocation; GLuint _rotationTextureID; + ViewStateInterface* _viewState; }; #endif // hifi_AmbientOcclusionEffect_h diff --git a/interface/src/renderer/DeferredLightingEffect.cpp b/interface/src/renderer/DeferredLightingEffect.cpp index 18a93aa042..d3145b9d5d 100644 --- a/interface/src/renderer/DeferredLightingEffect.cpp +++ b/interface/src/renderer/DeferredLightingEffect.cpp @@ -14,14 +14,17 @@ #include +#include +#include #include #include #include +#include -#include "Application.h" #include "DeferredLightingEffect.h" -void DeferredLightingEffect::init() { +void DeferredLightingEffect::init(ViewStateInterface* viewState) { + _viewState = viewState; _simpleProgram.addShaderFromSourceFile(QGLShader::Vertex, PathUtils::resourcesPath() + "shaders/simple.vert"); _simpleProgram.addShaderFromSourceFile(QGLShader::Fragment, PathUtils::resourcesPath() + "shaders/simple.frag"); _simpleProgram.link(); @@ -176,19 +179,18 @@ void DeferredLightingEffect::render() { ProgramObject* program = &_directionalLight; const LightLocations* locations = &_directionalLightLocations; - bool shadowsEnabled = Menu::getInstance()->getShadowsEnabled(); - if (shadowsEnabled) { + bool shadowsEnabled = _viewState->getShadowsEnabled(); + if (shadowsEnabled) { glActiveTexture(GL_TEXTURE4); glBindTexture(GL_TEXTURE_2D, textureCache->getShadowDepthTextureID()); program = &_directionalLightShadowMap; locations = &_directionalLightShadowMapLocations; - if (Menu::getInstance()->isOptionChecked(MenuOption::CascadedShadows)) { + if (_viewState->getCascadeShadowsEnabled()) { program = &_directionalLightCascadedShadowMap; locations = &_directionalLightCascadedShadowMapLocations; _directionalLightCascadedShadowMap.bind(); - _directionalLightCascadedShadowMap.setUniform(locations->shadowDistances, - Application::getInstance()->getShadowDistances()); + _directionalLightCascadedShadowMap.setUniform(locations->shadowDistances, _viewState->getShadowDistances()); } else { program->bind(); @@ -202,8 +204,7 @@ void DeferredLightingEffect::render() { float left, right, bottom, top, nearVal, farVal; glm::vec4 nearClipPlane, farClipPlane; - Application::getInstance()->computeOffAxisFrustum( - left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane); + _viewState->computeOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane); program->setUniformValue(locations->nearLocation, nearVal); float depthScale = (farVal - nearVal) / farVal; program->setUniformValue(locations->depthScale, depthScale); @@ -238,8 +239,8 @@ void DeferredLightingEffect::render() { // enlarge the scales slightly to account for tesselation const float SCALE_EXPANSION = 0.05f; - const glm::vec3& eyePoint = Application::getInstance()->getDisplayViewFrustum()->getPosition(); - float nearRadius = glm::distance(eyePoint, Application::getInstance()->getDisplayViewFrustum()->getNearTopLeft()); + const glm::vec3& eyePoint = _viewState->getCurrentViewFrustum()->getPosition(); + float nearRadius = glm::distance(eyePoint, _viewState->getCurrentViewFrustum()->getNearTopLeft()); GeometryCache* geometryCache = DependencyManager::get(); diff --git a/interface/src/renderer/DeferredLightingEffect.h b/interface/src/renderer/DeferredLightingEffect.h index effcea27d2..40182e0917 100644 --- a/interface/src/renderer/DeferredLightingEffect.h +++ b/interface/src/renderer/DeferredLightingEffect.h @@ -16,6 +16,7 @@ #include #include +#include class PostLightingRenderable; @@ -23,7 +24,7 @@ class PostLightingRenderable; class DeferredLightingEffect { public: - void init(); + void init(ViewStateInterface* viewState); /// Returns a reference to a simple program suitable for rendering static /// untextured geometry (such as that generated by glutSolidSphere, etc.) @@ -118,6 +119,8 @@ private: QVector _pointLights; QVector _spotLights; QVector _postLightingRenderables; + + ViewStateInterface* _viewState; }; /// Simple interface for objects that require something to be rendered after deferred lighting. diff --git a/libraries/render-utils/src/ViewStateInterface.h b/libraries/render-utils/src/ViewStateInterface.h new file mode 100644 index 0000000000..decccdc401 --- /dev/null +++ b/libraries/render-utils/src/ViewStateInterface.h @@ -0,0 +1,36 @@ +// +// ViewStateInterface.h +// interface/src/renderer +// +// Created by Brad Hefta-Gaub on 12/16/14. +// 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_ViewStateInterface_h +#define hifi_ViewStateInterface_h + +#include + +/// Interface provided by Application to other objects that need access to the current view state details +class ViewStateInterface { +public: + + /// Returns the shadow distances for the current view state + virtual const glm::vec3& getShadowDistances() const = 0; + + /// Computes the off-axis frustum parameters for the view frustum, taking mirroring into account. + virtual void computeOffAxisFrustum(float& left, float& right, float& bottom, float& top, float& nearVal, + float& farVal, glm::vec4& nearClipPlane, glm::vec4& farClipPlane) const = 0; + + /// gets the current view frustum for rendering the view state + virtual ViewFrustum* getCurrentViewFrustum() = 0; + + virtual bool getShadowsEnabled() = 0; + virtual bool getCascadeShadowsEnabled() = 0; +}; + + +#endif // hifi_ViewStateInterface_h From fc1e1ecfc04fdc3475fb990c3e19f29e343b978d Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 16 Dec 2014 11:27:44 -0800 Subject: [PATCH 444/502] move DeferredLightingEffect and AmbientOcclusionEffect to libraries, make them DependencyManager enabled --- interface/src/Application.cpp | 13 +++++--- interface/src/Application.h | 7 ---- interface/src/MetavoxelSystem.cpp | 9 ++--- interface/src/avatar/Avatar.cpp | 3 +- .../src/entities/RenderableBoxEntityItem.cpp | 7 ++-- .../entities/RenderableLightEntityItem.cpp | 33 ++++++++++--------- .../entities/RenderableModelEntityItem.cpp | 7 ++-- .../entities/RenderableSphereEntityItem.cpp | 5 +-- interface/src/renderer/Model.cpp | 3 +- interface/src/ui/overlays/Cube3DOverlay.cpp | 7 ++-- interface/src/ui/overlays/Sphere3DOverlay.cpp | 1 - .../src}/AmbientOcclusionEffect.cpp | 10 +++--- .../src}/AmbientOcclusionEffect.h | 9 +++-- .../src}/DeferredLightingEffect.cpp | 20 ++++++++--- .../src}/DeferredLightingEffect.h | 11 +++++-- 15 files changed, 84 insertions(+), 61 deletions(-) rename {interface/src/renderer => libraries/render-utils/src}/AmbientOcclusionEffect.cpp (98%) rename {interface/src/renderer => libraries/render-utils/src}/AmbientOcclusionEffect.h (81%) rename {interface/src/renderer => libraries/render-utils/src}/DeferredLightingEffect.cpp (98%) rename {interface/src/renderer => libraries/render-utils/src}/DeferredLightingEffect.h (94%) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 57b3b57224..c9309616ae 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -54,7 +54,9 @@ #include #include +#include #include +#include #include #include #include @@ -110,6 +112,7 @@ #include "ui/TextRenderer.h" + using namespace std; // Starfield information @@ -1914,8 +1917,8 @@ void Application::init() { _environment.init(); - _deferredLightingEffect.init(this); - _ambientOcclusionEffect.init(this); + DependencyManager::get()->init(this); + DependencyManager::get()->init(this); // TODO: move _myAvatar out of Application. Move relevant code to MyAvataar or AvatarManager _avatarManager.init(); @@ -3070,7 +3073,7 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly, RenderAr glEnable(GL_LIGHTING); glEnable(GL_DEPTH_TEST); - _deferredLightingEffect.prepare(); + DependencyManager::get()->prepare(); if (!selfAvatarOnly) { // draw a red sphere @@ -3113,7 +3116,7 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly, RenderAr PerformanceTimer perfTimer("ambientOcclusion"); PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::displaySide() ... AmbientOcclusion..."); - _ambientOcclusionEffect.render(); + DependencyManager::get()->render(); } } @@ -3130,7 +3133,7 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly, RenderAr { PROFILE_RANGE("DeferredLighting"); PerformanceTimer perfTimer("lighting"); - _deferredLightingEffect.render(); + DependencyManager::get()->render(); } { diff --git a/interface/src/Application.h b/interface/src/Application.h index 9ca363254a..6b5bcc0770 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -62,8 +62,6 @@ #include "devices/PrioVR.h" #include "devices/SixenseManager.h" #include "entities/EntityTreeRenderer.h" -#include "renderer/AmbientOcclusionEffect.h" -#include "renderer/DeferredLightingEffect.h" #include "scripting/ControllerScriptingInterface.h" #include "ui/BandwidthDialog.h" #include "ui/BandwidthMeter.h" @@ -250,7 +248,6 @@ public: ToolWindow* getToolWindow() { return _toolWindow ; } - DeferredLightingEffect* getDeferredLightingEffect() { return &_deferredLightingEffect; } ControllerScriptingInterface* getControllerScriptingInterface() { return &_controllerScriptingInterface; } AvatarManager& getAvatarManager() { return _avatarManager; } @@ -569,10 +566,6 @@ private: QSet _keysPressed; - - DeferredLightingEffect _deferredLightingEffect; - AmbientOcclusionEffect _ambientOcclusionEffect; - Audio _audio; bool _enableProcessVoxelsThread; diff --git a/interface/src/MetavoxelSystem.cpp b/interface/src/MetavoxelSystem.cpp index 824f1e3313..d34bc4a594 100644 --- a/interface/src/MetavoxelSystem.cpp +++ b/interface/src/MetavoxelSystem.cpp @@ -21,6 +21,7 @@ #include +#include #include #include @@ -470,7 +471,7 @@ void MetavoxelSystem::render() { glColor4f(1.0f, 1.0f, 1.0f, 1.0f); glNormal3f(0.0f, 1.0f, 0.0f); - Application::getInstance()->getDeferredLightingEffect()->bindSimpleProgram(); + DependencyManager::get()->bindSimpleProgram(); foreach (const HermiteBatch& batch, _hermiteBatches) { batch.vertexBuffer->bind(); @@ -482,7 +483,7 @@ void MetavoxelSystem::render() { batch.vertexBuffer->release(); } - Application::getInstance()->getDeferredLightingEffect()->releaseSimpleProgram(); + DependencyManager::get()->releaseSimpleProgram(); glDisableClientState(GL_VERTEX_ARRAY); @@ -1981,7 +1982,7 @@ void SphereRenderer::render(const MetavoxelLOD& lod, bool contained, bool cursor glm::vec3 axis = glm::axis(rotation); glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z); - Application::getInstance()->getDeferredLightingEffect()->renderSolidSphere(sphere->getScale(), 32, 32); + DependencyManager::get()->renderSolidSphere(sphere->getScale(), 32, 32); glPopMatrix(); } @@ -2002,7 +2003,7 @@ void CuboidRenderer::render(const MetavoxelLOD& lod, bool contained, bool cursor glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z); glScalef(1.0f, cuboid->getAspectY(), cuboid->getAspectZ()); - Application::getInstance()->getDeferredLightingEffect()->renderSolidCube(cuboid->getScale() * 2.0f); + DependencyManager::get()->renderSolidCube(cuboid->getScale() * 2.0f); glPopMatrix(); } diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 4b7c5dfdf3..51fde3df43 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -364,7 +365,7 @@ void Avatar::render(const glm::vec3& cameraPosition, RenderMode renderMode, bool glm::quat orientation = getOrientation(); foreach (const AvatarManager::LocalLight& light, Application::getInstance()->getAvatarManager().getLocalLights()) { glm::vec3 direction = orientation * light.direction; - Application::getInstance()->getDeferredLightingEffect()->addSpotLight(position - direction * distance, + DependencyManager::get()->addSpotLight(position - direction * distance, distance * 2.0f, glm::vec3(), light.color, light.color, 1.0f, 0.5f, 0.0f, direction, LIGHT_EXPONENT, LIGHT_CUTOFF); } diff --git a/interface/src/entities/RenderableBoxEntityItem.cpp b/interface/src/entities/RenderableBoxEntityItem.cpp index 1cc1f72e93..f7b403bff2 100644 --- a/interface/src/entities/RenderableBoxEntityItem.cpp +++ b/interface/src/entities/RenderableBoxEntityItem.cpp @@ -16,6 +16,7 @@ #include "InterfaceConfig.h" #include +#include #include #include @@ -53,7 +54,7 @@ void RenderableBoxEntityItem::render(RenderArgs* args) { glm::vec3 positionToCenter = center - position; glTranslatef(positionToCenter.x, positionToCenter.y, positionToCenter.z); glScalef(dimensions.x, dimensions.y, dimensions.z); - Application::getInstance()->getDeferredLightingEffect()->renderSolidCube(1.0f); + DependencyManager::get()->renderSolidCube(1.0f); glPopMatrix(); glPopMatrix(); } else { @@ -90,7 +91,7 @@ void RenderableBoxEntityItem::render(RenderArgs* args) { glColor4f(getColor()[RED_INDEX] / MAX_COLOR, getColor()[GREEN_INDEX] / MAX_COLOR, getColor()[BLUE_INDEX] / MAX_COLOR, getLocalRenderAlpha()); - Application::getInstance()->getDeferredLightingEffect()->bindSimpleProgram(); + DependencyManager::get()->bindSimpleProgram(); glPushMatrix(); glTranslatef(position.x, position.y, position.z); @@ -105,7 +106,7 @@ void RenderableBoxEntityItem::render(RenderArgs* args) { glPopMatrix(); glPopMatrix(); - Application::getInstance()->getDeferredLightingEffect()->releaseSimpleProgram(); + DependencyManager::get()->releaseSimpleProgram(); glDisableClientState(GL_VERTEX_ARRAY); // disable vertex arrays glDisableClientState(GL_NORMAL_ARRAY); diff --git a/interface/src/entities/RenderableLightEntityItem.cpp b/interface/src/entities/RenderableLightEntityItem.cpp index 77dbb5da0b..48996d5b4c 100644 --- a/interface/src/entities/RenderableLightEntityItem.cpp +++ b/interface/src/entities/RenderableLightEntityItem.cpp @@ -15,6 +15,7 @@ #include "InterfaceConfig.h" +#include #include #include @@ -65,30 +66,30 @@ void RenderableLightEntityItem::render(RenderArgs* args) { if (!disableLights) { if (_isSpotlight) { - Application::getInstance()->getDeferredLightingEffect()->addSpotLight(position, largestDiameter / 2.0f, + DependencyManager::get()->addSpotLight(position, largestDiameter / 2.0f, ambient, diffuse, specular, constantAttenuation, linearAttenuation, quadraticAttenuation, direction, exponent, cutoff); } else { - Application::getInstance()->getDeferredLightingEffect()->addPointLight(position, largestDiameter / 2.0f, + DependencyManager::get()->addPointLight(position, largestDiameter / 2.0f, ambient, diffuse, specular, constantAttenuation, linearAttenuation, quadraticAttenuation); } } - bool wantDebug = false; - if (wantDebug) { - glColor4f(diffuseR, diffuseG, diffuseB, 1.0f); - glPushMatrix(); - glTranslatef(position.x, position.y, position.z); - glm::vec3 axis = glm::axis(rotation); - glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z); - glPushMatrix(); - glm::vec3 positionToCenter = center - position; - glTranslatef(positionToCenter.x, positionToCenter.y, positionToCenter.z); - glScalef(dimensions.x, dimensions.y, dimensions.z); - Application::getInstance()->getDeferredLightingEffect()->renderWireSphere(0.5f, 15, 15); - glPopMatrix(); +#ifdef WANT_DEBUG + glColor4f(diffuseR, diffuseG, diffuseB, 1.0f); + glPushMatrix(); + glTranslatef(position.x, position.y, position.z); + glm::vec3 axis = glm::axis(rotation); + glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z); + glPushMatrix(); + glm::vec3 positionToCenter = center - position; + glTranslatef(positionToCenter.x, positionToCenter.y, positionToCenter.z); + + glScalef(dimensions.x, dimensions.y, dimensions.z); + DependencyManager::get()->renderWireSphere(0.5f, 15, 15); glPopMatrix(); - } + glPopMatrix(); +#endif }; bool RenderableLightEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, diff --git a/interface/src/entities/RenderableModelEntityItem.cpp b/interface/src/entities/RenderableModelEntityItem.cpp index 080162dc16..13bc097f27 100644 --- a/interface/src/entities/RenderableModelEntityItem.cpp +++ b/interface/src/entities/RenderableModelEntityItem.cpp @@ -16,6 +16,7 @@ #include "InterfaceConfig.h" #include +#include #include #include @@ -191,7 +192,7 @@ void RenderableModelEntityItem::render(RenderArgs* args) { glColor3ub(getColor()[RED_INDEX],getColor()[GREEN_INDEX],getColor()[BLUE_INDEX]); glPushMatrix(); glTranslatef(position.x, position.y, position.z); - Application::getInstance()->getDeferredLightingEffect()->renderWireCube(size); + DependencyManager::get()->renderWireCube(size); glPopMatrix(); } } else { @@ -199,7 +200,7 @@ void RenderableModelEntityItem::render(RenderArgs* args) { glColor3ub(getColor()[RED_INDEX],getColor()[GREEN_INDEX],getColor()[BLUE_INDEX]); glPushMatrix(); glTranslatef(position.x, position.y, position.z); - Application::getInstance()->getDeferredLightingEffect()->renderWireCube(size); + DependencyManager::get()->renderWireCube(size); glPopMatrix(); } } @@ -208,7 +209,7 @@ void RenderableModelEntityItem::render(RenderArgs* args) { glColor3ub(getColor()[RED_INDEX],getColor()[GREEN_INDEX],getColor()[BLUE_INDEX]); glPushMatrix(); glTranslatef(position.x, position.y, position.z); - Application::getInstance()->getDeferredLightingEffect()->renderWireCube(size); + DependencyManager::get()->renderWireCube(size); glPopMatrix(); } } diff --git a/interface/src/entities/RenderableSphereEntityItem.cpp b/interface/src/entities/RenderableSphereEntityItem.cpp index d561670be8..db10edca73 100644 --- a/interface/src/entities/RenderableSphereEntityItem.cpp +++ b/interface/src/entities/RenderableSphereEntityItem.cpp @@ -15,6 +15,8 @@ #include "InterfaceConfig.h" +#include +#include #include #include @@ -23,7 +25,6 @@ #include "EntityTreeRenderer.h" #include "RenderableSphereEntityItem.h" - EntityItem* RenderableSphereEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { return new RenderableSphereEntityItem(entityID, properties); } @@ -51,7 +52,7 @@ void RenderableSphereEntityItem::render(RenderArgs* args) { glTranslatef(positionToCenter.x, positionToCenter.y, positionToCenter.z); glScalef(dimensions.x, dimensions.y, dimensions.z); - Application::getInstance()->getDeferredLightingEffect()->renderSolidSphere(0.5f, 15, 15); + DependencyManager::get()->renderSolidSphere(0.5f, 15, 15); glPopMatrix(); glPopMatrix(); }; diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 877f43a563..15db8e4361 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -493,7 +494,7 @@ bool Model::renderTriangleProxies() { glPushMatrix(); glTranslatef(center.x, center.y, center.z); glScalef(dimensions.x, dimensions.y, dimensions.z); - Application::getInstance()->getDeferredLightingEffect()->renderWireCube(1.0f); + DependencyManager::get()->renderWireCube(1.0f); glPopMatrix(); } diff --git a/interface/src/ui/overlays/Cube3DOverlay.cpp b/interface/src/ui/overlays/Cube3DOverlay.cpp index f518c309a1..c61d68f05d 100644 --- a/interface/src/ui/overlays/Cube3DOverlay.cpp +++ b/interface/src/ui/overlays/Cube3DOverlay.cpp @@ -13,6 +13,7 @@ #include +#include #include #include #include @@ -75,7 +76,7 @@ void Cube3DOverlay::render(RenderArgs* args) { glPushMatrix(); glColor4f(1.0f, 1.0f, 1.0f, alpha); glScalef(dimensions.x * _borderSize, dimensions.y * _borderSize, dimensions.z * _borderSize); - Application::getInstance()->getDeferredLightingEffect()->renderSolidCube(1.0f); + DependencyManager::get()->renderSolidCube(1.0f); glPopMatrix(); glDepthMask(GL_TRUE); } @@ -83,7 +84,7 @@ void Cube3DOverlay::render(RenderArgs* args) { glPushMatrix(); glColor4f(color.red / MAX_COLOR, color.green / MAX_COLOR, color.blue / MAX_COLOR, alpha); glScalef(dimensions.x, dimensions.y, dimensions.z); - Application::getInstance()->getDeferredLightingEffect()->renderSolidCube(1.0f); + DependencyManager::get()->renderSolidCube(1.0f); glPopMatrix(); } else { glLineWidth(_lineWidth); @@ -117,7 +118,7 @@ void Cube3DOverlay::render(RenderArgs* args) { } else { glScalef(dimensions.x, dimensions.y, dimensions.z); - Application::getInstance()->getDeferredLightingEffect()->renderWireCube(1.0f); + DependencyManager::get()->renderWireCube(1.0f); } } glPopMatrix(); diff --git a/interface/src/ui/overlays/Sphere3DOverlay.cpp b/interface/src/ui/overlays/Sphere3DOverlay.cpp index eb95672399..522902194f 100644 --- a/interface/src/ui/overlays/Sphere3DOverlay.cpp +++ b/interface/src/ui/overlays/Sphere3DOverlay.cpp @@ -62,7 +62,6 @@ void Sphere3DOverlay::render(RenderArgs* args) { glm::vec3 positionToCenter = center - position; glTranslatef(positionToCenter.x, positionToCenter.y, positionToCenter.z); glScalef(dimensions.x, dimensions.y, dimensions.z); - //Application::getInstance()->getDeferredLightingEffect()->renderSolidCube(1.0f); if (_isSolid) { DependencyManager::get()->renderSphere(1.0f, SLICES, SLICES); } else { diff --git a/interface/src/renderer/AmbientOcclusionEffect.cpp b/libraries/render-utils/src/AmbientOcclusionEffect.cpp similarity index 98% rename from interface/src/renderer/AmbientOcclusionEffect.cpp rename to libraries/render-utils/src/AmbientOcclusionEffect.cpp index 4362d21645..b9289204c7 100644 --- a/interface/src/renderer/AmbientOcclusionEffect.cpp +++ b/libraries/render-utils/src/AmbientOcclusionEffect.cpp @@ -10,20 +10,20 @@ // // include this before QOpenGLFramebufferObject, which includes an earlier version of OpenGL -#include "InterfaceConfig.h" +#include #include #include -#include #include -#include -#include #include -#include #include "AmbientOcclusionEffect.h" +#include "GlowEffect.h" +#include "ProgramObject.h" +#include "RenderUtil.h" +#include "TextureCache.h" const int ROTATION_WIDTH = 4; const int ROTATION_HEIGHT = 4; diff --git a/interface/src/renderer/AmbientOcclusionEffect.h b/libraries/render-utils/src/AmbientOcclusionEffect.h similarity index 81% rename from interface/src/renderer/AmbientOcclusionEffect.h rename to libraries/render-utils/src/AmbientOcclusionEffect.h index 444b76a3c9..1ee7269480 100644 --- a/interface/src/renderer/AmbientOcclusionEffect.h +++ b/libraries/render-utils/src/AmbientOcclusionEffect.h @@ -12,19 +12,24 @@ #ifndef hifi_AmbientOcclusionEffect_h #define hifi_AmbientOcclusionEffect_h -#include +#include + +#include "ViewStateInterface.h" class ProgramObject; /// A screen space ambient occlusion effect. See John Chapman's tutorial at /// http://john-chapman-graphics.blogspot.co.uk/2013/01/ssao-tutorial.html for reference. -class AmbientOcclusionEffect { +class AmbientOcclusionEffect: public DependencyManager::Dependency { public: void init(ViewStateInterface* viewState); void render(); private: + AmbientOcclusionEffect() {} + virtual ~AmbientOcclusionEffect() {} + friend class DependencyManager; ProgramObject* _occlusionProgram; int _nearLocation; diff --git a/interface/src/renderer/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp similarity index 98% rename from interface/src/renderer/DeferredLightingEffect.cpp rename to libraries/render-utils/src/DeferredLightingEffect.cpp index d3145b9d5d..ff2df95746 100644 --- a/interface/src/renderer/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -10,18 +10,28 @@ // // include this before QOpenGLFramebufferObject, which includes an earlier version of OpenGL -#include "InterfaceConfig.h" +#include + + +// TODO: remove these once we migrate away from GLUT calls +#if defined(__APPLE__) +#include +#else +#include +#endif #include -#include #include -#include #include -#include -#include + #include "DeferredLightingEffect.h" +#include "GeometryCache.h" +#include "GlowEffect.h" +#include "RenderUtil.h" +#include "TextureCache.h" + void DeferredLightingEffect::init(ViewStateInterface* viewState) { _viewState = viewState; diff --git a/interface/src/renderer/DeferredLightingEffect.h b/libraries/render-utils/src/DeferredLightingEffect.h similarity index 94% rename from interface/src/renderer/DeferredLightingEffect.h rename to libraries/render-utils/src/DeferredLightingEffect.h index 40182e0917..5dcd7d35f4 100644 --- a/interface/src/renderer/DeferredLightingEffect.h +++ b/libraries/render-utils/src/DeferredLightingEffect.h @@ -14,14 +14,16 @@ #include -#include +#include #include -#include + +#include "ProgramObject.h" +#include "ViewStateInterface.h" class PostLightingRenderable; /// Handles deferred lighting for the bits that require it (voxels, metavoxels...) -class DeferredLightingEffect { +class DeferredLightingEffect: public DependencyManager::Dependency { public: void init(ViewStateInterface* viewState); @@ -69,6 +71,9 @@ public: void render(); private: + DeferredLightingEffect() { } + virtual ~DeferredLightingEffect() { } + friend class DependencyManager; class LightLocations { public: From a9b3fdd3ebb6360a589e69f312bf73f807d1904a Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 16 Dec 2014 11:44:15 -0800 Subject: [PATCH 445/502] try this --- libraries/render-utils/src/DeferredLightingEffect.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index ff2df95746..f3bc0f9a22 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -16,6 +16,11 @@ // TODO: remove these once we migrate away from GLUT calls #if defined(__APPLE__) #include +#elif defined(WIN32) +#include +#include +#include +#include #else #include #endif From ec5c33feccf48c1071dbfef9027653ff86ab05cd Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 16 Dec 2014 11:57:06 -0800 Subject: [PATCH 446/502] try this --- libraries/render-utils/src/DeferredLightingEffect.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index f3bc0f9a22..a93f9fc89f 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -17,10 +17,7 @@ #if defined(__APPLE__) #include #elif defined(WIN32) -#include -#include -#include -#include + // nothing? #else #include #endif From ee34dfffc11ac48e7462af14f8876335c014a82b Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 16 Dec 2014 12:05:23 -0800 Subject: [PATCH 447/502] try this --- libraries/render-utils/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/render-utils/CMakeLists.txt b/libraries/render-utils/CMakeLists.txt index eb96e7c5ec..1a23f4c4f0 100644 --- a/libraries/render-utils/CMakeLists.txt +++ b/libraries/render-utils/CMakeLists.txt @@ -26,6 +26,7 @@ else (APPLE) # we're using static GLEW, so define GLEW_STATIC add_definitions(-DGLEW_STATIC) + target_link_libraries(${TARGET_NAME} "${GLEW_LIBRARIES}") endif() endif (APPLE) From 1ed2c62bbf7df6c9f5b5238138e2620e5f312ff5 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 16 Dec 2014 12:15:57 -0800 Subject: [PATCH 448/502] try this --- libraries/render-utils/CMakeLists.txt | 3 +++ libraries/render-utils/src/DeferredLightingEffect.cpp | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/libraries/render-utils/CMakeLists.txt b/libraries/render-utils/CMakeLists.txt index 1a23f4c4f0..0244fa91a6 100644 --- a/libraries/render-utils/CMakeLists.txt +++ b/libraries/render-utils/CMakeLists.txt @@ -24,6 +24,9 @@ else (APPLE) find_package(GLEW REQUIRED) include_directories(${GLEW_INCLUDE_DIRS}) + find_package(GLUT REQUIRED) + include_directories(SYSTEM "${GLUT_INCLUDE_DIRS}") + # we're using static GLEW, so define GLEW_STATIC add_definitions(-DGLEW_STATIC) target_link_libraries(${TARGET_NAME} "${GLEW_LIBRARIES}") diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index a93f9fc89f..9f54b25441 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -17,7 +17,7 @@ #if defined(__APPLE__) #include #elif defined(WIN32) - // nothing? +#include #else #include #endif From 58183515e6b33353f5125df90c8e9f83175c7938 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 16 Dec 2014 12:23:54 -0800 Subject: [PATCH 449/502] more windows shenanigans --- interface/src/renderer/Model.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 15db8e4361..56d7d30def 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include + #include #include #include From 16c1e597f15f90cd15a837e85207c4944cfd06b6 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 16 Dec 2014 12:53:22 -0800 Subject: [PATCH 450/502] remove Application dependency from Model --- interface/src/Application.cpp | 2 ++ interface/src/Application.h | 5 +++-- interface/src/renderer/Model.cpp | 19 +++++++++++-------- interface/src/renderer/Model.h | 6 ++++++ .../render-utils/src/ViewStateInterface.h | 7 +++++++ 5 files changed, 29 insertions(+), 10 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c9309616ae..02dae8e08e 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -429,6 +429,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : #endif this->installEventFilter(this); + + Model::setViewStateInterface(this); // The model class will sometimes need to know view state details from us } void Application::aboutToQuit() { diff --git a/interface/src/Application.h b/interface/src/Application.h index 6b5bcc0770..dea7c80940 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -232,7 +232,7 @@ public: const glm::vec3& getViewMatrixTranslation() const { return _viewMatrixTranslation; } void setViewMatrixTranslation(const glm::vec3& translation) { _viewMatrixTranslation = translation; } - const Transform& getViewTransform() const { return _viewTransform; } + virtual const Transform& getViewTransform() const { return _viewTransform; } void setViewTransform(const Transform& view); /// if you need to access the application settings, use lockSettings()/unlockSettings() @@ -255,7 +255,7 @@ public: void controlledBroadcastToNodes(const QByteArray& packet, const NodeSet& destinationNodeTypes); - void setupWorldLight(); + virtual void setupWorldLight(); QImage renderAvatarBillboard(); @@ -283,6 +283,7 @@ public: virtual ViewFrustum* getCurrentViewFrustum() { return getDisplayViewFrustum(); } virtual bool getShadowsEnabled(); virtual bool getCascadeShadowsEnabled(); + virtual QThread* getMainThread() { return thread(); } NodeBounds& getNodeBoundsDisplay() { return _nodeBoundsDisplay; } diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 56d7d30def..7fe024b8fe 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -22,6 +22,8 @@ #include #include #include +#include +#include #include #include #include @@ -29,11 +31,10 @@ #include #include "AnimationHandle.h" -#include "Application.h" +#include "Menu.h" #include "Model.h" -#include "gpu/Batch.h" -#include "gpu/GLBackend.h" + #define GLBATCH( call ) batch._##call //#define GLBATCH( call ) call @@ -63,7 +64,7 @@ Model::Model(QObject* parent) : _meshGroupsKnown(false) { // we may have been created in the network thread, but we live in the main thread - moveToThread(Application::getInstance()->thread()); + moveToThread(_viewState->getMainThread()); } Model::~Model() { @@ -109,6 +110,8 @@ Model::SkinLocations Model::_skinNormalSpecularMapLocations; Model::SkinLocations Model::_skinShadowLocations; Model::SkinLocations Model::_skinTranslucentLocations; +ViewStateInterface* Model::_viewState = NULL; + void Model::setScale(const glm::vec3& scale) { setScaleInternal(scale); // if anyone sets scale manually, then we are no longer scaled to fit @@ -727,7 +730,7 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) { if (_transforms.empty()) { _transforms.push_back(Transform()); } - _transforms[0] = Application::getInstance()->getViewTransform(); + _transforms[0] = _viewState->getViewTransform(); // apply entity translation offset to the viewTransform in one go (it's a preTranslate because viewTransform goes from world to eye space) _transforms[0].preTranslate(-_translation); @@ -870,7 +873,7 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) { } // restore all the default material settings - Application::getInstance()->setupWorldLight(); + _viewState->setupWorldLight(); if (args) { args->_translucentMeshPartsRendered = translucentMeshPartsRendered; @@ -1670,7 +1673,7 @@ void Model::setupBatchTransform(gpu::Batch& batch) { if (_transforms.empty()) { _transforms.push_back(Transform()); } - _transforms[0] = Application::getInstance()->getViewTransform(); + _transforms[0] = _viewState->getViewTransform(); _transforms[0].preTranslate(-_translation); batch.setViewTransform(_transforms[0]); } @@ -1830,7 +1833,7 @@ void Model::endScene(RenderMode mode, RenderArgs* args) { } // restore all the default material settings - Application::getInstance()->setupWorldLight(); + _viewState->setupWorldLight(); } diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 8000e7385b..2c6b0bd6ae 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -28,6 +28,7 @@ #include #include #include +#include #include "AnimationHandle.h" @@ -46,6 +47,8 @@ class Model : public QObject, public PhysicsEntity { public: + static void setViewStateInterface(ViewStateInterface* viewState) { _viewState = viewState; } + Model(QObject* parent = NULL); virtual ~Model(); @@ -455,6 +458,9 @@ private: static int renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args); + + static ViewStateInterface* _viewState; + }; Q_DECLARE_METATYPE(QPointer) diff --git a/libraries/render-utils/src/ViewStateInterface.h b/libraries/render-utils/src/ViewStateInterface.h index decccdc401..83501589d0 100644 --- a/libraries/render-utils/src/ViewStateInterface.h +++ b/libraries/render-utils/src/ViewStateInterface.h @@ -14,6 +14,9 @@ #include +class Transform; +class QThread; + /// Interface provided by Application to other objects that need access to the current view state details class ViewStateInterface { public: @@ -30,6 +33,10 @@ public: virtual bool getShadowsEnabled() = 0; virtual bool getCascadeShadowsEnabled() = 0; + + virtual QThread* getMainThread() = 0; + virtual const Transform& getViewTransform() const = 0; + virtual void setupWorldLight() = 0; }; From efa8a752f20fb9092df8279f4adbeabeb210f846 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 16 Dec 2014 13:14:57 -0800 Subject: [PATCH 451/502] remove dependency on Menu from Model --- interface/src/Application.cpp | 8 ++++++-- interface/src/Application.h | 1 + interface/src/renderer/Model.cpp | 16 ++++++++++------ libraries/render-utils/src/ViewStateInterface.h | 1 + 4 files changed, 18 insertions(+), 8 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 02dae8e08e..8b3c5a2fa1 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -191,6 +191,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : _isVSyncOn(true), _aboutToQuit(false) { + Model::setViewStateInterface(this); // The model class will sometimes need to know view state details from us + // read the ApplicationInfo.ini file for Name/Version/Domain information QSettings applicationInfo(PathUtils::resourcesPath() + "info/ApplicationInfo.ini", QSettings::IniFormat); @@ -429,8 +431,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : #endif this->installEventFilter(this); - - Model::setViewStateInterface(this); // The model class will sometimes need to know view state details from us } void Application::aboutToQuit() { @@ -2939,6 +2939,10 @@ void Application::setupWorldLight() { glMateriali(GL_FRONT, GL_SHININESS, 96); } +bool Application::shouldRenderMesh(float largestDimension, float distanceToCamera) { + return Menu::getInstance()->shouldRenderMesh(largestDimension, distanceToCamera); +} + QImage Application::renderAvatarBillboard() { DependencyManager::get()->getPrimaryFramebufferObject()->bind(); diff --git a/interface/src/Application.h b/interface/src/Application.h index dea7c80940..9aca90fac8 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -256,6 +256,7 @@ public: void controlledBroadcastToNodes(const QByteArray& packet, const NodeSet& destinationNodeTypes); virtual void setupWorldLight(); + virtual bool shouldRenderMesh(float largestDimension, float distanceToCamera); QImage renderAvatarBillboard(); diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 7fe024b8fe..2faeeeea55 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -31,7 +31,6 @@ #include #include "AnimationHandle.h" -#include "Menu.h" #include "Model.h" @@ -64,7 +63,9 @@ Model::Model(QObject* parent) : _meshGroupsKnown(false) { // we may have been created in the network thread, but we live in the main thread - moveToThread(_viewState->getMainThread()); + if (_viewState) { + moveToThread(_viewState->getMainThread()); + } } Model::~Model() { @@ -720,6 +721,9 @@ bool Model::render(float alpha, RenderMode mode, RenderArgs* args) { bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) { PROFILE_RANGE(__FUNCTION__); + if (!_viewState) { + return false; + } // Let's introduce a gpu::Batch to capture all the calls to the graphics api _renderBatch.clear(); @@ -2329,9 +2333,9 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, RenderArgs* args, Locations* locations, SkinLocations* skinLocations) { PROFILE_RANGE(__FUNCTION__); - bool dontCullOutOfViewMeshParts = Menu::getInstance()->isOptionChecked(MenuOption::DontCullOutOfViewMeshParts); - bool cullTooSmallMeshParts = !Menu::getInstance()->isOptionChecked(MenuOption::DontCullTooSmallMeshParts); - bool dontReduceMaterialSwitches = Menu::getInstance()->isOptionChecked(MenuOption::DontReduceMaterialSwitches); + bool dontCullOutOfViewMeshParts = false; // Menu::getInstance()->isOptionChecked(MenuOption::DontCullOutOfViewMeshParts); + bool cullTooSmallMeshParts = true; // !Menu::getInstance()->isOptionChecked(MenuOption::DontCullTooSmallMeshParts); + bool dontReduceMaterialSwitches = false; // Menu::getInstance()->isOptionChecked(MenuOption::DontReduceMaterialSwitches); TextureCache* textureCache = DependencyManager::get(); GlowEffect* glowEffect = DependencyManager::get(); @@ -2373,7 +2377,7 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod args->_viewFrustum->boxInFrustum(_calculatedMeshBoxes.at(i)) != ViewFrustum::OUTSIDE; if (shouldRender && cullTooSmallMeshParts) { float distance = args->_viewFrustum->distanceToCamera(_calculatedMeshBoxes.at(i).calcCenter()); - shouldRender = Menu::getInstance()->shouldRenderMesh(_calculatedMeshBoxes.at(i).getLargestDimension(), + shouldRender = !_viewState ? false : _viewState->shouldRenderMesh(_calculatedMeshBoxes.at(i).getLargestDimension(), distance); if (!shouldRender) { args->_meshesTooSmall++; diff --git a/libraries/render-utils/src/ViewStateInterface.h b/libraries/render-utils/src/ViewStateInterface.h index 83501589d0..9110eb8eb6 100644 --- a/libraries/render-utils/src/ViewStateInterface.h +++ b/libraries/render-utils/src/ViewStateInterface.h @@ -37,6 +37,7 @@ public: virtual QThread* getMainThread() = 0; virtual const Transform& getViewTransform() const = 0; virtual void setupWorldLight() = 0; + virtual bool shouldRenderMesh(float largestDimension, float distanceToCamera) = 0; }; From cf6aa563ac30635a11444e69215256446ecf8b6d Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 16 Dec 2014 13:54:24 -0800 Subject: [PATCH 452/502] DM returns shared pointer --- libraries/shared/src/DependencyManager.cpp | 4 -- libraries/shared/src/DependencyManager.h | 51 ++++++++++------------ 2 files changed, 22 insertions(+), 33 deletions(-) diff --git a/libraries/shared/src/DependencyManager.cpp b/libraries/shared/src/DependencyManager.cpp index c858cb7059..43bb92258e 100644 --- a/libraries/shared/src/DependencyManager.cpp +++ b/libraries/shared/src/DependencyManager.cpp @@ -17,8 +17,4 @@ DependencyManager& DependencyManager::getInstance() { } DependencyManager::~DependencyManager() { - foreach (Dependency* instance, _instanceHash) { - delete instance; - } - _instanceHash.clear(); } \ No newline at end of file diff --git a/libraries/shared/src/DependencyManager.h b/libraries/shared/src/DependencyManager.h index 87c7c7b4a6..455ec38bca 100644 --- a/libraries/shared/src/DependencyManager.h +++ b/libraries/shared/src/DependencyManager.h @@ -12,55 +12,48 @@ #ifndef hifi_DependencyManager_h #define hifi_DependencyManager_h -#include -#include +#include #include -#include + +#define SINGLETON_DEPENDENCY(T)\ +public:\ + typedef QSharedPointer SharedPointer;\ +private:\ + void customDeleter() { delete this; }\ + friend class DependencyManager; + +class QObject; class DependencyManager { public: // Only accessible method. // usage: T* instance = DependencyManager::get(); template - static T* get(); - - // Any class T in the DependencyManager needs to subclass Dependency - // They also need to have protected constructor(s) and virtual destructor - // As well as declare DependencyManager a friend class - class Dependency { - protected: - Dependency() {} - virtual ~Dependency() {} // Ensure the proper destruction of the object - friend DependencyManager; - }; + static QSharedPointer get(); private: static DependencyManager& getInstance(); DependencyManager() {} ~DependencyManager(); - typedef QHash InstanceHash; - static InstanceHash& getInstanceHash() { return getInstance()._instanceHash; } - InstanceHash _instanceHash; + static void noDelete(void*) {} }; template -T* DependencyManager::get() { - const QString& typeId = typeid(T).name(); +QSharedPointer DependencyManager::get() { + static QSharedPointer sharedPointer; + static T* instance = new T(); - // Search the hash for global instance - Dependency* instance = getInstanceHash().value(typeId, NULL); if (instance) { - return dynamic_cast(instance); + if (dynamic_cast(instance)) { // If this is a QOject, call deleteLater for destruction + sharedPointer = QSharedPointer(instance, &T::deleteLater); + } else { // Otherwise use custom deleter to avoid issues between private destructor and QSharedPointer + sharedPointer = QSharedPointer(instance, &T::customDeleter); + } + instance = NULL; } - - // Found no instance in hash so we create one. - T* newInstance = new T(); - instance = dynamic_cast(newInstance); - assert(instance != NULL); // If this triggers, check that T is derived from Dependency - getInstanceHash().insert(typeId, instance); - return newInstance; + return sharedPointer; } #endif // hifi_DependencyManager_h From e8a22f6f0f31d3f2adcc08751492b160490d47ae Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 16 Dec 2014 13:54:52 -0800 Subject: [PATCH 453/502] Switched to chared pointers and macros --- interface/src/Application.cpp | 3 +-- interface/src/GLCanvas.h | 9 ++++++--- interface/src/devices/DdeFaceTracker.h | 2 +- interface/src/devices/Faceshift.h | 2 +- interface/src/devices/Visage.h | 2 +- 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 4c9fdcaf0f..50275fcd1c 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -194,7 +194,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : _isVSyncOn(true), _aboutToQuit(false) { - QSharedPointer glCanvas = DependencyManager::get(); + GLCanvas::SharedPointer glCanvas = DependencyManager::get(); // read the ApplicationInfo.ini file for Name/Version/Domain information QSettings applicationInfo(Application::resourcesPath() + "info/ApplicationInfo.ini", QSettings::IniFormat); @@ -442,7 +442,6 @@ void Application::aboutToQuit() { } Application::~Application() { - DependencyManager::get()->setParent(NULL); _entities.getTree()->setSimulation(NULL); qInstallMessageHandler(NULL); diff --git a/interface/src/GLCanvas.h b/interface/src/GLCanvas.h index 2b1cd3539d..420bf77467 100644 --- a/interface/src/GLCanvas.h +++ b/interface/src/GLCanvas.h @@ -18,8 +18,10 @@ #include /// customized canvas that simply forwards requests/events to the singleton application -class GLCanvas : public QGLWidget, public DependencyManager::Dependency { +class GLCanvas : public QGLWidget { Q_OBJECT + SINGLETON_DEPENDENCY(GLCanvas) + public: bool isThrottleRendering() const; @@ -60,8 +62,9 @@ private slots: private: GLCanvas(); - ~GLCanvas(); - friend class DependencyManager; + ~GLCanvas() { + qDebug() << "Deleting GLCanvas"; + } }; #endif // hifi_GLCanvas_h diff --git a/interface/src/devices/DdeFaceTracker.h b/interface/src/devices/DdeFaceTracker.h index 5ae17729d4..23a5d1fcc8 100644 --- a/interface/src/devices/DdeFaceTracker.h +++ b/interface/src/devices/DdeFaceTracker.h @@ -20,7 +20,7 @@ class DdeFaceTracker : public FaceTracker { Q_OBJECT - SINGLETON_DEPENDENCY + SINGLETON_DEPENDENCY(DdeFaceTracker) public: //initialization diff --git a/interface/src/devices/Faceshift.h b/interface/src/devices/Faceshift.h index 73971db49d..b6b942dfee 100644 --- a/interface/src/devices/Faceshift.h +++ b/interface/src/devices/Faceshift.h @@ -26,7 +26,7 @@ /// Handles interaction with the Faceshift software, which provides head position/orientation and facial features. class Faceshift : public FaceTracker { Q_OBJECT - SINGLETON_DEPENDENCY + SINGLETON_DEPENDENCY(Faceshift) public: void init(); diff --git a/interface/src/devices/Visage.h b/interface/src/devices/Visage.h index 38e337aada..c12ce3aabd 100644 --- a/interface/src/devices/Visage.h +++ b/interface/src/devices/Visage.h @@ -28,7 +28,7 @@ namespace VisageSDK { /// Handles input from the Visage webcam feature tracking software. class Visage : public FaceTracker { Q_OBJECT - SINGLETON_DEPENDENCY + SINGLETON_DEPENDENCY(Visage) public: void init(); From 85c89517349790edd7510c00457bb21fb97d82fd Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 16 Dec 2014 13:57:22 -0800 Subject: [PATCH 454/502] really remove the debug settings from Model rendering --- examples/developerMenuItems.js | 4 ---- interface/src/Menu.h | 3 --- interface/src/renderer/Model.cpp | 10 +++------- 3 files changed, 3 insertions(+), 14 deletions(-) diff --git a/examples/developerMenuItems.js b/examples/developerMenuItems.js index 34bd3b3a75..3a274c7083 100644 --- a/examples/developerMenuItems.js +++ b/examples/developerMenuItems.js @@ -23,12 +23,8 @@ function setupMenus() { Menu.addMenuItem({ menuName: "Developer > Entities", menuItemName: "Display Model Element Bounds", isCheckable: true, isChecked: false }); Menu.addMenuItem({ menuName: "Developer > Entities", menuItemName: "Display Model Element Children", isCheckable: true, isChecked: false }); Menu.addMenuItem({ menuName: "Developer > Entities", menuItemName: "Don't Do Precision Picking", isCheckable: true, isChecked: false }); - Menu.addMenuItem({ menuName: "Developer > Entities", menuItemName: "Don't Attempt to Reduce Material Switches", isCheckable: true, isChecked: false }); Menu.addMenuItem({ menuName: "Developer > Entities", menuItemName: "Don't Attempt Render Entities as Scene", isCheckable: true, isChecked: false }); Menu.addMenuItem({ menuName: "Developer > Entities", menuItemName: "Don't Do Precision Picking", isCheckable: true, isChecked: false }); - Menu.addMenu("Developer > Entities > Culling"); - Menu.addMenuItem({ menuName: "Developer > Entities > Culling", menuItemName: "Don't Cull Out Of View Mesh Parts", isCheckable: true, isChecked: false }); - Menu.addMenuItem({ menuName: "Developer > Entities > Culling", menuItemName: "Don't Cull Too Small Mesh Parts", isCheckable: true, isChecked: false }); Menu.addMenuItem({ menuName: "Developer > Entities", menuItemName: "Disable Light Entities", isCheckable: true, isChecked: false }); } } diff --git a/interface/src/Menu.h b/interface/src/Menu.h index e2c687fff1..77936e7ac4 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -361,9 +361,6 @@ namespace MenuOption { const QString Collisions = "Collisions"; const QString Console = "Console..."; const QString ControlWithSpeech = "Control With Speech"; - const QString DontCullOutOfViewMeshParts = "Don't Cull Out Of View Mesh Parts"; - const QString DontCullTooSmallMeshParts = "Don't Cull Too Small Mesh Parts"; - const QString DontReduceMaterialSwitches = "Don't Attempt to Reduce Material Switches"; const QString DontRenderEntitiesAsScene = "Don't Render Entities as Scene"; const QString DontDoPrecisionPicking = "Don't Do Precision Picking"; const QString DecreaseAvatarSize = "Decrease Avatar Size"; diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 2faeeeea55..5f160d2e8d 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -2333,9 +2333,6 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, RenderArgs* args, Locations* locations, SkinLocations* skinLocations) { PROFILE_RANGE(__FUNCTION__); - bool dontCullOutOfViewMeshParts = false; // Menu::getInstance()->isOptionChecked(MenuOption::DontCullOutOfViewMeshParts); - bool cullTooSmallMeshParts = true; // !Menu::getInstance()->isOptionChecked(MenuOption::DontCullTooSmallMeshParts); - bool dontReduceMaterialSwitches = false; // Menu::getInstance()->isOptionChecked(MenuOption::DontReduceMaterialSwitches); TextureCache* textureCache = DependencyManager::get(); GlowEffect* glowEffect = DependencyManager::get(); @@ -2373,9 +2370,8 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod args->_meshesConsidered++; if (args->_viewFrustum) { - shouldRender = dontCullOutOfViewMeshParts || - args->_viewFrustum->boxInFrustum(_calculatedMeshBoxes.at(i)) != ViewFrustum::OUTSIDE; - if (shouldRender && cullTooSmallMeshParts) { + shouldRender = args->_viewFrustum->boxInFrustum(_calculatedMeshBoxes.at(i)) != ViewFrustum::OUTSIDE; + if (shouldRender) { float distance = args->_viewFrustum->distanceToCamera(_calculatedMeshBoxes.at(i).calcCenter()); shouldRender = !_viewState ? false : _viewState->shouldRenderMesh(_calculatedMeshBoxes.at(i).getLargestDimension(), distance); @@ -2433,7 +2429,7 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0); } else { - if (dontReduceMaterialSwitches || lastMaterialID != part.materialID) { + if (lastMaterialID != part.materialID) { const bool wantDebug = false; if (wantDebug) { qDebug() << "Material Changed ---------------------------------------------"; From 4d1529f77bc875a87c10b2006e449425a98bbdb7 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 16 Dec 2014 14:02:22 -0800 Subject: [PATCH 455/502] typedefs --- interface/src/Application.cpp | 26 +++++++++---------- interface/src/Camera.cpp | 2 +- interface/src/Menu.cpp | 2 +- interface/src/avatar/Head.cpp | 4 +-- interface/src/avatar/MyAvatar.cpp | 2 +- interface/src/devices/OculusManager.cpp | 4 +-- interface/src/devices/PrioVR.cpp | 2 +- interface/src/devices/SixenseManager.cpp | 2 +- interface/src/devices/TV3DManager.cpp | 4 +-- interface/src/renderer/GlowEffect.cpp | 2 +- .../ControllerScriptingInterface.cpp | 2 +- interface/src/ui/ApplicationOverlay.cpp | 20 +++++++------- interface/src/ui/PreferencesDialog.cpp | 2 +- interface/src/ui/Snapshot.cpp | 2 +- interface/src/ui/Stats.cpp | 8 +++--- 15 files changed, 42 insertions(+), 42 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 50275fcd1c..5746f1f670 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1047,7 +1047,7 @@ void Application::keyPressEvent(QKeyEvent* event) { if (isShifted) { _viewFrustum.setFocalLength(_viewFrustum.getFocalLength() - 0.1f); if (TV3DManager::isConnected()) { - QSharedPointer glCanvas = DependencyManager::get(); + GLCanvas::SharedPointer glCanvas = DependencyManager::get(); TV3DManager::configureCamera(_myCamera, glCanvas->getDeviceWidth(), glCanvas->getDeviceHeight()); } } else { @@ -1060,7 +1060,7 @@ void Application::keyPressEvent(QKeyEvent* event) { if (isShifted) { _viewFrustum.setFocalLength(_viewFrustum.getFocalLength() + 0.1f); if (TV3DManager::isConnected()) { - QSharedPointer glCanvas = DependencyManager::get(); + GLCanvas::SharedPointer glCanvas = DependencyManager::get(); TV3DManager::configureCamera(_myCamera, glCanvas->getDeviceWidth(), glCanvas->getDeviceHeight()); } @@ -1533,7 +1533,7 @@ void Application::idle() { void Application::checkBandwidthMeterClick() { // ... to be called upon button release - QSharedPointer glCanvas = DependencyManager::get(); + GLCanvas::SharedPointer glCanvas = DependencyManager::get(); if (Menu::getInstance()->isOptionChecked(MenuOption::Bandwidth) && Menu::getInstance()->isOptionChecked(MenuOption::Stats) && Menu::getInstance()->isOptionChecked(MenuOption::UserInterface) && @@ -1569,7 +1569,7 @@ void Application::setFullscreen(bool fullscreen) { } void Application::setEnable3DTVMode(bool enable3DTVMode) { - QSharedPointer glCanvas = DependencyManager::get(); + GLCanvas::SharedPointer glCanvas = DependencyManager::get(); resizeGL(glCanvas->getDeviceWidth(), glCanvas->getDeviceHeight()); } @@ -1595,7 +1595,7 @@ void Application::setEnableVRMode(bool enableVRMode) { _myCamera.setHmdRotation(glm::quat()); } - QSharedPointer glCanvas = DependencyManager::get(); + GLCanvas::SharedPointer glCanvas = DependencyManager::get(); resizeGL(glCanvas->getDeviceWidth(), glCanvas->getDeviceHeight()); } @@ -1658,7 +1658,7 @@ glm::vec3 Application::getMouseVoxelWorldCoordinates(const VoxelDetail& mouseVox bool Application::mouseOnScreen() const { if (OculusManager::isConnected()) { - QSharedPointer glCanvas = DependencyManager::get(); + GLCanvas::SharedPointer glCanvas = DependencyManager::get(); return getMouseX() >= 0 && getMouseX() <= glCanvas->getDeviceWidth() && getMouseY() >= 0 && getMouseY() <= glCanvas->getDeviceHeight(); } @@ -1700,9 +1700,9 @@ int Application::getMouseDragStartedY() const { } FaceTracker* Application::getActiveFaceTracker() { - QSharedPointer faceshift = DependencyManager::get(); - QSharedPointer visage = DependencyManager::get(); - QSharedPointer dde = DependencyManager::get(); + Faceshift::SharedPointer faceshift = DependencyManager::get(); + Visage::SharedPointer visage = DependencyManager::get(); + DdeFaceTracker::SharedPointer dde = DependencyManager::get(); return (dde->isActive() ? static_cast(dde.data()) : (faceshift->isActive() ? static_cast(faceshift.data()) : @@ -2035,7 +2035,7 @@ void Application::init() { _metavoxels.init(); - QSharedPointer glCanvas = DependencyManager::get(); + GLCanvas::SharedPointer glCanvas = DependencyManager::get(); _audio.init(glCanvas.data()); _rearMirrorTools = new RearMirrorTools(glCanvas.data(), _mirrorViewRect, _settings); @@ -2116,7 +2116,7 @@ void Application::updateMouseRay() { void Application::updateFaceshift() { bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); PerformanceWarning warn(showWarnings, "Application::updateFaceshift()"); - Faceshift* faceshift = DependencyManager::get().data(); + Faceshift::SharedPointer faceshift = DependencyManager::get(); // Update faceshift faceshift->update(); @@ -2920,7 +2920,7 @@ void Application::updateShadowMap() { fbo->release(); - QSharedPointer glCanvas = DependencyManager::get(); + GLCanvas::SharedPointer glCanvas = DependencyManager::get(); glViewport(0, 0, glCanvas->getDeviceWidth(), glCanvas->getDeviceHeight()); } @@ -3248,7 +3248,7 @@ void Application::computeOffAxisFrustum(float& left, float& right, float& bottom } glm::vec2 Application::getScaledScreenPoint(glm::vec2 projectedPoint) { - QSharedPointer glCanvas = DependencyManager::get(); + GLCanvas::SharedPointer glCanvas = DependencyManager::get(); float horizontalScale = glCanvas->getDeviceWidth() / 2.0f; float verticalScale = glCanvas->getDeviceHeight() / 2.0f; diff --git a/interface/src/Camera.cpp b/interface/src/Camera.cpp index 181f783af1..b2fd30a1a6 100644 --- a/interface/src/Camera.cpp +++ b/interface/src/Camera.cpp @@ -95,7 +95,7 @@ void Camera::setFarClip(float f) { } PickRay Camera::computePickRay(float x, float y) { - QSharedPointer glCanvas = DependencyManager::get(); + GLCanvas::SharedPointer glCanvas = DependencyManager::get(); return computeViewPickRay(x / glCanvas->width(), y / glCanvas->height()); } diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 501da725e4..91f4460410 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -1050,7 +1050,7 @@ void Menu::bumpSettings() { void sendFakeEnterEvent() { QPoint lastCursorPosition = QCursor::pos(); - QSharedPointer glCanvas = DependencyManager::get(); + GLCanvas::SharedPointer glCanvas = DependencyManager::get(); QPoint windowPosition = glCanvas->mapFromGlobal(lastCursorPosition); QEnterEvent enterEvent = QEnterEvent(windowPosition, windowPosition, lastCursorPosition); diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index 150b67eb13..9a228899c5 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -77,8 +77,8 @@ void Head::simulate(float deltaTime, bool isMine, bool billboard) { // Only use face trackers when not playing back a recording. if (!myAvatar->isPlaying()) { FaceTracker* faceTracker = Application::getInstance()->getActiveFaceTracker(); - QSharedPointer dde = DependencyManager::get(); - QSharedPointer faceshift = DependencyManager::get(); + DdeFaceTracker::SharedPointer dde = DependencyManager::get(); + Faceshift::SharedPointer faceshift = DependencyManager::get(); if ((_isFaceshiftConnected = (faceshift == faceTracker))) { _blendshapeCoefficients = faceTracker->getBlendshapeCoefficients(); diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index a546560ffd..8e40cb8b30 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -422,7 +422,7 @@ void MyAvatar::render(const glm::vec3& cameraPosition, RenderMode renderMode, bo } void MyAvatar::renderHeadMouse(int screenWidth, int screenHeight) const { - QSharedPointer faceshift = DependencyManager::get(); + Faceshift::SharedPointer faceshift = DependencyManager::get(); float pixelsPerDegree = screenHeight / Menu::getInstance()->getFieldOfView(); diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index 99515cb7a9..15aa129b93 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -560,7 +560,7 @@ void OculusManager::display(const glm::quat &bodyOrientation, const glm::vec3 &p } // restore our normal viewport - QSharedPointer glCanvas = DependencyManager::get(); + GLCanvas::SharedPointer glCanvas = DependencyManager::get(); glViewport(0, 0, glCanvas->getDeviceWidth(), glCanvas->getDeviceHeight()); glMatrixMode(GL_PROJECTION); @@ -579,7 +579,7 @@ void OculusManager::display(const glm::quat &bodyOrientation, const glm::vec3 &p void OculusManager::renderDistortionMesh(ovrPosef eyeRenderPose[ovrEye_Count]) { glLoadIdentity(); - QSharedPointer glCanvas = DependencyManager::get(); + GLCanvas::SharedPointer glCanvas = DependencyManager::get(); gluOrtho2D(0, glCanvas->getDeviceWidth(), 0, glCanvas->getDeviceHeight()); glDisable(GL_DEPTH_TEST); diff --git a/interface/src/devices/PrioVR.cpp b/interface/src/devices/PrioVR.cpp index ab7c317c37..5ef94339ae 100644 --- a/interface/src/devices/PrioVR.cpp +++ b/interface/src/devices/PrioVR.cpp @@ -215,7 +215,7 @@ void PrioVR::renderCalibrationCountdown() { static TextRenderer* textRenderer = TextRenderer::getInstance(MONO_FONT_FAMILY, 18, QFont::Bold, false, TextRenderer::OUTLINE_EFFECT, 2); QByteArray text = "Assume T-Pose in " + QByteArray::number(secondsRemaining) + "..."; - QSharedPointer glCanvas = DependencyManager::get(); + GLCanvas::SharedPointer glCanvas = DependencyManager::get(); textRenderer->draw((glCanvas->width() - textRenderer->computeWidth(text.constData())) / 2, glCanvas->height() / 2, text); diff --git a/interface/src/devices/SixenseManager.cpp b/interface/src/devices/SixenseManager.cpp index 73e4f53289..e2b4fedd50 100644 --- a/interface/src/devices/SixenseManager.cpp +++ b/interface/src/devices/SixenseManager.cpp @@ -461,7 +461,7 @@ void SixenseManager::updateCalibration(const sixenseControllerData* controllers) void SixenseManager::emulateMouse(PalmData* palm, int index) { Application* application = Application::getInstance(); MyAvatar* avatar = application->getAvatar(); - QSharedPointer glCanvas = DependencyManager::get(); + GLCanvas::SharedPointer glCanvas = DependencyManager::get(); QPoint pos; Qt::MouseButton bumperButton; diff --git a/interface/src/devices/TV3DManager.cpp b/interface/src/devices/TV3DManager.cpp index 5c891224a8..e4723d26a0 100644 --- a/interface/src/devices/TV3DManager.cpp +++ b/interface/src/devices/TV3DManager.cpp @@ -33,7 +33,7 @@ bool TV3DManager::isConnected() { } void TV3DManager::connect() { - QSharedPointer glCanvas = DependencyManager::get(); + GLCanvas::SharedPointer glCanvas = DependencyManager::get(); int width = glCanvas->getDeviceWidth(); int height = glCanvas->getDeviceHeight(); Camera& camera = *Application::getInstance()->getCamera(); @@ -91,7 +91,7 @@ void TV3DManager::display(Camera& whichCamera) { // left eye portal int portalX = 0; int portalY = 0; - QSharedPointer glCanvas = DependencyManager::get(); + GLCanvas::SharedPointer glCanvas = DependencyManager::get(); QSize deviceSize = glCanvas->getDeviceSize() * Application::getInstance()->getRenderResolutionScale(); int portalW = deviceSize.width() / 2; diff --git a/interface/src/renderer/GlowEffect.cpp b/interface/src/renderer/GlowEffect.cpp index a760889eff..9f953eed60 100644 --- a/interface/src/renderer/GlowEffect.cpp +++ b/interface/src/renderer/GlowEffect.cpp @@ -139,7 +139,7 @@ QOpenGLFramebufferObject* GlowEffect::render(bool toTexture) { QOpenGLFramebufferObject* destFBO = toTexture ? Application::getInstance()->getTextureCache()->getSecondaryFramebufferObject() : NULL; - QSharedPointer glCanvas = DependencyManager::get(); + GLCanvas::SharedPointer glCanvas = DependencyManager::get(); if (!Menu::getInstance()->isOptionChecked(MenuOption::EnableGlowEffect) || _isEmpty) { // copy the primary to the screen if (destFBO && QOpenGLFramebufferObject::hasOpenGLFramebufferBlit()) { diff --git a/interface/src/scripting/ControllerScriptingInterface.cpp b/interface/src/scripting/ControllerScriptingInterface.cpp index a562236a92..545de00d7d 100644 --- a/interface/src/scripting/ControllerScriptingInterface.cpp +++ b/interface/src/scripting/ControllerScriptingInterface.cpp @@ -268,7 +268,7 @@ void ControllerScriptingInterface::releaseJoystick(int joystickIndex) { } glm::vec2 ControllerScriptingInterface::getViewportDimensions() const { - QSharedPointer glCanvas = DependencyManager::get(); + GLCanvas::SharedPointer glCanvas = DependencyManager::get(); return glm::vec2(glCanvas->width(), glCanvas->height()); } diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index c95dc08e79..f16777a28d 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -145,7 +145,7 @@ void ApplicationOverlay::renderOverlay(bool renderToTexture) { PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "ApplicationOverlay::displayOverlay()"); Application* application = Application::getInstance(); Overlays& overlays = application->getOverlays(); - QSharedPointer glCanvas = DependencyManager::get(); + GLCanvas::SharedPointer glCanvas = DependencyManager::get(); MyAvatar* myAvatar = application->getAvatar(); _textureFov = glm::radians(Menu::getInstance()->getOculusUIAngularSize()); @@ -213,7 +213,7 @@ void ApplicationOverlay::displayOverlayTexture() { if (_alpha == 0.0f) { return; } - QSharedPointer glCanvas = DependencyManager::get(); + GLCanvas::SharedPointer glCanvas = DependencyManager::get(); glEnable(GL_TEXTURE_2D); glActiveTexture(GL_TEXTURE0); @@ -378,7 +378,7 @@ void ApplicationOverlay::displayOverlayTexture3DTV(Camera& whichCamera, float as glEnd(); - QSharedPointer glCanvas = DependencyManager::get(); + GLCanvas::SharedPointer glCanvas = DependencyManager::get(); if (_crosshairTexture == 0) { _crosshairTexture = glCanvas->bindTexture(QImage(Application::resourcesPath() + "images/sixense-reticle.png")); } @@ -432,7 +432,7 @@ void ApplicationOverlay::computeOculusPickRay(float x, float y, glm::vec3& origi //Caculate the click location using one of the sixense controllers. Scale is not applied QPoint ApplicationOverlay::getPalmClickLocation(const PalmData *palm) const { Application* application = Application::getInstance(); - QSharedPointer glCanvas = DependencyManager::get(); + GLCanvas::SharedPointer glCanvas = DependencyManager::get(); MyAvatar* myAvatar = application->getAvatar(); glm::vec3 tip = myAvatar->getLaserPointerTipPosition(palm); @@ -511,7 +511,7 @@ bool ApplicationOverlay::calculateRayUICollisionPoint(const glm::vec3& position, //Renders optional pointers void ApplicationOverlay::renderPointers() { Application* application = Application::getInstance(); - QSharedPointer glCanvas = DependencyManager::get(); + GLCanvas::SharedPointer glCanvas = DependencyManager::get(); //lazily load crosshair texture if (_crosshairTexture == 0) { @@ -559,7 +559,7 @@ void ApplicationOverlay::renderPointers() { void ApplicationOverlay::renderControllerPointers() { Application* application = Application::getInstance(); - QSharedPointer glCanvas = DependencyManager::get(); + GLCanvas::SharedPointer glCanvas = DependencyManager::get(); MyAvatar* myAvatar = application->getAvatar(); //Static variables used for storing controller state @@ -704,7 +704,7 @@ void ApplicationOverlay::renderPointersOculus(const glm::vec3& eyePos) { //Renders a small magnification of the currently bound texture at the coordinates void ApplicationOverlay::renderMagnifier(glm::vec2 magPos, float sizeMult, bool showBorder) const { - QSharedPointer glCanvas = DependencyManager::get(); + GLCanvas::SharedPointer glCanvas = DependencyManager::get(); const int widgetWidth = glCanvas->width(); const int widgetHeight = glCanvas->height(); @@ -762,7 +762,7 @@ void ApplicationOverlay::renderAudioMeter() { Application* application = Application::getInstance(); - QSharedPointer glCanvas = DependencyManager::get(); + GLCanvas::SharedPointer glCanvas = DependencyManager::get(); Audio* audio = application->getAudio(); // Display a single screen-size quad to create an alpha blended 'collision' flash @@ -893,7 +893,7 @@ void ApplicationOverlay::renderStatsAndLogs() { Application* application = Application::getInstance(); - QSharedPointer glCanvas = DependencyManager::get(); + GLCanvas::SharedPointer glCanvas = DependencyManager::get(); const OctreePacketProcessor& octreePacketProcessor = application->getOctreePacketProcessor(); BandwidthMeter* bandwidthMeter = application->getBandwidthMeter(); NodeBounds& nodeBoundsDisplay = application->getNodeBoundsDisplay(); @@ -935,7 +935,7 @@ void ApplicationOverlay::renderDomainConnectionStatusBorder() { NodeList* nodeList = NodeList::getInstance(); if (nodeList && !nodeList->getDomainHandler().isConnected()) { - QSharedPointer glCanvas = DependencyManager::get(); + GLCanvas::SharedPointer glCanvas = DependencyManager::get(); int right = glCanvas->width(); int bottom = glCanvas->height(); diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index d39266e0fd..7baacd3d5a 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -215,7 +215,7 @@ void PreferencesDialog::savePreferences() { myAvatar->setClampedTargetScale(ui.avatarScaleSpin->value()); Application::getInstance()->getVoxels()->setMaxVoxels(ui.maxVoxelsSpin->value()); - QSharedPointer glCanvas = DependencyManager::get(); + GLCanvas::SharedPointer glCanvas = DependencyManager::get(); Application::getInstance()->resizeGL(glCanvas->width(), glCanvas->height()); Menu::getInstance()->setRealWorldFieldOfView(ui.realWorldFieldOfViewSpin->value()); diff --git a/interface/src/ui/Snapshot.cpp b/interface/src/ui/Snapshot.cpp index ddd2b93805..e3b512adcc 100644 --- a/interface/src/ui/Snapshot.cpp +++ b/interface/src/ui/Snapshot.cpp @@ -83,7 +83,7 @@ QTemporaryFile* Snapshot::saveTempSnapshot() { } QFile* Snapshot::savedFileForSnapshot(bool isTemporary) { - QSharedPointer glCanvas = DependencyManager::get(); + GLCanvas::SharedPointer glCanvas = DependencyManager::get(); QImage shot = glCanvas->grabFrameBuffer(); Avatar* avatar = Application::getInstance()->getAvatar(); diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index 2581866c70..be1fd88445 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -56,7 +56,7 @@ Stats::Stats(): _metavoxelReceiveProgress(0), _metavoxelReceiveTotal(0) { - QSharedPointer glCanvas = DependencyManager::get(); + GLCanvas::SharedPointer glCanvas = DependencyManager::get(); resetWidth(glCanvas->width(), 0); } @@ -67,7 +67,7 @@ void Stats::toggleExpanded() { // called on mouse click release // check for clicks over stats in order to expand or contract them void Stats::checkClick(int mouseX, int mouseY, int mouseDragStartedX, int mouseDragStartedY, int horizontalOffset) { - QSharedPointer glCanvas = DependencyManager::get(); + GLCanvas::SharedPointer glCanvas = DependencyManager::get(); if (0 != glm::compMax(glm::abs(glm::ivec2(mouseX - mouseDragStartedX, mouseY - mouseDragStartedY)))) { // not worried about dragging on stats @@ -122,7 +122,7 @@ void Stats::checkClick(int mouseX, int mouseY, int mouseDragStartedX, int mouseD } void Stats::resetWidth(int width, int horizontalOffset) { - QSharedPointer glCanvas = DependencyManager::get(); + GLCanvas::SharedPointer glCanvas = DependencyManager::get(); int extraSpace = glCanvas->width() - horizontalOffset -2 - STATS_GENERAL_MIN_WIDTH - (Menu::getInstance()->isOptionChecked(MenuOption::TestPing) ? STATS_PING_MIN_WIDTH -1 : 0) @@ -198,7 +198,7 @@ void Stats::display( int bytesPerSecond, int voxelPacketsToProcess) { - QSharedPointer glCanvas = DependencyManager::get(); + GLCanvas::SharedPointer glCanvas = DependencyManager::get(); unsigned int backgroundColor = 0x33333399; int verticalOffset = 0, lines = 0; From 89101872bbc94998a92bd41a8da543963450a11b Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 16 Dec 2014 14:04:39 -0800 Subject: [PATCH 456/502] move Model and AnimationHandle to libraries --- interface/src/avatar/FaceModel.h | 2 +- interface/src/avatar/Hand.h | 5 +++-- interface/src/avatar/ModelReferential.cpp | 3 +-- interface/src/avatar/MyAvatar.cpp | 2 +- interface/src/avatar/SkeletonModel.h | 3 ++- interface/src/avatar/SkeletonRagdoll.cpp | 2 +- interface/src/entities/EntityTreeRenderer.h | 2 +- interface/src/ui/overlays/ModelOverlay.h | 4 ++-- .../render-utils/src}/AnimationHandle.cpp | 0 .../render-utils/src}/AnimationHandle.h | 0 .../render-utils/src}/Model.cpp | 4 ++-- .../render-utils/src}/Model.h | 14 +++++++------- 12 files changed, 21 insertions(+), 20 deletions(-) rename {interface/src/renderer => libraries/render-utils/src}/AnimationHandle.cpp (100%) rename {interface/src/renderer => libraries/render-utils/src}/AnimationHandle.h (100%) rename {interface/src/renderer => libraries/render-utils/src}/Model.cpp (99%) rename {interface/src/renderer => libraries/render-utils/src}/Model.h (99%) diff --git a/interface/src/avatar/FaceModel.h b/interface/src/avatar/FaceModel.h index eaaa07e635..6c14beb587 100644 --- a/interface/src/avatar/FaceModel.h +++ b/interface/src/avatar/FaceModel.h @@ -12,7 +12,7 @@ #ifndef hifi_FaceModel_h #define hifi_FaceModel_h -#include "renderer/Model.h" +#include class Head; diff --git a/interface/src/avatar/Hand.h b/interface/src/avatar/Hand.h index ed2fa3e1ab..688af151b4 100644 --- a/interface/src/avatar/Hand.h +++ b/interface/src/avatar/Hand.h @@ -11,6 +11,8 @@ #ifndef hifi_Hand_h #define hifi_Hand_h +#include "InterfaceConfig.h" + #include #include @@ -22,9 +24,8 @@ #include #include #include +#include -#include "InterfaceConfig.h" -#include "renderer/Model.h" #include "world.h" diff --git a/interface/src/avatar/ModelReferential.cpp b/interface/src/avatar/ModelReferential.cpp index df6e272da7..5b72fddae7 100644 --- a/interface/src/avatar/ModelReferential.cpp +++ b/interface/src/avatar/ModelReferential.cpp @@ -10,9 +10,8 @@ // #include - #include -#include "../renderer/Model.h" +#include #include "ModelReferential.h" diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 057b1f1fc6..6976e26e86 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -40,7 +41,6 @@ #include "Recorder.h" #include "devices/Faceshift.h" #include "devices/OculusManager.h" -#include "renderer/AnimationHandle.h" #include "ui/TextRenderer.h" using namespace std; diff --git a/interface/src/avatar/SkeletonModel.h b/interface/src/avatar/SkeletonModel.h index ea732acfd5..0956d27b3f 100644 --- a/interface/src/avatar/SkeletonModel.h +++ b/interface/src/avatar/SkeletonModel.h @@ -12,9 +12,10 @@ #ifndef hifi_SkeletonModel_h #define hifi_SkeletonModel_h -#include "renderer/Model.h" #include +#include + #include "SkeletonRagdoll.h" class Avatar; diff --git a/interface/src/avatar/SkeletonRagdoll.cpp b/interface/src/avatar/SkeletonRagdoll.cpp index 7c0e056826..c944e0bd45 100644 --- a/interface/src/avatar/SkeletonRagdoll.cpp +++ b/interface/src/avatar/SkeletonRagdoll.cpp @@ -11,10 +11,10 @@ #include #include +#include #include "SkeletonRagdoll.h" #include "MuscleConstraint.h" -#include "../renderer/Model.h" SkeletonRagdoll::SkeletonRagdoll(Model* model) : Ragdoll(), _model(model) { assert(_model); diff --git a/interface/src/entities/EntityTreeRenderer.h b/interface/src/entities/EntityTreeRenderer.h index a8695db36d..87f45d5f56 100644 --- a/interface/src/entities/EntityTreeRenderer.h +++ b/interface/src/entities/EntityTreeRenderer.h @@ -17,6 +17,7 @@ #include #include // for RayToEntityIntersectionResult +#include #include #include #include @@ -25,7 +26,6 @@ #include #include -#include "renderer/Model.h" class EntityScriptDetails { public: diff --git a/interface/src/ui/overlays/ModelOverlay.h b/interface/src/ui/overlays/ModelOverlay.h index 567498feb5..8cd095f778 100644 --- a/interface/src/ui/overlays/ModelOverlay.h +++ b/interface/src/ui/overlays/ModelOverlay.h @@ -12,9 +12,9 @@ #ifndef hifi_ModelOverlay_h #define hifi_ModelOverlay_h -#include "Base3DOverlay.h" +#include -#include "../../renderer/Model.h" +#include "Base3DOverlay.h" class ModelOverlay : public Base3DOverlay { Q_OBJECT diff --git a/interface/src/renderer/AnimationHandle.cpp b/libraries/render-utils/src/AnimationHandle.cpp similarity index 100% rename from interface/src/renderer/AnimationHandle.cpp rename to libraries/render-utils/src/AnimationHandle.cpp diff --git a/interface/src/renderer/AnimationHandle.h b/libraries/render-utils/src/AnimationHandle.h similarity index 100% rename from interface/src/renderer/AnimationHandle.h rename to libraries/render-utils/src/AnimationHandle.h diff --git a/interface/src/renderer/Model.cpp b/libraries/render-utils/src/Model.cpp similarity index 99% rename from interface/src/renderer/Model.cpp rename to libraries/render-utils/src/Model.cpp index 5f160d2e8d..16e6b1bf02 100644 --- a/interface/src/renderer/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -19,9 +19,7 @@ #include #include -#include #include -#include #include #include #include @@ -31,6 +29,8 @@ #include #include "AnimationHandle.h" +#include "DeferredLightingEffect.h" +#include "GlowEffect.h" #include "Model.h" diff --git a/interface/src/renderer/Model.h b/libraries/render-utils/src/Model.h similarity index 99% rename from interface/src/renderer/Model.h rename to libraries/render-utils/src/Model.h index 2c6b0bd6ae..d24f349f81 100644 --- a/interface/src/renderer/Model.h +++ b/libraries/render-utils/src/Model.h @@ -21,16 +21,18 @@ #include #include #include -#include #include -#include +#include +#include #include -#include -#include #include -#include #include "AnimationHandle.h" +#include "GeometryCache.h" +#include "JointState.h" +#include "ProgramObject.h" +#include "TextureCache.h" +#include "ViewStateInterface.h" class QScriptEngine; @@ -38,8 +40,6 @@ class Shape; #include "RenderArgs.h" class ViewFrustum; -#include "gpu/Stream.h" -#include "gpu/Batch.h" /// A generic 3D model displaying geometry loaded from a URL. class Model : public QObject, public PhysicsEntity { From b449f650a0c4ac9bffef4511cf187be1fa13f2cd Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 16 Dec 2014 14:22:02 -0800 Subject: [PATCH 457/502] more Model cleanup --- interface/src/MetavoxelSystem.cpp | 2 +- interface/src/entities/RenderableLightEntityItem.cpp | 1 - interface/src/entities/RenderableModelEntityItem.h | 7 ++----- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/interface/src/MetavoxelSystem.cpp b/interface/src/MetavoxelSystem.cpp index d34bc4a594..443c55359b 100644 --- a/interface/src/MetavoxelSystem.cpp +++ b/interface/src/MetavoxelSystem.cpp @@ -23,6 +23,7 @@ #include #include +#include #include #include @@ -32,7 +33,6 @@ #include "Application.h" #include "MetavoxelSystem.h" -#include "renderer/Model.h" REGISTER_META_OBJECT(DefaultMetavoxelRendererImplementation) REGISTER_META_OBJECT(SphereRenderer) diff --git a/interface/src/entities/RenderableLightEntityItem.cpp b/interface/src/entities/RenderableLightEntityItem.cpp index 48996d5b4c..58a3c3f18a 100644 --- a/interface/src/entities/RenderableLightEntityItem.cpp +++ b/interface/src/entities/RenderableLightEntityItem.cpp @@ -34,7 +34,6 @@ void RenderableLightEntityItem::render(RenderArgs* args) { PerformanceTimer perfTimer("RenderableLightEntityItem::render"); assert(getType() == EntityTypes::Light); glm::vec3 position = getPositionInMeters(); - glm::vec3 center = getCenterInMeters(); glm::vec3 dimensions = getDimensions() * (float)TREE_SCALE; glm::quat rotation = getRotation(); float largestDiameter = glm::max(dimensions.x, dimensions.y, dimensions.z); diff --git a/interface/src/entities/RenderableModelEntityItem.h b/interface/src/entities/RenderableModelEntityItem.h index 2401d0ea64..2c194467d2 100644 --- a/interface/src/entities/RenderableModelEntityItem.h +++ b/interface/src/entities/RenderableModelEntityItem.h @@ -16,6 +16,8 @@ #include #include +#include +#include #include #include #include @@ -23,11 +25,6 @@ #include #include -#include "renderer/Model.h" - -#include -#include - class RenderableModelEntityItem : public ModelEntityItem { public: static EntityItem* factory(const EntityItemID& entityID, const EntityItemProperties& properties); From ee2ce718b473edeb613be6d5e3330d1f61fcfc59 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 16 Dec 2014 15:14:14 -0800 Subject: [PATCH 458/502] header file cleanup --- interface/src/entities/EntityTreeRenderer.h | 3 +++ .../src/entities/RenderableModelEntityItem.cpp | 8 +------- .../src/entities/RenderableModelEntityItem.h | 15 +++++---------- .../src/entities/RenderableSphereEntityItem.cpp | 8 +------- .../src/entities/RenderableSphereEntityItem.h | 12 +----------- .../src/entities/RenderableTextEntityItem.cpp | 6 ++---- interface/src/entities/RenderableTextEntityItem.h | 12 +----------- 7 files changed, 14 insertions(+), 50 deletions(-) diff --git a/interface/src/entities/EntityTreeRenderer.h b/interface/src/entities/EntityTreeRenderer.h index 87f45d5f56..215a9df975 100644 --- a/interface/src/entities/EntityTreeRenderer.h +++ b/interface/src/entities/EntityTreeRenderer.h @@ -18,6 +18,7 @@ #include #include // for RayToEntityIntersectionResult #include +#include #include #include #include @@ -26,6 +27,8 @@ #include #include +class ScriptEngine; + class EntityScriptDetails { public: diff --git a/interface/src/entities/RenderableModelEntityItem.cpp b/interface/src/entities/RenderableModelEntityItem.cpp index 13bc097f27..c998570a27 100644 --- a/interface/src/entities/RenderableModelEntityItem.cpp +++ b/interface/src/entities/RenderableModelEntityItem.cpp @@ -11,18 +11,12 @@ #include -#include +#include -#include "InterfaceConfig.h" - -#include #include -#include #include - #include "Menu.h" -#include "EntityTreeRenderer.h" #include "RenderableModelEntityItem.h" EntityItem* RenderableModelEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { diff --git a/interface/src/entities/RenderableModelEntityItem.h b/interface/src/entities/RenderableModelEntityItem.h index 2c194467d2..b68723019f 100644 --- a/interface/src/entities/RenderableModelEntityItem.h +++ b/interface/src/entities/RenderableModelEntityItem.h @@ -12,18 +12,13 @@ #ifndef hifi_RenderableModelEntityItem_h #define hifi_RenderableModelEntityItem_h -#include -#include +#include +#include -#include -#include #include -#include -#include -#include -#include -#include -#include + +class Model; +class RenderArgs; class RenderableModelEntityItem : public ModelEntityItem { public: diff --git a/interface/src/entities/RenderableSphereEntityItem.cpp b/interface/src/entities/RenderableSphereEntityItem.cpp index db10edca73..97e3ee7869 100644 --- a/interface/src/entities/RenderableSphereEntityItem.cpp +++ b/interface/src/entities/RenderableSphereEntityItem.cpp @@ -11,18 +11,12 @@ #include -#include - -#include "InterfaceConfig.h" +#include #include #include #include -#include - -#include "Menu.h" -#include "EntityTreeRenderer.h" #include "RenderableSphereEntityItem.h" EntityItem* RenderableSphereEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { diff --git a/interface/src/entities/RenderableSphereEntityItem.h b/interface/src/entities/RenderableSphereEntityItem.h index 3c24889e79..0c8c6af7c2 100644 --- a/interface/src/entities/RenderableSphereEntityItem.h +++ b/interface/src/entities/RenderableSphereEntityItem.h @@ -12,18 +12,8 @@ #ifndef hifi_RenderableSphereEntityItem_h #define hifi_RenderableSphereEntityItem_h -#include -#include - -#include -#include -#include -#include -#include -#include -#include - #include +class RenderArgs; class RenderableSphereEntityItem : public SphereEntityItem { public: diff --git a/interface/src/entities/RenderableTextEntityItem.cpp b/interface/src/entities/RenderableTextEntityItem.cpp index 4059ee5751..1f680a8a0d 100644 --- a/interface/src/entities/RenderableTextEntityItem.cpp +++ b/interface/src/entities/RenderableTextEntityItem.cpp @@ -11,14 +11,12 @@ #include -#include "InterfaceConfig.h" - -#include +#include #include -#include "Menu.h" #include "EntityTreeRenderer.h" #include "RenderableTextEntityItem.h" +#include "ui/TextRenderer.h" const int FIXED_FONT_POINT_SIZE = 40; const float LINE_SCALE_RATIO = 1.2f; diff --git a/interface/src/entities/RenderableTextEntityItem.h b/interface/src/entities/RenderableTextEntityItem.h index 8760cb9df7..7fe85d9ef5 100644 --- a/interface/src/entities/RenderableTextEntityItem.h +++ b/interface/src/entities/RenderableTextEntityItem.h @@ -12,18 +12,8 @@ #ifndef hifi_RenderableTextEntityItem_h #define hifi_RenderableTextEntityItem_h -#include -#include - -#include -#include -#include -#include -#include -#include -#include - #include +class RenderArgs; class RenderableTextEntityItem : public TextEntityItem { public: From b2dac6f53fdb8c90f2197589cb5f083ccd5713df Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 16 Dec 2014 15:32:11 -0800 Subject: [PATCH 459/502] DM users update --- interface/src/Application.cpp | 4 ++-- interface/src/Menu.cpp | 2 +- libraries/animation/src/AnimationCache.h | 4 ++-- libraries/render-utils/src/AmbientOcclusionEffect.h | 5 +++-- libraries/render-utils/src/DeferredLightingEffect.h | 5 +++-- libraries/render-utils/src/GlowEffect.cpp | 9 ++++----- libraries/render-utils/src/GlowEffect.h | 4 ++-- libraries/script-engine/src/ScriptEngine.cpp | 2 +- libraries/shared/src/DependencyManager.h | 2 +- 9 files changed, 19 insertions(+), 18 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index f677c46269..e7455ef71e 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2051,7 +2051,7 @@ void Application::init() { DependencyManager::get()->associateWithWidget(glCanvas.data()); // initialize the GlowEffect with our widget - DependencyManager::get()->init(glCanvas, + DependencyManager::get()->init(glCanvas.data(), Menu::getInstance()->isOptionChecked(MenuOption::EnableGlowEffect)); } @@ -4032,7 +4032,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri scriptEngine->registerGlobalObject("Menu", MenuScriptingInterface::getInstance()); scriptEngine->registerGlobalObject("Settings", SettingsScriptingInterface::getInstance()); scriptEngine->registerGlobalObject("AudioDevice", AudioDeviceScriptingInterface::getInstance()); - scriptEngine->registerGlobalObject("AnimationCache", DependencyManager::get()); + scriptEngine->registerGlobalObject("AnimationCache", DependencyManager::get().data()); scriptEngine->registerGlobalObject("SoundCache", &SoundCache::getInstance()); scriptEngine->registerGlobalObject("Account", AccountScriptingInterface::getInstance()); scriptEngine->registerGlobalObject("Metavoxels", &_metavoxels); diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 0521615257..f0c2a687a4 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -427,7 +427,7 @@ Menu::Menu() : appInstance, SLOT(setRenderVoxels(bool))); addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::EnableGlowEffect, 0, true, - DependencyManager::get(), SLOT(toggleGlowEffect(bool))); + DependencyManager::get().data(), SLOT(toggleGlowEffect(bool))); addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Wireframe, Qt::ALT | Qt::Key_W, false); addActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::LodTools, Qt::SHIFT | Qt::Key_L, this, SLOT(lodTools())); diff --git a/libraries/animation/src/AnimationCache.h b/libraries/animation/src/AnimationCache.h index 5f3f305461..4e67014822 100644 --- a/libraries/animation/src/AnimationCache.h +++ b/libraries/animation/src/AnimationCache.h @@ -24,8 +24,9 @@ class Animation; typedef QSharedPointer AnimationPointer; /// Scriptable interface for FBX animation loading. -class AnimationCache : public ResourceCache, public DependencyManager::Dependency { +class AnimationCache : public ResourceCache { Q_OBJECT + SINGLETON_DEPENDENCY(AnimationCache) public: Q_INVOKABLE AnimationPointer getAnimation(const QString& url) { return getAnimation(QUrl(url)); } @@ -38,7 +39,6 @@ protected: private: AnimationCache(QObject* parent = NULL); virtual ~AnimationCache() { } - friend class DependencyManager; }; diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.h b/libraries/render-utils/src/AmbientOcclusionEffect.h index 1ee7269480..421461860d 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.h +++ b/libraries/render-utils/src/AmbientOcclusionEffect.h @@ -20,7 +20,9 @@ class ProgramObject; /// A screen space ambient occlusion effect. See John Chapman's tutorial at /// http://john-chapman-graphics.blogspot.co.uk/2013/01/ssao-tutorial.html for reference. -class AmbientOcclusionEffect: public DependencyManager::Dependency { +class AmbientOcclusionEffect { + SINGLETON_DEPENDENCY(AmbientOcclusionEffect) + public: void init(ViewStateInterface* viewState); @@ -29,7 +31,6 @@ public: private: AmbientOcclusionEffect() {} virtual ~AmbientOcclusionEffect() {} - friend class DependencyManager; ProgramObject* _occlusionProgram; int _nearLocation; diff --git a/libraries/render-utils/src/DeferredLightingEffect.h b/libraries/render-utils/src/DeferredLightingEffect.h index 5dcd7d35f4..904f9827ea 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.h +++ b/libraries/render-utils/src/DeferredLightingEffect.h @@ -23,7 +23,9 @@ class PostLightingRenderable; /// Handles deferred lighting for the bits that require it (voxels, metavoxels...) -class DeferredLightingEffect: public DependencyManager::Dependency { +class DeferredLightingEffect { + SINGLETON_DEPENDENCY(DeferredLightingEffect) + public: void init(ViewStateInterface* viewState); @@ -73,7 +75,6 @@ public: private: DeferredLightingEffect() { } virtual ~DeferredLightingEffect() { } - friend class DependencyManager; class LightLocations { public: diff --git a/libraries/render-utils/src/GlowEffect.cpp b/libraries/render-utils/src/GlowEffect.cpp index 62e3a9d691..fb7189f61e 100644 --- a/libraries/render-utils/src/GlowEffect.cpp +++ b/libraries/render-utils/src/GlowEffect.cpp @@ -12,7 +12,6 @@ // include this before QOpenGLFramebufferObject, which includes an earlier version of OpenGL #include -#include #include #include @@ -157,7 +156,6 @@ QOpenGLFramebufferObject* GlowEffect::render(bool toTexture) { QOpenGLFramebufferObject* destFBO = toTexture ? textureCache->getSecondaryFramebufferObject() : NULL; - GLCanvas::SharedPointer glCanvas = DependencyManager::get(); if (!_enabled || _isEmpty) { // copy the primary to the screen if (destFBO && QOpenGLFramebufferObject::hasOpenGLFramebufferBlit()) { @@ -165,7 +163,7 @@ QOpenGLFramebufferObject* GlowEffect::render(bool toTexture) { } else { maybeBind(destFBO); if (!destFBO) { - glViewport(0, 0, glCanvas->getDeviceWidth(), glCanvas->getDeviceHeight()); + glViewport(0, 0, getDeviceWidth(), getDeviceHeight()); } glEnable(GL_TEXTURE_2D); glDisable(GL_LIGHTING); @@ -212,8 +210,9 @@ QOpenGLFramebufferObject* GlowEffect::render(bool toTexture) { } maybeBind(destFBO); if (!destFBO) { - glViewport(0, 0, glCanvas->getDeviceWidth(), glCanvas->getDeviceHeight()); - _addSeparateProgram->bind(); + glViewport(0, 0, getDeviceWidth(), getDeviceHeight()); + } + _addSeparateProgram->bind(); renderFullscreenQuad(); _addSeparateProgram->release(); maybeRelease(destFBO); diff --git a/libraries/render-utils/src/GlowEffect.h b/libraries/render-utils/src/GlowEffect.h index cc3e6e5867..37f29afb62 100644 --- a/libraries/render-utils/src/GlowEffect.h +++ b/libraries/render-utils/src/GlowEffect.h @@ -25,8 +25,9 @@ class QOpenGLFramebufferObject; class ProgramObject; /// A generic full screen glow effect. -class GlowEffect : public QObject, public DependencyManager::Dependency { +class GlowEffect : public QObject { Q_OBJECT + SINGLETON_DEPENDENCY(GlowEffect) public: @@ -60,7 +61,6 @@ public slots: private: GlowEffect(); virtual ~GlowEffect(); - friend class DependencyManager; int getDeviceWidth() const; int getDeviceHeight() const; diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index ec5f2bc0e7..6117da9d18 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -255,7 +255,7 @@ void ScriptEngine::init() { registerGlobalObject("Quat", &_quatLibrary); registerGlobalObject("Vec3", &_vec3Library); registerGlobalObject("Uuid", &_uuidLibrary); - registerGlobalObject("AnimationCache", DependencyManager::get()); + registerGlobalObject("AnimationCache", DependencyManager::get().data()); registerGlobalObject("Voxels", &_voxelsScriptingInterface); diff --git a/libraries/shared/src/DependencyManager.h b/libraries/shared/src/DependencyManager.h index 455ec38bca..d1a1896947 100644 --- a/libraries/shared/src/DependencyManager.h +++ b/libraries/shared/src/DependencyManager.h @@ -46,7 +46,7 @@ QSharedPointer DependencyManager::get() { static T* instance = new T(); if (instance) { - if (dynamic_cast(instance)) { // If this is a QOject, call deleteLater for destruction + if (dynamic_cast(instance) != NULL) { // If this is a QOject, call deleteLater for destruction sharedPointer = QSharedPointer(instance, &T::deleteLater); } else { // Otherwise use custom deleter to avoid issues between private destructor and QSharedPointer sharedPointer = QSharedPointer(instance, &T::customDeleter); From d385a7b8acb300061b40c42f7b3866dd62a7b7ee Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 16 Dec 2014 15:35:56 -0800 Subject: [PATCH 460/502] header file cleanup --- interface/src/entities/EntityTreeRenderer.cpp | 15 +++------------ interface/src/entities/EntityTreeRenderer.h | 12 +----------- .../src/entities/RenderableBoxEntityItem.cpp | 10 +--------- interface/src/entities/RenderableBoxEntityItem.h | 11 ----------- .../src/entities/RenderableLightEntityItem.cpp | 8 +------- .../src/entities/RenderableLightEntityItem.h | 11 ----------- .../src/entities/RenderableModelEntityItem.h | 1 - .../src/entities/RenderableSphereEntityItem.h | 1 - .../src/entities/RenderableTextEntityItem.cpp | 1 - interface/src/entities/RenderableTextEntityItem.h | 1 - interface/src/ui/overlays/LocalModelsOverlay.h | 4 ++-- 11 files changed, 8 insertions(+), 67 deletions(-) diff --git a/interface/src/entities/EntityTreeRenderer.cpp b/interface/src/entities/EntityTreeRenderer.cpp index 59b3f697c8..727a21c4c8 100644 --- a/interface/src/entities/EntityTreeRenderer.cpp +++ b/interface/src/entities/EntityTreeRenderer.cpp @@ -9,28 +9,19 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include + #include #include -#include - -#include "InterfaceConfig.h" - -#include #include -#include -#include +#include #include -#include - #include "Menu.h" -#include "NetworkAccessManager.h" #include "EntityTreeRenderer.h" -#include "devices/OculusManager.h" - #include "RenderableBoxEntityItem.h" #include "RenderableLightEntityItem.h" #include "RenderableModelEntityItem.h" diff --git a/interface/src/entities/EntityTreeRenderer.h b/interface/src/entities/EntityTreeRenderer.h index 215a9df975..1e0f4de125 100644 --- a/interface/src/entities/EntityTreeRenderer.h +++ b/interface/src/entities/EntityTreeRenderer.h @@ -12,24 +12,14 @@ #ifndef hifi_EntityTreeRenderer_h #define hifi_EntityTreeRenderer_h -#include -#include - #include #include // for RayToEntityIntersectionResult -#include #include -#include -#include #include -#include -#include -#include -#include +class Model; class ScriptEngine; - class EntityScriptDetails { public: QString scriptText; diff --git a/interface/src/entities/RenderableBoxEntityItem.cpp b/interface/src/entities/RenderableBoxEntityItem.cpp index f7b403bff2..bb0de0ce6d 100644 --- a/interface/src/entities/RenderableBoxEntityItem.cpp +++ b/interface/src/entities/RenderableBoxEntityItem.cpp @@ -11,21 +11,13 @@ #include -#include +#include -#include "InterfaceConfig.h" - -#include #include -#include #include - -#include "Menu.h" -#include "EntityTreeRenderer.h" #include "RenderableBoxEntityItem.h" - EntityItem* RenderableBoxEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { return new RenderableBoxEntityItem(entityID, properties); } diff --git a/interface/src/entities/RenderableBoxEntityItem.h b/interface/src/entities/RenderableBoxEntityItem.h index da4714f32b..c4495d2328 100644 --- a/interface/src/entities/RenderableBoxEntityItem.h +++ b/interface/src/entities/RenderableBoxEntityItem.h @@ -12,17 +12,6 @@ #ifndef hifi_RenderableBoxEntityItem_h #define hifi_RenderableBoxEntityItem_h -#include -#include - -#include -#include -#include -#include -#include -#include -#include - #include class RenderableBoxEntityItem : public BoxEntityItem { diff --git a/interface/src/entities/RenderableLightEntityItem.cpp b/interface/src/entities/RenderableLightEntityItem.cpp index 58a3c3f18a..be64fe7520 100644 --- a/interface/src/entities/RenderableLightEntityItem.cpp +++ b/interface/src/entities/RenderableLightEntityItem.cpp @@ -11,21 +11,15 @@ #include -#include - -#include "InterfaceConfig.h" +#include #include #include -#include - #include "Application.h" #include "Menu.h" -#include "EntityTreeRenderer.h" #include "RenderableLightEntityItem.h" - EntityItem* RenderableLightEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { return new RenderableLightEntityItem(entityID, properties); } diff --git a/interface/src/entities/RenderableLightEntityItem.h b/interface/src/entities/RenderableLightEntityItem.h index 2113f486cc..cfafb85983 100644 --- a/interface/src/entities/RenderableLightEntityItem.h +++ b/interface/src/entities/RenderableLightEntityItem.h @@ -12,17 +12,6 @@ #ifndef hifi_RenderableLightEntityItem_h #define hifi_RenderableLightEntityItem_h -#include -#include - -#include -#include -#include -#include -#include -#include -#include - #include class RenderableLightEntityItem : public LightEntityItem { diff --git a/interface/src/entities/RenderableModelEntityItem.h b/interface/src/entities/RenderableModelEntityItem.h index b68723019f..9e66e4ef40 100644 --- a/interface/src/entities/RenderableModelEntityItem.h +++ b/interface/src/entities/RenderableModelEntityItem.h @@ -18,7 +18,6 @@ #include class Model; -class RenderArgs; class RenderableModelEntityItem : public ModelEntityItem { public: diff --git a/interface/src/entities/RenderableSphereEntityItem.h b/interface/src/entities/RenderableSphereEntityItem.h index 0c8c6af7c2..3ed651b0ae 100644 --- a/interface/src/entities/RenderableSphereEntityItem.h +++ b/interface/src/entities/RenderableSphereEntityItem.h @@ -13,7 +13,6 @@ #define hifi_RenderableSphereEntityItem_h #include -class RenderArgs; class RenderableSphereEntityItem : public SphereEntityItem { public: diff --git a/interface/src/entities/RenderableTextEntityItem.cpp b/interface/src/entities/RenderableTextEntityItem.cpp index 1f680a8a0d..5a3d5df8f9 100644 --- a/interface/src/entities/RenderableTextEntityItem.cpp +++ b/interface/src/entities/RenderableTextEntityItem.cpp @@ -14,7 +14,6 @@ #include #include -#include "EntityTreeRenderer.h" #include "RenderableTextEntityItem.h" #include "ui/TextRenderer.h" diff --git a/interface/src/entities/RenderableTextEntityItem.h b/interface/src/entities/RenderableTextEntityItem.h index 7fe85d9ef5..e57ab0538a 100644 --- a/interface/src/entities/RenderableTextEntityItem.h +++ b/interface/src/entities/RenderableTextEntityItem.h @@ -13,7 +13,6 @@ #define hifi_RenderableTextEntityItem_h #include -class RenderArgs; class RenderableTextEntityItem : public TextEntityItem { public: diff --git a/interface/src/ui/overlays/LocalModelsOverlay.h b/interface/src/ui/overlays/LocalModelsOverlay.h index 39465de7f9..a82943a4a0 100644 --- a/interface/src/ui/overlays/LocalModelsOverlay.h +++ b/interface/src/ui/overlays/LocalModelsOverlay.h @@ -12,10 +12,10 @@ #ifndef hifi_LocalModelsOverlay_h #define hifi_LocalModelsOverlay_h -#include "entities/EntityTreeRenderer.h" - #include "Volume3DOverlay.h" +class EntityTreeRenderer; + class LocalModelsOverlay : public Volume3DOverlay { Q_OBJECT public: From 74a8f0059d0eb34a4fa1e20f0ddc6acf30a2931f Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 16 Dec 2014 15:43:24 -0800 Subject: [PATCH 461/502] some Application dependecy cleanup --- interface/src/entities/EntityTreeRenderer.cpp | 4 ---- interface/src/entities/EntityTreeRenderer.h | 2 -- 2 files changed, 6 deletions(-) diff --git a/interface/src/entities/EntityTreeRenderer.cpp b/interface/src/entities/EntityTreeRenderer.cpp index 727a21c4c8..951c214c44 100644 --- a/interface/src/entities/EntityTreeRenderer.cpp +++ b/interface/src/entities/EntityTreeRenderer.cpp @@ -29,10 +29,6 @@ #include "RenderableTextEntityItem.h" -QThread* EntityTreeRenderer::getMainThread() { - return Application::getInstance()->getEntities()->thread(); -} - EntityTreeRenderer::EntityTreeRenderer(bool wantScripts) : OctreeRenderer(), _wantScripts(wantScripts), diff --git a/interface/src/entities/EntityTreeRenderer.h b/interface/src/entities/EntityTreeRenderer.h index 1e0f4de125..b9fe516efd 100644 --- a/interface/src/entities/EntityTreeRenderer.h +++ b/interface/src/entities/EntityTreeRenderer.h @@ -57,8 +57,6 @@ public: /// clears the tree virtual void clear(); - static QThread* getMainThread(); - /// if a renderable entity item needs a model, we will allocate it for them Q_INVOKABLE Model* allocateModel(const QString& url); From 3f2b5aeca408f5fef82be452dd13c1182eed840e Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 16 Dec 2014 16:22:59 -0800 Subject: [PATCH 462/502] Cleaner destruction handling --- libraries/shared/src/DependencyManager.h | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/libraries/shared/src/DependencyManager.h b/libraries/shared/src/DependencyManager.h index d1a1896947..06a01058fd 100644 --- a/libraries/shared/src/DependencyManager.h +++ b/libraries/shared/src/DependencyManager.h @@ -20,7 +20,14 @@ public:\ typedef QSharedPointer SharedPointer;\ private:\ - void customDeleter() { delete this; }\ + void customDeleter() {\ + QObject* thisObject = dynamic_cast(this);\ + if (thisObject) {\ + thisObject->deleteLater();\ + } else {\ + delete this;\ + }\ + }\ friend class DependencyManager; class QObject; @@ -42,17 +49,7 @@ private: template QSharedPointer DependencyManager::get() { - static QSharedPointer sharedPointer; - static T* instance = new T(); - - if (instance) { - if (dynamic_cast(instance) != NULL) { // If this is a QOject, call deleteLater for destruction - sharedPointer = QSharedPointer(instance, &T::deleteLater); - } else { // Otherwise use custom deleter to avoid issues between private destructor and QSharedPointer - sharedPointer = QSharedPointer(instance, &T::customDeleter); - } - instance = NULL; - } + static QSharedPointer sharedPointer = QSharedPointer(new T(), &T::customDeleter); return sharedPointer; } From 3dfded89b8c172a4ad8f2a9b7a9f9ed58e91f725 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 16 Dec 2014 16:28:09 -0800 Subject: [PATCH 463/502] remove menu dependency from EntityTreeRenderer, some Application cleanup --- interface/src/Application.cpp | 16 ++- interface/src/Application.h | 3 + interface/src/entities/EntityTreeRenderer.cpp | 127 +++++++----------- interface/src/entities/EntityTreeRenderer.h | 15 ++- .../render-utils/src/ViewStateInterface.h | 3 + 5 files changed, 83 insertions(+), 81 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 8b3c5a2fa1..d8c7811b6a 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -155,9 +155,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : _voxelImporter(), _importSucceded(false), _sharedVoxelSystem(TREE_SCALE, DEFAULT_MAX_VOXELS_PER_SYSTEM, &_clipboard), - _entities(true), + _entities(true, this), _entityCollisionSystem(), - _entityClipboardRenderer(false), + _entityClipboardRenderer(false, this), _entityClipboard(), _wantToKillLocalVoxels(false), _viewFrustum(), @@ -2943,6 +2943,18 @@ bool Application::shouldRenderMesh(float largestDimension, float distanceToCamer return Menu::getInstance()->shouldRenderMesh(largestDimension, distanceToCamera); } +float Application::getSizeScale() const { + return Menu::getInstance()->getVoxelSizeScale(); +} + +int Application::getBoundaryLevelAdjust() const { + return Menu::getInstance()->getBoundaryLevelAdjust(); +} + +PickRay Application::computePickRay(float x, float y) { + return getCamera()->computePickRay(x, y); +} + QImage Application::renderAvatarBillboard() { DependencyManager::get()->getPrimaryFramebufferObject()->bind(); diff --git a/interface/src/Application.h b/interface/src/Application.h index 9aca90fac8..86683a6608 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -285,6 +285,9 @@ public: virtual bool getShadowsEnabled(); virtual bool getCascadeShadowsEnabled(); virtual QThread* getMainThread() { return thread(); } + virtual float getSizeScale() const; + virtual int getBoundaryLevelAdjust() const; + virtual PickRay computePickRay(float x, float y); NodeBounds& getNodeBoundsDisplay() { return _nodeBoundsDisplay; } diff --git a/interface/src/entities/EntityTreeRenderer.cpp b/interface/src/entities/EntityTreeRenderer.cpp index 951c214c44..6684daf7e8 100644 --- a/interface/src/entities/EntityTreeRenderer.cpp +++ b/interface/src/entities/EntityTreeRenderer.cpp @@ -18,8 +18,9 @@ #include #include #include +#include -#include "Menu.h" +#include "Application.h" #include "EntityTreeRenderer.h" #include "RenderableBoxEntityItem.h" @@ -29,11 +30,16 @@ #include "RenderableTextEntityItem.h" -EntityTreeRenderer::EntityTreeRenderer(bool wantScripts) : +EntityTreeRenderer::EntityTreeRenderer(bool wantScripts, ViewStateInterface* viewState) : OctreeRenderer(), _wantScripts(wantScripts), _entitiesScriptEngine(NULL), - _lastMouseEventValid(false) + _lastMouseEventValid(false), + _viewState(viewState), + _displayElementChildProxies(false), + _displayModelBounds(false), + _displayModelElementProxy(false), + _dontDoPrecisionPicking(false) { REGISTER_ENTITY_TYPE_WITH_FACTORY(Model, RenderableModelEntityItem::factory) REGISTER_ENTITY_TYPE_WITH_FACTORY(Box, RenderableBoxEntityItem::factory) @@ -63,7 +69,7 @@ void EntityTreeRenderer::init() { entityTree->setFBXService(this); if (_wantScripts) { - _entitiesScriptEngine = new ScriptEngine(NO_SCRIPT, "Entities", + _entitiesScriptEngine = new ScriptEngine(NO_SCRIPT, "Entities", Application::getInstance()->getControllerScriptingInterface()); Application::getInstance()->registerScriptEngineWithApplicationServices(_entitiesScriptEngine); } @@ -276,44 +282,38 @@ void EntityTreeRenderer::checkEnterLeaveEntities() { } void EntityTreeRenderer::render(RenderArgs::RenderMode renderMode, RenderArgs::RenderSide renderSide) { - bool dontRenderAsScene = Menu::getInstance()->isOptionChecked(MenuOption::DontRenderEntitiesAsScene); + if (_tree) { + Model::startScene(renderSide); + RenderArgs args = { this, _viewFrustum, getSizeScale(), getBoundaryLevelAdjust(), renderMode, renderSide, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + _tree->lockForRead(); + _tree->recurseTreeWithOperation(renderOperation, &args); + + Model::RenderMode modelRenderMode = renderMode == RenderArgs::SHADOW_RENDER_MODE + ? Model::SHADOW_RENDER_MODE : Model::DEFAULT_RENDER_MODE; + + // we must call endScene while we still have the tree locked so that no one deletes a model + // on us while rendering the scene + Model::endScene(modelRenderMode, &args); + _tree->unlock(); - if (dontRenderAsScene) { - OctreeRenderer::render(renderMode, renderSide); - } else { - if (_tree) { - Model::startScene(renderSide); - RenderArgs args = { this, _viewFrustum, getSizeScale(), getBoundaryLevelAdjust(), renderMode, renderSide, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - _tree->lockForRead(); - _tree->recurseTreeWithOperation(renderOperation, &args); + // stats... + _meshesConsidered = args._meshesConsidered; + _meshesRendered = args._meshesRendered; + _meshesOutOfView = args._meshesOutOfView; + _meshesTooSmall = args._meshesTooSmall; - Model::RenderMode modelRenderMode = renderMode == RenderArgs::SHADOW_RENDER_MODE - ? Model::SHADOW_RENDER_MODE : Model::DEFAULT_RENDER_MODE; + _elementsTouched = args._elementsTouched; + _itemsRendered = args._itemsRendered; + _itemsOutOfView = args._itemsOutOfView; + _itemsTooSmall = args._itemsTooSmall; - // we must call endScene while we still have the tree locked so that no one deletes a model - // on us while rendering the scene - Model::endScene(modelRenderMode, &args); - _tree->unlock(); - - // stats... - _meshesConsidered = args._meshesConsidered; - _meshesRendered = args._meshesRendered; - _meshesOutOfView = args._meshesOutOfView; - _meshesTooSmall = args._meshesTooSmall; + _materialSwitches = args._materialSwitches; + _trianglesRendered = args._trianglesRendered; + _quadsRendered = args._quadsRendered; - _elementsTouched = args._elementsTouched; - _itemsRendered = args._itemsRendered; - _itemsOutOfView = args._itemsOutOfView; - _itemsTooSmall = args._itemsTooSmall; - - _materialSwitches = args._materialSwitches; - _trianglesRendered = args._trianglesRendered; - _quadsRendered = args._quadsRendered; - - _translucentMeshPartsRendered = args._translucentMeshPartsRendered; - _opaqueMeshPartsRendered = args._opaqueMeshPartsRendered; - } + _translucentMeshPartsRendered = args._translucentMeshPartsRendered; + _opaqueMeshPartsRendered = args._opaqueMeshPartsRendered; } deleteReleasedModels(); // seems like as good as any other place to do some memory cleanup } @@ -345,7 +345,7 @@ const Model* EntityTreeRenderer::getModelForEntityItem(const EntityItem* entityI return result; } -void renderElementProxy(EntityTreeElement* entityTreeElement) { +void EntityTreeRenderer::renderElementProxy(EntityTreeElement* entityTreeElement) { glm::vec3 elementCenter = entityTreeElement->getAACube().calcCenter() * (float) TREE_SCALE; float elementSize = entityTreeElement->getScale() * (float) TREE_SCALE; glColor3f(1.0f, 0.0f, 0.0f); @@ -354,9 +354,7 @@ void renderElementProxy(EntityTreeElement* entityTreeElement) { glutWireCube(elementSize); glPopMatrix(); - bool displayElementChildProxies = Menu::getInstance()->isOptionChecked(MenuOption::DisplayModelElementChildProxies); - - if (displayElementChildProxies) { + if (_displayElementChildProxies) { // draw the children float halfSize = elementSize / 2.0f; float quarterSize = elementSize / 4.0f; @@ -412,8 +410,7 @@ void renderElementProxy(EntityTreeElement* entityTreeElement) { void EntityTreeRenderer::renderProxies(const EntityItem* entity, RenderArgs* args) { bool isShadowMode = args->_renderMode == RenderArgs::SHADOW_RENDER_MODE; - bool displayModelBounds = Menu::getInstance()->isOptionChecked(MenuOption::DisplayModelBounds); - if (!isShadowMode && displayModelBounds) { + if (!isShadowMode && _displayModelBounds) { PerformanceTimer perfTimer("renderProxies"); AACube maxCube = entity->getMaximumAACube(); @@ -473,8 +470,6 @@ void EntityTreeRenderer::renderProxies(const EntityItem* entity, RenderArgs* arg } void EntityTreeRenderer::renderElement(OctreeElement* element, RenderArgs* args) { - bool wantDebug = false; - args->_elementsTouched++; // actually render it here... // we need to iterate the actual entityItems of the element @@ -486,11 +481,8 @@ void EntityTreeRenderer::renderElement(OctreeElement* element, RenderArgs* args) uint16_t numberOfEntities = entityItems.size(); bool isShadowMode = args->_renderMode == RenderArgs::SHADOW_RENDER_MODE; - bool displayElementProxy = Menu::getInstance()->isOptionChecked(MenuOption::DisplayModelElementProxy); - - - if (!isShadowMode && displayElementProxy && numberOfEntities > 0) { + if (!isShadowMode && _displayModelElementProxy && numberOfEntities > 0) { renderElementProxy(entityTreeElement); } @@ -507,23 +499,9 @@ void EntityTreeRenderer::renderElement(OctreeElement* element, RenderArgs* args) // when they are outside of the view frustum... float distance = args->_viewFrustum->distanceToCamera(entityBox.calcCenter()); - if (wantDebug) { - qDebug() << "------- renderElement() ----------"; - qDebug() << " type:" << EntityTypes::getEntityTypeName(entityItem->getType()); - if (entityItem->getType() == EntityTypes::Model) { - ModelEntityItem* modelEntity = static_cast(entityItem); - qDebug() << " url:" << modelEntity->getModelURL(); - } - qDebug() << " entityBox:" << entityItem->getAABox(); - qDebug() << " dimensions:" << entityItem->getDimensionsInMeters() << "in meters"; - qDebug() << " largestDimension:" << entityBox.getLargestDimension() << "in meters"; - qDebug() << " shouldRender:" << Menu::getInstance()->shouldRenderMesh(entityBox.getLargestDimension(), distance); - qDebug() << " in frustum:" << (args->_viewFrustum->boxInFrustum(entityBox) != ViewFrustum::OUTSIDE); - } - bool outOfView = args->_viewFrustum->boxInFrustum(entityBox) == ViewFrustum::OUTSIDE; if (!outOfView) { - bool bigEnoughToRender = Menu::getInstance()->shouldRenderMesh(entityBox.getLargestDimension(), distance); + bool bigEnoughToRender = _viewState->shouldRenderMesh(entityBox.getLargestDimension(), distance); if (bigEnoughToRender) { renderProxies(entityItem, args); @@ -548,11 +526,11 @@ void EntityTreeRenderer::renderElement(OctreeElement* element, RenderArgs* args) } float EntityTreeRenderer::getSizeScale() const { - return Menu::getInstance()->getVoxelSizeScale(); + return _viewState->getSizeScale(); } int EntityTreeRenderer::getBoundaryLevelAdjust() const { - return Menu::getInstance()->getBoundaryLevelAdjust(); + return _viewState->getBoundaryLevelAdjust(); } @@ -627,11 +605,6 @@ void EntityTreeRenderer::deleteReleasedModels() { } } -PickRay EntityTreeRenderer::computePickRay(float x, float y) { - return Application::getInstance()->getCamera()->computePickRay(x, y); -} - - RayToEntityIntersectionResult EntityTreeRenderer::findRayIntersectionWorker(const PickRay& ray, Octree::lockType lockType, bool precisionPicking) { RayToEntityIntersectionResult result; @@ -693,9 +666,9 @@ QScriptValueList EntityTreeRenderer::createEntityArgs(const EntityItemID& entity void EntityTreeRenderer::mousePressEvent(QMouseEvent* event, unsigned int deviceID) { PerformanceTimer perfTimer("EntityTreeRenderer::mousePressEvent"); - PickRay ray = computePickRay(event->x(), event->y()); + PickRay ray = _viewState->computePickRay(event->x(), event->y()); - bool precisionPicking = !Menu::getInstance()->isOptionChecked(MenuOption::DontDoPrecisionPicking); + bool precisionPicking = !_dontDoPrecisionPicking; RayToEntityIntersectionResult rayPickResult = findRayIntersectionWorker(ray, Octree::Lock, precisionPicking); if (rayPickResult.intersects) { //qDebug() << "mousePressEvent over entity:" << rayPickResult.entityID; @@ -719,8 +692,8 @@ void EntityTreeRenderer::mousePressEvent(QMouseEvent* event, unsigned int device void EntityTreeRenderer::mouseReleaseEvent(QMouseEvent* event, unsigned int deviceID) { PerformanceTimer perfTimer("EntityTreeRenderer::mouseReleaseEvent"); - PickRay ray = computePickRay(event->x(), event->y()); - bool precisionPicking = !Menu::getInstance()->isOptionChecked(MenuOption::DontDoPrecisionPicking); + PickRay ray = _viewState->computePickRay(event->x(), event->y()); + bool precisionPicking = !_dontDoPrecisionPicking; RayToEntityIntersectionResult rayPickResult = findRayIntersectionWorker(ray, Octree::Lock, precisionPicking); if (rayPickResult.intersects) { //qDebug() << "mouseReleaseEvent over entity:" << rayPickResult.entityID; @@ -754,7 +727,7 @@ void EntityTreeRenderer::mouseReleaseEvent(QMouseEvent* event, unsigned int devi void EntityTreeRenderer::mouseMoveEvent(QMouseEvent* event, unsigned int deviceID) { PerformanceTimer perfTimer("EntityTreeRenderer::mouseMoveEvent"); - PickRay ray = computePickRay(event->x(), event->y()); + PickRay ray = _viewState->computePickRay(event->x(), event->y()); bool precisionPicking = false; // for mouse moves we do not do precision picking RayToEntityIntersectionResult rayPickResult = findRayIntersectionWorker(ray, Octree::TryLock, precisionPicking); diff --git a/interface/src/entities/EntityTreeRenderer.h b/interface/src/entities/EntityTreeRenderer.h index b9fe516efd..c3bd77aba7 100644 --- a/interface/src/entities/EntityTreeRenderer.h +++ b/interface/src/entities/EntityTreeRenderer.h @@ -30,7 +30,7 @@ public: class EntityTreeRenderer : public OctreeRenderer, public EntityItemFBXService { Q_OBJECT public: - EntityTreeRenderer(bool wantScripts); + EntityTreeRenderer(bool wantScripts, ViewStateInterface* viewState); virtual ~EntityTreeRenderer(); virtual char getMyNodeType() const { return NodeType::EntityServer; } @@ -100,17 +100,22 @@ public slots: void entityCollisionWithVoxel(const EntityItemID& entityID, const VoxelDetail& voxel, const Collision& collision); void entityCollisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const Collision& collision); + // optional slots that can be wired to menu items + void setDisplayElementChildProxies(bool value) { _displayElementChildProxies = value; } + void setDisplayModelBounds(bool value) { _displayModelBounds = value; } + void setDisplayModelElementProxy(bool value) { _displayModelElementProxy = value; } + void setDontDoPrecisionPicking(bool value) { _dontDoPrecisionPicking = value; } protected: virtual Octree* createTree() { return new EntityTree(true); } private: + void renderElementProxy(EntityTreeElement* entityTreeElement); void checkAndCallPreload(const EntityItemID& entityID); void checkAndCallUnload(const EntityItemID& entityID); QList _releasedModels; void renderProxies(const EntityItem* entity, RenderArgs* args); - PickRay computePickRay(float x, float y); RayToEntityIntersectionResult findRayIntersectionWorker(const PickRay& ray, Octree::lockType lockType, bool precisionPicking); @@ -136,6 +141,12 @@ private: bool _lastMouseEventValid; MouseEvent _lastMouseEvent; + ViewStateInterface* _viewState; + bool _displayElementChildProxies; + bool _displayModelBounds; + bool _displayModelElementProxy; + bool _dontDoPrecisionPicking; + }; #endif // hifi_EntityTreeRenderer_h diff --git a/libraries/render-utils/src/ViewStateInterface.h b/libraries/render-utils/src/ViewStateInterface.h index 9110eb8eb6..5f85e998a4 100644 --- a/libraries/render-utils/src/ViewStateInterface.h +++ b/libraries/render-utils/src/ViewStateInterface.h @@ -38,6 +38,9 @@ public: virtual const Transform& getViewTransform() const = 0; virtual void setupWorldLight() = 0; virtual bool shouldRenderMesh(float largestDimension, float distanceToCamera) = 0; + virtual float getSizeScale() const = 0; + virtual int getBoundaryLevelAdjust() const = 0; + virtual PickRay computePickRay(float x, float y) = 0; }; From 6304a5e819e1cb06423f85b62e3ea3fa56d83f86 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 16 Dec 2014 16:50:15 -0800 Subject: [PATCH 464/502] Unused removed method --- libraries/shared/src/DependencyManager.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/libraries/shared/src/DependencyManager.h b/libraries/shared/src/DependencyManager.h index 06a01058fd..fdf8030199 100644 --- a/libraries/shared/src/DependencyManager.h +++ b/libraries/shared/src/DependencyManager.h @@ -42,9 +42,7 @@ public: private: static DependencyManager& getInstance(); DependencyManager() {} - ~DependencyManager(); - - static void noDelete(void*) {} + ~DependencyManager(); }; template From 77bc00e4105f0aae31d64abb817516d8375e0a94 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 16 Dec 2014 18:34:39 -0800 Subject: [PATCH 465/502] a simple model for persistent scripts in domain-server --- .../resources/describe-settings.json | 27 +++++++++ domain-server/resources/web/js/settings.js | 8 ++- domain-server/src/DomainServer.cpp | 59 ++++++++++--------- domain-server/src/DomainServer.h | 2 +- 4 files changed, 64 insertions(+), 32 deletions(-) diff --git a/domain-server/resources/describe-settings.json b/domain-server/resources/describe-settings.json index 50de26c518..ae6f116537 100644 --- a/domain-server/resources/describe-settings.json +++ b/domain-server/resources/describe-settings.json @@ -76,6 +76,33 @@ } ] }, + { + "name": "scripts", + "label": "Scripts", + "settings": [ + { + "name": "persistent_scripts", + "type": "table", + "label": "Persistent Scripts", + "help": "Add the URLs for scripts that you would like to ensure are always running in your domain.", + "columns": [ + { + "name": "url", + "label": "Script URL" + }, + { + "name": "num_instances", + "label": "# instances", + "default": 1 + }, + { + "name": "pool", + "label": "Pool" + } + ] + } + ] + }, { "name": "audio_env", "label": "Audio Environment", diff --git a/domain-server/resources/web/js/settings.js b/domain-server/resources/web/js/settings.js index a27965abce..141bd72a26 100644 --- a/domain-server/resources/web/js/settings.js +++ b/domain-server/resources/web/js/settings.js @@ -363,7 +363,8 @@ function makeTableInputs(setting) { _.each(setting.columns, function(col) { html += "\ - \ + \ " }) @@ -389,8 +390,9 @@ function badgeSidebarForDifferences(changedElement) { // badge for any settings we have that are not the same or are not present in initialValues for (var setting in panelJSON) { - if (!_.isEqual(panelJSON[setting], initialPanelJSON[setting]) - && (panelJSON[setting] !== "" || _.has(initialPanelJSON, setting))) { + if ((!_.has(initialPanelJSON, setting) && panelJSON[setting] !== "") || + (!_.isEqual(panelJSON[setting], initialPanelJSON[setting]) + && (panelJSON[setting] !== "" || _.has(initialPanelJSON, setting)))) { badgeValue += 1 } } diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index bf9505671b..470b69be01 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -233,6 +233,9 @@ void DomainServer::setupNodeListAndAssignments(const QUuid& sessionUUID) { parseAssignmentConfigs(parsedTypes); populateDefaultStaticAssignmentsExcludingTypes(parsedTypes); + + // check for scripts the user wants to persist from their domain-server config + populateStaticScriptedAssignmentsFromSettings(); LimitedNodeList* nodeList = LimitedNodeList::createInstance(domainServerPort, domainServerDTLSPort); @@ -451,8 +454,6 @@ void DomainServer::parseAssignmentConfigs(QSet& excludedTypes) if (assignmentType != Assignment::AgentType) { createStaticAssignmentsForType(assignmentType, assignmentList); - } else { - createScriptedAssignmentsFromList(assignmentList); } excludedTypes.insert(assignmentType); @@ -468,35 +469,37 @@ void DomainServer::addStaticAssignmentToAssignmentHash(Assignment* newAssignment _allAssignments.insert(newAssignment->getUUID(), SharedAssignmentPointer(newAssignment)); } -void DomainServer::createScriptedAssignmentsFromList(const QVariantList &configList) { - foreach(const QVariant& configVariant, configList) { - if (configVariant.canConvert(QMetaType::QVariantMap)) { - QVariantMap configMap = configVariant.toMap(); - - // make sure we were passed a URL, otherwise this is an invalid scripted assignment - const QString ASSIGNMENT_URL_KEY = "url"; - QString assignmentURL = configMap[ASSIGNMENT_URL_KEY].toString(); - - if (!assignmentURL.isEmpty()) { - // check the json for a pool - const QString ASSIGNMENT_POOL_KEY = "pool"; - QString assignmentPool = configMap[ASSIGNMENT_POOL_KEY].toString(); - - // check for a number of instances, if not passed then default is 1 - const QString ASSIGNMENT_INSTANCES_KEY = "instances"; - int numInstances = configMap[ASSIGNMENT_INSTANCES_KEY].toInt(); - numInstances = (numInstances == 0 ? 1 : numInstances); - - qDebug() << "Adding a static scripted assignment from" << assignmentURL; - - for (int i = 0; i < numInstances; i++) { +void DomainServer::populateStaticScriptedAssignmentsFromSettings() { + const QString PERSISTENT_SCRIPTS_KEY_PATH = "scripts.persistent_scripts"; + const QVariant* persistentScriptsVariant = valueForKeyPath(_settingsManager.getSettingsMap(), PERSISTENT_SCRIPTS_KEY_PATH); + + if (persistentScriptsVariant) { + QVariantList persistentScriptsList = persistentScriptsVariant->toList(); + foreach(const QVariant& persistentScriptVariant, persistentScriptsList) { + QVariantMap persistentScript = persistentScriptVariant.toMap(); + + const QString PERSISTENT_SCRIPT_URL_KEY = "url"; + const QString PERSISTENT_SCRIPT_NUM_INSTANCES_KEY = "num_instances"; + const QString PERSISTENT_SCRIPT_POOL_KEY = "pool"; + + if (persistentScript.contains(PERSISTENT_SCRIPT_URL_KEY)) { + // check how many instances of this script to add + + int numInstances = persistentScript[PERSISTENT_SCRIPT_NUM_INSTANCES_KEY].toInt(); + QString scriptURL = persistentScript[PERSISTENT_SCRIPT_URL_KEY].toString(); + + QString scriptPool = persistentScript.value(PERSISTENT_SCRIPT_POOL_KEY).toString(); + + qDebug() << "Adding" << numInstances << "of persistent script at URL" << scriptURL << "- pool" << scriptPool; + + for (int i = 0; i < numInstances; ++i) { // add a scripted assignment to the queue for this instance Assignment* scriptAssignment = new Assignment(Assignment::CreateCommand, Assignment::AgentType, - assignmentPool); - scriptAssignment->setPayload(assignmentURL.toUtf8()); - - // scripts passed on CL or via JSON are static - so they are added back to the queue if the node dies + scriptPool); + scriptAssignment->setPayload(scriptURL.toUtf8()); + + // add it to static hash so we know we have to keep giving it back out addStaticAssignmentToAssignmentHash(scriptAssignment); } } diff --git a/domain-server/src/DomainServer.h b/domain-server/src/DomainServer.h index 76ab562f74..f910534eb1 100644 --- a/domain-server/src/DomainServer.h +++ b/domain-server/src/DomainServer.h @@ -100,9 +100,9 @@ private: void parseAssignmentConfigs(QSet& excludedTypes); void addStaticAssignmentToAssignmentHash(Assignment* newAssignment); - void createScriptedAssignmentsFromList(const QVariantList& configList); void createStaticAssignmentsForType(Assignment::Type type, const QVariantList& configList); void populateDefaultStaticAssignmentsExcludingTypes(const QSet& excludedTypes); + void populateStaticScriptedAssignmentsFromSettings(); SharedAssignmentPointer matchingQueuedAssignmentForCheckIn(const QUuid& checkInUUID, NodeType_t nodeType); SharedAssignmentPointer deployableAssignmentForRequest(const Assignment& requestAssignment); From b95eac759e5550330d25474bd52237ab3e1f2b76 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 17 Dec 2014 08:52:48 -0800 Subject: [PATCH 466/502] Fix minor grid spacing not updating --- examples/libraries/gridTool.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/libraries/gridTool.js b/examples/libraries/gridTool.js index 622822e108..b1c258dc31 100644 --- a/examples/libraries/gridTool.js +++ b/examples/libraries/gridTool.js @@ -195,7 +195,7 @@ Grid = function(opts) { Overlays.editOverlay(gridOverlay, { position: { x: origin.y, y: origin.y, z: -origin.y }, visible: that.visible && that.enabled, - minorGridSpacing: minorGridSpacing, + minorGridWidth: minorGridSpacing, majorGridEvery: majorGridEvery, color: gridColor, alpha: gridAlpha, From 2ee33cef9f1bbe53b2a8ed1f4bc8aa7f7c224463 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 17 Dec 2014 10:21:27 -0800 Subject: [PATCH 467/502] have targets bubble up their Qt modules --- cmake/macros/LinkHifiLibraries.cmake | 4 ++++ cmake/macros/LinkSharedDependencies.cmake | 15 +++++++++++++++ cmake/macros/SetupHifiLibrary.cmake | 13 ++----------- cmake/macros/SetupHifiProject.cmake | 15 ++------------- 4 files changed, 23 insertions(+), 24 deletions(-) diff --git a/cmake/macros/LinkHifiLibraries.cmake b/cmake/macros/LinkHifiLibraries.cmake index a46023fe9a..464af76553 100644 --- a/cmake/macros/LinkHifiLibraries.cmake +++ b/cmake/macros/LinkHifiLibraries.cmake @@ -33,6 +33,10 @@ macro(LINK_HIFI_LIBRARIES) get_target_property(LINKED_TARGET_DEPENDENCY_INCLUDES ${HIFI_LIBRARY} DEPENDENCY_INCLUDES) list(APPEND ${TARGET_NAME}_DEPENDENCY_INCLUDES ${LINKED_TARGET_DEPENDENCY_INCLUDES}) + # ask the library what its qt module dependencies are and link them + get_target_property(LINKED_TARGET_DEPENDENCY_QT_MODULES ${HIFI_LIBRARY} DEPENDENCY_QT_MODULES) + list(APPEND ${TARGET_NAME}_DEPENDENCY_QT_MODULES ${LINKED_TARGET_DEPENDENCY_QT_MODULES}) + endforeach() endmacro(LINK_HIFI_LIBRARIES) \ No newline at end of file diff --git a/cmake/macros/LinkSharedDependencies.cmake b/cmake/macros/LinkSharedDependencies.cmake index afd25db0d7..890736d806 100644 --- a/cmake/macros/LinkSharedDependencies.cmake +++ b/cmake/macros/LinkSharedDependencies.cmake @@ -24,10 +24,25 @@ macro(LINK_SHARED_DEPENDENCIES) include_directories(SYSTEM ${${TARGET_NAME}_DEPENDENCY_INCLUDES}) endif () + if (${TARGET_NAME}_DEPENDENCY_QT_MODULES) + list(REMOVE_DUPLICATES ${TARGET_NAME}_DEPENDENCY_QT_MODULES) + + message(${TARGET_NAME}) + message(${${TARGET_NAME}_DEPENDENCY_QT_MODULES}) + + # find these Qt modules and link them to our own target + find_package(Qt5 COMPONENTS ${${TARGET_NAME}_DEPENDENCY_QT_MODULES} REQUIRED) + + foreach(QT_MODULE ${QT_MODULES_TO_LINK}) + target_link_libraries(${TARGET_NAME} Qt5::${QT_MODULE}) + endforeach() + endif () + # we've already linked our Qt modules, but we need to bubble them up to parents list(APPEND ${TARGET_NAME}_LIBRARIES_TO_LINK "${${TARGET_NAME}_QT_MODULES_TO_LINK}") # set the property on this target so it can be retreived by targets linking to us set_target_properties(${TARGET_NAME} PROPERTIES DEPENDENCY_LIBRARIES "${${TARGET_NAME}_LIBRARIES_TO_LINK}") set_target_properties(${TARGET_NAME} PROPERTIES DEPENDENCY_INCLUDES "${${TARGET_NAME}_DEPENDENCY_INCLUDES}") + set_target_properties(${TARGET_NAME} PROPERTIES DEPENDENCY_QT_MODULES "${${TARGET_NAME}_DEPENDENCY_QT_MODULES}") endmacro(LINK_SHARED_DEPENDENCIES) \ No newline at end of file diff --git a/cmake/macros/SetupHifiLibrary.cmake b/cmake/macros/SetupHifiLibrary.cmake index 950286ce45..de9f9b9d1e 100644 --- a/cmake/macros/SetupHifiLibrary.cmake +++ b/cmake/macros/SetupHifiLibrary.cmake @@ -18,16 +18,7 @@ macro(SETUP_HIFI_LIBRARY) # create a library and set the property so it can be referenced later add_library(${TARGET_NAME} ${LIB_SRCS} ${AUTOMTC_SRC}) - set(QT_MODULES_TO_LINK ${ARGN}) - list(APPEND QT_MODULES_TO_LINK Core) + set(${TARGET_NAME}_DEPENDENCY_QT_MODULES ${ARGN}) + list(APPEND ${TARGET_NAME}_DEPENDENCY_QT_MODULES Core) - find_package(Qt5 COMPONENTS ${QT_MODULES_TO_LINK} REQUIRED) - - foreach(QT_MODULE ${QT_MODULES_TO_LINK}) - get_target_property(QT_LIBRARY_LOCATION Qt5::${QT_MODULE} LOCATION) - - # add the actual path to the Qt module to our LIBRARIES_TO_LINK variable - target_link_libraries(${TARGET_NAME} Qt5::${QT_MODULE}) - list(APPEND ${TARGET_NAME}_QT_MODULES_TO_LINK ${QT_LIBRARY_LOCATION}) - endforeach() endmacro(SETUP_HIFI_LIBRARY) \ No newline at end of file diff --git a/cmake/macros/SetupHifiProject.cmake b/cmake/macros/SetupHifiProject.cmake index d21e2c11bb..157c22ea79 100644 --- a/cmake/macros/SetupHifiProject.cmake +++ b/cmake/macros/SetupHifiProject.cmake @@ -25,17 +25,6 @@ macro(SETUP_HIFI_PROJECT) # add the executable, include additional optional sources add_executable(${TARGET_NAME} ${TARGET_SRCS} "${AUTOMTC_SRC}") - set(QT_MODULES_TO_LINK ${ARGN}) - list(APPEND QT_MODULES_TO_LINK Core) - - find_package(Qt5 COMPONENTS ${QT_MODULES_TO_LINK} REQUIRED) - - foreach(QT_MODULE ${QT_MODULES_TO_LINK}) - target_link_libraries(${TARGET_NAME} Qt5::${QT_MODULE}) - - # add the actual path to the Qt module to our LIBRARIES_TO_LINK variable - get_target_property(QT_LIBRARY_LOCATION Qt5::${QT_MODULE} LOCATION) - list(APPEND ${TARGET_NAME}_QT_MODULES_TO_LINK ${QT_LIBRARY_LOCATION}) - endforeach() - + set(${TARGET_NAME}_DEPENDENCY_QT_MODULES ${ARGN}) + list(APPEND ${TARGET_NAME}_DEPENDENCY_QT_MODULES Core) endmacro() \ No newline at end of file From 421680696756cf75bed30742d9514cdd3e13443c Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 17 Dec 2014 10:21:53 -0800 Subject: [PATCH 468/502] remove extra debugging in LinkSharedDependencies --- cmake/macros/LinkSharedDependencies.cmake | 3 --- 1 file changed, 3 deletions(-) diff --git a/cmake/macros/LinkSharedDependencies.cmake b/cmake/macros/LinkSharedDependencies.cmake index 890736d806..c5049cf842 100644 --- a/cmake/macros/LinkSharedDependencies.cmake +++ b/cmake/macros/LinkSharedDependencies.cmake @@ -27,9 +27,6 @@ macro(LINK_SHARED_DEPENDENCIES) if (${TARGET_NAME}_DEPENDENCY_QT_MODULES) list(REMOVE_DUPLICATES ${TARGET_NAME}_DEPENDENCY_QT_MODULES) - message(${TARGET_NAME}) - message(${${TARGET_NAME}_DEPENDENCY_QT_MODULES}) - # find these Qt modules and link them to our own target find_package(Qt5 COMPONENTS ${${TARGET_NAME}_DEPENDENCY_QT_MODULES} REQUIRED) From 33d50c6eb62beab46a52da27f1b3e4b2a8f15766 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 17 Dec 2014 10:26:51 -0800 Subject: [PATCH 469/502] fix dependency qt module linking in LinkSharedDependencies --- cmake/macros/LinkSharedDependencies.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/macros/LinkSharedDependencies.cmake b/cmake/macros/LinkSharedDependencies.cmake index c5049cf842..fd5461c288 100644 --- a/cmake/macros/LinkSharedDependencies.cmake +++ b/cmake/macros/LinkSharedDependencies.cmake @@ -30,7 +30,7 @@ macro(LINK_SHARED_DEPENDENCIES) # find these Qt modules and link them to our own target find_package(Qt5 COMPONENTS ${${TARGET_NAME}_DEPENDENCY_QT_MODULES} REQUIRED) - foreach(QT_MODULE ${QT_MODULES_TO_LINK}) + foreach(QT_MODULE ${${TARGET_NAME}_DEPENDENCY_QT_MODULES}) target_link_libraries(${TARGET_NAME} Qt5::${QT_MODULE}) endforeach() endif () From d3bf28e87971ac8abbde30d68a61a82b62cda9b3 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 17 Dec 2014 11:10:24 -0800 Subject: [PATCH 470/502] more Application dependency cleanup --- libraries/gpu/src/gpu/GLUTConfig.h | 25 +++++++++++++ ...terface.h => AbstractViewStateInterface.h} | 0 .../src/AbstractScriptingServicesInterface.h | 35 +++++++++++++++++++ 3 files changed, 60 insertions(+) create mode 100644 libraries/gpu/src/gpu/GLUTConfig.h rename libraries/render-utils/src/{ViewStateInterface.h => AbstractViewStateInterface.h} (100%) create mode 100644 libraries/script-engine/src/AbstractScriptingServicesInterface.h diff --git a/libraries/gpu/src/gpu/GLUTConfig.h b/libraries/gpu/src/gpu/GLUTConfig.h new file mode 100644 index 0000000000..214f2bb2b0 --- /dev/null +++ b/libraries/gpu/src/gpu/GLUTConfig.h @@ -0,0 +1,25 @@ +// +// GPUConfig.h +// libraries/gpu/src/gpu +// +// Created by Brad Hefta-Gaub on 12/17/14. +// 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 gpu__GLUTConfig__ +#define gpu__GLUTConfig__ + +// TODO: remove these once we migrate away from GLUT calls +#if defined(__APPLE__) +#include +#elif defined(WIN32) +#include +#else +#include +#endif + + +#endif // gpu__GLUTConfig__ diff --git a/libraries/render-utils/src/ViewStateInterface.h b/libraries/render-utils/src/AbstractViewStateInterface.h similarity index 100% rename from libraries/render-utils/src/ViewStateInterface.h rename to libraries/render-utils/src/AbstractViewStateInterface.h diff --git a/libraries/script-engine/src/AbstractScriptingServicesInterface.h b/libraries/script-engine/src/AbstractScriptingServicesInterface.h new file mode 100644 index 0000000000..5e7ad81f67 --- /dev/null +++ b/libraries/script-engine/src/AbstractScriptingServicesInterface.h @@ -0,0 +1,35 @@ +// +// AbstractScriptingServicesInterface.h +// interface/src/script-engine +// +// Created by Brad Hefta-Gaub on 12/16/14. +// 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_AbstractScriptingServicesInterface_h +#define hifi_AbstractScriptingServicesInterface_h + +//#include + +class AbstractControllerScriptingInterface; +class Transform; +class ScriptEngine; +class QThread; + +/// Interface provided by Application to other objects that need access to scripting services of the application +class AbstractScriptingServicesInterface { +public: + + /// Returns the controller interface for the application + virtual AbstractControllerScriptingInterface* getControllerScriptingInterface() = 0; + + /// Registers application specific services with a script engine. + virtual void registerScriptEngineWithApplicationServices(ScriptEngine* scriptEngine) = 0; + +}; + + +#endif // hifi_AbstractScriptingServicesInterface_h From 5d636e21c64d8789f198bbdaf4cbf325372740cc Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 17 Dec 2014 11:10:45 -0800 Subject: [PATCH 471/502] more Application dependency cleanup --- interface/src/Application.cpp | 6 ++--- interface/src/Application.h | 14 ++++++----- interface/src/entities/EntityTreeRenderer.cpp | 23 ++++++++++++------- interface/src/entities/EntityTreeRenderer.h | 8 +++++-- .../src/AbstractViewStateInterface.h | 16 ++++++++----- .../src/AmbientOcclusionEffect.cpp | 3 ++- .../render-utils/src/AmbientOcclusionEffect.h | 7 +++--- .../src/DeferredLightingEffect.cpp | 15 ++++-------- .../render-utils/src/DeferredLightingEffect.h | 6 ++--- libraries/render-utils/src/Model.cpp | 4 +++- libraries/render-utils/src/Model.h | 6 ++--- 11 files changed, 60 insertions(+), 48 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index d8c7811b6a..1453cec53b 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -155,9 +155,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : _voxelImporter(), _importSucceded(false), _sharedVoxelSystem(TREE_SCALE, DEFAULT_MAX_VOXELS_PER_SYSTEM, &_clipboard), - _entities(true, this), + _entities(true, this, this), _entityCollisionSystem(), - _entityClipboardRenderer(false, this), + _entityClipboardRenderer(false, this, this), _entityClipboard(), _wantToKillLocalVoxels(false), _viewFrustum(), @@ -191,7 +191,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : _isVSyncOn(true), _aboutToQuit(false) { - Model::setViewStateInterface(this); // The model class will sometimes need to know view state details from us + Model::setAbstractViewStateInterface(this); // The model class will sometimes need to know view state details from us // read the ApplicationInfo.ini file for Name/Version/Domain information QSettings applicationInfo(PathUtils::resourcesPath() + "info/ApplicationInfo.ini", QSettings::IniFormat); diff --git a/interface/src/Application.h b/interface/src/Application.h index 86683a6608..d192a9abe6 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -32,6 +32,8 @@ #include #include +#include +#include #include #include #include @@ -42,7 +44,6 @@ #include #include #include -#include #include #include "MainWindow.h" @@ -127,7 +128,7 @@ static const quint64 TOO_LONG_SINCE_LAST_SEND_DOWNSTREAM_AUDIO_STATS = 1 * USECS static const QString INFO_HELP_PATH = "html/interface-welcome-allsvg.html"; static const QString INFO_EDIT_ENTITIES_PATH = "html/edit-entities-commands.html"; -class Application : public QApplication, public ViewStateInterface { +class Application : public QApplication, public AbstractViewStateInterface, AbstractScriptingServicesInterface { Q_OBJECT friend class OctreePacketProcessor; @@ -186,6 +187,7 @@ public: GLCanvas* getGLWidget() { return _glWidget; } bool isThrottleRendering() const { return _glWidget->isThrottleRendering(); } MyAvatar* getAvatar() { return _myAvatar; } + const MyAvatar* getAvatar() const { return _myAvatar; } Audio* getAudio() { return &_audio; } Camera* getCamera() { return &_myCamera; } ViewFrustum* getViewFrustum() { return &_viewFrustum; } @@ -248,7 +250,9 @@ public: ToolWindow* getToolWindow() { return _toolWindow ; } - ControllerScriptingInterface* getControllerScriptingInterface() { return &_controllerScriptingInterface; } + virtual AbstractControllerScriptingInterface* getControllerScriptingInterface() { return &_controllerScriptingInterface; } + virtual void registerScriptEngineWithApplicationServices(ScriptEngine* scriptEngine); + AvatarManager& getAvatarManager() { return _avatarManager; } void resetProfile(const QString& username); @@ -288,6 +292,7 @@ public: virtual float getSizeScale() const; virtual int getBoundaryLevelAdjust() const; virtual PickRay computePickRay(float x, float y); + virtual const glm::vec3& getAvatarPosition() const { return getAvatar()->getPosition(); } NodeBounds& getNodeBoundsDisplay() { return _nodeBoundsDisplay; } @@ -312,9 +317,6 @@ public: bool isVSyncEditable() const; bool isAboutToQuit() const { return _aboutToQuit; } - - void registerScriptEngineWithApplicationServices(ScriptEngine* scriptEngine); - // the isHMDmode is true whenever we use the interface from an HMD and not a standard flat display // rendering of several elements depend on that // TODO: carry that information on the Camera as a setting diff --git a/interface/src/entities/EntityTreeRenderer.cpp b/interface/src/entities/EntityTreeRenderer.cpp index 6684daf7e8..5654b416f1 100644 --- a/interface/src/entities/EntityTreeRenderer.cpp +++ b/interface/src/entities/EntityTreeRenderer.cpp @@ -11,16 +11,21 @@ #include +#include // TODO - we need to get rid of this ASAP + #include +#include #include - + +#include +#include #include +#include #include #include -#include +#include -#include "Application.h" #include "EntityTreeRenderer.h" #include "RenderableBoxEntityItem.h" @@ -30,12 +35,14 @@ #include "RenderableTextEntityItem.h" -EntityTreeRenderer::EntityTreeRenderer(bool wantScripts, ViewStateInterface* viewState) : +EntityTreeRenderer::EntityTreeRenderer(bool wantScripts, AbstractViewStateInterface* viewState, + AbstractScriptingServicesInterface* scriptingServices) : OctreeRenderer(), _wantScripts(wantScripts), _entitiesScriptEngine(NULL), _lastMouseEventValid(false), _viewState(viewState), + _scriptingServices(scriptingServices), _displayElementChildProxies(false), _displayModelBounds(false), _displayModelElementProxy(false), @@ -70,13 +77,13 @@ void EntityTreeRenderer::init() { if (_wantScripts) { _entitiesScriptEngine = new ScriptEngine(NO_SCRIPT, "Entities", - Application::getInstance()->getControllerScriptingInterface()); - Application::getInstance()->registerScriptEngineWithApplicationServices(_entitiesScriptEngine); + _scriptingServices->getControllerScriptingInterface()); + _scriptingServices->registerScriptEngineWithApplicationServices(_entitiesScriptEngine); } // make sure our "last avatar position" is something other than our current position, so that on our // first chance, we'll check for enter/leave entity events. - glm::vec3 avatarPosition = Application::getInstance()->getAvatar()->getPosition(); + glm::vec3 avatarPosition = _viewState->getAvatarPosition(); _lastAvatarPosition = avatarPosition + glm::vec3(1.0f, 1.0f, 1.0f); connect(entityTree, &EntityTree::deletingEntity, this, &EntityTreeRenderer::deletingEntity); @@ -233,7 +240,7 @@ void EntityTreeRenderer::update() { void EntityTreeRenderer::checkEnterLeaveEntities() { if (_tree) { _tree->lockForWrite(); // so that our scripts can do edits if they want - glm::vec3 avatarPosition = Application::getInstance()->getAvatar()->getPosition() / (float) TREE_SCALE; + glm::vec3 avatarPosition = _viewState->getAvatarPosition() / (float) TREE_SCALE; if (avatarPosition != _lastAvatarPosition) { float radius = 1.0f / (float) TREE_SCALE; // for now, assume 1 meter radius diff --git a/interface/src/entities/EntityTreeRenderer.h b/interface/src/entities/EntityTreeRenderer.h index c3bd77aba7..f827685409 100644 --- a/interface/src/entities/EntityTreeRenderer.h +++ b/interface/src/entities/EntityTreeRenderer.h @@ -19,6 +19,8 @@ class Model; class ScriptEngine; +class AbstractViewStateInterface; +class AbstractScriptingServicesInterface; class EntityScriptDetails { public: @@ -30,7 +32,8 @@ public: class EntityTreeRenderer : public OctreeRenderer, public EntityItemFBXService { Q_OBJECT public: - EntityTreeRenderer(bool wantScripts, ViewStateInterface* viewState); + EntityTreeRenderer(bool wantScripts, AbstractViewStateInterface* viewState, + AbstractScriptingServicesInterface* scriptingServices); virtual ~EntityTreeRenderer(); virtual char getMyNodeType() const { return NodeType::EntityServer; } @@ -141,7 +144,8 @@ private: bool _lastMouseEventValid; MouseEvent _lastMouseEvent; - ViewStateInterface* _viewState; + AbstractViewStateInterface* _viewState; + AbstractScriptingServicesInterface* _scriptingServices; bool _displayElementChildProxies; bool _displayModelBounds; bool _displayModelElementProxy; diff --git a/libraries/render-utils/src/AbstractViewStateInterface.h b/libraries/render-utils/src/AbstractViewStateInterface.h index 5f85e998a4..50a75c769a 100644 --- a/libraries/render-utils/src/AbstractViewStateInterface.h +++ b/libraries/render-utils/src/AbstractViewStateInterface.h @@ -1,5 +1,5 @@ // -// ViewStateInterface.h +// AbstractViewStateInterface.h // interface/src/renderer // // Created by Brad Hefta-Gaub on 12/16/14. @@ -9,16 +9,18 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#ifndef hifi_ViewStateInterface_h -#define hifi_ViewStateInterface_h +#ifndef hifi_AbstractViewStateInterface_h +#define hifi_AbstractViewStateInterface_h -#include +#include class Transform; class QThread; +class ViewFrustum; +class PickRay; /// Interface provided by Application to other objects that need access to the current view state details -class ViewStateInterface { +class AbstractViewStateInterface { public: /// Returns the shadow distances for the current view state @@ -41,7 +43,9 @@ public: virtual float getSizeScale() const = 0; virtual int getBoundaryLevelAdjust() const = 0; virtual PickRay computePickRay(float x, float y) = 0; + + virtual const glm::vec3& getAvatarPosition() const = 0; }; -#endif // hifi_ViewStateInterface_h +#endif // hifi_AbstractViewStateInterface_h diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.cpp b/libraries/render-utils/src/AmbientOcclusionEffect.cpp index b9289204c7..40a02a60a4 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.cpp +++ b/libraries/render-utils/src/AmbientOcclusionEffect.cpp @@ -19,6 +19,7 @@ #include #include +#include "AbstractViewStateInterface.h" #include "AmbientOcclusionEffect.h" #include "GlowEffect.h" #include "ProgramObject.h" @@ -28,7 +29,7 @@ const int ROTATION_WIDTH = 4; const int ROTATION_HEIGHT = 4; -void AmbientOcclusionEffect::init(ViewStateInterface* viewState) { +void AmbientOcclusionEffect::init(AbstractViewStateInterface* viewState) { _viewState = viewState; // we will use this for view state services _occlusionProgram = new ProgramObject(); diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.h b/libraries/render-utils/src/AmbientOcclusionEffect.h index 1ee7269480..59ab8b7c8b 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.h +++ b/libraries/render-utils/src/AmbientOcclusionEffect.h @@ -14,8 +14,7 @@ #include -#include "ViewStateInterface.h" - +class AbstractViewStateInterface; class ProgramObject; /// A screen space ambient occlusion effect. See John Chapman's tutorial at @@ -23,7 +22,7 @@ class ProgramObject; class AmbientOcclusionEffect: public DependencyManager::Dependency { public: - void init(ViewStateInterface* viewState); + void init(AbstractViewStateInterface* viewState); void render(); private: @@ -44,7 +43,7 @@ private: int _blurScaleLocation; GLuint _rotationTextureID; - ViewStateInterface* _viewState; + AbstractViewStateInterface* _viewState; }; #endif // hifi_AmbientOcclusionEffect_h diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 9f54b25441..5af14b6640 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -12,22 +12,15 @@ // include this before QOpenGLFramebufferObject, which includes an earlier version of OpenGL #include - -// TODO: remove these once we migrate away from GLUT calls -#if defined(__APPLE__) -#include -#elif defined(WIN32) -#include -#else -#include -#endif +#include // TODO - we need to get rid of this ASAP #include #include #include +#include - +#include "AbstractViewStateInterface.h" #include "DeferredLightingEffect.h" #include "GeometryCache.h" #include "GlowEffect.h" @@ -35,7 +28,7 @@ #include "TextureCache.h" -void DeferredLightingEffect::init(ViewStateInterface* viewState) { +void DeferredLightingEffect::init(AbstractViewStateInterface* viewState) { _viewState = viewState; _simpleProgram.addShaderFromSourceFile(QGLShader::Vertex, PathUtils::resourcesPath() + "shaders/simple.vert"); _simpleProgram.addShaderFromSourceFile(QGLShader::Fragment, PathUtils::resourcesPath() + "shaders/simple.frag"); diff --git a/libraries/render-utils/src/DeferredLightingEffect.h b/libraries/render-utils/src/DeferredLightingEffect.h index 5dcd7d35f4..955a289f6d 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.h +++ b/libraries/render-utils/src/DeferredLightingEffect.h @@ -18,15 +18,15 @@ #include #include "ProgramObject.h" -#include "ViewStateInterface.h" +class AbstractViewStateInterface; class PostLightingRenderable; /// Handles deferred lighting for the bits that require it (voxels, metavoxels...) class DeferredLightingEffect: public DependencyManager::Dependency { public: - void init(ViewStateInterface* viewState); + void init(AbstractViewStateInterface* viewState); /// Returns a reference to a simple program suitable for rendering static /// untextured geometry (such as that generated by glutSolidSphere, etc.) @@ -125,7 +125,7 @@ private: QVector _spotLights; QVector _postLightingRenderables; - ViewStateInterface* _viewState; + AbstractViewStateInterface* _viewState; }; /// Simple interface for objects that require something to be rendered after deferred lighting. diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 16e6b1bf02..b422a7f404 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -27,7 +27,9 @@ #include #include #include +#include +#include "AbstractViewStateInterface.h" #include "AnimationHandle.h" #include "DeferredLightingEffect.h" #include "GlowEffect.h" @@ -111,7 +113,7 @@ Model::SkinLocations Model::_skinNormalSpecularMapLocations; Model::SkinLocations Model::_skinShadowLocations; Model::SkinLocations Model::_skinTranslucentLocations; -ViewStateInterface* Model::_viewState = NULL; +AbstractViewStateInterface* Model::_viewState = NULL; void Model::setScale(const glm::vec3& scale) { setScaleInternal(scale); diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index d24f349f81..841389073e 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -32,8 +32,8 @@ #include "JointState.h" #include "ProgramObject.h" #include "TextureCache.h" -#include "ViewStateInterface.h" +class AbstractViewStateInterface; class QScriptEngine; class Shape; @@ -47,7 +47,7 @@ class Model : public QObject, public PhysicsEntity { public: - static void setViewStateInterface(ViewStateInterface* viewState) { _viewState = viewState; } + static void setAbstractViewStateInterface(AbstractViewStateInterface* viewState) { _viewState = viewState; } Model(QObject* parent = NULL); virtual ~Model(); @@ -459,7 +459,7 @@ private: bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args); - static ViewStateInterface* _viewState; + static AbstractViewStateInterface* _viewState; }; From a465aa20ff5bb2b6a9b3ac396137fd74ab65c34d Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 17 Dec 2014 11:41:42 -0800 Subject: [PATCH 472/502] more Application and Menu dependency removal --- .../entities/RenderableLightEntityItem.cpp | 33 ++++++++----------- .../entities/RenderableModelEntityItem.cpp | 24 +++----------- .../src/entities/RenderableModelEntityItem.h | 1 + .../entities/src/EntityScriptingInterface.cpp | 10 ++---- libraries/entities/src/EntityTree.cpp | 1 - libraries/entities/src/EntityTree.h | 3 -- libraries/entities/src/LightEntityItem.cpp | 1 + libraries/entities/src/LightEntityItem.h | 5 +++ 8 files changed, 29 insertions(+), 49 deletions(-) diff --git a/interface/src/entities/RenderableLightEntityItem.cpp b/interface/src/entities/RenderableLightEntityItem.cpp index be64fe7520..9097956c88 100644 --- a/interface/src/entities/RenderableLightEntityItem.cpp +++ b/interface/src/entities/RenderableLightEntityItem.cpp @@ -16,8 +16,6 @@ #include #include -#include "Application.h" -#include "Menu.h" #include "RenderableLightEntityItem.h" EntityItem* RenderableLightEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { @@ -55,17 +53,13 @@ void RenderableLightEntityItem::render(RenderArgs* args) { float exponent = getExponent(); float cutoff = glm::radians(getCutoff()); - bool disableLights = Menu::getInstance()->isOptionChecked(MenuOption::DisableLightEntities); - - if (!disableLights) { - if (_isSpotlight) { - DependencyManager::get()->addSpotLight(position, largestDiameter / 2.0f, - ambient, diffuse, specular, constantAttenuation, linearAttenuation, quadraticAttenuation, - direction, exponent, cutoff); - } else { - DependencyManager::get()->addPointLight(position, largestDiameter / 2.0f, - ambient, diffuse, specular, constantAttenuation, linearAttenuation, quadraticAttenuation); - } + if (_isSpotlight) { + DependencyManager::get()->addSpotLight(position, largestDiameter / 2.0f, + ambient, diffuse, specular, constantAttenuation, linearAttenuation, quadraticAttenuation, + direction, exponent, cutoff); + } else { + DependencyManager::get()->addPointLight(position, largestDiameter / 2.0f, + ambient, diffuse, specular, constantAttenuation, linearAttenuation, quadraticAttenuation); } #ifdef WANT_DEBUG @@ -88,10 +82,11 @@ void RenderableLightEntityItem::render(RenderArgs* args) { bool RenderableLightEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, void** intersectedObject, bool precisionPicking) const { - - // TODO: this isn't really correct because we don't know if we actually live in the main tree of the applications's - // EntityTreeRenderer. But we probably do. Technically we could be on the clipboard and someone might be trying to - // use the ray intersection API there. Anyway... if you ever try to do ray intersection testing off of trees other - // than the main tree of the main entity renderer, then you'll need to fix this mechanism. - return Application::getInstance()->getEntities()->getTree()->getLightsArePickable(); + + // TODO: consider if this is really what we want to do. We've made it so that "lights are pickable" is a global state + // this is probably reasonable since there's typically only one tree you'd be picking on at a time. Technically we could + // be on the clipboard and someone might be trying to use the ray intersection API there. Anyway... if you ever try to + // do ray intersection testing off of trees other than the main tree of the main entity renderer, then we'll need to + // fix this mechanism. + return _lightsArePickable; } diff --git a/interface/src/entities/RenderableModelEntityItem.cpp b/interface/src/entities/RenderableModelEntityItem.cpp index c998570a27..3e5118d203 100644 --- a/interface/src/entities/RenderableModelEntityItem.cpp +++ b/interface/src/entities/RenderableModelEntityItem.cpp @@ -13,10 +13,13 @@ #include +#include + #include +#include #include -#include "Menu.h" +#include "EntityTreeRenderer.h" #include "RenderableModelEntityItem.h" EntityItem* RenderableModelEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { @@ -159,28 +162,11 @@ void RenderableModelEntityItem::render(RenderArgs* args) { _needsInitialSimulation = false; } - // TODO: should we allow entityItems to have alpha on their models? - Model::RenderMode modelRenderMode = args->_renderMode == RenderArgs::SHADOW_RENDER_MODE - ? Model::SHADOW_RENDER_MODE : Model::DEFAULT_RENDER_MODE; - if (_model->isActive()) { // TODO: this is the majority of model render time. And rendering of a cube model vs the basic Box render // is significantly more expensive. Is there a way to call this that doesn't cost us as much? PerformanceTimer perfTimer("model->render"); - bool dontRenderAsScene = Menu::getInstance()->isOptionChecked(MenuOption::DontRenderEntitiesAsScene); - bool displayModelTriangles = Menu::getInstance()->isOptionChecked(MenuOption::DisplayModelTriangles); - bool rendered = false; - if (displayModelTriangles) { - rendered = _model->renderTriangleProxies(); - } - - if (!rendered) { - if (dontRenderAsScene) { - _model->render(alpha, modelRenderMode, args); - } else { - _model->renderInScene(alpha, args); - } - } + _model->renderInScene(alpha, args); } else { // if we couldn't get a model, then just draw a cube glColor3ub(getColor()[RED_INDEX],getColor()[GREEN_INDEX],getColor()[BLUE_INDEX]); diff --git a/interface/src/entities/RenderableModelEntityItem.h b/interface/src/entities/RenderableModelEntityItem.h index 9e66e4ef40..6f61a1b9db 100644 --- a/interface/src/entities/RenderableModelEntityItem.h +++ b/interface/src/entities/RenderableModelEntityItem.h @@ -18,6 +18,7 @@ #include class Model; +class EntityTreeRenderer; class RenderableModelEntityItem : public ModelEntityItem { public: diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 26870ad9bb..6226012052 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -11,6 +11,7 @@ #include "EntityScriptingInterface.h" #include "EntityTree.h" +#include "LightEntityItem.h" #include "ModelEntityItem.h" EntityScriptingInterface::EntityScriptingInterface() : @@ -226,16 +227,11 @@ RayToEntityIntersectionResult EntityScriptingInterface::findRayIntersectionWorke } void EntityScriptingInterface::setLightsArePickable(bool value) { - if (_entityTree) { - _entityTree->setLightsArePickable(value); - } + LightEntityItem::setLightsArePickable(value); } bool EntityScriptingInterface::getLightsArePickable() const { - if (_entityTree) { - return _entityTree->getLightsArePickable(); - } - return false; + return LightEntityItem::getLightsArePickable(); } diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 17178ccbed..fb8e4345f4 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -22,7 +22,6 @@ EntityTree::EntityTree(bool shouldReaverage) : Octree(shouldReaverage), _fbxService(NULL), - _lightsArePickable(true), _simulation(NULL) { _rootElement = createNewElement(); diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index 9a0fb43ecb..cfd08c3b5c 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -150,8 +150,6 @@ public: void emitEntityScriptChanging(const EntityItemID& entityItemID); - bool getLightsArePickable() const { return _lightsArePickable; } - void setLightsArePickable(bool value) { _lightsArePickable = value; } void setSimulation(EntitySimulation* simulation); signals: @@ -180,7 +178,6 @@ private: QHash _entityToElementMap; - bool _lightsArePickable; EntitySimulation* _simulation; }; diff --git a/libraries/entities/src/LightEntityItem.cpp b/libraries/entities/src/LightEntityItem.cpp index a24fe58c2a..44b83bc94e 100644 --- a/libraries/entities/src/LightEntityItem.cpp +++ b/libraries/entities/src/LightEntityItem.cpp @@ -18,6 +18,7 @@ #include "EntityTreeElement.h" #include "LightEntityItem.h" +bool LightEntityItem::_lightsArePickable = false; EntityItem* LightEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { return new LightEntityItem(entityID, properties); diff --git a/libraries/entities/src/LightEntityItem.h b/libraries/entities/src/LightEntityItem.h index eb9a2ed051..6ebb85beda 100644 --- a/libraries/entities/src/LightEntityItem.h +++ b/libraries/entities/src/LightEntityItem.h @@ -99,6 +99,9 @@ public: void setCutoff(float value) { _cutoff = value; } virtual const Shape& getCollisionShapeInMeters() const { return _emptyShape; } + + static bool getLightsArePickable() { return _lightsArePickable; } + static void setLightsArePickable(bool value) { _lightsArePickable = value; } protected: virtual void recalculateCollisionShape() { /* nothing to do */ } @@ -116,6 +119,8 @@ protected: // used for collision detection SphereShape _emptyShape; + + static bool _lightsArePickable; }; #endif // hifi_LightEntityItem_h From e36ee2a96130328ecddf1704edfc498905245e6c Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 17 Dec 2014 12:19:34 -0800 Subject: [PATCH 473/502] more correct creation and edit times for entities --- libraries/entities/src/EntityItem.cpp | 75 ++++++++++++------- libraries/entities/src/EntityItem.h | 5 +- libraries/entities/src/EntityItemProperties.h | 4 +- libraries/entities/src/EntityTypes.cpp | 8 +- 4 files changed, 55 insertions(+), 37 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index b271439662..22cfeb3674 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -53,14 +53,13 @@ void EntityItem::initFromEntityItemID(const EntityItemID& entityItemID) { _creatorTokenID = entityItemID.creatorTokenID; // init values with defaults before calling setProperties - //uint64_t now = usecTimestampNow(); _lastEdited = 0; _lastEditedFromRemote = 0; _lastEditedFromRemoteInRemoteTime = 0; _lastSimulated = 0; _lastUpdated = 0; - _created = 0; // TODO: when do we actually want to make this "now" + _created = usecTimestampNow(); _changedOnServer = 0; _position = glm::vec3(0,0,0); @@ -99,16 +98,20 @@ EntityItem::EntityItem(const EntityItemID& entityItemID) { EntityItem::EntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) { _type = EntityTypes::Unknown; - _lastEdited = 0; + quint64 now = usecTimestampNow(); + _created = properties.getCreated() < now ? properties.getCreated() : now; + _lastEdited = _lastEditedFromRemote = _lastSimulated = _lastUpdated = _lastEditedFromRemoteInRemoteTime = _created; _lastEditedFromRemote = 0; _lastEditedFromRemoteInRemoteTime = 0; _lastSimulated = 0; _lastUpdated = 0; - _created = properties.getCreated(); _dirtyFlags = 0; _changedOnServer = 0; initFromEntityItemID(entityItemID); setProperties(properties, true); // force copy + if (_lastEdited == 0) { + _lastEdited = _created; + } } EntityPropertyFlags EntityItem::getEntityProperties(EncodeBitstreamParams& params) const { @@ -367,7 +370,12 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef bytesRead += sizeof(createdFromBuffer); createdFromBuffer -= clockSkew; - _created = createdFromBuffer; // TODO: do we ever want to discard this??? + if (createdFromBuffer < _created) { + // the server claims that this entity has an older creation time + // so we accept it and clear _lastEdited + _created = createdFromBuffer; + _lastEdited = 0; + } if (wantDebug) { quint64 lastEdited = getLastEdited(); @@ -416,14 +424,14 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef if (fromSameServerEdit) { // If this is from the same sever packet, then check against any local changes since we got // the most recent packet from this server time - if (_lastEdited > _lastEditedFromRemote) { + if (_lastEdited >= _lastEditedFromRemote) { ignoreServerPacket = true; } } else { // If this isn't from the same sever packet, then honor our skew adjusted times... // If we've changed our local tree more recently than the new data from this packet // then we will not be changing our values, instead we just read and skip the data - if (_lastEdited > lastEditedFromBufferAdjusted) { + if (_lastEdited >= lastEditedFromBufferAdjusted) { ignoreServerPacket = true; } } @@ -439,7 +447,8 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef qDebug() << "USING NEW data from server!!! ****************"; } - _lastEdited = lastEditedFromBufferAdjusted; + // don't allow _lastEdited to be in the future + _lastEdited = lastEditedFromBufferAdjusted < now ? lastEditedFromBufferAdjusted : now; _lastEditedFromRemote = now; _lastEditedFromRemoteInRemoteTime = lastEditedFromBuffer; @@ -451,7 +460,8 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef ByteCountCoded updateDeltaCoder = encodedUpdateDelta; quint64 updateDelta = updateDeltaCoder; if (overwriteLocalData) { - _lastSimulated = _lastUpdated = lastEditedFromBufferAdjusted + updateDelta; // don't adjust for clock skew since we already did that for _lastEdited + _lastUpdated = lastEditedFromBufferAdjusted + updateDelta; // don't adjust for clock skew since we already did that for _lastEdited + _lastSimulated = now; if (wantDebug) { qDebug() << "_lastUpdated =" << _lastUpdated; qDebug() << "_lastEdited=" << _lastEdited; @@ -576,7 +586,7 @@ void EntityItem::simulate(const quint64& now) { float timeElapsed = (float)(now - _lastSimulated) / (float)(USECS_PER_SECOND); if (wantDebug) { - qDebug() << "********** EntityItem::update()"; + qDebug() << "********** EntityItem::simulate()"; qDebug() << " entity ID=" << getEntityItemID(); qDebug() << " now=" << now; qDebug() << " _lastSimulated=" << _lastSimulated; @@ -612,10 +622,8 @@ void EntityItem::simulate(const quint64& now) { } } - _lastSimulated = now; - if (wantDebug) { - qDebug() << " ********** EntityItem::update() .... SETTING _lastSimulated=" << _lastSimulated; + qDebug() << " ********** EntityItem::simulate() .... SETTING _lastSimulated=" << _lastSimulated; } if (hasAngularVelocity()) { @@ -645,13 +653,13 @@ void EntityItem::simulate(const quint64& now) { } } - if (hasVelocity() || hasGravity()) { + if (hasVelocity()) { glm::vec3 position = getPosition(); glm::vec3 velocity = getVelocity(); glm::vec3 newPosition = position + (velocity * timeElapsed); if (wantDebug) { - qDebug() << " EntityItem::update()...."; + qDebug() << " EntityItem::simulate()...."; qDebug() << " timeElapsed:" << timeElapsed; qDebug() << " old AACube:" << getMaximumAACube(); qDebug() << " old position:" << position; @@ -677,15 +685,15 @@ void EntityItem::simulate(const quint64& now) { } // handle gravity.... - if (hasGravity() && !isRestingOnSurface()) { - velocity += getGravity() * timeElapsed; - } - - // handle resting on surface case, this is definitely a bit of a hack, and it only works on the - // "ground" plane of the domain, but for now it - if (hasGravity() && isRestingOnSurface()) { - velocity.y = 0.0f; - position.y = getDistanceToBottomOfEntity(); + if (hasGravity()) { + // handle resting on surface case, this is definitely a bit of a hack, and it only works on the + // "ground" plane of the domain, but for now it what we've got + if (isRestingOnSurface()) { + velocity.y = 0.0f; + position.y = getDistanceToBottomOfEntity(); + } else { + velocity += getGravity() * timeElapsed; + } } // handle damping for velocity @@ -721,10 +729,12 @@ void EntityItem::simulate(const quint64& now) { qDebug() << " old getAABox:" << getAABox(); } } + + _lastSimulated = now; } bool EntityItem::isMoving() const { - return hasVelocity() || (hasGravity() && !isRestingOnSurface()) || hasAngularVelocity(); + return hasVelocity() || hasAngularVelocity(); } bool EntityItem::lifetimeHasExpired() const { @@ -773,10 +783,13 @@ bool EntityItem::setProperties(const EntityItemProperties& properties, bool forc // handle the setting of created timestamps for the basic new entity case if (forceCopy) { + quint64 now = usecTimestampNow(); if (properties.getCreated() == UNKNOWN_CREATED_TIME) { - _created = usecTimestampNow(); + _created = now; } else if (properties.getCreated() != USE_EXISTING_CREATED_TIME) { - _created = properties.getCreated(); + quint64 created = properties.getCreated(); + // don't allow _created to be in the future + _created = created < now ? created : now; } } @@ -803,13 +816,17 @@ bool EntityItem::setProperties(const EntityItemProperties& properties, bool forc if (somethingChanged) { somethingChangedNotification(); // notify derived classes that something has changed bool wantDebug = false; + uint64_t now = usecTimestampNow(); if (wantDebug) { - uint64_t now = usecTimestampNow(); int elapsed = now - getLastEdited(); qDebug() << "EntityItem::setProperties() AFTER update... edited AGO=" << elapsed << "now=" << now << " getLastEdited()=" << getLastEdited(); } - setLastEdited(properties._lastEdited); + // don't allow _lastEdited to be in the future + setLastEdited(properties._lastEdited < now ? properties._lastEdited : now); + if (getDirtyFlags() & EntityItem::DIRTY_POSITION) { + _lastSimulated = usecTimestampNow(); + } } return somethingChanged; diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index d5a4689657..7455b96f6b 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -85,7 +85,7 @@ public: /// Last edited time of this entity universal usecs quint64 getLastEdited() const { return _lastEdited; } void setLastEdited(quint64 lastEdited) - { _lastEdited = _lastSimulated = _lastUpdated = lastEdited; _changedOnServer = glm::max(lastEdited, _changedOnServer); } + { _lastEdited = _lastUpdated = lastEdited; _changedOnServer = glm::max(lastEdited, _changedOnServer); } float getEditedAgo() const /// Elapsed seconds since this entity was last edited { return (float)(usecTimestampNow() - getLastEdited()) / (float)USECS_PER_SECOND; } @@ -120,9 +120,6 @@ public: static int expectedBytes(); - static bool encodeEntityEditMessageDetails(PacketType command, EntityItemID id, const EntityItemProperties& details, - unsigned char* bufferOut, int sizeIn, int& sizeOut); - static void adjustEditPacketForClockSkew(unsigned char* codeColorBuffer, size_t length, int clockSkew); // perform update diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 642e24beec..e5f78e8fc7 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -95,8 +95,8 @@ enum EntityPropertyList { typedef PropertyFlags EntityPropertyFlags; -const quint64 UNKNOWN_CREATED_TIME = (quint64)(-1); -const quint64 USE_EXISTING_CREATED_TIME = (quint64)(-2); +const quint64 UNKNOWN_CREATED_TIME = 0; +const quint64 USE_EXISTING_CREATED_TIME = 1; /// A collection of properties of an entity item used in the scripting API. Translates between the actual properties of an diff --git a/libraries/entities/src/EntityTypes.cpp b/libraries/entities/src/EntityTypes.cpp index 194df024e0..f7806445bc 100644 --- a/libraries/entities/src/EntityTypes.cpp +++ b/libraries/entities/src/EntityTypes.cpp @@ -71,7 +71,6 @@ bool EntityTypes::registerEntityType(EntityType entityType, const char* name, En EntityItem* EntityTypes::constructEntityItem(EntityType entityType, const EntityItemID& entityID, const EntityItemProperties& properties) { - EntityItem* newEntityItem = NULL; EntityTypeFactory factory = NULL; if (entityType >= 0 && entityType <= LAST) { @@ -129,7 +128,12 @@ EntityItem* EntityTypes::constructEntityItem(const unsigned char* data, int byte EntityItemID tempEntityID(actualID); EntityItemProperties tempProperties; - tempProperties.setCreated(usecTimestampNow()); // this is temporary... + + // we set the Creation and Edit times to 'now', but if the server submits an earlier Creation time + // then it will be accepted + quint64 now = usecTimestampNow(); + tempProperties.setCreated(now); + tempProperties.setLastEdited(now); return constructEntityItem(entityType, tempEntityID, tempProperties); } From 2be3b73e8c81da64f53fe10379f426d8c9fa9e91 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 17 Dec 2014 12:32:52 -0800 Subject: [PATCH 474/502] move TextRender to libraries/render-utils --- interface/src/Application.cpp | 2 +- interface/src/Util.cpp | 6 +++--- interface/src/avatar/Avatar.cpp | 2 +- interface/src/avatar/MyAvatar.cpp | 2 +- interface/src/devices/PrioVR.cpp | 2 +- interface/src/entities/RenderableTextEntityItem.cpp | 2 +- interface/src/ui/BandwidthMeter.h | 2 +- interface/src/ui/overlays/Text3DOverlay.cpp | 3 ++- interface/src/ui/overlays/TextOverlay.cpp | 2 +- .../src/ui => libraries/render-utils/src}/TextRenderer.cpp | 3 ++- .../src/ui => libraries/render-utils/src}/TextRenderer.h | 7 ++++--- 11 files changed, 18 insertions(+), 15 deletions(-) rename {interface/src/ui => libraries/render-utils/src}/TextRenderer.cpp (99%) rename {interface/src/ui => libraries/render-utils/src}/TextRenderer.h (97%) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 1453cec53b..62f06f81d5 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -73,6 +73,7 @@ #include #include #include +#include #include #include @@ -109,7 +110,6 @@ #include "ui/InfoView.h" #include "ui/Snapshot.h" #include "ui/Stats.h" -#include "ui/TextRenderer.h" diff --git a/interface/src/Util.cpp b/interface/src/Util.cpp index 6d40726f14..458640820b 100644 --- a/interface/src/Util.cpp +++ b/interface/src/Util.cpp @@ -19,12 +19,12 @@ #include #include -#include - #include +#include +#include + #include "InterfaceConfig.h" -#include "ui/TextRenderer.h" #include "VoxelConstants.h" #include "world.h" #include "Application.h" diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 51fde3df43..81d7920783 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include "Application.h" @@ -42,7 +43,6 @@ #include "Recorder.h" #include "world.h" #include "devices/OculusManager.h" -#include "ui/TextRenderer.h" using namespace std; diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 6976e26e86..37afd404dc 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include "Application.h" #include "Audio.h" @@ -41,7 +42,6 @@ #include "Recorder.h" #include "devices/Faceshift.h" #include "devices/OculusManager.h" -#include "ui/TextRenderer.h" using namespace std; diff --git a/interface/src/devices/PrioVR.cpp b/interface/src/devices/PrioVR.cpp index d3e985d259..0417a50527 100644 --- a/interface/src/devices/PrioVR.cpp +++ b/interface/src/devices/PrioVR.cpp @@ -14,11 +14,11 @@ #include #include +#include #include "Application.h" #include "PrioVR.h" #include "scripting/JoystickScriptingInterface.h" -#include "ui/TextRenderer.h" #ifdef HAVE_PRIOVR const unsigned int SERIAL_LIST[] = { 0x00000001, 0x00000000, 0x00000008, 0x00000009, 0x0000000A, diff --git a/interface/src/entities/RenderableTextEntityItem.cpp b/interface/src/entities/RenderableTextEntityItem.cpp index 5a3d5df8f9..24f4a71295 100644 --- a/interface/src/entities/RenderableTextEntityItem.cpp +++ b/interface/src/entities/RenderableTextEntityItem.cpp @@ -13,9 +13,9 @@ #include #include +#include #include "RenderableTextEntityItem.h" -#include "ui/TextRenderer.h" const int FIXED_FONT_POINT_SIZE = 40; const float LINE_SCALE_RATIO = 1.2f; diff --git a/interface/src/ui/BandwidthMeter.h b/interface/src/ui/BandwidthMeter.h index 09353512d1..9931355f8e 100644 --- a/interface/src/ui/BandwidthMeter.h +++ b/interface/src/ui/BandwidthMeter.h @@ -16,7 +16,7 @@ #include -#include "ui/TextRenderer.h" +#include class BandwidthMeter { diff --git a/interface/src/ui/overlays/Text3DOverlay.cpp b/interface/src/ui/overlays/Text3DOverlay.cpp index 41e36cb396..9b80d873f9 100644 --- a/interface/src/ui/overlays/Text3DOverlay.cpp +++ b/interface/src/ui/overlays/Text3DOverlay.cpp @@ -11,9 +11,10 @@ // include this before QGLWidget, which includes an earlier version of OpenGL #include "InterfaceConfig.h" +#include + #include "Application.h" #include "Text3DOverlay.h" -#include "ui/TextRenderer.h" const xColor DEFAULT_BACKGROUND_COLOR = { 0, 0, 0 }; const float DEFAULT_BACKGROUND_ALPHA = 0.7f; diff --git a/interface/src/ui/overlays/TextOverlay.cpp b/interface/src/ui/overlays/TextOverlay.cpp index ae8a7cbcfe..97d910eb64 100644 --- a/interface/src/ui/overlays/TextOverlay.cpp +++ b/interface/src/ui/overlays/TextOverlay.cpp @@ -13,9 +13,9 @@ #include #include +#include #include "TextOverlay.h" -#include "ui/TextRenderer.h" TextOverlay::TextOverlay() : _backgroundColor(DEFAULT_BACKGROUND_COLOR), diff --git a/interface/src/ui/TextRenderer.cpp b/libraries/render-utils/src/TextRenderer.cpp similarity index 99% rename from interface/src/ui/TextRenderer.cpp rename to libraries/render-utils/src/TextRenderer.cpp index fce4c76c0d..34098c6862 100644 --- a/interface/src/ui/TextRenderer.cpp +++ b/libraries/render-utils/src/TextRenderer.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include + #include #include #include @@ -18,7 +20,6 @@ #include #include -#include "InterfaceConfig.h" #include "TextRenderer.h" #include "glm/glm.hpp" diff --git a/interface/src/ui/TextRenderer.h b/libraries/render-utils/src/TextRenderer.h similarity index 97% rename from interface/src/ui/TextRenderer.h rename to libraries/render-utils/src/TextRenderer.h index 2ffd8b24b7..078efb0463 100644 --- a/interface/src/ui/TextRenderer.h +++ b/libraries/render-utils/src/TextRenderer.h @@ -12,6 +12,8 @@ #ifndef hifi_TextRenderer_h #define hifi_TextRenderer_h +#include + #include #include #include @@ -19,11 +21,10 @@ #include #include -#include "gpu/Resource.h" -#include "gpu/Stream.h" +#include +#include -#include "InterfaceConfig.h" // a special "character" that renders as a solid block const char SOLID_BLOCK_CHAR = 127; From cb7f5a5b45b072245d05c873d2b2f60a5e1c586e Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 17 Dec 2014 12:41:58 -0800 Subject: [PATCH 475/502] Roll gridTool.js back temporarily --- examples/libraries/gridTool.js | 74 +++++----------------------------- 1 file changed, 11 insertions(+), 63 deletions(-) diff --git a/examples/libraries/gridTool.js b/examples/libraries/gridTool.js index b1c258dc31..7d98befec8 100644 --- a/examples/libraries/gridTool.js +++ b/examples/libraries/gridTool.js @@ -1,9 +1,3 @@ -var SETTING_GRID_VISIBLE = 'gridVisible'; -var SETTING_GRID_SNAP_TO_GRID = 'gridSnapToGrid'; -var SETTING_GRID_MINOR_WIDTH= 'gridMinorWidth'; -var SETTING_GRID_MAJOR_EVERY = 'gridMajorEvery'; -var SETTING_GRID_COLOR = 'gridColor'; - Grid = function(opts) { var that = {}; @@ -18,6 +12,9 @@ Grid = function(opts) { var worldSize = 16384; + var minorGridWidth = 0.5; + var majorGridWidth = 1.5; + var snapToGrid = false; var gridOverlay = Overlays.addOverlay("grid", { @@ -26,7 +23,7 @@ Grid = function(opts) { color: { red: 0, green: 0, blue: 128 }, alpha: 1.0, rotation: Quat.fromPitchYawRollDegrees(90, 0, 0), - minorGridSpacing: 0.1, + minorGridWidth: 0.1, majorGridEvery: 2, }); @@ -43,37 +40,16 @@ Grid = function(opts) { that.getSnapToGrid = function() { return snapToGrid; }; that.setEnabled = function(enabled) { - if (that.enabled != enabled) { - that.enabled = enabled; - - if (enabled) { - if (selectionManager.hasSelection()) { - that.setPosition(selectionManager.getBottomPosition()); - } else { - that.setPosition(MyAvatar.position); - } - } - - updateGrid(); - } + that.enabled = enabled; + updateGrid(); } that.setVisible = function(visible, noUpdate) { - if (visible != that.visible) { - that.visible = visible; - updateGrid(); + that.visible = visible; + updateGrid(); - if (visible) { - if (selectionManager.hasSelection()) { - that.setPosition(selectionManager.getBottomPosition()); - } else { - that.setPosition(MyAvatar.position); - } - } - - if (!noUpdate) { - that.emitUpdate(); - } + if (!noUpdate) { + that.emitUpdate(); } } @@ -205,43 +181,15 @@ Grid = function(opts) { } function cleanup() { - saveSettings(); - Overlays.deleteOverlay(gridOverlay); } - function loadSettings() { - that.setVisible(Settings.getValue(SETTING_GRID_VISIBLE) == "true", true); - snapToGrid = Settings.getValue(SETTING_GRID_SNAP_TO_GRID) == "true"; - minorGridSpacing = parseFloat(Settings.getValue(SETTING_GRID_MINOR_WIDTH), 10); - majorGridEvery = parseInt(Settings.getValue(SETTING_GRID_MAJOR_EVERY), 10); - try { - var newColor = JSON.parse(Settings.getValue(SETTING_GRID_COLOR)); - if (newColor.red !== undefined && newColor.green !== undefined && newColor.blue !== undefined) { - gridColor.red = newColor.red; - gridColor.green = newColor.green; - gridColor.blue = newColor.blue; - } - } catch (e) { - } - updateGrid(); - } - - function saveSettings() { - Settings.setValue(SETTING_GRID_VISIBLE, that.visible); - Settings.setValue(SETTING_GRID_SNAP_TO_GRID, snapToGrid); - Settings.setValue(SETTING_GRID_MINOR_WIDTH, minorGridSpacing); - Settings.setValue(SETTING_GRID_MAJOR_EVERY, majorGridEvery); - Settings.setValue(SETTING_GRID_COLOR, JSON.stringify(gridColor)); - } - that.addListener = function(callback) { that.onUpdate = callback; } Script.scriptEnding.connect(cleanup); - - loadSettings(); + updateGrid(); that.onUpdate = null; From 9f9b8bcb68432c8a511f17d8f1f1b63b1c6d0d54 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 17 Dec 2014 12:54:41 -0800 Subject: [PATCH 476/502] move interface/entities to libraries/entities-renderer --- interface/CMakeLists.txt | 3 +- interface/src/Application.h | 2 +- libraries/entities-renderer/CMakeLists.txt | 37 +++++++++++++++++++ .../src}/EntityTreeRenderer.cpp | 0 .../src}/EntityTreeRenderer.h | 0 .../src}/RenderableBoxEntityItem.cpp | 0 .../src}/RenderableBoxEntityItem.h | 0 .../src}/RenderableLightEntityItem.cpp | 0 .../src}/RenderableLightEntityItem.h | 0 .../src}/RenderableModelEntityItem.cpp | 0 .../src}/RenderableModelEntityItem.h | 0 .../src}/RenderableSphereEntityItem.cpp | 0 .../src}/RenderableSphereEntityItem.h | 0 .../src}/RenderableTextEntityItem.cpp | 0 .../src}/RenderableTextEntityItem.h | 0 15 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 libraries/entities-renderer/CMakeLists.txt rename {interface/src/entities => libraries/entities-renderer/src}/EntityTreeRenderer.cpp (100%) rename {interface/src/entities => libraries/entities-renderer/src}/EntityTreeRenderer.h (100%) rename {interface/src/entities => libraries/entities-renderer/src}/RenderableBoxEntityItem.cpp (100%) rename {interface/src/entities => libraries/entities-renderer/src}/RenderableBoxEntityItem.h (100%) rename {interface/src/entities => libraries/entities-renderer/src}/RenderableLightEntityItem.cpp (100%) rename {interface/src/entities => libraries/entities-renderer/src}/RenderableLightEntityItem.h (100%) rename {interface/src/entities => libraries/entities-renderer/src}/RenderableModelEntityItem.cpp (100%) rename {interface/src/entities => libraries/entities-renderer/src}/RenderableModelEntityItem.h (100%) rename {interface/src/entities => libraries/entities-renderer/src}/RenderableSphereEntityItem.cpp (100%) rename {interface/src/entities => libraries/entities-renderer/src}/RenderableSphereEntityItem.h (100%) rename {interface/src/entities => libraries/entities-renderer/src}/RenderableTextEntityItem.cpp (100%) rename {interface/src/entities => libraries/entities-renderer/src}/RenderableTextEntityItem.h (100%) diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index ffc401ba63..8c7b7b2211 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -107,7 +107,8 @@ endif() add_executable(${TARGET_NAME} MACOSX_BUNDLE ${INTERFACE_SRCS} ${QM}) # link required hifi libraries -link_hifi_libraries(shared octree voxels gpu fbx metavoxels networking entities avatars audio animation script-engine physics render-utils) +link_hifi_libraries(shared octree voxels gpu fbx metavoxels networking entities avatars audio animation script-engine physics + render-utils entities-renderer) # find any optional and required libraries find_package(ZLIB REQUIRED) diff --git a/interface/src/Application.h b/interface/src/Application.h index d192a9abe6..7a727d07b5 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -62,7 +63,6 @@ #include "avatar/MyAvatar.h" #include "devices/PrioVR.h" #include "devices/SixenseManager.h" -#include "entities/EntityTreeRenderer.h" #include "scripting/ControllerScriptingInterface.h" #include "ui/BandwidthDialog.h" #include "ui/BandwidthMeter.h" diff --git a/libraries/entities-renderer/CMakeLists.txt b/libraries/entities-renderer/CMakeLists.txt new file mode 100644 index 0000000000..5744ea0b7b --- /dev/null +++ b/libraries/entities-renderer/CMakeLists.txt @@ -0,0 +1,37 @@ +set(TARGET_NAME entities-renderer) + +# use setup_hifi_library macro to setup our project and link appropriate Qt modules +setup_hifi_library(Widgets OpenGL Network Script) + +include_glm() + +link_hifi_libraries(shared gpu) +if (APPLE) + # link in required OS X frameworks and include the right GL headers + find_library(OpenGL OpenGL) + + #target_link_libraries(${TARGET_NAME} ${OpenGL}) + +else (APPLE) + find_package(OpenGL REQUIRED) + + if (${OPENGL_INCLUDE_DIR}) + include_directories(SYSTEM "${OPENGL_INCLUDE_DIR}") + endif () + + # link target to external libraries + if (WIN32) + find_package(GLEW REQUIRED) + include_directories(${GLEW_INCLUDE_DIRS}) + + find_package(GLUT REQUIRED) + include_directories(SYSTEM "${GLUT_INCLUDE_DIRS}") + + # we're using static GLEW, so define GLEW_STATIC + add_definitions(-DGLEW_STATIC) + target_link_libraries(${TARGET_NAME} "${GLEW_LIBRARIES}") + endif() +endif (APPLE) + +# call macro to link our dependencies and bubble them up via a property on our target +link_shared_dependencies() diff --git a/interface/src/entities/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp similarity index 100% rename from interface/src/entities/EntityTreeRenderer.cpp rename to libraries/entities-renderer/src/EntityTreeRenderer.cpp diff --git a/interface/src/entities/EntityTreeRenderer.h b/libraries/entities-renderer/src/EntityTreeRenderer.h similarity index 100% rename from interface/src/entities/EntityTreeRenderer.h rename to libraries/entities-renderer/src/EntityTreeRenderer.h diff --git a/interface/src/entities/RenderableBoxEntityItem.cpp b/libraries/entities-renderer/src/RenderableBoxEntityItem.cpp similarity index 100% rename from interface/src/entities/RenderableBoxEntityItem.cpp rename to libraries/entities-renderer/src/RenderableBoxEntityItem.cpp diff --git a/interface/src/entities/RenderableBoxEntityItem.h b/libraries/entities-renderer/src/RenderableBoxEntityItem.h similarity index 100% rename from interface/src/entities/RenderableBoxEntityItem.h rename to libraries/entities-renderer/src/RenderableBoxEntityItem.h diff --git a/interface/src/entities/RenderableLightEntityItem.cpp b/libraries/entities-renderer/src/RenderableLightEntityItem.cpp similarity index 100% rename from interface/src/entities/RenderableLightEntityItem.cpp rename to libraries/entities-renderer/src/RenderableLightEntityItem.cpp diff --git a/interface/src/entities/RenderableLightEntityItem.h b/libraries/entities-renderer/src/RenderableLightEntityItem.h similarity index 100% rename from interface/src/entities/RenderableLightEntityItem.h rename to libraries/entities-renderer/src/RenderableLightEntityItem.h diff --git a/interface/src/entities/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp similarity index 100% rename from interface/src/entities/RenderableModelEntityItem.cpp rename to libraries/entities-renderer/src/RenderableModelEntityItem.cpp diff --git a/interface/src/entities/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h similarity index 100% rename from interface/src/entities/RenderableModelEntityItem.h rename to libraries/entities-renderer/src/RenderableModelEntityItem.h diff --git a/interface/src/entities/RenderableSphereEntityItem.cpp b/libraries/entities-renderer/src/RenderableSphereEntityItem.cpp similarity index 100% rename from interface/src/entities/RenderableSphereEntityItem.cpp rename to libraries/entities-renderer/src/RenderableSphereEntityItem.cpp diff --git a/interface/src/entities/RenderableSphereEntityItem.h b/libraries/entities-renderer/src/RenderableSphereEntityItem.h similarity index 100% rename from interface/src/entities/RenderableSphereEntityItem.h rename to libraries/entities-renderer/src/RenderableSphereEntityItem.h diff --git a/interface/src/entities/RenderableTextEntityItem.cpp b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp similarity index 100% rename from interface/src/entities/RenderableTextEntityItem.cpp rename to libraries/entities-renderer/src/RenderableTextEntityItem.cpp diff --git a/interface/src/entities/RenderableTextEntityItem.h b/libraries/entities-renderer/src/RenderableTextEntityItem.h similarity index 100% rename from interface/src/entities/RenderableTextEntityItem.h rename to libraries/entities-renderer/src/RenderableTextEntityItem.h From 881119ebf3f87112db8c29a904fb216517d393bc Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 17 Dec 2014 13:23:12 -0800 Subject: [PATCH 477/502] removed dead code --- .../script-engine/src/AbstractScriptingServicesInterface.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/libraries/script-engine/src/AbstractScriptingServicesInterface.h b/libraries/script-engine/src/AbstractScriptingServicesInterface.h index 5e7ad81f67..9d24531b60 100644 --- a/libraries/script-engine/src/AbstractScriptingServicesInterface.h +++ b/libraries/script-engine/src/AbstractScriptingServicesInterface.h @@ -12,8 +12,6 @@ #ifndef hifi_AbstractScriptingServicesInterface_h #define hifi_AbstractScriptingServicesInterface_h -//#include - class AbstractControllerScriptingInterface; class Transform; class ScriptEngine; From 7db350eac29057728fd28e5a415f62b7ec8758bb Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 17 Dec 2014 14:07:26 -0800 Subject: [PATCH 478/502] remove calls to glut in entities --- .../src/EntityTreeRenderer.cpp | 29 +++++++++---------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 5654b416f1..7253b96480 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -11,8 +11,6 @@ #include -#include // TODO - we need to get rid of this ASAP - #include #include @@ -20,6 +18,7 @@ #include #include +#include #include #include #include @@ -358,7 +357,7 @@ void EntityTreeRenderer::renderElementProxy(EntityTreeElement* entityTreeElement glColor3f(1.0f, 0.0f, 0.0f); glPushMatrix(); glTranslatef(elementCenter.x, elementCenter.y, elementCenter.z); - glutWireCube(elementSize); + DependencyManager::get()->renderWireCube(elementSize); glPopMatrix(); if (_displayElementChildProxies) { @@ -368,49 +367,49 @@ void EntityTreeRenderer::renderElementProxy(EntityTreeElement* entityTreeElement glColor3f(1.0f, 1.0f, 0.0f); glPushMatrix(); glTranslatef(elementCenter.x - quarterSize, elementCenter.y - quarterSize, elementCenter.z - quarterSize); - glutWireCube(halfSize); + DependencyManager::get()->renderWireCube(halfSize); glPopMatrix(); glColor3f(1.0f, 0.0f, 1.0f); glPushMatrix(); glTranslatef(elementCenter.x + quarterSize, elementCenter.y - quarterSize, elementCenter.z - quarterSize); - glutWireCube(halfSize); + DependencyManager::get()->renderWireCube(halfSize); glPopMatrix(); glColor3f(0.0f, 1.0f, 0.0f); glPushMatrix(); glTranslatef(elementCenter.x - quarterSize, elementCenter.y + quarterSize, elementCenter.z - quarterSize); - glutWireCube(halfSize); + DependencyManager::get()->renderWireCube(halfSize); glPopMatrix(); glColor3f(0.0f, 0.0f, 1.0f); glPushMatrix(); glTranslatef(elementCenter.x - quarterSize, elementCenter.y - quarterSize, elementCenter.z + quarterSize); - glutWireCube(halfSize); + DependencyManager::get()->renderWireCube(halfSize); glPopMatrix(); glColor3f(1.0f, 1.0f, 1.0f); glPushMatrix(); glTranslatef(elementCenter.x + quarterSize, elementCenter.y + quarterSize, elementCenter.z + quarterSize); - glutWireCube(halfSize); + DependencyManager::get()->renderWireCube(halfSize); glPopMatrix(); glColor3f(0.0f, 0.5f, 0.5f); glPushMatrix(); glTranslatef(elementCenter.x - quarterSize, elementCenter.y + quarterSize, elementCenter.z + quarterSize); - glutWireCube(halfSize); + DependencyManager::get()->renderWireCube(halfSize); glPopMatrix(); glColor3f(0.5f, 0.0f, 0.0f); glPushMatrix(); glTranslatef(elementCenter.x + quarterSize, elementCenter.y - quarterSize, elementCenter.z + quarterSize); - glutWireCube(halfSize); + DependencyManager::get()->renderWireCube(halfSize); glPopMatrix(); glColor3f(0.0f, 0.5f, 0.0f); glPushMatrix(); glTranslatef(elementCenter.x + quarterSize, elementCenter.y + quarterSize, elementCenter.z - quarterSize); - glutWireCube(halfSize); + DependencyManager::get()->renderWireCube(halfSize); glPopMatrix(); } } @@ -437,14 +436,14 @@ void EntityTreeRenderer::renderProxies(const EntityItem* entity, RenderArgs* arg glColor4f(1.0f, 1.0f, 0.0f, 1.0f); glPushMatrix(); glTranslatef(maxCenter.x, maxCenter.y, maxCenter.z); - glutWireCube(maxCube.getScale()); + DependencyManager::get()->renderWireCube(maxCube.getScale()); glPopMatrix(); // draw the min bounding cube glColor4f(0.0f, 1.0f, 0.0f, 1.0f); glPushMatrix(); glTranslatef(minCenter.x, minCenter.y, minCenter.z); - glutWireCube(minCube.getScale()); + DependencyManager::get()->renderWireCube(minCube.getScale()); glPopMatrix(); // draw the entityBox bounding box @@ -452,7 +451,7 @@ void EntityTreeRenderer::renderProxies(const EntityItem* entity, RenderArgs* arg glPushMatrix(); glTranslatef(entityBoxCenter.x, entityBoxCenter.y, entityBoxCenter.z); glScalef(entityBoxScale.x, entityBoxScale.y, entityBoxScale.z); - glutWireCube(1.0f); + DependencyManager::get()->renderWireCube(1.0f); glPopMatrix(); @@ -470,7 +469,7 @@ void EntityTreeRenderer::renderProxies(const EntityItem* entity, RenderArgs* arg glm::vec3 positionToCenter = center - position; glTranslatef(positionToCenter.x, positionToCenter.y, positionToCenter.z); glScalef(dimensions.x, dimensions.y, dimensions.z); - glutWireCube(1.0f); + DependencyManager::get()->renderWireCube(1.0f); glPopMatrix(); glPopMatrix(); } From 1e5c44f117c9d3ea47681feabaa86caa7e598bbf Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 17 Dec 2014 15:48:49 -0800 Subject: [PATCH 479/502] accept changes with the same Edit timestamp --- libraries/entities/src/EntityItem.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 22cfeb3674..f62cd278c8 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -109,9 +109,6 @@ EntityItem::EntityItem(const EntityItemID& entityItemID, const EntityItemPropert _changedOnServer = 0; initFromEntityItemID(entityItemID); setProperties(properties, true); // force copy - if (_lastEdited == 0) { - _lastEdited = _created; - } } EntityPropertyFlags EntityItem::getEntityProperties(EncodeBitstreamParams& params) const { @@ -424,14 +421,14 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef if (fromSameServerEdit) { // If this is from the same sever packet, then check against any local changes since we got // the most recent packet from this server time - if (_lastEdited >= _lastEditedFromRemote) { + if (_lastEdited > _lastEditedFromRemote) { ignoreServerPacket = true; } } else { // If this isn't from the same sever packet, then honor our skew adjusted times... // If we've changed our local tree more recently than the new data from this packet // then we will not be changing our values, instead we just read and skip the data - if (_lastEdited >= lastEditedFromBufferAdjusted) { + if (_lastEdited > lastEditedFromBufferAdjusted) { ignoreServerPacket = true; } } From 44ebf37510e971cc6c0410ebc6ee7b5b4e4cb052 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 17 Dec 2014 15:52:34 -0800 Subject: [PATCH 480/502] handle case where obj at rest but still falls --- libraries/entities/src/EntityItem.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index f62cd278c8..4ad2770d05 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -650,7 +650,7 @@ void EntityItem::simulate(const quint64& now) { } } - if (hasVelocity()) { + if (hasVelocity() || hasGravity()) { glm::vec3 position = getPosition(); glm::vec3 velocity = getVelocity(); glm::vec3 newPosition = position + (velocity * timeElapsed); @@ -731,7 +731,7 @@ void EntityItem::simulate(const quint64& now) { } bool EntityItem::isMoving() const { - return hasVelocity() || hasAngularVelocity(); + return hasVelocity() (hasGravity() && !isRestingOnSurface()) || hasAngularVelocity(); } bool EntityItem::lifetimeHasExpired() const { From ef42203481b67d9f368dee3484f84345bd2f8960 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 17 Dec 2014 15:58:52 -0800 Subject: [PATCH 481/502] add wire cube implementation to GeometryCache and DeferredLightingEffect --- libraries/render-utils/src/DeferredLightingEffect.cpp | 2 +- libraries/render-utils/src/GeometryCache.cpp | 8 ++++++-- libraries/render-utils/src/GeometryCache.h | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 14d383418f..065ca3a741 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -68,7 +68,7 @@ void DeferredLightingEffect::renderSolidSphere(float radius, int slices, int sta void DeferredLightingEffect::renderWireSphere(float radius, int slices, int stacks) { bindSimpleProgram(); - glutWireSphere(radius, slices, stacks); + DependencyManager::get()->renderSphere(radius, slices, stacks, false); releaseSimpleProgram(); } diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index 56092945a2..a770d942fe 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -119,7 +119,7 @@ const int NUM_COORDS_PER_VERTEX = 3; const int NUM_BYTES_PER_VERTEX = NUM_COORDS_PER_VERTEX * sizeof(GLfloat); const int NUM_BYTES_PER_INDEX = sizeof(GLushort); -void GeometryCache::renderSphere(float radius, int slices, int stacks) { +void GeometryCache::renderSphere(float radius, int slices, int stacks, bool solid) { VerticesIndices& vbo = _sphereVBOs[IntPair(slices, stacks)]; int vertices = slices * (stacks - 1) + 2; int indices = slices * stacks * NUM_VERTICES_PER_TRIANGULATED_QUAD; @@ -211,7 +211,11 @@ void GeometryCache::renderSphere(float radius, int slices, int stacks) { glPushMatrix(); glScalef(radius, radius, radius); - glDrawRangeElementsEXT(GL_TRIANGLES, 0, vertices - 1, indices, GL_UNSIGNED_SHORT, 0); + if (solid) { + glDrawRangeElementsEXT(GL_TRIANGLES, 0, vertices - 1, indices, GL_UNSIGNED_SHORT, 0); + } else { + glDrawRangeElementsEXT(GL_LINES, 0, vertices - 1, indices, GL_UNSIGNED_SHORT, 0); + } glPopMatrix(); glDisableClientState(GL_VERTEX_ARRAY); diff --git a/libraries/render-utils/src/GeometryCache.h b/libraries/render-utils/src/GeometryCache.h index 97f24f94a3..f0045c10bf 100644 --- a/libraries/render-utils/src/GeometryCache.h +++ b/libraries/render-utils/src/GeometryCache.h @@ -38,7 +38,7 @@ class GeometryCache : public ResourceCache { public: void renderHemisphere(int slices, int stacks); - void renderSphere(float radius, int slices, int stacks); + void renderSphere(float radius, int slices, int stacks, bool solid = true); void renderSquare(int xDivisions, int yDivisions); void renderHalfCylinder(int slices, int stacks); void renderCone(float base, float height, int slices, int stacks); From 75d468da9e14f0f1a8b9a65bb9ab357e36f01ed9 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 17 Dec 2014 15:59:16 -0800 Subject: [PATCH 482/502] set _lastEdited to _created rather than to zero --- libraries/entities/src/EntityItem.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 4ad2770d05..a72eb86b0c 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -368,10 +368,9 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef createdFromBuffer -= clockSkew; if (createdFromBuffer < _created) { - // the server claims that this entity has an older creation time - // so we accept it and clear _lastEdited + // the server claims that this entity has an older creation time so we accept it _created = createdFromBuffer; - _lastEdited = 0; + _lastEdited = _created; } if (wantDebug) { From 756d09d895465452d27255565805cb3968b5f696 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 17 Dec 2014 16:06:15 -0800 Subject: [PATCH 483/502] fix typo that broke the build --- libraries/entities/src/EntityItem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index a72eb86b0c..cd34cd55c6 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -730,7 +730,7 @@ void EntityItem::simulate(const quint64& now) { } bool EntityItem::isMoving() const { - return hasVelocity() (hasGravity() && !isRestingOnSurface()) || hasAngularVelocity(); + return hasVelocity() || (hasGravity() && !isRestingOnSurface()) || hasAngularVelocity(); } bool EntityItem::lifetimeHasExpired() const { From adf51bfeb82df214c6b5e76899cbee63ec104e3a Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 17 Dec 2014 16:41:28 -0800 Subject: [PATCH 484/502] temp disable visage to get to C++11 support --- cmake/modules/FindVisage.cmake | 13 +++++++------ interface/CMakeLists.txt | 3 +-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/cmake/modules/FindVisage.cmake b/cmake/modules/FindVisage.cmake index 96176a2648..2b288f4681 100644 --- a/cmake/modules/FindVisage.cmake +++ b/cmake/modules/FindVisage.cmake @@ -32,9 +32,10 @@ if (APPLE) find_library(VISAGE_VISION_LIBRARY NAME vsvision PATH_SUFFIXES lib HINTS ${VISAGE_SEARCH_DIRS}) find_library(VISAGE_OPENCV_LIBRARY NAME OpenCV PATH_SUFFIXES dependencies/OpenCV_MacOSX/lib HINTS ${VISAGE_SEARCH_DIRS}) - find_library(AppKit AppKit) - find_library(QuartzCore QuartzCore) + find_library(CoreVideo CoreVideo) find_library(QTKit QTKit) + find_library(IOKit IOKit) + elseif (WIN32) find_path(VISAGE_XML_INCLUDE_DIR libxml/xmlreader.h PATH_SUFFIXES dependencies/libxml2/include HINTS ${VISAGE_SEARCH_DIRS}) find_path(VISAGE_OPENCV_INCLUDE_DIR opencv/cv.h PATH_SUFFIXES dependencies/OpenCV/include HINTS ${VISAGE_SEARCH_DIRS}) @@ -49,19 +50,19 @@ include(FindPackageHandleStandardArgs) list(APPEND VISAGE_ARGS_LIST VISAGE_BASE_INCLUDE_DIR VISAGE_XML_INCLUDE_DIR VISAGE_OPENCV_INCLUDE_DIR VISAGE_OPENCV2_INCLUDE_DIR - VISAGE_CORE_LIBRARY VISAGE_VISION_LIBRARY VISAGE_OPENCV_LIBRARY) + VISAGE_CORE_LIBRARY VISAGE_VISION_LIBRARY) if (APPLE) - list(APPEND VISAGE_ARGS_LIST QuartzCore AppKit QTKit) + list(APPEND VISAGE_ARGS_LIST CoreVideo QTKit IOKit) endif () find_package_handle_standard_args(Visage DEFAULT_MSG ${VISAGE_ARGS_LIST}) set(VISAGE_INCLUDE_DIRS "${VISAGE_XML_INCLUDE_DIR}" "${VISAGE_OPENCV_INCLUDE_DIR}" "${VISAGE_OPENCV2_INCLUDE_DIR}" "${VISAGE_BASE_INCLUDE_DIR}") -set(VISAGE_LIBRARIES "${VISAGE_CORE_LIBRARY}" "${VISAGE_VISION_LIBRARY}" "${VISAGE_OPENCV_LIBRARY}") +set(VISAGE_LIBRARIES "${VISAGE_CORE_LIBRARY}" "${VISAGE_VISION_LIBRARY}") if (APPLE) - list(APPEND VISAGE_LIBRARIES ${QuartzCore} ${AppKit} ${QTKit}) + list(APPEND VISAGE_LIBRARIES "${CoreVideo}" "${QTKit}" "${IOKit}") endif () mark_as_advanced(VISAGE_INCLUDE_DIRS VISAGE_LIBRARIES) diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index ffc401ba63..78f4cbd6a6 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" "LibOVR" "PrioVR" "Sixense" "Visage" "LeapMotion" "RtMidi" "Qxmpp" "SDL2" "Gverb") +set(OPTIONAL_EXTERNALS "Faceshift" "LibOVR" "PrioVR" "Sixense" "LeapMotion" "RtMidi" "Qxmpp" "SDL2" "Gverb") foreach(EXTERNAL ${OPTIONAL_EXTERNALS}) string(TOUPPER ${EXTERNAL} ${EXTERNAL}_UPPERCASE) if (NOT ${${EXTERNAL}_UPPERCASE}_ROOT_DIR) @@ -156,7 +156,6 @@ if (VISAGE_FOUND AND NOT DISABLE_VISAGE AND APPLE) SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-comment") find_library(AVFoundation AVFoundation) find_library(CoreMedia CoreMedia) - find_library(NEW_STD_LIBRARY libc++.dylib /usr/lib/) target_link_libraries(${TARGET_NAME} ${AVFoundation} ${CoreMedia} ${NEW_STD_LIBRARY}) endif () From b202eb7dae01b9a878f3e7c87d349ac9b5db63b6 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 18 Dec 2014 09:14:44 -0800 Subject: [PATCH 485/502] DRY up gpu library/header linking --- libraries/entities-renderer/CMakeLists.txt | 28 +------------- libraries/gpu/CMakeLists.txt | 44 +++++++++++----------- libraries/render-utils/CMakeLists.txt | 26 ------------- 3 files changed, 24 insertions(+), 74 deletions(-) diff --git a/libraries/entities-renderer/CMakeLists.txt b/libraries/entities-renderer/CMakeLists.txt index 5744ea0b7b..1e77afe544 100644 --- a/libraries/entities-renderer/CMakeLists.txt +++ b/libraries/entities-renderer/CMakeLists.txt @@ -5,33 +5,7 @@ setup_hifi_library(Widgets OpenGL Network Script) include_glm() -link_hifi_libraries(shared gpu) -if (APPLE) - # link in required OS X frameworks and include the right GL headers - find_library(OpenGL OpenGL) - - #target_link_libraries(${TARGET_NAME} ${OpenGL}) - -else (APPLE) - find_package(OpenGL REQUIRED) - - if (${OPENGL_INCLUDE_DIR}) - include_directories(SYSTEM "${OPENGL_INCLUDE_DIR}") - endif () - - # link target to external libraries - if (WIN32) - find_package(GLEW REQUIRED) - include_directories(${GLEW_INCLUDE_DIRS}) - - find_package(GLUT REQUIRED) - include_directories(SYSTEM "${GLUT_INCLUDE_DIRS}") - - # we're using static GLEW, so define GLEW_STATIC - add_definitions(-DGLEW_STATIC) - target_link_libraries(${TARGET_NAME} "${GLEW_LIBRARIES}") - endif() -endif (APPLE) +link_hifi_libraries(shared gpu script-engine) # call macro to link our dependencies and bubble them up via a property on our target link_shared_dependencies() diff --git a/libraries/gpu/CMakeLists.txt b/libraries/gpu/CMakeLists.txt index 577f9f7a58..340adcc9e6 100644 --- a/libraries/gpu/CMakeLists.txt +++ b/libraries/gpu/CMakeLists.txt @@ -6,13 +6,32 @@ setup_hifi_library() include_glm() link_hifi_libraries(shared) + if (APPLE) # link in required OS X frameworks and include the right GL headers find_library(OpenGL OpenGL) target_link_libraries(${TARGET_NAME} ${OpenGL}) - -else (APPLE) +elseif (WIN32) + find_package(GLEW REQUIRED) + include_directories(${GLEW_INCLUDE_DIRS}) + + # we're using static GLEW, so define GLEW_STATIC + add_definitions(-DGLEW_STATIC) + + target_link_libraries(${TARGET_NAME} "${GLEW_LIBRARIES}" opengl32.lib) + + # need to bubble up the GLEW_INCLUDE_DIRS + list(APPEND ${TARGET_NAME}_DEPENDENCY_INCLUDES "${GLEW_INCLUDE_DIRS}") + + # try to find the Nsight package and add it to the build if we find it + find_package(NSIGHT) + if (NSIGHT_FOUND) + include_directories(${NSIGHT_INCLUDE_DIRS}) + add_definitions(-DNSIGHT_FOUND) + target_link_libraries(${TARGET_NAME} "${NSIGHT_LIBRARIES}") + endif () +else () find_package(OpenGL REQUIRED) if (${OPENGL_INCLUDE_DIR}) @@ -21,25 +40,8 @@ else (APPLE) target_link_libraries(${TARGET_NAME} "${OPENGL_LIBRARY}") - # link target to external libraries - if (WIN32) - find_package(GLEW REQUIRED) - include_directories(${GLEW_INCLUDE_DIRS}) - - # we're using static GLEW, so define GLEW_STATIC - add_definitions(-DGLEW_STATIC) - - target_link_libraries(${TARGET_NAME} "${GLEW_LIBRARIES}" "${NSIGHT_LIBRARIES}" opengl32.lib) - - # try to find the Nsight package and add it to the build if we find it - find_package(NSIGHT) - if (NSIGHT_FOUND) - include_directories(${NSIGHT_INCLUDE_DIRS}) - add_definitions(-DNSIGHT_FOUND) - target_link_libraries(${TARGET_NAME} "${NSIGHT_LIBRARIES}") - endif () - - endif() + # need to bubble up the OPENGL_INCLUDE_DIR + list(APPEND ${TARGET_NAME}_DEPENDENCY_INCLUDES "${OPENGL_INCLUDE_DIR}") endif (APPLE) # call macro to link our dependencies and bubble them up via a property on our target diff --git a/libraries/render-utils/CMakeLists.txt b/libraries/render-utils/CMakeLists.txt index 0244fa91a6..8d4f85a2ac 100644 --- a/libraries/render-utils/CMakeLists.txt +++ b/libraries/render-utils/CMakeLists.txt @@ -6,32 +6,6 @@ setup_hifi_library(Widgets OpenGL Network Script) include_glm() link_hifi_libraries(shared gpu) -if (APPLE) - # link in required OS X frameworks and include the right GL headers - find_library(OpenGL OpenGL) - - #target_link_libraries(${TARGET_NAME} ${OpenGL}) - -else (APPLE) - find_package(OpenGL REQUIRED) - - if (${OPENGL_INCLUDE_DIR}) - include_directories(SYSTEM "${OPENGL_INCLUDE_DIR}") - endif () - - # link target to external libraries - if (WIN32) - find_package(GLEW REQUIRED) - include_directories(${GLEW_INCLUDE_DIRS}) - - find_package(GLUT REQUIRED) - include_directories(SYSTEM "${GLUT_INCLUDE_DIRS}") - - # we're using static GLEW, so define GLEW_STATIC - add_definitions(-DGLEW_STATIC) - target_link_libraries(${TARGET_NAME} "${GLEW_LIBRARIES}") - endif() -endif (APPLE) # call macro to link our dependencies and bubble them up via a property on our target link_shared_dependencies() From d38c78f2c31f42e22c0ab84feac15e4bbbe1a4c5 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 18 Dec 2014 09:34:04 -0800 Subject: [PATCH 486/502] remove bubbling of linked libraries, cmake does it --- assignment-client/CMakeLists.txt | 2 +- cmake/macros/LinkHifiLibraries.cmake | 9 -------- cmake/macros/LinkSharedDependencies.cmake | 25 +---------------------- cmake/macros/SetupHifiLibrary.cmake | 7 +++++++ cmake/macros/SetupHifiProject.cmake | 7 +++++++ domain-server/CMakeLists.txt | 2 +- libraries/fbx/CMakeLists.txt | 2 +- libraries/networking/CMakeLists.txt | 2 +- libraries/octree/CMakeLists.txt | 2 +- libraries/voxels/CMakeLists.txt | 2 +- 10 files changed, 21 insertions(+), 39 deletions(-) diff --git a/assignment-client/CMakeLists.txt b/assignment-client/CMakeLists.txt index 69ad1cd815..6e31182f0d 100644 --- a/assignment-client/CMakeLists.txt +++ b/assignment-client/CMakeLists.txt @@ -12,7 +12,7 @@ link_hifi_libraries( ) if (UNIX) - list(APPEND ${TARGET_NAME}_LIBRARIES_TO_LINK ${CMAKE_DL_LIBS}) + target_link_libraries(${TARGET_NAME} ${CMAKE_DL_LIBS}) endif (UNIX) link_shared_dependencies() diff --git a/cmake/macros/LinkHifiLibraries.cmake b/cmake/macros/LinkHifiLibraries.cmake index 464af76553..646b680f27 100644 --- a/cmake/macros/LinkHifiLibraries.cmake +++ b/cmake/macros/LinkHifiLibraries.cmake @@ -25,18 +25,9 @@ macro(LINK_HIFI_LIBRARIES) # link the actual library - it is static so don't bubble it up target_link_libraries(${TARGET_NAME} ${HIFI_LIBRARY}) - # ask the library what its dynamic dependencies are and link them - get_target_property(LINKED_TARGET_DEPENDENCY_LIBRARIES ${HIFI_LIBRARY} DEPENDENCY_LIBRARIES) - list(APPEND ${TARGET_NAME}_LIBRARIES_TO_LINK ${LINKED_TARGET_DEPENDENCY_LIBRARIES}) - # ask the library what its include dependencies are and link them get_target_property(LINKED_TARGET_DEPENDENCY_INCLUDES ${HIFI_LIBRARY} DEPENDENCY_INCLUDES) list(APPEND ${TARGET_NAME}_DEPENDENCY_INCLUDES ${LINKED_TARGET_DEPENDENCY_INCLUDES}) - - # ask the library what its qt module dependencies are and link them - get_target_property(LINKED_TARGET_DEPENDENCY_QT_MODULES ${HIFI_LIBRARY} DEPENDENCY_QT_MODULES) - list(APPEND ${TARGET_NAME}_DEPENDENCY_QT_MODULES ${LINKED_TARGET_DEPENDENCY_QT_MODULES}) - endforeach() endmacro(LINK_HIFI_LIBRARIES) \ No newline at end of file diff --git a/cmake/macros/LinkSharedDependencies.cmake b/cmake/macros/LinkSharedDependencies.cmake index fd5461c288..9168c5a921 100644 --- a/cmake/macros/LinkSharedDependencies.cmake +++ b/cmake/macros/LinkSharedDependencies.cmake @@ -9,14 +9,7 @@ # See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html # -macro(LINK_SHARED_DEPENDENCIES) - if (${TARGET_NAME}_LIBRARIES_TO_LINK) - list(REMOVE_DUPLICATES ${TARGET_NAME}_LIBRARIES_TO_LINK) - - # link these libraries to our target - target_link_libraries(${TARGET_NAME} ${${TARGET_NAME}_LIBRARIES_TO_LINK}) - endif () - +macro(LINK_SHARED_DEPENDENCIES) if (${TARGET_NAME}_DEPENDENCY_INCLUDES) list(REMOVE_DUPLICATES ${TARGET_NAME}_DEPENDENCY_INCLUDES) @@ -24,22 +17,6 @@ macro(LINK_SHARED_DEPENDENCIES) include_directories(SYSTEM ${${TARGET_NAME}_DEPENDENCY_INCLUDES}) endif () - if (${TARGET_NAME}_DEPENDENCY_QT_MODULES) - list(REMOVE_DUPLICATES ${TARGET_NAME}_DEPENDENCY_QT_MODULES) - - # find these Qt modules and link them to our own target - find_package(Qt5 COMPONENTS ${${TARGET_NAME}_DEPENDENCY_QT_MODULES} REQUIRED) - - foreach(QT_MODULE ${${TARGET_NAME}_DEPENDENCY_QT_MODULES}) - target_link_libraries(${TARGET_NAME} Qt5::${QT_MODULE}) - endforeach() - endif () - - # we've already linked our Qt modules, but we need to bubble them up to parents - list(APPEND ${TARGET_NAME}_LIBRARIES_TO_LINK "${${TARGET_NAME}_QT_MODULES_TO_LINK}") - # set the property on this target so it can be retreived by targets linking to us - set_target_properties(${TARGET_NAME} PROPERTIES DEPENDENCY_LIBRARIES "${${TARGET_NAME}_LIBRARIES_TO_LINK}") set_target_properties(${TARGET_NAME} PROPERTIES DEPENDENCY_INCLUDES "${${TARGET_NAME}_DEPENDENCY_INCLUDES}") - set_target_properties(${TARGET_NAME} PROPERTIES DEPENDENCY_QT_MODULES "${${TARGET_NAME}_DEPENDENCY_QT_MODULES}") endmacro(LINK_SHARED_DEPENDENCIES) \ No newline at end of file diff --git a/cmake/macros/SetupHifiLibrary.cmake b/cmake/macros/SetupHifiLibrary.cmake index de9f9b9d1e..362a833862 100644 --- a/cmake/macros/SetupHifiLibrary.cmake +++ b/cmake/macros/SetupHifiLibrary.cmake @@ -21,4 +21,11 @@ macro(SETUP_HIFI_LIBRARY) set(${TARGET_NAME}_DEPENDENCY_QT_MODULES ${ARGN}) list(APPEND ${TARGET_NAME}_DEPENDENCY_QT_MODULES Core) + # find these Qt modules and link them to our own target + find_package(Qt5 COMPONENTS ${${TARGET_NAME}_DEPENDENCY_QT_MODULES} REQUIRED) + + foreach(QT_MODULE ${${TARGET_NAME}_DEPENDENCY_QT_MODULES}) + target_link_libraries(${TARGET_NAME} Qt5::${QT_MODULE}) + endforeach() + endmacro(SETUP_HIFI_LIBRARY) \ No newline at end of file diff --git a/cmake/macros/SetupHifiProject.cmake b/cmake/macros/SetupHifiProject.cmake index 157c22ea79..3f9787faa1 100644 --- a/cmake/macros/SetupHifiProject.cmake +++ b/cmake/macros/SetupHifiProject.cmake @@ -27,4 +27,11 @@ macro(SETUP_HIFI_PROJECT) set(${TARGET_NAME}_DEPENDENCY_QT_MODULES ${ARGN}) list(APPEND ${TARGET_NAME}_DEPENDENCY_QT_MODULES Core) + + # find these Qt modules and link them to our own target + find_package(Qt5 COMPONENTS ${${TARGET_NAME}_DEPENDENCY_QT_MODULES} REQUIRED) + + foreach(QT_MODULE ${${TARGET_NAME}_DEPENDENCY_QT_MODULES}) + target_link_libraries(${TARGET_NAME} Qt5::${QT_MODULE}) + endforeach() endmacro() \ No newline at end of file diff --git a/domain-server/CMakeLists.txt b/domain-server/CMakeLists.txt index b804ff27d3..b9f730baaf 100644 --- a/domain-server/CMakeLists.txt +++ b/domain-server/CMakeLists.txt @@ -50,6 +50,6 @@ endif () include_directories(SYSTEM "${OPENSSL_INCLUDE_DIR}") # append OpenSSL to our list of libraries to link -list(APPEND ${TARGET_NAME}_LIBRARIES_TO_LINK "${OPENSSL_LIBRARIES}") +target_link_libraries(${TARGET_NAME} "${OPENSSL_LIBRARIES}") link_shared_dependencies() \ No newline at end of file diff --git a/libraries/fbx/CMakeLists.txt b/libraries/fbx/CMakeLists.txt index 894fa14c33..2e58645b56 100644 --- a/libraries/fbx/CMakeLists.txt +++ b/libraries/fbx/CMakeLists.txt @@ -9,7 +9,7 @@ link_hifi_libraries(shared networking octree voxels) find_package(ZLIB REQUIRED) include_directories(SYSTEM "${ZLIB_INCLUDE_DIRS}") -list(APPEND ${TARGET_NAME}_LIBRARIES_TO_LINK "${ZLIB_LIBRARIES}") +target_link_libraries(${TARGET_NAME} "${ZLIB_LIBRARIES}") # call macro to link our dependencies and bubble them up via a property on our target link_shared_dependencies() diff --git a/libraries/networking/CMakeLists.txt b/libraries/networking/CMakeLists.txt index 7c8b628183..90e06bc13e 100644 --- a/libraries/networking/CMakeLists.txt +++ b/libraries/networking/CMakeLists.txt @@ -23,7 +23,7 @@ endif () include_directories(SYSTEM "${OPENSSL_INCLUDE_DIR}") # append OpenSSL to our list of libraries to link -list(APPEND ${TARGET_NAME}_LIBRARIES_TO_LINK "${OPENSSL_LIBRARIES}" "${TBB_LIBRARIES}") +target_link_libraries(${TARGET_NAME} "${OPENSSL_LIBRARIES}" "${TBB_LIBRARIES}") # append libcuckoo includes to our list of includes to bubble list(APPEND ${TARGET_NAME}_DEPENDENCY_INCLUDES "${TBB_INCLUDE_DIRS}") diff --git a/libraries/octree/CMakeLists.txt b/libraries/octree/CMakeLists.txt index 9aea2fdea1..f1a30f3724 100644 --- a/libraries/octree/CMakeLists.txt +++ b/libraries/octree/CMakeLists.txt @@ -13,7 +13,7 @@ find_package(ZLIB REQUIRED) include_directories(SYSTEM "${ZLIB_INCLUDE_DIRS}") # append ZLIB and OpenSSL to our list of libraries to link -list(APPEND ${TARGET_NAME}_LIBRARIES_TO_LINK "${ZLIB_LIBRARIES}") +target_link_libraries(${TARGET_NAME} "${ZLIB_LIBRARIES}") # call macro to link our dependencies and bubble them up via a property on our target link_shared_dependencies() diff --git a/libraries/voxels/CMakeLists.txt b/libraries/voxels/CMakeLists.txt index 3214978a2a..874a74ee95 100644 --- a/libraries/voxels/CMakeLists.txt +++ b/libraries/voxels/CMakeLists.txt @@ -12,7 +12,7 @@ find_package(ZLIB REQUIRED) include_directories(SYSTEM "${ZLIB_INCLUDE_DIRS}") # add it to our list of libraries to link -list(APPEND ${TARGET}_LIBRARIES_TO_LINK "${ZLIB_LIBRARIES}") +target_link_libraries(${TARGET_NAME} "${ZLIB_LIBRARIES}") # call macro to link our dependencies and bubble them up via a property on our target link_shared_dependencies() \ No newline at end of file From b326ab9839e4411927594799303cffb0ecf34393 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 18 Dec 2014 09:38:48 -0800 Subject: [PATCH 487/502] remove quotes from library links for debug/optimized --- domain-server/CMakeLists.txt | 2 +- libraries/fbx/CMakeLists.txt | 2 +- libraries/networking/CMakeLists.txt | 2 +- libraries/octree/CMakeLists.txt | 2 +- libraries/voxels/CMakeLists.txt | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/domain-server/CMakeLists.txt b/domain-server/CMakeLists.txt index b9f730baaf..482c397b14 100644 --- a/domain-server/CMakeLists.txt +++ b/domain-server/CMakeLists.txt @@ -50,6 +50,6 @@ endif () include_directories(SYSTEM "${OPENSSL_INCLUDE_DIR}") # append OpenSSL to our list of libraries to link -target_link_libraries(${TARGET_NAME} "${OPENSSL_LIBRARIES}") +target_link_libraries(${TARGET_NAME} ${OPENSSL_LIBRARIES}) link_shared_dependencies() \ No newline at end of file diff --git a/libraries/fbx/CMakeLists.txt b/libraries/fbx/CMakeLists.txt index 2e58645b56..5a151deb8b 100644 --- a/libraries/fbx/CMakeLists.txt +++ b/libraries/fbx/CMakeLists.txt @@ -9,7 +9,7 @@ link_hifi_libraries(shared networking octree voxels) find_package(ZLIB REQUIRED) include_directories(SYSTEM "${ZLIB_INCLUDE_DIRS}") -target_link_libraries(${TARGET_NAME} "${ZLIB_LIBRARIES}") +target_link_libraries(${TARGET_NAME} ${ZLIB_LIBRARIES}) # call macro to link our dependencies and bubble them up via a property on our target link_shared_dependencies() diff --git a/libraries/networking/CMakeLists.txt b/libraries/networking/CMakeLists.txt index 90e06bc13e..934e3e69b9 100644 --- a/libraries/networking/CMakeLists.txt +++ b/libraries/networking/CMakeLists.txt @@ -23,7 +23,7 @@ endif () include_directories(SYSTEM "${OPENSSL_INCLUDE_DIR}") # append OpenSSL to our list of libraries to link -target_link_libraries(${TARGET_NAME} "${OPENSSL_LIBRARIES}" "${TBB_LIBRARIES}") +target_link_libraries(${TARGET_NAME} ${OPENSSL_LIBRARIES} ${TBB_LIBRARIES}) # append libcuckoo includes to our list of includes to bubble list(APPEND ${TARGET_NAME}_DEPENDENCY_INCLUDES "${TBB_INCLUDE_DIRS}") diff --git a/libraries/octree/CMakeLists.txt b/libraries/octree/CMakeLists.txt index f1a30f3724..e8c6554ff4 100644 --- a/libraries/octree/CMakeLists.txt +++ b/libraries/octree/CMakeLists.txt @@ -13,7 +13,7 @@ find_package(ZLIB REQUIRED) include_directories(SYSTEM "${ZLIB_INCLUDE_DIRS}") # append ZLIB and OpenSSL to our list of libraries to link -target_link_libraries(${TARGET_NAME} "${ZLIB_LIBRARIES}") +target_link_libraries(${TARGET_NAME} ${ZLIB_LIBRARIES}) # call macro to link our dependencies and bubble them up via a property on our target link_shared_dependencies() diff --git a/libraries/voxels/CMakeLists.txt b/libraries/voxels/CMakeLists.txt index 874a74ee95..7980094884 100644 --- a/libraries/voxels/CMakeLists.txt +++ b/libraries/voxels/CMakeLists.txt @@ -12,7 +12,7 @@ find_package(ZLIB REQUIRED) include_directories(SYSTEM "${ZLIB_INCLUDE_DIRS}") # add it to our list of libraries to link -target_link_libraries(${TARGET_NAME} "${ZLIB_LIBRARIES}") +target_link_libraries(${TARGET_NAME} ${ZLIB_LIBRARIES}) # call macro to link our dependencies and bubble them up via a property on our target link_shared_dependencies() \ No newline at end of file From e6d3278b59c3d4a0530b054ee9e36ec2890f7668 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 18 Dec 2014 09:47:20 -0800 Subject: [PATCH 488/502] add back include of GLUT in render-utils --- libraries/render-utils/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libraries/render-utils/CMakeLists.txt b/libraries/render-utils/CMakeLists.txt index 8d4f85a2ac..4be4d93a9a 100644 --- a/libraries/render-utils/CMakeLists.txt +++ b/libraries/render-utils/CMakeLists.txt @@ -7,5 +7,8 @@ include_glm() link_hifi_libraries(shared gpu) +find_package(GLUT REQUIRED) +include_directories(SYSTEM "${GLUT_INCLUDE_DIRS}") + # call macro to link our dependencies and bubble them up via a property on our target link_shared_dependencies() From 4042b8b17ac6525e77ed61d139fb0cbf18e1bbd3 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 18 Dec 2014 09:50:10 -0800 Subject: [PATCH 489/502] duh, glut only required on win --- libraries/render-utils/CMakeLists.txt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libraries/render-utils/CMakeLists.txt b/libraries/render-utils/CMakeLists.txt index 4be4d93a9a..a6943addcc 100644 --- a/libraries/render-utils/CMakeLists.txt +++ b/libraries/render-utils/CMakeLists.txt @@ -7,8 +7,10 @@ include_glm() link_hifi_libraries(shared gpu) -find_package(GLUT REQUIRED) -include_directories(SYSTEM "${GLUT_INCLUDE_DIRS}") +if (WIN32) + find_package(GLUT REQUIRED) + include_directories(SYSTEM "${GLUT_INCLUDE_DIRS}") +endif () # call macro to link our dependencies and bubble them up via a property on our target link_shared_dependencies() From 11b44000998e222f3a2f523da63d58077a28a403 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 18 Dec 2014 11:20:17 -0800 Subject: [PATCH 490/502] move all glut-ness to geometry cache --- interface/src/Application.cpp | 2 +- interface/src/avatar/Hand.cpp | 2 +- interface/src/ui/MetavoxelEditor.cpp | 6 +- interface/src/ui/NodeBounds.cpp | 4 +- interface/src/ui/overlays/Sphere3DOverlay.cpp | 6 +- interface/src/voxels/VoxelFade.cpp | 3 +- .../src/RenderableBoxEntityItem.cpp | 78 +++---------------- .../src/DeferredLightingEffect.cpp | 6 +- .../render-utils/src/DeferredLightingEffect.h | 3 +- libraries/render-utils/src/GeometryCache.cpp | 10 +++ libraries/render-utils/src/GeometryCache.h | 2 + 11 files changed, 37 insertions(+), 85 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 4df23d2f7e..577f830495 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3575,7 +3575,7 @@ void Application::renderViewFrustum(ViewFrustum& viewFrustum) { glPushMatrix(); glColor4f(1, 1, 0, 1); glTranslatef(position.x, position.y, position.z); // where we actually want it! - glutWireSphere(keyholeRadius, 20, 20); + DependencyManager::get()->renderSphere(keyholeRadius, 20, 20, false); glPopMatrix(); } } diff --git a/interface/src/avatar/Hand.cpp b/interface/src/avatar/Hand.cpp index 91d59ae2fa..0ea0d1b725 100644 --- a/interface/src/avatar/Hand.cpp +++ b/interface/src/avatar/Hand.cpp @@ -153,7 +153,7 @@ void Hand::renderHandTargets(bool isMine) { const float collisionRadius = 0.05f; glColor4f(0.5f,0.5f,0.5f, alpha); - glutWireSphere(collisionRadius, 10.0f, 10.0f); + DependencyManager::get()->renderSphere(collisionRadius, 10, 10, false); glPopMatrix(); } } diff --git a/interface/src/ui/MetavoxelEditor.cpp b/interface/src/ui/MetavoxelEditor.cpp index f0516ab955..1a440570b7 100644 --- a/interface/src/ui/MetavoxelEditor.cpp +++ b/interface/src/ui/MetavoxelEditor.cpp @@ -33,6 +33,7 @@ #include #include +#include #include #include #include @@ -492,12 +493,11 @@ void BoxTool::render() { glColor4f(GRID_BRIGHTNESS, GRID_BRIGHTNESS, GRID_BRIGHTNESS, BOX_ALPHA); } glEnable(GL_CULL_FACE); - glutSolidCube(1.0); + DependencyManager::get()->renderSolidCube(1.0f); glDisable(GL_CULL_FACE); } glColor3f(GRID_BRIGHTNESS, GRID_BRIGHTNESS, GRID_BRIGHTNESS); - glutWireCube(1.0); - + DependencyManager::get()->renderWireCube(1.0f); glPopMatrix(); } diff --git a/interface/src/ui/NodeBounds.cpp b/interface/src/ui/NodeBounds.cpp index b0d3ddd14f..c529f6bbf3 100644 --- a/interface/src/ui/NodeBounds.cpp +++ b/interface/src/ui/NodeBounds.cpp @@ -12,6 +12,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include + #include "Application.h" #include "Util.h" @@ -132,7 +134,7 @@ void NodeBounds::draw() { getColorForNodeType(selectedNode->getType(), red, green, blue); glColor4f(red, green, blue, 0.2f); - glutSolidCube(1.0); + DependencyManager::get()->renderSolidCube(1.0f); glPopMatrix(); diff --git a/interface/src/ui/overlays/Sphere3DOverlay.cpp b/interface/src/ui/overlays/Sphere3DOverlay.cpp index 522902194f..3e30ec033d 100644 --- a/interface/src/ui/overlays/Sphere3DOverlay.cpp +++ b/interface/src/ui/overlays/Sphere3DOverlay.cpp @@ -62,11 +62,7 @@ void Sphere3DOverlay::render(RenderArgs* args) { glm::vec3 positionToCenter = center - position; glTranslatef(positionToCenter.x, positionToCenter.y, positionToCenter.z); glScalef(dimensions.x, dimensions.y, dimensions.z); - if (_isSolid) { - DependencyManager::get()->renderSphere(1.0f, SLICES, SLICES); - } else { - glutWireSphere(1.0f, SLICES, SLICES); - } + DependencyManager::get()->renderSphere(1.0f, SLICES, SLICES, _isSolid); glPopMatrix(); glPopMatrix(); diff --git a/interface/src/voxels/VoxelFade.cpp b/interface/src/voxels/VoxelFade.cpp index 367090291c..7bb3be67ab 100644 --- a/interface/src/voxels/VoxelFade.cpp +++ b/interface/src/voxels/VoxelFade.cpp @@ -12,6 +12,7 @@ #include "InterfaceConfig.h" #include +#include #include #include "Application.h" @@ -47,7 +48,7 @@ void VoxelFade::render() { voxelDetails.y + voxelDetails.s * 0.5f, voxelDetails.z + voxelDetails.s * 0.5f); glLineWidth(1.0f); - glutSolidCube(voxelDetails.s); + DependencyManager::get()->renderSolidCube(voxelDetails.s); glLineWidth(1.0f); glPopMatrix(); glEnable(GL_LIGHTING); diff --git a/libraries/entities-renderer/src/RenderableBoxEntityItem.cpp b/libraries/entities-renderer/src/RenderableBoxEntityItem.cpp index bb0de0ce6d..276db09477 100644 --- a/libraries/entities-renderer/src/RenderableBoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableBoxEntityItem.cpp @@ -28,79 +28,23 @@ void RenderableBoxEntityItem::render(RenderArgs* args) { glm::vec3 position = getPositionInMeters(); glm::vec3 center = getCenter() * (float)TREE_SCALE; glm::vec3 dimensions = getDimensions() * (float)TREE_SCALE; - glm::vec3 halfDimensions = dimensions / 2.0f; glm::quat rotation = getRotation(); - const bool useGlutCube = true; const float MAX_COLOR = 255.0f; - if (useGlutCube) { - glColor4f(getColor()[RED_INDEX] / MAX_COLOR, getColor()[GREEN_INDEX] / MAX_COLOR, - getColor()[BLUE_INDEX] / MAX_COLOR, getLocalRenderAlpha()); + glColor4f(getColor()[RED_INDEX] / MAX_COLOR, getColor()[GREEN_INDEX] / MAX_COLOR, + getColor()[BLUE_INDEX] / MAX_COLOR, getLocalRenderAlpha()); + glPushMatrix(); + glTranslatef(position.x, position.y, position.z); + glm::vec3 axis = glm::axis(rotation); + glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z); glPushMatrix(); - glTranslatef(position.x, position.y, position.z); - glm::vec3 axis = glm::axis(rotation); - glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z); - glPushMatrix(); - glm::vec3 positionToCenter = center - position; - glTranslatef(positionToCenter.x, positionToCenter.y, positionToCenter.z); - glScalef(dimensions.x, dimensions.y, dimensions.z); - DependencyManager::get()->renderSolidCube(1.0f); - glPopMatrix(); + glm::vec3 positionToCenter = center - position; + glTranslatef(positionToCenter.x, positionToCenter.y, positionToCenter.z); + glScalef(dimensions.x, dimensions.y, dimensions.z); + DependencyManager::get()->renderSolidCube(1.0f); glPopMatrix(); - } else { - static GLfloat vertices[] = { 1, 1, 1, -1, 1, 1, -1,-1, 1, 1,-1, 1, // v0,v1,v2,v3 (front) - 1, 1, 1, 1,-1, 1, 1,-1,-1, 1, 1,-1, // v0,v3,v4,v5 (right) - 1, 1, 1, 1, 1,-1, -1, 1,-1, -1, 1, 1, // v0,v5,v6,v1 (top) - -1, 1, 1, -1, 1,-1, -1,-1,-1, -1,-1, 1, // v1,v6,v7,v2 (left) - -1,-1,-1, 1,-1,-1, 1,-1, 1, -1,-1, 1, // v7,v4,v3,v2 (bottom) - 1,-1,-1, -1,-1,-1, -1, 1,-1, 1, 1,-1 }; // v4,v7,v6,v5 (back) + glPopMatrix(); - // normal array - static GLfloat normals[] = { 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, // v0,v1,v2,v3 (front) - 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, // v0,v3,v4,v5 (right) - 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, // v0,v5,v6,v1 (top) - -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, // v1,v6,v7,v2 (left) - 0,-1, 0, 0,-1, 0, 0,-1, 0, 0,-1, 0, // v7,v4,v3,v2 (bottom) - 0, 0,-1, 0, 0,-1, 0, 0,-1, 0, 0,-1 }; // v4,v7,v6,v5 (back) - - // index array of vertex array for glDrawElements() & glDrawRangeElement() - static GLubyte indices[] = { 0, 1, 2, 2, 3, 0, // front - 4, 5, 6, 6, 7, 4, // right - 8, 9,10, 10,11, 8, // top - 12,13,14, 14,15,12, // left - 16,17,18, 18,19,16, // bottom - 20,21,22, 22,23,20 }; // back - - - - glEnableClientState(GL_NORMAL_ARRAY); - glEnableClientState(GL_VERTEX_ARRAY); - glNormalPointer(GL_FLOAT, 0, normals); - glVertexPointer(3, GL_FLOAT, 0, vertices); - - glColor4f(getColor()[RED_INDEX] / MAX_COLOR, getColor()[GREEN_INDEX] / MAX_COLOR, - getColor()[BLUE_INDEX] / MAX_COLOR, getLocalRenderAlpha()); - - DependencyManager::get()->bindSimpleProgram(); - - glPushMatrix(); - glTranslatef(position.x, position.y, position.z); - glm::vec3 axis = glm::axis(rotation); - glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z); - glPushMatrix(); - glm::vec3 positionToCenter = center - position; - glTranslatef(positionToCenter.x, positionToCenter.y, positionToCenter.z); - // we need to do half the size because the geometry in the VBOs are from -1,-1,-1 to 1,1,1 - glScalef(halfDimensions.x, halfDimensions.y, halfDimensions.z); - glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_BYTE, indices); - glPopMatrix(); - glPopMatrix(); - - DependencyManager::get()->releaseSimpleProgram(); - - glDisableClientState(GL_VERTEX_ARRAY); // disable vertex arrays - glDisableClientState(GL_NORMAL_ARRAY); - } }; diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 065ca3a741..0dd6f9d0b8 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -12,8 +12,6 @@ // include this before QOpenGLFramebufferObject, which includes an earlier version of OpenGL #include -#include // TODO - we need to get rid of this ASAP - #include #include @@ -74,13 +72,13 @@ void DeferredLightingEffect::renderWireSphere(float radius, int slices, int stac void DeferredLightingEffect::renderSolidCube(float size) { bindSimpleProgram(); - glutSolidCube(size); + DependencyManager::get()->renderSolidCube(size); releaseSimpleProgram(); } void DeferredLightingEffect::renderWireCube(float size) { bindSimpleProgram(); - glutWireCube(size); + DependencyManager::get()->renderWireCube(size); releaseSimpleProgram(); } diff --git a/libraries/render-utils/src/DeferredLightingEffect.h b/libraries/render-utils/src/DeferredLightingEffect.h index 7ace3448d7..4f3b930a09 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.h +++ b/libraries/render-utils/src/DeferredLightingEffect.h @@ -30,8 +30,7 @@ public: void init(AbstractViewStateInterface* viewState); - /// Returns a reference to a simple program suitable for rendering static - /// untextured geometry (such as that generated by glutSolidSphere, etc.) + /// Returns a reference to a simple program suitable for rendering static untextured geometry ProgramObject& getSimpleProgram() { return _simpleProgram; } /// 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 a770d942fe..e31ae2333a 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -11,6 +11,7 @@ // include this before QOpenGLBuffer, which includes an earlier version of OpenGL #include +#include // TODO - we need to get rid of this ASAP #include @@ -507,6 +508,15 @@ void GeometryCache::renderGrid(int xDivisions, int yDivisions) { buffer.release(); } +void GeometryCache::renderSolidCube(float size) { + glutSolidCube(size); +} + +void GeometryCache::renderWireCube(float size) { + glutWireCube(size); +} + + QSharedPointer GeometryCache::getGeometry(const QUrl& url, const QUrl& fallback, bool delayLoad) { return getResource(url, fallback, delayLoad).staticCast(); } diff --git a/libraries/render-utils/src/GeometryCache.h b/libraries/render-utils/src/GeometryCache.h index f0045c10bf..92e65718ab 100644 --- a/libraries/render-utils/src/GeometryCache.h +++ b/libraries/render-utils/src/GeometryCache.h @@ -43,6 +43,8 @@ public: void renderHalfCylinder(int slices, int stacks); void renderCone(float base, float height, int slices, int stacks); void renderGrid(int xDivisions, int yDivisions); + void renderSolidCube(float size); + void renderWireCube(float size); /// Loads geometry from the specified URL. /// \param fallback a fallback URL to load if the desired one is unavailable From 011b313b681c4ac8767e51dbd3afa2d06b6f412d Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 18 Dec 2014 11:30:57 -0800 Subject: [PATCH 491/502] fix indentation in MetavoxelClientManager --- libraries/metavoxels/src/MetavoxelClientManager.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/metavoxels/src/MetavoxelClientManager.cpp b/libraries/metavoxels/src/MetavoxelClientManager.cpp index dfc736edc9..e0489b4bd0 100644 --- a/libraries/metavoxels/src/MetavoxelClientManager.cpp +++ b/libraries/metavoxels/src/MetavoxelClientManager.cpp @@ -50,7 +50,8 @@ SharedObjectPointer MetavoxelClientManager::findFirstRaySpannerIntersection(cons if (client) { float clientDistance; SharedObjectPointer clientSpanner = client->getDataCopy().findFirstRaySpannerIntersection( - origin, direction, attribute, clientDistance); + origin, direction, attribute, clientDistance + ); if (clientSpanner && clientDistance < closestDistance) { closestSpanner = clientSpanner; closestDistance = clientDistance; From 28381a3b7092fc956153df7561029059616c2a0b Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 18 Dec 2014 11:39:02 -0800 Subject: [PATCH 492/502] cleanup of EntityItem::_created timestamp logic EntityItem::_created initializes to 0 in ctor and must be set either by EntityItemProperties (via server update) or manually whenever a script creates a fresh entity --- libraries/entities/src/EntityItem.cpp | 101 +++++++++++------- libraries/entities/src/EntityItem.h | 3 +- .../entities/src/EntityItemProperties.cpp | 14 ++- libraries/entities/src/EntityItemProperties.h | 6 +- .../entities/src/EntityItemPropertiesMacros.h | 4 +- libraries/entities/src/EntityTree.cpp | 17 ++- libraries/entities/src/EntityTypes.cpp | 17 +-- 7 files changed, 95 insertions(+), 67 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index cd34cd55c6..348efac9a3 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -53,13 +53,13 @@ void EntityItem::initFromEntityItemID(const EntityItemID& entityItemID) { _creatorTokenID = entityItemID.creatorTokenID; // init values with defaults before calling setProperties + quint64 now = usecTimestampNow(); + _lastSimulated = now; + _lastUpdated = now; _lastEdited = 0; _lastEditedFromRemote = 0; _lastEditedFromRemoteInRemoteTime = 0; - - _lastSimulated = 0; - _lastUpdated = 0; - _created = usecTimestampNow(); + _created = UNKNOWN_CREATED_TIME; _changedOnServer = 0; _position = glm::vec3(0,0,0); @@ -85,12 +85,13 @@ void EntityItem::initFromEntityItemID(const EntityItemID& entityItemID) { EntityItem::EntityItem(const EntityItemID& entityItemID) { _type = EntityTypes::Unknown; + quint64 now = usecTimestampNow(); + _lastSimulated = now; + _lastUpdated = now; _lastEdited = 0; _lastEditedFromRemote = 0; _lastEditedFromRemoteInRemoteTime = 0; - _lastSimulated = 0; - _lastUpdated = 0; - _created = 0; + _created = UNKNOWN_CREATED_TIME; _dirtyFlags = 0; _changedOnServer = 0; initFromEntityItemID(entityItemID); @@ -99,16 +100,16 @@ EntityItem::EntityItem(const EntityItemID& entityItemID) { EntityItem::EntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) { _type = EntityTypes::Unknown; quint64 now = usecTimestampNow(); - _created = properties.getCreated() < now ? properties.getCreated() : now; - _lastEdited = _lastEditedFromRemote = _lastSimulated = _lastUpdated = _lastEditedFromRemoteInRemoteTime = _created; + _lastSimulated = now; + _lastUpdated = now; + _lastEdited = 0; _lastEditedFromRemote = 0; _lastEditedFromRemoteInRemoteTime = 0; - _lastSimulated = 0; - _lastUpdated = 0; + _created = UNKNOWN_CREATED_TIME; _dirtyFlags = 0; _changedOnServer = 0; initFromEntityItemID(entityItemID); - setProperties(properties, true); // force copy + setProperties(properties); } EntityPropertyFlags EntityItem::getEntityProperties(EncodeBitstreamParams& params) const { @@ -365,12 +366,15 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef memcpy(&createdFromBuffer, dataAt, sizeof(createdFromBuffer)); dataAt += sizeof(createdFromBuffer); bytesRead += sizeof(createdFromBuffer); - createdFromBuffer -= clockSkew; - - if (createdFromBuffer < _created) { - // the server claims that this entity has an older creation time so we accept it + + quint64 now = usecTimestampNow(); + if (_created == UNKNOWN_CREATED_TIME) { + // we don't yet have a _created timestamp, so we accept this one + createdFromBuffer -= clockSkew; + if (createdFromBuffer > now || createdFromBuffer == UNKNOWN_CREATED_TIME) { + createdFromBuffer = now; + } _created = createdFromBuffer; - _lastEdited = _created; } if (wantDebug) { @@ -385,7 +389,6 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef qDebug() << " ago=" << editedAgo << "seconds - " << agoAsString; } - quint64 now = usecTimestampNow(); quint64 lastEditedFromBuffer = 0; quint64 lastEditedFromBufferAdjusted = 0; @@ -395,6 +398,9 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef dataAt += sizeof(lastEditedFromBuffer); bytesRead += sizeof(lastEditedFromBuffer); lastEditedFromBufferAdjusted = lastEditedFromBuffer - clockSkew; + if (lastEditedFromBufferAdjusted > now) { + lastEditedFromBufferAdjusted = now; + } bool fromSameServerEdit = (lastEditedFromBuffer == _lastEditedFromRemoteInRemoteTime); @@ -444,10 +450,12 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef } // don't allow _lastEdited to be in the future - _lastEdited = lastEditedFromBufferAdjusted < now ? lastEditedFromBufferAdjusted : now; + _lastEdited = lastEditedFromBufferAdjusted; _lastEditedFromRemote = now; _lastEditedFromRemoteInRemoteTime = lastEditedFromBuffer; + // TODO: only send this notification if something ACTUALLY changed (hint, we haven't yet parsed + // the properties out of the bitstream (see below)) somethingChangedNotification(); // notify derived classes that something has changed } @@ -456,8 +464,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef ByteCountCoded updateDeltaCoder = encodedUpdateDelta; quint64 updateDelta = updateDeltaCoder; if (overwriteLocalData) { - _lastUpdated = lastEditedFromBufferAdjusted + updateDelta; // don't adjust for clock skew since we already did that for _lastEdited - _lastSimulated = now; + _lastUpdated = lastEditedFromBufferAdjusted + updateDelta; // don't adjust for clock skew since we already did that if (wantDebug) { qDebug() << "_lastUpdated =" << _lastUpdated; qDebug() << "_lastEdited=" << _lastEdited; @@ -529,6 +536,9 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef bytesRead += readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args, propertyFlags, overwriteLocalData); recalculateCollisionShape(); + if (overwriteLocalData && (getDirtyFlags() & EntityItem::DIRTY_POSITION)) { + _lastSimulated = now; + } } return bytesRead; } @@ -774,21 +784,9 @@ EntityItemProperties EntityItem::getProperties() const { return properties; } -bool EntityItem::setProperties(const EntityItemProperties& properties, bool forceCopy) { +bool EntityItem::setProperties(const EntityItemProperties& properties) { bool somethingChanged = false; - // handle the setting of created timestamps for the basic new entity case - if (forceCopy) { - quint64 now = usecTimestampNow(); - if (properties.getCreated() == UNKNOWN_CREATED_TIME) { - _created = now; - } else if (properties.getCreated() != USE_EXISTING_CREATED_TIME) { - quint64 created = properties.getCreated(); - // don't allow _created to be in the future - _created = created < now ? created : now; - } - } - SET_ENTITY_PROPERTY_FROM_PROPERTIES(position, updatePositionInMeters); // this will call recalculate collision shape if needed SET_ENTITY_PROPERTY_FROM_PROPERTIES(dimensions, updateDimensionsInMeters); // NOTE: radius is obsolete SET_ENTITY_PROPERTY_FROM_PROPERTIES(rotation, updateRotation); @@ -818,16 +816,43 @@ bool EntityItem::setProperties(const EntityItemProperties& properties, bool forc qDebug() << "EntityItem::setProperties() AFTER update... edited AGO=" << elapsed << "now=" << now << " getLastEdited()=" << getLastEdited(); } - // don't allow _lastEdited to be in the future - setLastEdited(properties._lastEdited < now ? properties._lastEdited : now); + if (_created != UNKNOWN_CREATED_TIME) { + setLastEdited(now); + } if (getDirtyFlags() & EntityItem::DIRTY_POSITION) { - _lastSimulated = usecTimestampNow(); + _lastSimulated = now; } } - + + // timestamps + quint64 timestamp = properties.getCreated(); + if (_created == UNKNOWN_CREATED_TIME && timestamp != UNKNOWN_CREATED_TIME) { + quint64 now = usecTimestampNow(); + if (timestamp > now) { + timestamp = now; + } + _created = timestamp; + + timestamp = properties.getLastEdited(); + if (timestamp > now) { + timestamp = now; + } else if (timestamp < _created) { + timestamp = _created; + } + _lastEdited = timestamp; + } + return somethingChanged; } +void EntityItem::recordCreationTime() { + assert(_created == UNKNOWN_CREATED_TIME); + _created = usecTimestampNow(); + _lastEdited = _created; + _lastUpdated = _created; + _lastSimulated = _created; +} + // TODO: is this really correct? how do we use size, does it need to handle rotation? float EntityItem::getSize() const { diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 7455b96f6b..0d0aa96706 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -74,12 +74,13 @@ public: virtual EntityItemProperties getProperties() const; /// returns true if something changed - virtual bool setProperties(const EntityItemProperties& properties, bool forceCopy = false); + virtual bool setProperties(const EntityItemProperties& properties); /// Override this in your derived class if you'd like to be informed when something about the state of the entity /// has changed. This will be called with properties change or when new data is loaded from a stream virtual void somethingChangedNotification() { } + void recordCreationTime(); // set _created to 'now' quint64 getLastSimulated() const { return _lastSimulated; } /// Last simulated time of this entity universal usecs /// Last edited time of this entity universal usecs diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 11c9646cbc..58b110c4b0 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -156,6 +156,17 @@ void EntityItemProperties::debugDump() const { props.debugDumpBits(); } +void EntityItemProperties::setCreated(quint64 usecTime) { + _created = usecTime; + if (_lastEdited < _created) { + _lastEdited = _created; + } +} + +void EntityItemProperties::setLastEdited(quint64 usecTime) { + _lastEdited = usecTime > _created ? usecTime : _created; +} + EntityPropertyFlags EntityItemProperties::getChangedProperties() const { EntityPropertyFlags changedProperties; @@ -652,9 +663,6 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int entityID.creatorTokenID = UNKNOWN_ENTITY_TOKEN; entityID.isKnownID = true; valid = true; - - // created time is lastEdited time - properties.setCreated(USE_EXISTING_CREATED_TIME); } // Entity Type... diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index e5f78e8fc7..b843c85327 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -96,8 +96,6 @@ enum EntityPropertyList { typedef PropertyFlags EntityPropertyFlags; const quint64 UNKNOWN_CREATED_TIME = 0; -const quint64 USE_EXISTING_CREATED_TIME = 1; - /// A collection of properties of an entity item used in the scripting API. Translates between the actual properties of an /// entity and a JavaScript style hash/QScriptValue storing a set of properties. Used in scripting to set/get the complete @@ -134,7 +132,7 @@ public: AABox getAABoxInMeters() const; void debugDump() const; - void setLastEdited(quint64 usecTime) { _lastEdited = usecTime; } + void setLastEdited(quint64 usecTime); DEFINE_PROPERTY(PROP_VISIBLE, Visible, visible, bool); DEFINE_PROPERTY_REF_WITH_SETTER(PROP_POSITION, Position, position, glm::vec3); @@ -180,7 +178,7 @@ public: float getAge() const { return (float)(usecTimestampNow() - _created) / (float)USECS_PER_SECOND; } quint64 getCreated() const { return _created; } - void setCreated(quint64 usecTime) { _created = usecTime; } + void setCreated(quint64 usecTime); bool hasCreatedTime() const { return (_created != UNKNOWN_CREATED_TIME); } bool containsBoundsProperties() const { return (_positionChanged || _dimensionsChanged); } diff --git a/libraries/entities/src/EntityItemPropertiesMacros.h b/libraries/entities/src/EntityItemPropertiesMacros.h index 3288e56a3d..9f86156422 100644 --- a/libraries/entities/src/EntityItemPropertiesMacros.h +++ b/libraries/entities/src/EntityItemPropertiesMacros.h @@ -137,13 +137,13 @@ } #define SET_ENTITY_PROPERTY_FROM_PROPERTIES(P,M) \ - if (properties._##P##Changed || forceCopy) { \ + if (properties._##P##Changed) { \ M(properties._##P); \ somethingChanged = true; \ } #define SET_ENTITY_PROPERTY_FROM_PROPERTIES_GETTER(C,G,S) \ - if (properties.C() || forceCopy) { \ + if (properties.C()) { \ S(properties.G()); \ somethingChanged = true; \ } diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index fb8e4345f4..3580e64b35 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -164,9 +164,17 @@ EntityItem* EntityTree::addEntity(const EntityItemID& entityID, const EntityItem // NOTE: This method is used in the client and the server tree. In the client, it's possible to create EntityItems // that do not yet have known IDs. In the server tree however we don't want to have entities without known IDs. - if (getIsServer() && !entityID.isKnownID) { - qDebug() << "UNEXPECTED!!! ----- EntityTree::addEntity()... (getIsSever() && !entityID.isKnownID)"; - return result; + bool recordCreationTime = false; + if (!entityID.isKnownID) { + if (getIsServer()) { + qDebug() << "UNEXPECTED!!! ----- EntityTree::addEntity()... (getIsSever() && !entityID.isKnownID)"; + return result; + } + if (properties.getCreated() == UNKNOWN_CREATED_TIME) { + // the entity's creation time was not specified in properties, which means this is a NEW entity + // and we must record its creation time + recordCreationTime = true; + } } // You should not call this on existing entities that are already part of the tree! Call updateEntity() @@ -182,6 +190,9 @@ EntityItem* EntityTree::addEntity(const EntityItemID& entityID, const EntityItem result = EntityTypes::constructEntityItem(type, entityID, properties); if (result) { + if (recordCreationTime) { + result->recordCreationTime(); + } // Recurse the tree and store the entity in the correct tree element AddEntityOperator theOperator(this, result); recurseTreeWithOperator(&theOperator); diff --git a/libraries/entities/src/EntityTypes.cpp b/libraries/entities/src/EntityTypes.cpp index f7806445bc..fd9484e0d6 100644 --- a/libraries/entities/src/EntityTypes.cpp +++ b/libraries/entities/src/EntityTypes.cpp @@ -77,15 +77,7 @@ EntityItem* EntityTypes::constructEntityItem(EntityType entityType, const Entity factory = _factories[entityType]; } if (factory) { - // NOTE: if someone attempts to create an entity with properties that do not include a proper "created" time - // then set the created time to now - if (!properties.hasCreatedTime()) { - EntityItemProperties mutableProperties = properties; - mutableProperties.setCreated(usecTimestampNow()); - newEntityItem = factory(entityID, mutableProperties); - } else { - newEntityItem = factory(entityID, properties); - } + newEntityItem = factory(entityID, properties); } return newEntityItem; } @@ -128,13 +120,6 @@ EntityItem* EntityTypes::constructEntityItem(const unsigned char* data, int byte EntityItemID tempEntityID(actualID); EntityItemProperties tempProperties; - - // we set the Creation and Edit times to 'now', but if the server submits an earlier Creation time - // then it will be accepted - quint64 now = usecTimestampNow(); - tempProperties.setCreated(now); - tempProperties.setLastEdited(now); - return constructEntityItem(entityType, tempEntityID, tempProperties); } From b03e6c53e1b34c7b110c8ba4b0b6af01c7748e30 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 18 Dec 2014 11:41:20 -0800 Subject: [PATCH 493/502] fixing derived classes to use new EntityItem API remove 'forceCopy' argument in EntityItem::setProperties() --- .../entities-renderer/src/RenderableModelEntityItem.cpp | 4 ++-- libraries/entities-renderer/src/RenderableModelEntityItem.h | 2 +- libraries/entities/src/BoxEntityItem.cpp | 6 +++--- libraries/entities/src/BoxEntityItem.h | 2 +- libraries/entities/src/LightEntityItem.cpp | 6 +++--- libraries/entities/src/LightEntityItem.h | 2 +- libraries/entities/src/ModelEntityItem.cpp | 6 +++--- libraries/entities/src/ModelEntityItem.h | 2 +- libraries/entities/src/SphereEntityItem.cpp | 6 +++--- libraries/entities/src/SphereEntityItem.h | 2 +- libraries/entities/src/TextEntityItem.cpp | 6 +++--- libraries/entities/src/TextEntityItem.h | 2 +- 12 files changed, 23 insertions(+), 23 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 3e5118d203..92e925d73e 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -34,9 +34,9 @@ RenderableModelEntityItem::~RenderableModelEntityItem() { } } -bool RenderableModelEntityItem::setProperties(const EntityItemProperties& properties, bool forceCopy) { +bool RenderableModelEntityItem::setProperties(const EntityItemProperties& properties) { QString oldModelURL = getModelURL(); - bool somethingChanged = ModelEntityItem::setProperties(properties, forceCopy); + bool somethingChanged = ModelEntityItem::setProperties(properties); if (somethingChanged && oldModelURL != getModelURL()) { _needsModelReload = true; } diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index 6f61a1b9db..65cded0207 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -35,7 +35,7 @@ public: virtual ~RenderableModelEntityItem(); virtual EntityItemProperties getProperties() const; - virtual bool setProperties(const EntityItemProperties& properties, bool forceCopy); + virtual bool setProperties(const EntityItemProperties& properties); virtual int readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead, ReadBitstreamToTreeParams& args, EntityPropertyFlags& propertyFlags, bool overwriteLocalData); diff --git a/libraries/entities/src/BoxEntityItem.cpp b/libraries/entities/src/BoxEntityItem.cpp index 16204f0c16..cece544263 100644 --- a/libraries/entities/src/BoxEntityItem.cpp +++ b/libraries/entities/src/BoxEntityItem.cpp @@ -29,7 +29,7 @@ BoxEntityItem::BoxEntityItem(const EntityItemID& entityItemID, const EntityItemP { _type = EntityTypes::Box; _created = properties.getCreated(); - setProperties(properties, true); + setProperties(properties); } EntityItemProperties BoxEntityItem::getProperties() const { @@ -44,9 +44,9 @@ EntityItemProperties BoxEntityItem::getProperties() const { return properties; } -bool BoxEntityItem::setProperties(const EntityItemProperties& properties, bool forceCopy) { +bool BoxEntityItem::setProperties(const EntityItemProperties& properties) { bool somethingChanged = false; - somethingChanged = EntityItem::setProperties(properties, forceCopy); // set the properties in our base class + somethingChanged = EntityItem::setProperties(properties); // set the properties in our base class SET_ENTITY_PROPERTY_FROM_PROPERTIES(color, setColor); diff --git a/libraries/entities/src/BoxEntityItem.h b/libraries/entities/src/BoxEntityItem.h index b5f4521f96..da9e7544c6 100644 --- a/libraries/entities/src/BoxEntityItem.h +++ b/libraries/entities/src/BoxEntityItem.h @@ -24,7 +24,7 @@ public: // methods for getting/setting all properties of an entity virtual EntityItemProperties getProperties() const; - virtual bool setProperties(const EntityItemProperties& properties, bool forceCopy = false); + virtual bool setProperties(const EntityItemProperties& properties); // TODO: eventually only include properties changed since the params.lastViewFrustumSent time virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const; diff --git a/libraries/entities/src/LightEntityItem.cpp b/libraries/entities/src/LightEntityItem.cpp index 44b83bc94e..c125364e63 100644 --- a/libraries/entities/src/LightEntityItem.cpp +++ b/libraries/entities/src/LightEntityItem.cpp @@ -41,7 +41,7 @@ LightEntityItem::LightEntityItem(const EntityItemID& entityItemID, const EntityI _exponent = 0.0f; _cutoff = PI; - setProperties(properties, true); + setProperties(properties); // a light is not collide-able so we make it's shape be a tiny sphere at origin _emptyShape.setTranslation(glm::vec3(0.0f, 0.0f, 0.0f)); @@ -71,8 +71,8 @@ EntityItemProperties LightEntityItem::getProperties() const { return properties; } -bool LightEntityItem::setProperties(const EntityItemProperties& properties, bool forceCopy) { - bool somethingChanged = EntityItem::setProperties(properties, forceCopy); // set the properties in our base class +bool LightEntityItem::setProperties(const EntityItemProperties& properties) { + bool somethingChanged = EntityItem::setProperties(properties); // set the properties in our base class SET_ENTITY_PROPERTY_FROM_PROPERTIES(isSpotlight, setIsSpotlight); SET_ENTITY_PROPERTY_FROM_PROPERTIES(diffuseColor, setDiffuseColor); diff --git a/libraries/entities/src/LightEntityItem.h b/libraries/entities/src/LightEntityItem.h index 6ebb85beda..249a4c8472 100644 --- a/libraries/entities/src/LightEntityItem.h +++ b/libraries/entities/src/LightEntityItem.h @@ -28,7 +28,7 @@ public: // methods for getting/setting all properties of an entity virtual EntityItemProperties getProperties() const; - virtual bool setProperties(const EntityItemProperties& properties, bool forceCopy = false); + virtual bool setProperties(const EntityItemProperties& properties); virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const; diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index b14248b3bc..02ebbebdb4 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -34,7 +34,7 @@ ModelEntityItem::ModelEntityItem(const EntityItemID& entityItemID, const EntityI EntityItem(entityItemID, properties) { _type = EntityTypes::Model; - setProperties(properties, true); + setProperties(properties); _lastAnimated = usecTimestampNow(); _jointMappingCompleted = false; _color[0] = _color[1] = _color[2] = 0; @@ -55,9 +55,9 @@ EntityItemProperties ModelEntityItem::getProperties() const { return properties; } -bool ModelEntityItem::setProperties(const EntityItemProperties& properties, bool forceCopy) { +bool ModelEntityItem::setProperties(const EntityItemProperties& properties) { bool somethingChanged = false; - somethingChanged = EntityItem::setProperties(properties, forceCopy); // set the properties in our base class + somethingChanged = EntityItem::setProperties(properties); // set the properties in our base class SET_ENTITY_PROPERTY_FROM_PROPERTIES(color, setColor); SET_ENTITY_PROPERTY_FROM_PROPERTIES(modelURL, setModelURL); diff --git a/libraries/entities/src/ModelEntityItem.h b/libraries/entities/src/ModelEntityItem.h index 6b4ca2416a..4c14dca177 100644 --- a/libraries/entities/src/ModelEntityItem.h +++ b/libraries/entities/src/ModelEntityItem.h @@ -26,7 +26,7 @@ public: // methods for getting/setting all properties of an entity virtual EntityItemProperties getProperties() const; - virtual bool setProperties(const EntityItemProperties& properties, bool forceCopy = false); + virtual bool setProperties(const EntityItemProperties& properties); // TODO: eventually only include properties changed since the params.lastViewFrustumSent time virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const; diff --git a/libraries/entities/src/SphereEntityItem.cpp b/libraries/entities/src/SphereEntityItem.cpp index b0df310ad2..06035f6b6e 100644 --- a/libraries/entities/src/SphereEntityItem.cpp +++ b/libraries/entities/src/SphereEntityItem.cpp @@ -31,7 +31,7 @@ SphereEntityItem::SphereEntityItem(const EntityItemID& entityItemID, const Entit EntityItem(entityItemID, properties) { _type = EntityTypes::Sphere; - setProperties(properties, true); + setProperties(properties); } EntityItemProperties SphereEntityItem::getProperties() const { @@ -40,8 +40,8 @@ EntityItemProperties SphereEntityItem::getProperties() const { return properties; } -bool SphereEntityItem::setProperties(const EntityItemProperties& properties, bool forceCopy) { - bool somethingChanged = EntityItem::setProperties(properties, forceCopy); // set the properties in our base class +bool SphereEntityItem::setProperties(const EntityItemProperties& properties) { + bool somethingChanged = EntityItem::setProperties(properties); // set the properties in our base class SET_ENTITY_PROPERTY_FROM_PROPERTIES(color, setColor); diff --git a/libraries/entities/src/SphereEntityItem.h b/libraries/entities/src/SphereEntityItem.h index 74cc7d1635..3b7dccaff9 100644 --- a/libraries/entities/src/SphereEntityItem.h +++ b/libraries/entities/src/SphereEntityItem.h @@ -25,7 +25,7 @@ public: // methods for getting/setting all properties of an entity virtual EntityItemProperties getProperties() const; - virtual bool setProperties(const EntityItemProperties& properties, bool forceCopy = false); + virtual bool setProperties(const EntityItemProperties& properties); virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const; diff --git a/libraries/entities/src/TextEntityItem.cpp b/libraries/entities/src/TextEntityItem.cpp index bb76a2e690..c43638f827 100644 --- a/libraries/entities/src/TextEntityItem.cpp +++ b/libraries/entities/src/TextEntityItem.cpp @@ -37,7 +37,7 @@ TextEntityItem::TextEntityItem(const EntityItemID& entityItemID, const EntityIte { _type = EntityTypes::Text; _created = properties.getCreated(); - setProperties(properties, true); + setProperties(properties); } void TextEntityItem::setDimensions(const glm::vec3& value) { @@ -57,9 +57,9 @@ EntityItemProperties TextEntityItem::getProperties() const { return properties; } -bool TextEntityItem::setProperties(const EntityItemProperties& properties, bool forceCopy) { +bool TextEntityItem::setProperties(const EntityItemProperties& properties) { bool somethingChanged = false; - somethingChanged = EntityItem::setProperties(properties, forceCopy); // set the properties in our base class + somethingChanged = EntityItem::setProperties(properties); // set the properties in our base class SET_ENTITY_PROPERTY_FROM_PROPERTIES(text, setText); SET_ENTITY_PROPERTY_FROM_PROPERTIES(lineHeight, setLineHeight); diff --git a/libraries/entities/src/TextEntityItem.h b/libraries/entities/src/TextEntityItem.h index 83143b1134..1f0bd7d85e 100644 --- a/libraries/entities/src/TextEntityItem.h +++ b/libraries/entities/src/TextEntityItem.h @@ -27,7 +27,7 @@ public: // methods for getting/setting all properties of an entity virtual EntityItemProperties getProperties() const; - virtual bool setProperties(const EntityItemProperties& properties, bool forceCopy = false); + virtual bool setProperties(const EntityItemProperties& properties); // TODO: eventually only include properties changed since the params.lastViewFrustumSent time virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const; From 587df1178dfc19dc31e261466bd54ffa138fe646 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 18 Dec 2014 13:57:19 -0800 Subject: [PATCH 494/502] use constant for MSEC to USEC conversion --- libraries/networking/src/LimitedNodeList.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index c6e79cc18f..de533ec7be 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -504,7 +504,7 @@ void LimitedNodeList::removeSilentNodes() { SharedNodePointer node = it->second; node->getMutex().lock(); - if ((usecTimestampNow() - node->getLastHeardMicrostamp()) > (NODE_SILENCE_THRESHOLD_MSECS * 1000)) { + if ((usecTimestampNow() - node->getLastHeardMicrostamp()) > (NODE_SILENCE_THRESHOLD_MSECS * USECS_PER_MSEC)) { // call the NodeHash erase to get rid of this node it = _nodeHash.unsafe_erase(it); From df3eca5aca594a6f8b6108c09f9fa72945076ea7 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 18 Dec 2014 14:01:22 -0800 Subject: [PATCH 495/502] add a comment for the UUID hasher --- libraries/networking/src/UUIDHasher.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libraries/networking/src/UUIDHasher.h b/libraries/networking/src/UUIDHasher.h index d5d16e21e9..02f7e3685a 100644 --- a/libraries/networking/src/UUIDHasher.h +++ b/libraries/networking/src/UUIDHasher.h @@ -14,6 +14,9 @@ #include "UUID.h" +// uses the same hashing performed by Qt +// https://qt.gitorious.org/qt/qtbase/source/73ef64fb5fabb60101a3cac6e43f0c5bb2298000:src/corelib/plugin/quuid.cpp + class UUIDHasher { public: size_t operator()(const QUuid& uuid) const { From 07f95c597cde73fa127c72085e443f65cb2c68f5 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 18 Dec 2014 14:08:55 -0800 Subject: [PATCH 496/502] add read locks for find on tbb hash --- libraries/networking/src/LimitedNodeList.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index de533ec7be..907ac86704 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -352,6 +352,8 @@ int LimitedNodeList::findNodeAndUpdateWithDataFromPacket(const QByteArray& packe } SharedNodePointer LimitedNodeList::nodeWithUUID(const QUuid& nodeUUID) { + QReadLocker readLocker(&_nodeMutex); + NodeHash::const_iterator it = _nodeHash.find(nodeUUID); return it == _nodeHash.cend() ? SharedNodePointer() : it->second; } @@ -386,10 +388,14 @@ void LimitedNodeList::reset() { } void LimitedNodeList::killNodeWithUUID(const QUuid& nodeUUID) { + _nodeMutex.lockForRead(); + NodeHash::iterator it = _nodeHash.find(nodeUUID); if (it != _nodeHash.end()) { SharedNodePointer matchingNode = it->second; + _nodeMutex.unlock(); + QWriteLocker writeLocker(&_nodeMutex); _nodeHash.unsafe_erase(it); From e13e9febdc69178a13e29e3e993b5f339bcfb0be Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 18 Dec 2014 14:16:22 -0800 Subject: [PATCH 497/502] unlock the node mutex if node not found --- libraries/networking/src/LimitedNodeList.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index 907ac86704..5e13f6bbc9 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -400,6 +400,8 @@ void LimitedNodeList::killNodeWithUUID(const QUuid& nodeUUID) { _nodeHash.unsafe_erase(it); handleNodeKill(matchingNode); + } else { + _nodeMutex.unlock(); } } From 325d0dbce1daac75a9a6eda26df62616142d3fd2 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 18 Dec 2014 14:31:34 -0800 Subject: [PATCH 498/502] include QUuid instead of UUID in UUIDHasher --- libraries/networking/src/UUIDHasher.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/networking/src/UUIDHasher.h b/libraries/networking/src/UUIDHasher.h index 02f7e3685a..5429e151c7 100644 --- a/libraries/networking/src/UUIDHasher.h +++ b/libraries/networking/src/UUIDHasher.h @@ -12,7 +12,7 @@ #ifndef hifi_UUIDHasher_h #define hifi_UUIDHasher_h -#include "UUID.h" +#include // uses the same hashing performed by Qt // https://qt.gitorious.org/qt/qtbase/source/73ef64fb5fabb60101a3cac6e43f0c5bb2298000:src/corelib/plugin/quuid.cpp From 26bcca95c90e650076b23b7c4b69dd2780a9e278 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 18 Dec 2014 15:42:02 -0800 Subject: [PATCH 499/502] remove glutWireCube() --- libraries/render-utils/src/GeometryCache.cpp | 60 +++++++++++++++++++- libraries/render-utils/src/GeometryCache.h | 2 + 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index e31ae2333a..d28702fa20 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -513,7 +513,65 @@ void GeometryCache::renderSolidCube(float size) { } void GeometryCache::renderWireCube(float size) { - glutWireCube(size); + VerticesIndices& vbo = _wireCubeVBOs[size]; + const int FLOATS_PER_VERTEX = 3; + const int VERTICES_PER_EDGE = 2; + const int TOP_EDGES = 4; + const int BOTTOM_EDGES = 4; + const int SIDE_EDGES = 4; + const int vertices = 8; + const int indices = (TOP_EDGES + BOTTOM_EDGES + SIDE_EDGES) * VERTICES_PER_EDGE; + if (vbo.first == 0) { + int vertexPoints = vertices * FLOATS_PER_VERTEX; + GLfloat* vertexData = new GLfloat[vertexPoints]; // only vertices, no normals because we're a wire cube + GLfloat* vertex = vertexData; + float halfSize = size / 2.0f; + + static GLfloat cannonicalVertices[] = + { 1, 1, 1, 1, 1,-1, -1, 1,-1, -1, 1, 1, // v0, v1, v2, v3 (top) + 1,-1, 1, 1,-1,-1, -1,-1,-1, -1,-1, 1 // v4, v5, v6, v7 (bottom) + }; + + // index array of vertex array for glDrawRangeElement() as a GL_LINES for each edge + const GLubyte LINE_BREAK = static_cast(-1); + static GLubyte cannonicalIndices[indices] = { + 0, 1, 1, 2, 2, 3, 3, 0, // (top) + 4, 5, 5, 6, 6, 7, 7, 4, // (bottom) + 0, 4, 1, 5, 2, 6, 3, 7, // (side edges) + }; + + for (int i = 0; i < vertexPoints; i++) { + vertex[i] = cannonicalVertices[i] * halfSize; + } + + glGenBuffers(1, &vbo.first); + glBindBuffer(GL_ARRAY_BUFFER, vbo.first); + glBufferData(GL_ARRAY_BUFFER, vertices * NUM_BYTES_PER_VERTEX, vertexData, GL_STATIC_DRAW); + delete[] vertexData; + + GLushort* indexData = new GLushort[indices]; + GLushort* index = indexData; + for (int i = 0; i < indices; i++) { + index[i] = cannonicalIndices[i]; + } + + glGenBuffers(1, &vbo.second); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo.second); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices * NUM_BYTES_PER_INDEX, indexData, GL_STATIC_DRAW); + delete[] indexData; + + } else { + glBindBuffer(GL_ARRAY_BUFFER, vbo.first); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo.second); + } + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(FLOATS_PER_VERTEX, GL_FLOAT, FLOATS_PER_VERTEX * sizeof(float), 0); + glDrawRangeElementsEXT(GL_LINES, 0, vertices - 1, indices, GL_UNSIGNED_SHORT, 0); + glDisableClientState(GL_VERTEX_ARRAY); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + } diff --git a/libraries/render-utils/src/GeometryCache.h b/libraries/render-utils/src/GeometryCache.h index 92e65718ab..514ee03c79 100644 --- a/libraries/render-utils/src/GeometryCache.h +++ b/libraries/render-utils/src/GeometryCache.h @@ -68,6 +68,8 @@ private: QHash _squareVBOs; QHash _halfCylinderVBOs; QHash _coneVBOs; + QHash _wireCubeVBOs; + QHash _solidCubeVBOs; QHash _gridBuffers; QHash > _networkGeometry; From 8091564a731f3ea08a275197b3935ce0e5078ae2 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 18 Dec 2014 16:12:30 -0800 Subject: [PATCH 500/502] remove all glut --- interface/src/Application.cpp | 2 - interface/src/Util.cpp | 6 -- libraries/gpu/src/gpu/GLUTConfig.h | 25 ------ libraries/render-utils/src/GeometryCache.cpp | 95 +++++++++++++++++++- 4 files changed, 91 insertions(+), 37 deletions(-) delete mode 100644 libraries/gpu/src/gpu/GLUTConfig.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index d502e380b5..a7b91db315 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -537,8 +537,6 @@ void Application::initializeGL() { } else { isInitialized = true; } - int argc = 0; - glutInit(&argc, 0); #endif #ifdef WIN32 diff --git a/interface/src/Util.cpp b/interface/src/Util.cpp index 38f18e96d9..d795964c5c 100644 --- a/interface/src/Util.cpp +++ b/interface/src/Util.cpp @@ -33,12 +33,6 @@ using namespace std; -// no clue which versions are affected... -#define WORKAROUND_BROKEN_GLUT_STROKES -// see http://www.opengl.org/resources/libraries/glut/spec3/node78.html - - - void renderWorldBox() { // Show edge of world float red[] = {1, 0, 0}; diff --git a/libraries/gpu/src/gpu/GLUTConfig.h b/libraries/gpu/src/gpu/GLUTConfig.h deleted file mode 100644 index 214f2bb2b0..0000000000 --- a/libraries/gpu/src/gpu/GLUTConfig.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// GPUConfig.h -// libraries/gpu/src/gpu -// -// Created by Brad Hefta-Gaub on 12/17/14. -// 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 gpu__GLUTConfig__ -#define gpu__GLUTConfig__ - -// TODO: remove these once we migrate away from GLUT calls -#if defined(__APPLE__) -#include -#elif defined(WIN32) -#include -#else -#include -#endif - - -#endif // gpu__GLUTConfig__ diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index d28702fa20..2837568ef5 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -11,7 +11,6 @@ // include this before QOpenGLBuffer, which includes an earlier version of OpenGL #include -#include // TODO - we need to get rid of this ASAP #include @@ -509,7 +508,97 @@ void GeometryCache::renderGrid(int xDivisions, int yDivisions) { } void GeometryCache::renderSolidCube(float size) { - glutSolidCube(size); + VerticesIndices& vbo = _solidCubeVBOs[size]; + const int FLOATS_PER_VERTEX = 3; + const int VERTICES_PER_FACE = 4; + const int NUMBER_OF_FACES = 6; + const int TRIANGLES_PER_FACE = 2; + const int VERTICES_PER_TRIANGLE = 3; + const int vertices = NUMBER_OF_FACES * VERTICES_PER_FACE * FLOATS_PER_VERTEX; + const int indices = NUMBER_OF_FACES * TRIANGLES_PER_FACE * VERTICES_PER_TRIANGLE; + const int vertexPoints = vertices * FLOATS_PER_VERTEX; + if (vbo.first == 0) { + GLfloat* vertexData = new GLfloat[vertexPoints * 2]; // vertices and normals + GLfloat* vertex = vertexData; + float halfSize = size / 2.0f; + + static GLfloat cannonicalVertices[vertexPoints] = + { 1, 1, 1, -1, 1, 1, -1,-1, 1, 1,-1, 1, // v0,v1,v2,v3 (front) + 1, 1, 1, 1,-1, 1, 1,-1,-1, 1, 1,-1, // v0,v3,v4,v5 (right) + 1, 1, 1, 1, 1,-1, -1, 1,-1, -1, 1, 1, // v0,v5,v6,v1 (top) + -1, 1, 1, -1, 1,-1, -1,-1,-1, -1,-1, 1, // v1,v6,v7,v2 (left) + -1,-1,-1, 1,-1,-1, 1,-1, 1, -1,-1, 1, // v7,v4,v3,v2 (bottom) + 1,-1,-1, -1,-1,-1, -1, 1,-1, 1, 1,-1 }; // v4,v7,v6,v5 (back) + + // normal array + static GLfloat cannonicalNormals[vertexPoints] = + { 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, // v0,v1,v2,v3 (front) + 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, // v0,v3,v4,v5 (right) + 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, // v0,v5,v6,v1 (top) + -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, // v1,v6,v7,v2 (left) + 0,-1, 0, 0,-1, 0, 0,-1, 0, 0,-1, 0, // v7,v4,v3,v2 (bottom) + 0, 0,-1, 0, 0,-1, 0, 0,-1, 0, 0,-1 }; // v4,v7,v6,v5 (back) + + // index array of vertex array for glDrawElements() & glDrawRangeElement() + static GLubyte cannonicalIndices[indices] = + { 0, 1, 2, 2, 3, 0, // front + 4, 5, 6, 6, 7, 4, // right + 8, 9,10, 10,11, 8, // top + 12,13,14, 14,15,12, // left + 16,17,18, 18,19,16, // bottom + 20,21,22, 22,23,20 }; // back + + + + GLfloat* cannonicalVertex = &cannonicalVertices[0]; + GLfloat* cannonicalNormal = &cannonicalNormals[0]; + + for (int i = 0; i < vertices; i++) { + //normals + *(vertex++) = *cannonicalNormal++; + *(vertex++) = *cannonicalNormal++; + *(vertex++) = *cannonicalNormal++; + + // vertices + *(vertex++) = halfSize * *cannonicalVertex++; + *(vertex++) = halfSize * *cannonicalVertex++; + *(vertex++) = halfSize * *cannonicalVertex++; + + } + + glGenBuffers(1, &vbo.first); + glBindBuffer(GL_ARRAY_BUFFER, vbo.first); + glBufferData(GL_ARRAY_BUFFER, vertices * NUM_BYTES_PER_VERTEX, vertexData, GL_STATIC_DRAW); + delete[] vertexData; + + GLushort* indexData = new GLushort[indices]; + GLushort* index = indexData; + for (int i = 0; i < indices; i++) { + index[i] = cannonicalIndices[i]; + } + + glGenBuffers(1, &vbo.second); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo.second); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices * NUM_BYTES_PER_INDEX, indexData, GL_STATIC_DRAW); + delete[] indexData; + + } else { + glBindBuffer(GL_ARRAY_BUFFER, vbo.first); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo.second); + } + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_NORMAL_ARRAY); + + glNormalPointer(GL_FLOAT, 6 * sizeof(float), 0); + glVertexPointer(3, GL_FLOAT, (6 * sizeof(float)), (const void *)(3 * sizeof(float))); + + glDrawRangeElementsEXT(GL_TRIANGLES, 0, vertices - 1, indices, GL_UNSIGNED_SHORT, 0); + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_NORMAL_ARRAY); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); } void GeometryCache::renderWireCube(float size) { @@ -533,7 +622,6 @@ void GeometryCache::renderWireCube(float size) { }; // index array of vertex array for glDrawRangeElement() as a GL_LINES for each edge - const GLubyte LINE_BREAK = static_cast(-1); static GLubyte cannonicalIndices[indices] = { 0, 1, 1, 2, 2, 3, 3, 0, // (top) 4, 5, 5, 6, 6, 7, 7, 4, // (bottom) @@ -571,7 +659,6 @@ void GeometryCache::renderWireCube(float size) { glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - } From 47d8b0b062ee4bd2179d0fe93acc923192575b10 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 18 Dec 2014 16:24:26 -0800 Subject: [PATCH 501/502] Replace Game Of Life with intructions --- .../resources/web/assignment/placeholder.js | 134 +----------------- 1 file changed, 3 insertions(+), 131 deletions(-) diff --git a/domain-server/resources/web/assignment/placeholder.js b/domain-server/resources/web/assignment/placeholder.js index 46a706999f..663215fc7e 100644 --- a/domain-server/resources/web/assignment/placeholder.js +++ b/domain-server/resources/web/assignment/placeholder.js @@ -1,131 +1,3 @@ -// Add your JavaScript for assignment below this line - -// The following is an example of Conway's Game of Life (http://en.wikipedia.org/wiki/Conway's_Game_of_Life) - -var NUMBER_OF_CELLS_EACH_DIMENSION = 64; -var NUMBER_OF_CELLS = NUMBER_OF_CELLS_EACH_DIMENSION * NUMBER_OF_CELLS_EACH_DIMENSION; - -var currentCells = []; -var nextCells = []; - -var METER_LENGTH = 1; -var cellScale = (NUMBER_OF_CELLS_EACH_DIMENSION * METER_LENGTH) / NUMBER_OF_CELLS_EACH_DIMENSION; - -// randomly populate the cell start values -for (var i = 0; i < NUMBER_OF_CELLS_EACH_DIMENSION; i++) { - // create the array to hold this row - currentCells[i] = []; - - // create the array to hold this row in the nextCells array - nextCells[i] = []; - - for (var j = 0; j < NUMBER_OF_CELLS_EACH_DIMENSION; j++) { - currentCells[i][j] = Math.floor(Math.random() * 2); - - // put the same value in the nextCells array for first board draw - nextCells[i][j] = currentCells[i][j]; - } -} - -function isNeighbourAlive(i, j) { - if (i < 0 || i >= NUMBER_OF_CELLS_EACH_DIMENSION - || i < 0 || j >= NUMBER_OF_CELLS_EACH_DIMENSION) { - return 0; - } else { - return currentCells[i][j]; - } -} - -function updateCells() { - var i = 0; - var j = 0; - - for (i = 0; i < NUMBER_OF_CELLS_EACH_DIMENSION; i++) { - for (j = 0; j < NUMBER_OF_CELLS_EACH_DIMENSION; j++) { - // figure out the number of live neighbours for the i-j cell - var liveNeighbours = - isNeighbourAlive(i + 1, j - 1) + isNeighbourAlive(i + 1, j) + isNeighbourAlive(i + 1, j + 1) + - isNeighbourAlive(i, j - 1) + isNeighbourAlive(i, j + 1) + - isNeighbourAlive(i - 1, j - 1) + isNeighbourAlive(i - 1, j) + isNeighbourAlive(i - 1, j + 1); - - if (currentCells[i][j]) { - // live cell - - if (liveNeighbours < 2) { - // rule #1 - under-population - this cell will die - // mark it zero to mark the change - nextCells[i][j] = 0; - } else if (liveNeighbours < 4) { - // rule #2 - this cell lives - // mark it -1 to mark no change - nextCells[i][j] = -1; - } else { - // rule #3 - overcrowding - this cell dies - // mark it zero to mark the change - nextCells[i][j] = 0; - } - } else { - // dead cell - if (liveNeighbours == 3) { - // rule #4 - reproduction - this cell revives - // mark it one to mark the change - nextCells[i][j] = 1; - } else { - // this cell stays dead - // mark it -1 for no change - nextCells[i][j] = -1; - } - } - - if (Math.random() < 0.001) { - // Random mutation to keep things interesting in there. - nextCells[i][j] = 1; - } - } - } - - for (i = 0; i < NUMBER_OF_CELLS_EACH_DIMENSION; i++) { - for (j = 0; j < NUMBER_OF_CELLS_EACH_DIMENSION; j++) { - if (nextCells[i][j] != -1) { - // there has been a change to this cell, change the value in the currentCells array - currentCells[i][j] = nextCells[i][j]; - } - } - } -} - -function sendNextCells() { - for (var i = 0; i < NUMBER_OF_CELLS_EACH_DIMENSION; i++) { - for (var j = 0; j < NUMBER_OF_CELLS_EACH_DIMENSION; j++) { - if (nextCells[i][j] != -1) { - // there has been a change to the state of this cell, send it - - // find the x and y position for this voxel, z = 0 - var x = j * cellScale; - var y = i * cellScale; - - // queue a packet to add a voxel for the new cell - var color = (nextCells[i][j] == 1) ? 255 : 1; - Voxels.setVoxel(x, y, 0, cellScale, color, color, color); - } - } - } -} - -var sentFirstBoard = false; - -function step(deltaTime) { - if (sentFirstBoard) { - // we've already sent the first full board, perform a step in time - updateCells(); - } else { - // this will be our first board send - sentFirstBoard = true; - } - - sendNextCells(); -} - - -Script.update.connect(step); -Voxels.setPacketsPerSecond(200); \ No newline at end of file +// Here you can put a script that will be run by an Assignement Client (AC) +// For examples, please go to http://public.highfidelity.io/scripts +// The directory named acScripts contains Assignement Clients specific scripts you can try. \ No newline at end of file From e6123ec4a7721c427f43728d951eb492c1c5d7c4 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 18 Dec 2014 16:31:19 -0800 Subject: [PATCH 502/502] Typo --- domain-server/resources/web/assignment/placeholder.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/domain-server/resources/web/assignment/placeholder.js b/domain-server/resources/web/assignment/placeholder.js index 663215fc7e..2c1d8253aa 100644 --- a/domain-server/resources/web/assignment/placeholder.js +++ b/domain-server/resources/web/assignment/placeholder.js @@ -1,3 +1,3 @@ -// Here you can put a script that will be run by an Assignement Client (AC) +// Here you can put a script that will be run by an assignment-client (AC) // For examples, please go to http://public.highfidelity.io/scripts -// The directory named acScripts contains Assignement Clients specific scripts you can try. \ No newline at end of file +// The directory named acScripts contains assignment-client specific scripts you can try.