mirror of
https://github.com/overte-org/overte.git
synced 2025-04-21 09:44:21 +02:00
Merge branch master from upstream
This commit is contained in:
commit
1714f7fb27
73 changed files with 1363 additions and 1185 deletions
|
@ -32,15 +32,7 @@ link_hifi_library(voxels ${TARGET_NAME} "${ROOT_DIR}")
|
|||
# link the hifi networking library
|
||||
link_hifi_library(networking ${TARGET_NAME} "${ROOT_DIR}")
|
||||
|
||||
find_package(GnuTLS REQUIRED)
|
||||
|
||||
# include the GnuTLS dir
|
||||
include_directories(SYSTEM "${GNUTLS_INCLUDE_DIR}")
|
||||
|
||||
# add a definition for ssize_t so that windows doesn't bail on gnutls.h
|
||||
# add a definition for ssize_t so that windows doesn't bail
|
||||
if (WIN32)
|
||||
add_definitions(-Dssize_t=long)
|
||||
endif ()
|
||||
|
||||
# link GnuTLS
|
||||
target_link_libraries(${TARGET_NAME} "${GNUTLS_LIBRARY}")
|
||||
endif ()
|
|
@ -37,15 +37,6 @@ link_hifi_library(animation ${TARGET_NAME} "${ROOT_DIR}")
|
|||
link_hifi_library(script-engine ${TARGET_NAME} "${ROOT_DIR}")
|
||||
link_hifi_library(embedded-webserver ${TARGET_NAME} "${ROOT_DIR}")
|
||||
|
||||
find_package(GnuTLS REQUIRED)
|
||||
|
||||
# add a definition for ssize_t so that windows doesn't bail on gnutls.h
|
||||
if (WIN32)
|
||||
add_definitions(-Dssize_t=long)
|
||||
endif ()
|
||||
|
||||
include_directories(SYSTEM "${GNUTLS_INCLUDE_DIR}")
|
||||
|
||||
if (UNIX)
|
||||
target_link_libraries(${TARGET_NAME} ${CMAKE_DL_LIBS})
|
||||
endif (UNIX)
|
||||
|
@ -54,4 +45,9 @@ IF (WIN32)
|
|||
target_link_libraries(${TARGET_NAME} Winmm Ws2_32)
|
||||
ENDIF(WIN32)
|
||||
|
||||
target_link_libraries(${TARGET_NAME} Qt5::Network Qt5::Widgets Qt5::Script "${GNUTLS_LIBRARY}")
|
||||
target_link_libraries(${TARGET_NAME} Qt5::Network Qt5::Widgets Qt5::Script)
|
||||
|
||||
# add a definition for ssize_t so that windows doesn't bail
|
||||
if (WIN32)
|
||||
add_definitions(-Dssize_t=long)
|
||||
endif ()
|
|
@ -13,8 +13,6 @@
|
|||
#include <QtCore/QThread>
|
||||
#include <QtCore/QTimer>
|
||||
|
||||
#include <gnutls/gnutls.h>
|
||||
|
||||
#include <AccountManager.h>
|
||||
#include <Assignment.h>
|
||||
#include <Logging.h>
|
||||
|
@ -39,8 +37,6 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) :
|
|||
QCoreApplication(argc, argv),
|
||||
_assignmentServerHostname(DEFAULT_ASSIGNMENT_SERVER_HOSTNAME)
|
||||
{
|
||||
DTLSClientSession::globalInit();
|
||||
|
||||
setOrganizationName("High Fidelity");
|
||||
setOrganizationDomain("highfidelity.io");
|
||||
setApplicationName("assignment-client");
|
||||
|
@ -106,10 +102,6 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) :
|
|||
this, &AssignmentClient::handleAuthenticationRequest);
|
||||
}
|
||||
|
||||
AssignmentClient::~AssignmentClient() {
|
||||
DTLSClientSession::globalDeinit();
|
||||
}
|
||||
|
||||
void AssignmentClient::sendAssignmentRequest() {
|
||||
if (!_currentAssignment) {
|
||||
NodeList::getInstance()->sendAssignment(_requestAssignment);
|
||||
|
|
|
@ -21,7 +21,6 @@ class AssignmentClient : public QCoreApplication {
|
|||
public:
|
||||
AssignmentClient(int &argc, char **argv);
|
||||
static const SharedAssignmentPointer& getCurrentAssignment() { return _currentAssignment; }
|
||||
~AssignmentClient();
|
||||
private slots:
|
||||
void sendAssignmentRequest();
|
||||
void readPendingDatagrams();
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
#
|
||||
# FindGnuTLS.cmake
|
||||
#
|
||||
# Try to find the GnuTLS library
|
||||
#
|
||||
# You can provide a GNUTLS_ROOT_DIR which contains lib and include directories
|
||||
#
|
||||
# Once done this will define
|
||||
#
|
||||
# GNUTLS_FOUND - system found GnuTLS
|
||||
# GNUTLS_INCLUDE_DIR - the GnuTLS include directory
|
||||
# GNUTLS_LIBRARY - Link this to use GnuTLS
|
||||
#
|
||||
# Created on 3/31/2014 by Stephen Birarda
|
||||
# Copyright (c) 2014 High Fidelity
|
||||
#
|
||||
# Distributed under the Apache License, Version 2.0.
|
||||
# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
#
|
||||
|
||||
if (GNUTLS_LIBRARY AND GNUTLS_INCLUDE_DIRS)
|
||||
# in cache already
|
||||
set(GNUTLS_FOUND TRUE)
|
||||
else ()
|
||||
set(GNUTLS_SEARCH_DIRS "${GNUTLS_ROOT_DIR}" "$ENV{HIFI_LIB_DIR}/gnutls")
|
||||
|
||||
find_path(GNUTLS_INCLUDE_DIR gnutls/gnutls.h PATH_SUFFIXES include HINTS ${GNUTLS_SEARCH_DIRS})
|
||||
|
||||
find_library(GNUTLS_LIBRARY NAMES gnutls libgnutls libgnutls-28 PATH_SUFFIXES lib HINTS ${GNUTLS_SEARCH_DIRS})
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(GNUTLS DEFAULT_MSG GNUTLS_INCLUDE_DIR GNUTLS_LIBRARY)
|
||||
|
||||
if (WIN32 AND NOT GNUTLS_FOUND)
|
||||
message(STATUS "If you're generating a MSVC environment, you'll need to run the command")
|
||||
message(STATUS "$GnuTLS-DIR\\bin>lib /def:libgnutls-28.def")
|
||||
message(STATUS "From the MSVC command prompt to generate the .lib file and copy it into")
|
||||
message(STATUS "the GnuTLS lib folder. Replace $GnuTLS-DIR in the command with the directory")
|
||||
message(STATUS "containing GnuTLS.")
|
||||
endif ()
|
||||
endif ()
|
|
@ -49,7 +49,7 @@ else (LIBOVR_LIBRARIES AND LIBOVR_INCLUDE_DIRS)
|
|||
set(WINDOWS_LIBOVR_NAME "libovr.lib")
|
||||
endif()
|
||||
|
||||
find_library(LIBOVR_LIBRARIES "Lib/Win32/VS2010/${LIBOVR_NAME}" HINTS ${LIBOVR_SEARCH_DIRS})
|
||||
find_library(LIBOVR_LIBRARIES "Lib/Win32/${WINDOWS_LIBOVR_NAME}" HINTS ${LIBOVR_SEARCH_DIRS})
|
||||
endif ()
|
||||
|
||||
if (LIBOVR_INCLUDE_DIRS AND LIBOVR_LIBRARIES)
|
||||
|
|
|
@ -17,7 +17,6 @@ include(${MACRO_DIR}/IncludeGLM.cmake)
|
|||
include_glm(${TARGET_NAME} "${ROOT_DIR}")
|
||||
|
||||
find_package(Qt5Network REQUIRED)
|
||||
find_package(GnuTLS REQUIRED)
|
||||
|
||||
include(${MACRO_DIR}/SetupHifiProject.cmake)
|
||||
|
||||
|
@ -38,17 +37,14 @@ link_hifi_library(networking ${TARGET_NAME} "${ROOT_DIR}")
|
|||
link_hifi_library(shared ${TARGET_NAME} "${ROOT_DIR}")
|
||||
link_hifi_library(embedded-webserver ${TARGET_NAME} "${ROOT_DIR}")
|
||||
|
||||
# include the GnuTLS dir
|
||||
include_directories(SYSTEM "${GNUTLS_INCLUDE_DIR}")
|
||||
|
||||
# add a definition for ssize_t so that windows doesn't bail on gnutls.h
|
||||
if (WIN32)
|
||||
add_definitions(-Dssize_t=long)
|
||||
endif ()
|
||||
|
||||
IF (WIN32)
|
||||
target_link_libraries(${TARGET_NAME} Winmm Ws2_32)
|
||||
ENDIF(WIN32)
|
||||
|
||||
# link QtNetwork and GnuTLS
|
||||
target_link_libraries(${TARGET_NAME} Qt5::Network "${GNUTLS_LIBRARY}")
|
||||
# link QtNetwork
|
||||
target_link_libraries(${TARGET_NAME} Qt5::Network)
|
||||
|
||||
# add a definition for ssize_t so that windows doesn't bail
|
||||
if (WIN32)
|
||||
add_definitions(-Dssize_t=long)
|
||||
endif ()
|
|
@ -1,18 +0,0 @@
|
|||
//
|
||||
// DTLSServerSession.cpp
|
||||
// domain-server/src
|
||||
//
|
||||
// Created by Stephen Birarda on 2014-04-01.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "DTLSServerSession.h"
|
||||
|
||||
DTLSServerSession::DTLSServerSession(QUdpSocket& dtlsSocket, HifiSockAddr& destinationSocket) :
|
||||
DTLSSession(GNUTLS_SERVER, dtlsSocket, destinationSocket)
|
||||
{
|
||||
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
//
|
||||
// DTLSServerSession.h
|
||||
// domain-server/src
|
||||
//
|
||||
// Created by Stephen Birarda on 2014-04-01.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#ifndef hifi_DTLSServerSession_h
|
||||
#define hifi_DTLSServerSession_h
|
||||
|
||||
#include <gnutls/dtls.h>
|
||||
|
||||
#include <DTLSSession.h>
|
||||
|
||||
class DTLSServerSession : public DTLSSession {
|
||||
public:
|
||||
DTLSServerSession(QUdpSocket& dtlsSocket, HifiSockAddr& destinationSocket);
|
||||
};
|
||||
|
||||
#endif // hifi_DTLSServerSession_h
|
|
@ -18,8 +18,6 @@
|
|||
#include <QtCore/QTimer>
|
||||
#include <QtCore/QUrlQuery>
|
||||
|
||||
#include <gnutls/dtls.h>
|
||||
|
||||
#include <AccountManager.h>
|
||||
#include <HifiConfigVariantMap.h>
|
||||
#include <HTTPConnection.h>
|
||||
|
@ -28,7 +26,6 @@
|
|||
#include <UUID.h>
|
||||
|
||||
#include "DomainServerNodeData.h"
|
||||
#include "DummyDTLSSession.h"
|
||||
|
||||
#include "DomainServer.h"
|
||||
|
||||
|
@ -39,18 +36,12 @@ DomainServer::DomainServer(int argc, char* argv[]) :
|
|||
_allAssignments(),
|
||||
_unfulfilledAssignments(),
|
||||
_isUsingDTLS(false),
|
||||
_x509Credentials(NULL),
|
||||
_dhParams(NULL),
|
||||
_priorityCache(NULL),
|
||||
_dtlsSessions(),
|
||||
_oauthProviderURL(),
|
||||
_oauthClientID(),
|
||||
_hostname(),
|
||||
_networkReplyUUIDMap(),
|
||||
_sessionAuthenticationHash()
|
||||
{
|
||||
gnutls_global_init();
|
||||
|
||||
setOrganizationName("High Fidelity");
|
||||
setOrganizationDomain("highfidelity.io");
|
||||
setApplicationName("domain-server");
|
||||
|
@ -64,31 +55,10 @@ DomainServer::DomainServer(int argc, char* argv[]) :
|
|||
qDebug() << "Setting up LimitedNodeList and assignments.";
|
||||
setupNodeListAndAssignments();
|
||||
|
||||
if (_isUsingDTLS) {
|
||||
LimitedNodeList* nodeList = LimitedNodeList::getInstance();
|
||||
|
||||
// connect our socket to read datagrams received on the DTLS socket
|
||||
connect(&nodeList->getDTLSSocket(), &QUdpSocket::readyRead, this, &DomainServer::readAvailableDTLSDatagrams);
|
||||
}
|
||||
|
||||
_networkAccessManager = new QNetworkAccessManager(this);
|
||||
}
|
||||
}
|
||||
|
||||
DomainServer::~DomainServer() {
|
||||
if (_x509Credentials) {
|
||||
gnutls_certificate_free_credentials(*_x509Credentials);
|
||||
gnutls_priority_deinit(*_priorityCache);
|
||||
gnutls_dh_params_deinit(*_dhParams);
|
||||
|
||||
delete _x509Credentials;
|
||||
delete _priorityCache;
|
||||
delete _dhParams;
|
||||
delete _cookieKey;
|
||||
}
|
||||
gnutls_global_deinit();
|
||||
}
|
||||
|
||||
bool DomainServer::optionallyReadX509KeyAndCertificate() {
|
||||
const QString X509_CERTIFICATE_OPTION = "cert";
|
||||
const QString X509_PRIVATE_KEY_OPTION = "key";
|
||||
|
@ -100,28 +70,28 @@ bool DomainServer::optionallyReadX509KeyAndCertificate() {
|
|||
if (!certPath.isEmpty() && !keyPath.isEmpty()) {
|
||||
// the user wants to use DTLS to encrypt communication with nodes
|
||||
// let's make sure we can load the key and certificate
|
||||
_x509Credentials = new gnutls_certificate_credentials_t;
|
||||
gnutls_certificate_allocate_credentials(_x509Credentials);
|
||||
// _x509Credentials = new gnutls_certificate_credentials_t;
|
||||
// gnutls_certificate_allocate_credentials(_x509Credentials);
|
||||
|
||||
QString keyPassphraseString = QProcessEnvironment::systemEnvironment().value(X509_KEY_PASSPHRASE_ENV);
|
||||
|
||||
qDebug() << "Reading certificate file at" << certPath << "for DTLS.";
|
||||
qDebug() << "Reading key file at" << keyPath << "for DTLS.";
|
||||
|
||||
int gnutlsReturn = gnutls_certificate_set_x509_key_file2(*_x509Credentials,
|
||||
certPath.toLocal8Bit().constData(),
|
||||
keyPath.toLocal8Bit().constData(),
|
||||
GNUTLS_X509_FMT_PEM,
|
||||
keyPassphraseString.toLocal8Bit().constData(),
|
||||
0);
|
||||
// int gnutlsReturn = gnutls_certificate_set_x509_key_file2(*_x509Credentials,
|
||||
// certPath.toLocal8Bit().constData(),
|
||||
// keyPath.toLocal8Bit().constData(),
|
||||
// GNUTLS_X509_FMT_PEM,
|
||||
// keyPassphraseString.toLocal8Bit().constData(),
|
||||
// 0);
|
||||
//
|
||||
// if (gnutlsReturn < 0) {
|
||||
// qDebug() << "Unable to load certificate or key file." << "Error" << gnutlsReturn << "- domain-server will now quit.";
|
||||
// QMetaObject::invokeMethod(this, "quit", Qt::QueuedConnection);
|
||||
// return false;
|
||||
// }
|
||||
|
||||
if (gnutlsReturn < 0) {
|
||||
qDebug() << "Unable to load certificate or key file." << "Error" << gnutlsReturn << "- domain-server will now quit.";
|
||||
QMetaObject::invokeMethod(this, "quit", Qt::QueuedConnection);
|
||||
return false;
|
||||
}
|
||||
|
||||
qDebug() << "Successfully read certificate and private key.";
|
||||
// qDebug() << "Successfully read certificate and private key.";
|
||||
|
||||
// we need to also pass this certificate and private key to the HTTPS manager
|
||||
// this is used for Oauth callbacks when authorizing users against a data server
|
||||
|
@ -176,39 +146,6 @@ bool DomainServer::optionallySetupOAuth() {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool DomainServer::optionallySetupDTLS() {
|
||||
if (_x509Credentials) {
|
||||
qDebug() << "Generating Diffie-Hellman parameters.";
|
||||
|
||||
// generate Diffie-Hellman parameters
|
||||
// When short bit length is used, it might be wise to regenerate parameters often.
|
||||
int dhBits = gnutls_sec_param_to_pk_bits(GNUTLS_PK_DH, GNUTLS_SEC_PARAM_LEGACY);
|
||||
|
||||
_dhParams = new gnutls_dh_params_t;
|
||||
gnutls_dh_params_init(_dhParams);
|
||||
gnutls_dh_params_generate2(*_dhParams, dhBits);
|
||||
|
||||
qDebug() << "Successfully generated Diffie-Hellman parameters.";
|
||||
|
||||
// set the D-H paramters on the X509 credentials
|
||||
gnutls_certificate_set_dh_params(*_x509Credentials, *_dhParams);
|
||||
|
||||
// setup the key used for cookie verification
|
||||
_cookieKey = new gnutls_datum_t;
|
||||
gnutls_key_generate(_cookieKey, GNUTLS_COOKIE_KEY_SIZE);
|
||||
|
||||
_priorityCache = new gnutls_priority_t;
|
||||
const char DTLS_PRIORITY_STRING[] = "PERFORMANCE:-VERS-TLS-ALL:+VERS-DTLS1.2:%SERVER_PRECEDENCE";
|
||||
gnutls_priority_init(_priorityCache, DTLS_PRIORITY_STRING, NULL);
|
||||
|
||||
_isUsingDTLS = true;
|
||||
|
||||
qDebug() << "Initial DTLS setup complete.";
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void DomainServer::setupNodeListAndAssignments(const QUuid& sessionUUID) {
|
||||
|
||||
const QString CUSTOM_PORT_OPTION = "port";
|
||||
|
@ -552,8 +489,8 @@ void DomainServer::sendDomainListToNode(const SharedNodePointer& node, const Hif
|
|||
|
||||
if (nodeInterestList.size() > 0) {
|
||||
|
||||
DTLSServerSession* dtlsSession = _isUsingDTLS ? _dtlsSessions[senderSockAddr] : NULL;
|
||||
int dataMTU = dtlsSession ? (int)gnutls_dtls_get_data_mtu(*dtlsSession->getGnuTLSSession()) : MAX_PACKET_SIZE;
|
||||
// DTLSServerSession* dtlsSession = _isUsingDTLS ? _dtlsSessions[senderSockAddr] : NULL;
|
||||
int dataMTU = MAX_PACKET_SIZE;
|
||||
|
||||
if (nodeData->isAuthenticated()) {
|
||||
// if this authenticated node has any interest types, send back those nodes as well
|
||||
|
@ -589,11 +526,7 @@ void DomainServer::sendDomainListToNode(const SharedNodePointer& node, const Hif
|
|||
// we need to break here and start a new packet
|
||||
// so send the current one
|
||||
|
||||
if (!dtlsSession) {
|
||||
nodeList->writeDatagram(broadcastPacket, node, senderSockAddr);
|
||||
} else {
|
||||
dtlsSession->writeDatagram(broadcastPacket);
|
||||
}
|
||||
nodeList->writeDatagram(broadcastPacket, node, senderSockAddr);
|
||||
|
||||
// reset the broadcastPacket structure
|
||||
broadcastPacket.resize(numBroadcastPacketLeadBytes);
|
||||
|
@ -607,11 +540,7 @@ void DomainServer::sendDomainListToNode(const SharedNodePointer& node, const Hif
|
|||
}
|
||||
|
||||
// always write the last broadcastPacket
|
||||
if (!dtlsSession) {
|
||||
nodeList->writeDatagram(broadcastPacket, node, senderSockAddr);
|
||||
} else {
|
||||
dtlsSession->writeDatagram(broadcastPacket);
|
||||
}
|
||||
nodeList->writeDatagram(broadcastPacket, node, senderSockAddr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -689,86 +618,6 @@ void DomainServer::readAvailableDatagrams() {
|
|||
}
|
||||
}
|
||||
|
||||
void DomainServer::readAvailableDTLSDatagrams() {
|
||||
LimitedNodeList* nodeList = LimitedNodeList::getInstance();
|
||||
|
||||
QUdpSocket& dtlsSocket = nodeList->getDTLSSocket();
|
||||
|
||||
static sockaddr senderSockAddr;
|
||||
static socklen_t sockAddrSize = sizeof(senderSockAddr);
|
||||
|
||||
while (dtlsSocket.hasPendingDatagrams()) {
|
||||
// check if we have an active DTLS session for this sender
|
||||
QByteArray peekDatagram(dtlsSocket.pendingDatagramSize(), 0);
|
||||
|
||||
recvfrom(dtlsSocket.socketDescriptor(), peekDatagram.data(), dtlsSocket.pendingDatagramSize(),
|
||||
MSG_PEEK, &senderSockAddr, &sockAddrSize);
|
||||
|
||||
HifiSockAddr senderHifiSockAddr(&senderSockAddr);
|
||||
DTLSServerSession* existingSession = _dtlsSessions.value(senderHifiSockAddr);
|
||||
|
||||
if (existingSession) {
|
||||
if (!existingSession->completedHandshake()) {
|
||||
// check if we have completed handshake with this user
|
||||
int handshakeReturn = gnutls_handshake(*existingSession->getGnuTLSSession());
|
||||
|
||||
if (handshakeReturn == 0) {
|
||||
existingSession->setCompletedHandshake(true);
|
||||
} else if (gnutls_error_is_fatal(handshakeReturn)) {
|
||||
// this was a fatal error handshaking, so remove this session
|
||||
qDebug() << "Fatal error -" << gnutls_strerror(handshakeReturn) << "- during DTLS handshake with"
|
||||
<< senderHifiSockAddr;
|
||||
_dtlsSessions.remove(senderHifiSockAddr);
|
||||
}
|
||||
} else {
|
||||
// pull the data from this user off the stack and process it
|
||||
int receivedBytes = gnutls_record_recv(*existingSession->getGnuTLSSession(),
|
||||
peekDatagram.data(), peekDatagram.size());
|
||||
if (receivedBytes > 0) {
|
||||
processDatagram(peekDatagram.left(receivedBytes), senderHifiSockAddr);
|
||||
} else if (gnutls_error_is_fatal(receivedBytes)) {
|
||||
qDebug() << "Fatal error -" << gnutls_strerror(receivedBytes) << "- during DTLS handshake with"
|
||||
<< senderHifiSockAddr;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// first we verify the cookie
|
||||
// see http://gnutls.org/manual/html_node/DTLS-sessions.html for why this is required
|
||||
gnutls_dtls_prestate_st prestate;
|
||||
memset(&prestate, 0, sizeof(prestate));
|
||||
int cookieValid = gnutls_dtls_cookie_verify(_cookieKey, &senderSockAddr, sizeof(senderSockAddr),
|
||||
peekDatagram.data(), peekDatagram.size(), &prestate);
|
||||
|
||||
if (cookieValid < 0) {
|
||||
// the cookie sent by the client was not valid
|
||||
// send a valid one
|
||||
DummyDTLSSession tempServerSession(LimitedNodeList::getInstance()->getDTLSSocket(), senderHifiSockAddr);
|
||||
|
||||
gnutls_dtls_cookie_send(_cookieKey, &senderSockAddr, sizeof(senderSockAddr), &prestate,
|
||||
&tempServerSession, DTLSSession::socketPush);
|
||||
|
||||
// acutally pull the peeked data off the network stack so that it gets discarded
|
||||
dtlsSocket.readDatagram(peekDatagram.data(), peekDatagram.size());
|
||||
} else {
|
||||
// cookie valid but no existing session - set up a new session now
|
||||
DTLSServerSession* newServerSession = new DTLSServerSession(LimitedNodeList::getInstance()->getDTLSSocket(),
|
||||
senderHifiSockAddr);
|
||||
gnutls_session_t* gnutlsSession = newServerSession->getGnuTLSSession();
|
||||
|
||||
gnutls_priority_set(*gnutlsSession, *_priorityCache);
|
||||
gnutls_credentials_set(*gnutlsSession, GNUTLS_CRD_CERTIFICATE, *_x509Credentials);
|
||||
gnutls_dtls_prestate_set(*gnutlsSession, &prestate);
|
||||
|
||||
// handshake to begin the session
|
||||
gnutls_handshake(*gnutlsSession);
|
||||
|
||||
qDebug() << "Beginning DTLS session with node at" << senderHifiSockAddr;
|
||||
_dtlsSessions[senderHifiSockAddr] = newServerSession;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DomainServer::processDatagram(const QByteArray& receivedPacket, const HifiSockAddr& senderSockAddr) {
|
||||
LimitedNodeList* nodeList = LimitedNodeList::getInstance();
|
||||
|
||||
|
@ -1210,14 +1059,6 @@ void DomainServer::nodeKilled(SharedNodePointer node) {
|
|||
reinterpret_cast<DomainServerNodeData*>(otherNode->getLinkedData())->getSessionSecretHash().remove(node->getUUID());
|
||||
}
|
||||
}
|
||||
|
||||
if (_isUsingDTLS) {
|
||||
// check if we need to remove a DTLS session from our in-memory hash
|
||||
DTLSServerSession* existingSession = _dtlsSessions.take(nodeData->getSendingSockAddr());
|
||||
if (existingSession) {
|
||||
delete existingSession;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,21 +20,16 @@
|
|||
#include <QtCore/QStringList>
|
||||
#include <QtCore/QUrl>
|
||||
|
||||
#include <gnutls/gnutls.h>
|
||||
|
||||
#include <Assignment.h>
|
||||
#include <HTTPSConnection.h>
|
||||
#include <LimitedNodeList.h>
|
||||
|
||||
#include "DTLSServerSession.h"
|
||||
|
||||
typedef QSharedPointer<Assignment> SharedAssignmentPointer;
|
||||
|
||||
class DomainServer : public QCoreApplication, public HTTPSRequestHandler {
|
||||
Q_OBJECT
|
||||
public:
|
||||
DomainServer(int argc, char* argv[]);
|
||||
~DomainServer();
|
||||
|
||||
bool handleHTTPRequest(HTTPConnection* connection, const QUrl& url);
|
||||
bool handleHTTPSRequest(HTTPSConnection* connection, const QUrl& url);
|
||||
|
@ -50,11 +45,9 @@ public slots:
|
|||
private slots:
|
||||
|
||||
void readAvailableDatagrams();
|
||||
void readAvailableDTLSDatagrams();
|
||||
private:
|
||||
void setupNodeListAndAssignments(const QUuid& sessionUUID = QUuid::createUuid());
|
||||
bool optionallySetupOAuth();
|
||||
bool optionallySetupDTLS();
|
||||
bool optionallyReadX509KeyAndCertificate();
|
||||
|
||||
void processDatagram(const QByteArray& receivedPacket, const HifiSockAddr& senderSockAddr);
|
||||
|
@ -96,12 +89,6 @@ private:
|
|||
QVariantMap _argumentVariantMap;
|
||||
|
||||
bool _isUsingDTLS;
|
||||
gnutls_certificate_credentials_t* _x509Credentials;
|
||||
gnutls_dh_params_t* _dhParams;
|
||||
gnutls_datum_t* _cookieKey;
|
||||
gnutls_priority_t* _priorityCache;
|
||||
|
||||
QHash<HifiSockAddr, DTLSServerSession*> _dtlsSessions;
|
||||
|
||||
QNetworkAccessManager* _networkAccessManager;
|
||||
|
||||
|
|
|
@ -21,9 +21,9 @@ var roll = 0.0;
|
|||
var rotation = Quat.fromPitchYawRollDegrees(pitch, yaw, roll)
|
||||
|
||||
var originalProperties = {
|
||||
position: { x: 10,
|
||||
y: 0,
|
||||
z: 0 },
|
||||
position: { x: MyAvatar.position.x,
|
||||
y: MyAvatar.position.y,
|
||||
z: MyAvatar.position.z },
|
||||
|
||||
radius : 1,
|
||||
|
||||
|
@ -56,11 +56,11 @@ function moveModel(deltaTime) {
|
|||
|
||||
if (count % adjustFPSEveryWhile == 0) {
|
||||
if (animationFPS == 30) {
|
||||
animationFPS = 10;
|
||||
} else if (animationFPS == 10) {
|
||||
animationFPS = 60;
|
||||
} else if (animationFPS == 60) {
|
||||
animationFPS = 30;
|
||||
} else if (animationFPS == 10) {
|
||||
animationFPS = 10;
|
||||
} else if (animationFPS == 60) {
|
||||
animationFPS = 60;
|
||||
}
|
||||
print("animationFPS=" + animationFPS);
|
||||
isPlaying = true;
|
||||
|
|
|
@ -25,7 +25,7 @@ function printVector(string, vector) {
|
|||
}
|
||||
|
||||
var CHANCE_OF_MOVING = 0.005;
|
||||
var CHANCE_OF_SOUND = 0.000;
|
||||
var CHANCE_OF_SOUND = 0.005;
|
||||
var CHANCE_OF_HEAD_TURNING = 0.05;
|
||||
var CHANCE_OF_BIG_MOVE = 0.1;
|
||||
var CHANCE_OF_WAVING = 0.009;
|
||||
|
@ -41,11 +41,11 @@ var isWaving = false;
|
|||
var waveFrequency = 0.0;
|
||||
var waveAmplitude = 0.0;
|
||||
|
||||
var X_MIN = 20.0;
|
||||
var X_MAX = 25.0;
|
||||
var Z_MIN = 20.0;
|
||||
var Z_MAX = 25.0;
|
||||
var Y_PELVIS = 2.5;
|
||||
var X_MIN = 5.0;
|
||||
var X_MAX = 15.0;
|
||||
var Z_MIN = 5.0;
|
||||
var Z_MAX = 15.0;
|
||||
var Y_PELVIS = 1.0;
|
||||
var SPINE_JOINT_NUMBER = 13;
|
||||
var SHOULDER_JOINT_NUMBER = 17;
|
||||
var ELBOW_JOINT_NUMBER = 18;
|
||||
|
|
|
@ -76,50 +76,59 @@ function controller(wichSide) {
|
|||
this.oldModelRadius;
|
||||
|
||||
this.laser = Overlays.addOverlay("line3d", {
|
||||
position: this.palmPosition,
|
||||
end: this.tipPosition,
|
||||
position: { x: 0, y: 0, z: 0 },
|
||||
end: { x: 0, y: 0, z: 0 },
|
||||
color: LASER_COLOR,
|
||||
alpha: 1,
|
||||
visible: false,
|
||||
lineWidth: LASER_WIDTH
|
||||
lineWidth: LASER_WIDTH,
|
||||
anchor: "MyAvatar"
|
||||
});
|
||||
|
||||
this.guideScale = 0.02;
|
||||
this.ball = Overlays.addOverlay("sphere", {
|
||||
position: this.palmPosition,
|
||||
position: { x: 0, y: 0, z: 0 },
|
||||
size: this.guideScale,
|
||||
solid: true,
|
||||
color: { red: 0, green: 255, blue: 0 },
|
||||
alpha: 1,
|
||||
visible: false,
|
||||
anchor: "MyAvatar"
|
||||
});
|
||||
this.leftRight = Overlays.addOverlay("line3d", {
|
||||
position: this.palmPosition,
|
||||
end: this.tipPosition,
|
||||
position: { x: 0, y: 0, z: 0 },
|
||||
end: { x: 0, y: 0, z: 0 },
|
||||
color: { red: 0, green: 0, blue: 255 },
|
||||
alpha: 1,
|
||||
visible: false,
|
||||
lineWidth: LASER_WIDTH
|
||||
lineWidth: LASER_WIDTH,
|
||||
anchor: "MyAvatar"
|
||||
});
|
||||
this.topDown = Overlays.addOverlay("line3d", {
|
||||
position: this.palmPosition,
|
||||
end: this.tipPosition,
|
||||
position: { x: 0, y: 0, z: 0 },
|
||||
end: { x: 0, y: 0, z: 0 },
|
||||
color: { red: 0, green: 0, blue: 255 },
|
||||
alpha: 1,
|
||||
visible: false,
|
||||
lineWidth: LASER_WIDTH
|
||||
lineWidth: LASER_WIDTH,
|
||||
anchor: "MyAvatar"
|
||||
});
|
||||
|
||||
|
||||
|
||||
this.grab = function (modelID, properties) {
|
||||
print("Grabbing " + modelID.id);
|
||||
this.grabbing = true;
|
||||
this.modelID = modelID;
|
||||
if (this.isLocked(properties)) {
|
||||
print("Model locked " + modelID.id);
|
||||
} else {
|
||||
print("Grabbing " + modelID.id);
|
||||
|
||||
this.oldModelPosition = properties.position;
|
||||
this.oldModelRotation = properties.modelRotation;
|
||||
this.oldModelRadius = properties.radius;
|
||||
this.grabbing = true;
|
||||
this.modelID = modelID;
|
||||
|
||||
this.oldModelPosition = properties.position;
|
||||
this.oldModelRotation = properties.modelRotation;
|
||||
this.oldModelRadius = properties.radius;
|
||||
}
|
||||
}
|
||||
|
||||
this.release = function () {
|
||||
|
@ -140,8 +149,23 @@ function controller(wichSide) {
|
|||
this.pressed = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
this.isLocked = function (properties) {
|
||||
// special case to lock the ground plane model in hq.
|
||||
if (location.hostname == "hq.highfidelity.io" &&
|
||||
properties.modelURL == "https://s3-us-west-1.amazonaws.com/highfidelity-public/ozan/Terrain_Reduce_forAlpha.fbx") {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
this.checkModel = function (properties) {
|
||||
// special case to lock the ground plane model in hq.
|
||||
if (this.isLocked(properties)) {
|
||||
return { valid: false };
|
||||
}
|
||||
|
||||
|
||||
// P P - Model
|
||||
// /| A - Palm
|
||||
// / | d B - unit vector toward tip
|
||||
|
@ -170,10 +194,17 @@ function controller(wichSide) {
|
|||
}
|
||||
|
||||
this.moveLaser = function () {
|
||||
var endPosition = Vec3.sum(this.palmPosition, Vec3.multiply(this.front, LASER_LENGTH_FACTOR));
|
||||
// the overlays here are anchored to the avatar, which means they are specified in the avatar's local frame
|
||||
|
||||
var inverseRotation = Quat.inverse(MyAvatar.orientation);
|
||||
var startPosition = Vec3.multiplyQbyV(inverseRotation, Vec3.subtract(this.palmPosition, MyAvatar.position));
|
||||
var direction = Vec3.multiplyQbyV(inverseRotation, Vec3.subtract(this.tipPosition, this.palmPosition));
|
||||
var distance = Vec3.length(direction);
|
||||
direction = Vec3.multiply(direction, LASER_LENGTH_FACTOR / distance);
|
||||
var endPosition = Vec3.sum(startPosition, direction);
|
||||
|
||||
Overlays.editOverlay(this.laser, {
|
||||
position: this.palmPosition,
|
||||
position: startPosition,
|
||||
end: endPosition,
|
||||
visible: true
|
||||
});
|
||||
|
@ -219,11 +250,11 @@ function controller(wichSide) {
|
|||
position: newPosition,
|
||||
modelRotation: newRotation
|
||||
});
|
||||
print("Moving " + this.modelID.id);
|
||||
// print("Moving " + this.modelID.id);
|
||||
// Vec3.print("Old Position: ", this.oldModelPosition);
|
||||
// Vec3.print("Sav Position: ", newPosition);
|
||||
Quat.print("Old Rotation: ", this.oldModelRotation);
|
||||
Quat.print("New Rotation: ", newRotation);
|
||||
// Quat.print("Old Rotation: ", this.oldModelRotation);
|
||||
// Quat.print("New Rotation: ", newRotation);
|
||||
|
||||
this.oldModelRotation = newRotation;
|
||||
this.oldModelPosition = newPosition;
|
||||
|
@ -274,15 +305,18 @@ function controller(wichSide) {
|
|||
}
|
||||
|
||||
var properties = Models.getModelProperties(foundModels[i]);
|
||||
print("Checking properties: " + properties.id + " " + properties.isKnownID);
|
||||
|
||||
var check = this.checkModel(properties);
|
||||
if (check.valid) {
|
||||
this.grab(foundModels[i], properties);
|
||||
this.x = check.x;
|
||||
this.y = check.y;
|
||||
this.z = check.z;
|
||||
return;
|
||||
if (this.isLocked(properties)) {
|
||||
print("Model locked " + properties.id);
|
||||
} else {
|
||||
print("Checking properties: " + properties.id + " " + properties.isKnownID);
|
||||
var check = this.checkModel(properties);
|
||||
if (check.valid) {
|
||||
this.grab(foundModels[i], properties);
|
||||
this.x = check.x;
|
||||
this.y = check.y;
|
||||
this.z = check.z;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -301,7 +335,7 @@ var rightController = new controller(RIGHT);
|
|||
|
||||
function moveModels() {
|
||||
if (leftController.grabbing && rightController.grabbing && rightController.modelID.id == leftController.modelID.id) {
|
||||
print("Both controllers");
|
||||
//print("Both controllers");
|
||||
var oldLeftPoint = Vec3.sum(leftController.oldPalmPosition, Vec3.multiply(leftController.oldFront, leftController.x));
|
||||
var oldRightPoint = Vec3.sum(rightController.oldPalmPosition, Vec3.multiply(rightController.oldFront, rightController.x));
|
||||
|
||||
|
@ -319,7 +353,7 @@ function moveModels() {
|
|||
|
||||
var newPosition = Vec3.sum(middle,
|
||||
Vec3.multiply(Vec3.subtract(leftController.oldModelPosition, oldMiddle), ratio));
|
||||
Vec3.print("Ratio : " + ratio + " New position: ", newPosition);
|
||||
//Vec3.print("Ratio : " + ratio + " New position: ", newPosition);
|
||||
var rotation = Quat.multiply(leftController.rotation,
|
||||
Quat.inverse(leftController.oldRotation));
|
||||
rotation = Quat.multiply(rotation, leftController.oldModelRotation);
|
||||
|
@ -452,51 +486,54 @@ function mousePressEvent(event) {
|
|||
}
|
||||
|
||||
var properties = Models.getModelProperties(foundModels[i]);
|
||||
print("Checking properties: " + properties.id + " " + properties.isKnownID);
|
||||
if (this.isLocked(properties)) {
|
||||
print("Model locked " + properties.id);
|
||||
} else {
|
||||
print("Checking properties: " + properties.id + " " + properties.isKnownID);
|
||||
// P P - Model
|
||||
// /| A - Palm
|
||||
// / | d B - unit vector toward tip
|
||||
// / | X - base of the perpendicular line
|
||||
// A---X----->B d - distance fom axis
|
||||
// x x - distance from A
|
||||
//
|
||||
// |X-A| = (P-A).B
|
||||
// X == A + ((P-A).B)B
|
||||
// d = |P-X|
|
||||
|
||||
// P P - Model
|
||||
// /| A - Palm
|
||||
// / | d B - unit vector toward tip
|
||||
// / | X - base of the perpendicular line
|
||||
// A---X----->B d - distance fom axis
|
||||
// x x - distance from A
|
||||
//
|
||||
// |X-A| = (P-A).B
|
||||
// X == A + ((P-A).B)B
|
||||
// d = |P-X|
|
||||
var A = pickRay.origin;
|
||||
var B = Vec3.normalize(pickRay.direction);
|
||||
var P = properties.position;
|
||||
|
||||
var A = pickRay.origin;
|
||||
var B = Vec3.normalize(pickRay.direction);
|
||||
var P = properties.position;
|
||||
var x = Vec3.dot(Vec3.subtract(P, A), B);
|
||||
var X = Vec3.sum(A, Vec3.multiply(B, x));
|
||||
var d = Vec3.length(Vec3.subtract(P, X));
|
||||
|
||||
var x = Vec3.dot(Vec3.subtract(P, A), B);
|
||||
var X = Vec3.sum(A, Vec3.multiply(B, x));
|
||||
var d = Vec3.length(Vec3.subtract(P, X));
|
||||
|
||||
if (d < properties.radius && 0 < x && x < LASER_LENGTH_FACTOR) {
|
||||
modelSelected = true;
|
||||
selectedModelID = foundModels[i];
|
||||
selectedModelProperties = properties;
|
||||
if (d < properties.radius && 0 < x && x < LASER_LENGTH_FACTOR) {
|
||||
modelSelected = true;
|
||||
selectedModelID = foundModels[i];
|
||||
selectedModelProperties = properties;
|
||||
|
||||
selectedModelProperties.oldRadius = selectedModelProperties.radius;
|
||||
selectedModelProperties.oldPosition = {
|
||||
x: selectedModelProperties.position.x,
|
||||
y: selectedModelProperties.position.y,
|
||||
z: selectedModelProperties.position.z,
|
||||
};
|
||||
selectedModelProperties.oldRotation = {
|
||||
x: selectedModelProperties.modelRotation.x,
|
||||
y: selectedModelProperties.modelRotation.y,
|
||||
z: selectedModelProperties.modelRotation.z,
|
||||
w: selectedModelProperties.modelRotation.w,
|
||||
};
|
||||
selectedModelProperties.oldRadius = selectedModelProperties.radius;
|
||||
selectedModelProperties.oldPosition = {
|
||||
x: selectedModelProperties.position.x,
|
||||
y: selectedModelProperties.position.y,
|
||||
z: selectedModelProperties.position.z,
|
||||
};
|
||||
selectedModelProperties.oldRotation = {
|
||||
x: selectedModelProperties.modelRotation.x,
|
||||
y: selectedModelProperties.modelRotation.y,
|
||||
z: selectedModelProperties.modelRotation.z,
|
||||
w: selectedModelProperties.modelRotation.w,
|
||||
};
|
||||
|
||||
|
||||
orientation = MyAvatar.orientation;
|
||||
intersection = rayPlaneIntersection(pickRay, P, Quat.getFront(orientation));
|
||||
print("Clicked on " + selectedModelID.id + " " + modelSelected);
|
||||
orientation = MyAvatar.orientation;
|
||||
intersection = rayPlaneIntersection(pickRay, P, Quat.getFront(orientation));
|
||||
|
||||
return;
|
||||
print("Clicked on " + selectedModelID.id + " " + modelSelected);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ var impactSound = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-pub
|
|||
var targetHitSound = new Sound("http://highfidelity-public.s3-us-west-1.amazonaws.com/sounds/Space%20Invaders/hit.raw");
|
||||
var targetLaunchSound = new Sound("http://highfidelity-public.s3-us-west-1.amazonaws.com/sounds/Space%20Invaders/shoot.raw");
|
||||
|
||||
var gunModel = "http://highfidelity-public.s3-us-west-1.amazonaws.com/models/attachments/Raygun2.fst";
|
||||
var gunModel = "http://public.highfidelity.io/models/attachments/HaloGun.fst";
|
||||
|
||||
var audioOptions = new AudioInjectionOptions();
|
||||
audioOptions.volume = 0.9;
|
||||
|
@ -199,7 +199,7 @@ function playLoadSound() {
|
|||
Audio.playSound(loadSound, audioOptions);
|
||||
}
|
||||
|
||||
MyAvatar.attach(gunModel, "RightHand", {x: -0.02, y: -.14, z: 0.07}, Quat.fromPitchYawRollDegrees(-70, -151, 72), 0.20);
|
||||
//MyAvatar.attach(gunModel, "RightHand", {x: -0.02, y: -.14, z: 0.07}, Quat.fromPitchYawRollDegrees(-70, -151, 72), 0.20);
|
||||
MyAvatar.attach(gunModel, "LeftHand", {x: -0.02, y: -.14, z: 0.07}, Quat.fromPitchYawRollDegrees(-70, -151, 72), 0.20);
|
||||
|
||||
// Give a bit of time to load before playing sound
|
||||
|
@ -320,7 +320,6 @@ function scriptEnding() {
|
|||
Overlays.deleteOverlay(reticle);
|
||||
Overlays.deleteOverlay(text);
|
||||
MyAvatar.detachOne(gunModel);
|
||||
MyAvatar.detachOne(gunModel);
|
||||
}
|
||||
|
||||
Particles.particleCollisionWithVoxel.connect(particleCollisionWithVoxel);
|
||||
|
|
|
@ -50,6 +50,13 @@ var LEFT_BUTTON_4 = 4;
|
|||
var RIGHT_PALM = 2;
|
||||
var RIGHT_BUTTON_4 = 10;
|
||||
|
||||
|
||||
function printVector(text, v, decimals) {
|
||||
print(text + " " + v.x.toFixed(decimals) + ", " + v.y.toFixed(decimals) + ", " + v.z.toFixed(decimals));
|
||||
}
|
||||
|
||||
var debug = false;
|
||||
|
||||
// Used by handleGrabBehavior() for managing the grab position changes
|
||||
function getAndResetGrabDelta() {
|
||||
var HAND_GRAB_SCALE_DISTANCE = 2.0;
|
||||
|
@ -60,24 +67,12 @@ function getAndResetGrabDelta() {
|
|||
return result;
|
||||
}
|
||||
|
||||
// Used by handleGrabBehavior() for managing the grab velocity feature
|
||||
function getAndResetGrabDeltaVelocity() {
|
||||
var HAND_GRAB_SCALE_VELOCITY = 50.0;
|
||||
var delta = Vec3.multiply(grabDeltaVelocity, (MyAvatar.scale * HAND_GRAB_SCALE_VELOCITY));
|
||||
grabDeltaVelocity = { x: 0, y: 0, z: 0};
|
||||
var avatarRotation = MyAvatar.orientation;
|
||||
var result = Quat.multiply(avatarRotation, Vec3.multiply(delta, -1));
|
||||
return result;
|
||||
}
|
||||
|
||||
// Used by handleGrabBehavior() for managing the grab rotation feature
|
||||
function getAndResetGrabRotation() {
|
||||
function getGrabRotation() {
|
||||
var quatDiff = Quat.multiply(grabCurrentRotation, Quat.inverse(grabStartRotation));
|
||||
grabStartRotation = grabCurrentRotation;
|
||||
return quatDiff;
|
||||
}
|
||||
|
||||
// handles all the grab related behavior: position (crawl), velocity (flick), and rotate (twist)
|
||||
// When move button is pressed, process results
|
||||
function handleGrabBehavior(deltaTime) {
|
||||
// check for and handle grab behaviors
|
||||
grabbingWithRightHand = Controller.isButtonPressed(RIGHT_BUTTON_4);
|
||||
|
@ -88,9 +83,11 @@ function handleGrabBehavior(deltaTime) {
|
|||
if (grabbingWithRightHand && !wasGrabbingWithRightHand) {
|
||||
// Just starting grab, capture starting rotation
|
||||
grabStartRotation = Controller.getSpatialControlRawRotation(RIGHT_PALM);
|
||||
grabStartPosition = Controller.getSpatialControlPosition(RIGHT_PALM);
|
||||
if (debug) printVector("start position", grabStartPosition, 3);
|
||||
}
|
||||
if (grabbingWithRightHand) {
|
||||
grabDelta = Vec3.sum(grabDelta, Vec3.multiply(Controller.getSpatialControlVelocity(RIGHT_PALM), deltaTime));
|
||||
grabDelta = Vec3.subtract(Controller.getSpatialControlPosition(RIGHT_PALM), grabStartPosition);
|
||||
grabCurrentRotation = Controller.getSpatialControlRawRotation(RIGHT_PALM);
|
||||
}
|
||||
if (!grabbingWithRightHand && wasGrabbingWithRightHand) {
|
||||
|
@ -102,10 +99,12 @@ function handleGrabBehavior(deltaTime) {
|
|||
if (grabbingWithLeftHand && !wasGrabbingWithLeftHand) {
|
||||
// Just starting grab, capture starting rotation
|
||||
grabStartRotation = Controller.getSpatialControlRawRotation(LEFT_PALM);
|
||||
grabStartPosition = Controller.getSpatialControlPosition(LEFT_PALM);
|
||||
if (debug) printVector("start position", grabStartPosition, 3);
|
||||
}
|
||||
|
||||
if (grabbingWithLeftHand) {
|
||||
grabDelta = Vec3.sum(grabDelta, Vec3.multiply(Controller.getSpatialControlVelocity(LEFT_PALM), deltaTime));
|
||||
grabDelta = Vec3.subtract(Controller.getSpatialControlPosition(LEFT_PALM), grabStartPosition);
|
||||
grabCurrentRotation = Controller.getSpatialControlRawRotation(LEFT_PALM);
|
||||
}
|
||||
if (!grabbingWithLeftHand && wasGrabbingWithLeftHand) {
|
||||
|
@ -119,44 +118,57 @@ function handleGrabBehavior(deltaTime) {
|
|||
|
||||
if (grabbing) {
|
||||
|
||||
// move position
|
||||
var moveFromGrab = getAndResetGrabDelta();
|
||||
if (Vec3.length(moveFromGrab) > EPSILON) {
|
||||
MyAvatar.position = Vec3.sum(MyAvatar.position, moveFromGrab);
|
||||
velocity = { x: 0, y: 0, z: 0};
|
||||
}
|
||||
|
||||
// add some rotation...
|
||||
var deltaRotation = getAndResetGrabRotation();
|
||||
var GRAB_CONTROLLER_TURN_SCALING = 0.5;
|
||||
var euler = Vec3.multiply(Quat.safeEulerAngles(deltaRotation), GRAB_CONTROLLER_TURN_SCALING);
|
||||
var headOrientation = MyAvatar.headOrientation;
|
||||
var front = Quat.getFront(headOrientation);
|
||||
var right = Quat.getRight(headOrientation);
|
||||
var up = Quat.getUp(headOrientation);
|
||||
|
||||
// Adjust body yaw by yaw from controller
|
||||
var orientation = Quat.multiply(Quat.angleAxis(-euler.y, {x:0, y: 1, z:0}), MyAvatar.orientation);
|
||||
grabDelta = Vec3.multiplyQbyV(MyAvatar.orientation, Vec3.multiply(grabDelta, -1));
|
||||
|
||||
if (debug) {
|
||||
printVector("grabDelta: ", grabDelta, 3);
|
||||
}
|
||||
|
||||
var THRUST_GRAB_SCALING = 0.0;
|
||||
|
||||
var thrustFront = Vec3.multiply(front, MyAvatar.scale * grabDelta.z * THRUST_GRAB_SCALING * deltaTime);
|
||||
MyAvatar.addThrust(thrustFront);
|
||||
var thrustRight = Vec3.multiply(right, MyAvatar.scale * grabDelta.x * THRUST_GRAB_SCALING * deltaTime);
|
||||
MyAvatar.addThrust(thrustRight);
|
||||
var thrustUp = Vec3.multiply(up, MyAvatar.scale * grabDelta.y * THRUST_GRAB_SCALING * deltaTime);
|
||||
MyAvatar.addThrust(thrustUp);
|
||||
|
||||
|
||||
// add some rotation...
|
||||
var deltaRotation = getGrabRotation();
|
||||
var PITCH_SCALING = 2.0;
|
||||
var PITCH_DEAD_ZONE = 2.0;
|
||||
var YAW_SCALING = 2.0;
|
||||
var ROLL_SCALING = 2.0;
|
||||
|
||||
var euler = Quat.safeEulerAngles(deltaRotation);
|
||||
|
||||
// Adjust body yaw by roll from controller
|
||||
var orientation = Quat.multiply(Quat.angleAxis(((euler.y * YAW_SCALING) +
|
||||
(euler.z * ROLL_SCALING)) * deltaTime, {x:0, y: 1, z:0}), MyAvatar.orientation);
|
||||
MyAvatar.orientation = orientation;
|
||||
|
||||
// Adjust head pitch from controller
|
||||
MyAvatar.headPitch = MyAvatar.headPitch - euler.x;
|
||||
var pitch = 0.0;
|
||||
if (Math.abs(euler.x) > PITCH_DEAD_ZONE) {
|
||||
pitch = (euler.x < 0.0) ? (euler.x + PITCH_DEAD_ZONE) : (euler.x - PITCH_DEAD_ZONE);
|
||||
}
|
||||
MyAvatar.headPitch = MyAvatar.headPitch + (pitch * PITCH_SCALING * deltaTime);
|
||||
|
||||
// TODO: Add some camera roll proportional to the rate of turn (so it feels like an airplane or roller coaster)
|
||||
|
||||
}
|
||||
|
||||
// add some velocity...
|
||||
if (stoppedGrabbing) {
|
||||
velocity = Vec3.sum(velocity, getAndResetGrabDeltaVelocity());
|
||||
}
|
||||
|
||||
// handle residual velocity
|
||||
if(Vec3.length(velocity) > EPSILON) {
|
||||
MyAvatar.position = Vec3.sum(MyAvatar.position, Vec3.multiply(velocity, deltaTime));
|
||||
// damp velocity
|
||||
velocity = Vec3.multiply(velocity, damping);
|
||||
}
|
||||
|
||||
|
||||
wasGrabbingWithRightHand = grabbingWithRightHand;
|
||||
wasGrabbingWithLeftHand = grabbingWithLeftHand;
|
||||
}
|
||||
|
||||
// Main update function that handles flying and grabbing behaviort
|
||||
// Update for joysticks and move button
|
||||
function flyWithHydra(deltaTime) {
|
||||
var thrustJoystickPosition = Controller.getJoystickPosition(THRUST_CONTROLLER);
|
||||
|
||||
|
|
153
examples/sit.js
Normal file
153
examples/sit.js
Normal file
|
@ -0,0 +1,153 @@
|
|||
//
|
||||
// sit.js
|
||||
// examples
|
||||
//
|
||||
// Created by Mika Impola on February 8, 2014
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
|
||||
var buttonImageUrl = "https://worklist-prod.s3.amazonaws.com/attachment/0aca88e1-9bd8-5c1d.svg";
|
||||
|
||||
var windowDimensions = Controller.getViewportDimensions();
|
||||
|
||||
var buttonWidth = 37;
|
||||
var buttonHeight = 46;
|
||||
var buttonPadding = 10;
|
||||
|
||||
var buttonPositionX = windowDimensions.x - buttonPadding - buttonWidth;
|
||||
var buttonPositionY = (windowDimensions.y - buttonHeight) / 2 ;
|
||||
|
||||
var sitDownButton = Overlays.addOverlay("image", {
|
||||
x: buttonPositionX, y: buttonPositionY, width: buttonWidth, height: buttonHeight,
|
||||
subImage: { x: 0, y: buttonHeight, width: buttonWidth, height: buttonHeight},
|
||||
imageURL: buttonImageUrl,
|
||||
visible: true,
|
||||
alpha: 1.0
|
||||
});
|
||||
var standUpButton = Overlays.addOverlay("image", {
|
||||
x: buttonPositionX, y: buttonPositionY, width: buttonWidth, height: buttonHeight,
|
||||
subImage: { x: buttonWidth, y: buttonHeight, width: buttonWidth, height: buttonHeight},
|
||||
imageURL: buttonImageUrl,
|
||||
visible: false,
|
||||
alpha: 1.0
|
||||
});
|
||||
|
||||
var passedTime = 0.0;
|
||||
var startPosition = null;
|
||||
var animationLenght = 2.0;
|
||||
|
||||
// This is the pose we would like to end up
|
||||
var pose = [
|
||||
{joint:"RightUpLeg", rotation: {x:100.0, y:15.0, z:0.0}},
|
||||
{joint:"RightLeg", rotation: {x:-130.0, y:15.0, z:0.0}},
|
||||
{joint:"RightFoot", rotation: {x:30, y:15.0, z:0.0}},
|
||||
{joint:"LeftUpLeg", rotation: {x:100.0, y:-15.0, z:0.0}},
|
||||
{joint:"LeftLeg", rotation: {x:-130.0, y:-15.0, z:0.0}},
|
||||
{joint:"LeftFoot", rotation: {x:30, y:15.0, z:0.0}},
|
||||
|
||||
{joint:"Spine2", rotation: {x:20, y:0.0, z:0.0}},
|
||||
|
||||
{joint:"RightShoulder", rotation: {x:0.0, y:40.0, z:0.0}},
|
||||
{joint:"LeftShoulder", rotation: {x:0.0, y:-40.0, z:0.0}}
|
||||
|
||||
];
|
||||
|
||||
var startPoseAndTransition = [];
|
||||
|
||||
function storeStartPoseAndTransition() {
|
||||
for (var i = 0; i < pose.length; i++){
|
||||
var startRotation = Quat.safeEulerAngles(MyAvatar.getJointRotation(pose[i].joint));
|
||||
var transitionVector = Vec3.subtract( pose[i].rotation, startRotation );
|
||||
startPoseAndTransition.push({joint: pose[i].joint, start: startRotation, transition: transitionVector});
|
||||
}
|
||||
}
|
||||
|
||||
function updateJoints(factor){
|
||||
for (var i = 0; i < startPoseAndTransition.length; i++){
|
||||
var scaledTransition = Vec3.multiply(startPoseAndTransition[i].transition, factor);
|
||||
var rotation = Vec3.sum(startPoseAndTransition[i].start, scaledTransition);
|
||||
MyAvatar.setJointData(startPoseAndTransition[i].joint, Quat.fromVec3Degrees( rotation ));
|
||||
}
|
||||
}
|
||||
|
||||
var sittingDownAnimation = function(deltaTime) {
|
||||
|
||||
passedTime += deltaTime;
|
||||
var factor = passedTime/animationLenght;
|
||||
|
||||
if ( passedTime <= animationLenght ) {
|
||||
updateJoints(factor);
|
||||
|
||||
var pos = { x: startPosition.x - 0.3 * factor, y: startPosition.y - 0.5 * factor, z: startPosition.z};
|
||||
MyAvatar.position = pos;
|
||||
}
|
||||
}
|
||||
|
||||
var standingUpAnimation = function(deltaTime){
|
||||
|
||||
passedTime += deltaTime;
|
||||
var factor = 1 - passedTime/animationLenght;
|
||||
|
||||
if ( passedTime <= animationLenght ) {
|
||||
|
||||
updateJoints(factor);
|
||||
|
||||
var pos = { x: startPosition.x + 0.3 * (passedTime/animationLenght), y: startPosition.y + 0.5 * (passedTime/animationLenght), z: startPosition.z};
|
||||
MyAvatar.position = pos;
|
||||
}
|
||||
}
|
||||
|
||||
Controller.mousePressEvent.connect(function(event){
|
||||
|
||||
var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y});
|
||||
|
||||
if (clickedOverlay == sitDownButton) {
|
||||
passedTime = 0.0;
|
||||
startPosition = MyAvatar.position;
|
||||
storeStartPoseAndTransition();
|
||||
try{
|
||||
Script.update.disconnect(standingUpAnimation);
|
||||
} catch(e){
|
||||
// no need to handle. if it wasn't connected no harm done
|
||||
}
|
||||
Script.update.connect(sittingDownAnimation);
|
||||
Overlays.editOverlay(sitDownButton, { visible: false });
|
||||
Overlays.editOverlay(standUpButton, { visible: true });
|
||||
} else if (clickedOverlay == standUpButton) {
|
||||
passedTime = 0.0;
|
||||
startPosition = MyAvatar.position;
|
||||
try{
|
||||
Script.update.disconnect(sittingDownAnimation);
|
||||
} catch (e){}
|
||||
Script.update.connect(standingUpAnimation);
|
||||
Overlays.editOverlay(standUpButton, { visible: false });
|
||||
Overlays.editOverlay(sitDownButton, { visible: true });
|
||||
}
|
||||
})
|
||||
|
||||
function update(deltaTime){
|
||||
var newWindowDimensions = Controller.getViewportDimensions();
|
||||
if( newWindowDimensions.x != windowDimensions.x || newWindowDimensions.y != windowDimensions.y ){
|
||||
windowDimensions = newWindowDimensions;
|
||||
var newX = windowDimensions.x - buttonPadding - buttonWidth;
|
||||
var newY = (windowDimensions.y - buttonHeight) / 2 ;
|
||||
Overlays.editOverlay( standUpButton, {x: newX, y: newY} );
|
||||
Overlays.editOverlay( sitDownButton, {x: newX, y: newY} );
|
||||
}
|
||||
}
|
||||
|
||||
Script.update.connect(update);
|
||||
|
||||
Script.scriptEnding.connect(function() {
|
||||
|
||||
for (var i = 0; i < pose.length; i++){
|
||||
MyAvatar.clearJointData(pose[i][0]);
|
||||
}
|
||||
|
||||
Overlays.deleteOverlay(sitDownButton);
|
||||
Overlays.deleteOverlay(standUpButton);
|
||||
});
|
|
@ -69,7 +69,6 @@ foreach(EXTERNAL_SOURCE_SUBDIR ${EXTERNAL_SOURCE_SUBDIRS})
|
|||
endforeach(EXTERNAL_SOURCE_SUBDIR)
|
||||
|
||||
find_package(Qt5 COMPONENTS Core Gui Multimedia Network OpenGL Script Svg WebKit WebKitWidgets Xml UiTools)
|
||||
find_package(GnuTLS REQUIRED)
|
||||
|
||||
# grab the ui files in resources/ui
|
||||
file (GLOB_RECURSE QT_UI_FILES ui/*.ui)
|
||||
|
@ -136,6 +135,7 @@ find_package(Faceplus)
|
|||
find_package(Faceshift)
|
||||
find_package(LibOVR)
|
||||
find_package(PrioVR)
|
||||
find_package(SDL)
|
||||
find_package(Sixense)
|
||||
find_package(Visage)
|
||||
find_package(ZLIB)
|
||||
|
@ -193,6 +193,13 @@ if (PRIOVR_FOUND AND NOT DISABLE_PRIOVR)
|
|||
target_link_libraries(${TARGET_NAME} "${PRIOVR_LIBRARIES}")
|
||||
endif (PRIOVR_FOUND AND NOT DISABLE_PRIOVR)
|
||||
|
||||
# and with SDL for joysticks
|
||||
if (SDL_FOUND AND NOT DISABLE_SDL)
|
||||
add_definitions(-DHAVE_SDL)
|
||||
include_directories(SYSTEM "${SDL_INCLUDE_DIR}")
|
||||
target_link_libraries(${TARGET_NAME} "${SDL_LIBRARY}")
|
||||
endif (SDL_FOUND AND NOT DISABLE_SDL)
|
||||
|
||||
# and with qxmpp for chat
|
||||
if (QXMPP_FOUND AND NOT DISABLE_QXMPP)
|
||||
add_definitions(-DHAVE_QXMPP -DQXMPP_STATIC)
|
||||
|
@ -204,14 +211,9 @@ endif (QXMPP_FOUND AND NOT DISABLE_QXMPP)
|
|||
# include headers for interface and InterfaceConfig.
|
||||
include_directories("${PROJECT_SOURCE_DIR}/src" "${PROJECT_BINARY_DIR}/includes")
|
||||
|
||||
# add a definition for ssize_t so that windows doesn't bail on gnutls.h
|
||||
if (WIN32)
|
||||
add_definitions(-Dssize_t=long)
|
||||
endif ()
|
||||
|
||||
# include external library headers
|
||||
# use system flag so warnings are supressed
|
||||
include_directories(SYSTEM "${FACESHIFT_INCLUDE_DIRS}" "${GNUTLS_INCLUDE_DIR}")
|
||||
include_directories(SYSTEM "${FACESHIFT_INCLUDE_DIRS}")
|
||||
|
||||
target_link_libraries(
|
||||
${TARGET_NAME}
|
||||
|
@ -219,9 +221,11 @@ target_link_libraries(
|
|||
"${ZLIB_LIBRARIES}"
|
||||
Qt5::Core Qt5::Gui Qt5::Multimedia Qt5::Network Qt5::OpenGL
|
||||
Qt5::Script Qt5::Svg Qt5::WebKit Qt5::WebKitWidgets Qt5::Xml Qt5::UiTools
|
||||
"${GNUTLS_LIBRARY}"
|
||||
)
|
||||
|
||||
# assume we are using a Qt build without bearer management
|
||||
add_definitions(-DQT_NO_BEARERMANAGEMENT)
|
||||
|
||||
if (APPLE)
|
||||
# link in required OS X frameworks and include the right GL headers
|
||||
find_library(AppKit AppKit)
|
||||
|
@ -281,6 +285,9 @@ else (APPLE)
|
|||
# we're using static GLEW, so define GLEW_STATIC
|
||||
add_definitions(-DGLEW_STATIC)
|
||||
|
||||
# add a definition for ssize_t so that windows doesn't bail
|
||||
add_definitions(-Dssize_t=long)
|
||||
|
||||
target_link_libraries(${TARGET_NAME} "${GLEW_LIBRARY}" wsock32.lib opengl32.lib)
|
||||
endif()
|
||||
endif (APPLE)
|
||||
|
|
|
@ -20,11 +20,14 @@ varying vec4 normal;
|
|||
void main(void) {
|
||||
// compute the base color based on OpenGL lighting model
|
||||
vec4 normalizedNormal = normalize(normal);
|
||||
float diffuse = dot(normalizedNormal, gl_LightSource[0].position);
|
||||
float facingLight = step(0.0, diffuse);
|
||||
vec4 base = gl_Color * (gl_FrontLightModelProduct.sceneColor + gl_FrontLightProduct[0].ambient +
|
||||
gl_FrontLightProduct[0].diffuse * max(0.0, dot(normalizedNormal, gl_LightSource[0].position)));
|
||||
gl_FrontLightProduct[0].diffuse * (diffuse * facingLight));
|
||||
|
||||
// compute the specular component (sans exponent)
|
||||
float specular = max(0.0, dot(normalize(gl_LightSource[0].position + vec4(0.0, 0.0, 1.0, 0.0)), normalizedNormal));
|
||||
float specular = facingLight * max(0.0, dot(normalize(gl_LightSource[0].position + vec4(0.0, 0.0, 1.0, 0.0)),
|
||||
normalizedNormal));
|
||||
|
||||
// modulate texture by base color and add specular contribution
|
||||
gl_FragColor = base * texture2D(diffuseMap, gl_TexCoord[0].st) +
|
||||
|
|
|
@ -32,12 +32,15 @@ void main(void) {
|
|||
// compute the base color based on OpenGL lighting model
|
||||
vec4 viewNormal = vec4(normalizedTangent * localNormal.x +
|
||||
normalizedBitangent * localNormal.y + normalizedNormal * localNormal.z, 0.0);
|
||||
float diffuse = dot(viewNormal, gl_LightSource[0].position);
|
||||
float facingLight = step(0.0, diffuse);
|
||||
vec4 base = gl_Color * (gl_FrontLightModelProduct.sceneColor + gl_FrontLightProduct[0].ambient +
|
||||
gl_FrontLightProduct[0].diffuse * max(0.0, dot(viewNormal, gl_LightSource[0].position)));
|
||||
gl_FrontLightProduct[0].diffuse * (diffuse * facingLight));
|
||||
|
||||
// compute the specular component (sans exponent)
|
||||
float specular = max(0.0, dot(normalize(gl_LightSource[0].position + vec4(0.0, 0.0, 1.0, 0.0)), viewNormal));
|
||||
|
||||
float specular = facingLight * max(0.0, dot(normalize(gl_LightSource[0].position + vec4(0.0, 0.0, 1.0, 0.0)),
|
||||
viewNormal));
|
||||
|
||||
// modulate texture by base color and add specular contribution
|
||||
gl_FragColor = base * texture2D(diffuseMap, gl_TexCoord[0].st) +
|
||||
vec4(pow(specular, gl_FrontMaterial.shininess) * gl_FrontLightProduct[0].specular.rgb, 0.0);
|
||||
|
|
|
@ -35,12 +35,15 @@ void main(void) {
|
|||
// compute the base color based on OpenGL lighting model
|
||||
vec4 viewNormal = vec4(normalizedTangent * localNormal.x +
|
||||
normalizedBitangent * localNormal.y + normalizedNormal * localNormal.z, 0.0);
|
||||
float diffuse = dot(viewNormal, gl_LightSource[0].position);
|
||||
float facingLight = step(0.0, diffuse);
|
||||
vec4 base = gl_Color * (gl_FrontLightModelProduct.sceneColor + gl_FrontLightProduct[0].ambient +
|
||||
gl_FrontLightProduct[0].diffuse * max(0.0, dot(viewNormal, gl_LightSource[0].position)));
|
||||
gl_FrontLightProduct[0].diffuse * (diffuse * facingLight));
|
||||
|
||||
// compute the specular component (sans exponent)
|
||||
float specular = max(0.0, dot(normalize(gl_LightSource[0].position + vec4(0.0, 0.0, 1.0, 0.0)), viewNormal));
|
||||
|
||||
float specular = facingLight * max(0.0, dot(normalize(gl_LightSource[0].position + vec4(0.0, 0.0, 1.0, 0.0)),
|
||||
viewNormal));
|
||||
|
||||
// modulate texture by base color and add specular contribution
|
||||
gl_FragColor = base * texture2D(diffuseMap, gl_TexCoord[0].st) + vec4(pow(specular, gl_FrontMaterial.shininess) *
|
||||
gl_FrontLightProduct[0].specular.rgb * texture2D(specularMap, gl_TexCoord[0].st).rgb, 0.0);
|
||||
|
|
|
@ -23,12 +23,15 @@ varying vec4 normal;
|
|||
void main(void) {
|
||||
// compute the base color based on OpenGL lighting model
|
||||
vec4 normalizedNormal = normalize(normal);
|
||||
float diffuse = dot(normalizedNormal, gl_LightSource[0].position);
|
||||
float facingLight = step(0.0, diffuse);
|
||||
vec4 base = gl_Color * (gl_FrontLightModelProduct.sceneColor + gl_FrontLightProduct[0].ambient +
|
||||
gl_FrontLightProduct[0].diffuse * max(0.0, dot(normalizedNormal, gl_LightSource[0].position)));
|
||||
gl_FrontLightProduct[0].diffuse * (diffuse * facingLight));
|
||||
|
||||
// compute the specular component (sans exponent)
|
||||
float specular = max(0.0, dot(normalize(gl_LightSource[0].position + vec4(0.0, 0.0, 1.0, 0.0)), normalizedNormal));
|
||||
|
||||
float specular = facingLight * max(0.0, dot(normalize(gl_LightSource[0].position + vec4(0.0, 0.0, 1.0, 0.0)),
|
||||
normalizedNormal));
|
||||
|
||||
// modulate texture by base color and add specular contribution
|
||||
gl_FragColor = base * texture2D(diffuseMap, gl_TexCoord[0].st) + vec4(pow(specular, gl_FrontMaterial.shininess) *
|
||||
gl_FrontLightProduct[0].specular.rgb * texture2D(specularMap, gl_TexCoord[0].st).rgb, 0.0);
|
||||
|
|
|
@ -169,13 +169,11 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
|
|||
_voxelHideShowThread(&_voxels),
|
||||
_packetsPerSecond(0),
|
||||
_bytesPerSecond(0),
|
||||
_nodeBoundsDisplay(this),
|
||||
_previousScriptLocation(),
|
||||
_runningScriptsWidget(new RunningScriptsWidget(_window)),
|
||||
_runningScriptsWidgetWasVisible(false)
|
||||
{
|
||||
// init GnuTLS for DTLS with domain-servers
|
||||
DTLSClientSession::globalInit();
|
||||
|
||||
// read the ApplicationInfo.ini file for Name/Version/Domain information
|
||||
QSettings applicationInfo(Application::resourcesPath() + "info/ApplicationInfo.ini", QSettings::IniFormat);
|
||||
|
||||
|
@ -430,8 +428,6 @@ Application::~Application() {
|
|||
delete _glWidget;
|
||||
|
||||
AccountManager::getInstance().destroy();
|
||||
|
||||
DTLSClientSession::globalDeinit();
|
||||
}
|
||||
|
||||
void Application::saveSettings() {
|
||||
|
@ -1990,7 +1986,8 @@ void Application::update(float deltaTime) {
|
|||
_myAvatar->updateLookAtTargetAvatar();
|
||||
updateMyAvatarLookAtPosition();
|
||||
_sixenseManager.update(deltaTime);
|
||||
_prioVR.update();
|
||||
_joystickManager.update();
|
||||
_prioVR.update(deltaTime);
|
||||
updateMyAvatar(deltaTime); // Sample hardware, update view frustum if needed, and send avatar data to mixer/nodes
|
||||
updateThreads(deltaTime); // If running non-threaded, then give the threads some time to process...
|
||||
_avatarManager.updateOtherAvatars(deltaTime); //loop through all the other avatars and simulate them...
|
||||
|
@ -2526,6 +2523,9 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) {
|
|||
|
||||
// restore default, white specular
|
||||
glMaterialfv(GL_FRONT, GL_SPECULAR, WHITE_SPECULAR_COLOR);
|
||||
|
||||
_nodeBoundsDisplay.draw();
|
||||
|
||||
}
|
||||
|
||||
bool mirrorMode = (whichCamera.getInterpolatedMode() == CAMERA_MODE_MIRROR);
|
||||
|
@ -2759,6 +2759,7 @@ void Application::displayOverlay() {
|
|||
? 80 : 20;
|
||||
drawText(_glWidget->width() - 100, _glWidget->height() - timerBottom, 0.30f, 0.0f, 0, frameTimer, WHITE_TEXT);
|
||||
}
|
||||
_nodeBoundsDisplay.drawOverlay();
|
||||
|
||||
// give external parties a change to hook in
|
||||
emit renderingOverlay();
|
||||
|
@ -3416,8 +3417,9 @@ ScriptEngine* Application::loadScript(const QString& scriptName, bool loadScript
|
|||
}
|
||||
|
||||
// start the script on a new thread...
|
||||
ScriptEngine* scriptEngine = new ScriptEngine(QUrl(scriptName), &_controllerScriptingInterface);
|
||||
_scriptEnginesHash.insert(scriptName, scriptEngine);
|
||||
QUrl scriptUrl(scriptName);
|
||||
ScriptEngine* scriptEngine = new ScriptEngine(scriptUrl, &_controllerScriptingInterface);
|
||||
_scriptEnginesHash.insert(scriptUrl.toString(), scriptEngine);
|
||||
|
||||
if (!scriptEngine->hasScript()) {
|
||||
qDebug() << "Application::loadScript(), script failed to load...";
|
||||
|
|
|
@ -58,6 +58,7 @@
|
|||
#include "avatar/MyAvatar.h"
|
||||
#include "devices/Faceplus.h"
|
||||
#include "devices/Faceshift.h"
|
||||
#include "devices/JoystickManager.h"
|
||||
#include "devices/PrioVR.h"
|
||||
#include "devices/SixenseManager.h"
|
||||
#include "devices/Visage.h"
|
||||
|
@ -73,6 +74,7 @@
|
|||
#include "ui/BandwidthDialog.h"
|
||||
#include "ui/BandwidthMeter.h"
|
||||
#include "ui/ModelsBrowser.h"
|
||||
#include "ui/NodeBounds.h"
|
||||
#include "ui/OctreeStatsDialog.h"
|
||||
#include "ui/RearMirrorTools.h"
|
||||
#include "ui/SnapshotShareDialog.h"
|
||||
|
@ -190,12 +192,15 @@ public:
|
|||
bool isMouseHidden() const { return _mouseHidden; }
|
||||
const glm::vec3& getMouseRayOrigin() const { return _mouseRayOrigin; }
|
||||
const glm::vec3& getMouseRayDirection() const { return _mouseRayDirection; }
|
||||
int getMouseX() const { return _mouseX; }
|
||||
int getMouseY() const { return _mouseY; }
|
||||
Faceplus* getFaceplus() { return &_faceplus; }
|
||||
Faceshift* getFaceshift() { return &_faceshift; }
|
||||
Visage* getVisage() { return &_visage; }
|
||||
FaceTracker* getActiveFaceTracker();
|
||||
SixenseManager* getSixenseManager() { return &_sixenseManager; }
|
||||
PrioVR* getPrioVR() { return &_prioVR; }
|
||||
JoystickManager* getJoystickManager() { return &_joystickManager; }
|
||||
BandwidthMeter* getBandwidthMeter() { return &_bandwidthMeter; }
|
||||
QUndoStack* getUndoStack() { return &_undoStack; }
|
||||
|
||||
|
@ -244,7 +249,7 @@ public:
|
|||
void computeOffAxisFrustum(float& left, float& right, float& bottom, float& top, float& nearVal,
|
||||
float& farVal, glm::vec4& nearClipPlane, glm::vec4& farClipPlane) const;
|
||||
|
||||
|
||||
NodeBounds& getNodeBoundsDisplay() { return _nodeBoundsDisplay; }
|
||||
|
||||
VoxelShader& getVoxelShader() { return _voxelShader; }
|
||||
PointShader& getPointShader() { return _pointShader; }
|
||||
|
@ -449,6 +454,7 @@ private:
|
|||
|
||||
SixenseManager _sixenseManager;
|
||||
PrioVR _prioVR;
|
||||
JoystickManager _joystickManager;
|
||||
|
||||
Camera _myCamera; // My view onto the world
|
||||
Camera _viewFrustumOffsetCamera; // The camera we use to sometimes show the view frustum from an offset mode
|
||||
|
@ -523,6 +529,8 @@ private:
|
|||
NodeToOctreeSceneStats _octreeServerSceneStats;
|
||||
QReadWriteLock _octreeSceneStatsLock;
|
||||
|
||||
NodeBounds _nodeBoundsDisplay;
|
||||
|
||||
std::vector<VoxelFade> _voxelFades;
|
||||
ControllerScriptingInterface _controllerScriptingInterface;
|
||||
QPointer<LogDialog> _logDialog;
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include "ui/MetavoxelEditor.h"
|
||||
#include "ui/ModelsBrowser.h"
|
||||
#include "ui/LoginDialog.h"
|
||||
#include "ui/NodeBounds.h"
|
||||
|
||||
|
||||
Menu* Menu::_instance = NULL;
|
||||
|
@ -242,6 +243,19 @@ Menu::Menu() :
|
|||
SLOT(setEnable3DTVMode(bool)));
|
||||
|
||||
|
||||
QMenu* nodeBordersMenu = viewMenu->addMenu("Server Borders");
|
||||
NodeBounds& nodeBounds = appInstance->getNodeBoundsDisplay();
|
||||
addCheckableActionToQMenuAndActionHash(nodeBordersMenu, MenuOption::ShowBordersVoxelNodes,
|
||||
Qt::CTRL | Qt::SHIFT | Qt::Key_1, false,
|
||||
&nodeBounds, SLOT(setShowVoxelNodes(bool)));
|
||||
addCheckableActionToQMenuAndActionHash(nodeBordersMenu, MenuOption::ShowBordersModelNodes,
|
||||
Qt::CTRL | Qt::SHIFT | Qt::Key_2, false,
|
||||
&nodeBounds, SLOT(setShowModelNodes(bool)));
|
||||
addCheckableActionToQMenuAndActionHash(nodeBordersMenu, MenuOption::ShowBordersParticleNodes,
|
||||
Qt::CTRL | Qt::SHIFT | Qt::Key_3, false,
|
||||
&nodeBounds, SLOT(setShowParticleNodes(bool)));
|
||||
|
||||
|
||||
QMenu* avatarSizeMenu = viewMenu->addMenu("Avatar Size");
|
||||
|
||||
addActionToQMenuAndActionHash(avatarSizeMenu,
|
||||
|
@ -331,7 +345,7 @@ Menu::Menu() :
|
|||
#endif
|
||||
|
||||
#ifdef HAVE_VISAGE
|
||||
addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::Visage, 0, true,
|
||||
addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::Visage, 0, false,
|
||||
appInstance->getVisage(), SLOT(updateEnabled()));
|
||||
#endif
|
||||
|
||||
|
@ -351,6 +365,7 @@ Menu::Menu() :
|
|||
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::HandsCollideWithSelf, 0, false);
|
||||
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::ShowIKConstraints, 0, false);
|
||||
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::AlignForearmsWithWrists, 0, true);
|
||||
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::AlternateIK, 0, false);
|
||||
|
||||
addDisabledActionAndSeparator(developerMenu, "Testing");
|
||||
|
||||
|
|
|
@ -267,6 +267,7 @@ private:
|
|||
namespace MenuOption {
|
||||
const QString AboutApp = "About Interface";
|
||||
const QString AlignForearmsWithWrists = "Align Forearms with Wrists";
|
||||
const QString AlternateIK = "Alternate IK";
|
||||
const QString AmbientOcclusion = "Ambient Occlusion";
|
||||
const QString Atmosphere = "Atmosphere";
|
||||
const QString Attachments = "Attachments...";
|
||||
|
@ -366,6 +367,9 @@ namespace MenuOption {
|
|||
const QString SettingsExport = "Export Settings";
|
||||
const QString SettingsImport = "Import Settings";
|
||||
const QString Shadows = "Shadows";
|
||||
const QString ShowBordersVoxelNodes = "Show Voxel Nodes";
|
||||
const QString ShowBordersModelNodes = "Show Model Nodes";
|
||||
const QString ShowBordersParticleNodes = "Show Particle Nodes";
|
||||
const QString ShowIKConstraints = "Show IK Constraints";
|
||||
const QString Stars = "Stars";
|
||||
const QString Stats = "Stats";
|
||||
|
|
|
@ -214,37 +214,37 @@ void Avatar::render(const glm::vec3& cameraPosition, RenderMode renderMode) {
|
|||
if (Menu::getInstance()->isOptionChecked(MenuOption::Avatars)) {
|
||||
renderBody(renderMode, glowLevel);
|
||||
}
|
||||
if (renderMode != SHADOW_RENDER_MODE &&
|
||||
Menu::getInstance()->isOptionChecked(MenuOption::RenderSkeletonCollisionShapes)) {
|
||||
_skeletonModel.updateShapePositions();
|
||||
_skeletonModel.renderJointCollisionShapes(0.7f);
|
||||
}
|
||||
if (renderMode != SHADOW_RENDER_MODE &&
|
||||
Menu::getInstance()->isOptionChecked(MenuOption::RenderHeadCollisionShapes)) {
|
||||
if (shouldRenderHead(cameraPosition, renderMode)) {
|
||||
getHead()->getFaceModel().updateShapePositions();
|
||||
if (renderMode != SHADOW_RENDER_MODE) {
|
||||
bool renderSkeleton = Menu::getInstance()->isOptionChecked(MenuOption::RenderSkeletonCollisionShapes);
|
||||
bool renderHead = Menu::getInstance()->isOptionChecked(MenuOption::RenderHeadCollisionShapes);
|
||||
bool renderBounding = Menu::getInstance()->isOptionChecked(MenuOption::RenderBoundingCollisionShapes);
|
||||
if (renderSkeleton || renderHead || renderBounding) {
|
||||
updateShapePositions();
|
||||
}
|
||||
|
||||
if (renderSkeleton) {
|
||||
_skeletonModel.renderJointCollisionShapes(0.7f);
|
||||
}
|
||||
|
||||
if (renderHead && shouldRenderHead(cameraPosition, renderMode)) {
|
||||
getHead()->getFaceModel().renderJointCollisionShapes(0.7f);
|
||||
}
|
||||
}
|
||||
if (renderMode != SHADOW_RENDER_MODE &&
|
||||
Menu::getInstance()->isOptionChecked(MenuOption::RenderBoundingCollisionShapes)) {
|
||||
if (shouldRenderHead(cameraPosition, renderMode)) {
|
||||
getHead()->getFaceModel().updateShapePositions();
|
||||
if (renderBounding && shouldRenderHead(cameraPosition, renderMode)) {
|
||||
getHead()->getFaceModel().renderBoundingCollisionShapes(0.7f);
|
||||
_skeletonModel.updateShapePositions();
|
||||
_skeletonModel.renderBoundingCollisionShapes(0.7f);
|
||||
}
|
||||
}
|
||||
// If this is the avatar being looked at, render a little ball above their head
|
||||
if (renderMode != SHADOW_RENDER_MODE &&_isLookAtTarget) {
|
||||
const float LOOK_AT_INDICATOR_RADIUS = 0.03f;
|
||||
const float LOOK_AT_INDICATOR_HEIGHT = 0.60f;
|
||||
const float LOOK_AT_INDICATOR_COLOR[] = { 0.8f, 0.0f, 0.0f, 0.5f };
|
||||
glPushMatrix();
|
||||
glColor4fv(LOOK_AT_INDICATOR_COLOR);
|
||||
glTranslatef(_position.x, _position.y + (getSkeletonHeight() * LOOK_AT_INDICATOR_HEIGHT), _position.z);
|
||||
glutSolidSphere(LOOK_AT_INDICATOR_RADIUS, 15, 15);
|
||||
glPopMatrix();
|
||||
|
||||
// If this is the avatar being looked at, render a little ball above their head
|
||||
if (_isLookAtTarget) {
|
||||
const float LOOK_AT_INDICATOR_RADIUS = 0.03f;
|
||||
const float LOOK_AT_INDICATOR_HEIGHT = 0.60f;
|
||||
const float LOOK_AT_INDICATOR_COLOR[] = { 0.8f, 0.0f, 0.0f, 0.5f };
|
||||
glPushMatrix();
|
||||
glColor4fv(LOOK_AT_INDICATOR_COLOR);
|
||||
glTranslatef(_position.x, _position.y + (getSkeletonHeight() * LOOK_AT_INDICATOR_HEIGHT), _position.z);
|
||||
glutSolidSphere(LOOK_AT_INDICATOR_RADIUS, 15, 15);
|
||||
glPopMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
// quick check before falling into the code below:
|
||||
|
@ -585,6 +585,12 @@ void Avatar::updateShapePositions() {
|
|||
_skeletonModel.updateShapePositions();
|
||||
Model& headModel = getHead()->getFaceModel();
|
||||
headModel.updateShapePositions();
|
||||
/* KEEP FOR DEBUG: use this in rather than code above to see shapes
|
||||
* in their default positions where the bounding shape is computed.
|
||||
_skeletonModel.resetShapePositions();
|
||||
Model& headModel = getHead()->getFaceModel();
|
||||
headModel.resetShapePositions();
|
||||
*/
|
||||
}
|
||||
|
||||
bool Avatar::findCollisions(const QVector<const Shape*>& shapes, CollisionList& collisions) {
|
||||
|
|
|
@ -164,7 +164,8 @@ void SkeletonModel::applyPalmData(int jointIndex, PalmData& palm) {
|
|||
|
||||
// rotate palm to align with its normal (normal points out of hand's palm)
|
||||
glm::quat palmRotation;
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::AlignForearmsWithWrists)) {
|
||||
if (!Menu::getInstance()->isOptionChecked(MenuOption::AlternateIK) &&
|
||||
Menu::getInstance()->isOptionChecked(MenuOption::AlignForearmsWithWrists)) {
|
||||
getJointRotation(parentJointIndex, palmRotation, true);
|
||||
} else {
|
||||
getJointRotation(jointIndex, palmRotation, true);
|
||||
|
@ -176,7 +177,10 @@ void SkeletonModel::applyPalmData(int jointIndex, PalmData& palm) {
|
|||
palmRotation = rotationBetween(palmRotation * glm::vec3(-sign, 0.0f, 0.0f), direction) * palmRotation;
|
||||
|
||||
// set hand position, rotation
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::AlignForearmsWithWrists)) {
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::AlternateIK)) {
|
||||
setHandPosition(jointIndex, palm.getPosition(), palmRotation);
|
||||
|
||||
} else if (Menu::getInstance()->isOptionChecked(MenuOption::AlignForearmsWithWrists)) {
|
||||
glm::vec3 forearmVector = palmRotation * glm::vec3(sign, 0.0f, 0.0f);
|
||||
setJointPosition(parentJointIndex, palm.getPosition() + forearmVector *
|
||||
geometry.joints.at(jointIndex).distanceToParent * extractUniformScale(_scale));
|
||||
|
@ -276,3 +280,66 @@ void SkeletonModel::renderJointConstraints(int jointIndex) {
|
|||
glLineWidth(1.0f);
|
||||
}
|
||||
|
||||
void SkeletonModel::setHandPosition(int jointIndex, const glm::vec3& position, const glm::quat& rotation) {
|
||||
// this algorithm is from sample code from sixense
|
||||
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
||||
int elbowJointIndex = geometry.joints.at(jointIndex).parentIndex;
|
||||
if (elbowJointIndex == -1) {
|
||||
return;
|
||||
}
|
||||
int shoulderJointIndex = geometry.joints.at(elbowJointIndex).parentIndex;
|
||||
glm::vec3 shoulderPosition;
|
||||
if (!getJointPosition(shoulderJointIndex, shoulderPosition)) {
|
||||
return;
|
||||
}
|
||||
// precomputed lengths
|
||||
float scale = extractUniformScale(_scale);
|
||||
float upperArmLength = geometry.joints.at(elbowJointIndex).distanceToParent * scale;
|
||||
float lowerArmLength = geometry.joints.at(jointIndex).distanceToParent * scale;
|
||||
|
||||
// first set wrist position
|
||||
glm::vec3 wristPosition = position;
|
||||
|
||||
glm::vec3 shoulderToWrist = wristPosition - shoulderPosition;
|
||||
float distanceToWrist = glm::length(shoulderToWrist);
|
||||
|
||||
// prevent gimbal lock
|
||||
if (distanceToWrist > upperArmLength + lowerArmLength - EPSILON) {
|
||||
distanceToWrist = upperArmLength + lowerArmLength - EPSILON;
|
||||
shoulderToWrist = glm::normalize(shoulderToWrist) * distanceToWrist;
|
||||
wristPosition = shoulderPosition + shoulderToWrist;
|
||||
}
|
||||
|
||||
// cosine of angle from upper arm to hand vector
|
||||
float cosA = (upperArmLength * upperArmLength + distanceToWrist * distanceToWrist - lowerArmLength * lowerArmLength) /
|
||||
(2 * upperArmLength * distanceToWrist);
|
||||
float mid = upperArmLength * cosA;
|
||||
float height = sqrt(upperArmLength * upperArmLength + mid * mid - 2 * upperArmLength * mid * cosA);
|
||||
|
||||
// direction of the elbow
|
||||
glm::vec3 handNormal = glm::cross(rotation * glm::vec3(0.0f, 1.0f, 0.0f), shoulderToWrist); // elbow rotating with wrist
|
||||
glm::vec3 relaxedNormal = glm::cross(glm::vec3(0.0f, 1.0f, 0.0f), shoulderToWrist); // elbow pointing straight down
|
||||
const float NORMAL_WEIGHT = 0.5f;
|
||||
glm::vec3 finalNormal = glm::mix(relaxedNormal, handNormal, NORMAL_WEIGHT);
|
||||
|
||||
bool rightHand = (jointIndex == geometry.rightHandJointIndex);
|
||||
if (rightHand ? (finalNormal.y > 0.0f) : (finalNormal.y < 0.0f)) {
|
||||
finalNormal.y = 0.0f; // dont allow elbows to point inward (y is vertical axis)
|
||||
}
|
||||
|
||||
glm::vec3 tangent = glm::normalize(glm::cross(shoulderToWrist, finalNormal));
|
||||
|
||||
// ik solution
|
||||
glm::vec3 elbowPosition = shoulderPosition + glm::normalize(shoulderToWrist) * mid - tangent * height;
|
||||
|
||||
glm::vec3 forwardVector(rightHand ? -1.0f : 1.0f, 0.0f, 0.0f);
|
||||
|
||||
glm::quat shoulderRotation = rotationBetween(forwardVector, elbowPosition - shoulderPosition);
|
||||
setJointRotation(shoulderJointIndex, shoulderRotation, true);
|
||||
|
||||
setJointRotation(elbowJointIndex, rotationBetween(shoulderRotation * forwardVector,
|
||||
wristPosition - elbowPosition) * shoulderRotation, true);
|
||||
|
||||
setJointRotation(jointIndex, rotation, true);
|
||||
}
|
||||
|
||||
|
|
|
@ -51,6 +51,7 @@ protected:
|
|||
private:
|
||||
|
||||
void renderJointConstraints(int jointIndex);
|
||||
void setHandPosition(int jointIndex, const glm::vec3& position, const glm::quat& rotation);
|
||||
|
||||
Avatar* _owningAvatar;
|
||||
};
|
||||
|
|
64
interface/src/devices/JoystickManager.cpp
Normal file
64
interface/src/devices/JoystickManager.cpp
Normal file
|
@ -0,0 +1,64 @@
|
|||
//
|
||||
// JoystickManager.cpp
|
||||
// interface/src/devices
|
||||
//
|
||||
// Created by Andrzej Kapolka on 5/15/14.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include <QtDebug>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include "JoystickManager.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
JoystickManager::JoystickManager() {
|
||||
#ifdef HAVE_SDL
|
||||
SDL_Init(SDL_INIT_JOYSTICK);
|
||||
int joystickCount = SDL_NumJoysticks();
|
||||
for (int i = 0; i < joystickCount; i++) {
|
||||
SDL_Joystick* joystick = SDL_JoystickOpen(i);
|
||||
if (joystick) {
|
||||
JoystickState state = { SDL_JoystickName(i), QVector<float>(SDL_JoystickNumAxes(joystick)),
|
||||
QVector<bool>(SDL_JoystickNumButtons(joystick)) };
|
||||
_joystickStates.append(state);
|
||||
_joysticks.append(joystick);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
JoystickManager::~JoystickManager() {
|
||||
#ifdef HAVE_SDL
|
||||
foreach (SDL_Joystick* joystick, _joysticks) {
|
||||
SDL_JoystickClose(joystick);
|
||||
}
|
||||
SDL_Quit();
|
||||
#endif
|
||||
}
|
||||
|
||||
void JoystickManager::update() {
|
||||
#ifdef HAVE_SDL
|
||||
SDL_JoystickUpdate();
|
||||
|
||||
for (int i = 0; i < _joystickStates.size(); i++) {
|
||||
SDL_Joystick* joystick = _joysticks.at(i);
|
||||
JoystickState& state = _joystickStates[i];
|
||||
for (int j = 0; j < state.axes.size(); j++) {
|
||||
float value = glm::round(SDL_JoystickGetAxis(joystick, j) + 0.5f) / numeric_limits<short>::max();
|
||||
const float DEAD_ZONE = 0.1f;
|
||||
state.axes[j] = glm::abs(value) < DEAD_ZONE ? 0.0f : value;
|
||||
}
|
||||
for (int j = 0; j < state.buttons.size(); j++) {
|
||||
state.buttons[j] = SDL_JoystickGetButton(joystick, j);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
53
interface/src/devices/JoystickManager.h
Normal file
53
interface/src/devices/JoystickManager.h
Normal file
|
@ -0,0 +1,53 @@
|
|||
//
|
||||
// JoystickManager.h
|
||||
// interface/src/devices
|
||||
//
|
||||
// Created by Andrzej Kapolka on 5/15/14.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#ifndef hifi_JoystickManager_h
|
||||
#define hifi_JoystickManager_h
|
||||
|
||||
#include <QObject>
|
||||
#include <QVector>
|
||||
|
||||
#ifdef HAVE_SDL
|
||||
#include <SDL.h>
|
||||
#undef main
|
||||
#endif
|
||||
|
||||
class JoystickState;
|
||||
|
||||
/// Handles joystick input through SDL.
|
||||
class JoystickManager : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
JoystickManager();
|
||||
virtual ~JoystickManager();
|
||||
|
||||
const QVector<JoystickState>& getJoystickStates() const { return _joystickStates; }
|
||||
|
||||
void update();
|
||||
|
||||
private:
|
||||
QVector<JoystickState> _joystickStates;
|
||||
|
||||
#ifdef HAVE_SDL
|
||||
QVector<SDL_Joystick*> _joysticks;
|
||||
#endif
|
||||
};
|
||||
|
||||
class JoystickState {
|
||||
public:
|
||||
QString name;
|
||||
QVector<float> axes;
|
||||
QVector<bool> buttons;
|
||||
};
|
||||
|
||||
#endif // hifi_JoystickManager_h
|
|
@ -9,6 +9,7 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include <QTimer>
|
||||
#include <QtDebug>
|
||||
|
||||
#include <FBXReader.h>
|
||||
|
@ -17,6 +18,7 @@
|
|||
#include "PrioVR.h"
|
||||
#include "ui/TextRenderer.h"
|
||||
|
||||
#ifdef HAVE_PRIOVR
|
||||
const unsigned int SERIAL_LIST[] = { 0x00000001, 0x00000000, 0x00000008, 0x00000009, 0x0000000A,
|
||||
0x0000000C, 0x0000000D, 0x0000000E, 0x00000004, 0x00000005, 0x00000010, 0x00000011 };
|
||||
const unsigned char AXIS_LIST[] = { 9, 43, 37, 37, 37, 13, 13, 13, 52, 52, 28, 28 };
|
||||
|
@ -25,7 +27,6 @@ const int LIST_LENGTH = sizeof(SERIAL_LIST) / sizeof(SERIAL_LIST[0]);
|
|||
const char* JOINT_NAMES[] = { "Neck", "Spine", "LeftArm", "LeftForeArm", "LeftHand", "RightArm",
|
||||
"RightForeArm", "RightHand", "LeftUpLeg", "LeftLeg", "RightUpLeg", "RightLeg" };
|
||||
|
||||
#ifdef HAVE_PRIOVR
|
||||
static int indexOfHumanIKJoint(const char* jointName) {
|
||||
for (int i = 0;; i++) {
|
||||
QByteArray humanIKJoint = HUMANIK_JOINTS[i];
|
||||
|
@ -37,6 +38,87 @@ static int indexOfHumanIKJoint(const char* jointName) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void setPalm(float deltaTime, int index) {
|
||||
MyAvatar* avatar = Application::getInstance()->getAvatar();
|
||||
Hand* hand = avatar->getHand();
|
||||
PalmData* palm;
|
||||
bool foundHand = false;
|
||||
for (size_t j = 0; j < hand->getNumPalms(); j++) {
|
||||
if (hand->getPalms()[j].getSixenseID() == index) {
|
||||
palm = &(hand->getPalms()[j]);
|
||||
foundHand = true;
|
||||
}
|
||||
}
|
||||
if (!foundHand) {
|
||||
PalmData newPalm(hand);
|
||||
hand->getPalms().push_back(newPalm);
|
||||
palm = &(hand->getPalms()[hand->getNumPalms() - 1]);
|
||||
palm->setSixenseID(index);
|
||||
}
|
||||
|
||||
palm->setActive(true);
|
||||
|
||||
// Read controller buttons and joystick into the hand
|
||||
if (!Application::getInstance()->getJoystickManager()->getJoystickStates().isEmpty()) {
|
||||
const JoystickState& state = Application::getInstance()->getJoystickManager()->getJoystickStates().at(0);
|
||||
if (state.axes.size() >= 4 && state.buttons.size() >= 4) {
|
||||
if (index == SIXENSE_CONTROLLER_ID_LEFT_HAND) {
|
||||
palm->setControllerButtons(state.buttons.at(1) ? BUTTON_FWD : 0);
|
||||
palm->setTrigger(state.buttons.at(0) ? 1.0f : 0.0f);
|
||||
palm->setJoystick(state.axes.at(0), -state.axes.at(1));
|
||||
|
||||
} else {
|
||||
palm->setControllerButtons(state.buttons.at(3) ? BUTTON_FWD : 0);
|
||||
palm->setTrigger(state.buttons.at(2) ? 1.0f : 0.0f);
|
||||
palm->setJoystick(state.axes.at(2), -state.axes.at(3));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
glm::vec3 position;
|
||||
glm::quat rotation;
|
||||
|
||||
Model* skeletonModel = &Application::getInstance()->getAvatar()->getSkeletonModel();
|
||||
int jointIndex;
|
||||
glm::quat inverseRotation = glm::inverse(Application::getInstance()->getAvatar()->getOrientation());
|
||||
if (index == SIXENSE_CONTROLLER_ID_LEFT_HAND) {
|
||||
jointIndex = skeletonModel->getLeftHandJointIndex();
|
||||
skeletonModel->getJointRotation(jointIndex, rotation, true);
|
||||
rotation = inverseRotation * rotation * glm::quat(glm::vec3(0.0f, PI_OVER_TWO, 0.0f));
|
||||
|
||||
} else {
|
||||
jointIndex = skeletonModel->getRightHandJointIndex();
|
||||
skeletonModel->getJointRotation(jointIndex, rotation, true);
|
||||
rotation = inverseRotation * rotation * glm::quat(glm::vec3(0.0f, -PI_OVER_TWO, 0.0f));
|
||||
}
|
||||
skeletonModel->getJointPosition(jointIndex, position);
|
||||
position = inverseRotation * (position - skeletonModel->getTranslation());
|
||||
|
||||
palm->setRawRotation(rotation);
|
||||
|
||||
// Compute current velocity from position change
|
||||
glm::vec3 rawVelocity;
|
||||
if (deltaTime > 0.f) {
|
||||
rawVelocity = (position - palm->getRawPosition()) / deltaTime;
|
||||
} else {
|
||||
rawVelocity = glm::vec3(0.0f);
|
||||
}
|
||||
palm->setRawVelocity(rawVelocity);
|
||||
palm->setRawPosition(position);
|
||||
|
||||
// Store the one fingertip in the palm structure so we can track velocity
|
||||
const float FINGER_LENGTH = 0.3f; // meters
|
||||
const glm::vec3 FINGER_VECTOR(0.0f, 0.0f, FINGER_LENGTH);
|
||||
const glm::vec3 newTipPosition = position + rotation * FINGER_VECTOR;
|
||||
glm::vec3 oldTipPosition = palm->getTipRawPosition();
|
||||
if (deltaTime > 0.f) {
|
||||
palm->setTipVelocity((newTipPosition - oldTipPosition) / deltaTime);
|
||||
} else {
|
||||
palm->setTipVelocity(glm::vec3(0.f));
|
||||
}
|
||||
palm->setTipPosition(newTipPosition);
|
||||
}
|
||||
#endif
|
||||
|
||||
PrioVR::PrioVR() {
|
||||
|
@ -78,7 +160,7 @@ glm::quat PrioVR::getTorsoRotation() const {
|
|||
return _jointRotations.size() > TORSO_ROTATION_INDEX ? _jointRotations.at(TORSO_ROTATION_INDEX) : glm::quat();
|
||||
}
|
||||
|
||||
void PrioVR::update() {
|
||||
void PrioVR::update(float deltaTime) {
|
||||
#ifdef HAVE_PRIOVR
|
||||
if (!_skeletalDevice) {
|
||||
return;
|
||||
|
@ -96,6 +178,10 @@ void PrioVR::update() {
|
|||
_lastJointRotations[i] = _jointRotations.at(i);
|
||||
_jointRotations[i] = safeMix(lastRotation, _jointRotations.at(i), 0.5f);
|
||||
}
|
||||
|
||||
// convert the joysticks into palm data
|
||||
setPalm(deltaTime, SIXENSE_CONTROLLER_ID_LEFT_HAND);
|
||||
setPalm(deltaTime, SIXENSE_CONTROLLER_ID_RIGHT_HAND);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ public:
|
|||
const QVector<int>& getHumanIKJointIndices() const { return _humanIKJointIndices; }
|
||||
const QVector<glm::quat>& getJointRotations() const { return _jointRotations; }
|
||||
|
||||
void update();
|
||||
void update(float deltaTime);
|
||||
void reset();
|
||||
|
||||
private slots:
|
||||
|
|
|
@ -39,6 +39,7 @@ Model::Model(QObject* parent) :
|
|||
_scaledToFit(false),
|
||||
_snapModelToCenter(false),
|
||||
_snappedToCenter(false),
|
||||
_rootIndex(-1),
|
||||
_shapesAreDirty(true),
|
||||
_boundingRadius(0.f),
|
||||
_boundingShape(),
|
||||
|
@ -128,7 +129,6 @@ QVector<Model::JointState> Model::createJointStates(const FBXGeometry& geometry)
|
|||
jointIsSet.fill(false, numJoints);
|
||||
int numJointsSet = 0;
|
||||
int lastNumJointsSet = -1;
|
||||
glm::mat4 baseTransform = glm::mat4_cast(_rotation) * glm::scale(_scale) * glm::translate(_offset);
|
||||
while (numJointsSet < numJoints && numJointsSet != lastNumJointsSet) {
|
||||
lastNumJointsSet = numJointsSet;
|
||||
for (int i = 0; i < numJoints; ++i) {
|
||||
|
@ -139,6 +139,8 @@ QVector<Model::JointState> Model::createJointStates(const FBXGeometry& geometry)
|
|||
const FBXJoint& joint = geometry.joints[i];
|
||||
int parentIndex = joint.parentIndex;
|
||||
if (parentIndex == -1) {
|
||||
_rootIndex = i;
|
||||
glm::mat4 baseTransform = glm::mat4_cast(_rotation) * glm::scale(_scale) * glm::translate(_offset);
|
||||
glm::quat combinedRotation = joint.preRotation * state.rotation * joint.postRotation;
|
||||
state.transform = baseTransform * geometry.offset * glm::translate(state.translation) * joint.preTransform *
|
||||
glm::mat4_cast(combinedRotation) * joint.postTransform;
|
||||
|
@ -603,66 +605,20 @@ void Model::clearShapes() {
|
|||
void Model::rebuildShapes() {
|
||||
clearShapes();
|
||||
|
||||
if (!_geometry) {
|
||||
if (!_geometry || _rootIndex == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
||||
|
||||
if (geometry.joints.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
int numJoints = geometry.joints.size();
|
||||
QVector<glm::mat4> transforms;
|
||||
transforms.fill(glm::mat4(), numJoints);
|
||||
QVector<glm::quat> combinedRotations;
|
||||
combinedRotations.fill(glm::quat(), numJoints);
|
||||
QVector<bool> shapeIsSet;
|
||||
shapeIsSet.fill(false, numJoints);
|
||||
int rootIndex = 0;
|
||||
|
||||
// We create the shapes with proper dimensions, but we set their transforms later.
|
||||
float uniformScale = extractUniformScale(_scale);
|
||||
int numShapesSet = 0;
|
||||
int lastNumShapesSet = -1;
|
||||
while (numShapesSet < numJoints && numShapesSet != lastNumShapesSet) {
|
||||
lastNumShapesSet = numShapesSet;
|
||||
for (int i = 0; i < numJoints; ++i) {
|
||||
if (shapeIsSet[i]) {
|
||||
continue;
|
||||
}
|
||||
const FBXJoint& joint = geometry.joints[i];
|
||||
int parentIndex = joint.parentIndex;
|
||||
if (parentIndex == -1) {
|
||||
rootIndex = i;
|
||||
glm::mat4 baseTransform = glm::mat4_cast(_rotation) * uniformScale * glm::translate(_offset);
|
||||
glm::quat combinedRotation = joint.preRotation * joint.rotation * joint.postRotation;
|
||||
transforms[i] = baseTransform * geometry.offset * glm::translate(joint.translation) * joint.preTransform *
|
||||
glm::mat4_cast(combinedRotation) * joint.postTransform;
|
||||
combinedRotations[i] = _rotation * combinedRotation;
|
||||
++numShapesSet;
|
||||
shapeIsSet[i] = true;
|
||||
} else if (shapeIsSet[parentIndex]) {
|
||||
glm::quat combinedRotation = joint.preRotation * joint.rotation * joint.postRotation;
|
||||
transforms[i] = transforms[parentIndex] * glm::translate(joint.translation) * joint.preTransform *
|
||||
glm::mat4_cast(combinedRotation) * joint.postTransform;
|
||||
combinedRotations[i] = combinedRotations[parentIndex] * combinedRotation;
|
||||
++numShapesSet;
|
||||
shapeIsSet[i] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// joint shapes
|
||||
Extents totalExtents;
|
||||
totalExtents.reset();
|
||||
for (int i = 0; i < _jointStates.size(); i++) {
|
||||
const FBXJoint& joint = geometry.joints[i];
|
||||
|
||||
glm::vec3 worldPosition = extractTranslation(transforms[i]);
|
||||
Extents shapeExtents;
|
||||
shapeExtents.reset();
|
||||
|
||||
float radius = uniformScale * joint.boneRadius;
|
||||
float halfHeight = 0.5f * uniformScale * joint.distanceToParent;
|
||||
Shape::Type type = joint.shapeType;
|
||||
|
@ -672,47 +628,150 @@ void Model::rebuildShapes() {
|
|||
}
|
||||
if (type == Shape::CAPSULE_SHAPE) {
|
||||
CapsuleShape* capsule = new CapsuleShape(radius, halfHeight);
|
||||
capsule->setPosition(worldPosition);
|
||||
capsule->setRotation(combinedRotations[i] * joint.shapeRotation);
|
||||
_jointShapes.push_back(capsule);
|
||||
|
||||
// add the two furthest surface points of the capsule
|
||||
glm::vec3 axis;
|
||||
capsule->computeNormalizedAxis(axis);
|
||||
axis = halfHeight * axis + glm::vec3(radius);
|
||||
shapeExtents.addPoint(worldPosition + axis);
|
||||
shapeExtents.addPoint(worldPosition - axis);
|
||||
|
||||
totalExtents.addExtents(shapeExtents);
|
||||
} else if (type == Shape::SPHERE_SHAPE) {
|
||||
SphereShape* sphere = new SphereShape(radius, worldPosition);
|
||||
SphereShape* sphere = new SphereShape(radius, glm::vec3(0.0f));
|
||||
_jointShapes.push_back(sphere);
|
||||
|
||||
glm::vec3 axis = glm::vec3(radius);
|
||||
shapeExtents.addPoint(worldPosition + axis);
|
||||
shapeExtents.addPoint(worldPosition - axis);
|
||||
totalExtents.addExtents(shapeExtents);
|
||||
} else {
|
||||
// this shape type is not handled and the joint shouldn't collide,
|
||||
// however we must have a shape for each joint,
|
||||
// so we make a bogus sphere with zero radius.
|
||||
// TODO: implement collision groups for more control over what collides with what
|
||||
SphereShape* sphere = new SphereShape(0.f, worldPosition);
|
||||
SphereShape* sphere = new SphereShape(0.f, glm::vec3(0.0f));
|
||||
_jointShapes.push_back(sphere);
|
||||
}
|
||||
}
|
||||
|
||||
// bounding shape
|
||||
// NOTE: we assume that the longest side of totalExtents is the yAxis
|
||||
// This method moves the shapes to their default positions in Model frame
|
||||
// which is where we compute the bounding shape's parameters.
|
||||
computeBoundingShape(geometry);
|
||||
|
||||
// finally sync shapes to joint positions
|
||||
_shapesAreDirty = true;
|
||||
updateShapePositions();
|
||||
}
|
||||
|
||||
void Model::computeBoundingShape(const FBXGeometry& geometry) {
|
||||
// compute default joint transforms and rotations
|
||||
// (in local frame, ignoring Model translation and rotation)
|
||||
int numJoints = geometry.joints.size();
|
||||
QVector<glm::mat4> transforms;
|
||||
transforms.fill(glm::mat4(), numJoints);
|
||||
QVector<glm::quat> finalRotations;
|
||||
finalRotations.fill(glm::quat(), numJoints);
|
||||
|
||||
QVector<bool> shapeIsSet;
|
||||
shapeIsSet.fill(false, numJoints);
|
||||
int numShapesSet = 0;
|
||||
int lastNumShapesSet = -1;
|
||||
glm::vec3 rootOffset(0.0f);
|
||||
while (numShapesSet < numJoints && numShapesSet != lastNumShapesSet) {
|
||||
lastNumShapesSet = numShapesSet;
|
||||
for (int i = 0; i < numJoints; i++) {
|
||||
const FBXJoint& joint = geometry.joints.at(i);
|
||||
int parentIndex = joint.parentIndex;
|
||||
|
||||
if (parentIndex == -1) {
|
||||
glm::mat4 baseTransform = glm::scale(_scale) * glm::translate(_offset);
|
||||
glm::quat combinedRotation = joint.preRotation * joint.rotation * joint.postRotation;
|
||||
transforms[i] = baseTransform * geometry.offset * glm::translate(joint.translation)
|
||||
* joint.preTransform * glm::mat4_cast(combinedRotation) * joint.postTransform;
|
||||
rootOffset = extractTranslation(transforms[i]);
|
||||
finalRotations[i] = combinedRotation;
|
||||
++numShapesSet;
|
||||
shapeIsSet[i] = true;
|
||||
} else if (shapeIsSet[parentIndex]) {
|
||||
glm::quat combinedRotation = joint.preRotation * joint.rotation * joint.postRotation;
|
||||
transforms[i] = transforms[parentIndex] * glm::translate(joint.translation)
|
||||
* joint.preTransform * glm::mat4_cast(combinedRotation) * joint.postTransform;
|
||||
finalRotations[i] = finalRotations[parentIndex] * combinedRotation;
|
||||
++numShapesSet;
|
||||
shapeIsSet[i] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// sync shapes to joints
|
||||
_boundingRadius = 0.0f;
|
||||
float uniformScale = extractUniformScale(_scale);
|
||||
for (int i = 0; i < _jointShapes.size(); i++) {
|
||||
const FBXJoint& joint = geometry.joints[i];
|
||||
glm::vec3 jointToShapeOffset = uniformScale * (finalRotations[i] * joint.shapePosition);
|
||||
glm::vec3 localPosition = extractTranslation(transforms[i]) + jointToShapeOffset- rootOffset;
|
||||
Shape* shape = _jointShapes[i];
|
||||
shape->setPosition(localPosition);
|
||||
shape->setRotation(finalRotations[i] * joint.shapeRotation);
|
||||
float distance = glm::length(localPosition) + shape->getBoundingRadius();
|
||||
if (distance > _boundingRadius) {
|
||||
_boundingRadius = distance;
|
||||
}
|
||||
}
|
||||
|
||||
// compute bounding box
|
||||
Extents totalExtents;
|
||||
totalExtents.reset();
|
||||
for (int i = 0; i < _jointShapes.size(); i++) {
|
||||
Extents shapeExtents;
|
||||
shapeExtents.reset();
|
||||
|
||||
Shape* shape = _jointShapes[i];
|
||||
glm::vec3 localPosition = shape->getPosition();
|
||||
int type = shape->getType();
|
||||
if (type == Shape::CAPSULE_SHAPE) {
|
||||
// add the two furthest surface points of the capsule
|
||||
CapsuleShape* capsule = static_cast<CapsuleShape*>(shape);
|
||||
glm::vec3 axis;
|
||||
capsule->computeNormalizedAxis(axis);
|
||||
float radius = capsule->getRadius();
|
||||
float halfHeight = capsule->getHalfHeight();
|
||||
axis = halfHeight * axis + glm::vec3(radius);
|
||||
|
||||
shapeExtents.addPoint(localPosition + axis);
|
||||
shapeExtents.addPoint(localPosition - axis);
|
||||
totalExtents.addExtents(shapeExtents);
|
||||
} else if (type == Shape::SPHERE_SHAPE) {
|
||||
float radius = shape->getBoundingRadius();
|
||||
glm::vec3 axis = glm::vec3(radius);
|
||||
shapeExtents.addPoint(localPosition + axis);
|
||||
shapeExtents.addPoint(localPosition - axis);
|
||||
totalExtents.addExtents(shapeExtents);
|
||||
}
|
||||
}
|
||||
|
||||
// compute bounding shape parameters
|
||||
// NOTE: we assume that the longest side of totalExtents is the yAxis...
|
||||
glm::vec3 diagonal = totalExtents.maximum - totalExtents.minimum;
|
||||
// the radius is half the RMS of the X and Z sides:
|
||||
// ... and assume the radius is half the RMS of the X and Z sides:
|
||||
float capsuleRadius = 0.5f * sqrtf(0.5f * (diagonal.x * diagonal.x + diagonal.z * diagonal.z));
|
||||
_boundingShape.setRadius(capsuleRadius);
|
||||
_boundingShape.setHalfHeight(0.5f * diagonal.y - capsuleRadius);
|
||||
_boundingShapeLocalOffset = 0.5f * (totalExtents.maximum + totalExtents.minimum);
|
||||
}
|
||||
|
||||
glm::quat inverseRotation = glm::inverse(_rotation);
|
||||
glm::vec3 rootPosition = extractTranslation(transforms[rootIndex]);
|
||||
_boundingShapeLocalOffset = inverseRotation * (0.5f * (totalExtents.maximum + totalExtents.minimum) - rootPosition);
|
||||
void Model::resetShapePositions() {
|
||||
// DEBUG method.
|
||||
// Moves shapes to the joint default locations for debug visibility into
|
||||
// how the bounding shape is computed.
|
||||
|
||||
if (!_geometry || _rootIndex == -1) {
|
||||
// geometry or joints have not yet been created
|
||||
return;
|
||||
}
|
||||
|
||||
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
||||
if (geometry.joints.isEmpty() || _jointShapes.size() != geometry.joints.size()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// The shapes are moved to their default positions in computeBoundingShape().
|
||||
computeBoundingShape(geometry);
|
||||
|
||||
// Then we move them into world frame for rendering at the Model's location.
|
||||
for (int i = 0; i < _jointShapes.size(); i++) {
|
||||
Shape* shape = _jointShapes[i];
|
||||
shape->setPosition(_translation + _rotation * shape->getPosition());
|
||||
shape->setRotation(_rotation * shape->getRotation());
|
||||
}
|
||||
_boundingShape.setPosition(_translation + _rotation * _boundingShapeLocalOffset);
|
||||
_boundingShape.setRotation(_rotation);
|
||||
}
|
||||
|
@ -728,17 +787,17 @@ void Model::updateShapePositions() {
|
|||
// shape position and rotation need to be in world-frame
|
||||
glm::vec3 jointToShapeOffset = uniformScale * (_jointStates[i].combinedRotation * joint.shapePosition);
|
||||
glm::vec3 worldPosition = extractTranslation(_jointStates[i].transform) + jointToShapeOffset + _translation;
|
||||
_jointShapes[i]->setPosition(worldPosition);
|
||||
_jointShapes[i]->setRotation(_jointStates[i].combinedRotation * joint.shapeRotation);
|
||||
float distance2 = glm::distance2(worldPosition, _translation);
|
||||
if (distance2 > _boundingRadius) {
|
||||
_boundingRadius = distance2;
|
||||
Shape* shape = _jointShapes[i];
|
||||
shape->setPosition(worldPosition);
|
||||
shape->setRotation(_jointStates[i].combinedRotation * joint.shapeRotation);
|
||||
float distance = glm::distance(worldPosition, _translation) + shape->getBoundingRadius();
|
||||
if (distance > _boundingRadius) {
|
||||
_boundingRadius = distance;
|
||||
}
|
||||
if (joint.parentIndex == -1) {
|
||||
rootPosition = worldPosition;
|
||||
}
|
||||
}
|
||||
_boundingRadius = sqrtf(_boundingRadius);
|
||||
_shapesAreDirty = false;
|
||||
_boundingShape.setPosition(rootPosition + _rotation * _boundingShapeLocalOffset);
|
||||
_boundingShape.setRotation(_rotation);
|
||||
|
|
|
@ -187,6 +187,7 @@ public:
|
|||
|
||||
void clearShapes();
|
||||
void rebuildShapes();
|
||||
void resetShapePositions();
|
||||
void updateShapePositions();
|
||||
void renderJointCollisionShapes(float alpha);
|
||||
void renderBoundingCollisionShapes(float alpha);
|
||||
|
@ -234,6 +235,7 @@ protected:
|
|||
|
||||
bool _snapModelToCenter; /// is the model's offset automatically adjusted to center around 0,0,0 in model space
|
||||
bool _snappedToCenter; /// are we currently snapped to center
|
||||
int _rootIndex;
|
||||
|
||||
class JointState {
|
||||
public:
|
||||
|
@ -293,6 +295,8 @@ protected:
|
|||
|
||||
void applyRotationDelta(int jointIndex, const glm::quat& delta, bool constrain = true);
|
||||
|
||||
void computeBoundingShape(const FBXGeometry& geometry);
|
||||
|
||||
private:
|
||||
|
||||
void applyNextGeometry();
|
||||
|
|
|
@ -74,7 +74,7 @@ bool ControllerScriptingInterface::isPrimaryButtonPressed() const {
|
|||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -351,6 +351,7 @@ bool ModelHandler::parseHeaders(QNetworkReply* reply) {
|
|||
|
||||
QList<QStandardItem*> items = _model.findItems(QFileInfo(reply->url().toString()).baseName());
|
||||
if (items.isEmpty() || items.first()->text() == DO_NOT_MODIFY_TAG) {
|
||||
_lock.unlock();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
239
interface/src/ui/NodeBounds.cpp
Normal file
239
interface/src/ui/NodeBounds.cpp
Normal file
|
@ -0,0 +1,239 @@
|
|||
//
|
||||
// NodeBounds.cpp
|
||||
// interface/src/ui
|
||||
//
|
||||
// Created by Ryan Huffman on 05/14/14.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// This class draws a border around the different Voxel, Model, and Particle nodes on the current domain,
|
||||
// and a semi-transparent cube around the currently mouse-overed node.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "Application.h"
|
||||
#include "Util.h"
|
||||
|
||||
#include "NodeBounds.h"
|
||||
|
||||
NodeBounds::NodeBounds(QObject* parent) :
|
||||
QObject(parent),
|
||||
_showVoxelNodes(false),
|
||||
_showModelNodes(false),
|
||||
_showParticleNodes(false),
|
||||
_overlayText() {
|
||||
|
||||
}
|
||||
|
||||
void NodeBounds::draw() {
|
||||
if (!(_showVoxelNodes || _showModelNodes || _showParticleNodes)) {
|
||||
_overlayText[0] = '\0';
|
||||
return;
|
||||
}
|
||||
|
||||
NodeToJurisdictionMap& voxelServerJurisdictions = Application::getInstance()->getVoxelServerJurisdictions();
|
||||
NodeToJurisdictionMap& modelServerJurisdictions = Application::getInstance()->getModelServerJurisdictions();
|
||||
NodeToJurisdictionMap& particleServerJurisdictions = Application::getInstance()->getParticleServerJurisdictions();
|
||||
NodeToJurisdictionMap* serverJurisdictions;
|
||||
|
||||
// Compute ray to find selected nodes later on. We can't use the pre-computed ray in Application because it centers
|
||||
// itself after the cursor disappears.
|
||||
Application* application = Application::getInstance();
|
||||
QGLWidget* glWidget = application->getGLWidget();
|
||||
float mouseX = application->getMouseX() / (float)glWidget->width();
|
||||
float mouseY = application->getMouseY() / (float)glWidget->height();
|
||||
glm::vec3 mouseRayOrigin;
|
||||
glm::vec3 mouseRayDirection;
|
||||
application->getViewFrustum()->computePickRay(mouseX, mouseY, mouseRayOrigin, mouseRayDirection);
|
||||
|
||||
// Variables to keep track of the selected node and properties to draw the cube later if needed
|
||||
Node* selectedNode = NULL;
|
||||
float selectedDistance = FLT_MAX;
|
||||
bool selectedIsInside = true;
|
||||
glm::vec3 selectedCenter;
|
||||
float selectedScale = 0;
|
||||
|
||||
NodeList* nodeList = NodeList::getInstance();
|
||||
|
||||
foreach (const SharedNodePointer& node, nodeList->getNodeHash()) {
|
||||
NodeType_t nodeType = node->getType();
|
||||
|
||||
if (nodeType == NodeType::VoxelServer && _showVoxelNodes) {
|
||||
serverJurisdictions = &voxelServerJurisdictions;
|
||||
} else if (nodeType == NodeType::ModelServer && _showModelNodes) {
|
||||
serverJurisdictions = &modelServerJurisdictions;
|
||||
} else if (nodeType == NodeType::ParticleServer && _showParticleNodes) {
|
||||
serverJurisdictions = &particleServerJurisdictions;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
QUuid nodeUUID = node->getUUID();
|
||||
if (serverJurisdictions->find(nodeUUID) != serverJurisdictions->end()) {
|
||||
const JurisdictionMap& map = serverJurisdictions->value(nodeUUID);
|
||||
|
||||
unsigned char* rootCode = map.getRootOctalCode();
|
||||
|
||||
if (rootCode) {
|
||||
VoxelPositionSize rootDetails;
|
||||
voxelDetailsForCode(rootCode, rootDetails);
|
||||
glm::vec3 location(rootDetails.x, rootDetails.y, rootDetails.z);
|
||||
location *= (float)TREE_SCALE;
|
||||
|
||||
AABox serverBounds(location, rootDetails.s * TREE_SCALE);
|
||||
|
||||
glm::vec3 center = serverBounds.getVertex(BOTTOM_RIGHT_NEAR)
|
||||
+ ((serverBounds.getVertex(TOP_LEFT_FAR) - serverBounds.getVertex(BOTTOM_RIGHT_NEAR)) / 2.0f);
|
||||
|
||||
const float VOXEL_NODE_SCALE = 1.00f;
|
||||
const float MODEL_NODE_SCALE = 0.99f;
|
||||
const float PARTICLE_NODE_SCALE = 0.98f;
|
||||
|
||||
float scaleFactor = rootDetails.s * TREE_SCALE;
|
||||
|
||||
// Scale by 0.92 - 1.00 depending on the scale of the node. This allows smaller nodes to scale in
|
||||
// a bit and not overlap larger nodes.
|
||||
scaleFactor *= 0.92 + (rootDetails.s * 0.08);
|
||||
|
||||
// Scale different node types slightly differently because it's common for them to overlap.
|
||||
if (nodeType == NodeType::VoxelServer) {
|
||||
scaleFactor *= VOXEL_NODE_SCALE;
|
||||
} else if (nodeType == NodeType::ModelServer) {
|
||||
scaleFactor *= MODEL_NODE_SCALE;
|
||||
} else {
|
||||
scaleFactor *= PARTICLE_NODE_SCALE;
|
||||
}
|
||||
|
||||
float red, green, blue;
|
||||
getColorForNodeType(nodeType, red, green, blue);
|
||||
drawNodeBorder(center, scaleFactor, red, green, blue);
|
||||
|
||||
float distance;
|
||||
BoxFace face;
|
||||
bool inside = serverBounds.contains(mouseRayOrigin);
|
||||
bool colliding = serverBounds.findRayIntersection(mouseRayOrigin, mouseRayDirection, distance, face);
|
||||
|
||||
// If the camera is inside a node it will be "selected" if you don't have your cursor over another node
|
||||
// that you aren't inside.
|
||||
if (colliding && (!selectedNode || (!inside && (distance < selectedDistance || selectedIsInside)))) {
|
||||
selectedNode = node.data();
|
||||
selectedDistance = distance;
|
||||
selectedIsInside = inside;
|
||||
selectedCenter = center;
|
||||
selectedScale = scaleFactor;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (selectedNode) {
|
||||
glPushMatrix();
|
||||
|
||||
glTranslatef(selectedCenter.x, selectedCenter.y, selectedCenter.z);
|
||||
glScalef(selectedScale, selectedScale, selectedScale);
|
||||
|
||||
NodeType_t selectedNodeType = selectedNode->getType();
|
||||
float red, green, blue;
|
||||
getColorForNodeType(selectedNode->getType(), red, green, blue);
|
||||
|
||||
glColor4f(red, green, blue, 0.2);
|
||||
glutSolidCube(1.0);
|
||||
|
||||
glPopMatrix();
|
||||
|
||||
HifiSockAddr addr = selectedNode->getPublicSocket();
|
||||
QString overlay = QString("%1:%2 %3ms")
|
||||
.arg(addr.getAddress().toString())
|
||||
.arg(addr.getPort())
|
||||
.arg(selectedNode->getPingMs())
|
||||
.left(MAX_OVERLAY_TEXT_LENGTH);
|
||||
|
||||
// Ideally we'd just use a QString, but I ran into weird blinking issues using
|
||||
// constData() directly, as if the data was being overwritten.
|
||||
strcpy(_overlayText, overlay.toLocal8Bit().constData());
|
||||
} else {
|
||||
_overlayText[0] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
void NodeBounds::drawNodeBorder(const glm::vec3& center, float scale, float red, float green, float blue) {
|
||||
glPushMatrix();
|
||||
|
||||
glTranslatef(center.x, center.y, center.z);
|
||||
glScalef(scale, scale, scale);
|
||||
|
||||
glLineWidth(2.5);
|
||||
glColor3f(red, green, blue);
|
||||
glBegin(GL_LINES);
|
||||
|
||||
glVertex3f(-0.5, -0.5, -0.5);
|
||||
glVertex3f( 0.5, -0.5, -0.5);
|
||||
|
||||
glVertex3f(-0.5, -0.5, -0.5);
|
||||
glVertex3f(-0.5, 0.5, -0.5);
|
||||
|
||||
glVertex3f(-0.5, -0.5, -0.5);
|
||||
glVertex3f(-0.5, -0.5, 0.5);
|
||||
|
||||
glVertex3f(-0.5, 0.5, -0.5);
|
||||
glVertex3f( 0.5, 0.5, -0.5);
|
||||
|
||||
glVertex3f(-0.5, 0.5, -0.5);
|
||||
glVertex3f(-0.5, 0.5, 0.5);
|
||||
|
||||
glVertex3f( 0.5, 0.5, 0.5);
|
||||
glVertex3f(-0.5, 0.5, 0.5);
|
||||
|
||||
glVertex3f( 0.5, 0.5, 0.5);
|
||||
glVertex3f( 0.5, -0.5, 0.5);
|
||||
|
||||
glVertex3f( 0.5, 0.5, 0.5);
|
||||
glVertex3f( 0.5, 0.5, -0.5);
|
||||
|
||||
glVertex3f( 0.5, -0.5, 0.5);
|
||||
glVertex3f(-0.5, -0.5, 0.5);
|
||||
|
||||
glVertex3f( 0.5, -0.5, 0.5);
|
||||
glVertex3f( 0.5, -0.5, -0.5);
|
||||
|
||||
glVertex3f( 0.5, 0.5, -0.5);
|
||||
glVertex3f( 0.5, -0.5, -0.5);
|
||||
|
||||
glVertex3f(-0.5, 0.5, 0.5);
|
||||
glVertex3f(-0.5, -0.5, 0.5);
|
||||
|
||||
glEnd();
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
void NodeBounds::getColorForNodeType(NodeType_t nodeType, float& red, float& green, float& blue) {
|
||||
red = nodeType == NodeType::VoxelServer ? 1.0 : 0.0;
|
||||
green = nodeType == NodeType::ParticleServer ? 1.0 : 0.0;
|
||||
blue = nodeType == NodeType::ModelServer ? 1.0 : 0.0;
|
||||
}
|
||||
|
||||
void NodeBounds::drawOverlay() {
|
||||
if (strlen(_overlayText) > 0) {
|
||||
Application* application = Application::getInstance();
|
||||
|
||||
const float TEXT_COLOR[] = { 0.90f, 0.90f, 0.90f };
|
||||
const float TEXT_SCALE = 0.1f;
|
||||
const int TEXT_HEIGHT = 10;
|
||||
const float ROTATION = 0.0f;
|
||||
const int FONT = 2;
|
||||
const int PADDING = 10;
|
||||
const int MOUSE_OFFSET = 10;
|
||||
const int BACKGROUND_OFFSET_Y = -20;
|
||||
const int BACKGROUND_BEVEL = 3;
|
||||
|
||||
int mouseX = application->getMouseX(),
|
||||
mouseY = application->getMouseY(),
|
||||
textWidth = widthText(TEXT_SCALE, 0, _overlayText);
|
||||
glColor4f(0.4, 0.4, 0.4, 0.6);
|
||||
renderBevelCornersRect(mouseX + MOUSE_OFFSET, mouseY - TEXT_HEIGHT - PADDING,
|
||||
textWidth + (2 * PADDING), TEXT_HEIGHT + (2 * PADDING), BACKGROUND_BEVEL);
|
||||
drawText(mouseX + MOUSE_OFFSET + PADDING, mouseY, TEXT_SCALE, ROTATION, FONT, _overlayText, TEXT_COLOR);
|
||||
}
|
||||
}
|
50
interface/src/ui/NodeBounds.h
Normal file
50
interface/src/ui/NodeBounds.h
Normal file
|
@ -0,0 +1,50 @@
|
|||
//
|
||||
// NodeBounds.h
|
||||
// interface/src/ui
|
||||
//
|
||||
// Created by Ryan Huffman on 05/14/14.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#ifndef hifi_NodeBounds_h
|
||||
#define hifi_NodeBounds_h
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include <NodeList.h>
|
||||
|
||||
const int MAX_OVERLAY_TEXT_LENGTH = 64;
|
||||
|
||||
class NodeBounds : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
NodeBounds(QObject* parent = NULL);
|
||||
|
||||
bool getShowVoxelNodes() { return _showVoxelNodes; }
|
||||
bool getShowModelNodes() { return _showModelNodes; }
|
||||
bool getShowParticleNodes() { return _showParticleNodes; }
|
||||
|
||||
void draw();
|
||||
void drawOverlay();
|
||||
|
||||
public slots:
|
||||
void setShowVoxelNodes(bool value) { _showVoxelNodes = value; }
|
||||
void setShowModelNodes(bool value) { _showModelNodes = value; }
|
||||
void setShowParticleNodes(bool value) { _showParticleNodes = value; }
|
||||
|
||||
protected:
|
||||
void drawNodeBorder(const glm::vec3& center, float scale, float red, float green, float blue);
|
||||
void getColorForNodeType(NodeType_t nodeType, float& red, float& green, float& blue);
|
||||
|
||||
private:
|
||||
bool _showVoxelNodes;
|
||||
bool _showModelNodes;
|
||||
bool _showParticleNodes;
|
||||
char _overlayText[MAX_OVERLAY_TEXT_LENGTH + 1];
|
||||
|
||||
};
|
||||
|
||||
#endif // hifi_NodeBounds_h
|
|
@ -28,12 +28,35 @@ OAuthWebViewHandler::OAuthWebViewHandler() :
|
|||
|
||||
}
|
||||
|
||||
const char HIGH_FIDELITY_CA[] = "-----BEGIN CERTIFICATE-----\n"
|
||||
"MIID6TCCA1KgAwIBAgIJANlfRkRD9A8bMA0GCSqGSIb3DQEBBQUAMIGqMQswCQYD\n"
|
||||
"VQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5j\n"
|
||||
"aXNjbzEbMBkGA1UEChMSSGlnaCBGaWRlbGl0eSwgSW5jMRMwEQYDVQQLEwpPcGVy\n"
|
||||
"YXRpb25zMRgwFgYDVQQDEw9oaWdoZmlkZWxpdHkuaW8xIjAgBgkqhkiG9w0BCQEW\n"
|
||||
"E29wc0BoaWdoZmlkZWxpdHkuaW8wHhcNMTQwMzI4MjIzMzM1WhcNMjQwMzI1MjIz\n"
|
||||
"MzM1WjCBqjELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNV\n"
|
||||
"BAcTDVNhbiBGcmFuY2lzY28xGzAZBgNVBAoTEkhpZ2ggRmlkZWxpdHksIEluYzET\n"
|
||||
"MBEGA1UECxMKT3BlcmF0aW9uczEYMBYGA1UEAxMPaGlnaGZpZGVsaXR5LmlvMSIw\n"
|
||||
"IAYJKoZIhvcNAQkBFhNvcHNAaGlnaGZpZGVsaXR5LmlvMIGfMA0GCSqGSIb3DQEB\n"
|
||||
"AQUAA4GNADCBiQKBgQDyo1euYiPPEdnvDZnIjWrrP230qUKMSj8SWoIkbTJF2hE8\n"
|
||||
"2eP3YOgbgSGBzZ8EJBxIOuNmj9g9Eg6691hIKFqy5W0BXO38P04Gg+pVBvpHFGBi\n"
|
||||
"wpqGbfsjaUDuYmBeJRcMO0XYkLCRQG+lAQNHoFDdItWAJfC3FwtP3OCDnz8cNwID\n"
|
||||
"AQABo4IBEzCCAQ8wHQYDVR0OBBYEFCSv2kmiGg6VFMnxXzLDNP304cPAMIHfBgNV\n"
|
||||
"HSMEgdcwgdSAFCSv2kmiGg6VFMnxXzLDNP304cPAoYGwpIGtMIGqMQswCQYDVQQG\n"
|
||||
"EwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNj\n"
|
||||
"bzEbMBkGA1UEChMSSGlnaCBGaWRlbGl0eSwgSW5jMRMwEQYDVQQLEwpPcGVyYXRp\n"
|
||||
"b25zMRgwFgYDVQQDEw9oaWdoZmlkZWxpdHkuaW8xIjAgBgkqhkiG9w0BCQEWE29w\n"
|
||||
"c0BoaWdoZmlkZWxpdHkuaW+CCQDZX0ZEQ/QPGzAMBgNVHRMEBTADAQH/MA0GCSqG\n"
|
||||
"SIb3DQEBBQUAA4GBAEkQl3p+lH5vuoCNgyfa67nL0MsBEt+5RSBOgjwCjjASjzou\n"
|
||||
"FTv5w0he2OypgMQb8i/BYtS1lJSFqjPJcSM1Salzrm3xDOK5pOXJ7h6SQLPDVEyf\n"
|
||||
"Hy2/9d/to+99+SOUlvfzfgycgjOc+s/AV7Y+GBd7uzGxUdrN4egCZW1F6/mH\n"
|
||||
"-----END CERTIFICATE-----\n";
|
||||
|
||||
void OAuthWebViewHandler::addHighFidelityRootCAToSSLConfig() {
|
||||
QSslConfiguration sslConfig = QSslConfiguration::defaultConfiguration();
|
||||
|
||||
// add the High Fidelity root CA to the list of trusted CA certificates
|
||||
QByteArray highFidelityCACertificate(reinterpret_cast<char*>(DTLSSession::highFidelityCADatum()->data),
|
||||
DTLSSession::highFidelityCADatum()->size);
|
||||
QByteArray highFidelityCACertificate(HIGH_FIDELITY_CA, sizeof(HIGH_FIDELITY_CA));
|
||||
sslConfig.setCaCertificates(sslConfig.caCertificates() + QSslCertificate::fromData(highFidelityCACertificate));
|
||||
|
||||
// set the modified configuration
|
||||
|
|
|
@ -23,7 +23,8 @@ Overlay::Overlay() :
|
|||
_parent(NULL),
|
||||
_alpha(DEFAULT_ALPHA),
|
||||
_color(DEFAULT_BACKGROUND_COLOR),
|
||||
_visible(true)
|
||||
_visible(true),
|
||||
_anchor(NO_ANCHOR)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -51,8 +52,15 @@ void Overlay::setProperties(const QScriptValue& properties) {
|
|||
if (properties.property("alpha").isValid()) {
|
||||
setAlpha(properties.property("alpha").toVariant().toFloat());
|
||||
}
|
||||
|
||||
|
||||
if (properties.property("visible").isValid()) {
|
||||
setVisible(properties.property("visible").toVariant().toBool());
|
||||
}
|
||||
|
||||
if (properties.property("anchor").isValid()) {
|
||||
QString property = properties.property("anchor").toVariant().toString();
|
||||
if (property == "MyAvatar") {
|
||||
setAnchor(MY_AVATAR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,6 +28,11 @@ class Overlay : public QObject {
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum Anchor {
|
||||
NO_ANCHOR,
|
||||
MY_AVATAR
|
||||
};
|
||||
|
||||
Overlay();
|
||||
~Overlay();
|
||||
void init(QGLWidget* parent);
|
||||
|
@ -38,11 +43,13 @@ public:
|
|||
bool getVisible() const { return _visible; }
|
||||
const xColor& getColor() const { return _color; }
|
||||
float getAlpha() const { return _alpha; }
|
||||
Anchor getAnchor() const { return _anchor; }
|
||||
|
||||
// setters
|
||||
void setVisible(bool visible) { _visible = visible; }
|
||||
void setColor(const xColor& color) { _color = color; }
|
||||
void setAlpha(float alpha) { _alpha = alpha; }
|
||||
void setAnchor(Anchor anchor) { _anchor = anchor; }
|
||||
|
||||
virtual void setProperties(const QScriptValue& properties);
|
||||
|
||||
|
@ -51,6 +58,7 @@ protected:
|
|||
float _alpha;
|
||||
xColor _color;
|
||||
bool _visible; // should the overlay be drawn at all
|
||||
Anchor _anchor;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include <Application.h>
|
||||
|
||||
#include "Cube3DOverlay.h"
|
||||
#include "ImageOverlay.h"
|
||||
|
@ -57,8 +58,41 @@ void Overlays::render2D() {
|
|||
}
|
||||
|
||||
void Overlays::render3D() {
|
||||
if (_overlays3D.size() == 0) {
|
||||
return;
|
||||
}
|
||||
bool myAvatarComputed = false;
|
||||
MyAvatar* avatar;
|
||||
glm::quat myAvatarRotation;
|
||||
glm::vec3 myAvatarPosition;
|
||||
float angle;
|
||||
glm::vec3 axis;
|
||||
float myAvatarScale;
|
||||
|
||||
foreach(Overlay* thisOverlay, _overlays3D) {
|
||||
glPushMatrix();
|
||||
switch (thisOverlay->getAnchor()) {
|
||||
case Overlay::MY_AVATAR:
|
||||
if (!myAvatarComputed) {
|
||||
avatar = Application::getInstance()->getAvatar();
|
||||
myAvatarRotation = avatar->getOrientation();
|
||||
myAvatarPosition = avatar->getPosition();
|
||||
angle = glm::degrees(glm::angle(myAvatarRotation));
|
||||
axis = glm::axis(myAvatarRotation);
|
||||
myAvatarScale = avatar->getScale();
|
||||
|
||||
myAvatarComputed = true;
|
||||
}
|
||||
|
||||
glTranslatef(myAvatarPosition.x, myAvatarPosition.y, myAvatarPosition.z);
|
||||
glRotatef(angle, axis.x, axis.y, axis.z);
|
||||
glScalef(myAvatarScale, myAvatarScale, myAvatarScale);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
thisOverlay->render();
|
||||
glPopMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -26,12 +26,10 @@ link_hifi_library(fbx ${TARGET_NAME} "${ROOT_DIR}")
|
|||
|
||||
# link ZLIB
|
||||
find_package(ZLIB)
|
||||
find_package(GnuTLS REQUIRED)
|
||||
|
||||
# add a definition for ssize_t so that windows doesn't bail on gnutls.h
|
||||
target_link_libraries(${TARGET_NAME} "${ZLIB_LIBRARIES}" Qt5::Widgets)
|
||||
|
||||
# add a definition for ssize_t so that windows doesn't bail
|
||||
if (WIN32)
|
||||
add_definitions(-Dssize_t=long)
|
||||
endif ()
|
||||
|
||||
include_directories(SYSTEM "${ZLIB_INCLUDE_DIRS}" "${GNUTLS_INCLUDE_DIR}")
|
||||
target_link_libraries(${TARGET_NAME} "${ZLIB_LIBRARIES}" "${GNUTLS_LIBRARY}" Qt5::Widgets)
|
||||
endif ()
|
|
@ -23,13 +23,7 @@ include(${MACRO_DIR}/LinkHifiLibrary.cmake)
|
|||
link_hifi_library(shared ${TARGET_NAME} "${ROOT_DIR}")
|
||||
link_hifi_library(networking ${TARGET_NAME} "${ROOT_DIR}")
|
||||
|
||||
# link GnuTLS
|
||||
find_package(GnuTLS REQUIRED)
|
||||
|
||||
# add a definition for ssize_t so that windows doesn't bail on gnutls.h
|
||||
# add a definition for ssize_t so that windows doesn't bail
|
||||
if (WIN32)
|
||||
add_definitions(-Dssize_t=long)
|
||||
endif ()
|
||||
|
||||
include_directories(SYSTEM "${GNUTLS_INCLUDE_DIR}")
|
||||
target_link_libraries(${TARGET_NAME} "${GNUTLS_LIBRARY}")
|
||||
endif ()
|
|
@ -28,13 +28,9 @@ link_hifi_library(octree ${TARGET_NAME} "${ROOT_DIR}")
|
|||
link_hifi_library(voxels ${TARGET_NAME} "${ROOT_DIR}")
|
||||
link_hifi_library(networking ${TARGET_NAME} "${ROOT_DIR}")
|
||||
|
||||
find_package(GnuTLS REQUIRED)
|
||||
target_link_libraries(${TARGET_NAME} Qt5::Script)
|
||||
|
||||
# add a definition for ssize_t so that windows doesn't bail on gnutls.h
|
||||
# add a definition for ssize_t so that windows doesn't bail
|
||||
if (WIN32)
|
||||
add_definitions(-Dssize_t=long)
|
||||
endif ()
|
||||
|
||||
|
||||
include_directories(SYSTEM "${GNUTLS_INCLUDE_DIR}")
|
||||
target_link_libraries(${TARGET_NAME} Qt5::Script "${GNUTLS_LIBRARY}")
|
||||
endif ()
|
|
@ -24,15 +24,13 @@ link_hifi_library(networking ${TARGET_NAME} "${ROOT_DIR}")
|
|||
link_hifi_library(octree ${TARGET_NAME} "${ROOT_DIR}")
|
||||
link_hifi_library(voxels ${TARGET_NAME} "${ROOT_DIR}")
|
||||
|
||||
# link ZLIB and GnuTLS
|
||||
# link ZLIB
|
||||
find_package(ZLIB)
|
||||
find_package(GnuTLS REQUIRED)
|
||||
|
||||
# add a definition for ssize_t so that windows doesn't bail on gnutls.h
|
||||
include_directories(SYSTEM "${ZLIB_INCLUDE_DIRS}")
|
||||
target_link_libraries(${TARGET_NAME} "${ZLIB_LIBRARIES}" Qt5::Widgets)
|
||||
|
||||
# add a definition for ssize_t so that windows doesn't bail
|
||||
if (WIN32)
|
||||
add_definitions(-Dssize_t=long)
|
||||
endif ()
|
||||
|
||||
|
||||
include_directories(SYSTEM "${ZLIB_INCLUDE_DIRS}" "${GNUTLS_INCLUDE_DIR}")
|
||||
target_link_libraries(${TARGET_NAME} "${ZLIB_LIBRARIES}" Qt5::Widgets "${GNUTLS_LIBRARY}")
|
||||
endif ()
|
|
@ -585,6 +585,7 @@ const char* HUMANIK_JOINTS[] = {
|
|||
"LeftArm",
|
||||
"LeftForeArm",
|
||||
"LeftHand",
|
||||
"Neck",
|
||||
"Spine",
|
||||
"Hips",
|
||||
"RightUpLeg",
|
||||
|
|
|
@ -27,12 +27,9 @@ link_hifi_library(networking ${TARGET_NAME} "${ROOT_DIR}")
|
|||
include(${MACRO_DIR}/IncludeGLM.cmake)
|
||||
include_glm(${TARGET_NAME} "${ROOT_DIR}")
|
||||
|
||||
find_package(GnuTLS REQUIRED)
|
||||
target_link_libraries(${TARGET_NAME} Qt5::Network Qt5::Widgets Qt5::Script)
|
||||
|
||||
# add a definition for ssize_t so that windows doesn't bail on gnutls.h
|
||||
# add a definition for ssize_t so that windows doesn't bail
|
||||
if (WIN32)
|
||||
add_definitions(-Dssize_t=long)
|
||||
endif ()
|
||||
|
||||
include_directories(SYSTEM "${GNUTLS_INCLUDE_DIR}")
|
||||
target_link_libraries(${TARGET_NAME} Qt5::Network Qt5::Widgets Qt5::Script "${GNUTLS_LIBRARY}")
|
||||
endif ()
|
|
@ -33,14 +33,13 @@ link_hifi_library(animation ${TARGET_NAME} "${ROOT_DIR}")
|
|||
# for streamable
|
||||
link_hifi_library(metavoxels ${TARGET_NAME} "${ROOT_DIR}")
|
||||
|
||||
# link ZLIB and GnuTLS
|
||||
# link ZLIB
|
||||
find_package(ZLIB)
|
||||
find_package(GnuTLS REQUIRED)
|
||||
|
||||
# add a definition for ssize_t so that windows doesn't bail on gnutls.h
|
||||
include_directories(SYSTEM "${ZLIB_INCLUDE_DIRS}")
|
||||
target_link_libraries(${TARGET_NAME} "${ZLIB_LIBRARIES}" Qt5::Widgets)
|
||||
|
||||
# add a definition for ssize_t so that windows doesn't bail
|
||||
if (WIN32)
|
||||
add_definitions(-Dssize_t=long)
|
||||
endif ()
|
||||
|
||||
include_directories(SYSTEM "${ZLIB_INCLUDE_DIRS}" "${GNUTLS_INCLUDE_DIR}")
|
||||
target_link_libraries(${TARGET_NAME} "${ZLIB_LIBRARIES}" Qt5::Widgets "${GNUTLS_LIBRARY}")
|
||||
endif ()
|
|
@ -714,6 +714,7 @@ void ModelItem::mapJoints(const QStringList& modelJointNames) {
|
|||
|
||||
if (!_jointMappingCompleted) {
|
||||
QStringList animationJointNames = myAnimation->getJointNames();
|
||||
|
||||
if (modelJointNames.size() > 0 && animationJointNames.size() > 0) {
|
||||
_jointMapping.resize(modelJointNames.size());
|
||||
for (int i = 0; i < modelJointNames.size(); i++) {
|
||||
|
@ -729,13 +730,17 @@ QVector<glm::quat> ModelItem::getAnimationFrame() {
|
|||
if (hasAnimation() && _jointMappingCompleted) {
|
||||
Animation* myAnimation = getAnimation(_animationURL);
|
||||
QVector<FBXAnimationFrame> frames = myAnimation->getFrames();
|
||||
int animationFrameIndex = (int)std::floor(_animationFrameIndex) % frames.size();
|
||||
QVector<glm::quat> rotations = frames[animationFrameIndex].rotations;
|
||||
frameData.resize(_jointMapping.size());
|
||||
for (int j = 0; j < _jointMapping.size(); j++) {
|
||||
int rotationIndex = _jointMapping[j];
|
||||
if (rotationIndex != -1 && rotationIndex < rotations.size()) {
|
||||
frameData[j] = rotations[rotationIndex];
|
||||
int frameCount = frames.size();
|
||||
|
||||
if (frameCount > 0) {
|
||||
int animationFrameIndex = (int)glm::floor(_animationFrameIndex) % frameCount;
|
||||
QVector<glm::quat> rotations = frames[animationFrameIndex].rotations;
|
||||
frameData.resize(_jointMapping.size());
|
||||
for (int j = 0; j < _jointMapping.size(); j++) {
|
||||
int rotationIndex = _jointMapping[j];
|
||||
if (rotationIndex != -1 && rotationIndex < rotations.size()) {
|
||||
frameData[j] = rotations[rotationIndex];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -108,6 +108,7 @@ bool FindAndUpdateModelOperator::PostRecursion(OctreeElement* element) {
|
|||
return !_found; // if we haven't yet found it, keep looking
|
||||
}
|
||||
|
||||
// TODO: improve this to not use multiple recursions
|
||||
void ModelTree::storeModel(const ModelItem& model, const SharedNodePointer& senderNode) {
|
||||
// First, look for the existing model in the tree..
|
||||
FindAndUpdateModelOperator theOperator(model);
|
||||
|
@ -118,8 +119,13 @@ void ModelTree::storeModel(const ModelItem& model, const SharedNodePointer& send
|
|||
AABox modelBox = model.getAABox();
|
||||
ModelTreeElement* element = (ModelTreeElement*)getOrCreateChildElementContaining(model.getAABox());
|
||||
element->storeModel(model);
|
||||
|
||||
// In the case where we stored it, we also need to mark the entire "path" down to the model as
|
||||
// having changed. Otherwise viewers won't see this change. So we call this recursion now that
|
||||
// we know it will be found, this find/update will correctly mark the tree as changed.
|
||||
recurseTreeWithOperator(&theOperator);
|
||||
}
|
||||
// what else do we need to do here to get reaveraging to work
|
||||
|
||||
_isDirty = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,6 @@ set(TARGET_NAME networking)
|
|||
project(${TARGET_NAME})
|
||||
|
||||
find_package(Qt5 COMPONENTS Network)
|
||||
find_package(GnuTLS REQUIRED)
|
||||
|
||||
include(${MACRO_DIR}/SetupHifiLibrary.cmake)
|
||||
setup_hifi_library(${TARGET_NAME})
|
||||
|
@ -20,10 +19,9 @@ setup_hifi_library(${TARGET_NAME})
|
|||
include(${MACRO_DIR}/IncludeGLM.cmake)
|
||||
include_glm(${TARGET_NAME} "${ROOT_DIR}")
|
||||
|
||||
# add a definition for ssize_t so that windows doesn't bail on gnutls.h
|
||||
target_link_libraries(${TARGET_NAME} Qt5::Network)
|
||||
|
||||
# add a definition for ssize_t so that windows doesn't bail
|
||||
if (WIN32)
|
||||
add_definitions(-Dssize_t=long)
|
||||
endif ()
|
||||
|
||||
include_directories(SYSTEM "${GNUTLS_INCLUDE_DIR}")
|
||||
target_link_libraries(${TARGET_NAME} Qt5::Network "${GNUTLS_LIBRARY}")
|
||||
endif ()
|
|
@ -1,83 +0,0 @@
|
|||
//
|
||||
// DTLSClientSession.cpp
|
||||
// libraries/networking/src
|
||||
//
|
||||
// Created by Stephen Birarda on 2014-04-01.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "DomainHandler.h"
|
||||
|
||||
#include "DTLSClientSession.h"
|
||||
|
||||
gnutls_certificate_credentials_t DTLSClientSession::_x509CACredentials;
|
||||
|
||||
void DTLSClientSession::globalInit() {
|
||||
static bool initialized = false;
|
||||
|
||||
if (!initialized) {
|
||||
gnutls_global_init();
|
||||
gnutls_certificate_allocate_credentials(&_x509CACredentials);
|
||||
|
||||
gnutls_certificate_set_x509_trust_mem(_x509CACredentials, DTLSSession::highFidelityCADatum(), GNUTLS_X509_FMT_PEM);
|
||||
gnutls_certificate_set_verify_function(_x509CACredentials, DTLSClientSession::verifyServerCertificate);
|
||||
}
|
||||
}
|
||||
|
||||
void DTLSClientSession::globalDeinit() {
|
||||
gnutls_certificate_free_credentials(_x509CACredentials);
|
||||
|
||||
gnutls_global_deinit();
|
||||
}
|
||||
|
||||
int DTLSClientSession::verifyServerCertificate(gnutls_session_t session) {
|
||||
unsigned int verifyStatus = 0;
|
||||
|
||||
// grab the hostname from the domain handler that this session is associated with
|
||||
DomainHandler* domainHandler = reinterpret_cast<DomainHandler*>(gnutls_session_get_ptr(session));
|
||||
qDebug() << "Checking for" << domainHandler->getHostname() << "from cert.";
|
||||
|
||||
int certReturn = gnutls_certificate_verify_peers3(session,
|
||||
domainHandler->getHostname().toLocal8Bit().constData(),
|
||||
&verifyStatus);
|
||||
|
||||
if (certReturn < 0) {
|
||||
return GNUTLS_E_CERTIFICATE_ERROR;
|
||||
}
|
||||
|
||||
gnutls_certificate_type_t typeReturn = gnutls_certificate_type_get(session);
|
||||
|
||||
gnutls_datum_t printOut;
|
||||
|
||||
certReturn = gnutls_certificate_verification_status_print(verifyStatus, typeReturn, &printOut, 0);
|
||||
|
||||
if (certReturn < 0) {
|
||||
return GNUTLS_E_CERTIFICATE_ERROR;
|
||||
}
|
||||
|
||||
qDebug() << "Gnutls certificate verification status:" << reinterpret_cast<char *>(printOut.data);
|
||||
|
||||
#ifdef WIN32
|
||||
free(printOut.data);
|
||||
#else
|
||||
gnutls_free(printOut.data);
|
||||
#endif
|
||||
|
||||
if (verifyStatus != 0) {
|
||||
qDebug() << "Server provided certificate for DTLS is not trusted. Can not complete handshake.";
|
||||
return GNUTLS_E_CERTIFICATE_ERROR;
|
||||
} else {
|
||||
// certificate is valid, continue handshaking as normal
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
DTLSClientSession::DTLSClientSession(QUdpSocket& dtlsSocket, HifiSockAddr& destinationSocket) :
|
||||
DTLSSession(GNUTLS_CLIENT, dtlsSocket, destinationSocket)
|
||||
{
|
||||
gnutls_priority_set_direct(_gnutlsSession, "PERFORMANCE", NULL);
|
||||
gnutls_credentials_set(_gnutlsSession, GNUTLS_CRD_CERTIFICATE, _x509CACredentials);
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
//
|
||||
// DTLSClientSession.h
|
||||
// libraries/networking/src
|
||||
//
|
||||
// Created by Stephen Birarda on 2014-04-01.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#ifndef hifi_DTLSClientSession_h
|
||||
#define hifi_DTLSClientSession_h
|
||||
|
||||
#include "DTLSSession.h"
|
||||
|
||||
class DTLSClientSession : public DTLSSession {
|
||||
public:
|
||||
DTLSClientSession(QUdpSocket& dtlsSocket, HifiSockAddr& destinationSocket);
|
||||
|
||||
static void globalInit();
|
||||
static void globalDeinit();
|
||||
|
||||
static int verifyServerCertificate(gnutls_session_t session);
|
||||
|
||||
static gnutls_certificate_credentials_t _x509CACredentials;
|
||||
static bool _wasGloballyInitialized;
|
||||
};
|
||||
|
||||
#endif // hifi_DTLSClientSession_h
|
|
@ -1,145 +0,0 @@
|
|||
//
|
||||
// DTLSSession.cpp
|
||||
// libraries/networking/src
|
||||
//
|
||||
// Created by Stephen Birarda on 2014-04-01.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include <gnutls/dtls.h>
|
||||
|
||||
#include "NodeList.h"
|
||||
#include "DTLSSession.h"
|
||||
|
||||
int DTLSSession::socketPullTimeout(gnutls_transport_ptr_t ptr, unsigned int ms) {
|
||||
DTLSSession* session = static_cast<DTLSSession*>(ptr);
|
||||
QUdpSocket& dtlsSocket = session->_dtlsSocket;
|
||||
|
||||
if (dtlsSocket.hasPendingDatagrams()) {
|
||||
// peek the data on stack to see if it belongs to this session
|
||||
static sockaddr senderSockAddr;
|
||||
static socklen_t sockAddrSize = sizeof(senderSockAddr);
|
||||
|
||||
QByteArray peekDatagram(dtlsSocket.pendingDatagramSize(), 0);
|
||||
|
||||
recvfrom(dtlsSocket.socketDescriptor(), peekDatagram.data(), dtlsSocket.pendingDatagramSize(),
|
||||
MSG_PEEK, &senderSockAddr, &sockAddrSize);
|
||||
|
||||
if (HifiSockAddr(&senderSockAddr) == session->_destinationSocket) {
|
||||
// there is data for this session ready to be read
|
||||
return 1;
|
||||
} else {
|
||||
// the next data from the dtlsSocket is not for this session
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
// no data available on the dtlsSocket
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
ssize_t DTLSSession::socketPull(gnutls_transport_ptr_t ptr, void* buffer, size_t size) {
|
||||
DTLSSession* session = static_cast<DTLSSession*>(ptr);
|
||||
QUdpSocket& dtlsSocket = session->_dtlsSocket;
|
||||
|
||||
HifiSockAddr pulledSockAddr;
|
||||
qint64 bytesReceived = dtlsSocket.readDatagram(reinterpret_cast<char*>(buffer), size,
|
||||
pulledSockAddr.getAddressPointer(), pulledSockAddr.getPortPointer());
|
||||
if (bytesReceived == -1) {
|
||||
// no data to pull, return -1
|
||||
#if DTLS_VERBOSE_DEBUG
|
||||
qDebug() << "Received no data on call to readDatagram";
|
||||
#endif
|
||||
return bytesReceived;
|
||||
}
|
||||
|
||||
if (pulledSockAddr == session->_destinationSocket) {
|
||||
// bytes received from the correct sender, return number of bytes received
|
||||
|
||||
#if DTLS_VERBOSE_DEBUG
|
||||
qDebug() << "Received" << bytesReceived << "on DTLS socket from" << pulledSockAddr;
|
||||
#endif
|
||||
|
||||
return bytesReceived;
|
||||
}
|
||||
|
||||
// we pulled a packet not matching this session, so output that
|
||||
qDebug() << "Denied connection from" << pulledSockAddr;
|
||||
|
||||
gnutls_transport_set_errno(session->_gnutlsSession, GNUTLS_E_AGAIN);
|
||||
return -1;
|
||||
}
|
||||
|
||||
gnutls_datum_t* DTLSSession::highFidelityCADatum() {
|
||||
static gnutls_datum_t hifiCADatum;
|
||||
static bool datumInitialized = false;
|
||||
|
||||
static unsigned char HIGHFIDELITY_ROOT_CA_CERT[] =
|
||||
"-----BEGIN CERTIFICATE-----\n"
|
||||
"MIID6TCCA1KgAwIBAgIJANlfRkRD9A8bMA0GCSqGSIb3DQEBBQUAMIGqMQswCQYD\n"
|
||||
"VQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5j\n"
|
||||
"aXNjbzEbMBkGA1UEChMSSGlnaCBGaWRlbGl0eSwgSW5jMRMwEQYDVQQLEwpPcGVy\n"
|
||||
"YXRpb25zMRgwFgYDVQQDEw9oaWdoZmlkZWxpdHkuaW8xIjAgBgkqhkiG9w0BCQEW\n"
|
||||
"E29wc0BoaWdoZmlkZWxpdHkuaW8wHhcNMTQwMzI4MjIzMzM1WhcNMjQwMzI1MjIz\n"
|
||||
"MzM1WjCBqjELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNV\n"
|
||||
"BAcTDVNhbiBGcmFuY2lzY28xGzAZBgNVBAoTEkhpZ2ggRmlkZWxpdHksIEluYzET\n"
|
||||
"MBEGA1UECxMKT3BlcmF0aW9uczEYMBYGA1UEAxMPaGlnaGZpZGVsaXR5LmlvMSIw\n"
|
||||
"IAYJKoZIhvcNAQkBFhNvcHNAaGlnaGZpZGVsaXR5LmlvMIGfMA0GCSqGSIb3DQEB\n"
|
||||
"AQUAA4GNADCBiQKBgQDyo1euYiPPEdnvDZnIjWrrP230qUKMSj8SWoIkbTJF2hE8\n"
|
||||
"2eP3YOgbgSGBzZ8EJBxIOuNmj9g9Eg6691hIKFqy5W0BXO38P04Gg+pVBvpHFGBi\n"
|
||||
"wpqGbfsjaUDuYmBeJRcMO0XYkLCRQG+lAQNHoFDdItWAJfC3FwtP3OCDnz8cNwID\n"
|
||||
"AQABo4IBEzCCAQ8wHQYDVR0OBBYEFCSv2kmiGg6VFMnxXzLDNP304cPAMIHfBgNV\n"
|
||||
"HSMEgdcwgdSAFCSv2kmiGg6VFMnxXzLDNP304cPAoYGwpIGtMIGqMQswCQYDVQQG\n"
|
||||
"EwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNj\n"
|
||||
"bzEbMBkGA1UEChMSSGlnaCBGaWRlbGl0eSwgSW5jMRMwEQYDVQQLEwpPcGVyYXRp\n"
|
||||
"b25zMRgwFgYDVQQDEw9oaWdoZmlkZWxpdHkuaW8xIjAgBgkqhkiG9w0BCQEWE29w\n"
|
||||
"c0BoaWdoZmlkZWxpdHkuaW+CCQDZX0ZEQ/QPGzAMBgNVHRMEBTADAQH/MA0GCSqG\n"
|
||||
"SIb3DQEBBQUAA4GBAEkQl3p+lH5vuoCNgyfa67nL0MsBEt+5RSBOgjwCjjASjzou\n"
|
||||
"FTv5w0he2OypgMQb8i/BYtS1lJSFqjPJcSM1Salzrm3xDOK5pOXJ7h6SQLPDVEyf\n"
|
||||
"Hy2/9d/to+99+SOUlvfzfgycgjOc+s/AV7Y+GBd7uzGxUdrN4egCZW1F6/mH\n"
|
||||
"-----END CERTIFICATE-----\n";
|
||||
|
||||
if (!datumInitialized) {
|
||||
hifiCADatum.data = HIGHFIDELITY_ROOT_CA_CERT;
|
||||
hifiCADatum.size = sizeof(HIGHFIDELITY_ROOT_CA_CERT);
|
||||
}
|
||||
|
||||
return &hifiCADatum;
|
||||
}
|
||||
|
||||
DTLSSession::DTLSSession(int end, QUdpSocket& dtlsSocket, HifiSockAddr& destinationSocket) :
|
||||
DummyDTLSSession(dtlsSocket, destinationSocket),
|
||||
_completedHandshake(false)
|
||||
{
|
||||
gnutls_init(&_gnutlsSession, end | GNUTLS_DATAGRAM | GNUTLS_NONBLOCK);
|
||||
|
||||
// see http://gnutls.org/manual/html_node/Datagram-TLS-API.html#gnutls_005fdtls_005fset_005fmtu
|
||||
const unsigned int DTLS_MAX_MTU = 1452;
|
||||
gnutls_dtls_set_mtu(_gnutlsSession, DTLS_MAX_MTU);
|
||||
|
||||
const unsigned int DTLS_HANDSHAKE_RETRANSMISSION_TIMEOUT = DOMAIN_SERVER_CHECK_IN_MSECS;
|
||||
const unsigned int DTLS_TOTAL_CONNECTION_TIMEOUT = 2 * NODE_SILENCE_THRESHOLD_MSECS;
|
||||
gnutls_dtls_set_timeouts(_gnutlsSession, DTLS_HANDSHAKE_RETRANSMISSION_TIMEOUT, DTLS_TOTAL_CONNECTION_TIMEOUT);
|
||||
|
||||
gnutls_transport_set_ptr(_gnutlsSession, this);
|
||||
gnutls_transport_set_push_function(_gnutlsSession, DummyDTLSSession::socketPush);
|
||||
gnutls_transport_set_pull_function(_gnutlsSession, socketPull);
|
||||
gnutls_transport_set_pull_timeout_function(_gnutlsSession, socketPullTimeout);
|
||||
}
|
||||
|
||||
DTLSSession::~DTLSSession() {
|
||||
gnutls_deinit(_gnutlsSession);
|
||||
}
|
||||
|
||||
void DTLSSession::setCompletedHandshake(bool completedHandshake) {
|
||||
_completedHandshake = completedHandshake;
|
||||
qDebug() << "Completed DTLS handshake with" << _destinationSocket;
|
||||
}
|
||||
|
||||
qint64 DTLSSession::writeDatagram(const QByteArray& datagram) {
|
||||
// we don't need to put a hash in this packet, so just send it off
|
||||
return gnutls_record_send(_gnutlsSession, datagram.data(), datagram.size());
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
//
|
||||
// DTLSSession.h
|
||||
// libraries/networking/src
|
||||
//
|
||||
// Created by Stephen Birarda on 2014-04-01.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#ifndef hifi_DTLSSession_h
|
||||
#define hifi_DTLSSession_h
|
||||
|
||||
#include <QtNetwork/QUdpSocket>
|
||||
|
||||
#include <gnutls/gnutls.h>
|
||||
|
||||
#include "DummyDTLSSession.h"
|
||||
#include "HifiSockAddr.h"
|
||||
|
||||
class DTLSSession : public DummyDTLSSession {
|
||||
Q_OBJECT
|
||||
public:
|
||||
DTLSSession(int end, QUdpSocket& dtlsSocket, HifiSockAddr& destinationSocket);
|
||||
~DTLSSession();
|
||||
|
||||
static int socketPullTimeout(gnutls_transport_ptr_t ptr, unsigned int ms);
|
||||
static ssize_t socketPull(gnutls_transport_ptr_t ptr, void* buffer, size_t size);
|
||||
|
||||
static gnutls_datum_t* highFidelityCADatum();
|
||||
|
||||
qint64 writeDatagram(const QByteArray& datagram);
|
||||
|
||||
gnutls_session_t* getGnuTLSSession() { return &_gnutlsSession; }
|
||||
|
||||
bool completedHandshake() const { return _completedHandshake; }
|
||||
void setCompletedHandshake(bool completedHandshake);
|
||||
protected:
|
||||
gnutls_session_t _gnutlsSession;
|
||||
bool _completedHandshake;
|
||||
};
|
||||
|
||||
#endif // hifi_DTLSSession_h
|
|
@ -9,8 +9,6 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include <gnutls/dtls.h>
|
||||
|
||||
#include "NodeList.h"
|
||||
#include "PacketHeaders.h"
|
||||
|
||||
|
@ -22,16 +20,11 @@ DomainHandler::DomainHandler(QObject* parent) :
|
|||
_sockAddr(HifiSockAddr(QHostAddress::Null, DEFAULT_DOMAIN_SERVER_PORT)),
|
||||
_assignmentUUID(),
|
||||
_isConnected(false),
|
||||
_dtlsSession(NULL),
|
||||
_handshakeTimer(NULL)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
DomainHandler::~DomainHandler() {
|
||||
delete _dtlsSession;
|
||||
}
|
||||
|
||||
void DomainHandler::clearConnectionInfo() {
|
||||
_uuid = QUuid();
|
||||
_isConnected = false;
|
||||
|
@ -41,38 +34,12 @@ void DomainHandler::clearConnectionInfo() {
|
|||
delete _handshakeTimer;
|
||||
_handshakeTimer = NULL;
|
||||
}
|
||||
|
||||
delete _dtlsSession;
|
||||
_dtlsSession = NULL;
|
||||
}
|
||||
|
||||
void DomainHandler::reset() {
|
||||
clearConnectionInfo();
|
||||
_hostname = QString();
|
||||
_sockAddr.setAddress(QHostAddress::Null);
|
||||
|
||||
delete _dtlsSession;
|
||||
_dtlsSession = NULL;
|
||||
}
|
||||
|
||||
const unsigned int DTLS_HANDSHAKE_INTERVAL_MSECS = 100;
|
||||
|
||||
void DomainHandler::initializeDTLSSession() {
|
||||
if (!_dtlsSession) {
|
||||
_dtlsSession = new DTLSClientSession(NodeList::getInstance()->getDTLSSocket(), _sockAddr);
|
||||
|
||||
gnutls_session_set_ptr(*_dtlsSession->getGnuTLSSession(), this);
|
||||
|
||||
// start a timer to complete the handshake process
|
||||
_handshakeTimer = new QTimer(this);
|
||||
connect(_handshakeTimer, &QTimer::timeout, this, &DomainHandler::completeDTLSHandshake);
|
||||
|
||||
// start the handshake right now
|
||||
completeDTLSHandshake();
|
||||
|
||||
// start the timer to finish off the handshake
|
||||
_handshakeTimer->start(DTLS_HANDSHAKE_INTERVAL_MSECS);
|
||||
}
|
||||
}
|
||||
|
||||
void DomainHandler::setSockAddr(const HifiSockAddr& sockAddr, const QString& hostname) {
|
||||
|
@ -120,30 +87,6 @@ void DomainHandler::setHostname(const QString& hostname) {
|
|||
}
|
||||
}
|
||||
|
||||
void DomainHandler::completeDTLSHandshake() {
|
||||
int handshakeReturn = gnutls_handshake(*_dtlsSession->getGnuTLSSession());
|
||||
|
||||
if (handshakeReturn == 0) {
|
||||
// we've shaken hands, so we're good to go now
|
||||
_dtlsSession->setCompletedHandshake(true);
|
||||
|
||||
_handshakeTimer->stop();
|
||||
delete _handshakeTimer;
|
||||
_handshakeTimer = NULL;
|
||||
|
||||
// emit a signal so NodeList can handle incoming DTLS packets
|
||||
emit completedDTLSHandshake();
|
||||
|
||||
} else if (gnutls_error_is_fatal(handshakeReturn)) {
|
||||
// this was a fatal error handshaking, so remove this session
|
||||
qDebug() << "Fatal error -" << gnutls_strerror(handshakeReturn)
|
||||
<< "- during DTLS handshake with DS at"
|
||||
<< qPrintable((_hostname.isEmpty() ? _sockAddr.getAddress().toString() : _hostname));
|
||||
|
||||
clearConnectionInfo();
|
||||
}
|
||||
}
|
||||
|
||||
void DomainHandler::completedHostnameLookup(const QHostInfo& hostInfo) {
|
||||
for (int i = 0; i < hostInfo.addresses().size(); i++) {
|
||||
if (hostInfo.addresses()[i].protocol() == QAbstractSocket::IPv4Protocol) {
|
||||
|
@ -179,5 +122,5 @@ void DomainHandler::parseDTLSRequirementPacket(const QByteArray& dtlsRequirement
|
|||
|
||||
_sockAddr.setPort(dtlsPort);
|
||||
|
||||
initializeDTLSSession();
|
||||
// initializeDTLSSession();
|
||||
}
|
|
@ -18,7 +18,6 @@
|
|||
#include <QtCore/QUrl>
|
||||
#include <QtNetwork/QHostInfo>
|
||||
|
||||
#include "DTLSClientSession.h"
|
||||
#include "HifiSockAddr.h"
|
||||
|
||||
const QString DEFAULT_DOMAIN_HOSTNAME = "sandbox.highfidelity.io";
|
||||
|
@ -32,7 +31,6 @@ class DomainHandler : public QObject {
|
|||
Q_OBJECT
|
||||
public:
|
||||
DomainHandler(QObject* parent = 0);
|
||||
~DomainHandler();
|
||||
|
||||
void clearConnectionInfo();
|
||||
|
||||
|
@ -56,29 +54,22 @@ public:
|
|||
bool isConnected() const { return _isConnected; }
|
||||
void setIsConnected(bool isConnected);
|
||||
|
||||
DTLSClientSession* getDTLSSession() { return _dtlsSession; }
|
||||
|
||||
void parseDTLSRequirementPacket(const QByteArray& dtlsRequirementPacket);
|
||||
|
||||
private slots:
|
||||
void completeDTLSHandshake();
|
||||
void completedHostnameLookup(const QHostInfo& hostInfo);
|
||||
signals:
|
||||
void hostnameChanged(const QString& hostname);
|
||||
void connectedToDomain(const QString& hostname);
|
||||
void completedDTLSHandshake();
|
||||
void DTLSConnectionLost();
|
||||
|
||||
private:
|
||||
void reset();
|
||||
void initializeDTLSSession();
|
||||
|
||||
QUuid _uuid;
|
||||
QString _hostname;
|
||||
HifiSockAddr _sockAddr;
|
||||
QUuid _assignmentUUID;
|
||||
bool _isConnected;
|
||||
DTLSClientSession* _dtlsSession;
|
||||
QTimer* _handshakeTimer;
|
||||
};
|
||||
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
//
|
||||
// DummyDTLSSession.cpp
|
||||
// libraries/networking/src
|
||||
//
|
||||
// Created by Stephen Birarda on 2014-04-04.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "DummyDTLSSession.h"
|
||||
|
||||
ssize_t DummyDTLSSession::socketPush(gnutls_transport_ptr_t ptr, const void* buffer, size_t size) {
|
||||
DummyDTLSSession* session = static_cast<DummyDTLSSession*>(ptr);
|
||||
QUdpSocket& dtlsSocket = session->_dtlsSocket;
|
||||
|
||||
#if DTLS_VERBOSE_DEBUG
|
||||
qDebug() << "Pushing a message of size" << size << "to" << session->_destinationSocket;
|
||||
#endif
|
||||
|
||||
return dtlsSocket.writeDatagram(reinterpret_cast<const char*>(buffer), size,
|
||||
session->_destinationSocket.getAddress(), session->_destinationSocket.getPort());
|
||||
}
|
||||
|
||||
DummyDTLSSession::DummyDTLSSession(QUdpSocket& dtlsSocket, const HifiSockAddr& destinationSocket) :
|
||||
_dtlsSocket(dtlsSocket),
|
||||
_destinationSocket(destinationSocket)
|
||||
{
|
||||
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
//
|
||||
// DummyDTLSSession.h
|
||||
// libraries/networking/src
|
||||
//
|
||||
// Created by Stephen Birarda on 2014-04-04.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#ifndef hifi_DummyDTLSSession_h
|
||||
#define hifi_DummyDTLSSession_h
|
||||
|
||||
#include <QtNetwork/QUdpSocket>
|
||||
|
||||
#include <gnutls/gnutls.h>
|
||||
|
||||
#include "HifiSockAddr.h"
|
||||
|
||||
#define DTLS_VERBOSE_DEBUG 0
|
||||
|
||||
class DummyDTLSSession : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
DummyDTLSSession(QUdpSocket& dtlsSocket, const HifiSockAddr& destinationSocket);
|
||||
|
||||
static ssize_t socketPush(gnutls_transport_ptr_t ptr, const void* buffer, size_t size);
|
||||
protected:
|
||||
QUdpSocket& _dtlsSocket;
|
||||
HifiSockAddr _destinationSocket;
|
||||
};
|
||||
|
||||
#endif // hifi_DummyDTLSSession_h
|
|
@ -27,8 +27,6 @@
|
|||
#include <QtNetwork/QHostAddress>
|
||||
#include <QtNetwork/QUdpSocket>
|
||||
|
||||
#include <gnutls/gnutls.h>
|
||||
|
||||
#include "DomainHandler.h"
|
||||
#include "Node.h"
|
||||
|
||||
|
|
|
@ -15,8 +15,6 @@
|
|||
#include <QtCore/QUrl>
|
||||
#include <QtNetwork/QHostInfo>
|
||||
|
||||
#include <gnutls/dtls.h>
|
||||
|
||||
#include "AccountManager.h"
|
||||
#include "Assignment.h"
|
||||
#include "HifiSockAddr.h"
|
||||
|
@ -68,9 +66,6 @@ NodeList::NodeList(char newOwnerType, unsigned short socketListenPort, unsigned
|
|||
|
||||
// clear our NodeList when logout is requested
|
||||
connect(&AccountManager::getInstance(), &AccountManager::logoutComplete , this, &NodeList::reset);
|
||||
|
||||
// perform a function when DTLS handshake is completed
|
||||
connect(&_domainHandler, &DomainHandler::completedDTLSHandshake, this, &NodeList::completedDTLSHandshake);
|
||||
}
|
||||
|
||||
qint64 NodeList::sendStatsToDomainServer(const QJsonObject& statsObject) {
|
||||
|
@ -117,30 +112,6 @@ void NodeList::timePingReply(const QByteArray& packet, const SharedNodePointer&
|
|||
}
|
||||
}
|
||||
|
||||
void NodeList::completedDTLSHandshake() {
|
||||
// at this point, we've got a DTLS socket
|
||||
// make this NodeList the handler of DTLS packets
|
||||
connect(_dtlsSocket, &QUdpSocket::readyRead, this, &NodeList::processAvailableDTLSDatagrams);
|
||||
}
|
||||
|
||||
void NodeList::processAvailableDTLSDatagrams() {
|
||||
while (_dtlsSocket->hasPendingDatagrams()) {
|
||||
QByteArray dtlsPacket(_dtlsSocket->pendingDatagramSize(), 0);
|
||||
|
||||
// pull the data from this user off the stack and process it
|
||||
int receivedBytes = gnutls_record_recv(*_domainHandler.getDTLSSession()->getGnuTLSSession(),
|
||||
dtlsPacket.data(), dtlsPacket.size());
|
||||
if (receivedBytes > 0) {
|
||||
// successful data receive, hand this off to processNodeData
|
||||
processNodeData(_domainHandler.getSockAddr(), dtlsPacket.left(receivedBytes));
|
||||
} else if (gnutls_error_is_fatal(receivedBytes)) {
|
||||
qDebug() << "Fatal error -" << gnutls_strerror(receivedBytes) << "- receiving DTLS packet from domain-server.";
|
||||
} else {
|
||||
qDebug() << "non fatal receive" << receivedBytes;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NodeList::processNodeData(const HifiSockAddr& senderSockAddr, const QByteArray& packet) {
|
||||
switch (packetTypeForPacket(packet)) {
|
||||
case PacketTypeDomainList: {
|
||||
|
@ -365,19 +336,9 @@ void NodeList::sendDomainServerCheckIn() {
|
|||
// send a STUN request to figure it out
|
||||
sendSTUNRequest();
|
||||
} else if (!_domainHandler.getIP().isNull()) {
|
||||
|
||||
DTLSClientSession* dtlsSession = _domainHandler.getDTLSSession();
|
||||
|
||||
bool isUsingDTLS = false;
|
||||
|
||||
if (dtlsSession) {
|
||||
if (!dtlsSession->completedHandshake()) {
|
||||
// if the handshake process is not complete then we can't check in, so return
|
||||
return;
|
||||
} else {
|
||||
isUsingDTLS = true;
|
||||
}
|
||||
}
|
||||
|
||||
PacketType domainPacketType = !_domainHandler.isConnected()
|
||||
? PacketTypeDomainConnectRequest : PacketTypeDomainListRequest;
|
||||
|
||||
|
@ -405,8 +366,6 @@ void NodeList::sendDomainServerCheckIn() {
|
|||
|
||||
if (!isUsingDTLS) {
|
||||
writeDatagram(domainServerPacket, _domainHandler.getSockAddr(), QUuid());
|
||||
} else {
|
||||
dtlsSession->writeDatagram(domainServerPacket);
|
||||
}
|
||||
|
||||
const int NUM_DOMAIN_SERVER_CHECKINS_PER_STUN_REQUEST = 5;
|
||||
|
|
|
@ -27,8 +27,6 @@
|
|||
#include <QtNetwork/QHostAddress>
|
||||
#include <QtNetwork/QUdpSocket>
|
||||
|
||||
#include <gnutls/gnutls.h>
|
||||
|
||||
#include "DomainHandler.h"
|
||||
#include "LimitedNodeList.h"
|
||||
#include "Node.h"
|
||||
|
@ -83,8 +81,6 @@ public slots:
|
|||
void reset();
|
||||
void sendDomainServerCheckIn();
|
||||
void pingInactiveNodes();
|
||||
void completedDTLSHandshake();
|
||||
void processAvailableDTLSDatagrams();
|
||||
signals:
|
||||
void limitOfSilentDomainCheckInsReached();
|
||||
private:
|
||||
|
|
|
@ -24,15 +24,13 @@ include(${MACRO_DIR}/LinkHifiLibrary.cmake)
|
|||
link_hifi_library(shared ${TARGET_NAME} "${ROOT_DIR}")
|
||||
link_hifi_library(networking ${TARGET_NAME} "${ROOT_DIR}")
|
||||
|
||||
# link ZLIB and GnuTLS
|
||||
# link ZLIB
|
||||
find_package(ZLIB)
|
||||
find_package(GnuTLS REQUIRED)
|
||||
|
||||
# add a definition for ssize_t so that windows doesn't bail on gnutls.h
|
||||
include_directories(SYSTEM "${ZLIB_INCLUDE_DIRS}")
|
||||
target_link_libraries(${TARGET_NAME} "${ZLIB_LIBRARIES}" Qt5::Widgets)
|
||||
|
||||
# add a definition for ssize_t so that windows doesn't bail
|
||||
if (WIN32)
|
||||
add_definitions(-Dssize_t=long)
|
||||
endif ()
|
||||
|
||||
|
||||
include_directories(SYSTEM "${ZLIB_INCLUDE_DIRS}" "${GNUTLS_INCLUDE_DIR}")
|
||||
target_link_libraries(${TARGET_NAME} "${ZLIB_LIBRARIES}" Qt5::Widgets "${GNUTLS_LIBRARY}")
|
||||
endif ()
|
|
@ -1389,6 +1389,7 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* element,
|
|||
keepDiggingDeeper = (inViewNotLeafCount > 0);
|
||||
|
||||
if (continueThisLevel && keepDiggingDeeper) {
|
||||
|
||||
// at this point, we need to iterate the children who are in view, even if not colored
|
||||
// and we need to determine if there's a deeper tree below them that we care about.
|
||||
//
|
||||
|
@ -1433,7 +1434,12 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* element,
|
|||
//
|
||||
// This only applies in the view frustum case, in other cases, like file save and copy/past where
|
||||
// no viewFrustum was requested, we still want to recurse the child tree.
|
||||
if (!params.viewFrustum || !oneAtBit(childrenColoredBits, originalIndex)) {
|
||||
//
|
||||
// NOTE: some octree styles (like models and particles) will store content in parent elements, and child
|
||||
// elements. In this case, if we stop recursion when we include any data (the colorbits should really be
|
||||
// called databits), then we wouldn't send the children. So those types of Octree's should tell us to keep
|
||||
// recursing, by returning TRUE in recurseChildrenWithData().
|
||||
if (recurseChildrenWithData() || !params.viewFrustum || !oneAtBit(childrenColoredBits, originalIndex)) {
|
||||
childTreeBytesOut = encodeTreeBitstreamRecursion(childElement, packetData, bag, params,
|
||||
thisLevel, nodeLocationThisView);
|
||||
}
|
||||
|
@ -1519,16 +1525,6 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* element,
|
|||
} // end keepDiggingDeeper
|
||||
|
||||
// At this point all our BitMasks are complete... so let's output them to see how they compare...
|
||||
/**
|
||||
printf("This Level's BitMasks: childInTree:");
|
||||
outputBits(childrenExistInTreeBits, false, true);
|
||||
printf(" childInPacket:");
|
||||
outputBits(childrenExistInPacketBits, false, true);
|
||||
printf(" childrenColored:");
|
||||
outputBits(childrenColoredBits, false, true);
|
||||
qDebug("");
|
||||
**/
|
||||
|
||||
// if we were unable to fit this level in our packet, then rewind and add it to the element bag for
|
||||
// sending later...
|
||||
if (continueThisLevel) {
|
||||
|
|
|
@ -209,6 +209,8 @@ public:
|
|||
virtual bool handlesEditPacketType(PacketType packetType) const { return false; }
|
||||
virtual int processEditPacketData(PacketType packetType, const unsigned char* packetData, int packetLength,
|
||||
const unsigned char* editData, int maxLength, const SharedNodePointer& sourceNode) { return 0; }
|
||||
|
||||
virtual bool recurseChildrenWithData() const { return true; }
|
||||
|
||||
|
||||
virtual void update() { }; // nothing to do by default
|
||||
|
|
|
@ -27,14 +27,13 @@ link_hifi_library(fbx ${TARGET_NAME} "${ROOT_DIR}")
|
|||
link_hifi_library(networking ${TARGET_NAME} "${ROOT_DIR}")
|
||||
link_hifi_library(animation ${TARGET_NAME} "${ROOT_DIR}")
|
||||
|
||||
# link ZLIB and GnuTLS
|
||||
# link ZLIB
|
||||
find_package(ZLIB)
|
||||
find_package(GnuTLS REQUIRED)
|
||||
|
||||
# add a definition for ssize_t so that windows doesn't bail on gnutls.h
|
||||
include_directories(SYSTEM "${ZLIB_INCLUDE_DIRS}")
|
||||
target_link_libraries(${TARGET_NAME} "${ZLIB_LIBRARIES}" Qt5::Widgets)
|
||||
|
||||
# add a definition for ssize_t so that windows doesn't bail
|
||||
if (WIN32)
|
||||
add_definitions(-Dssize_t=long)
|
||||
endif ()
|
||||
|
||||
include_directories(SYSTEM "${ZLIB_INCLUDE_DIRS}" "${GNUTLS_INCLUDE_DIR}")
|
||||
target_link_libraries(${TARGET_NAME} "${ZLIB_LIBRARIES}" Qt5::Widgets "${GNUTLS_LIBRARY}")
|
||||
endif ()
|
|
@ -31,12 +31,11 @@ link_hifi_library(animation ${TARGET_NAME} "${ROOT_DIR}")
|
|||
|
||||
# link ZLIB
|
||||
find_package(ZLIB)
|
||||
find_package(GnuTLS REQUIRED)
|
||||
|
||||
# add a definition for ssize_t so that windows doesn't bail on gnutls.h
|
||||
include_directories(SYSTEM "${ZLIB_INCLUDE_DIRS}")
|
||||
target_link_libraries(${TARGET_NAME} "${ZLIB_LIBRARIES}" Qt5::Widgets)
|
||||
|
||||
# add a definition for ssize_t so that windows doesn't bail
|
||||
if (WIN32)
|
||||
add_definitions(-Dssize_t=long)
|
||||
endif ()
|
||||
|
||||
include_directories(SYSTEM "${ZLIB_INCLUDE_DIRS}" "${GNUTLS_INCLUDE_DIR}")
|
||||
target_link_libraries(${TARGET_NAME} "${ZLIB_LIBRARIES}" "${GNUTLS_LIBRARY}" Qt5::Widgets)
|
||||
endif ()
|
|
@ -608,8 +608,20 @@ void ScriptEngine::include(const QString& includeFile) {
|
|||
QUrl url = resolveInclude(includeFile);
|
||||
QString includeContents;
|
||||
|
||||
if (url.scheme() == "file") {
|
||||
if (url.scheme() == "http" || url.scheme() == "ftp") {
|
||||
QNetworkAccessManager* networkManager = new QNetworkAccessManager(this);
|
||||
QNetworkReply* reply = networkManager->get(QNetworkRequest(url));
|
||||
qDebug() << "Downloading included script at" << includeFile;
|
||||
QEventLoop loop;
|
||||
QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
|
||||
loop.exec();
|
||||
includeContents = reply->readAll();
|
||||
} else {
|
||||
#ifdef _WIN32
|
||||
QString fileName = url.toString();
|
||||
#else
|
||||
QString fileName = url.toLocalFile();
|
||||
#endif
|
||||
QFile scriptFile(fileName);
|
||||
if (scriptFile.open(QFile::ReadOnly | QFile::Text)) {
|
||||
qDebug() << "Loading file:" << fileName;
|
||||
|
@ -619,14 +631,6 @@ void ScriptEngine::include(const QString& includeFile) {
|
|||
qDebug() << "ERROR Loading file:" << fileName;
|
||||
emit errorMessage("ERROR Loading file:" + fileName);
|
||||
}
|
||||
} else {
|
||||
QNetworkAccessManager* networkManager = new QNetworkAccessManager(this);
|
||||
QNetworkReply* reply = networkManager->get(QNetworkRequest(url));
|
||||
qDebug() << "Downloading included script at" << includeFile;
|
||||
QEventLoop loop;
|
||||
QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
|
||||
loop.exec();
|
||||
includeContents = reply->readAll();
|
||||
}
|
||||
|
||||
QScriptValue result = _engine.evaluate(includeContents);
|
||||
|
|
|
@ -26,15 +26,13 @@ link_hifi_library(shared ${TARGET_NAME} "${ROOT_DIR}")
|
|||
link_hifi_library(octree ${TARGET_NAME} "${ROOT_DIR}")
|
||||
link_hifi_library(networking ${TARGET_NAME} "${ROOT_DIR}")
|
||||
|
||||
# link ZLIB and GnuTLS
|
||||
# link ZLIB
|
||||
find_package(ZLIB)
|
||||
find_package(GnuTLS REQUIRED)
|
||||
|
||||
# add a definition for ssize_t so that windows doesn't bail on gnutls.h
|
||||
include_directories(SYSTEM "${ZLIB_INCLUDE_DIRS}")
|
||||
target_link_libraries(${TARGET_NAME} "${ZLIB_LIBRARIES}" Qt5::Widgets Qt5::Script)
|
||||
|
||||
# add a definition for ssize_t so that windows doesn't bail
|
||||
if (WIN32)
|
||||
add_definitions(-Dssize_t=long)
|
||||
endif ()
|
||||
|
||||
|
||||
include_directories(SYSTEM "${ZLIB_INCLUDE_DIRS}" "${GNUTLS_INCLUDE_DIR}")
|
||||
target_link_libraries(${TARGET_NAME} "${ZLIB_LIBRARIES}" "${GNUTLS_LIBRARY}" Qt5::Widgets Qt5::Script)
|
||||
endif ()
|
|
@ -55,6 +55,7 @@ public:
|
|||
virtual bool handlesEditPacketType(PacketType packetType) const;
|
||||
virtual int processEditPacketData(PacketType packetType, const unsigned char* packetData, int packetLength,
|
||||
const unsigned char* editData, int maxLength, const SharedNodePointer& node);
|
||||
virtual bool recurseChildrenWithData() const { return false; }
|
||||
|
||||
private:
|
||||
// helper functions for nudgeSubTree
|
||||
|
|
|
@ -34,16 +34,13 @@ link_hifi_library(voxels ${TARGET_NAME} "${ROOT_DIR}")
|
|||
# link in the hifi networking library
|
||||
link_hifi_library(networking ${TARGET_NAME} "${ROOT_DIR}")
|
||||
|
||||
# link GnuTLS
|
||||
find_package(GnuTLS REQUIRED)
|
||||
|
||||
IF (WIN32)
|
||||
target_link_libraries(${TARGET_NAME} Winmm Ws2_32)
|
||||
|
||||
# add a definition for ssize_t so that windows doesn't bail on gnutls.h
|
||||
add_definitions(-Dssize_t=long)
|
||||
ENDIF(WIN32)
|
||||
|
||||
include_directories(SYSTEM "${GNUTLS_INCLUDE_DIR}")
|
||||
target_link_libraries(${TARGET_NAME} Qt5::Script)
|
||||
|
||||
target_link_libraries(${TARGET_NAME} Qt5::Script "${GNUTLS_LIBRARY}")
|
||||
# add a definition for ssize_t so that windows doesn't bail
|
||||
if (WIN32)
|
||||
add_definitions(-Dssize_t=long)
|
||||
endif ()
|
Loading…
Reference in a new issue