mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-09 15:09:34 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi into graphicsMaster
This commit is contained in:
commit
d8a71db929
40 changed files with 584 additions and 408 deletions
|
@ -1,4 +1,4 @@
|
||||||
cmake_minimum_required(VERSION 2.8.12.2)
|
cmake_minimum_required(VERSION 3.2)
|
||||||
|
|
||||||
if (USE_ANDROID_TOOLCHAIN)
|
if (USE_ANDROID_TOOLCHAIN)
|
||||||
set(CMAKE_TOOLCHAIN_FILE "${CMAKE_CURRENT_SOURCE_DIR}/cmake/android/android.toolchain.cmake")
|
set(CMAKE_TOOLCHAIN_FILE "${CMAKE_CURRENT_SOURCE_DIR}/cmake/android/android.toolchain.cmake")
|
||||||
|
@ -67,9 +67,9 @@ if ((NOT MSVC12) AND (NOT MSVC14))
|
||||||
CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)
|
CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)
|
||||||
|
|
||||||
if (COMPILER_SUPPORTS_CXX11)
|
if (COMPILER_SUPPORTS_CXX11)
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
||||||
elseif(COMPILER_SUPPORTS_CXX0X)
|
elseif(COMPILER_SUPPORTS_CXX0X)
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
|
||||||
else()
|
else()
|
||||||
message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.")
|
message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.")
|
||||||
endif()
|
endif()
|
||||||
|
@ -228,34 +228,4 @@ if (HIFI_MEMORY_DEBUGGING)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
include_application_version()
|
include_application_version()
|
||||||
|
generate_installers()
|
||||||
if (DEFINED DEPLOY_PACKAGE AND DEPLOY_PACKAGE)
|
|
||||||
message(STATUS "+++++ Package for deployment will be generated on this build +++++")
|
|
||||||
|
|
||||||
file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/full-stack-deployment)
|
|
||||||
|
|
||||||
set(ICONPATH_INTERFACE "$INSTDIR/${PATH_INSTALL_DATA}/interface.ico")
|
|
||||||
set(ICONPATH_STACK_MANAGER "$INSTDIR/${PATH_INSTALL_DATA}/stack-manager.ico")
|
|
||||||
string(REPLACE "/" "\\\\" ICONPATH_INTERFACE ${ICONPATH_INTERFACE})
|
|
||||||
string(REPLACE "/" "\\\\" ICONPATH_STACK_MANAGER ${ICONPATH_STACK_MANAGER})
|
|
||||||
|
|
||||||
set(CPACK_PACKAGE_NAME "High Fidelity")
|
|
||||||
set(CPACK_PACKAGE_VENDOR "High Fidelity, Inc")
|
|
||||||
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "High Fidelity Interface and Stack")
|
|
||||||
set(CPACK_PACKAGE_VERSION "${BUILD_SEQ}")
|
|
||||||
set(CPACK_PACKAGE_VERSION_MAJOR "${BUILD_SEQ}")
|
|
||||||
set(CPACK_PACKAGE_VERSION_MINOR "0")
|
|
||||||
set(CPACK_PACKAGE_VERSION_PATCH "0")
|
|
||||||
set(CPACK_PACKAGE_INSTALL_DIRECTORY "High Fidelity-${BUILD_SEQ}")
|
|
||||||
set(CPACK_NSIS_EXECUTABLES_DIRECTORY ".")
|
|
||||||
set(CPACK_PACKAGE_EXECUTABLES
|
|
||||||
stack-manager "Stack Manager"
|
|
||||||
interface "Interface"
|
|
||||||
)
|
|
||||||
|
|
||||||
if (WIN32)
|
|
||||||
install(DIRECTORY ${CMAKE_BINARY_DIR}/full-stack-deployment/ DESTINATION "./")
|
|
||||||
endif (WIN32)
|
|
||||||
|
|
||||||
include(CPack)
|
|
||||||
endif ()
|
|
|
@ -35,6 +35,7 @@
|
||||||
#include "AssignmentActionFactory.h"
|
#include "AssignmentActionFactory.h"
|
||||||
|
|
||||||
#include "AssignmentClient.h"
|
#include "AssignmentClient.h"
|
||||||
|
#include "AssignmentClientLogging.h"
|
||||||
#include "avatars/ScriptableAvatar.h"
|
#include "avatars/ScriptableAvatar.h"
|
||||||
|
|
||||||
const QString ASSIGNMENT_CLIENT_TARGET_NAME = "assignment-client";
|
const QString ASSIGNMENT_CLIENT_TARGET_NAME = "assignment-client";
|
||||||
|
@ -84,7 +85,7 @@ AssignmentClient::AssignmentClient(Assignment::Type requestAssignmentType, QStri
|
||||||
// check for a wallet UUID on the command line or in the config
|
// check for a wallet UUID on the command line or in the config
|
||||||
// this would represent where the user running AC wants funds sent to
|
// this would represent where the user running AC wants funds sent to
|
||||||
if (!walletUUID.isNull()) {
|
if (!walletUUID.isNull()) {
|
||||||
qDebug() << "The destination wallet UUID for credits is" << uuidStringWithoutCurlyBraces(walletUUID);
|
qCDebug(assigmnentclient) << "The destination wallet UUID for credits is" << uuidStringWithoutCurlyBraces(walletUUID);
|
||||||
_requestAssignment.setWalletUUID(walletUUID);
|
_requestAssignment.setWalletUUID(walletUUID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,13 +99,13 @@ AssignmentClient::AssignmentClient(Assignment::Type requestAssignmentType, QStri
|
||||||
_assignmentServerSocket.setObjectName("AssigmentServer");
|
_assignmentServerSocket.setObjectName("AssigmentServer");
|
||||||
nodeList->setAssignmentServerSocket(_assignmentServerSocket);
|
nodeList->setAssignmentServerSocket(_assignmentServerSocket);
|
||||||
|
|
||||||
qDebug() << "Assignment server socket is" << _assignmentServerSocket;
|
qCDebug(assigmnentclient) << "Assignment server socket is" << _assignmentServerSocket;
|
||||||
|
|
||||||
// call a timer function every ASSIGNMENT_REQUEST_INTERVAL_MSECS to ask for assignment, if required
|
// call a timer function every ASSIGNMENT_REQUEST_INTERVAL_MSECS to ask for assignment, if required
|
||||||
qDebug() << "Waiting for assignment -" << _requestAssignment;
|
qCDebug(assigmnentclient) << "Waiting for assignment -" << _requestAssignment;
|
||||||
|
|
||||||
if (_assignmentServerHostname != "localhost") {
|
if (_assignmentServerHostname != "localhost") {
|
||||||
qDebug () << "- will attempt to connect to domain-server on" << _assignmentServerSocket.getPort();
|
qCDebug(assigmnentclient) << "- will attempt to connect to domain-server on" << _assignmentServerSocket.getPort();
|
||||||
}
|
}
|
||||||
|
|
||||||
connect(&_requestTimer, SIGNAL(timeout()), SLOT(sendAssignmentRequest()));
|
connect(&_requestTimer, SIGNAL(timeout()), SLOT(sendAssignmentRequest()));
|
||||||
|
@ -122,7 +123,7 @@ AssignmentClient::AssignmentClient(Assignment::Type requestAssignmentType, QStri
|
||||||
_assignmentClientMonitorSocket = HifiSockAddr(DEFAULT_ASSIGNMENT_CLIENT_MONITOR_HOSTNAME, assignmentMonitorPort);
|
_assignmentClientMonitorSocket = HifiSockAddr(DEFAULT_ASSIGNMENT_CLIENT_MONITOR_HOSTNAME, assignmentMonitorPort);
|
||||||
_assignmentClientMonitorSocket.setObjectName("AssignmentClientMonitor");
|
_assignmentClientMonitorSocket.setObjectName("AssignmentClientMonitor");
|
||||||
|
|
||||||
qDebug() << "Assignment-client monitor socket is" << _assignmentClientMonitorSocket;
|
qCDebug(assigmnentclient) << "Assignment-client monitor socket is" << _assignmentClientMonitorSocket;
|
||||||
|
|
||||||
// Hook up a timer to send this child's status to the Monitor once per second
|
// Hook up a timer to send this child's status to the Monitor once per second
|
||||||
setUpStatusToMonitor();
|
setUpStatusToMonitor();
|
||||||
|
@ -133,7 +134,7 @@ AssignmentClient::AssignmentClient(Assignment::Type requestAssignmentType, QStri
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssignmentClient::stopAssignmentClient() {
|
void AssignmentClient::stopAssignmentClient() {
|
||||||
qDebug() << "Forced stop of assignment-client.";
|
qCDebug(assigmnentclient) << "Forced stop of assignment-client.";
|
||||||
|
|
||||||
_requestTimer.stop();
|
_requestTimer.stop();
|
||||||
_statsTimerACM.stop();
|
_statsTimerACM.stop();
|
||||||
|
@ -209,14 +210,14 @@ void AssignmentClient::sendAssignmentRequest() {
|
||||||
quint16 localAssignmentServerPort;
|
quint16 localAssignmentServerPort;
|
||||||
if (nodeList->getLocalServerPortFromSharedMemory(DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY, localAssignmentServerPort)) {
|
if (nodeList->getLocalServerPortFromSharedMemory(DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY, localAssignmentServerPort)) {
|
||||||
if (localAssignmentServerPort != _assignmentServerSocket.getPort()) {
|
if (localAssignmentServerPort != _assignmentServerSocket.getPort()) {
|
||||||
qDebug() << "Port for local assignment server read from shared memory is"
|
qCDebug(assigmnentclient) << "Port for local assignment server read from shared memory is"
|
||||||
<< localAssignmentServerPort;
|
<< localAssignmentServerPort;
|
||||||
|
|
||||||
_assignmentServerSocket.setPort(localAssignmentServerPort);
|
_assignmentServerSocket.setPort(localAssignmentServerPort);
|
||||||
nodeList->setAssignmentServerSocket(_assignmentServerSocket);
|
nodeList->setAssignmentServerSocket(_assignmentServerSocket);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
qDebug() << "Failed to read local assignment server port from shared memory"
|
qCWarning(assigmnentclient) << "Failed to read local assignment server port from shared memory"
|
||||||
<< "- will send assignment request to previous assignment server socket.";
|
<< "- will send assignment request to previous assignment server socket.";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -226,13 +227,13 @@ void AssignmentClient::sendAssignmentRequest() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssignmentClient::handleCreateAssignmentPacket(QSharedPointer<ReceivedMessage> message) {
|
void AssignmentClient::handleCreateAssignmentPacket(QSharedPointer<ReceivedMessage> message) {
|
||||||
qDebug() << "Received a PacketType::CreateAssignment - attempting to unpack.";
|
qCDebug(assigmnentclient) << "Received a PacketType::CreateAssignment - attempting to unpack.";
|
||||||
|
|
||||||
// construct the deployed assignment from the packet data
|
// construct the deployed assignment from the packet data
|
||||||
_currentAssignment = AssignmentFactory::unpackAssignment(*message);
|
_currentAssignment = AssignmentFactory::unpackAssignment(*message);
|
||||||
|
|
||||||
if (_currentAssignment && !_isAssigned) {
|
if (_currentAssignment && !_isAssigned) {
|
||||||
qDebug() << "Received an assignment -" << *_currentAssignment;
|
qDebug(assigmnentclient) << "Received an assignment -" << *_currentAssignment;
|
||||||
_isAssigned = true;
|
_isAssigned = true;
|
||||||
|
|
||||||
auto nodeList = DependencyManager::get<NodeList>();
|
auto nodeList = DependencyManager::get<NodeList>();
|
||||||
|
@ -242,7 +243,7 @@ void AssignmentClient::handleCreateAssignmentPacket(QSharedPointer<ReceivedMessa
|
||||||
nodeList->getDomainHandler().setSockAddr(message->getSenderSockAddr(), _assignmentServerHostname);
|
nodeList->getDomainHandler().setSockAddr(message->getSenderSockAddr(), _assignmentServerHostname);
|
||||||
nodeList->getDomainHandler().setAssignmentUUID(_currentAssignment->getUUID());
|
nodeList->getDomainHandler().setAssignmentUUID(_currentAssignment->getUUID());
|
||||||
|
|
||||||
qDebug() << "Destination IP for assignment is" << nodeList->getDomainHandler().getIP().toString();
|
qCDebug(assigmnentclient) << "Destination IP for assignment is" << nodeList->getDomainHandler().getIP().toString();
|
||||||
|
|
||||||
// start the deployed assignment
|
// start the deployed assignment
|
||||||
QThread* workerThread = new QThread;
|
QThread* workerThread = new QThread;
|
||||||
|
@ -270,7 +271,7 @@ void AssignmentClient::handleCreateAssignmentPacket(QSharedPointer<ReceivedMessa
|
||||||
// Starts an event loop, and emits workerThread->started()
|
// Starts an event loop, and emits workerThread->started()
|
||||||
workerThread->start();
|
workerThread->start();
|
||||||
} else {
|
} else {
|
||||||
qDebug() << "Received an assignment that could not be unpacked. Re-requesting.";
|
qCWarning(assigmnentclient) << "Received an assignment that could not be unpacked. Re-requesting.";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -278,12 +279,12 @@ void AssignmentClient::handleStopNodePacket(QSharedPointer<ReceivedMessage> mess
|
||||||
const HifiSockAddr& senderSockAddr = message->getSenderSockAddr();
|
const HifiSockAddr& senderSockAddr = message->getSenderSockAddr();
|
||||||
|
|
||||||
if (senderSockAddr.getAddress() == QHostAddress::LocalHost ||
|
if (senderSockAddr.getAddress() == QHostAddress::LocalHost ||
|
||||||
senderSockAddr.getAddress() == QHostAddress::LocalHostIPv6) {
|
senderSockAddr.getAddress() == QHostAddress::LocalHostIPv6) {
|
||||||
qDebug() << "AssignmentClientMonitor at" << senderSockAddr << "requested stop via PacketType::StopNode.";
|
|
||||||
|
qCDebug(assigmnentclient) << "AssignmentClientMonitor at" << senderSockAddr << "requested stop via PacketType::StopNode.";
|
||||||
QCoreApplication::quit();
|
QCoreApplication::quit();
|
||||||
} else {
|
} else {
|
||||||
qDebug() << "Got a stop packet from other than localhost.";
|
qCWarning(assigmnentclient) << "Got a stop packet from other than localhost.";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -303,7 +304,7 @@ void AssignmentClient::handleAuthenticationRequest() {
|
||||||
// ask the account manager to log us in from the env variables
|
// ask the account manager to log us in from the env variables
|
||||||
accountManager.requestAccessToken(username, password);
|
accountManager.requestAccessToken(username, password);
|
||||||
} else {
|
} else {
|
||||||
qDebug() << "Authentication was requested against" << qPrintable(accountManager.getAuthURL().toString())
|
qCWarning(assigmnentclient) << "Authentication was requested against" << qPrintable(accountManager.getAuthURL().toString())
|
||||||
<< "but both or one of" << qPrintable(DATA_SERVER_USERNAME_ENV)
|
<< "but both or one of" << qPrintable(DATA_SERVER_USERNAME_ENV)
|
||||||
<< "/" << qPrintable(DATA_SERVER_PASSWORD_ENV) << "are not set. Unable to authenticate.";
|
<< "/" << qPrintable(DATA_SERVER_PASSWORD_ENV) << "are not set. Unable to authenticate.";
|
||||||
|
|
||||||
|
@ -321,7 +322,7 @@ void AssignmentClient::assignmentCompleted() {
|
||||||
// reset the logging target to the the CHILD_TARGET_NAME
|
// reset the logging target to the the CHILD_TARGET_NAME
|
||||||
LogHandler::getInstance().setTargetName(ASSIGNMENT_CLIENT_TARGET_NAME);
|
LogHandler::getInstance().setTargetName(ASSIGNMENT_CLIENT_TARGET_NAME);
|
||||||
|
|
||||||
qDebug() << "Assignment finished or never started - waiting for new assignment.";
|
qCDebug(assigmnentclient) << "Assignment finished or never started - waiting for new assignment.";
|
||||||
|
|
||||||
auto nodeList = DependencyManager::get<NodeList>();
|
auto nodeList = DependencyManager::get<NodeList>();
|
||||||
|
|
||||||
|
|
14
assignment-client/src/AssignmentClientLogging.cpp
Normal file
14
assignment-client/src/AssignmentClientLogging.cpp
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
//
|
||||||
|
// AssignmentClientLogging.cpp
|
||||||
|
// assignment-client/src
|
||||||
|
//
|
||||||
|
// Created by Clement on 12/14/15.
|
||||||
|
// Copyright 2015 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "AssignmentClientLogging.h"
|
||||||
|
|
||||||
|
Q_LOGGING_CATEGORY(assigmnentclient, "hifi.assignment-client")
|
19
assignment-client/src/AssignmentClientLogging.h
Normal file
19
assignment-client/src/AssignmentClientLogging.h
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
//
|
||||||
|
// AssignmentClientLogging.h
|
||||||
|
// assignment-client/src
|
||||||
|
//
|
||||||
|
// Created by Clement on 12/14/15.
|
||||||
|
// Copyright 2015 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef hifi_AssignmentClientLogging_h
|
||||||
|
#define hifi_AssignmentClientLogging_h
|
||||||
|
|
||||||
|
#include <QLoggingCategory>
|
||||||
|
|
||||||
|
Q_DECLARE_LOGGING_CATEGORY(assigmnentclient)
|
||||||
|
|
||||||
|
#endif // hifi_AssignmentClientLogging_h
|
|
@ -20,80 +20,8 @@
|
||||||
|
|
||||||
#include "OctreeSendThread.h"
|
#include "OctreeSendThread.h"
|
||||||
|
|
||||||
OctreeQueryNode::OctreeQueryNode() :
|
|
||||||
_viewSent(false),
|
|
||||||
_octreePacket(),
|
|
||||||
_octreePacketWaiting(false),
|
|
||||||
_lastOctreePayload(new char[udt::MAX_PACKET_SIZE]),
|
|
||||||
_lastOctreePacketLength(0),
|
|
||||||
_duplicatePacketCount(0),
|
|
||||||
_firstSuppressedPacket(usecTimestampNow()),
|
|
||||||
_maxSearchLevel(1),
|
|
||||||
_maxLevelReachedInLastSearch(1),
|
|
||||||
_lastTimeBagEmpty(0),
|
|
||||||
_viewFrustumChanging(false),
|
|
||||||
_viewFrustumJustStoppedChanging(true),
|
|
||||||
_octreeSendThread(NULL),
|
|
||||||
_lastClientBoundaryLevelAdjust(0),
|
|
||||||
_lastClientOctreeSizeScale(DEFAULT_OCTREE_SIZE_SCALE),
|
|
||||||
_lodChanged(false),
|
|
||||||
_lodInitialized(false),
|
|
||||||
_sequenceNumber(0),
|
|
||||||
_lastRootTimestamp(0),
|
|
||||||
_myPacketType(PacketType::Unknown),
|
|
||||||
_isShuttingDown(false),
|
|
||||||
_sentPacketHistory()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
OctreeQueryNode::~OctreeQueryNode() {
|
|
||||||
_isShuttingDown = true;
|
|
||||||
if (_octreeSendThread) {
|
|
||||||
forceNodeShutdown();
|
|
||||||
}
|
|
||||||
|
|
||||||
delete[] _lastOctreePayload;
|
|
||||||
}
|
|
||||||
|
|
||||||
void OctreeQueryNode::nodeKilled() {
|
void OctreeQueryNode::nodeKilled() {
|
||||||
_isShuttingDown = true;
|
_isShuttingDown = true;
|
||||||
if (_octreeSendThread) {
|
|
||||||
// just tell our thread we want to shutdown, this is asynchronous, and fast, we don't need or want it to block
|
|
||||||
// while the thread actually shuts down
|
|
||||||
_octreeSendThread->setIsShuttingDown();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void OctreeQueryNode::forceNodeShutdown() {
|
|
||||||
_isShuttingDown = true;
|
|
||||||
if (_octreeSendThread) {
|
|
||||||
// we really need to force our thread to shutdown, this is synchronous, we will block while the thread actually
|
|
||||||
// shuts down because we really need it to shutdown, and it's ok if we wait for it to complete
|
|
||||||
OctreeSendThread* sendThread = _octreeSendThread;
|
|
||||||
_octreeSendThread = NULL;
|
|
||||||
sendThread->setIsShuttingDown();
|
|
||||||
sendThread->terminate();
|
|
||||||
delete sendThread;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void OctreeQueryNode::sendThreadFinished() {
|
|
||||||
// We've been notified by our thread that it is shutting down. So we can clean up our reference to it, and
|
|
||||||
// delete the actual thread object. Cleaning up our thread will correctly unroll all refereces to shared
|
|
||||||
// pointers to our node as well as the octree server assignment
|
|
||||||
if (_octreeSendThread) {
|
|
||||||
OctreeSendThread* sendThread = _octreeSendThread;
|
|
||||||
_octreeSendThread = NULL;
|
|
||||||
delete sendThread;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void OctreeQueryNode::initializeOctreeSendThread(OctreeServer* myServer, const SharedNodePointer& node) {
|
|
||||||
_octreeSendThread = new OctreeSendThread(myServer, node);
|
|
||||||
|
|
||||||
// we want to be notified when the thread finishes
|
|
||||||
connect(_octreeSendThread, &GenericThread::finished, this, &OctreeQueryNode::sendThreadFinished);
|
|
||||||
_octreeSendThread->initialize(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OctreeQueryNode::packetIsDuplicate() const {
|
bool OctreeQueryNode::packetIsDuplicate() const {
|
||||||
|
@ -105,7 +33,7 @@ bool OctreeQueryNode::packetIsDuplicate() const {
|
||||||
// of the entire packet, we need to compare only the packet content...
|
// of the entire packet, we need to compare only the packet content...
|
||||||
|
|
||||||
if (_lastOctreePacketLength == _octreePacket->getPayloadSize()) {
|
if (_lastOctreePacketLength == _octreePacket->getPayloadSize()) {
|
||||||
if (memcmp(_lastOctreePayload + OCTREE_PACKET_EXTRA_HEADERS_SIZE,
|
if (memcmp(&_lastOctreePayload + OCTREE_PACKET_EXTRA_HEADERS_SIZE,
|
||||||
_octreePacket->getPayload() + OCTREE_PACKET_EXTRA_HEADERS_SIZE,
|
_octreePacket->getPayload() + OCTREE_PACKET_EXTRA_HEADERS_SIZE,
|
||||||
_octreePacket->getPayloadSize() - OCTREE_PACKET_EXTRA_HEADERS_SIZE) == 0) {
|
_octreePacket->getPayloadSize() - OCTREE_PACKET_EXTRA_HEADERS_SIZE) == 0) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -173,7 +101,7 @@ void OctreeQueryNode::resetOctreePacket() {
|
||||||
// scene information, (e.g. the root node packet of a static scene), we can use this as a strategy for reducing
|
// scene information, (e.g. the root node packet of a static scene), we can use this as a strategy for reducing
|
||||||
// packet send rate.
|
// packet send rate.
|
||||||
_lastOctreePacketLength = _octreePacket->getPayloadSize();
|
_lastOctreePacketLength = _octreePacket->getPayloadSize();
|
||||||
memcpy(_lastOctreePayload, _octreePacket->getPayload(), _lastOctreePacketLength);
|
memcpy(&_lastOctreePayload, _octreePacket->getPayload(), _lastOctreePacketLength);
|
||||||
|
|
||||||
// If we're moving, and the client asked for low res, then we force monochrome, otherwise, use
|
// If we're moving, and the client asked for low res, then we force monochrome, otherwise, use
|
||||||
// the clients requested color state.
|
// the clients requested color state.
|
||||||
|
|
|
@ -29,8 +29,8 @@ class OctreeServer;
|
||||||
class OctreeQueryNode : public OctreeQuery {
|
class OctreeQueryNode : public OctreeQuery {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
OctreeQueryNode();
|
OctreeQueryNode() = default;
|
||||||
virtual ~OctreeQueryNode();
|
virtual ~OctreeQueryNode() = default;
|
||||||
|
|
||||||
void init(); // called after creation to set up some virtual items
|
void init(); // called after creation to set up some virtual items
|
||||||
virtual PacketType getMyPacketType() const = 0;
|
virtual PacketType getMyPacketType() const = 0;
|
||||||
|
@ -79,9 +79,6 @@ public:
|
||||||
|
|
||||||
OctreeSceneStats stats;
|
OctreeSceneStats stats;
|
||||||
|
|
||||||
void initializeOctreeSendThread(OctreeServer* myServer, const SharedNodePointer& node);
|
|
||||||
bool isOctreeSendThreadInitalized() { return _octreeSendThread; }
|
|
||||||
|
|
||||||
void dumpOutOfView();
|
void dumpOutOfView();
|
||||||
|
|
||||||
quint64 getLastRootTimestamp() const { return _lastRootTimestamp; }
|
quint64 getLastRootTimestamp() const { return _lastRootTimestamp; }
|
||||||
|
@ -92,7 +89,6 @@ public:
|
||||||
void sceneStart(quint64 sceneSendStartTime) { _sceneSendStartTime = sceneSendStartTime; }
|
void sceneStart(quint64 sceneSendStartTime) { _sceneSendStartTime = sceneSendStartTime; }
|
||||||
|
|
||||||
void nodeKilled();
|
void nodeKilled();
|
||||||
void forceNodeShutdown();
|
|
||||||
bool isShuttingDown() const { return _isShuttingDown; }
|
bool isShuttingDown() const { return _isShuttingDown; }
|
||||||
|
|
||||||
void octreePacketSent() { packetSent(*_octreePacket); }
|
void octreePacketSent() { packetSent(*_octreePacket); }
|
||||||
|
@ -104,49 +100,47 @@ public:
|
||||||
bool hasNextNackedPacket() const;
|
bool hasNextNackedPacket() const;
|
||||||
const NLPacket* getNextNackedPacket();
|
const NLPacket* getNextNackedPacket();
|
||||||
|
|
||||||
private slots:
|
|
||||||
void sendThreadFinished();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
OctreeQueryNode(const OctreeQueryNode &);
|
OctreeQueryNode(const OctreeQueryNode &);
|
||||||
OctreeQueryNode& operator= (const OctreeQueryNode&);
|
OctreeQueryNode& operator= (const OctreeQueryNode&);
|
||||||
|
|
||||||
bool _viewSent;
|
bool _viewSent { false };
|
||||||
std::unique_ptr<NLPacket> _octreePacket;
|
std::unique_ptr<NLPacket> _octreePacket;
|
||||||
bool _octreePacketWaiting;
|
bool _octreePacketWaiting;
|
||||||
|
|
||||||
char* _lastOctreePayload = nullptr;
|
unsigned int _lastOctreePacketLength { 0 };
|
||||||
unsigned int _lastOctreePacketLength;
|
int _duplicatePacketCount { 0 };
|
||||||
int _duplicatePacketCount;
|
quint64 _firstSuppressedPacket { usecTimestampNow() };
|
||||||
quint64 _firstSuppressedPacket;
|
|
||||||
|
|
||||||
int _maxSearchLevel;
|
int _maxSearchLevel { 1 };
|
||||||
int _maxLevelReachedInLastSearch;
|
int _maxLevelReachedInLastSearch { 1 };
|
||||||
ViewFrustum _currentViewFrustum;
|
ViewFrustum _currentViewFrustum;
|
||||||
ViewFrustum _lastKnownViewFrustum;
|
ViewFrustum _lastKnownViewFrustum;
|
||||||
quint64 _lastTimeBagEmpty;
|
quint64 _lastTimeBagEmpty { 0 };
|
||||||
bool _viewFrustumChanging;
|
bool _viewFrustumChanging { false };
|
||||||
bool _viewFrustumJustStoppedChanging;
|
bool _viewFrustumJustStoppedChanging { true };
|
||||||
|
|
||||||
OctreeSendThread* _octreeSendThread;
|
OctreeSendThread* _octreeSendThread { nullptr };
|
||||||
|
|
||||||
// watch for LOD changes
|
// watch for LOD changes
|
||||||
int _lastClientBoundaryLevelAdjust;
|
int _lastClientBoundaryLevelAdjust { 0 };
|
||||||
float _lastClientOctreeSizeScale;
|
float _lastClientOctreeSizeScale { DEFAULT_OCTREE_SIZE_SCALE };
|
||||||
bool _lodChanged;
|
bool _lodChanged { false };
|
||||||
bool _lodInitialized;
|
bool _lodInitialized { false };
|
||||||
|
|
||||||
OCTREE_PACKET_SEQUENCE _sequenceNumber;
|
OCTREE_PACKET_SEQUENCE _sequenceNumber { 0 };
|
||||||
|
|
||||||
quint64 _lastRootTimestamp;
|
quint64 _lastRootTimestamp { 0 };
|
||||||
|
|
||||||
PacketType _myPacketType;
|
PacketType _myPacketType { PacketType::Unknown };
|
||||||
bool _isShuttingDown;
|
bool _isShuttingDown { false };
|
||||||
|
|
||||||
SentPacketHistory _sentPacketHistory;
|
SentPacketHistory _sentPacketHistory;
|
||||||
QQueue<OCTREE_PACKET_SEQUENCE> _nackedSequenceNumbers;
|
QQueue<OCTREE_PACKET_SEQUENCE> _nackedSequenceNumbers;
|
||||||
|
|
||||||
quint64 _sceneSendStartTime = 0;
|
quint64 _sceneSendStartTime = 0;
|
||||||
|
|
||||||
|
std::array<char, udt::MAX_PACKET_SIZE> _lastOctreePayload;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_OctreeQueryNode_h
|
#endif // hifi_OctreeQueryNode_h
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include <udt/PacketHeaders.h>
|
#include <udt/PacketHeaders.h>
|
||||||
#include <PerfStat.h>
|
#include <PerfStat.h>
|
||||||
|
|
||||||
|
#include "OctreeQueryNode.h"
|
||||||
#include "OctreeSendThread.h"
|
#include "OctreeSendThread.h"
|
||||||
#include "OctreeServer.h"
|
#include "OctreeServer.h"
|
||||||
#include "OctreeServerConsts.h"
|
#include "OctreeServerConsts.h"
|
||||||
|
@ -25,15 +26,12 @@ quint64 endSceneSleepTime = 0;
|
||||||
OctreeSendThread::OctreeSendThread(OctreeServer* myServer, const SharedNodePointer& node) :
|
OctreeSendThread::OctreeSendThread(OctreeServer* myServer, const SharedNodePointer& node) :
|
||||||
_myServer(myServer),
|
_myServer(myServer),
|
||||||
_node(node),
|
_node(node),
|
||||||
_nodeUUID(node->getUUID()),
|
_nodeUuid(node->getUUID())
|
||||||
_packetData(),
|
|
||||||
_nodeMissingCount(0),
|
|
||||||
_isShuttingDown(false)
|
|
||||||
{
|
{
|
||||||
QString safeServerName("Octree");
|
QString safeServerName("Octree");
|
||||||
|
|
||||||
// set our QThread object name so we can identify this thread while debugging
|
// set our QThread object name so we can identify this thread while debugging
|
||||||
setObjectName(QString("Octree Send Thread (%1)").arg(uuidStringWithoutCurlyBraces(node->getUUID())));
|
setObjectName(QString("Octree Send Thread (%1)").arg(uuidStringWithoutCurlyBraces(_nodeUuid)));
|
||||||
|
|
||||||
if (_myServer) {
|
if (_myServer) {
|
||||||
safeServerName = _myServer->getMyServerName();
|
safeServerName = _myServer->getMyServerName();
|
||||||
|
@ -46,6 +44,8 @@ OctreeSendThread::OctreeSendThread(OctreeServer* myServer, const SharedNodePoint
|
||||||
}
|
}
|
||||||
|
|
||||||
OctreeSendThread::~OctreeSendThread() {
|
OctreeSendThread::~OctreeSendThread() {
|
||||||
|
setIsShuttingDown();
|
||||||
|
|
||||||
QString safeServerName("Octree");
|
QString safeServerName("Octree");
|
||||||
if (_myServer) {
|
if (_myServer) {
|
||||||
safeServerName = _myServer->getMyServerName();
|
safeServerName = _myServer->getMyServerName();
|
||||||
|
@ -56,8 +56,6 @@ OctreeSendThread::~OctreeSendThread() {
|
||||||
|
|
||||||
OctreeServer::clientDisconnected();
|
OctreeServer::clientDisconnected();
|
||||||
OctreeServer::stopTrackingThread(this);
|
OctreeServer::stopTrackingThread(this);
|
||||||
|
|
||||||
_node.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OctreeSendThread::setIsShuttingDown() {
|
void OctreeSendThread::setIsShuttingDown() {
|
||||||
|
@ -79,15 +77,17 @@ bool OctreeSendThread::process() {
|
||||||
|
|
||||||
// don't do any send processing until the initial load of the octree is complete...
|
// don't do any send processing until the initial load of the octree is complete...
|
||||||
if (_myServer->isInitialLoadComplete()) {
|
if (_myServer->isInitialLoadComplete()) {
|
||||||
if (_node) {
|
if (auto node = _node.lock()) {
|
||||||
_nodeMissingCount = 0;
|
_nodeMissingCount = 0;
|
||||||
OctreeQueryNode* nodeData = static_cast<OctreeQueryNode*>(_node->getLinkedData());
|
OctreeQueryNode* nodeData = static_cast<OctreeQueryNode*>(node->getLinkedData());
|
||||||
|
|
||||||
// Sometimes the node data has not yet been linked, in which case we can't really do anything
|
// Sometimes the node data has not yet been linked, in which case we can't really do anything
|
||||||
if (nodeData && !nodeData->isShuttingDown()) {
|
if (nodeData && !nodeData->isShuttingDown()) {
|
||||||
bool viewFrustumChanged = nodeData->updateCurrentViewFrustum();
|
bool viewFrustumChanged = nodeData->updateCurrentViewFrustum();
|
||||||
packetDistributor(nodeData, viewFrustumChanged);
|
packetDistributor(node, nodeData, viewFrustumChanged);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
return false; // exit early if we're shutting down
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,7 +123,8 @@ AtomicUIntStat OctreeSendThread::_totalSpecialBytes { 0 };
|
||||||
AtomicUIntStat OctreeSendThread::_totalSpecialPackets { 0 };
|
AtomicUIntStat OctreeSendThread::_totalSpecialPackets { 0 };
|
||||||
|
|
||||||
|
|
||||||
int OctreeSendThread::handlePacketSend(OctreeQueryNode* nodeData, int& trueBytesSent, int& truePacketsSent) {
|
int OctreeSendThread::handlePacketSend(SharedNodePointer node, OctreeQueryNode* nodeData, int& trueBytesSent,
|
||||||
|
int& truePacketsSent) {
|
||||||
OctreeServer::didHandlePacketSend(this);
|
OctreeServer::didHandlePacketSend(this);
|
||||||
|
|
||||||
// if we're shutting down, then exit early
|
// if we're shutting down, then exit early
|
||||||
|
@ -183,12 +184,12 @@ int OctreeSendThread::handlePacketSend(OctreeQueryNode* nodeData, int& trueBytes
|
||||||
|
|
||||||
// actually send it
|
// actually send it
|
||||||
OctreeServer::didCallWriteDatagram(this);
|
OctreeServer::didCallWriteDatagram(this);
|
||||||
DependencyManager::get<NodeList>()->sendUnreliablePacket(statsPacket, *_node);
|
DependencyManager::get<NodeList>()->sendUnreliablePacket(statsPacket, *node);
|
||||||
packetSent = true;
|
packetSent = true;
|
||||||
} else {
|
} else {
|
||||||
// not enough room in the packet, send two packets
|
// not enough room in the packet, send two packets
|
||||||
OctreeServer::didCallWriteDatagram(this);
|
OctreeServer::didCallWriteDatagram(this);
|
||||||
DependencyManager::get<NodeList>()->sendUnreliablePacket(statsPacket, *_node);
|
DependencyManager::get<NodeList>()->sendUnreliablePacket(statsPacket, *node);
|
||||||
|
|
||||||
// since a stats message is only included on end of scene, don't consider any of these bytes "wasted", since
|
// since a stats message is only included on end of scene, don't consider any of these bytes "wasted", since
|
||||||
// there was nothing else to send.
|
// there was nothing else to send.
|
||||||
|
@ -219,7 +220,7 @@ int OctreeSendThread::handlePacketSend(OctreeQueryNode* nodeData, int& trueBytes
|
||||||
packetsSent++;
|
packetsSent++;
|
||||||
|
|
||||||
OctreeServer::didCallWriteDatagram(this);
|
OctreeServer::didCallWriteDatagram(this);
|
||||||
DependencyManager::get<NodeList>()->sendUnreliablePacket(nodeData->getPacket(), *_node);
|
DependencyManager::get<NodeList>()->sendUnreliablePacket(nodeData->getPacket(), *node);
|
||||||
packetSent = true;
|
packetSent = true;
|
||||||
|
|
||||||
int packetSizeWithHeader = nodeData->getPacket().getDataSize();
|
int packetSizeWithHeader = nodeData->getPacket().getDataSize();
|
||||||
|
@ -251,7 +252,7 @@ int OctreeSendThread::handlePacketSend(OctreeQueryNode* nodeData, int& trueBytes
|
||||||
if (nodeData->isPacketWaiting() && !nodeData->isShuttingDown()) {
|
if (nodeData->isPacketWaiting() && !nodeData->isShuttingDown()) {
|
||||||
// just send the octree packet
|
// just send the octree packet
|
||||||
OctreeServer::didCallWriteDatagram(this);
|
OctreeServer::didCallWriteDatagram(this);
|
||||||
DependencyManager::get<NodeList>()->sendUnreliablePacket(nodeData->getPacket(), *_node);
|
DependencyManager::get<NodeList>()->sendUnreliablePacket(nodeData->getPacket(), *node);
|
||||||
packetSent = true;
|
packetSent = true;
|
||||||
|
|
||||||
int packetSizeWithHeader = nodeData->getPacket().getDataSize();
|
int packetSizeWithHeader = nodeData->getPacket().getDataSize();
|
||||||
|
@ -293,7 +294,7 @@ int OctreeSendThread::handlePacketSend(OctreeQueryNode* nodeData, int& trueBytes
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Version of octree element distributor that sends the deepest LOD level at once
|
/// Version of octree element distributor that sends the deepest LOD level at once
|
||||||
int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrustumChanged) {
|
int OctreeSendThread::packetDistributor(SharedNodePointer node, OctreeQueryNode* nodeData, bool viewFrustumChanged) {
|
||||||
|
|
||||||
OctreeServer::didPacketDistributor(this);
|
OctreeServer::didPacketDistributor(this);
|
||||||
|
|
||||||
|
@ -322,7 +323,7 @@ int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrus
|
||||||
// If we have a packet waiting, and our desired want color, doesn't match the current waiting packets color
|
// If we have a packet waiting, and our desired want color, doesn't match the current waiting packets color
|
||||||
// then let's just send that waiting packet.
|
// then let's just send that waiting packet.
|
||||||
if (nodeData->isPacketWaiting()) {
|
if (nodeData->isPacketWaiting()) {
|
||||||
packetsSentThisInterval += handlePacketSend(nodeData, trueBytesSent, truePacketsSent);
|
packetsSentThisInterval += handlePacketSend(node, nodeData, trueBytesSent, truePacketsSent);
|
||||||
} else {
|
} else {
|
||||||
nodeData->resetOctreePacket();
|
nodeData->resetOctreePacket();
|
||||||
}
|
}
|
||||||
|
@ -355,7 +356,7 @@ int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrus
|
||||||
//unsigned long encodeTime = nodeData->stats.getTotalEncodeTime();
|
//unsigned long encodeTime = nodeData->stats.getTotalEncodeTime();
|
||||||
//unsigned long elapsedTime = nodeData->stats.getElapsedTime();
|
//unsigned long elapsedTime = nodeData->stats.getElapsedTime();
|
||||||
|
|
||||||
int packetsJustSent = handlePacketSend(nodeData, trueBytesSent, truePacketsSent);
|
int packetsJustSent = handlePacketSend(node, nodeData, trueBytesSent, truePacketsSent);
|
||||||
packetsSentThisInterval += packetsJustSent;
|
packetsSentThisInterval += packetsJustSent;
|
||||||
|
|
||||||
// If we're starting a full scene, then definitely we want to empty the elementBag
|
// If we're starting a full scene, then definitely we want to empty the elementBag
|
||||||
|
@ -431,8 +432,8 @@ int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrus
|
||||||
|
|
||||||
// Our trackSend() function is implemented by the server subclass, and will be called back
|
// Our trackSend() function is implemented by the server subclass, and will be called back
|
||||||
// during the encodeTreeBitstream() as new entities/data elements are sent
|
// during the encodeTreeBitstream() as new entities/data elements are sent
|
||||||
params.trackSend = [this](const QUuid& dataID, quint64 dataEdited) {
|
params.trackSend = [this, node](const QUuid& dataID, quint64 dataEdited) {
|
||||||
_myServer->trackSend(dataID, dataEdited, _nodeUUID);
|
_myServer->trackSend(dataID, dataEdited, node->getUUID());
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: should this include the lock time or not? This stat is sent down to the client,
|
// TODO: should this include the lock time or not? This stat is sent down to the client,
|
||||||
|
@ -481,7 +482,7 @@ int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrus
|
||||||
unsigned int writtenSize = _packetData.getFinalizedSize() + sizeof(OCTREE_PACKET_INTERNAL_SECTION_SIZE);
|
unsigned int writtenSize = _packetData.getFinalizedSize() + sizeof(OCTREE_PACKET_INTERNAL_SECTION_SIZE);
|
||||||
|
|
||||||
if (writtenSize > nodeData->getAvailable()) {
|
if (writtenSize > nodeData->getAvailable()) {
|
||||||
packetsSentThisInterval += handlePacketSend(nodeData, trueBytesSent, truePacketsSent);
|
packetsSentThisInterval += handlePacketSend(node, nodeData, trueBytesSent, truePacketsSent);
|
||||||
}
|
}
|
||||||
|
|
||||||
nodeData->writeToPacket(_packetData.getFinalizedData(), _packetData.getFinalizedSize());
|
nodeData->writeToPacket(_packetData.getFinalizedData(), _packetData.getFinalizedSize());
|
||||||
|
@ -501,7 +502,7 @@ int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrus
|
||||||
int targetSize = MAX_OCTREE_PACKET_DATA_SIZE;
|
int targetSize = MAX_OCTREE_PACKET_DATA_SIZE;
|
||||||
if (sendNow) {
|
if (sendNow) {
|
||||||
quint64 packetSendingStart = usecTimestampNow();
|
quint64 packetSendingStart = usecTimestampNow();
|
||||||
packetsSentThisInterval += handlePacketSend(nodeData, trueBytesSent, truePacketsSent);
|
packetsSentThisInterval += handlePacketSend(node, nodeData, trueBytesSent, truePacketsSent);
|
||||||
quint64 packetSendingEnd = usecTimestampNow();
|
quint64 packetSendingEnd = usecTimestampNow();
|
||||||
packetSendingElapsedUsec = (float)(packetSendingEnd - packetSendingStart);
|
packetSendingElapsedUsec = (float)(packetSendingEnd - packetSendingStart);
|
||||||
|
|
||||||
|
@ -538,9 +539,9 @@ int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrus
|
||||||
// Here's where we can/should allow the server to send other data...
|
// Here's where we can/should allow the server to send other data...
|
||||||
// send the environment packet
|
// send the environment packet
|
||||||
// TODO: should we turn this into a while loop to better handle sending multiple special packets
|
// TODO: should we turn this into a while loop to better handle sending multiple special packets
|
||||||
if (_myServer->hasSpecialPacketsToSend(_node) && !nodeData->isShuttingDown()) {
|
if (_myServer->hasSpecialPacketsToSend(node) && !nodeData->isShuttingDown()) {
|
||||||
int specialPacketsSent = 0;
|
int specialPacketsSent = 0;
|
||||||
trueBytesSent += _myServer->sendSpecialPackets(_node, nodeData, specialPacketsSent);
|
trueBytesSent += _myServer->sendSpecialPackets(node, nodeData, specialPacketsSent);
|
||||||
nodeData->resetOctreePacket(); // because nodeData's _sequenceNumber has changed
|
nodeData->resetOctreePacket(); // because nodeData's _sequenceNumber has changed
|
||||||
truePacketsSent += specialPacketsSent;
|
truePacketsSent += specialPacketsSent;
|
||||||
packetsSentThisInterval += specialPacketsSent;
|
packetsSentThisInterval += specialPacketsSent;
|
||||||
|
@ -556,7 +557,7 @@ int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrus
|
||||||
while (nodeData->hasNextNackedPacket() && packetsSentThisInterval < maxPacketsPerInterval) {
|
while (nodeData->hasNextNackedPacket() && packetsSentThisInterval < maxPacketsPerInterval) {
|
||||||
const NLPacket* packet = nodeData->getNextNackedPacket();
|
const NLPacket* packet = nodeData->getNextNackedPacket();
|
||||||
if (packet) {
|
if (packet) {
|
||||||
DependencyManager::get<NodeList>()->sendUnreliablePacket(*packet, *_node);
|
DependencyManager::get<NodeList>()->sendUnreliablePacket(*packet, *node);
|
||||||
truePacketsSent++;
|
truePacketsSent++;
|
||||||
packetsSentThisInterval++;
|
packetsSentThisInterval++;
|
||||||
|
|
||||||
|
|
|
@ -18,8 +18,7 @@
|
||||||
|
|
||||||
#include <GenericThread.h>
|
#include <GenericThread.h>
|
||||||
|
|
||||||
#include "OctreeQueryNode.h"
|
class OctreeQueryNode;
|
||||||
|
|
||||||
class OctreeServer;
|
class OctreeServer;
|
||||||
|
|
||||||
using AtomicUIntStat = std::atomic<uintmax_t>;
|
using AtomicUIntStat = std::atomic<uintmax_t>;
|
||||||
|
@ -32,6 +31,9 @@ public:
|
||||||
virtual ~OctreeSendThread();
|
virtual ~OctreeSendThread();
|
||||||
|
|
||||||
void setIsShuttingDown();
|
void setIsShuttingDown();
|
||||||
|
bool isShuttingDown() { return _isShuttingDown; }
|
||||||
|
|
||||||
|
QUuid getNodeUuid() const { return _nodeUuid; }
|
||||||
|
|
||||||
static AtomicUIntStat _totalBytes;
|
static AtomicUIntStat _totalBytes;
|
||||||
static AtomicUIntStat _totalWastedBytes;
|
static AtomicUIntStat _totalWastedBytes;
|
||||||
|
@ -48,17 +50,18 @@ protected:
|
||||||
virtual bool process();
|
virtual bool process();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
OctreeServer* _myServer;
|
int handlePacketSend(SharedNodePointer node, OctreeQueryNode* nodeData, int& trueBytesSent, int& truePacketsSent);
|
||||||
SharedNodePointer _node;
|
int packetDistributor(SharedNodePointer node, OctreeQueryNode* nodeData, bool viewFrustumChanged);
|
||||||
QUuid _nodeUUID;
|
|
||||||
|
|
||||||
int handlePacketSend(OctreeQueryNode* nodeData, int& trueBytesSent, int& truePacketsSent);
|
OctreeServer* _myServer { nullptr };
|
||||||
int packetDistributor(OctreeQueryNode* nodeData, bool viewFrustumChanged);
|
QWeakPointer<Node> _node;
|
||||||
|
QUuid _nodeUuid;
|
||||||
|
|
||||||
OctreePacketData _packetData;
|
OctreePacketData _packetData;
|
||||||
|
|
||||||
int _nodeMissingCount;
|
int _nodeMissingCount { 0 };
|
||||||
bool _isShuttingDown;
|
bool _isShuttingDown { false };
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_OctreeSendThread_h
|
#endif // hifi_OctreeSendThread_h
|
||||||
|
|
|
@ -25,9 +25,9 @@
|
||||||
|
|
||||||
#include "../AssignmentClient.h"
|
#include "../AssignmentClient.h"
|
||||||
|
|
||||||
|
#include "OctreeQueryNode.h"
|
||||||
#include "OctreeServerConsts.h"
|
#include "OctreeServerConsts.h"
|
||||||
|
|
||||||
OctreeServer* OctreeServer::_instance = NULL;
|
|
||||||
int OctreeServer::_clientCount = 0;
|
int OctreeServer::_clientCount = 0;
|
||||||
const int MOVING_AVERAGE_SAMPLE_COUNTS = 1000000;
|
const int MOVING_AVERAGE_SAMPLE_COUNTS = 1000000;
|
||||||
|
|
||||||
|
@ -231,13 +231,6 @@ OctreeServer::OctreeServer(ReceivedMessage& message) :
|
||||||
_started(time(0)),
|
_started(time(0)),
|
||||||
_startedUSecs(usecTimestampNow())
|
_startedUSecs(usecTimestampNow())
|
||||||
{
|
{
|
||||||
if (_instance) {
|
|
||||||
qDebug() << "Octree Server starting... while old instance still running _instance=["<<_instance<<"] this=[" << this << "]";
|
|
||||||
}
|
|
||||||
|
|
||||||
qDebug() << "Octree Server starting... setting _instance to=[" << this << "]";
|
|
||||||
_instance = this;
|
|
||||||
|
|
||||||
_averageLoopTime.updateAverage(0);
|
_averageLoopTime.updateAverage(0);
|
||||||
qDebug() << "Octree server starting... [" << this << "]";
|
qDebug() << "Octree server starting... [" << this << "]";
|
||||||
|
|
||||||
|
@ -281,9 +274,6 @@ OctreeServer::~OctreeServer() {
|
||||||
_tree.reset();
|
_tree.reset();
|
||||||
qDebug() << qPrintable(_safeServerName) << "server DONE cleaning up octree... [" << this << "]";
|
qDebug() << qPrintable(_safeServerName) << "server DONE cleaning up octree... [" << this << "]";
|
||||||
|
|
||||||
if (_instance == this) {
|
|
||||||
_instance = NULL; // we are gone
|
|
||||||
}
|
|
||||||
qDebug() << qPrintable(_safeServerName) << "server DONE shutting down... [" << this << "]";
|
qDebug() << qPrintable(_safeServerName) << "server DONE shutting down... [" << this << "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -878,16 +868,38 @@ void OctreeServer::parsePayload() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OctreeServer::UniqueSendThread OctreeServer::createSendThread(const SharedNodePointer& node) {
|
||||||
|
auto sendThread = std::unique_ptr<OctreeSendThread>(new OctreeSendThread(this, node));
|
||||||
|
|
||||||
|
// we want to be notified when the thread finishes
|
||||||
|
connect(sendThread.get(), &GenericThread::finished, this, &OctreeServer::removeSendThread);
|
||||||
|
sendThread->initialize(true);
|
||||||
|
|
||||||
|
return sendThread;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OctreeServer::removeSendThread() {
|
||||||
|
// If the object has been deleted since the event was queued, sender() will return nullptr
|
||||||
|
if (auto sendThread = qobject_cast<OctreeSendThread*>(sender())) {
|
||||||
|
// This deletes the unique_ptr, so sendThread is destructed after that line
|
||||||
|
_sendThreads.erase(sendThread->getNodeUuid());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void OctreeServer::handleOctreeQueryPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode) {
|
void OctreeServer::handleOctreeQueryPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode) {
|
||||||
if (!_isFinished) {
|
if (!_isFinished && !_isShuttingDown) {
|
||||||
// If we got a query packet, then we're talking to an agent, and we
|
// If we got a query packet, then we're talking to an agent, and we
|
||||||
// need to make sure we have it in our nodeList.
|
// need to make sure we have it in our nodeList.
|
||||||
auto nodeList = DependencyManager::get<NodeList>();
|
auto nodeList = DependencyManager::get<NodeList>();
|
||||||
nodeList->updateNodeWithDataFromPacket(message, senderNode);
|
nodeList->updateNodeWithDataFromPacket(message, senderNode);
|
||||||
|
|
||||||
OctreeQueryNode* nodeData = dynamic_cast<OctreeQueryNode*>(senderNode->getLinkedData());
|
auto it = _sendThreads.find(senderNode->getUUID());
|
||||||
if (nodeData && !nodeData->isOctreeSendThreadInitalized()) {
|
if (it == _sendThreads.end()) {
|
||||||
nodeData->initializeOctreeSendThread(this, senderNode);
|
_sendThreads.emplace(senderNode->getUUID(), createSendThread(senderNode));
|
||||||
|
} else if (it->second->isShuttingDown()) {
|
||||||
|
_sendThreads.erase(it); // Remove right away and wait on thread to be
|
||||||
|
|
||||||
|
_sendThreads.emplace(senderNode->getUUID(), createSendThread(senderNode));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1117,8 +1129,8 @@ void OctreeServer::domainSettingsRequestComplete() {
|
||||||
setvbuf(stdout, NULL, _IOLBF, 0);
|
setvbuf(stdout, NULL, _IOLBF, 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
nodeList->linkedDataCreateCallback = [] (Node* node) {
|
nodeList->linkedDataCreateCallback = [this](Node* node) {
|
||||||
auto queryNodeData = _instance->createOctreeQueryNode();
|
auto queryNodeData = createOctreeQueryNode();
|
||||||
queryNodeData->init();
|
queryNodeData->init();
|
||||||
node->setLinkedData(std::move(queryNodeData));
|
node->setLinkedData(std::move(queryNodeData));
|
||||||
};
|
};
|
||||||
|
@ -1167,6 +1179,13 @@ void OctreeServer::nodeAdded(SharedNodePointer node) {
|
||||||
|
|
||||||
void OctreeServer::nodeKilled(SharedNodePointer node) {
|
void OctreeServer::nodeKilled(SharedNodePointer node) {
|
||||||
quint64 start = usecTimestampNow();
|
quint64 start = usecTimestampNow();
|
||||||
|
|
||||||
|
// Shutdown send thread
|
||||||
|
auto it = _sendThreads.find(node->getUUID());
|
||||||
|
if (it != _sendThreads.end()) {
|
||||||
|
auto& sendThread = *it->second;
|
||||||
|
sendThread.setIsShuttingDown();
|
||||||
|
}
|
||||||
|
|
||||||
// calling this here since nodeKilled slot in ReceivedPacketProcessor can't be triggered by signals yet!!
|
// calling this here since nodeKilled slot in ReceivedPacketProcessor can't be triggered by signals yet!!
|
||||||
_octreeInboundPacketProcessor->nodeKilled(node);
|
_octreeInboundPacketProcessor->nodeKilled(node);
|
||||||
|
@ -1188,24 +1207,6 @@ void OctreeServer::nodeKilled(SharedNodePointer node) {
|
||||||
trackViewerGone(node->getUUID());
|
trackViewerGone(node->getUUID());
|
||||||
}
|
}
|
||||||
|
|
||||||
void OctreeServer::forceNodeShutdown(SharedNodePointer node) {
|
|
||||||
quint64 start = usecTimestampNow();
|
|
||||||
|
|
||||||
qDebug() << qPrintable(_safeServerName) << "server killed node:" << *node;
|
|
||||||
OctreeQueryNode* nodeData = dynamic_cast<OctreeQueryNode*>(node->getLinkedData());
|
|
||||||
if (nodeData) {
|
|
||||||
nodeData->forceNodeShutdown(); // tell our node data and sending threads that we'd like to shut down
|
|
||||||
} else {
|
|
||||||
qDebug() << qPrintable(_safeServerName) << "server node missing linked data node:" << *node;
|
|
||||||
}
|
|
||||||
|
|
||||||
quint64 end = usecTimestampNow();
|
|
||||||
quint64 usecsElapsed = (end - start);
|
|
||||||
qDebug() << qPrintable(_safeServerName) << "server forceNodeShutdown() took: "
|
|
||||||
<< usecsElapsed << " usecs for node:" << *node;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void OctreeServer::aboutToFinish() {
|
void OctreeServer::aboutToFinish() {
|
||||||
qDebug() << qPrintable(_safeServerName) << "server STARTING about to finish...";
|
qDebug() << qPrintable(_safeServerName) << "server STARTING about to finish...";
|
||||||
|
|
||||||
|
@ -1214,9 +1215,8 @@ void OctreeServer::aboutToFinish() {
|
||||||
qDebug() << qPrintable(_safeServerName) << "inform Octree Inbound Packet Processor that we are shutting down...";
|
qDebug() << qPrintable(_safeServerName) << "inform Octree Inbound Packet Processor that we are shutting down...";
|
||||||
|
|
||||||
// we're going down - set the NodeList linkedDataCallback to NULL so we do not create any more OctreeQueryNode objects.
|
// we're going down - set the NodeList linkedDataCallback to NULL so we do not create any more OctreeQueryNode objects.
|
||||||
// This ensures that when we forceNodeShutdown below for each node we don't get any more newly connecting nodes
|
// This ensures that we don't get any more newly connecting nodes
|
||||||
auto nodeList = DependencyManager::get<NodeList>();
|
DependencyManager::get<NodeList>()->linkedDataCreateCallback = nullptr;
|
||||||
nodeList->linkedDataCreateCallback = NULL;
|
|
||||||
|
|
||||||
if (_octreeInboundPacketProcessor) {
|
if (_octreeInboundPacketProcessor) {
|
||||||
_octreeInboundPacketProcessor->terminating();
|
_octreeInboundPacketProcessor->terminating();
|
||||||
|
@ -1226,21 +1226,15 @@ void OctreeServer::aboutToFinish() {
|
||||||
_jurisdictionSender->terminating();
|
_jurisdictionSender->terminating();
|
||||||
}
|
}
|
||||||
|
|
||||||
QSet<SharedNodePointer> nodesToShutdown;
|
// Shut down all the send threads
|
||||||
|
for (auto& it : _sendThreads) {
|
||||||
// Force a shutdown of all of our OctreeSendThreads.
|
auto& sendThread = *it.second;
|
||||||
// At this point it has to be impossible for a linkedDataCreateCallback to be called for a new node
|
sendThread.setIsShuttingDown();
|
||||||
nodeList->eachNode([&nodesToShutdown](const SharedNodePointer& node) {
|
|
||||||
nodesToShutdown << node;
|
|
||||||
});
|
|
||||||
|
|
||||||
// What follows is a hack to force OctreeSendThreads to cleanup before the OctreeServer is gone.
|
|
||||||
// I would prefer to allow the SharedNodePointer ref count drop to zero to do this automatically
|
|
||||||
// but that isn't possible as long as the OctreeSendThread has an OctreeServer* that it uses.
|
|
||||||
for (auto& node : nodesToShutdown) {
|
|
||||||
qDebug() << qPrintable(_safeServerName) << "server about to finish while node still connected node:" << *node;
|
|
||||||
forceNodeShutdown(node);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Clear will destruct all the unique_ptr to OctreeSendThreads which will call the GenericThread's dtor
|
||||||
|
// which waits on the thread to be done before returning
|
||||||
|
_sendThreads.clear(); // Cleans up all the send threads.
|
||||||
|
|
||||||
if (_persistThread) {
|
if (_persistThread) {
|
||||||
_persistThread->aboutToFinish();
|
_persistThread->aboutToFinish();
|
||||||
|
@ -1459,15 +1453,22 @@ void OctreeServer::didCallWriteDatagram(OctreeSendThread* thread) {
|
||||||
|
|
||||||
|
|
||||||
void OctreeServer::stopTrackingThread(OctreeSendThread* thread) {
|
void OctreeServer::stopTrackingThread(OctreeSendThread* thread) {
|
||||||
QMutexLocker lockerA(&_threadsDidProcessMutex);
|
{
|
||||||
QMutexLocker lockerB(&_threadsDidPacketDistributorMutex);
|
QMutexLocker locker(&_threadsDidProcessMutex);
|
||||||
QMutexLocker lockerC(&_threadsDidHandlePacketSendMutex);
|
_threadsDidProcess.remove(thread);
|
||||||
QMutexLocker lockerD(&_threadsDidCallWriteDatagramMutex);
|
}
|
||||||
|
{
|
||||||
_threadsDidProcess.remove(thread);
|
QMutexLocker locker(&_threadsDidPacketDistributorMutex);
|
||||||
_threadsDidPacketDistributor.remove(thread);
|
_threadsDidPacketDistributor.remove(thread);
|
||||||
_threadsDidHandlePacketSend.remove(thread);
|
}
|
||||||
_threadsDidCallWriteDatagram.remove(thread);
|
{
|
||||||
|
QMutexLocker locker(&_threadsDidHandlePacketSendMutex);
|
||||||
|
_threadsDidHandlePacketSend.remove(thread);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
QMutexLocker locker(&_threadsDidCallWriteDatagramMutex);
|
||||||
|
_threadsDidCallWriteDatagram.remove(thread);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int howManyThreadsDidSomething(QMutex& mutex, QMap<OctreeSendThread*, quint64>& something, quint64 since) {
|
int howManyThreadsDidSomething(QMutex& mutex, QMap<OctreeSendThread*, quint64>& something, quint64 since) {
|
||||||
|
|
|
@ -124,7 +124,6 @@ public:
|
||||||
bool handleHTTPRequest(HTTPConnection* connection, const QUrl& url, bool skipSubHandler);
|
bool handleHTTPRequest(HTTPConnection* connection, const QUrl& url, bool skipSubHandler);
|
||||||
|
|
||||||
virtual void aboutToFinish();
|
virtual void aboutToFinish();
|
||||||
void forceNodeShutdown(SharedNodePointer node);
|
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
/// runs the octree server assignment
|
/// runs the octree server assignment
|
||||||
|
@ -138,8 +137,12 @@ private slots:
|
||||||
void handleOctreeQueryPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode);
|
void handleOctreeQueryPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode);
|
||||||
void handleOctreeDataNackPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode);
|
void handleOctreeDataNackPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode);
|
||||||
void handleJurisdictionRequestPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode);
|
void handleJurisdictionRequestPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode);
|
||||||
|
void removeSendThread();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
using UniqueSendThread = std::unique_ptr<OctreeSendThread>;
|
||||||
|
using SendThreads = std::unordered_map<QUuid, UniqueSendThread>;
|
||||||
|
|
||||||
virtual OctreePointer createTree() = 0;
|
virtual OctreePointer createTree() = 0;
|
||||||
bool readOptionBool(const QString& optionName, const QJsonObject& settingsSectionObject, bool& result);
|
bool readOptionBool(const QString& optionName, const QJsonObject& settingsSectionObject, bool& result);
|
||||||
bool readOptionInt(const QString& optionName, const QJsonObject& settingsSectionObject, int& result);
|
bool readOptionInt(const QString& optionName, const QJsonObject& settingsSectionObject, int& result);
|
||||||
|
@ -153,6 +156,8 @@ protected:
|
||||||
QString getFileLoadTime();
|
QString getFileLoadTime();
|
||||||
QString getConfiguration();
|
QString getConfiguration();
|
||||||
QString getStatusLink();
|
QString getStatusLink();
|
||||||
|
|
||||||
|
UniqueSendThread createSendThread(const SharedNodePointer& node);
|
||||||
|
|
||||||
int _argc;
|
int _argc;
|
||||||
const char** _argv;
|
const char** _argv;
|
||||||
|
@ -187,11 +192,11 @@ protected:
|
||||||
int _backupInterval;
|
int _backupInterval;
|
||||||
int _maxBackupVersions;
|
int _maxBackupVersions;
|
||||||
|
|
||||||
static OctreeServer* _instance;
|
|
||||||
|
|
||||||
time_t _started;
|
time_t _started;
|
||||||
quint64 _startedUSecs;
|
quint64 _startedUSecs;
|
||||||
QString _safeServerName;
|
QString _safeServerName;
|
||||||
|
|
||||||
|
SendThreads _sendThreads;
|
||||||
|
|
||||||
static int _clientCount;
|
static int _clientCount;
|
||||||
static SimpleMovingAverage _averageLoopTime;
|
static SimpleMovingAverage _averageLoopTime;
|
||||||
|
|
|
@ -1,26 +1,27 @@
|
||||||
macro(CONSOLIDATE_STACK_COMPONENTS)
|
macro(CONSOLIDATE_STACK_COMPONENTS)
|
||||||
|
|
||||||
if (DEFINED DEPLOY_PACKAGE AND DEPLOY_PACKAGE AND WIN32)
|
if (DEFINED DEPLOY_PACKAGE AND DEPLOY_PACKAGE)
|
||||||
|
if (WIN32)
|
||||||
# Copy all the output for this target into the common deployment location
|
# Copy all the output for this target into the common deployment location
|
||||||
add_custom_command(
|
|
||||||
TARGET ${TARGET_NAME} POST_BUILD
|
|
||||||
COMMAND "${CMAKE_COMMAND}" -E copy_directory $<TARGET_FILE_DIR:${TARGET_NAME}> ${CMAKE_BINARY_DIR}/full-stack-deployment
|
|
||||||
)
|
|
||||||
|
|
||||||
# Copy icon files for interface and stack manager
|
|
||||||
if (TARGET_NAME STREQUAL "interface" OR TARGET_NAME STREQUAL "stack-manager")
|
|
||||||
if (TARGET_NAME STREQUAL "interface")
|
|
||||||
set (ICON_FILE_PATH "${PROJECT_SOURCE_DIR}/icon/interface.ico")
|
|
||||||
set (ICON_DESTINATION_NAME "interface.ico")
|
|
||||||
elseif (TARGET_NAME STREQUAL "stack-manager")
|
|
||||||
set (ICON_FILE_PATH "${PROJECT_SOURCE_DIR}/assets/icon.ico")
|
|
||||||
set (ICON_DESTINATION_NAME "stack-manager.ico")
|
|
||||||
endif ()
|
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
TARGET ${TARGET_NAME} POST_BUILD
|
TARGET ${TARGET_NAME} POST_BUILD
|
||||||
COMMAND "${CMAKE_COMMAND}" -E copy ${ICON_FILE_PATH} ${CMAKE_BINARY_DIR}/full-stack-deployment/${ICON_DESTINATION_NAME}
|
COMMAND "${CMAKE_COMMAND}" -E copy_directory $<TARGET_FILE_DIR:${TARGET_NAME}> ${CMAKE_BINARY_DIR}/full-stack-deployment
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Copy icon files for interface and stack manager
|
||||||
|
if (TARGET_NAME STREQUAL "interface" OR TARGET_NAME STREQUAL "stack-manager")
|
||||||
|
if (TARGET_NAME STREQUAL "interface")
|
||||||
|
set (ICON_FILE_PATH "${PROJECT_SOURCE_DIR}/icon/interface.ico")
|
||||||
|
set (ICON_DESTINATION_NAME "interface.ico")
|
||||||
|
elseif (TARGET_NAME STREQUAL "stack-manager")
|
||||||
|
set (ICON_FILE_PATH "${PROJECT_SOURCE_DIR}/assets/icon.ico")
|
||||||
|
set (ICON_DESTINATION_NAME "stack-manager.ico")
|
||||||
|
endif ()
|
||||||
|
add_custom_command(
|
||||||
|
TARGET ${TARGET_NAME} POST_BUILD
|
||||||
|
COMMAND "${CMAKE_COMMAND}" -E copy ${ICON_FILE_PATH} ${CMAKE_BINARY_DIR}/full-stack-deployment/${ICON_DESTINATION_NAME}
|
||||||
|
)
|
||||||
|
endif ()
|
||||||
endif ()
|
endif ()
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
|
30
cmake/macros/GenerateInstallers.cmake
Normal file
30
cmake/macros/GenerateInstallers.cmake
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
#
|
||||||
|
# GenerateInstallers.cmake
|
||||||
|
# cmake/macros
|
||||||
|
#
|
||||||
|
# Created by Leonardo Murillo on 12/16/2015.
|
||||||
|
# Copyright 2015 High Fidelity, Inc.
|
||||||
|
#
|
||||||
|
# Distributed under the Apache License, Version 2.0.
|
||||||
|
# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
#
|
||||||
|
|
||||||
|
macro(GENERATE_INSTALLERS)
|
||||||
|
if (DEFINED DEPLOY_PACKAGE AND DEPLOY_PACKAGE AND WIN32)
|
||||||
|
file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/full-stack-deployment")
|
||||||
|
find_program(MAKENSIS_COMMAND makensis PATHS [HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\NSIS])
|
||||||
|
if (NOT MAKENSIS_COMMAND)
|
||||||
|
message(FATAL_ERROR "The Nullsoft Scriptable Install Systems is required for generating packaged installers on Windows (http://nsis.sourceforge.net/)")
|
||||||
|
endif ()
|
||||||
|
add_custom_target(
|
||||||
|
build-package ALL
|
||||||
|
DEPENDS interface assignment-client domain-server stack-manager
|
||||||
|
COMMAND set INSTALLER_SOURCE_DIR=${CMAKE_BINARY_DIR}/full-stack-deployment
|
||||||
|
COMMAND set INSTALLER_NAME=${CMAKE_BINARY_DIR}/${INSTALLER_NAME}
|
||||||
|
COMMAND set INSTALLER_SCRIPTS_DIR=${CMAKE_SOURCE_DIR}/examples
|
||||||
|
COMMAND set INSTALLER_COMPANY=${INSTALLER_COMPANY}
|
||||||
|
COMMAND set INSTALLER_DIRECTORY=${INSTALLER_DIRECTORY}
|
||||||
|
COMMAND CMD /C "\"${MAKENSIS_COMMAND}\" ${CMAKE_SOURCE_DIR}/tools/nsis/release.nsi"
|
||||||
|
)
|
||||||
|
endif ()
|
||||||
|
endmacro()
|
|
@ -14,13 +14,22 @@ macro(INCLUDE_APPLICATION_VERSION)
|
||||||
# We are relying on Jenkins defined environment variables to determine the origin of this build
|
# We are relying on Jenkins defined environment variables to determine the origin of this build
|
||||||
# and will only package if this is a PR or Release build
|
# and will only package if this is a PR or Release build
|
||||||
if (DEFINED ENV{JOB_ID})
|
if (DEFINED ENV{JOB_ID})
|
||||||
set (DEPLOY_PACKAGE 1)
|
set(DEPLOY_PACKAGE 1)
|
||||||
set (BUILD_SEQ $ENV{JOB_ID})
|
set(BUILD_SEQ $ENV{JOB_ID})
|
||||||
|
set(INSTALLER_COMPANY "High Fidelity")
|
||||||
|
set(INSTALLER_DIRECTORY "${INSTALLER_COMPANY}")
|
||||||
|
set(INSTALLER_NAME "interface-win64-${BUILD_SEQ}.exe")
|
||||||
elseif (DEFINED ENV{ghprbPullId})
|
elseif (DEFINED ENV{ghprbPullId})
|
||||||
set (DEPLOY_PACKAGE 1)
|
set(DEPLOY_PACKAGE 1)
|
||||||
set (BUILD_SEQ "PR-$ENV{ghprbPullId}")
|
set(BUILD_SEQ "PR-$ENV{ghprbPullId}")
|
||||||
|
set(INSTALLER_COMPANY "High Fidelity - PR")
|
||||||
|
set(INSTALLER_DIRECTORY "${INSTALLER_COMPANY}\\${BUILD_SEQ}")
|
||||||
|
set(INSTALLER_NAME "pr-interface-win64-${BUILD_SEQ}.exe")
|
||||||
else ()
|
else ()
|
||||||
set(BUILD_SEQ "dev")
|
set(BUILD_SEQ "dev")
|
||||||
|
set(INSTALLER_COMPANY "High Fidelity - Dev")
|
||||||
|
set(INSTALLER_DIRECTORY "${INSTALLER_COMPANY}")
|
||||||
|
set(INSTALLER_NAME "dev-interface-win64.exe")
|
||||||
endif ()
|
endif ()
|
||||||
configure_file("${MACRO_DIR}/ApplicationVersion.h.in" "${PROJECT_BINARY_DIR}/includes/ApplicationVersion.h")
|
configure_file("${MACRO_DIR}/ApplicationVersion.h.in" "${PROJECT_BINARY_DIR}/includes/ApplicationVersion.h")
|
||||||
include_directories("${PROJECT_BINARY_DIR}/includes")
|
include_directories("${PROJECT_BINARY_DIR}/includes")
|
||||||
|
|
|
@ -1260,15 +1260,14 @@ void Application::paintGL() {
|
||||||
hmdOffset.x = -hmdOffset.x;
|
hmdOffset.x = -hmdOffset.x;
|
||||||
|
|
||||||
_myCamera.setPosition(myAvatar->getDefaultEyePosition()
|
_myCamera.setPosition(myAvatar->getDefaultEyePosition()
|
||||||
+ glm::vec3(0, _raiseMirror * myAvatar->getAvatarScale(), 0)
|
+ glm::vec3(0, _raiseMirror * myAvatar->getUniformScale(), 0)
|
||||||
+ mirrorBodyOrientation * glm::vec3(0.0f, 0.0f, 1.0f) * MIRROR_FULLSCREEN_DISTANCE * _scaleMirror
|
+ mirrorBodyOrientation * glm::vec3(0.0f, 0.0f, 1.0f) * MIRROR_FULLSCREEN_DISTANCE * _scaleMirror
|
||||||
+ mirrorBodyOrientation * hmdOffset);
|
+ mirrorBodyOrientation * hmdOffset);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
_myCamera.setRotation(myAvatar->getWorldAlignedOrientation()
|
_myCamera.setRotation(myAvatar->getWorldAlignedOrientation()
|
||||||
* glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f)));
|
* glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f)));
|
||||||
_myCamera.setPosition(myAvatar->getDefaultEyePosition()
|
_myCamera.setPosition(myAvatar->getDefaultEyePosition()
|
||||||
+ glm::vec3(0, _raiseMirror * myAvatar->getAvatarScale(), 0)
|
+ glm::vec3(0, _raiseMirror * myAvatar->getUniformScale(), 0)
|
||||||
+ (myAvatar->getOrientation() * glm::quat(glm::vec3(0.0f, _rotateMirror, 0.0f))) *
|
+ (myAvatar->getOrientation() * glm::quat(glm::vec3(0.0f, _rotateMirror, 0.0f))) *
|
||||||
glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_FULLSCREEN_DISTANCE * _scaleMirror);
|
glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_FULLSCREEN_DISTANCE * _scaleMirror);
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,7 +99,8 @@ Avatar::Avatar(RigPointer rig) :
|
||||||
// we may have been created in the network thread, but we live in the main thread
|
// we may have been created in the network thread, but we live in the main thread
|
||||||
moveToThread(qApp->thread());
|
moveToThread(qApp->thread());
|
||||||
|
|
||||||
setAvatarScale(1.0f);
|
setScale(glm::vec3(1.0f)); // avatar scale is uniform
|
||||||
|
|
||||||
// give the pointer to our head to inherited _headData variable from AvatarData
|
// give the pointer to our head to inherited _headData variable from AvatarData
|
||||||
_headData = static_cast<HeadData*>(new Head(this));
|
_headData = static_cast<HeadData*>(new Head(this));
|
||||||
_handData = static_cast<HandData*>(new Hand(this));
|
_handData = static_cast<HandData*>(new Hand(this));
|
||||||
|
@ -143,15 +144,35 @@ AABox Avatar::getBounds() const {
|
||||||
|
|
||||||
float Avatar::getLODDistance() const {
|
float Avatar::getLODDistance() const {
|
||||||
return DependencyManager::get<LODManager>()->getAvatarLODDistanceMultiplier() *
|
return DependencyManager::get<LODManager>()->getAvatarLODDistanceMultiplier() *
|
||||||
glm::distance(qApp->getCamera()->getPosition(), getPosition()) / getAvatarScale();
|
glm::distance(qApp->getCamera()->getPosition(), getPosition()) / getUniformScale();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Avatar::animateScaleChanges(float deltaTime) {
|
||||||
|
float currentScale = getUniformScale();
|
||||||
|
if (currentScale != _targetScale) {
|
||||||
|
// use exponential decay toward _targetScale
|
||||||
|
const float SCALE_ANIMATION_TIMESCALE = 0.5f;
|
||||||
|
float blendFactor = glm::clamp(deltaTime / SCALE_ANIMATION_TIMESCALE, 0.0f, 1.0f);
|
||||||
|
float animatedScale = (1.0f - blendFactor) * currentScale + blendFactor * _targetScale;
|
||||||
|
|
||||||
|
// snap to the end when we get close enough
|
||||||
|
const float MIN_RELATIVE_SCALE_ERROR = 0.03f;
|
||||||
|
if (fabsf(_targetScale - currentScale) / _targetScale < 0.03f) {
|
||||||
|
animatedScale = _targetScale;
|
||||||
|
}
|
||||||
|
|
||||||
|
setScale(glm::vec3(animatedScale)); // avatar scale is uniform
|
||||||
|
rebuildCollisionShape();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Avatar::simulate(float deltaTime) {
|
void Avatar::simulate(float deltaTime) {
|
||||||
PerformanceTimer perfTimer("simulate");
|
PerformanceTimer perfTimer("simulate");
|
||||||
|
|
||||||
if (getAvatarScale() != _targetScale) {
|
if (!isDead() && !_motionState) {
|
||||||
setAvatarScale(_targetScale);
|
DependencyManager::get<AvatarManager>()->addAvatarToSimulation(this);
|
||||||
}
|
}
|
||||||
|
animateScaleChanges(deltaTime);
|
||||||
|
|
||||||
// update the billboard render flag
|
// update the billboard render flag
|
||||||
const float BILLBOARD_HYSTERESIS_PROPORTION = 0.1f;
|
const float BILLBOARD_HYSTERESIS_PROPORTION = 0.1f;
|
||||||
|
@ -164,7 +185,7 @@ void Avatar::simulate(float deltaTime) {
|
||||||
_shouldRenderBillboard = true;
|
_shouldRenderBillboard = true;
|
||||||
qCDebug(interfaceapp) << "Billboarding" << (isMyAvatar() ? "myself" : getSessionUUID()) << "for LOD" << getLODDistance();
|
qCDebug(interfaceapp) << "Billboarding" << (isMyAvatar() ? "myself" : getSessionUUID()) << "for LOD" << getLODDistance();
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool isControllerLogging = DependencyManager::get<AvatarManager>()->getRenderDistanceControllerIsLogging();
|
const bool isControllerLogging = DependencyManager::get<AvatarManager>()->getRenderDistanceControllerIsLogging();
|
||||||
float renderDistance = DependencyManager::get<AvatarManager>()->getRenderDistance();
|
float renderDistance = DependencyManager::get<AvatarManager>()->getRenderDistance();
|
||||||
const float SKIP_HYSTERESIS_PROPORTION = isControllerLogging ? 0.0f : BILLBOARD_HYSTERESIS_PROPORTION;
|
const float SKIP_HYSTERESIS_PROPORTION = isControllerLogging ? 0.0f : BILLBOARD_HYSTERESIS_PROPORTION;
|
||||||
|
@ -210,7 +231,7 @@ void Avatar::simulate(float deltaTime) {
|
||||||
_skeletonModel.getHeadPosition(headPosition);
|
_skeletonModel.getHeadPosition(headPosition);
|
||||||
Head* head = getHead();
|
Head* head = getHead();
|
||||||
head->setPosition(headPosition);
|
head->setPosition(headPosition);
|
||||||
head->setScale(getAvatarScale());
|
head->setScale(getUniformScale());
|
||||||
head->simulate(deltaTime, false, _shouldRenderBillboard);
|
head->simulate(deltaTime, false, _shouldRenderBillboard);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -238,12 +259,12 @@ void Avatar::simulate(float deltaTime) {
|
||||||
measureMotionDerivatives(deltaTime);
|
measureMotionDerivatives(deltaTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Avatar::isLookingAtMe(AvatarSharedPointer avatar) {
|
bool Avatar::isLookingAtMe(AvatarSharedPointer avatar) const {
|
||||||
const float HEAD_SPHERE_RADIUS = 0.1f;
|
const float HEAD_SPHERE_RADIUS = 0.1f;
|
||||||
glm::vec3 theirLookAt = dynamic_pointer_cast<Avatar>(avatar)->getHead()->getLookAtPosition();
|
glm::vec3 theirLookAt = dynamic_pointer_cast<Avatar>(avatar)->getHead()->getLookAtPosition();
|
||||||
glm::vec3 myEyePosition = getHead()->getEyePosition();
|
glm::vec3 myEyePosition = getHead()->getEyePosition();
|
||||||
|
|
||||||
return glm::distance(theirLookAt, myEyePosition) <= (HEAD_SPHERE_RADIUS * getAvatarScale());
|
return glm::distance(theirLookAt, myEyePosition) <= (HEAD_SPHERE_RADIUS * getUniformScale());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Avatar::slamPosition(const glm::vec3& newPosition) {
|
void Avatar::slamPosition(const glm::vec3& newPosition) {
|
||||||
|
@ -423,7 +444,7 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) {
|
||||||
const float BASE_LIGHT_DISTANCE = 2.0f;
|
const float BASE_LIGHT_DISTANCE = 2.0f;
|
||||||
const float LIGHT_EXPONENT = 1.0f;
|
const float LIGHT_EXPONENT = 1.0f;
|
||||||
const float LIGHT_CUTOFF = glm::radians(80.0f);
|
const float LIGHT_CUTOFF = glm::radians(80.0f);
|
||||||
float distance = BASE_LIGHT_DISTANCE * getAvatarScale();
|
float distance = BASE_LIGHT_DISTANCE * getUniformScale();
|
||||||
glm::vec3 position = glm::mix(_skeletonModel.getTranslation(), getHead()->getFaceModel().getTranslation(), 0.9f);
|
glm::vec3 position = glm::mix(_skeletonModel.getTranslation(), getHead()->getFaceModel().getTranslation(), 0.9f);
|
||||||
glm::quat orientation = getOrientation();
|
glm::quat orientation = getOrientation();
|
||||||
foreach (const AvatarManager::LocalLight& light, DependencyManager::get<AvatarManager>()->getLocalLights()) {
|
foreach (const AvatarManager::LocalLight& light, DependencyManager::get<AvatarManager>()->getLocalLights()) {
|
||||||
|
@ -436,7 +457,8 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) {
|
||||||
bool renderBounding = Menu::getInstance()->isOptionChecked(MenuOption::RenderBoundingCollisionShapes);
|
bool renderBounding = Menu::getInstance()->isOptionChecked(MenuOption::RenderBoundingCollisionShapes);
|
||||||
if (renderBounding && shouldRenderHead(renderArgs) && _skeletonModel.isRenderable()) {
|
if (renderBounding && shouldRenderHead(renderArgs) && _skeletonModel.isRenderable()) {
|
||||||
PROFILE_RANGE_BATCH(batch, __FUNCTION__":skeletonBoundingCollisionShapes");
|
PROFILE_RANGE_BATCH(batch, __FUNCTION__":skeletonBoundingCollisionShapes");
|
||||||
_skeletonModel.renderBoundingCollisionShapes(*renderArgs->_batch, 0.7f);
|
const float BOUNDING_SHAPE_ALPHA = 0.7f;
|
||||||
|
_skeletonModel.renderBoundingCollisionShapes(*renderArgs->_batch, getUniformScale(), BOUNDING_SHAPE_ALPHA);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this is the avatar being looked at, render a little ball above their head
|
// If this is the avatar being looked at, render a little ball above their head
|
||||||
|
@ -479,7 +501,7 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) {
|
||||||
}
|
}
|
||||||
|
|
||||||
DependencyManager::get<DeferredLightingEffect>()->renderSolidSphereInstance(batch,
|
DependencyManager::get<DeferredLightingEffect>()->renderSolidSphereInstance(batch,
|
||||||
Transform(transform).postScale(eyeDiameter * getAvatarScale() / 2.0f + RADIUS_INCREMENT),
|
Transform(transform).postScale(eyeDiameter * getUniformScale() / 2.0f + RADIUS_INCREMENT),
|
||||||
glm::vec4(LOOKING_AT_ME_COLOR, alpha));
|
glm::vec4(LOOKING_AT_ME_COLOR, alpha));
|
||||||
|
|
||||||
position = getHead()->getRightEyePosition();
|
position = getHead()->getRightEyePosition();
|
||||||
|
@ -489,7 +511,7 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) {
|
||||||
eyeDiameter = DEFAULT_EYE_DIAMETER;
|
eyeDiameter = DEFAULT_EYE_DIAMETER;
|
||||||
}
|
}
|
||||||
DependencyManager::get<DeferredLightingEffect>()->renderSolidSphereInstance(batch,
|
DependencyManager::get<DeferredLightingEffect>()->renderSolidSphereInstance(batch,
|
||||||
Transform(transform).postScale(eyeDiameter * getAvatarScale() / 2.0f + RADIUS_INCREMENT),
|
Transform(transform).postScale(eyeDiameter * getUniformScale() / 2.0f + RADIUS_INCREMENT),
|
||||||
glm::vec4(LOOKING_AT_ME_COLOR, alpha));
|
glm::vec4(LOOKING_AT_ME_COLOR, alpha));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -590,9 +612,9 @@ void Avatar::simulateAttachments(float deltaTime) {
|
||||||
glm::quat jointRotation;
|
glm::quat jointRotation;
|
||||||
if (_skeletonModel.getJointPositionInWorldFrame(jointIndex, jointPosition) &&
|
if (_skeletonModel.getJointPositionInWorldFrame(jointIndex, jointPosition) &&
|
||||||
_skeletonModel.getJointRotationInWorldFrame(jointIndex, jointRotation)) {
|
_skeletonModel.getJointRotationInWorldFrame(jointIndex, jointRotation)) {
|
||||||
model->setTranslation(jointPosition + jointRotation * attachment.translation * getAvatarScale());
|
model->setTranslation(jointPosition + jointRotation * attachment.translation * getUniformScale());
|
||||||
model->setRotation(jointRotation * attachment.rotation);
|
model->setRotation(jointRotation * attachment.rotation);
|
||||||
model->setScaleToFit(true, getAvatarScale() * attachment.scale, true); // hack to force rescale
|
model->setScaleToFit(true, getUniformScale() * attachment.scale, true); // hack to force rescale
|
||||||
model->setSnapModelToCenter(false); // hack to force resnap
|
model->setSnapModelToCenter(false); // hack to force resnap
|
||||||
model->setSnapModelToCenter(true);
|
model->setSnapModelToCenter(true);
|
||||||
model->simulate(deltaTime);
|
model->simulate(deltaTime);
|
||||||
|
@ -647,7 +669,7 @@ void Avatar::renderBillboard(RenderArgs* renderArgs) {
|
||||||
}
|
}
|
||||||
|
|
||||||
float Avatar::getBillboardSize() const {
|
float Avatar::getBillboardSize() const {
|
||||||
return getAvatarScale() * BILLBOARD_DISTANCE * glm::tan(glm::radians(BILLBOARD_FIELD_OF_VIEW / 2.0f));
|
return getUniformScale() * BILLBOARD_DISTANCE * glm::tan(glm::radians(BILLBOARD_FIELD_OF_VIEW / 2.0f));
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
@ -796,7 +818,7 @@ void Avatar::renderDisplayName(gpu::Batch& batch, const ViewFrustum& frustum, co
|
||||||
}
|
}
|
||||||
|
|
||||||
void Avatar::setSkeletonOffset(const glm::vec3& offset) {
|
void Avatar::setSkeletonOffset(const glm::vec3& offset) {
|
||||||
const float MAX_OFFSET_LENGTH = getAvatarScale() * 0.5f;
|
const float MAX_OFFSET_LENGTH = getUniformScale() * 0.5f;
|
||||||
float offsetLength = glm::length(offset);
|
float offsetLength = glm::length(offset);
|
||||||
if (offsetLength > MAX_OFFSET_LENGTH) {
|
if (offsetLength > MAX_OFFSET_LENGTH) {
|
||||||
_skeletonOffset = (MAX_OFFSET_LENGTH / offsetLength) * offset;
|
_skeletonOffset = (MAX_OFFSET_LENGTH / offsetLength) * offset;
|
||||||
|
@ -905,7 +927,7 @@ glm::vec3 Avatar::getJointPosition(const QString& name) const {
|
||||||
|
|
||||||
void Avatar::scaleVectorRelativeToPosition(glm::vec3 &positionToScale) const {
|
void Avatar::scaleVectorRelativeToPosition(glm::vec3 &positionToScale) const {
|
||||||
//Scale a world space vector as if it was relative to the position
|
//Scale a world space vector as if it was relative to the position
|
||||||
positionToScale = getPosition() + getAvatarScale() * (positionToScale - getPosition());
|
positionToScale = getPosition() + getUniformScale() * (positionToScale - getPosition());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Avatar::setFaceModelURL(const QUrl& faceModelURL) {
|
void Avatar::setFaceModelURL(const QUrl& faceModelURL) {
|
||||||
|
@ -945,7 +967,7 @@ void Avatar::setAttachmentData(const QVector<AttachmentData>& attachmentData) {
|
||||||
for (int i = 0; i < attachmentData.size(); i++) {
|
for (int i = 0; i < attachmentData.size(); i++) {
|
||||||
_attachmentModels[i]->setURL(attachmentData.at(i).modelURL);
|
_attachmentModels[i]->setURL(attachmentData.at(i).modelURL);
|
||||||
_attachmentModels[i]->setSnapModelToCenter(true);
|
_attachmentModels[i]->setSnapModelToCenter(true);
|
||||||
_attachmentModels[i]->setScaleToFit(true, getAvatarScale() * _attachmentData.at(i).scale);
|
_attachmentModels[i]->setScaleToFit(true, getUniformScale() * _attachmentData.at(i).scale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1033,15 +1055,6 @@ void Avatar::renderJointConnectingCone(gpu::Batch& batch, glm::vec3 position1, g
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Avatar::setAvatarScale(float scale) {
|
|
||||||
if (_targetScale * (1.0f - RESCALING_TOLERANCE) < scale &&
|
|
||||||
scale < _targetScale * (1.0f + RESCALING_TOLERANCE)) {
|
|
||||||
setScale(glm::vec3(_targetScale));
|
|
||||||
} else {
|
|
||||||
setScale(glm::vec3(scale));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
float Avatar::getSkeletonHeight() const {
|
float Avatar::getSkeletonHeight() const {
|
||||||
Extents extents = _skeletonModel.getBindExtents();
|
Extents extents = _skeletonModel.getBindExtents();
|
||||||
return extents.maximum.y - extents.minimum.y;
|
return extents.maximum.y - extents.minimum.y;
|
||||||
|
@ -1053,7 +1066,7 @@ float Avatar::getHeadHeight() const {
|
||||||
|
|
||||||
// HACK: We have a really odd case when fading out for some models where this value explodes
|
// HACK: We have a really odd case when fading out for some models where this value explodes
|
||||||
float result = extents.maximum.y - extents.minimum.y;
|
float result = extents.maximum.y - extents.minimum.y;
|
||||||
if (result >= 0.0f && result < 100.0f * getAvatarScale() ) {
|
if (result >= 0.0f && result < 100.0f * getUniformScale() ) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1096,13 +1109,21 @@ void Avatar::setShowDisplayName(bool showDisplayName) {
|
||||||
|
|
||||||
// virtual
|
// virtual
|
||||||
void Avatar::computeShapeInfo(ShapeInfo& shapeInfo) {
|
void Avatar::computeShapeInfo(ShapeInfo& shapeInfo) {
|
||||||
shapeInfo.setCapsuleY(_skeletonModel.getBoundingCapsuleRadius(), 0.5f * _skeletonModel.getBoundingCapsuleHeight());
|
float uniformScale = getUniformScale();
|
||||||
shapeInfo.setOffset(_skeletonModel.getBoundingCapsuleOffset());
|
shapeInfo.setCapsuleY(uniformScale * _skeletonModel.getBoundingCapsuleRadius(),
|
||||||
|
0.5f * uniformScale * _skeletonModel.getBoundingCapsuleHeight());
|
||||||
|
shapeInfo.setOffset(uniformScale * _skeletonModel.getBoundingCapsuleOffset());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Avatar::setMotionState(AvatarMotionState* motionState) {
|
||||||
|
_motionState = motionState;
|
||||||
}
|
}
|
||||||
|
|
||||||
// virtual
|
// virtual
|
||||||
void Avatar::rebuildSkeletonBody() {
|
void Avatar::rebuildCollisionShape() {
|
||||||
DependencyManager::get<AvatarManager>()->updateAvatarPhysicsShape(this);
|
if (_motionState) {
|
||||||
|
_motionState->addDirtyFlags(Simulation::DIRTY_SHAPE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::vec3 Avatar::getLeftPalmPosition() {
|
glm::vec3 Avatar::getLeftPalmPosition() {
|
||||||
|
|
|
@ -36,7 +36,6 @@ namespace render {
|
||||||
|
|
||||||
static const float SCALING_RATIO = .05f;
|
static const float SCALING_RATIO = .05f;
|
||||||
static const float SMOOTHING_RATIO = .05f; // 0 < ratio < 1
|
static const float SMOOTHING_RATIO = .05f; // 0 < ratio < 1
|
||||||
static const float RESCALING_TOLERANCE = .02f;
|
|
||||||
|
|
||||||
static const float BILLBOARD_FIELD_OF_VIEW = 30.0f; // degrees
|
static const float BILLBOARD_FIELD_OF_VIEW = 30.0f; // degrees
|
||||||
static const float BILLBOARD_DISTANCE = 5.56f; // meters
|
static const float BILLBOARD_DISTANCE = 5.56f; // meters
|
||||||
|
@ -89,7 +88,7 @@ public:
|
||||||
SkeletonModel& getSkeletonModel() { return _skeletonModel; }
|
SkeletonModel& getSkeletonModel() { return _skeletonModel; }
|
||||||
const SkeletonModel& getSkeletonModel() const { return _skeletonModel; }
|
const SkeletonModel& getSkeletonModel() const { return _skeletonModel; }
|
||||||
glm::vec3 getChestPosition() const;
|
glm::vec3 getChestPosition() const;
|
||||||
float getAvatarScale() const { return getScale().y; }
|
float getUniformScale() const { return getScale().y; }
|
||||||
const Head* getHead() const { return static_cast<const Head*>(_headData); }
|
const Head* getHead() const { return static_cast<const Head*>(_headData); }
|
||||||
Head* getHead() { return static_cast<Head*>(_headData); }
|
Head* getHead() { return static_cast<Head*>(_headData); }
|
||||||
Hand* getHand() { return static_cast<Hand*>(_handData); }
|
Hand* getHand() { return static_cast<Hand*>(_handData); }
|
||||||
|
@ -154,11 +153,10 @@ public:
|
||||||
// (otherwise floating point error will cause problems at large positions).
|
// (otherwise floating point error will cause problems at large positions).
|
||||||
void applyPositionDelta(const glm::vec3& delta);
|
void applyPositionDelta(const glm::vec3& delta);
|
||||||
|
|
||||||
virtual void rebuildSkeletonBody();
|
virtual void rebuildCollisionShape();
|
||||||
|
|
||||||
virtual void computeShapeInfo(ShapeInfo& shapeInfo);
|
virtual void computeShapeInfo(ShapeInfo& shapeInfo);
|
||||||
|
|
||||||
void setMotionState(AvatarMotionState* motionState) { _motionState = motionState; }
|
|
||||||
AvatarMotionState* getMotionState() { return _motionState; }
|
AvatarMotionState* getMotionState() { return _motionState; }
|
||||||
|
|
||||||
virtual void setPosition(const glm::vec3& position) override;
|
virtual void setPosition(const glm::vec3& position) override;
|
||||||
|
@ -173,6 +171,10 @@ public slots:
|
||||||
glm::quat getRightPalmRotation();
|
glm::quat getRightPalmRotation();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
friend class AvatarManager;
|
||||||
|
|
||||||
|
void setMotionState(AvatarMotionState* motionState);
|
||||||
|
|
||||||
SkeletonModel _skeletonModel;
|
SkeletonModel _skeletonModel;
|
||||||
glm::vec3 _skeletonOffset;
|
glm::vec3 _skeletonOffset;
|
||||||
QVector<Model*> _attachmentModels;
|
QVector<Model*> _attachmentModels;
|
||||||
|
@ -199,14 +201,15 @@ protected:
|
||||||
float _stringLength;
|
float _stringLength;
|
||||||
bool _moving; ///< set when position is changing
|
bool _moving; ///< set when position is changing
|
||||||
|
|
||||||
bool isLookingAtMe(AvatarSharedPointer avatar);
|
|
||||||
|
|
||||||
// protected methods...
|
// protected methods...
|
||||||
|
bool isLookingAtMe(AvatarSharedPointer avatar) const;
|
||||||
|
|
||||||
|
virtual void animateScaleChanges(float deltaTime);
|
||||||
|
|
||||||
glm::vec3 getBodyRightDirection() const { return getOrientation() * IDENTITY_RIGHT; }
|
glm::vec3 getBodyRightDirection() const { return getOrientation() * IDENTITY_RIGHT; }
|
||||||
glm::vec3 getBodyUpDirection() const { return getOrientation() * IDENTITY_UP; }
|
glm::vec3 getBodyUpDirection() const { return getOrientation() * IDENTITY_UP; }
|
||||||
glm::vec3 getBodyFrontDirection() const { return getOrientation() * IDENTITY_FRONT; }
|
glm::vec3 getBodyFrontDirection() const { return getOrientation() * IDENTITY_FRONT; }
|
||||||
glm::quat computeRotationFromBodyToWorldUp(float proportion = 1.0f) const;
|
glm::quat computeRotationFromBodyToWorldUp(float proportion = 1.0f) const;
|
||||||
void setAvatarScale(float scale);
|
|
||||||
void measureMotionDerivatives(float deltaTime);
|
void measureMotionDerivatives(float deltaTime);
|
||||||
|
|
||||||
float getSkeletonHeight() const;
|
float getSkeletonHeight() const;
|
||||||
|
|
|
@ -203,7 +203,7 @@ void AvatarManager::simulateAvatarFades(float deltaTime) {
|
||||||
while (fadingIterator != _avatarFades.end()) {
|
while (fadingIterator != _avatarFades.end()) {
|
||||||
auto avatar = std::static_pointer_cast<Avatar>(*fadingIterator);
|
auto avatar = std::static_pointer_cast<Avatar>(*fadingIterator);
|
||||||
avatar->startUpdate();
|
avatar->startUpdate();
|
||||||
avatar->setTargetScale(avatar->getAvatarScale() * SHRINK_RATE);
|
avatar->setTargetScale(avatar->getUniformScale() * SHRINK_RATE);
|
||||||
if (avatar->getTargetScale() <= MIN_FADE_SCALE) {
|
if (avatar->getTargetScale() <= MIN_FADE_SCALE) {
|
||||||
avatar->removeFromScene(*fadingIterator, scene, pendingChanges);
|
avatar->removeFromScene(*fadingIterator, scene, pendingChanges);
|
||||||
fadingIterator = _avatarFades.erase(fadingIterator);
|
fadingIterator = _avatarFades.erase(fadingIterator);
|
||||||
|
@ -223,14 +223,14 @@ AvatarSharedPointer AvatarManager::newSharedAvatar() {
|
||||||
AvatarSharedPointer AvatarManager::addAvatar(const QUuid& sessionUUID, const QWeakPointer<Node>& mixerWeakPointer) {
|
AvatarSharedPointer AvatarManager::addAvatar(const QUuid& sessionUUID, const QWeakPointer<Node>& mixerWeakPointer) {
|
||||||
auto newAvatar = AvatarHashMap::addAvatar(sessionUUID, mixerWeakPointer);
|
auto newAvatar = AvatarHashMap::addAvatar(sessionUUID, mixerWeakPointer);
|
||||||
auto rawRenderableAvatar = std::static_pointer_cast<Avatar>(newAvatar);
|
auto rawRenderableAvatar = std::static_pointer_cast<Avatar>(newAvatar);
|
||||||
|
|
||||||
render::ScenePointer scene = qApp->getMain3DScene();
|
render::ScenePointer scene = qApp->getMain3DScene();
|
||||||
render::PendingChanges pendingChanges;
|
render::PendingChanges pendingChanges;
|
||||||
if (DependencyManager::get<SceneScriptingInterface>()->shouldRenderAvatars()) {
|
if (DependencyManager::get<SceneScriptingInterface>()->shouldRenderAvatars()) {
|
||||||
rawRenderableAvatar->addToScene(rawRenderableAvatar, scene, pendingChanges);
|
rawRenderableAvatar->addToScene(rawRenderableAvatar, scene, pendingChanges);
|
||||||
}
|
}
|
||||||
scene->enqueuePendingChanges(pendingChanges);
|
scene->enqueuePendingChanges(pendingChanges);
|
||||||
|
|
||||||
return newAvatar;
|
return newAvatar;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -251,7 +251,7 @@ void AvatarManager::removeAvatarMotionState(AvatarSharedPointer avatar) {
|
||||||
// virtual
|
// virtual
|
||||||
void AvatarManager::removeAvatar(const QUuid& sessionUUID) {
|
void AvatarManager::removeAvatar(const QUuid& sessionUUID) {
|
||||||
QWriteLocker locker(&_hashLock);
|
QWriteLocker locker(&_hashLock);
|
||||||
|
|
||||||
auto removedAvatar = _avatarHash.take(sessionUUID);
|
auto removedAvatar = _avatarHash.take(sessionUUID);
|
||||||
if (removedAvatar) {
|
if (removedAvatar) {
|
||||||
handleRemovedAvatar(removedAvatar);
|
handleRemovedAvatar(removedAvatar);
|
||||||
|
@ -260,7 +260,8 @@ void AvatarManager::removeAvatar(const QUuid& sessionUUID) {
|
||||||
|
|
||||||
void AvatarManager::handleRemovedAvatar(const AvatarSharedPointer& removedAvatar) {
|
void AvatarManager::handleRemovedAvatar(const AvatarSharedPointer& removedAvatar) {
|
||||||
AvatarHashMap::handleRemovedAvatar(removedAvatar);
|
AvatarHashMap::handleRemovedAvatar(removedAvatar);
|
||||||
|
|
||||||
|
removedAvatar->die();
|
||||||
removeAvatarMotionState(removedAvatar);
|
removeAvatarMotionState(removedAvatar);
|
||||||
_avatarFades.push_back(removedAvatar);
|
_avatarFades.push_back(removedAvatar);
|
||||||
}
|
}
|
||||||
|
@ -268,7 +269,7 @@ void AvatarManager::handleRemovedAvatar(const AvatarSharedPointer& removedAvatar
|
||||||
void AvatarManager::clearOtherAvatars() {
|
void AvatarManager::clearOtherAvatars() {
|
||||||
// clear any avatars that came from an avatar-mixer
|
// clear any avatars that came from an avatar-mixer
|
||||||
QWriteLocker locker(&_hashLock);
|
QWriteLocker locker(&_hashLock);
|
||||||
|
|
||||||
AvatarHash::iterator avatarIterator = _avatarHash.begin();
|
AvatarHash::iterator avatarIterator = _avatarHash.begin();
|
||||||
while (avatarIterator != _avatarHash.end()) {
|
while (avatarIterator != _avatarHash.end()) {
|
||||||
auto avatar = std::static_pointer_cast<Avatar>(avatarIterator.value());
|
auto avatar = std::static_pointer_cast<Avatar>(avatarIterator.value());
|
||||||
|
@ -278,7 +279,7 @@ void AvatarManager::clearOtherAvatars() {
|
||||||
} else {
|
} else {
|
||||||
auto removedAvatar = avatarIterator.value();
|
auto removedAvatar = avatarIterator.value();
|
||||||
avatarIterator = _avatarHash.erase(avatarIterator);
|
avatarIterator = _avatarHash.erase(avatarIterator);
|
||||||
|
|
||||||
handleRemovedAvatar(removedAvatar);
|
handleRemovedAvatar(removedAvatar);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -374,20 +375,18 @@ void AvatarManager::handleCollisionEvents(const CollisionEvents& collisionEvents
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AvatarManager::updateAvatarPhysicsShape(Avatar* avatar) {
|
void AvatarManager::addAvatarToSimulation(Avatar* avatar) {
|
||||||
AvatarMotionState* motionState = avatar->getMotionState();
|
assert(!avatar->getMotionState());
|
||||||
if (motionState) {
|
|
||||||
motionState->addDirtyFlags(Simulation::DIRTY_SHAPE);
|
ShapeInfo shapeInfo;
|
||||||
} else {
|
avatar->computeShapeInfo(shapeInfo);
|
||||||
ShapeInfo shapeInfo;
|
btCollisionShape* shape = ObjectMotionState::getShapeManager()->getShape(shapeInfo);
|
||||||
avatar->computeShapeInfo(shapeInfo);
|
if (shape) {
|
||||||
btCollisionShape* shape = ObjectMotionState::getShapeManager()->getShape(shapeInfo);
|
// we don't add to the simulation now, we put it on a list to be added later
|
||||||
if (shape) {
|
AvatarMotionState* motionState = new AvatarMotionState(avatar, shape);
|
||||||
AvatarMotionState* motionState = new AvatarMotionState(avatar, shape);
|
avatar->setMotionState(motionState);
|
||||||
avatar->setMotionState(motionState);
|
_motionStatesToAdd.insert(motionState);
|
||||||
_motionStatesToAdd.insert(motionState);
|
_avatarMotionStates.insert(motionState);
|
||||||
_avatarMotionStates.insert(motionState);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -416,6 +415,6 @@ AvatarSharedPointer AvatarManager::getAvatarBySessionID(const QUuid& sessionID)
|
||||||
if (sessionID == _myAvatar->getSessionUUID()) {
|
if (sessionID == _myAvatar->getSessionUUID()) {
|
||||||
return _myAvatar;
|
return _myAvatar;
|
||||||
}
|
}
|
||||||
|
|
||||||
return findAvatar(sessionID);
|
return findAvatar(sessionID);
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,7 @@ public:
|
||||||
glm::vec3 color;
|
glm::vec3 color;
|
||||||
glm::vec3 direction;
|
glm::vec3 direction;
|
||||||
};
|
};
|
||||||
|
|
||||||
Q_INVOKABLE void setLocalLights(const QVector<AvatarManager::LocalLight>& localLights);
|
Q_INVOKABLE void setLocalLights(const QVector<AvatarManager::LocalLight>& localLights);
|
||||||
Q_INVOKABLE QVector<AvatarManager::LocalLight> getLocalLights() const;
|
Q_INVOKABLE QVector<AvatarManager::LocalLight> getLocalLights() const;
|
||||||
// Currently, your own avatar will be included as the null avatar id.
|
// Currently, your own avatar will be included as the null avatar id.
|
||||||
|
@ -66,8 +66,8 @@ public:
|
||||||
void handleOutgoingChanges(const VectorOfMotionStates& motionStates);
|
void handleOutgoingChanges(const VectorOfMotionStates& motionStates);
|
||||||
void handleCollisionEvents(const CollisionEvents& collisionEvents);
|
void handleCollisionEvents(const CollisionEvents& collisionEvents);
|
||||||
|
|
||||||
void updateAvatarPhysicsShape(Avatar* avatar);
|
void addAvatarToSimulation(Avatar* avatar);
|
||||||
|
|
||||||
// Expose results and parameter-tuning operations to other systems, such as stats and javascript.
|
// Expose results and parameter-tuning operations to other systems, such as stats and javascript.
|
||||||
Q_INVOKABLE float getRenderDistance() { return _renderDistance; }
|
Q_INVOKABLE float getRenderDistance() { return _renderDistance; }
|
||||||
Q_INVOKABLE float getRenderDistanceInverseLowLimit() { return _renderDistanceController.getControlledValueLowLimit(); }
|
Q_INVOKABLE float getRenderDistanceInverseLowLimit() { return _renderDistanceController.getControlledValueLowLimit(); }
|
||||||
|
@ -80,7 +80,7 @@ public:
|
||||||
Q_INVOKABLE void setRenderDistanceKD(float newValue) { _renderDistanceController.setKD(newValue); }
|
Q_INVOKABLE void setRenderDistanceKD(float newValue) { _renderDistanceController.setKD(newValue); }
|
||||||
Q_INVOKABLE void setRenderDistanceInverseLowLimit(float newValue) { _renderDistanceController.setControlledValueLowLimit(newValue); }
|
Q_INVOKABLE void setRenderDistanceInverseLowLimit(float newValue) { _renderDistanceController.setControlledValueLowLimit(newValue); }
|
||||||
Q_INVOKABLE void setRenderDistanceInverseHighLimit(float newValue);
|
Q_INVOKABLE void setRenderDistanceInverseHighLimit(float newValue);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void setShouldShowReceiveStats(bool shouldShowReceiveStats) { _shouldShowReceiveStats = shouldShowReceiveStats; }
|
void setShouldShowReceiveStats(bool shouldShowReceiveStats) { _shouldShowReceiveStats = shouldShowReceiveStats; }
|
||||||
void updateAvatarRenderStatus(bool shouldRenderAvatars);
|
void updateAvatarRenderStatus(bool shouldRenderAvatars);
|
||||||
|
@ -90,19 +90,19 @@ private:
|
||||||
AvatarManager(const AvatarManager& other);
|
AvatarManager(const AvatarManager& other);
|
||||||
|
|
||||||
void simulateAvatarFades(float deltaTime);
|
void simulateAvatarFades(float deltaTime);
|
||||||
|
|
||||||
// virtual overrides
|
// virtual overrides
|
||||||
virtual AvatarSharedPointer newSharedAvatar();
|
virtual AvatarSharedPointer newSharedAvatar();
|
||||||
virtual AvatarSharedPointer addAvatar(const QUuid& sessionUUID, const QWeakPointer<Node>& mixerWeakPointer);
|
virtual AvatarSharedPointer addAvatar(const QUuid& sessionUUID, const QWeakPointer<Node>& mixerWeakPointer);
|
||||||
void removeAvatarMotionState(AvatarSharedPointer avatar);
|
void removeAvatarMotionState(AvatarSharedPointer avatar);
|
||||||
|
|
||||||
virtual void removeAvatar(const QUuid& sessionUUID);
|
virtual void removeAvatar(const QUuid& sessionUUID);
|
||||||
virtual void handleRemovedAvatar(const AvatarSharedPointer& removedAvatar);
|
virtual void handleRemovedAvatar(const AvatarSharedPointer& removedAvatar);
|
||||||
|
|
||||||
QVector<AvatarSharedPointer> _avatarFades;
|
QVector<AvatarSharedPointer> _avatarFades;
|
||||||
std::shared_ptr<MyAvatar> _myAvatar;
|
std::shared_ptr<MyAvatar> _myAvatar;
|
||||||
quint64 _lastSendAvatarDataTime = 0; // Controls MyAvatar send data rate.
|
quint64 _lastSendAvatarDataTime = 0; // Controls MyAvatar send data rate.
|
||||||
|
|
||||||
QVector<AvatarManager::LocalLight> _localLights;
|
QVector<AvatarManager::LocalLight> _localLights;
|
||||||
|
|
||||||
bool _shouldShowReceiveStats = false;
|
bool _shouldShowReceiveStats = false;
|
||||||
|
|
|
@ -46,7 +46,7 @@ public:
|
||||||
virtual float getObjectFriction() const;
|
virtual float getObjectFriction() const;
|
||||||
virtual float getObjectLinearDamping() const;
|
virtual float getObjectLinearDamping() const;
|
||||||
virtual float getObjectAngularDamping() const;
|
virtual float getObjectAngularDamping() const;
|
||||||
|
|
||||||
virtual glm::vec3 getObjectPosition() const;
|
virtual glm::vec3 getObjectPosition() const;
|
||||||
virtual glm::quat getObjectRotation() const;
|
virtual glm::quat getObjectRotation() const;
|
||||||
virtual glm::vec3 getObjectLinearVelocity() const;
|
virtual glm::vec3 getObjectLinearVelocity() const;
|
||||||
|
|
|
@ -37,7 +37,7 @@ void Hand::simulate(float deltaTime, bool isMine) {
|
||||||
void Hand::renderHandTargets(RenderArgs* renderArgs, bool isMine) {
|
void Hand::renderHandTargets(RenderArgs* renderArgs, bool isMine) {
|
||||||
float avatarScale = 1.0f;
|
float avatarScale = 1.0f;
|
||||||
if (_owningAvatar) {
|
if (_owningAvatar) {
|
||||||
avatarScale = _owningAvatar->getAvatarScale();
|
avatarScale = _owningAvatar->getUniformScale();
|
||||||
}
|
}
|
||||||
|
|
||||||
const float alpha = 1.0f;
|
const float alpha = 1.0f;
|
||||||
|
@ -62,7 +62,7 @@ void Hand::renderHandTargets(RenderArgs* renderArgs, bool isMine) {
|
||||||
transform.setRotation(palm.getRotation());
|
transform.setRotation(palm.getRotation());
|
||||||
transform.postScale(SPHERE_RADIUS);
|
transform.postScale(SPHERE_RADIUS);
|
||||||
DependencyManager::get<DeferredLightingEffect>()->renderSolidSphereInstance(batch, transform, grayColor);
|
DependencyManager::get<DeferredLightingEffect>()->renderSolidSphereInstance(batch, transform, grayColor);
|
||||||
|
|
||||||
// draw a green sphere at the old "finger tip"
|
// draw a green sphere at the old "finger tip"
|
||||||
transform = Transform();
|
transform = Transform();
|
||||||
position = palm.getTipPosition();
|
position = palm.getTipPosition();
|
||||||
|
@ -72,7 +72,7 @@ void Hand::renderHandTargets(RenderArgs* renderArgs, bool isMine) {
|
||||||
DependencyManager::get<DeferredLightingEffect>()->renderSolidSphereInstance(batch, transform, greenColor);
|
DependencyManager::get<DeferredLightingEffect>()->renderSolidSphereInstance(batch, transform, greenColor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const float AXIS_RADIUS = 0.1f * SPHERE_RADIUS;
|
const float AXIS_RADIUS = 0.1f * SPHERE_RADIUS;
|
||||||
const float AXIS_LENGTH = 10.0f * SPHERE_RADIUS;
|
const float AXIS_LENGTH = 10.0f * SPHERE_RADIUS;
|
||||||
|
|
||||||
|
|
|
@ -287,10 +287,7 @@ extern void avatarStateFromFrame(const QByteArray& frameData, AvatarData* _avata
|
||||||
void MyAvatar::simulate(float deltaTime) {
|
void MyAvatar::simulate(float deltaTime) {
|
||||||
PerformanceTimer perfTimer("simulate");
|
PerformanceTimer perfTimer("simulate");
|
||||||
|
|
||||||
if (getAvatarScale() != _targetScale) {
|
animateScaleChanges(deltaTime);
|
||||||
float scale = (1.0f - SMOOTHING_RATIO) * getAvatarScale() + SMOOTHING_RATIO * _targetScale;
|
|
||||||
setAvatarScale(scale);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
{
|
||||||
PerformanceTimer perfTimer("transform");
|
PerformanceTimer perfTimer("transform");
|
||||||
|
@ -337,7 +334,7 @@ void MyAvatar::simulate(float deltaTime) {
|
||||||
headPosition = getPosition();
|
headPosition = getPosition();
|
||||||
}
|
}
|
||||||
head->setPosition(headPosition);
|
head->setPosition(headPosition);
|
||||||
head->setScale(getAvatarScale());
|
head->setScale(getUniformScale());
|
||||||
head->simulate(deltaTime, true);
|
head->simulate(deltaTime, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -681,7 +678,7 @@ void MyAvatar::loadData() {
|
||||||
|
|
||||||
_leanScale = loadSetting(settings, "leanScale", 0.05f);
|
_leanScale = loadSetting(settings, "leanScale", 0.05f);
|
||||||
_targetScale = loadSetting(settings, "scale", 1.0f);
|
_targetScale = loadSetting(settings, "scale", 1.0f);
|
||||||
setAvatarScale(getAvatarScale());
|
setScale(glm::vec3(_targetScale));
|
||||||
|
|
||||||
_animGraphUrl = settings.value("animGraphURL", "").toString();
|
_animGraphUrl = settings.value("animGraphURL", "").toString();
|
||||||
_fullAvatarURLFromPreferences = settings.value("fullAvatarURL", AvatarData::defaultFullAvatarModelUrl()).toUrl();
|
_fullAvatarURLFromPreferences = settings.value("fullAvatarURL", AvatarData::defaultFullAvatarModelUrl()).toUrl();
|
||||||
|
@ -809,7 +806,7 @@ void MyAvatar::updateLookAtTargetAvatar() {
|
||||||
float distanceTo = glm::length(avatar->getHead()->getEyePosition() - cameraPosition);
|
float distanceTo = glm::length(avatar->getHead()->getEyePosition() - cameraPosition);
|
||||||
avatar->setIsLookAtTarget(false);
|
avatar->setIsLookAtTarget(false);
|
||||||
if (!avatar->isMyAvatar() && avatar->isInitialized() &&
|
if (!avatar->isMyAvatar() && avatar->isInitialized() &&
|
||||||
(distanceTo < GREATEST_LOOKING_AT_DISTANCE * getAvatarScale())) {
|
(distanceTo < GREATEST_LOOKING_AT_DISTANCE * getUniformScale())) {
|
||||||
float angleTo = glm::angle(lookForward, glm::normalize(avatar->getHead()->getEyePosition() - cameraPosition));
|
float angleTo = glm::angle(lookForward, glm::normalize(avatar->getHead()->getEyePosition() - cameraPosition));
|
||||||
if (angleTo < (smallestAngleTo * (isCurrentTarget ? KEEP_LOOKING_AT_CURRENT_ANGLE_FACTOR : 1.0f))) {
|
if (angleTo < (smallestAngleTo * (isCurrentTarget ? KEEP_LOOKING_AT_CURRENT_ANGLE_FACTOR : 1.0f))) {
|
||||||
_lookAtTargetAvatar = avatarPointer;
|
_lookAtTargetAvatar = avatarPointer;
|
||||||
|
@ -1036,14 +1033,15 @@ glm::vec3 MyAvatar::getSkeletonPosition() const {
|
||||||
return Avatar::getPosition();
|
return Avatar::getPosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyAvatar::rebuildSkeletonBody() {
|
void MyAvatar::rebuildCollisionShape() {
|
||||||
// compute localAABox
|
// compute localAABox
|
||||||
float radius = _skeletonModel.getBoundingCapsuleRadius();
|
float scale = getUniformScale();
|
||||||
float height = _skeletonModel.getBoundingCapsuleHeight() + 2.0f * radius;
|
float radius = scale * _skeletonModel.getBoundingCapsuleRadius();
|
||||||
|
float height = scale * _skeletonModel.getBoundingCapsuleHeight() + 2.0f * radius;
|
||||||
glm::vec3 corner(-radius, -0.5f * height, -radius);
|
glm::vec3 corner(-radius, -0.5f * height, -radius);
|
||||||
corner += _skeletonModel.getBoundingCapsuleOffset();
|
corner += scale * _skeletonModel.getBoundingCapsuleOffset();
|
||||||
glm::vec3 scale(2.0f * radius, height, 2.0f * radius);
|
glm::vec3 diagonal(2.0f * radius, height, 2.0f * radius);
|
||||||
_characterController.setLocalBoundingBox(corner, scale);
|
_characterController.setLocalBoundingBox(corner, diagonal);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyAvatar::prepareForPhysicsSimulation() {
|
void MyAvatar::prepareForPhysicsSimulation() {
|
||||||
|
@ -1331,7 +1329,7 @@ const float RENDER_HEAD_CUTOFF_DISTANCE = 0.50f;
|
||||||
bool MyAvatar::cameraInsideHead() const {
|
bool MyAvatar::cameraInsideHead() const {
|
||||||
const Head* head = getHead();
|
const Head* head = getHead();
|
||||||
const glm::vec3 cameraPosition = qApp->getCamera()->getPosition();
|
const glm::vec3 cameraPosition = qApp->getCamera()->getPosition();
|
||||||
return glm::length(cameraPosition - head->getEyePosition()) < (RENDER_HEAD_CUTOFF_DISTANCE * getAvatarScale());
|
return glm::length(cameraPosition - head->getEyePosition()) < (RENDER_HEAD_CUTOFF_DISTANCE * getUniformScale());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MyAvatar::shouldRenderHead(const RenderArgs* renderArgs) const {
|
bool MyAvatar::shouldRenderHead(const RenderArgs* renderArgs) const {
|
||||||
|
@ -1455,11 +1453,11 @@ glm::vec3 MyAvatar::applyKeyboardMotor(float deltaTime, const glm::vec3& localVe
|
||||||
if (isHovering) {
|
if (isHovering) {
|
||||||
// we're flying --> complex acceleration curve with high max speed
|
// we're flying --> complex acceleration curve with high max speed
|
||||||
float motorSpeed = glm::length(_keyboardMotorVelocity);
|
float motorSpeed = glm::length(_keyboardMotorVelocity);
|
||||||
float finalMaxMotorSpeed = getAvatarScale() * MAX_KEYBOARD_MOTOR_SPEED;
|
float finalMaxMotorSpeed = getUniformScale() * MAX_KEYBOARD_MOTOR_SPEED;
|
||||||
float speedGrowthTimescale = 2.0f;
|
float speedGrowthTimescale = 2.0f;
|
||||||
float speedIncreaseFactor = 1.8f;
|
float speedIncreaseFactor = 1.8f;
|
||||||
motorSpeed *= 1.0f + glm::clamp(deltaTime / speedGrowthTimescale , 0.0f, 1.0f) * speedIncreaseFactor;
|
motorSpeed *= 1.0f + glm::clamp(deltaTime / speedGrowthTimescale , 0.0f, 1.0f) * speedIncreaseFactor;
|
||||||
const float maxBoostSpeed = getAvatarScale() * MAX_BOOST_SPEED;
|
const float maxBoostSpeed = getUniformScale() * MAX_BOOST_SPEED;
|
||||||
if (motorSpeed < maxBoostSpeed) {
|
if (motorSpeed < maxBoostSpeed) {
|
||||||
// an active keyboard motor should never be slower than this
|
// an active keyboard motor should never be slower than this
|
||||||
float boostCoefficient = (maxBoostSpeed - motorSpeed) / maxBoostSpeed;
|
float boostCoefficient = (maxBoostSpeed - motorSpeed) / maxBoostSpeed;
|
||||||
|
|
|
@ -249,7 +249,7 @@ public slots:
|
||||||
|
|
||||||
Q_INVOKABLE void updateMotionBehaviorFromMenu();
|
Q_INVOKABLE void updateMotionBehaviorFromMenu();
|
||||||
|
|
||||||
virtual void rebuildSkeletonBody() override;
|
virtual void rebuildCollisionShape() override;
|
||||||
|
|
||||||
Q_INVOKABLE QUrl getAnimGraphUrl() const { return _animGraphUrl; }
|
Q_INVOKABLE QUrl getAnimGraphUrl() const { return _animGraphUrl; }
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ MyCharacterController::~MyCharacterController() {
|
||||||
|
|
||||||
void MyCharacterController::updateShapeIfNecessary() {
|
void MyCharacterController::updateShapeIfNecessary() {
|
||||||
if (_pendingFlags & PENDING_FLAG_UPDATE_SHAPE) {
|
if (_pendingFlags & PENDING_FLAG_UPDATE_SHAPE) {
|
||||||
_pendingFlags &= ~ PENDING_FLAG_UPDATE_SHAPE;
|
_pendingFlags &= ~PENDING_FLAG_UPDATE_SHAPE;
|
||||||
|
|
||||||
// compute new dimensions from avatar's bounding box
|
// compute new dimensions from avatar's bounding box
|
||||||
float x = _boxScale.x;
|
float x = _boxScale.x;
|
||||||
|
|
|
@ -69,7 +69,7 @@ void SkeletonModel::initJointStates() {
|
||||||
_headClipDistance = -(meshExtents.minimum.z / _scale.z - _defaultEyeModelPosition.z);
|
_headClipDistance = -(meshExtents.minimum.z / _scale.z - _defaultEyeModelPosition.z);
|
||||||
_headClipDistance = std::max(_headClipDistance, DEFAULT_NEAR_CLIP);
|
_headClipDistance = std::max(_headClipDistance, DEFAULT_NEAR_CLIP);
|
||||||
|
|
||||||
_owningAvatar->rebuildSkeletonBody();
|
_owningAvatar->rebuildCollisionShape();
|
||||||
emit skeletonLoaded();
|
emit skeletonLoaded();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -338,35 +338,38 @@ void SkeletonModel::computeBoundingShape() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_rig->computeAvatarBoundingCapsule(geometry,
|
float radius, height;
|
||||||
_boundingCapsuleRadius,
|
glm::vec3 offset;
|
||||||
_boundingCapsuleHeight,
|
_rig->computeAvatarBoundingCapsule(geometry, radius, height, offset);
|
||||||
_boundingCapsuleLocalOffset);
|
float invScale = 1.0f / _owningAvatar->getUniformScale();
|
||||||
|
_boundingCapsuleRadius = invScale * radius;
|
||||||
|
_boundingCapsuleHeight = invScale * height;
|
||||||
|
_boundingCapsuleLocalOffset = invScale * offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkeletonModel::renderBoundingCollisionShapes(gpu::Batch& batch, float alpha) {
|
void SkeletonModel::renderBoundingCollisionShapes(gpu::Batch& batch, float scale, float alpha) {
|
||||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||||
auto deferredLighting = DependencyManager::get<DeferredLightingEffect>();
|
auto deferredLighting = DependencyManager::get<DeferredLightingEffect>();
|
||||||
// draw a blue sphere at the capsule top point
|
// draw a blue sphere at the capsule top point
|
||||||
glm::vec3 topPoint = _translation + getRotation() * (_boundingCapsuleLocalOffset + (0.5f * _boundingCapsuleHeight) * glm::vec3(0.0f, 1.0f, 0.0f));
|
glm::vec3 topPoint = _translation + getRotation() * (scale * (_boundingCapsuleLocalOffset + (0.5f * _boundingCapsuleHeight) * Vectors::UNIT_Y));
|
||||||
|
|
||||||
deferredLighting->renderSolidSphereInstance(batch,
|
deferredLighting->renderSolidSphereInstance(batch,
|
||||||
Transform().setTranslation(topPoint).postScale(_boundingCapsuleRadius),
|
Transform().setTranslation(topPoint).postScale(scale * _boundingCapsuleRadius),
|
||||||
glm::vec4(0.6f, 0.6f, 0.8f, alpha));
|
glm::vec4(0.6f, 0.6f, 0.8f, alpha));
|
||||||
|
|
||||||
// draw a yellow sphere at the capsule bottom point
|
// draw a yellow sphere at the capsule bottom point
|
||||||
glm::vec3 bottomPoint = topPoint - glm::vec3(0.0f, _boundingCapsuleHeight, 0.0f);
|
glm::vec3 bottomPoint = topPoint - glm::vec3(0.0f, scale * _boundingCapsuleHeight, 0.0f);
|
||||||
glm::vec3 axis = topPoint - bottomPoint;
|
glm::vec3 axis = topPoint - bottomPoint;
|
||||||
|
|
||||||
deferredLighting->renderSolidSphereInstance(batch,
|
deferredLighting->renderSolidSphereInstance(batch,
|
||||||
Transform().setTranslation(bottomPoint).postScale(_boundingCapsuleRadius),
|
Transform().setTranslation(bottomPoint).postScale(scale * _boundingCapsuleRadius),
|
||||||
glm::vec4(0.8f, 0.8f, 0.6f, alpha));
|
glm::vec4(0.8f, 0.8f, 0.6f, alpha));
|
||||||
|
|
||||||
// draw a green cylinder between the two points
|
// draw a green cylinder between the two points
|
||||||
glm::vec3 origin(0.0f);
|
glm::vec3 origin(0.0f);
|
||||||
batch.setModelTransform(Transform().setTranslation(bottomPoint));
|
batch.setModelTransform(Transform().setTranslation(bottomPoint));
|
||||||
deferredLighting->bindSimpleProgram(batch);
|
deferredLighting->bindSimpleProgram(batch);
|
||||||
Avatar::renderJointConnectingCone(batch, origin, axis, _boundingCapsuleRadius, _boundingCapsuleRadius,
|
Avatar::renderJointConnectingCone(batch, origin, axis, scale * _boundingCapsuleRadius, scale * _boundingCapsuleRadius,
|
||||||
glm::vec4(0.6f, 0.8f, 0.6f, alpha));
|
glm::vec4(0.6f, 0.8f, 0.6f, alpha));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -89,7 +89,7 @@ public:
|
||||||
/// \return whether or not the head was found.
|
/// \return whether or not the head was found.
|
||||||
glm::vec3 getDefaultEyeModelPosition() const;
|
glm::vec3 getDefaultEyeModelPosition() const;
|
||||||
|
|
||||||
void renderBoundingCollisionShapes(gpu::Batch& batch, float alpha);
|
void renderBoundingCollisionShapes(gpu::Batch& batch, float scale, float alpha);
|
||||||
float getBoundingCapsuleRadius() const { return _boundingCapsuleRadius; }
|
float getBoundingCapsuleRadius() const { return _boundingCapsuleRadius; }
|
||||||
float getBoundingCapsuleHeight() const { return _boundingCapsuleHeight; }
|
float getBoundingCapsuleHeight() const { return _boundingCapsuleHeight; }
|
||||||
const glm::vec3 getBoundingCapsuleOffset() const { return _boundingCapsuleLocalOffset; }
|
const glm::vec3 getBoundingCapsuleOffset() const { return _boundingCapsuleLocalOffset; }
|
||||||
|
|
|
@ -386,7 +386,7 @@ bool ApplicationCompositor::calculateRayUICollisionPoint(const glm::vec3& positi
|
||||||
glm::vec3 relativeDirection = glm::normalize(inverseOrientation * direction);
|
glm::vec3 relativeDirection = glm::normalize(inverseOrientation * direction);
|
||||||
|
|
||||||
float t;
|
float t;
|
||||||
if (raySphereIntersect(relativeDirection, relativePosition, _oculusUIRadius * myAvatar->getAvatarScale(), &t)){
|
if (raySphereIntersect(relativeDirection, relativePosition, _oculusUIRadius * myAvatar->getUniformScale(), &t)){
|
||||||
result = position + direction * t;
|
result = position + direction * t;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -199,7 +199,7 @@ void PreferencesDialog::loadPreferences() {
|
||||||
|
|
||||||
ui.leanScaleSpin->setValue(myAvatar->getLeanScale());
|
ui.leanScaleSpin->setValue(myAvatar->getLeanScale());
|
||||||
|
|
||||||
ui.avatarScaleSpin->setValue(myAvatar->getAvatarScale());
|
ui.avatarScaleSpin->setValue(myAvatar->getUniformScale());
|
||||||
ui.avatarAnimationEdit->setText(myAvatar->getAnimGraphUrl().toString());
|
ui.avatarAnimationEdit->setText(myAvatar->getAnimGraphUrl().toString());
|
||||||
|
|
||||||
ui.maxOctreePPSSpin->setValue(qApp->getMaxOctreePacketsPerSecond());
|
ui.maxOctreePPSSpin->setValue(qApp->getMaxOctreePacketsPerSecond());
|
||||||
|
@ -256,7 +256,7 @@ void PreferencesDialog::savePreferences() {
|
||||||
|
|
||||||
myAvatar->getHead()->setPupilDilation(ui.pupilDilationSlider->value() / (float)ui.pupilDilationSlider->maximum());
|
myAvatar->getHead()->setPupilDilation(ui.pupilDilationSlider->value() / (float)ui.pupilDilationSlider->maximum());
|
||||||
myAvatar->setLeanScale(ui.leanScaleSpin->value());
|
myAvatar->setLeanScale(ui.leanScaleSpin->value());
|
||||||
myAvatar->setClampedTargetScale(ui.avatarScaleSpin->value());
|
myAvatar->setTargetScaleVerbose(ui.avatarScaleSpin->value());
|
||||||
if (myAvatar->getAnimGraphUrl() != ui.avatarAnimationEdit->text()) { // If changed, destroy the old and start with the new
|
if (myAvatar->getAnimGraphUrl() != ui.avatarAnimationEdit->text()) { // If changed, destroy the old and start with the new
|
||||||
myAvatar->setAnimGraphUrl(ui.avatarAnimationEdit->text());
|
myAvatar->setAnimGraphUrl(ui.avatarAnimationEdit->text());
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,13 +26,15 @@
|
||||||
QString const Image3DOverlay::TYPE = "image3d";
|
QString const Image3DOverlay::TYPE = "image3d";
|
||||||
|
|
||||||
Image3DOverlay::Image3DOverlay() {
|
Image3DOverlay::Image3DOverlay() {
|
||||||
_isLoaded = false;
|
_isLoaded = false;
|
||||||
|
_emissive = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Image3DOverlay::Image3DOverlay(const Image3DOverlay* image3DOverlay) :
|
Image3DOverlay::Image3DOverlay(const Image3DOverlay* image3DOverlay) :
|
||||||
Billboard3DOverlay(image3DOverlay),
|
Billboard3DOverlay(image3DOverlay),
|
||||||
_url(image3DOverlay->_url),
|
_url(image3DOverlay->_url),
|
||||||
_texture(image3DOverlay->_texture),
|
_texture(image3DOverlay->_texture),
|
||||||
|
_emissive(image3DOverlay->_emissive),
|
||||||
_fromImage(image3DOverlay->_fromImage)
|
_fromImage(image3DOverlay->_fromImage)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -93,8 +95,8 @@ void Image3DOverlay::render(RenderArgs* args) {
|
||||||
|
|
||||||
batch->setModelTransform(transform);
|
batch->setModelTransform(transform);
|
||||||
batch->setResourceTexture(0, _texture->getGPUTexture());
|
batch->setResourceTexture(0, _texture->getGPUTexture());
|
||||||
|
|
||||||
DependencyManager::get<DeferredLightingEffect>()->bindSimpleProgram(*batch, true, false, false, true);
|
DependencyManager::get<DeferredLightingEffect>()->bindSimpleProgram(*batch, true, false, _emissive, true);
|
||||||
DependencyManager::get<GeometryCache>()->renderQuad(
|
DependencyManager::get<GeometryCache>()->renderQuad(
|
||||||
*batch, topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight,
|
*batch, topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight,
|
||||||
glm::vec4(color.red / MAX_COLOR, color.green / MAX_COLOR, color.blue / MAX_COLOR, alpha)
|
glm::vec4(color.red / MAX_COLOR, color.green / MAX_COLOR, color.blue / MAX_COLOR, alpha)
|
||||||
|
@ -144,6 +146,11 @@ void Image3DOverlay::setProperties(const QScriptValue &properties) {
|
||||||
setClipFromSource(subImageRect);
|
setClipFromSource(subImageRect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QScriptValue emissiveValue = properties.property("emissive");
|
||||||
|
if (emissiveValue.isValid()) {
|
||||||
|
_emissive = emissiveValue.toBool();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QScriptValue Image3DOverlay::getProperty(const QString& property) {
|
QScriptValue Image3DOverlay::getProperty(const QString& property) {
|
||||||
|
@ -156,6 +163,9 @@ QScriptValue Image3DOverlay::getProperty(const QString& property) {
|
||||||
if (property == "offsetPosition") {
|
if (property == "offsetPosition") {
|
||||||
return vec3toScriptValue(_scriptEngine, getOffsetPosition());
|
return vec3toScriptValue(_scriptEngine, getOffsetPosition());
|
||||||
}
|
}
|
||||||
|
if (property == "emissive") {
|
||||||
|
return _emissive;
|
||||||
|
}
|
||||||
|
|
||||||
return Billboard3DOverlay::getProperty(property);
|
return Billboard3DOverlay::getProperty(property);
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,7 @@ public:
|
||||||
private:
|
private:
|
||||||
QString _url;
|
QString _url;
|
||||||
NetworkTexturePointer _texture;
|
NetworkTexturePointer _texture;
|
||||||
|
bool _emissive;
|
||||||
|
|
||||||
QRect _fromImage; // where from in the image to sample
|
QRect _fromImage; // where from in the image to sample
|
||||||
};
|
};
|
||||||
|
|
|
@ -68,7 +68,7 @@ namespace render {
|
||||||
glm::vec3 myAvatarPosition = avatar->getPosition();
|
glm::vec3 myAvatarPosition = avatar->getPosition();
|
||||||
float angle = glm::degrees(glm::angle(myAvatarRotation));
|
float angle = glm::degrees(glm::angle(myAvatarRotation));
|
||||||
glm::vec3 axis = glm::axis(myAvatarRotation);
|
glm::vec3 axis = glm::axis(myAvatarRotation);
|
||||||
float myAvatarScale = avatar->getAvatarScale();
|
float myAvatarScale = avatar->getUniformScale();
|
||||||
Transform transform = Transform();
|
Transform transform = Transform();
|
||||||
transform.setTranslation(myAvatarPosition);
|
transform.setTranslation(myAvatarPosition);
|
||||||
transform.setRotation(glm::angleAxis(angle, axis));
|
transform.setRotation(glm::angleAxis(angle, axis));
|
||||||
|
|
|
@ -90,7 +90,7 @@ const QUrl& AvatarData::defaultFullAvatarModelUrl() {
|
||||||
// There are a number of possible strategies for this set of tools through endRender, below.
|
// There are a number of possible strategies for this set of tools through endRender, below.
|
||||||
void AvatarData::nextAttitude(glm::vec3 position, glm::quat orientation) {
|
void AvatarData::nextAttitude(glm::vec3 position, glm::quat orientation) {
|
||||||
avatarLock.lock();
|
avatarLock.lock();
|
||||||
Transform trans;
|
Transform trans = getTransform();
|
||||||
trans.setTranslation(position);
|
trans.setTranslation(position);
|
||||||
trans.setRotation(orientation);
|
trans.setRotation(orientation);
|
||||||
SpatiallyNestable::setTransform(trans);
|
SpatiallyNestable::setTransform(trans);
|
||||||
|
@ -129,13 +129,10 @@ float AvatarData::getTargetScale() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void AvatarData::setTargetScale(float targetScale) {
|
void AvatarData::setTargetScale(float targetScale) {
|
||||||
_targetScale = std::max(MIN_AVATAR_SCALE, std::min(MAX_AVATAR_SCALE, targetScale));
|
_targetScale = glm::clamp(targetScale, MIN_AVATAR_SCALE, MAX_AVATAR_SCALE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AvatarData::setClampedTargetScale(float targetScale) {
|
void AvatarData::setTargetScaleVerbose(float targetScale) {
|
||||||
|
|
||||||
targetScale = glm::clamp(targetScale, MIN_AVATAR_SCALE, MAX_AVATAR_SCALE);
|
|
||||||
|
|
||||||
setTargetScale(targetScale);
|
setTargetScale(targetScale);
|
||||||
qCDebug(avatars) << "Changed scale to " << _targetScale;
|
qCDebug(avatars) << "Changed scale to " << _targetScale;
|
||||||
}
|
}
|
||||||
|
|
|
@ -172,7 +172,7 @@ public:
|
||||||
|
|
||||||
AvatarData();
|
AvatarData();
|
||||||
virtual ~AvatarData();
|
virtual ~AvatarData();
|
||||||
|
|
||||||
static const QUrl& defaultFullAvatarModelUrl();
|
static const QUrl& defaultFullAvatarModelUrl();
|
||||||
|
|
||||||
virtual bool isMyAvatar() const { return false; }
|
virtual bool isMyAvatar() const { return false; }
|
||||||
|
@ -237,7 +237,7 @@ public:
|
||||||
// Scale
|
// Scale
|
||||||
float getTargetScale() const;
|
float getTargetScale() const;
|
||||||
void setTargetScale(float targetScale);
|
void setTargetScale(float targetScale);
|
||||||
void setClampedTargetScale(float targetScale);
|
void setTargetScaleVerbose(float targetScale);
|
||||||
|
|
||||||
// Hand State
|
// Hand State
|
||||||
Q_INVOKABLE void setHandState(char s) { _handState = s; }
|
Q_INVOKABLE void setHandState(char s) { _handState = s; }
|
||||||
|
@ -261,7 +261,7 @@ public:
|
||||||
Q_INVOKABLE bool isJointDataValid(const QString& name) const;
|
Q_INVOKABLE bool isJointDataValid(const QString& name) const;
|
||||||
Q_INVOKABLE glm::quat getJointRotation(const QString& name) const;
|
Q_INVOKABLE glm::quat getJointRotation(const QString& name) const;
|
||||||
Q_INVOKABLE glm::vec3 getJointTranslation(const QString& name) const;
|
Q_INVOKABLE glm::vec3 getJointTranslation(const QString& name) const;
|
||||||
|
|
||||||
Q_INVOKABLE virtual QVector<glm::quat> getJointRotations() const;
|
Q_INVOKABLE virtual QVector<glm::quat> getJointRotations() const;
|
||||||
Q_INVOKABLE virtual void setJointRotations(QVector<glm::quat> jointRotations);
|
Q_INVOKABLE virtual void setJointRotations(QVector<glm::quat> jointRotations);
|
||||||
Q_INVOKABLE virtual void setJointTranslations(QVector<glm::vec3> jointTranslations);
|
Q_INVOKABLE virtual void setJointTranslations(QVector<glm::vec3> jointTranslations);
|
||||||
|
@ -342,6 +342,9 @@ public:
|
||||||
|
|
||||||
glm::vec3 getClientGlobalPosition() { return _globalPosition; }
|
glm::vec3 getClientGlobalPosition() { return _globalPosition; }
|
||||||
|
|
||||||
|
void die() { _isDead = true; }
|
||||||
|
bool isDead() const { return _isDead; }
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void sendAvatarDataPacket();
|
void sendAvatarDataPacket();
|
||||||
void sendIdentityPacket();
|
void sendIdentityPacket();
|
||||||
|
@ -413,6 +416,8 @@ protected:
|
||||||
// updates about one avatar to another.
|
// updates about one avatar to another.
|
||||||
glm::vec3 _globalPosition;
|
glm::vec3 _globalPosition;
|
||||||
|
|
||||||
|
bool _isDead { false };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend void avatarStateFromFrame(const QByteArray& frameData, AvatarData* _avatar);
|
friend void avatarStateFromFrame(const QByteArray& frameData, AvatarData* _avatar);
|
||||||
static QUrl _defaultFullAvatarModelUrl;
|
static QUrl _defaultFullAvatarModelUrl;
|
||||||
|
|
|
@ -595,18 +595,20 @@ void ParticleEffectEntityItem::integrateParticle(Particle& particle, float delta
|
||||||
|
|
||||||
void ParticleEffectEntityItem::stepSimulation(float deltaTime) {
|
void ParticleEffectEntityItem::stepSimulation(float deltaTime) {
|
||||||
// update particles between head and tail
|
// update particles between head and tail
|
||||||
|
int popCount = 0;
|
||||||
for (Particle& particle : _particles) {
|
for (Particle& particle : _particles) {
|
||||||
particle.lifetime += deltaTime;
|
particle.lifetime += deltaTime;
|
||||||
|
|
||||||
// if particle has died.
|
// if particle has died.
|
||||||
if (particle.lifetime >= _lifespan) {
|
if (particle.lifetime >= _lifespan) {
|
||||||
// move head forward
|
// move head forward
|
||||||
_particles.pop_front();
|
popCount++;
|
||||||
} else {
|
} else {
|
||||||
// Otherwise update it
|
// Otherwise update it
|
||||||
integrateParticle(particle, deltaTime);
|
integrateParticle(particle, deltaTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
_particles.erase(_particles.begin(), _particles.begin() + popCount);
|
||||||
|
|
||||||
// emit new particles, but only if we are emmitting
|
// emit new particles, but only if we are emmitting
|
||||||
if (getIsEmitting() && _emitRate > 0.0f && _lifespan > 0.0f && _polarStart <= _polarFinish) {
|
if (getIsEmitting() && _emitRate > 0.0f && _lifespan > 0.0f && _polarStart <= _polarFinish) {
|
||||||
|
|
|
@ -23,7 +23,7 @@ const int MAX_PAYLOAD_BYTES = 1024;
|
||||||
const QString emptyPool = QString();
|
const QString emptyPool = QString();
|
||||||
|
|
||||||
/// Holds information used for request, creation, and deployment of assignments
|
/// Holds information used for request, creation, and deployment of assignments
|
||||||
class Assignment : public NodeData {
|
class Assignment : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,6 @@ const char SOLO_NODE_TYPES[2] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
LimitedNodeList::LimitedNodeList(unsigned short socketListenPort, unsigned short dtlsListenPort) :
|
LimitedNodeList::LimitedNodeList(unsigned short socketListenPort, unsigned short dtlsListenPort) :
|
||||||
linkedDataCreateCallback(NULL),
|
|
||||||
_sessionUUID(),
|
_sessionUUID(),
|
||||||
_nodeHash(),
|
_nodeHash(),
|
||||||
_nodeMutex(QReadWriteLock::Recursive),
|
_nodeMutex(QReadWriteLock::Recursive),
|
||||||
|
|
|
@ -129,7 +129,7 @@ public:
|
||||||
qint64 sendPacketList(std::unique_ptr<NLPacketList> packetList, const HifiSockAddr& sockAddr);
|
qint64 sendPacketList(std::unique_ptr<NLPacketList> packetList, const HifiSockAddr& sockAddr);
|
||||||
qint64 sendPacketList(std::unique_ptr<NLPacketList> packetList, const Node& destinationNode);
|
qint64 sendPacketList(std::unique_ptr<NLPacketList> packetList, const Node& destinationNode);
|
||||||
|
|
||||||
void (*linkedDataCreateCallback)(Node *);
|
std::function<void(Node*)> linkedDataCreateCallback;
|
||||||
|
|
||||||
size_t size() const { return _nodeHash.size(); }
|
size_t size() const { return _nodeHash.size(); }
|
||||||
|
|
||||||
|
|
|
@ -128,8 +128,8 @@ void DeferredLightingEffect::init() {
|
||||||
|
|
||||||
|
|
||||||
gpu::PipelinePointer DeferredLightingEffect::bindSimpleProgram(gpu::Batch& batch, bool textured, bool culled,
|
gpu::PipelinePointer DeferredLightingEffect::bindSimpleProgram(gpu::Batch& batch, bool textured, bool culled,
|
||||||
bool emmisive, bool depthBias) {
|
bool emissive, bool depthBias) {
|
||||||
SimpleProgramKey config{textured, culled, emmisive, depthBias};
|
SimpleProgramKey config{textured, culled, emissive, depthBias};
|
||||||
gpu::PipelinePointer pipeline = getPipeline(config);
|
gpu::PipelinePointer pipeline = getPipeline(config);
|
||||||
batch.setPipeline(pipeline);
|
batch.setPipeline(pipeline);
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ public:
|
||||||
|
|
||||||
/// Sets up the state necessary to render static untextured geometry with the simple program.
|
/// Sets up the state necessary to render static untextured geometry with the simple program.
|
||||||
gpu::PipelinePointer bindSimpleProgram(gpu::Batch& batch, bool textured = false, bool culled = true,
|
gpu::PipelinePointer bindSimpleProgram(gpu::Batch& batch, bool textured = false, bool culled = true,
|
||||||
bool emmisive = false, bool depthBias = false);
|
bool emissive = false, bool depthBias = false);
|
||||||
|
|
||||||
void renderSolidSphereInstance(gpu::Batch& batch, const Transform& xfm, const glm::vec4& color);
|
void renderSolidSphereInstance(gpu::Batch& batch, const Transform& xfm, const glm::vec4& color);
|
||||||
void renderSolidSphereInstance(gpu::Batch& batch, const Transform& xfm, const glm::vec3& color) {
|
void renderSolidSphereInstance(gpu::Batch& batch, const Transform& xfm, const glm::vec3& color) {
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
|
|
||||||
|
|
||||||
GenericThread::GenericThread() :
|
GenericThread::GenericThread() :
|
||||||
QObject(),
|
|
||||||
_stopThread(false),
|
_stopThread(false),
|
||||||
_isThreaded(false) // assume non-threaded, must call initialize()
|
_isThreaded(false) // assume non-threaded, must call initialize()
|
||||||
{
|
{
|
||||||
|
@ -38,9 +37,10 @@ void GenericThread::initialize(bool isThreaded, QThread::Priority priority) {
|
||||||
_thread->setObjectName(objectName());
|
_thread->setObjectName(objectName());
|
||||||
|
|
||||||
// when the worker thread is started, call our engine's run..
|
// when the worker thread is started, call our engine's run..
|
||||||
connect(_thread, SIGNAL(started()), this, SLOT(threadRoutine()));
|
connect(_thread, &QThread::started, this, &GenericThread::threadRoutine);
|
||||||
|
connect(_thread, &QThread::finished, this, &GenericThread::finished);
|
||||||
|
|
||||||
this->moveToThread(_thread);
|
moveToThread(_thread);
|
||||||
|
|
||||||
// Starts an event loop, and emits _thread->started()
|
// Starts an event loop, and emits _thread->started()
|
||||||
_thread->start();
|
_thread->start();
|
||||||
|
@ -82,5 +82,4 @@ void GenericThread::threadRoutine() {
|
||||||
if (_isThreaded && _thread) {
|
if (_isThreaded && _thread) {
|
||||||
_thread->quit();
|
_thread->quit();
|
||||||
}
|
}
|
||||||
emit finished();
|
|
||||||
}
|
}
|
||||||
|
|
164
tools/nsis/release.nsi
Normal file
164
tools/nsis/release.nsi
Normal file
|
@ -0,0 +1,164 @@
|
||||||
|
!include LogicLib.nsh
|
||||||
|
!include x64.nsh
|
||||||
|
|
||||||
|
!define srcdir "$%INSTALLER_SOURCE_DIR%"
|
||||||
|
!define setup "$%INSTALLER_NAME%"
|
||||||
|
!define scriptsdir "$%INSTALLER_SCRIPTS_DIR%"
|
||||||
|
!define company "$%INSTALLER_COMPANY%"
|
||||||
|
!define install_directory "$%INSTALLER_DIRECTORY%"
|
||||||
|
!define interface_exec "interface.exe"
|
||||||
|
!define stack_manager_exec "stack-manager.exe"
|
||||||
|
!define interface_icon "interface.ico"
|
||||||
|
!define stack_manager_icon "stack-manager.ico"
|
||||||
|
!define regkey "Software\${company}"
|
||||||
|
!define uninstkey "Software\Microsoft\Windows\CurrentVersion\Uninstall\${company}"
|
||||||
|
!define install_dir_company "$PROGRAMFILES64\${install_directory}"
|
||||||
|
!define startmenu_company "$SMPROGRAMS\${install_directory}"
|
||||||
|
!define uninstaller "uninstall.exe"
|
||||||
|
|
||||||
|
;--------------------------------
|
||||||
|
|
||||||
|
XPStyle on
|
||||||
|
ShowInstDetails hide
|
||||||
|
ShowUninstDetails hide
|
||||||
|
|
||||||
|
Name "${company}"
|
||||||
|
Caption "${company}"
|
||||||
|
|
||||||
|
!ifdef icon
|
||||||
|
Icon "${icon}"
|
||||||
|
!endif
|
||||||
|
|
||||||
|
OutFile "${setup}"
|
||||||
|
|
||||||
|
SetDateSave on
|
||||||
|
SetDatablockOptimize on
|
||||||
|
CRCCheck on
|
||||||
|
SilentInstall normal
|
||||||
|
|
||||||
|
InstallDir "${install_dir_company}"
|
||||||
|
InstallDirRegKey HKLM "${regkey}" ""
|
||||||
|
|
||||||
|
; Page components
|
||||||
|
Page directory
|
||||||
|
Page components
|
||||||
|
Page instfiles
|
||||||
|
|
||||||
|
UninstPage uninstConfirm
|
||||||
|
UninstPage instfiles
|
||||||
|
|
||||||
|
;--------------------------------
|
||||||
|
|
||||||
|
AutoCloseWindow true
|
||||||
|
ShowInstDetails show
|
||||||
|
|
||||||
|
|
||||||
|
!ifdef screenimage
|
||||||
|
|
||||||
|
; set up background image
|
||||||
|
; uses BgImage plugin
|
||||||
|
|
||||||
|
Function .onGUIInit
|
||||||
|
; extract background BMP into temp plugin directory
|
||||||
|
InitPluginsDir
|
||||||
|
File /oname=$PLUGINSDIR\1.bmp "${screenimage}"
|
||||||
|
|
||||||
|
BgImage::SetBg /NOUNLOAD /FILLSCREEN $PLUGINSDIR\1.bmp
|
||||||
|
BgImage::Redraw /NOUNLOAD
|
||||||
|
FunctionEnd
|
||||||
|
|
||||||
|
Function .onGUIEnd
|
||||||
|
; Destroy must not have /NOUNLOAD so NSIS will be able to unload and delete BgImage before it exits
|
||||||
|
BgImage::Destroy
|
||||||
|
FunctionEnd
|
||||||
|
|
||||||
|
!endif
|
||||||
|
|
||||||
|
; Optional Component Selection
|
||||||
|
Section /o "DDE Face Recognition" SEC01
|
||||||
|
SetOutPath "$INSTDIR"
|
||||||
|
CreateDirectory $INSTDIR\dde
|
||||||
|
NSISdl::download "https://s3-us-west-1.amazonaws.com/hifi-production/optionals/dde-installer.exe" "$INSTDIR\dde-installer.exe"
|
||||||
|
ExecWait '"$INSTDIR\dde-installer.exe" /q:a /t:"$INSTDIR\dde"'
|
||||||
|
SectionEnd
|
||||||
|
|
||||||
|
; beginning (invisible) section
|
||||||
|
Section "Registry Entries and Procotol Handler" SEC02
|
||||||
|
|
||||||
|
SectionIn RO
|
||||||
|
|
||||||
|
WriteRegStr HKLM "${regkey}" "Install_Dir" "$INSTDIR"
|
||||||
|
WriteRegStr HKLM "${uninstkey}" "DisplayName" "${company} (remove only)"
|
||||||
|
WriteRegStr HKLM "${uninstkey}" "UninstallString" '"$INSTDIR\${uninstaller}"'
|
||||||
|
WriteRegStr HKCR "${company}\Shell\open\command\" "" '"$INSTDIR\${interface_exec} "%1"'
|
||||||
|
WriteRegStr HKCR "${company}\DefaultIcon" "" "$INSTDIR\${interface_icon}"
|
||||||
|
|
||||||
|
; hifi:// protocol handler registry entries
|
||||||
|
WriteRegStr HKCR 'hifi' '' 'URL:Alert Protocol'
|
||||||
|
WriteRegStr HKCR 'hifi' 'URL Protocol' ''
|
||||||
|
WriteRegStr HKCR 'hifi\DefaultIcon' '' '$INSTDIR\${interface_icon},1'
|
||||||
|
WriteRegStr HKCR 'hifi\shell\open\command' '' '$INSTDIR\${interface_exec} --url "%1"'
|
||||||
|
|
||||||
|
SetOutPath $INSTDIR
|
||||||
|
|
||||||
|
; package all files, recursively, preserving attributes
|
||||||
|
; assume files are in the correct places
|
||||||
|
File /r "${srcdir}\"
|
||||||
|
File /a "${srcdir}\${interface_icon}"
|
||||||
|
File /a "${srcdir}\${stack_manager_icon}"
|
||||||
|
; any application-specific files
|
||||||
|
!ifdef files
|
||||||
|
!include "${files}"
|
||||||
|
!endif
|
||||||
|
WriteUninstaller "${uninstaller}"
|
||||||
|
Exec '"$INSTDIR\2013_vcredist_x64.exe" /q /norestart'
|
||||||
|
Exec '"$INSTDIR\2010_vcredist_x86.exe" /q /norestart'
|
||||||
|
SectionEnd
|
||||||
|
|
||||||
|
; create shortcuts
|
||||||
|
Section "Start Menu Shortcuts" SEC03
|
||||||
|
|
||||||
|
SectionIn RO
|
||||||
|
|
||||||
|
; This should install the shortcuts for "All Users"
|
||||||
|
SetShellVarContext all
|
||||||
|
CreateDirectory "${startmenu_company}"
|
||||||
|
SetOutPath $INSTDIR ; for working directory
|
||||||
|
CreateShortCut "${startmenu_company}\Interface.lnk" "$INSTDIR\${interface_exec}" "" "$INSTDIR\${interface_icon}"
|
||||||
|
CreateShortCut "${startmenu_company}\Stack Manager.lnk" "$INSTDIR\${stack_manager_exec}" "" "$INSTDIR\${stack_manager_icon}"
|
||||||
|
CreateShortCut "${startmenu_company}\Uninstall ${company}.lnk" "$INSTDIR\${uninstaller}"
|
||||||
|
SectionEnd
|
||||||
|
|
||||||
|
; Uninstaller
|
||||||
|
; All section names prefixed by "Un" will be in the uninstaller
|
||||||
|
|
||||||
|
UninstallText "This will uninstall ${company}."
|
||||||
|
|
||||||
|
!ifdef icon
|
||||||
|
UninstallIcon "${interface_icon}"
|
||||||
|
!endif
|
||||||
|
|
||||||
|
Section "Uninstall" SEC04
|
||||||
|
|
||||||
|
SectionIn RO
|
||||||
|
|
||||||
|
; Explicitly remove all added shortcuts
|
||||||
|
SetShellVarContext all
|
||||||
|
DELETE "${startmenu_company}\Interface.lnk"
|
||||||
|
DELETE "${startmenu_company}\Stack Manager.lnk"
|
||||||
|
DELETE "${startmenu_company}\Uninstall ${company}.lnk"
|
||||||
|
|
||||||
|
RMDIR "${startmenu_company}"
|
||||||
|
|
||||||
|
RMDIR /r "$INSTDIR"
|
||||||
|
; This should remove the High Fidelity folder in Program Files if it's empty
|
||||||
|
RMDIR "${install_dir_company}"
|
||||||
|
|
||||||
|
!ifdef unfiles
|
||||||
|
!include "${unfiles}"
|
||||||
|
!endif
|
||||||
|
; It's good practice to put the registry key removal at the very end
|
||||||
|
DeleteRegKey HKLM "${uninstkey}"
|
||||||
|
DeleteRegKey HKLM "${regkey}"
|
||||||
|
DeleteRegKey HKCR 'hifi'
|
||||||
|
SectionEnd
|
Loading…
Reference in a new issue