mirror of
https://github.com/AleziaKurdis/overte.git
synced 2025-08-18 07:22:16 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi into freeglut_fix
This commit is contained in:
commit
f90062b38c
175 changed files with 2175 additions and 2328 deletions
|
@ -39,4 +39,4 @@ add_subdirectory(domain-server)
|
|||
add_subdirectory(interface)
|
||||
add_subdirectory(tests)
|
||||
add_subdirectory(voxel-edit)
|
||||
add_subdirectory(SvoViewer)
|
||||
add_subdirectory(svo-viewer)
|
||||
|
|
|
@ -3,26 +3,26 @@ cmake_minimum_required(VERSION 2.8)
|
|||
set(TARGET_NAME animation-server)
|
||||
|
||||
set(ROOT_DIR ..)
|
||||
set(MACRO_DIR ${ROOT_DIR}/cmake/macros)
|
||||
set(MACRO_DIR "${ROOT_DIR}/cmake/macros")
|
||||
|
||||
# setup for find modules
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../cmake/modules/")
|
||||
|
||||
# set up the external glm library
|
||||
include(${MACRO_DIR}/IncludeGLM.cmake)
|
||||
include_glm(${TARGET_NAME} ${ROOT_DIR})
|
||||
include("${MACRO_DIR}/IncludeGLM.cmake")
|
||||
include_glm(${TARGET_NAME} "${ROOT_DIR}")
|
||||
|
||||
include(${MACRO_DIR}/SetupHifiProject.cmake)
|
||||
include("${MACRO_DIR}/SetupHifiProject.cmake")
|
||||
setup_hifi_project(${TARGET_NAME} TRUE)
|
||||
|
||||
# link in the shared library
|
||||
include(${MACRO_DIR}/LinkHifiLibrary.cmake)
|
||||
link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR})
|
||||
link_hifi_library(shared ${TARGET_NAME} "${ROOT_DIR}")
|
||||
|
||||
# link in the hifi octree library
|
||||
link_hifi_library(octree ${TARGET_NAME} ${ROOT_DIR})
|
||||
link_hifi_library(octree ${TARGET_NAME} "${ROOT_DIR}")
|
||||
|
||||
# link in the hifi voxels library
|
||||
link_hifi_library(voxels ${TARGET_NAME} ${ROOT_DIR})
|
||||
link_hifi_library(voxels ${TARGET_NAME} "${ROOT_DIR}")
|
||||
|
||||
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
#include <OctalCode.h>
|
||||
#include <PacketHeaders.h>
|
||||
#include <JurisdictionListener.h>
|
||||
#include <SceneUtils.h>
|
||||
#include <SharedUtil.h>
|
||||
#include <VoxelEditPacketSender.h>
|
||||
#include <VoxelTree.h>
|
||||
|
|
|
@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8)
|
|||
set(TARGET_NAME assignment-client)
|
||||
|
||||
set(ROOT_DIR ..)
|
||||
set(MACRO_DIR ${ROOT_DIR}/cmake/macros)
|
||||
set(MACRO_DIR "${ROOT_DIR}/cmake/macros")
|
||||
|
||||
# setup for find modules
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../cmake/modules/")
|
||||
|
@ -12,26 +12,26 @@ find_package(Qt5Network REQUIRED)
|
|||
find_package(Qt5Script REQUIRED)
|
||||
find_package(Qt5Widgets REQUIRED)
|
||||
|
||||
include(${MACRO_DIR}/SetupHifiProject.cmake)
|
||||
include("${MACRO_DIR}/SetupHifiProject.cmake")
|
||||
setup_hifi_project(${TARGET_NAME} TRUE)
|
||||
|
||||
qt5_use_modules(${TARGET_NAME} Network Script Widgets)
|
||||
|
||||
# include glm
|
||||
include(${MACRO_DIR}/IncludeGLM.cmake)
|
||||
include_glm(${TARGET_NAME} ${ROOT_DIR})
|
||||
include("${MACRO_DIR}/IncludeGLM.cmake")
|
||||
include_glm(${TARGET_NAME} "${ROOT_DIR}")
|
||||
|
||||
# link in the shared libraries
|
||||
include(${MACRO_DIR}/LinkHifiLibrary.cmake)
|
||||
link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR})
|
||||
link_hifi_library(audio ${TARGET_NAME} ${ROOT_DIR})
|
||||
link_hifi_library(avatars ${TARGET_NAME} ${ROOT_DIR})
|
||||
link_hifi_library(octree ${TARGET_NAME} ${ROOT_DIR})
|
||||
link_hifi_library(voxels ${TARGET_NAME} ${ROOT_DIR})
|
||||
link_hifi_library(particles ${TARGET_NAME} ${ROOT_DIR})
|
||||
link_hifi_library(metavoxels ${TARGET_NAME} ${ROOT_DIR})
|
||||
link_hifi_library(script-engine ${TARGET_NAME} ${ROOT_DIR})
|
||||
link_hifi_library(embedded-webserver ${TARGET_NAME} ${ROOT_DIR})
|
||||
link_hifi_library(shared ${TARGET_NAME} "${ROOT_DIR}")
|
||||
link_hifi_library(audio ${TARGET_NAME} "${ROOT_DIR}")
|
||||
link_hifi_library(avatars ${TARGET_NAME} "${ROOT_DIR}")
|
||||
link_hifi_library(octree ${TARGET_NAME} "${ROOT_DIR}")
|
||||
link_hifi_library(voxels ${TARGET_NAME} "${ROOT_DIR}")
|
||||
link_hifi_library(particles ${TARGET_NAME} "${ROOT_DIR}")
|
||||
link_hifi_library(metavoxels ${TARGET_NAME} "${ROOT_DIR}")
|
||||
link_hifi_library(script-engine ${TARGET_NAME} "${ROOT_DIR}")
|
||||
link_hifi_library(embedded-webserver ${TARGET_NAME} "${ROOT_DIR}")
|
||||
|
||||
if (UNIX)
|
||||
target_link_libraries(${TARGET_NAME} ${CMAKE_DL_LIBS})
|
||||
|
|
|
@ -27,6 +27,9 @@ Agent::Agent(const QByteArray& packet) :
|
|||
_voxelEditSender(),
|
||||
_particleEditSender()
|
||||
{
|
||||
// be the parent of the script engine so it gets moved when we do
|
||||
_scriptEngine.setParent(this);
|
||||
|
||||
_scriptEngine.getVoxelsScriptingInterface()->setPacketSender(&_voxelEditSender);
|
||||
_scriptEngine.getParticlesScriptingInterface()->setPacketSender(&_particleEditSender);
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ AvatarMixer::AvatarMixer(const QByteArray& packet) :
|
|||
}
|
||||
|
||||
void attachAvatarDataToNode(Node* newNode) {
|
||||
if (newNode->getLinkedData() == NULL) {
|
||||
if (!newNode->getLinkedData()) {
|
||||
newNode->setLinkedData(new AvatarMixerClientData());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,13 +23,13 @@ OctreeSendThread::OctreeSendThread(const QUuid& nodeUUID, OctreeServer* myServer
|
|||
_packetData(),
|
||||
_nodeMissingCount(0)
|
||||
{
|
||||
qDebug() << "client connected";
|
||||
_myServer->clientConnected();
|
||||
qDebug() << "client connected - starting sending thread";
|
||||
OctreeServer::clientConnected();
|
||||
}
|
||||
|
||||
OctreeSendThread::~OctreeSendThread() {
|
||||
qDebug() << "client disconnected";
|
||||
_myServer->clientDisconnected();
|
||||
qDebug() << "client disconnected - ending sending thread";
|
||||
OctreeServer::clientDisconnected();
|
||||
}
|
||||
|
||||
|
||||
|
@ -43,7 +43,6 @@ bool OctreeSendThread::process() {
|
|||
}
|
||||
|
||||
quint64 start = usecTimestampNow();
|
||||
bool gotLock = false;
|
||||
|
||||
// don't do any send processing until the initial load of the octree is complete...
|
||||
if (_myServer->isInitialLoadComplete()) {
|
||||
|
@ -51,25 +50,19 @@ bool OctreeSendThread::process() {
|
|||
|
||||
if (node) {
|
||||
_nodeMissingCount = 0;
|
||||
// make sure the node list doesn't kill our node while we're using it
|
||||
if (node->getMutex().tryLock()) {
|
||||
gotLock = true;
|
||||
OctreeQueryNode* nodeData = NULL;
|
||||
OctreeQueryNode* nodeData = NULL;
|
||||
|
||||
nodeData = (OctreeQueryNode*) node->getLinkedData();
|
||||
nodeData = (OctreeQueryNode*) node->getLinkedData();
|
||||
|
||||
int packetsSent = 0;
|
||||
int packetsSent = 0;
|
||||
|
||||
// Sometimes the node data has not yet been linked, in which case we can't really do anything
|
||||
if (nodeData) {
|
||||
bool viewFrustumChanged = nodeData->updateCurrentViewFrustum();
|
||||
if (_myServer->wantsDebugSending() && _myServer->wantsVerboseDebug()) {
|
||||
printf("nodeData->updateCurrentViewFrustum() changed=%s\n", debug::valueOf(viewFrustumChanged));
|
||||
}
|
||||
packetsSent = packetDistributor(node, nodeData, viewFrustumChanged);
|
||||
// Sometimes the node data has not yet been linked, in which case we can't really do anything
|
||||
if (nodeData) {
|
||||
bool viewFrustumChanged = nodeData->updateCurrentViewFrustum();
|
||||
if (_myServer->wantsDebugSending() && _myServer->wantsVerboseDebug()) {
|
||||
printf("nodeData->updateCurrentViewFrustum() changed=%s\n", debug::valueOf(viewFrustumChanged));
|
||||
}
|
||||
|
||||
node->getMutex().unlock(); // we're done with this node for now.
|
||||
packetsSent = packetDistributor(node, nodeData, viewFrustumChanged);
|
||||
}
|
||||
} else {
|
||||
_nodeMissingCount++;
|
||||
|
@ -81,7 +74,7 @@ bool OctreeSendThread::process() {
|
|||
}
|
||||
|
||||
// Only sleep if we're still running and we got the lock last time we tried, otherwise try to get the lock asap
|
||||
if (isStillRunning() && gotLock) {
|
||||
if (isStillRunning()) {
|
||||
// dynamically sleep until we need to fire off the next set of octree elements
|
||||
int elapsed = (usecTimestampNow() - start);
|
||||
int usecToSleep = OCTREE_SEND_INTERVAL_USECS - elapsed;
|
||||
|
@ -90,9 +83,12 @@ bool OctreeSendThread::process() {
|
|||
PerformanceWarning warn(false,"OctreeSendThread... usleep()",false,&_usleepTime,&_usleepCalls);
|
||||
usleep(usecToSleep);
|
||||
} else {
|
||||
if (_myServer->wantsDebugSending() && _myServer->wantsVerboseDebug()) {
|
||||
std::cout << "Last send took too much time, not sleeping!\n";
|
||||
if (true || (_myServer->wantsDebugSending() && _myServer->wantsVerboseDebug())) {
|
||||
qDebug() << "Last send took too much time (" << (elapsed / USECS_PER_MSEC)
|
||||
<<" msecs), barely sleeping 1 usec!\n";
|
||||
}
|
||||
const int MIN_USEC_TO_SLEEP = 1;
|
||||
usleep(MIN_USEC_TO_SLEEP);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -114,6 +110,13 @@ int OctreeSendThread::handlePacketSend(const SharedNodePointer& node, OctreeQuer
|
|||
int packetsSent = 0;
|
||||
|
||||
// double check that the node has an active socket, otherwise, don't send...
|
||||
|
||||
quint64 lockWaitStart = usecTimestampNow();
|
||||
QMutexLocker locker(&node->getMutex());
|
||||
quint64 lockWaitEnd = usecTimestampNow();
|
||||
float lockWaitElapsedUsec = (float)(lockWaitEnd - lockWaitStart);
|
||||
OctreeServer::trackNodeWaitTime(lockWaitElapsedUsec);
|
||||
|
||||
const HifiSockAddr* nodeAddress = node->getActiveSocket();
|
||||
if (!nodeAddress) {
|
||||
return packetsSent; // without sending...
|
||||
|
@ -440,9 +443,19 @@ int OctreeSendThread::packetDistributor(const SharedNodePointer& node, OctreeQue
|
|||
isFullScene, &nodeData->stats, _myServer->getJurisdiction());
|
||||
|
||||
|
||||
quint64 lockWaitStart = usecTimestampNow();
|
||||
_myServer->getOctree()->lockForRead();
|
||||
quint64 lockWaitEnd = usecTimestampNow();
|
||||
float lockWaitElapsedUsec = (float)(lockWaitEnd - lockWaitStart);
|
||||
OctreeServer::trackTreeWaitTime(lockWaitElapsedUsec);
|
||||
|
||||
nodeData->stats.encodeStarted();
|
||||
|
||||
quint64 encodeStart = usecTimestampNow();
|
||||
bytesWritten = _myServer->getOctree()->encodeTreeBitstream(subTree, &_packetData, nodeData->nodeBag, params);
|
||||
quint64 encodeEnd = usecTimestampNow();
|
||||
int encodeElapsedMsec = (encodeEnd - encodeStart)/USECS_PER_MSEC;
|
||||
OctreeServer::trackEncodeTime(encodeElapsedMsec);
|
||||
|
||||
// If after calling encodeTreeBitstream() there are no nodes left to send, then we know we've
|
||||
// sent the entire scene. We want to know this below so we'll actually write this content into
|
||||
|
@ -555,7 +568,8 @@ int OctreeSendThread::packetDistributor(const SharedNodePointer& node, OctreeQue
|
|||
|
||||
|
||||
quint64 end = usecTimestampNow();
|
||||
int elapsedmsec = (end - start)/1000;
|
||||
int elapsedmsec = (end - start)/USECS_PER_MSEC;
|
||||
OctreeServer::trackLoopTime(elapsedmsec);
|
||||
|
||||
quint64 endCompressCalls = OctreePacketData::getCompressContentCalls();
|
||||
int elapsedCompressCalls = endCompressCalls - startCompressCalls;
|
||||
|
@ -563,7 +577,6 @@ int OctreeSendThread::packetDistributor(const SharedNodePointer& node, OctreeQue
|
|||
quint64 endCompressTimeMsecs = OctreePacketData::getCompressContentTime() / 1000;
|
||||
int elapsedCompressTimeMsecs = endCompressTimeMsecs - startCompressTimeMsecs;
|
||||
|
||||
|
||||
if (elapsedmsec > 100) {
|
||||
if (elapsedmsec > 1000) {
|
||||
int elapsedsec = (end - start)/1000000;
|
||||
|
|
|
@ -20,10 +20,13 @@
|
|||
|
||||
OctreeServer* OctreeServer::_instance = NULL;
|
||||
int OctreeServer::_clientCount = 0;
|
||||
|
||||
SimpleMovingAverage OctreeServer::_averageLoopTime(10000);
|
||||
SimpleMovingAverage OctreeServer::_averageEncodeTime(10000);
|
||||
SimpleMovingAverage OctreeServer::_averageTreeWaitTime(10000);
|
||||
SimpleMovingAverage OctreeServer::_averageNodeWaitTime(10000);
|
||||
|
||||
void OctreeServer::attachQueryNodeToNode(Node* newNode) {
|
||||
if (newNode->getLinkedData() == NULL) {
|
||||
if (!newNode->getLinkedData()) {
|
||||
OctreeQueryNode* newQueryNodeData = _instance->createOctreeQueryNode();
|
||||
newQueryNodeData->resetOctreePacket(true); // don't bump sequence
|
||||
newNode->setLinkedData(newQueryNodeData);
|
||||
|
@ -51,6 +54,7 @@ OctreeServer::OctreeServer(const QByteArray& packet) :
|
|||
_startedUSecs(usecTimestampNow())
|
||||
{
|
||||
_instance = this;
|
||||
_averageLoopTime.updateAverage(0);
|
||||
}
|
||||
|
||||
OctreeServer::~OctreeServer() {
|
||||
|
@ -266,7 +270,27 @@ bool OctreeServer::handleHTTPRequest(HTTPConnection* connection, const QString&
|
|||
.arg(locale.toString((uint)getPacketsTotalPerSecond()).rightJustified(COLUMN_WIDTH, ' '));
|
||||
statsString += QString(" Total Clients Connected: %1 clients\r\n\r\n")
|
||||
.arg(locale.toString((uint)getCurrentClientCount()).rightJustified(COLUMN_WIDTH, ' '));
|
||||
|
||||
|
||||
float averageLoopTime = getAverageLoopTime();
|
||||
statsString += QString().sprintf(" Average packetLoop() time: %5.2f msecs\r\n", averageLoopTime);
|
||||
qDebug() << "averageLoopTime=" << averageLoopTime;
|
||||
|
||||
float averageEncodeTime = getAverageEncodeTime();
|
||||
statsString += QString().sprintf(" Average encode time: %5.2f msecs\r\n", averageEncodeTime);
|
||||
qDebug() << "averageEncodeTime=" << averageEncodeTime;
|
||||
|
||||
|
||||
float averageTreeWaitTime = getAverageTreeWaitTime();
|
||||
statsString += QString().sprintf(" Average tree lock wait time: %7.2f usecs\r\n", averageTreeWaitTime);
|
||||
qDebug() << "averageTreeWaitTime=" << averageTreeWaitTime;
|
||||
|
||||
float averageNodeWaitTime = getAverageNodeWaitTime();
|
||||
statsString += QString().sprintf(" Average node lock wait time: %7.2f usecs\r\n", averageNodeWaitTime);
|
||||
qDebug() << "averageNodeWaitTime=" << averageNodeWaitTime;
|
||||
|
||||
|
||||
statsString += QString("\r\n");
|
||||
|
||||
statsString += QString(" Total Outbound Packets: %1 packets\r\n")
|
||||
.arg(locale.toString((uint)totalOutboundPackets).rightJustified(COLUMN_WIDTH, ' '));
|
||||
statsString += QString(" Total Outbound Bytes: %1 bytes\r\n")
|
||||
|
@ -584,6 +608,9 @@ void OctreeServer::run() {
|
|||
NodeList* nodeList = NodeList::getInstance();
|
||||
nodeList->setOwnerType(getMyNodeType());
|
||||
|
||||
connect(nodeList, SIGNAL(nodeAdded(SharedNodePointer)), SLOT(nodeAdded(SharedNodePointer)));
|
||||
connect(nodeList, SIGNAL(nodeKilled(SharedNodePointer)),SLOT(nodeKilled(SharedNodePointer)));
|
||||
|
||||
// we need to ask the DS about agents so we can ping/reply with them
|
||||
nodeList->addNodeTypeToInterestSet(NodeType::Agent);
|
||||
|
||||
|
@ -689,7 +716,7 @@ void OctreeServer::run() {
|
|||
strftime(localBuffer, MAX_TIME_LENGTH, "%m/%d/%Y %X", localtm);
|
||||
// Convert now to tm struct for UTC
|
||||
tm* gmtm = gmtime(&_started);
|
||||
if (gmtm != NULL) {
|
||||
if (gmtm) {
|
||||
strftime(utcBuffer, MAX_TIME_LENGTH, " [%m/%d/%Y %X UTC]", gmtm);
|
||||
}
|
||||
qDebug() << "Now running... started at: " << localBuffer << utcBuffer;
|
||||
|
@ -703,3 +730,19 @@ void OctreeServer::run() {
|
|||
silentNodeTimer->start(NODE_SILENCE_THRESHOLD_USECS / 1000);
|
||||
}
|
||||
|
||||
void OctreeServer::nodeAdded(SharedNodePointer node) {
|
||||
// we might choose to use this notifier to track clients in a pending state
|
||||
}
|
||||
|
||||
void OctreeServer::nodeKilled(SharedNodePointer node) {
|
||||
OctreeQueryNode* nodeData = static_cast<OctreeQueryNode*>(node->getLinkedData());
|
||||
if (nodeData) {
|
||||
// Note: It should be safe to do this without locking the node, because if any other threads
|
||||
// are using the SharedNodePointer, then they have a reference to the SharedNodePointer and the deleteLater()
|
||||
// won't actually delete it until all threads have released their references to the pointer.
|
||||
// But we can and should clear the linked data so that no one else tries to access it.
|
||||
nodeData->deleteLater();
|
||||
node->setLinkedData(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -74,11 +74,24 @@ public:
|
|||
|
||||
static void attachQueryNodeToNode(Node* newNode);
|
||||
|
||||
static void trackLoopTime(float time) { _averageLoopTime.updateAverage(time); }
|
||||
static float getAverageLoopTime() { return _averageLoopTime.getAverage(); }
|
||||
|
||||
static void trackEncodeTime(float time) { _averageEncodeTime.updateAverage(time); }
|
||||
static float getAverageEncodeTime() { return _averageEncodeTime.getAverage(); }
|
||||
|
||||
static void trackTreeWaitTime(float time) { _averageTreeWaitTime.updateAverage(time); }
|
||||
static float getAverageTreeWaitTime() { return _averageTreeWaitTime.getAverage(); }
|
||||
static void trackNodeWaitTime(float time) { _averageNodeWaitTime.updateAverage(time); }
|
||||
static float getAverageNodeWaitTime() { return _averageNodeWaitTime.getAverage(); }
|
||||
|
||||
bool handleHTTPRequest(HTTPConnection* connection, const QString& path);
|
||||
public slots:
|
||||
/// runs the voxel server assignment
|
||||
void run();
|
||||
void readPendingDatagrams();
|
||||
void nodeAdded(SharedNodePointer node);
|
||||
void nodeKilled(SharedNodePointer node);
|
||||
|
||||
protected:
|
||||
void parsePayload();
|
||||
|
@ -109,6 +122,10 @@ protected:
|
|||
quint64 _startedUSecs;
|
||||
|
||||
static int _clientCount;
|
||||
static SimpleMovingAverage _averageLoopTime;
|
||||
static SimpleMovingAverage _averageEncodeTime;
|
||||
static SimpleMovingAverage _averageTreeWaitTime;
|
||||
static SimpleMovingAverage _averageNodeWaitTime;
|
||||
};
|
||||
|
||||
#endif // __octree_server__OctreeServer__
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
macro(AUTO_MTC TARGET ROOT_DIR)
|
||||
if (NOT TARGET mtc)
|
||||
add_subdirectory(${ROOT_DIR}/tools/mtc ${ROOT_DIR}/tools/mtc)
|
||||
add_subdirectory("${ROOT_DIR}/tools/mtc" "${ROOT_DIR}/tools/mtc")
|
||||
endif (NOT TARGET mtc)
|
||||
|
||||
set(AUTOMTC_SRC ${TARGET}_automtc.cpp)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
MACRO(INCLUDE_GLM TARGET ROOT_DIR)
|
||||
set(GLM_ROOT_DIR ${ROOT_DIR}/externals)
|
||||
set(GLM_ROOT_DIR "${ROOT_DIR}/externals")
|
||||
find_package(GLM REQUIRED)
|
||||
include_directories(${GLM_INCLUDE_DIRS})
|
||||
include_directories("${GLM_INCLUDE_DIRS}")
|
||||
IF(APPLE OR UNIX)
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -isystem ${GLM_INCLUDE_DIRS}")
|
||||
ENDIF(APPLE OR UNIX)
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
MACRO(LINK_HIFI_LIBRARY LIBRARY TARGET ROOT_DIR)
|
||||
if (NOT TARGET ${LIBRARY})
|
||||
add_subdirectory(${ROOT_DIR}/libraries/${LIBRARY} ${ROOT_DIR}/libraries/${LIBRARY})
|
||||
add_subdirectory("${ROOT_DIR}/libraries/${LIBRARY}" "${ROOT_DIR}/libraries/${LIBRARY}")
|
||||
endif (NOT TARGET ${LIBRARY})
|
||||
|
||||
include_directories(${ROOT_DIR}/libraries/${LIBRARY}/src)
|
||||
include_directories("${ROOT_DIR}/libraries/${LIBRARY}/src")
|
||||
|
||||
add_dependencies(${TARGET} ${LIBRARY})
|
||||
target_link_libraries(${TARGET} ${LIBRARY})
|
||||
|
|
|
@ -6,9 +6,9 @@ macro(SETUP_HIFI_PROJECT TARGET INCLUDE_QT)
|
|||
|
||||
file(GLOB SRC_SUBDIRS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/src ${CMAKE_CURRENT_SOURCE_DIR}/src/*)
|
||||
foreach(DIR ${SRC_SUBDIRS})
|
||||
if(IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/src/${DIR})
|
||||
FILE(GLOB DIR_CONTENTS src/${DIR}/*)
|
||||
SET(TARGET_SRCS ${TARGET_SRCS} ${DIR_CONTENTS})
|
||||
if(IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/src/${DIR}")
|
||||
FILE(GLOB DIR_CONTENTS "src/${DIR}/*")
|
||||
SET(TARGET_SRCS ${TARGET_SRCS} "${DIR_CONTENTS}")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
|
|
|
@ -3,14 +3,14 @@ cmake_minimum_required(VERSION 2.8)
|
|||
set(TARGET_NAME domain-server)
|
||||
|
||||
set(ROOT_DIR ..)
|
||||
set(MACRO_DIR ${ROOT_DIR}/cmake/macros)
|
||||
set(MACRO_DIR "${ROOT_DIR}/cmake/macros")
|
||||
|
||||
# setup for find modules
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../cmake/modules/")
|
||||
|
||||
# set up the external glm library
|
||||
include(${MACRO_DIR}/IncludeGLM.cmake)
|
||||
include_glm(${TARGET_NAME} ${ROOT_DIR})
|
||||
include_glm(${TARGET_NAME} "${ROOT_DIR}")
|
||||
|
||||
find_package(Qt5Network REQUIRED)
|
||||
|
||||
|
@ -22,17 +22,17 @@ qt5_use_modules(${TARGET_NAME} Network)
|
|||
|
||||
# remove and then copy the files for the webserver
|
||||
add_custom_command(TARGET ${TARGET_NAME} POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E remove_directory
|
||||
COMMAND "${CMAKE_COMMAND}" -E remove_directory
|
||||
$<TARGET_FILE_DIR:${TARGET_NAME}>/resources/web)
|
||||
add_custom_command(TARGET ${TARGET_NAME} POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
||||
COMMAND "${CMAKE_COMMAND}" -E copy_directory
|
||||
"${PROJECT_SOURCE_DIR}/resources/web"
|
||||
$<TARGET_FILE_DIR:${TARGET_NAME}>/resources/web)
|
||||
|
||||
# link the shared hifi library
|
||||
include(${MACRO_DIR}/LinkHifiLibrary.cmake)
|
||||
link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR})
|
||||
link_hifi_library(embedded-webserver ${TARGET_NAME} ${ROOT_DIR})
|
||||
link_hifi_library(shared ${TARGET_NAME} "${ROOT_DIR}")
|
||||
link_hifi_library(embedded-webserver ${TARGET_NAME} "${ROOT_DIR}")
|
||||
|
||||
IF (WIN32)
|
||||
target_link_libraries(${TARGET_NAME} Winmm Ws2_32)
|
||||
|
|
119
examples/bot.js
119
examples/bot.js
|
@ -3,7 +3,7 @@
|
|||
// hifi
|
||||
//
|
||||
// Created by Stephen Birarda on 2/20/14.
|
||||
// Modified by Philip on 2/26/14
|
||||
// Modified by Philip on 3/3/14
|
||||
// Copyright (c) 2014 HighFidelity, Inc. All rights reserved.
|
||||
//
|
||||
// This is an example script that demonstrates an NPC avatar.
|
||||
|
@ -25,49 +25,55 @@ var CHANCE_OF_BIG_MOVE = 0.1;
|
|||
|
||||
var isMoving = false;
|
||||
var isTurningHead = false;
|
||||
var isPlayingAudio = false;
|
||||
|
||||
var X_MIN = 0.0;
|
||||
var X_MAX = 5.0;
|
||||
var Z_MIN = 0.0;
|
||||
var Z_MAX = 5.0;
|
||||
|
||||
var STARTING_RANGE = 18.0;
|
||||
var MAX_RANGE = 25.0;
|
||||
var MOVE_RANGE_SMALL = 0.5;
|
||||
var MOVE_RANGE_BIG = 5.0;
|
||||
var TURN_RANGE = 45.0;
|
||||
var MOVE_RANGE_BIG = Math.max(X_MAX - X_MIN, Z_MAX - Z_MIN) / 2.0;
|
||||
var TURN_RANGE = 70.0;
|
||||
var STOP_TOLERANCE = 0.05;
|
||||
var MOVE_RATE = 0.05;
|
||||
var TURN_RATE = 0.15;
|
||||
var PITCH_RATE = 0.20;
|
||||
var PITCH_RANGE = 30.0;
|
||||
|
||||
|
||||
var firstPosition = { x: getRandomFloat(0, STARTING_RANGE), y: 0, z: getRandomFloat(0, STARTING_RANGE) };
|
||||
var firstPosition = { x: getRandomFloat(X_MIN, X_MAX), y: 0, z: getRandomFloat(Z_MIN, Z_MAX) };
|
||||
var targetPosition = { x: 0, y: 0, z: 0 };
|
||||
|
||||
var targetDirection = { x: 0, y: 0, z: 0, w: 0 };
|
||||
var currentDirection = { x: 0, y: 0, z: 0, w: 0 };
|
||||
|
||||
var targetHeadPitch = 0.0;
|
||||
|
||||
var sounds = [];
|
||||
sounds.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Vocals/sigh1.raw"));
|
||||
sounds.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Vocals/sigh2.raw"));
|
||||
sounds.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Vocals/sigh3.raw"));
|
||||
sounds.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Vocals/sigh4.raw"));
|
||||
sounds.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Vocals/sigh5.raw"));
|
||||
sounds.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Vocals/sigh6.raw"));
|
||||
sounds.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Vocals/sigh7.raw"));
|
||||
sounds.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Vocals/sigh8.raw"));
|
||||
loadSounds();
|
||||
|
||||
function clamp(val, min, max){
|
||||
return Math.max(min, Math.min(max, val))
|
||||
}
|
||||
|
||||
// Play a random sound from a list of conversational audio clips
|
||||
function audioDone() {
|
||||
isPlayingAudio = false;
|
||||
}
|
||||
|
||||
var AVERAGE_AUDIO_LENGTH = 8000;
|
||||
function playRandomSound(position) {
|
||||
var whichSound = Math.floor((Math.random() * sounds.length) % sounds.length);
|
||||
var audioOptions = new AudioInjectionOptions();
|
||||
audioOptions.volume = 0.25 + (Math.random() * 0.75);
|
||||
audioOptions.position = position;
|
||||
Audio.playSound(sounds[whichSound], audioOptions);
|
||||
print("PlaySound " + whichSound);
|
||||
if (!isPlayingAudio) {
|
||||
var whichSound = Math.floor((Math.random() * sounds.length) % sounds.length);
|
||||
var audioOptions = new AudioInjectionOptions();
|
||||
audioOptions.volume = 0.25 + (Math.random() * 0.75);
|
||||
audioOptions.position = position;
|
||||
Audio.playSound(sounds[whichSound], audioOptions);
|
||||
isPlayingAudio = true;
|
||||
Script.setTimeout(audioDone, AVERAGE_AUDIO_LENGTH);
|
||||
}
|
||||
}
|
||||
|
||||
// change the avatar's position to the random one
|
||||
Avatar.position = firstPosition;
|
||||
Avatar.position = firstPosition;
|
||||
|
||||
// pick an integer between 1 and 20 for the face model for this bot
|
||||
botNumber = getRandomInt(1, 100);
|
||||
|
@ -93,7 +99,7 @@ if (botNumber <= 20) {
|
|||
// there is no need to change the body model - we're using the default
|
||||
Avatar.faceModelURL = "https://s3-us-west-1.amazonaws.com/highfidelity-public/meshes/" + newFaceFilePrefix + ".fst";
|
||||
Avatar.skeletonModelURL = "https://s3-us-west-1.amazonaws.com/highfidelity-public/meshes/" + newBodyFilePrefix + ".fst";
|
||||
Avatar.billboardURL = "https://dl.dropboxusercontent.com/u/1864924/bot-billboard.png";
|
||||
Avatar.billboardURL = "https://s3-us-west-1.amazonaws.com/highfidelity-public/meshes/billboards/bot" + botNumber + ".png";
|
||||
|
||||
Agent.isAvatar = true;
|
||||
|
||||
|
@ -102,6 +108,10 @@ function updateBehavior() {
|
|||
playRandomSound(Avatar.position);
|
||||
}
|
||||
|
||||
if (isPlayingAudio) {
|
||||
Avatar.handPosition = Vec3.sum(Avatar.position, Quat.getFront(Avatar.orientation));
|
||||
}
|
||||
|
||||
if (!isTurningHead && (Math.random() < CHANCE_OF_HEAD_TURNING)) {
|
||||
targetHeadPitch = getRandomFloat(-PITCH_RANGE, PITCH_RANGE);
|
||||
isTurningHead = true;
|
||||
|
@ -120,6 +130,9 @@ function updateBehavior() {
|
|||
} else {
|
||||
targetPosition = Vec3.sum(Avatar.position, Vec3.multiply(front, getRandomFloat(0.0, MOVE_RANGE_SMALL)));
|
||||
}
|
||||
targetPosition.x = clamp(targetPosition.x, X_MIN, X_MAX);
|
||||
targetPosition.z = clamp(targetPosition.z, Z_MIN, Z_MAX);
|
||||
|
||||
isMoving = true;
|
||||
} else {
|
||||
Avatar.position = Vec3.sum(Avatar.position, Vec3.multiply(Vec3.subtract(targetPosition, Avatar.position), MOVE_RATE));
|
||||
|
@ -128,10 +141,56 @@ function updateBehavior() {
|
|||
isMoving = false;
|
||||
}
|
||||
}
|
||||
if (Vec3.length(Avatar.position) > MAX_RANGE) {
|
||||
// Don't let our happy little person get out of the cage
|
||||
isMoving = false;
|
||||
Avatar.position = { x: 0, y: 0, z: 0 };
|
||||
}
|
||||
}
|
||||
Script.willSendVisualDataCallback.connect(updateBehavior);
|
||||
|
||||
function loadSounds() {
|
||||
sounds.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Cocktail+Party+Snippets/Raws/AB1.raw"));
|
||||
sounds.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Cocktail+Party+Snippets/Raws/Anchorman2.raw"));
|
||||
sounds.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Cocktail+Party+Snippets/Raws/B1.raw"));
|
||||
sounds.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Cocktail+Party+Snippets/Raws/B1.raw"));
|
||||
sounds.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Cocktail+Party+Snippets/Raws/Bale1.raw"));
|
||||
sounds.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Cocktail+Party+Snippets/Raws/Bandcamp.raw"));
|
||||
sounds.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Cocktail+Party+Snippets/Raws/Big1.raw"));
|
||||
sounds.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Cocktail+Party+Snippets/Raws/Big2.raw"));
|
||||
sounds.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Cocktail+Party+Snippets/Raws/Brian1.raw"));
|
||||
sounds.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Cocktail+Party+Snippets/Raws/Buster1.raw"));
|
||||
sounds.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Cocktail+Party+Snippets/Raws/CES1.raw"));
|
||||
sounds.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Cocktail+Party+Snippets/Raws/CES2.raw"));
|
||||
sounds.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Cocktail+Party+Snippets/Raws/CES3.raw"));
|
||||
sounds.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Cocktail+Party+Snippets/Raws/CES4.raw"));
|
||||
sounds.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Cocktail+Party+Snippets/Raws/Carrie1.raw"));
|
||||
sounds.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Cocktail+Party+Snippets/Raws/Carrie3.raw"));
|
||||
sounds.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Cocktail+Party+Snippets/Raws/Charlotte1.raw"));
|
||||
sounds.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Cocktail+Party+Snippets/Raws/EN1.raw"));
|
||||
sounds.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Cocktail+Party+Snippets/Raws/EN2.raw"));
|
||||
sounds.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Cocktail+Party+Snippets/Raws/EN3.raw"));
|
||||
sounds.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Cocktail+Party+Snippets/Raws/Eugene1.raw"));
|
||||
sounds.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Cocktail+Party+Snippets/Raws/Francesco1.raw"));
|
||||
sounds.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Cocktail+Party+Snippets/Raws/Italian1.raw"));
|
||||
sounds.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Cocktail+Party+Snippets/Raws/Japanese1.raw"));
|
||||
sounds.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Cocktail+Party+Snippets/Raws/Leigh1.raw"));
|
||||
sounds.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Cocktail+Party+Snippets/Raws/Lucille1.raw"));
|
||||
sounds.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Cocktail+Party+Snippets/Raws/Lucille2.raw"));
|
||||
sounds.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Cocktail+Party+Snippets/Raws/MeanGirls.raw"));
|
||||
sounds.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Cocktail+Party+Snippets/Raws/Murray2.raw"));
|
||||
sounds.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Cocktail+Party+Snippets/Raws/Nigel1.raw"));
|
||||
sounds.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Cocktail+Party+Snippets/Raws/PennyLane.raw"));
|
||||
sounds.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Cocktail+Party+Snippets/Raws/Pitt1.raw"));
|
||||
sounds.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Cocktail+Party+Snippets/Raws/Ricardo.raw"));
|
||||
sounds.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Cocktail+Party+Snippets/Raws/SN.raw"));
|
||||
sounds.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Cocktail+Party+Snippets/Raws/Sake1.raw"));
|
||||
sounds.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Cocktail+Party+Snippets/Raws/Samantha1.raw"));
|
||||
sounds.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Cocktail+Party+Snippets/Raws/Samantha2.raw"));
|
||||
sounds.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Cocktail+Party+Snippets/Raws/Spicoli1.raw"));
|
||||
sounds.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Cocktail+Party+Snippets/Raws/Supernatural.raw"));
|
||||
sounds.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Cocktail+Party+Snippets/Raws/Swearengen1.raw"));
|
||||
sounds.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Cocktail+Party+Snippets/Raws/TheDude.raw"));
|
||||
sounds.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Cocktail+Party+Snippets/Raws/Tony.raw"));
|
||||
sounds.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Cocktail+Party+Snippets/Raws/Triumph1.raw"));
|
||||
sounds.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Cocktail+Party+Snippets/Raws/Uma1.raw"));
|
||||
sounds.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Cocktail+Party+Snippets/Raws/Walken1.raw"));
|
||||
sounds.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Cocktail+Party+Snippets/Raws/Walken2.raw"));
|
||||
sounds.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Cocktail+Party+Snippets/Raws/Z1.raw"));
|
||||
sounds.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Cocktail+Party+Snippets/Raws/Z2.raw"));
|
||||
}
|
||||
|
|
|
@ -945,19 +945,32 @@ function setupMenus() {
|
|||
// hook up menus
|
||||
Menu.menuItemEvent.connect(menuItemEvent);
|
||||
|
||||
// delete the standard application menu item
|
||||
Menu.addSeparator("Edit", "Voxels");
|
||||
// add our menuitems
|
||||
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Voxels", isSeparator: true, beforeItem: "Physics" });
|
||||
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Cut", shortcutKey: "CTRL+X", afterItem: "Voxels" });
|
||||
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Copy", shortcutKey: "CTRL+C", afterItem: "Cut" });
|
||||
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Paste", shortcutKey: "CTRL+V", afterItem: "Copy" });
|
||||
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Nudge", shortcutKey: "CTRL+N", afterItem: "Paste" });
|
||||
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Delete", shortcutKeyEvent: { text: "backspace" }, afterItem: "Nudge" });
|
||||
|
||||
Menu.addSeparator("File", "Voxels");
|
||||
Menu.addMenuItem({ menuName: "File", menuItemName: "Voxels", isSeparator: true, beforeItem: "Settings" });
|
||||
Menu.addMenuItem({ menuName: "File", menuItemName: "Export Voxels", shortcutKey: "CTRL+E", afterItem: "Voxels" });
|
||||
Menu.addMenuItem({ menuName: "File", menuItemName: "Import Voxels", shortcutKey: "CTRL+I", afterItem: "Export Voxels" });
|
||||
}
|
||||
|
||||
function cleanupMenus() {
|
||||
// delete our menuitems
|
||||
Menu.removeSeparator("Edit", "Voxels");
|
||||
Menu.removeMenuItem("Edit", "Cut");
|
||||
Menu.removeMenuItem("Edit", "Copy");
|
||||
Menu.removeMenuItem("Edit", "Paste");
|
||||
Menu.removeMenuItem("Edit", "Nudge");
|
||||
Menu.removeMenuItem("Edit", "Delete");
|
||||
Menu.removeSeparator("File", "Voxels");
|
||||
Menu.removeMenuItem("File", "Export Voxels");
|
||||
Menu.removeMenuItem("File", "Import Voxels");
|
||||
}
|
||||
|
||||
function menuItemEvent(menuItem) {
|
||||
|
||||
// handle clipboard items
|
||||
|
@ -1277,12 +1290,55 @@ function touchEndEvent(event) {
|
|||
}
|
||||
}
|
||||
|
||||
var lastFingerAddVoxel = { x: -1, y: -1, z: -1}; // off of the build-able area
|
||||
var lastFingerDeleteVoxel = { x: -1, y: -1, z: -1}; // off of the build-able area
|
||||
|
||||
function checkControllers() {
|
||||
var controllersPerPalm = 2; // palm and finger
|
||||
for (var palm = 0; palm < 2; palm++) {
|
||||
var palmController = palm * controllersPerPalm;
|
||||
var fingerTipController = palmController + 1;
|
||||
var fingerTipPosition = Controller.getSpatialControlPosition(fingerTipController);
|
||||
|
||||
var BUTTON_COUNT = 6;
|
||||
var BUTTON_BASE = palm * BUTTON_COUNT;
|
||||
var BUTTON_1 = BUTTON_BASE + 1;
|
||||
var BUTTON_2 = BUTTON_BASE + 2;
|
||||
var FINGERTIP_VOXEL_SIZE = 0.05;
|
||||
|
||||
if (Controller.isButtonPressed(BUTTON_1)) {
|
||||
if (Vec3.length(Vec3.subtract(fingerTipPosition,lastFingerAddVoxel)) > (FINGERTIP_VOXEL_SIZE / 2)) {
|
||||
if (whichColor == -1) {
|
||||
newColor = { red: colors[0].red, green: colors[0].green, blue: colors[0].blue };
|
||||
} else {
|
||||
newColor = { red: colors[whichColor].red, green: colors[whichColor].green, blue: colors[whichColor].blue };
|
||||
}
|
||||
|
||||
Voxels.eraseVoxel(fingerTipPosition.x, fingerTipPosition.y, fingerTipPosition.z, FINGERTIP_VOXEL_SIZE);
|
||||
Voxels.setVoxel(fingerTipPosition.x, fingerTipPosition.y, fingerTipPosition.z, FINGERTIP_VOXEL_SIZE,
|
||||
newColor.red, newColor.green, newColor.blue);
|
||||
|
||||
lastFingerAddVoxel = fingerTipPosition;
|
||||
}
|
||||
} else if (Controller.isButtonPressed(BUTTON_2)) {
|
||||
if (Vec3.length(Vec3.subtract(fingerTipPosition,lastFingerDeleteVoxel)) > (FINGERTIP_VOXEL_SIZE / 2)) {
|
||||
Voxels.eraseVoxel(fingerTipPosition.x, fingerTipPosition.y, fingerTipPosition.z, FINGERTIP_VOXEL_SIZE);
|
||||
lastFingerDeleteVoxel = fingerTipPosition;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function update() {
|
||||
var newWindowDimensions = Controller.getViewportDimensions();
|
||||
if (newWindowDimensions.x != windowDimensions.x || newWindowDimensions.y != windowDimensions.y) {
|
||||
windowDimensions = newWindowDimensions;
|
||||
moveTools();
|
||||
}
|
||||
|
||||
if (editToolsOn) {
|
||||
checkControllers();
|
||||
}
|
||||
}
|
||||
|
||||
function wheelEvent(event) {
|
||||
|
@ -1339,6 +1395,7 @@ function scriptEnding() {
|
|||
Overlays.deleteOverlay(thumb);
|
||||
Controller.releaseKeyEvents({ text: "+" });
|
||||
Controller.releaseKeyEvents({ text: "-" });
|
||||
cleanupMenus();
|
||||
}
|
||||
Script.scriptEnding.connect(scriptEnding);
|
||||
|
||||
|
|
149
examples/gun.js
149
examples/gun.js
|
@ -3,16 +3,30 @@
|
|||
// hifi
|
||||
//
|
||||
// Created by Brad Hefta-Gaub on 12/31/13.
|
||||
// Modified by Philip on 3/3/14
|
||||
// Copyright (c) 2013 HighFidelity, Inc. All rights reserved.
|
||||
//
|
||||
// This is an example script that turns the hydra controllers into a particle gun.
|
||||
// This is an example script that turns the hydra controllers and mouse into a particle gun.
|
||||
// It reads the controller, watches for trigger pulls, and launches particles.
|
||||
// The particles it creates have a script that when they collide with Voxels, the
|
||||
// particle will change it's color to match the voxel it hits, and then delete the
|
||||
// voxel.
|
||||
// When particles collide with voxels they blow little holes out of the voxels.
|
||||
//
|
||||
//
|
||||
|
||||
var lastX = 0;
|
||||
var lastY = 0;
|
||||
var yawFromMouse = 0;
|
||||
var pitchFromMouse = 0;
|
||||
var isMouseDown = false;
|
||||
|
||||
var BULLET_VELOCITY = 5.0;
|
||||
|
||||
// Load some sound to use for loading and firing
|
||||
var fireSound = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Guns/GUN-SHOT2.raw");
|
||||
var loadSound = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Guns/Gun_Reload_Weapon22.raw");
|
||||
var impactSound = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Guns/BulletImpact2.raw");
|
||||
var audioOptions = new AudioInjectionOptions();
|
||||
audioOptions.volume = 0.9;
|
||||
|
||||
// initialize our triggers
|
||||
var triggerPulled = new Array();
|
||||
var numberOfTriggers = Controller.getNumberOfTriggers();
|
||||
|
@ -20,7 +34,60 @@ for (t = 0; t < numberOfTriggers; t++) {
|
|||
triggerPulled[t] = false;
|
||||
}
|
||||
|
||||
function checkController() {
|
||||
// Create a reticle image in center of screen
|
||||
var screenSize = Controller.getViewportDimensions();
|
||||
var reticle = Overlays.addOverlay("image", {
|
||||
x: screenSize.x / 2 - 16,
|
||||
y: screenSize.y / 2 - 16,
|
||||
width: 32,
|
||||
height: 32,
|
||||
imageURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/reticle.png",
|
||||
color: { red: 255, green: 255, blue: 255},
|
||||
alpha: 1
|
||||
});
|
||||
|
||||
function shootBullet(position, velocity) {
|
||||
var BULLET_SIZE = 0.02;
|
||||
Particles.addParticle(
|
||||
{ position: position,
|
||||
radius: BULLET_SIZE,
|
||||
color: { red: 200, green: 0, blue: 0 },
|
||||
velocity: velocity,
|
||||
gravity: { x: 0, y: -0.1, z: 0 },
|
||||
damping: 0 });
|
||||
|
||||
// Play firing sounds
|
||||
audioOptions.position = position;
|
||||
Audio.playSound(fireSound, audioOptions);
|
||||
}
|
||||
|
||||
function particleCollisionWithVoxel(particle, voxel) {
|
||||
var HOLE_SIZE = 0.25;
|
||||
var particleProperties = Particles.getParticleProperties(particle);
|
||||
var position = particleProperties.position;
|
||||
Particles.deleteParticle(particle);
|
||||
// Make a hole in this voxel
|
||||
Voxels.eraseVoxel(position.x, position.y, position.z, HOLE_SIZE);
|
||||
//audioOptions.position = position;
|
||||
audioOptions.position = Vec3.sum(Camera.getPosition(), Quat.getFront(Camera.getOrientation()));
|
||||
Audio.playSound(impactSound, audioOptions);
|
||||
}
|
||||
|
||||
function update() {
|
||||
|
||||
// Check for mouseLook movement, update rotation
|
||||
// rotate body yaw for yaw received from mouse
|
||||
var newOrientation = Quat.multiply(MyAvatar.orientation, Quat.fromVec3( { x: 0, y: yawFromMouse, z: 0 } ));
|
||||
MyAvatar.orientation = newOrientation;
|
||||
yawFromMouse = 0;
|
||||
|
||||
// apply pitch from mouse
|
||||
var newPitch = MyAvatar.headPitch + pitchFromMouse;
|
||||
MyAvatar.headPitch = newPitch;
|
||||
pitchFromMouse = 0;
|
||||
|
||||
// Check hydra controller for trigger press
|
||||
|
||||
var numberOfTriggers = Controller.getNumberOfTriggers();
|
||||
var numberOfSpatialControls = Controller.getNumberOfSpatialControls();
|
||||
var controllersPerTrigger = numberOfSpatialControls / numberOfTriggers;
|
||||
|
@ -45,6 +112,7 @@ function checkController() {
|
|||
}
|
||||
|
||||
if (shootABullet) {
|
||||
|
||||
var palmController = t * controllersPerTrigger;
|
||||
var palmPosition = Controller.getSpatialControlPosition(palmController);
|
||||
|
||||
|
@ -67,36 +135,53 @@ function checkController() {
|
|||
y: palmToFingerTipVector.y * linearVelocity,
|
||||
z: palmToFingerTipVector.z * linearVelocity };
|
||||
|
||||
// This is the script for the particles that this gun shoots.
|
||||
var script =
|
||||
" function collisionWithVoxel(voxel) { " +
|
||||
" print('collisionWithVoxel(voxel)... '); " +
|
||||
" print('myID=' + Particle.getID() + '\\n'); " +
|
||||
" var voxelColor = { red: voxel.red, green: voxel.green, blue: voxel.blue };" +
|
||||
" var voxelAt = { x: voxel.x, y: voxel.y, z: voxel.z };" +
|
||||
" var voxelScale = voxel.s;" +
|
||||
" print('voxelColor=' + voxel.red + ', ' + voxel.green + ', ' + voxel.blue + '\\n'); " +
|
||||
" var myColor = Particle.getColor();" +
|
||||
" print('myColor=' + myColor.red + ', ' + myColor.green + ', ' + myColor.blue + '\\n'); " +
|
||||
" Particle.setColor(voxelColor); " +
|
||||
" Voxels.eraseVoxel(voxelAt.x, voxelAt.y, voxelAt.z, voxelScale); " +
|
||||
" print('Voxels.eraseVoxel(' + voxelAt.x + ', ' + voxelAt.y + ', ' + voxelAt.z + ', ' + voxelScale + ')... \\n'); " +
|
||||
" } " +
|
||||
" Particle.collisionWithVoxel.connect(collisionWithVoxel); ";
|
||||
|
||||
Particles.addParticle(
|
||||
{ position: position,
|
||||
radius: 0.05,
|
||||
color: { red: 128, green: 128, blue: 128 },
|
||||
velocity: velocity,
|
||||
gravity: { x: 0, y: -0.1, z: 0 },
|
||||
damping: 0,
|
||||
script: script });
|
||||
shootBullet(position, velocity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function mousePressEvent(event) {
|
||||
isMouseDown = true;
|
||||
lastX = event.x;
|
||||
lastY = event.y;
|
||||
audioOptions.position = Vec3.sum(Camera.getPosition(), Quat.getFront(Camera.getOrientation()));
|
||||
Audio.playSound(loadSound, audioOptions);
|
||||
}
|
||||
|
||||
function mouseReleaseEvent(event) {
|
||||
// position
|
||||
var DISTANCE_FROM_CAMERA = 2.0;
|
||||
var camera = Camera.getPosition();
|
||||
var forwardVector = Quat.getFront(Camera.getOrientation());
|
||||
var newPosition = Vec3.sum(camera, Vec3.multiply(forwardVector, DISTANCE_FROM_CAMERA));
|
||||
var velocity = Vec3.multiply(forwardVector, BULLET_VELOCITY);
|
||||
shootBullet(newPosition, velocity);
|
||||
isMouseDown = false;
|
||||
}
|
||||
|
||||
function mouseMoveEvent(event) {
|
||||
if (isMouseDown) {
|
||||
var MOUSE_YAW_SCALE = -0.25;
|
||||
var MOUSE_PITCH_SCALE = -12.5;
|
||||
var FIXED_MOUSE_TIMESTEP = 0.016;
|
||||
yawFromMouse += ((event.x - lastX) * MOUSE_YAW_SCALE * FIXED_MOUSE_TIMESTEP);
|
||||
pitchFromMouse += ((event.y - lastY) * MOUSE_PITCH_SCALE * FIXED_MOUSE_TIMESTEP);
|
||||
lastX = event.x;
|
||||
lastY = event.y;
|
||||
}
|
||||
}
|
||||
|
||||
function scriptEnding() {
|
||||
Overlays.deleteOverlay(reticle);
|
||||
}
|
||||
|
||||
Particles.particleCollisionWithVoxel.connect(particleCollisionWithVoxel);
|
||||
Script.scriptEnding.connect(scriptEnding);
|
||||
Script.willSendVisualDataCallback.connect(update);
|
||||
Controller.mousePressEvent.connect(mousePressEvent);
|
||||
Controller.mouseReleaseEvent.connect(mouseReleaseEvent);
|
||||
Controller.mouseMoveEvent.connect(mouseMoveEvent);
|
||||
|
||||
|
||||
|
||||
// register the call back so it fires before each data send
|
||||
Script.willSendVisualDataCallback.connect(checkController);
|
||||
|
|
54
examples/localVoxelsExample.js
Normal file
54
examples/localVoxelsExample.js
Normal file
|
@ -0,0 +1,54 @@
|
|||
|
||||
var TREE_SCALE = 16384;
|
||||
var tree = LocalVoxels("tree");
|
||||
tree.setVoxel(0, 0, 0,
|
||||
0.5 * TREE_SCALE,
|
||||
255, 0, 0);
|
||||
tree.setVoxel(0.5 * TREE_SCALE,
|
||||
0.5 * TREE_SCALE,
|
||||
0.5 * TREE_SCALE,
|
||||
0.5 * TREE_SCALE,
|
||||
0, 255, 0);
|
||||
|
||||
var copy = LocalVoxels("copy");
|
||||
tree.pasteFrom(0, 0, 0, TREE_SCALE, "copy");
|
||||
tree.pasteFrom(0, 0, 0, TREE_SCALE, "clipboard");
|
||||
|
||||
var overlay1 = Overlays.addOverlay("localvoxels", {
|
||||
position: {x: 1, y: 1, z: 1},
|
||||
size: 1,
|
||||
name: "tree"
|
||||
});
|
||||
var overlay2 = Overlays.addOverlay("localvoxels", {
|
||||
position: {x: 1, y: 2, z: 1},
|
||||
size: 1,
|
||||
name: "tree"
|
||||
});
|
||||
var overlay3 = Overlays.addOverlay("localvoxels", {
|
||||
position: {x: 1, y: 3, z: 1},
|
||||
size: 1,
|
||||
name: "tree"
|
||||
});
|
||||
var overlay4 = Overlays.addOverlay("localvoxels", {
|
||||
position: {x: 1, y: 4, z: 1},
|
||||
size: 1,
|
||||
name: "copy"
|
||||
});
|
||||
|
||||
var clipboard = Overlays.addOverlay("localvoxels", {
|
||||
position: {x: 1, y: 5, z: 1},
|
||||
size: 1,
|
||||
name: "clipboard"
|
||||
});
|
||||
|
||||
|
||||
|
||||
// When our script shuts down, we should clean up all of our overlays
|
||||
function scriptEnding() {
|
||||
Overlays.deleteOverlay(overlay1);
|
||||
Overlays.deleteOverlay(overlay2);
|
||||
Overlays.deleteOverlay(overlay3);
|
||||
Overlays.deleteOverlay(overlay4);
|
||||
Overlays.deleteOverlay(clipboard);
|
||||
}
|
||||
Script.scriptEnding.connect(scriptEnding);
|
167
examples/voxelDrumming.js
Normal file
167
examples/voxelDrumming.js
Normal file
|
@ -0,0 +1,167 @@
|
|||
//
|
||||
// voxelDrumming.js
|
||||
// hifi
|
||||
//
|
||||
// Created by Brad Hefta-Gaub on 2/14/14.
|
||||
// Copyright (c) 2014 HighFidelity, Inc. All rights reserved.
|
||||
//
|
||||
// This is an example script that demonstrates use of the Overlays, Controller, and Audio classes
|
||||
//
|
||||
// It adds Hydra controller "fingertip on voxels" drumming
|
||||
//
|
||||
|
||||
Menu.addMenuItem({
|
||||
menuName: "Developer > Hand Options",
|
||||
menuItemName: "Voxel Drumming",
|
||||
isCheckable: true,
|
||||
isChecked: false
|
||||
});
|
||||
|
||||
var collisionCenter = new Array();
|
||||
collisionCenter[0] = { x: 0, y: 0, z: 0};
|
||||
collisionCenter[1] = { x: 0, y: 0, z: 0};
|
||||
|
||||
var collisionAge = new Array();
|
||||
collisionAge[0] = 0;
|
||||
collisionAge[1] = 0;
|
||||
|
||||
var collisionDuration = new Array();
|
||||
collisionDuration[0] = 0;
|
||||
collisionDuration[1] = 0;
|
||||
|
||||
var isColliding = new Array();
|
||||
isColliding[0] = false;
|
||||
isColliding[1] = false;
|
||||
|
||||
var highlightVoxel = Overlays.addOverlay("cube",
|
||||
{
|
||||
position: { x: 0, y: 0, z: 0},
|
||||
size: 0,
|
||||
color: { red: 0, green: 0, blue: 0 },
|
||||
visible: false,
|
||||
lineWidth: 3,
|
||||
solid: false
|
||||
});
|
||||
|
||||
var collisionBubble = new Array();
|
||||
collisionBubble[0] = Overlays.addOverlay("sphere",
|
||||
{
|
||||
position: { x: 0, y: 0, z: 0},
|
||||
size: 0,
|
||||
color: { red: 0, green: 0, blue: 0 },
|
||||
alpha: 0.5,
|
||||
visible: false
|
||||
});
|
||||
collisionBubble[1] = Overlays.addOverlay("sphere",
|
||||
{
|
||||
position: { x: 0, y: 0, z: 0},
|
||||
size: 0,
|
||||
color: { red: 0, green: 0, blue: 0 },
|
||||
alpha: 0.5,
|
||||
visible: false
|
||||
});
|
||||
|
||||
var audioOptions = new AudioInjectionOptions();
|
||||
audioOptions.position = { x: MyAvatar.position.x, y: MyAvatar.position.y + 1, z: MyAvatar.position.z };
|
||||
audioOptions.volume = 1;
|
||||
|
||||
|
||||
function clamp(valueToClamp, minValue, maxValue) {
|
||||
return Math.max(minValue, Math.min(maxValue, valueToClamp));
|
||||
}
|
||||
|
||||
function produceCollisionSound(palm, voxelDetail) {
|
||||
// Collision between finger and a voxel plays sound
|
||||
|
||||
var palmVelocity = Controller.getSpatialControlVelocity(palm * 2);
|
||||
var speed = Vec3.length(palmVelocity);
|
||||
var fingerTipPosition = Controller.getSpatialControlPosition(palm * 2 + 1);
|
||||
|
||||
var deltaTime = 1/60; //close enough
|
||||
var LOWEST_FREQUENCY = 100.0;
|
||||
var HERTZ_PER_RGB = 3.0;
|
||||
var DECAY_PER_SAMPLE = 0.0005;
|
||||
var DURATION_MAX = 2.0;
|
||||
var MIN_VOLUME = 0.1;
|
||||
var volume = MIN_VOLUME + clamp(speed, 0.0, (1.0 - MIN_VOLUME));
|
||||
var duration = volume;
|
||||
|
||||
collisionCenter[palm] = fingerTipPosition;
|
||||
collisionAge[palm] = deltaTime;
|
||||
collisionDuration[palm] = duration;
|
||||
|
||||
var voxelBrightness = voxelDetail.red + voxelDetail.green + voxelDetail.blue;
|
||||
var frequency = LOWEST_FREQUENCY + (voxelBrightness * HERTZ_PER_RGB);
|
||||
|
||||
audioOptions.position = fingerTipPosition;
|
||||
Audio.startDrumSound(volume, frequency, DURATION_MAX, DECAY_PER_SAMPLE, audioOptions);
|
||||
}
|
||||
|
||||
function update() {
|
||||
var deltaTime = 1/60; //close enough
|
||||
|
||||
// Voxel Drumming with fingertips if enabled
|
||||
if (Menu.isOptionChecked("Voxel Drumming")) {
|
||||
|
||||
for (var palm = 0; palm < 2; palm++) {
|
||||
var fingerTipPosition = Controller.getSpatialControlPosition(palm * 2 + 1);
|
||||
|
||||
var voxel = Voxels.getVoxelEnclosingPoint(fingerTipPosition);
|
||||
if (voxel.s > 0) {
|
||||
if (!isColliding[palm]) {
|
||||
// Collision has just started
|
||||
isColliding[palm] = true;
|
||||
produceCollisionSound(palm, voxel);
|
||||
|
||||
// Set highlight voxel
|
||||
Overlays.editOverlay(highlightVoxel,
|
||||
{
|
||||
position: { x: voxel.x, y: voxel.y, z: voxel.z},
|
||||
size: voxel.s + 0.002,
|
||||
color: { red: voxel.red + 128, green: voxel.green + 128, blue: voxel.blue + 128 },
|
||||
visible: true
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if (isColliding[palm]) {
|
||||
// Collision has just ended
|
||||
isColliding[palm] = false;
|
||||
Overlays.editOverlay(highlightVoxel, { visible: false });
|
||||
}
|
||||
}
|
||||
|
||||
if (collisionAge[palm] > 0) {
|
||||
collisionAge[palm] += deltaTime;
|
||||
}
|
||||
|
||||
// If hand/voxel collision has happened, render a little expanding sphere
|
||||
if (collisionAge[palm] > 0) {
|
||||
var opacity = clamp(1 - (collisionAge[palm] / collisionDuration[palm]), 0, 1);
|
||||
var size = collisionAge[palm] * 0.25;
|
||||
|
||||
Overlays.editOverlay(collisionBubble[palm],
|
||||
{
|
||||
position: { x: collisionCenter[palm].x, y: collisionCenter[palm].y, z: collisionCenter[palm].z},
|
||||
size: size,
|
||||
color: { red: 255, green: 0, blue: 0 },
|
||||
alpha: 0.5 * opacity,
|
||||
visible: true
|
||||
});
|
||||
|
||||
if (collisionAge[palm] > collisionDuration[palm]) {
|
||||
collisionAge[palm] = 0;
|
||||
Overlays.editOverlay(collisionBubble[palm], { visible: false });
|
||||
}
|
||||
}
|
||||
} // palm loop
|
||||
} // menu item check
|
||||
}
|
||||
Script.willSendVisualDataCallback.connect(update);
|
||||
|
||||
function scriptEnding() {
|
||||
Overlays.deleteOverlay(highlightVoxel);
|
||||
Overlays.deleteOverlay(collisionBubble[0]);
|
||||
Overlays.deleteOverlay(collisionBubble[1]);
|
||||
Menu.removeMenuItem("Developer > Hand Options","Voxel Drumming");
|
||||
}
|
||||
Script.scriptEnding.connect(scriptEnding);
|
|
@ -1,17 +1,17 @@
|
|||
cmake_minimum_required(VERSION 2.8)
|
||||
|
||||
set(ROOT_DIR ..)
|
||||
set(MACRO_DIR ${ROOT_DIR}/cmake/macros)
|
||||
set(MACRO_DIR "${ROOT_DIR}/cmake/macros")
|
||||
|
||||
set(TARGET_NAME interface)
|
||||
project(${TARGET_NAME})
|
||||
|
||||
# setup for find modules
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../cmake/modules/")
|
||||
set(FACESHIFT_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external/faceshift)
|
||||
set(LIBOVR_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external/LibOVR)
|
||||
set(SIXENSE_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external/Sixense)
|
||||
set(VISAGE_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external/visage)
|
||||
set(FACESHIFT_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/external/faceshift")
|
||||
set(LIBOVR_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/external/LibOVR")
|
||||
set(SIXENSE_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/external/Sixense")
|
||||
set(VISAGE_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/external/visage")
|
||||
|
||||
if (DEFINED ENV{JOB_ID})
|
||||
set(BUILD_SEQ $ENV{JOB_ID})
|
||||
|
@ -34,14 +34,14 @@ if (WIN32)
|
|||
add_definitions( -DWINDOWS_LEAN_AND_MEAN ) # needed to make sure windows doesn't go to crazy with its defines
|
||||
|
||||
# windows build needs an external glut, we're using freeglut
|
||||
set(GLUT_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/external/freeglut)
|
||||
set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} ${GLUT_ROOT_PATH})
|
||||
set(GLUT_ROOT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/external/freeglut")
|
||||
set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} "${GLUT_ROOT_PATH}")
|
||||
|
||||
# windows build needs glew (opengl extention wrangler) this will handle providing access to OpenGL methods after 1.1
|
||||
# which are not accessible on windows without glew or some other dynamic linking mechanism
|
||||
set(GLEW_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/external/glew)
|
||||
set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} ${GLEW_ROOT_PATH})
|
||||
include_directories(SYSTEM ${GLEW_ROOT_PATH}/include ${GLUT_ROOT_PATH}/include)
|
||||
set(GLEW_ROOT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/external/glew")
|
||||
set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} "${GLEW_ROOT_PATH}")
|
||||
include_directories(SYSTEM "${GLEW_ROOT_PATH}/include" "${GLUT_ROOT_PATH}/include")
|
||||
|
||||
#set(GL_HEADERS "#define GLEW_STATIC\n#define FREEGLUT_STATIC\n#define FREEGLUT_LIB_PRAGMAS 0\n#include <GL/glew.h>\n#include <GL/wglew.h>\n#include <GL/freeglut_std.h>\n#include <GL/freeglut_ext.h>")
|
||||
set(GL_HEADERS "#define GLEW_STATIC\n#include <windowshacks.h>\n#include <GL/glew.h>\n#include <GL/glut.h>")
|
||||
|
@ -49,18 +49,18 @@ if (WIN32)
|
|||
endif (WIN32)
|
||||
|
||||
# set up the external glm library
|
||||
include(${MACRO_DIR}/IncludeGLM.cmake)
|
||||
include_glm(${TARGET_NAME} ${ROOT_DIR})
|
||||
include("${MACRO_DIR}/IncludeGLM.cmake")
|
||||
include_glm(${TARGET_NAME} "${ROOT_DIR}")
|
||||
|
||||
# create the InterfaceConfig.h file based on GL_HEADERS above
|
||||
configure_file(InterfaceConfig.h.in ${PROJECT_BINARY_DIR}/includes/InterfaceConfig.h)
|
||||
configure_file(InterfaceVersion.h.in ${PROJECT_BINARY_DIR}/includes/InterfaceVersion.h)
|
||||
configure_file(InterfaceConfig.h.in "${PROJECT_BINARY_DIR}/includes/InterfaceConfig.h")
|
||||
configure_file(InterfaceVersion.h.in "${PROJECT_BINARY_DIR}/includes/InterfaceVersion.h")
|
||||
|
||||
# grab the implementation and header files from src dirs
|
||||
file(GLOB INTERFACE_SRCS src/*.cpp src/*.h)
|
||||
foreach(SUBDIR avatar devices renderer ui starfield)
|
||||
file(GLOB_RECURSE SUBDIR_SRCS src/${SUBDIR}/*.cpp src/${SUBDIR}/*.h)
|
||||
set(INTERFACE_SRCS ${INTERFACE_SRCS} ${SUBDIR_SRCS})
|
||||
set(INTERFACE_SRCS ${INTERFACE_SRCS} "${SUBDIR_SRCS}")
|
||||
endforeach(SUBDIR)
|
||||
|
||||
#windows also includes the faceshift externals, because using a lib doesn't work due to debug/release mismatch
|
||||
|
@ -68,8 +68,11 @@ if (WIN32)
|
|||
set(EXTERNAL_SOURCE_SUBDIRS "faceshift")
|
||||
endif (WIN32)
|
||||
foreach(EXTERNAL_SOURCE_SUBDIR ${EXTERNAL_SOURCE_SUBDIRS})
|
||||
file(GLOB_RECURSE SUBDIR_SRCS external/${EXTERNAL_SOURCE_SUBDIR}/src/*.cpp external/${EXTERNAL_SOURCE_SUBDIR}/src/*.c external/${EXTERNAL_SOURCE_SUBDIR}/src/*.h)
|
||||
set(INTERFACE_SRCS ${INTERFACE_SRCS} ${SUBDIR_SRCS})
|
||||
file(GLOB_RECURSE SUBDIR_SRCS
|
||||
"external/${EXTERNAL_SOURCE_SUBDIR}/src/*.cpp"
|
||||
"external/${EXTERNAL_SOURCE_SUBDIR}/src/*.c"
|
||||
"external/${EXTERNAL_SOURCE_SUBDIR}/src/*.h")
|
||||
set(INTERFACE_SRCS ${INTERFACE_SRCS} "${SUBDIR_SRCS}")
|
||||
endforeach(EXTERNAL_SOURCE_SUBDIR)
|
||||
|
||||
find_package(Qt5Core REQUIRED)
|
||||
|
@ -85,10 +88,10 @@ find_package(Qt5Xml REQUIRED)
|
|||
# grab the ui files in resources/ui
|
||||
file (GLOB_RECURSE QT_UI_FILES ui/*.ui)
|
||||
# have qt5 wrap them and generate the appropriate header files
|
||||
qt5_wrap_ui(QT_UI_HEADERS ${QT_UI_FILES})
|
||||
qt5_wrap_ui(QT_UI_HEADERS "${QT_UI_FILES}")
|
||||
|
||||
# add them to the interface source files
|
||||
set(INTERFACE_SRCS ${INTERFACE_SRCS} ${QT_UI_HEADERS})
|
||||
set(INTERFACE_SRCS ${INTERFACE_SRCS} "${QT_UI_HEADERS}")
|
||||
|
||||
if (APPLE)
|
||||
|
||||
|
@ -104,16 +107,16 @@ if (APPLE)
|
|||
# set where in the bundle to put the resources file
|
||||
SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_SOURCE_DIR}/interface.icns PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
|
||||
|
||||
SET(INTERFACE_SRCS ${INTERFACE_SRCS} ${CMAKE_CURRENT_SOURCE_DIR}/interface.icns)
|
||||
SET(INTERFACE_SRCS ${INTERFACE_SRCS} "${CMAKE_CURRENT_SOURCE_DIR}/interface.icns")
|
||||
|
||||
# grab the directories in resources and put them in the right spot in Resources
|
||||
file(GLOB RESOURCE_SUBDIRS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/resources ${CMAKE_CURRENT_SOURCE_DIR}/resources/*)
|
||||
file(GLOB RESOURCE_SUBDIRS RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}/resources" "${CMAKE_CURRENT_SOURCE_DIR}/resources/*")
|
||||
foreach(DIR ${RESOURCE_SUBDIRS})
|
||||
if(IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/resources/${DIR})
|
||||
FILE(GLOB DIR_CONTENTS resources/${DIR}/*)
|
||||
SET_SOURCE_FILES_PROPERTIES(${DIR_CONTENTS} PROPERTIES MACOSX_PACKAGE_LOCATION Resources/${DIR})
|
||||
if(IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/resources/${DIR}")
|
||||
FILE(GLOB DIR_CONTENTS "resources/${DIR}/*")
|
||||
SET_SOURCE_FILES_PROPERTIES(${DIR_CONTENTS} PROPERTIES MACOSX_PACKAGE_LOCATION "Resources/${DIR}")
|
||||
|
||||
SET(INTERFACE_SRCS ${INTERFACE_SRCS} ${DIR_CONTENTS})
|
||||
SET(INTERFACE_SRCS ${INTERFACE_SRCS} "${DIR_CONTENTS}")
|
||||
endif()
|
||||
endforeach()
|
||||
endif (APPLE)
|
||||
|
@ -125,14 +128,14 @@ add_executable(${TARGET_NAME} MACOSX_BUNDLE ${INTERFACE_SRCS})
|
|||
include(${MACRO_DIR}/LinkHifiLibrary.cmake)
|
||||
|
||||
# link required hifi libraries
|
||||
link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR})
|
||||
link_hifi_library(octree ${TARGET_NAME} ${ROOT_DIR})
|
||||
link_hifi_library(voxels ${TARGET_NAME} ${ROOT_DIR})
|
||||
link_hifi_library(metavoxels ${TARGET_NAME} ${ROOT_DIR})
|
||||
link_hifi_library(particles ${TARGET_NAME} ${ROOT_DIR})
|
||||
link_hifi_library(avatars ${TARGET_NAME} ${ROOT_DIR})
|
||||
link_hifi_library(audio ${TARGET_NAME} ${ROOT_DIR})
|
||||
link_hifi_library(script-engine ${TARGET_NAME} ${ROOT_DIR})
|
||||
link_hifi_library(shared ${TARGET_NAME} "${ROOT_DIR}")
|
||||
link_hifi_library(octree ${TARGET_NAME} "${ROOT_DIR}")
|
||||
link_hifi_library(voxels ${TARGET_NAME} "${ROOT_DIR}")
|
||||
link_hifi_library(metavoxels ${TARGET_NAME} "${ROOT_DIR}")
|
||||
link_hifi_library(particles ${TARGET_NAME} "${ROOT_DIR}")
|
||||
link_hifi_library(avatars ${TARGET_NAME} "${ROOT_DIR}")
|
||||
link_hifi_library(audio ${TARGET_NAME} "${ROOT_DIR}")
|
||||
link_hifi_library(script-engine ${TARGET_NAME} "${ROOT_DIR}")
|
||||
|
||||
# find required libraries
|
||||
find_package(Faceshift)
|
||||
|
@ -145,17 +148,17 @@ find_package(ZLIB)
|
|||
# include the Sixense library for Razer Hydra if available
|
||||
if (SIXENSE_FOUND AND NOT DISABLE_SIXENSE)
|
||||
add_definitions(-DHAVE_SIXENSE)
|
||||
include_directories(SYSTEM ${SIXENSE_INCLUDE_DIRS})
|
||||
include_directories(SYSTEM "${SIXENSE_INCLUDE_DIRS}")
|
||||
if (APPLE OR UNIX)
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -isystem ${SIXENSE_INCLUDE_DIRS}")
|
||||
endif (APPLE OR UNIX)
|
||||
target_link_libraries(${TARGET_NAME} ${SIXENSE_LIBRARIES})
|
||||
target_link_libraries(${TARGET_NAME} "${SIXENSE_LIBRARIES}")
|
||||
endif (SIXENSE_FOUND AND NOT DISABLE_SIXENSE)
|
||||
|
||||
# likewise with Visage library for webcam feature tracking
|
||||
if (VISAGE_FOUND AND NOT DISABLE_VISAGE)
|
||||
add_definitions(-DHAVE_VISAGE -DVISAGE_STATIC)
|
||||
include_directories(SYSTEM ${VISAGE_INCLUDE_DIRS})
|
||||
include_directories(SYSTEM "${VISAGE_INCLUDE_DIRS}")
|
||||
if (APPLE)
|
||||
add_definitions(-DMAC_OS_X)
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-comment -isystem ${VISAGE_INCLUDE_DIRS}")
|
||||
|
@ -164,39 +167,39 @@ if (VISAGE_FOUND AND NOT DISABLE_VISAGE)
|
|||
find_library(NEW_STD_LIBRARY libc++.dylib /usr/lib/)
|
||||
target_link_libraries(${TARGET_NAME} ${AVFoundation} ${CoreMedia} ${NEW_STD_LIBRARY})
|
||||
endif (APPLE)
|
||||
target_link_libraries(${TARGET_NAME} ${VISAGE_LIBRARIES})
|
||||
target_link_libraries(${TARGET_NAME} "${VISAGE_LIBRARIES}")
|
||||
endif (VISAGE_FOUND AND NOT DISABLE_VISAGE)
|
||||
|
||||
# and with LibOVR for Oculus Rift
|
||||
if (LIBOVR_FOUND AND NOT DISABLE_LIBOVR)
|
||||
add_definitions(-DHAVE_LIBOVR)
|
||||
include_directories(SYSTEM ${LIBOVR_INCLUDE_DIRS})
|
||||
include_directories(SYSTEM "${LIBOVR_INCLUDE_DIRS}")
|
||||
if (APPLE OR UNIX)
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -isystem ${LIBOVR_INCLUDE_DIRS}")
|
||||
endif (APPLE OR UNIX)
|
||||
target_link_libraries(${TARGET_NAME} ${LIBOVR_LIBRARIES})
|
||||
target_link_libraries(${TARGET_NAME} "${LIBOVR_LIBRARIES}")
|
||||
endif (LIBOVR_FOUND AND NOT DISABLE_LIBOVR)
|
||||
|
||||
qt5_use_modules(${TARGET_NAME} Core Gui Multimedia Network OpenGL Script Svg WebKit WebKitWidgets Xml UiTools)
|
||||
|
||||
# include headers for interface and InterfaceConfig.
|
||||
include_directories(
|
||||
${PROJECT_SOURCE_DIR}/src
|
||||
${PROJECT_BINARY_DIR}/includes
|
||||
"${PROJECT_SOURCE_DIR}/src"
|
||||
"${PROJECT_BINARY_DIR}/includes"
|
||||
)
|
||||
|
||||
# include external library headers
|
||||
# use system flag so warnings are supressed
|
||||
include_directories(
|
||||
SYSTEM
|
||||
${FACESHIFT_INCLUDE_DIRS}
|
||||
${GLM_INCLUDE_DIRS}
|
||||
"${FACESHIFT_INCLUDE_DIRS}"
|
||||
"${GLM_INCLUDE_DIRS}"
|
||||
)
|
||||
|
||||
target_link_libraries(
|
||||
${TARGET_NAME}
|
||||
${FACESHIFT_LIBRARIES}
|
||||
${ZLIB_LIBRARIES}
|
||||
"${FACESHIFT_LIBRARIES}"
|
||||
"${ZLIB_LIBRARIES}"
|
||||
)
|
||||
|
||||
if (APPLE)
|
||||
|
@ -228,8 +231,12 @@ if (APPLE)
|
|||
else (APPLE)
|
||||
find_package(OpenGL REQUIRED)
|
||||
find_package(GLUT REQUIRED)
|
||||
include_directories(${GLUT_INCLUDE_DIR} ${OPENGL_INCLUDE_DIR})
|
||||
target_link_libraries(${TARGET_NAME} ${OPENGL_LIBRARY})
|
||||
|
||||
if (OPENGL_INCLUDE_DIR)
|
||||
include_directories("${GLUT_INCLUDE_DIR}" "${OPENGL_INCLUDE_DIR}")
|
||||
endif (OPENGL_INCLUDE_DIR)
|
||||
|
||||
target_link_libraries(${TARGET_NAME} "${OPENGL_LIBRARY}")
|
||||
endif (APPLE)
|
||||
|
||||
# link target to external libraries
|
||||
|
@ -237,8 +244,8 @@ if (WIN32)
|
|||
target_link_libraries(
|
||||
${TARGET_NAME}
|
||||
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/external/glew/lib/Release/Win32/glew32s.lib
|
||||
${GLUT_ROOT_PATH}/lib/freeglut.lib
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/external/glew/lib/Release/Win32/glew32s.lib"
|
||||
"${GLUT_ROOT_PATH}/lib/freeglut.lib"
|
||||
|
||||
wsock32.lib
|
||||
opengl32.lib
|
||||
|
@ -250,15 +257,15 @@ else (WIN32)
|
|||
|
||||
target_link_libraries(
|
||||
${TARGET_NAME}
|
||||
${CMAKE_THREAD_LIBS_INIT}
|
||||
${GLUT_LIBRARY}
|
||||
"${CMAKE_THREAD_LIBS_INIT}"
|
||||
"${GLUT_LIBRARY}"
|
||||
)
|
||||
endif (UNIX AND NOT APPLE)
|
||||
endif (WIN32)
|
||||
|
||||
# install command for OS X bundle
|
||||
INSTALL(TARGETS ${TARGET_NAME}
|
||||
BUNDLE DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/install COMPONENT Runtime
|
||||
RUNTIME DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/install COMPONENT Runtime
|
||||
BUNDLE DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/install" COMPONENT Runtime
|
||||
RUNTIME DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/install" COMPONENT Runtime
|
||||
)
|
||||
|
||||
|
|
2
interface/external/faceshift/CMakeLists.txt
vendored
2
interface/external/faceshift/CMakeLists.txt
vendored
|
@ -8,4 +8,4 @@ file(GLOB FACESHIFT_SRCS include/*.h src/*.cpp)
|
|||
|
||||
include_directories(include)
|
||||
|
||||
add_library(${TARGET_NAME} ${FACESHIFT_SRCS})
|
||||
add_library(${TARGET_NAME} "${FACESHIFT_SRCS}")
|
||||
|
|
|
@ -61,6 +61,7 @@
|
|||
#include <ResourceCache.h>
|
||||
#include <UUID.h>
|
||||
#include <VoxelSceneStats.h>
|
||||
#include <LocalVoxelsList.h>
|
||||
|
||||
#include "Application.h"
|
||||
#include "ClipboardScriptingInterface.h"
|
||||
|
@ -139,8 +140,6 @@ Application::Application(int& argc, char** argv, timeval &startup_time) :
|
|||
_touchAvgY(0.0f),
|
||||
_isTouchPressed(false),
|
||||
_mousePressed(false),
|
||||
_isHoverVoxel(false),
|
||||
_isHighlightVoxel(false),
|
||||
_chatEntryOn(false),
|
||||
_audio(&_audioScope, STARTUP_JITTER_SAMPLES),
|
||||
_enableProcessVoxelsThread(true),
|
||||
|
@ -313,7 +312,10 @@ Application::Application(int& argc, char** argv, timeval &startup_time) :
|
|||
checkVersion();
|
||||
|
||||
_overlays.init(_glWidget); // do this before scripts load
|
||||
|
||||
|
||||
LocalVoxelsList::getInstance()->addPersistantTree(DOMAIN_TREE_NAME, _voxels.getTree());
|
||||
LocalVoxelsList::getInstance()->addPersistantTree(CLIPBOARD_TREE_NAME, &_clipboard);
|
||||
|
||||
// do this as late as possible so that all required subsystems are inialized
|
||||
loadScripts();
|
||||
}
|
||||
|
@ -360,6 +362,8 @@ Application::~Application() {
|
|||
_myAvatar = NULL;
|
||||
|
||||
delete _glWidget;
|
||||
|
||||
AccountManager::getInstance().destroy();
|
||||
}
|
||||
|
||||
void Application::restoreSizeAndPosition() {
|
||||
|
@ -748,9 +752,7 @@ void Application::keyPressEvent(QKeyEvent* event) {
|
|||
break;
|
||||
|
||||
case Qt::Key_S:
|
||||
if (isShifted && !isMeta) {
|
||||
_voxels.collectStatsForTreesAndVBOs();
|
||||
} else if (isShifted && isMeta) {
|
||||
if (isShifted && isMeta) {
|
||||
Menu::getInstance()->triggerOption(MenuOption::SuppressShortTimings);
|
||||
} else if (!isShifted && isMeta) {
|
||||
takeSnapshot();
|
||||
|
@ -1037,11 +1039,6 @@ void Application::mousePressEvent(QMouseEvent* event) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (!_isHoverVoxel || _myAvatar->getLookAtTargetAvatar()) {
|
||||
// disable for now
|
||||
// _pieMenu.mousePressEvent(_mouseX, _mouseY);
|
||||
}
|
||||
|
||||
} else if (event->button() == Qt::RightButton) {
|
||||
// right click items here
|
||||
}
|
||||
|
@ -1161,7 +1158,7 @@ void Application::dropEvent(QDropEvent *event) {
|
|||
}
|
||||
|
||||
SnapshotMetaData* snapshotData = Snapshot::parseSnapshotData(snapshotPath);
|
||||
if (snapshotData != NULL) {
|
||||
if (snapshotData) {
|
||||
if (!snapshotData->getDomain().isEmpty()) {
|
||||
Menu::getInstance()->goToDomain(snapshotData->getDomain());
|
||||
}
|
||||
|
@ -1296,7 +1293,7 @@ void Application::removeVoxel(glm::vec3 position,
|
|||
_voxelEditSender.sendVoxelEditMessage(PacketTypeVoxelErase, voxel);
|
||||
|
||||
// delete it locally to see the effect immediately (and in case no voxel server is present)
|
||||
_voxels.deleteVoxelAt(voxel.x, voxel.y, voxel.z, voxel.s);
|
||||
_voxels.getTree()->deleteVoxelAt(voxel.x, voxel.y, voxel.z, voxel.s);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1318,8 +1315,7 @@ void Application::makeVoxel(glm::vec3 position,
|
|||
_voxelEditSender.sendVoxelEditMessage(message, voxel);
|
||||
|
||||
// create the voxel locally so it appears immediately
|
||||
|
||||
_voxels.createVoxel(voxel.x, voxel.y, voxel.z, voxel.s,
|
||||
_voxels.getTree()->createVoxel(voxel.x, voxel.y, voxel.z, voxel.s,
|
||||
voxel.red, voxel.green, voxel.blue,
|
||||
isDestructive);
|
||||
}
|
||||
|
@ -1378,10 +1374,11 @@ void Application::exportVoxels(const VoxelDetail& sourceVoxel) {
|
|||
tr("Sparse Voxel Octree Files (*.svo)"));
|
||||
QByteArray fileNameAscii = fileNameString.toLocal8Bit();
|
||||
const char* fileName = fileNameAscii.data();
|
||||
VoxelTreeElement* selectedNode = _voxels.getVoxelAt(sourceVoxel.x, sourceVoxel.y, sourceVoxel.z, sourceVoxel.s);
|
||||
|
||||
VoxelTreeElement* selectedNode = _voxels.getTree()->getVoxelAt(sourceVoxel.x, sourceVoxel.y, sourceVoxel.z, sourceVoxel.s);
|
||||
if (selectedNode) {
|
||||
VoxelTree exportTree;
|
||||
_voxels.copySubTreeIntoNewTree(selectedNode, &exportTree, true);
|
||||
getVoxelTree()->copySubTreeIntoNewTree(selectedNode, &exportTree, true);
|
||||
exportTree.writeToSVOFile(fileName);
|
||||
}
|
||||
|
||||
|
@ -1423,9 +1420,10 @@ void Application::copyVoxels(const VoxelDetail& sourceVoxel) {
|
|||
}
|
||||
|
||||
// then copy onto it if there is something to copy
|
||||
VoxelTreeElement* selectedNode = _voxels.getVoxelAt(sourceVoxel.x, sourceVoxel.y, sourceVoxel.z, sourceVoxel.s);
|
||||
VoxelTreeElement* selectedNode = _voxels.getTree()->getVoxelAt(sourceVoxel.x, sourceVoxel.y, sourceVoxel.z, sourceVoxel.s);
|
||||
if (selectedNode) {
|
||||
_voxels.copySubTreeIntoNewTree(selectedNode, &_sharedVoxelSystem, true);
|
||||
getVoxelTree()->copySubTreeIntoNewTree(selectedNode, _sharedVoxelSystem.getTree(), true);
|
||||
_sharedVoxelSystem.forceRedrawEntireTree();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1436,6 +1434,7 @@ void Application::pasteVoxelsToOctalCode(const unsigned char* octalCodeDestinati
|
|||
args.newBaseOctCode = octalCodeDestination;
|
||||
_sharedVoxelSystem.getTree()->recurseTreeWithOperation(sendVoxelsOperation, &args);
|
||||
|
||||
// Switch back to clipboard if it was an import
|
||||
if (_sharedVoxelSystem.getTree() != &_clipboard) {
|
||||
_sharedVoxelSystem.killLocalVoxels();
|
||||
_sharedVoxelSystem.changeTree(&_clipboard);
|
||||
|
@ -1446,7 +1445,7 @@ void Application::pasteVoxelsToOctalCode(const unsigned char* octalCodeDestinati
|
|||
|
||||
void Application::pasteVoxels(const VoxelDetail& sourceVoxel) {
|
||||
unsigned char* calculatedOctCode = NULL;
|
||||
VoxelTreeElement* selectedNode = _voxels.getVoxelAt(sourceVoxel.x, sourceVoxel.y, sourceVoxel.z, sourceVoxel.s);
|
||||
VoxelTreeElement* selectedNode = _voxels.getTree()->getVoxelAt(sourceVoxel.x, sourceVoxel.y, sourceVoxel.z, sourceVoxel.s);
|
||||
|
||||
// we only need the selected voxel to get the newBaseOctCode, which we can actually calculate from the
|
||||
// voxel size/position details. If we don't have an actual selectedNode then use the mouseVoxel to create a
|
||||
|
@ -1466,7 +1465,7 @@ void Application::pasteVoxels(const VoxelDetail& sourceVoxel) {
|
|||
}
|
||||
|
||||
void Application::nudgeVoxelsByVector(const VoxelDetail& sourceVoxel, const glm::vec3& nudgeVec) {
|
||||
VoxelTreeElement* nodeToNudge = _voxels.getVoxelAt(sourceVoxel.x, sourceVoxel.y, sourceVoxel.z, sourceVoxel.s);
|
||||
VoxelTreeElement* nodeToNudge = _voxels.getTree()->getVoxelAt(sourceVoxel.x, sourceVoxel.y, sourceVoxel.z, sourceVoxel.s);
|
||||
if (nodeToNudge) {
|
||||
_voxels.getTree()->nudgeSubTree(nodeToNudge, nudgeVec, _voxelEditSender);
|
||||
}
|
||||
|
@ -1624,18 +1623,11 @@ bool Application::isLookingAtMyAvatar(Avatar* avatar) {
|
|||
return false;
|
||||
}
|
||||
|
||||
void Application::renderHighlightVoxel(VoxelDetail voxel) {
|
||||
glDisable(GL_LIGHTING);
|
||||
glPushMatrix();
|
||||
glScalef(TREE_SCALE, TREE_SCALE, TREE_SCALE);
|
||||
const float EDGE_EXPAND = 1.02f;
|
||||
glColor3ub(voxel.red + 128, voxel.green + 128, voxel.blue + 128);
|
||||
glTranslatef(voxel.x + voxel.s * 0.5f,
|
||||
voxel.y + voxel.s * 0.5f,
|
||||
voxel.z + voxel.s * 0.5f);
|
||||
glLineWidth(2.0f);
|
||||
glutWireCube(voxel.s * EDGE_EXPAND);
|
||||
glPopMatrix();
|
||||
void Application::updateLOD() {
|
||||
// adjust it unless we were asked to disable this feature
|
||||
if (!Menu::getInstance()->isOptionChecked(MenuOption::DisableAutoAdjustLOD)) {
|
||||
Menu::getInstance()->autoAdjustLOD(_fps);
|
||||
}
|
||||
}
|
||||
|
||||
void Application::updateMouseRay() {
|
||||
|
@ -1708,9 +1700,6 @@ void Application::updateMyAvatarLookAtPosition() {
|
|||
if (_myAvatar->getLookAtTargetAvatar()) {
|
||||
distance = glm::distance(_mouseRayOrigin,
|
||||
static_cast<Avatar*>(_myAvatar->getLookAtTargetAvatar())->getHead()->calculateAverageEyePosition());
|
||||
|
||||
} else if (_isHoverVoxel) {
|
||||
distance = glm::distance(_mouseRayOrigin, getMouseVoxelWorldCoordinates(_hoverVoxel));
|
||||
}
|
||||
const float FIXED_MIN_EYE_DISTANCE = 0.3f;
|
||||
float minEyeDistance = FIXED_MIN_EYE_DISTANCE + (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON ? 0.0f :
|
||||
|
@ -1741,17 +1730,6 @@ void Application::updateMyAvatarLookAtPosition() {
|
|||
_myAvatar->getHead()->setLookAtPosition(lookAtSpot);
|
||||
}
|
||||
|
||||
void Application::updateHoverVoxels(float deltaTime, float& distance, BoxFace& face) {
|
||||
|
||||
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
||||
PerformanceWarning warn(showWarnings, "Application::updateHoverVoxels()");
|
||||
|
||||
if (!_mousePressed) {
|
||||
PerformanceWarning warn(showWarnings, "Application::updateHoverVoxels() _voxels.findRayIntersection()");
|
||||
_isHoverVoxel = _voxels.findRayIntersection(_mouseRayOrigin, _mouseRayDirection, _hoverVoxel, distance, face);
|
||||
}
|
||||
}
|
||||
|
||||
void Application::updateHandAndTouch(float deltaTime) {
|
||||
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
||||
PerformanceWarning warn(showWarnings, "Application::updateHandAndTouch()");
|
||||
|
@ -1892,6 +1870,8 @@ void Application::update(float deltaTime) {
|
|||
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
||||
PerformanceWarning warn(showWarnings, "Application::update()");
|
||||
|
||||
updateLOD();
|
||||
|
||||
// check what's under the mouse and update the mouse voxel
|
||||
updateMouseRay();
|
||||
|
||||
|
@ -1900,11 +1880,6 @@ void Application::update(float deltaTime) {
|
|||
_myAvatar->updateLookAtTargetAvatar();
|
||||
updateMyAvatarLookAtPosition();
|
||||
|
||||
// Find the voxel we are hovering over, and respond if clicked
|
||||
float distance;
|
||||
BoxFace face;
|
||||
|
||||
updateHoverVoxels(deltaTime, distance, face); // clicking on voxels and making sounds
|
||||
updateHandAndTouch(deltaTime); // Update state for touch sensors
|
||||
updateLeap(deltaTime); // Leap finger-sensing device
|
||||
updateSixense(deltaTime); // Razer Hydra controllers
|
||||
|
@ -1921,6 +1896,8 @@ void Application::update(float deltaTime) {
|
|||
_particles.update(); // update the particles...
|
||||
_particleCollisionSystem.update(); // collide the particles...
|
||||
|
||||
_overlays.update(deltaTime);
|
||||
|
||||
// let external parties know we're updating
|
||||
emit simulating(deltaTime);
|
||||
}
|
||||
|
@ -1987,7 +1964,7 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node
|
|||
|
||||
foreach (const SharedNodePointer& node, NodeList::getInstance()->getNodeHash()) {
|
||||
// only send to the NodeTypes that are serverType
|
||||
if (node->getActiveSocket() != NULL && node->getType() == serverType) {
|
||||
if (node->getActiveSocket() && node->getType() == serverType) {
|
||||
totalServers++;
|
||||
|
||||
// get the server bounds for this server
|
||||
|
@ -2047,7 +2024,7 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node
|
|||
|
||||
foreach (const SharedNodePointer& node, nodeList->getNodeHash()) {
|
||||
// only send to the NodeTypes that are serverType
|
||||
if (node->getActiveSocket() != NULL && node->getType() == serverType) {
|
||||
if (node->getActiveSocket() && node->getType() == serverType) {
|
||||
|
||||
|
||||
// get the server bounds for this server
|
||||
|
@ -2370,14 +2347,7 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) {
|
|||
if (Menu::getInstance()->isOptionChecked(MenuOption::Voxels)) {
|
||||
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
|
||||
"Application::displaySide() ... voxels...");
|
||||
|
||||
_voxels.render();
|
||||
|
||||
// double check that our LOD doesn't need to be auto-adjusted
|
||||
// adjust it unless we were asked to disable this feature
|
||||
if (!Menu::getInstance()->isOptionChecked(MenuOption::DisableAutoAdjustLOD)) {
|
||||
Menu::getInstance()->autoAdjustLOD(_fps);
|
||||
}
|
||||
}
|
||||
|
||||
// also, metavoxels
|
||||
|
@ -2409,11 +2379,6 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) {
|
|||
|
||||
// restore default, white specular
|
||||
glMaterialfv(GL_FRONT, GL_SPECULAR, WHITE_SPECULAR_COLOR);
|
||||
|
||||
// Render the highlighted voxel
|
||||
if (_isHighlightVoxel) {
|
||||
renderHighlightVoxel(_highlightVoxel);
|
||||
}
|
||||
}
|
||||
|
||||
bool forceRenderMyHead = (whichCamera.getInterpolatedMode() == CAMERA_MODE_MIRROR);
|
||||
|
@ -2475,7 +2440,7 @@ void Application::computeOffAxisFrustum(float& left, float& right, float& bottom
|
|||
_viewFrustum.computeOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane);
|
||||
}
|
||||
|
||||
const float WHITE_TEXT[] = { 0.93, 0.93, 0.93 };
|
||||
const float WHITE_TEXT[] = { 0.93f, 0.93f, 0.93f };
|
||||
|
||||
void Application::displayOverlay() {
|
||||
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::displayOverlay()");
|
||||
|
@ -2524,15 +2489,6 @@ void Application::displayOverlay() {
|
|||
}
|
||||
}
|
||||
|
||||
// testing rendering coverage map
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::CoverageMapV2)) {
|
||||
renderCoverageMapV2();
|
||||
}
|
||||
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::CoverageMap)) {
|
||||
renderCoverageMap();
|
||||
}
|
||||
|
||||
// Show chat entry field
|
||||
if (_chatEntryOn) {
|
||||
_chatEntry.render(_glWidget->width(), _glWidget->height());
|
||||
|
@ -2974,115 +2930,6 @@ glm::vec2 Application::getScaledScreenPoint(glm::vec2 projectedPoint) {
|
|||
return screenPoint;
|
||||
}
|
||||
|
||||
// render the coverage map on screen
|
||||
void Application::renderCoverageMapV2() {
|
||||
glDisable(GL_LIGHTING);
|
||||
glLineWidth(2.0);
|
||||
glBegin(GL_LINES);
|
||||
glColor3f(0,1,1);
|
||||
|
||||
renderCoverageMapsV2Recursively(&_voxels.myCoverageMapV2);
|
||||
|
||||
glEnd();
|
||||
glEnable(GL_LIGHTING);
|
||||
}
|
||||
|
||||
void Application::renderCoverageMapsV2Recursively(CoverageMapV2* map) {
|
||||
// render ourselves...
|
||||
if (map->isCovered()) {
|
||||
BoundingBox box = map->getBoundingBox();
|
||||
|
||||
glm::vec2 firstPoint = getScaledScreenPoint(box.getVertex(0));
|
||||
glm::vec2 lastPoint(firstPoint);
|
||||
|
||||
for (int i = 1; i < box.getVertexCount(); i++) {
|
||||
glm::vec2 thisPoint = getScaledScreenPoint(box.getVertex(i));
|
||||
|
||||
glVertex2f(lastPoint.x, lastPoint.y);
|
||||
glVertex2f(thisPoint.x, thisPoint.y);
|
||||
lastPoint = thisPoint;
|
||||
}
|
||||
|
||||
glVertex2f(lastPoint.x, lastPoint.y);
|
||||
glVertex2f(firstPoint.x, firstPoint.y);
|
||||
} else {
|
||||
// iterate our children and call render on them.
|
||||
for (int i = 0; i < CoverageMapV2::NUMBER_OF_CHILDREN; i++) {
|
||||
CoverageMapV2* childMap = map->getChild(i);
|
||||
if (childMap) {
|
||||
renderCoverageMapsV2Recursively(childMap);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// render the coverage map on screen
|
||||
void Application::renderCoverageMap() {
|
||||
|
||||
glDisable(GL_LIGHTING);
|
||||
glLineWidth(2.0);
|
||||
glBegin(GL_LINES);
|
||||
glColor3f(0,0,1);
|
||||
|
||||
renderCoverageMapsRecursively(&_voxels.myCoverageMap);
|
||||
|
||||
glEnd();
|
||||
glEnable(GL_LIGHTING);
|
||||
}
|
||||
|
||||
void Application::renderCoverageMapsRecursively(CoverageMap* map) {
|
||||
for (int i = 0; i < map->getPolygonCount(); i++) {
|
||||
|
||||
OctreeProjectedPolygon* polygon = map->getPolygon(i);
|
||||
|
||||
if (polygon->getProjectionType() == (PROJECTION_RIGHT | PROJECTION_NEAR | PROJECTION_BOTTOM)) {
|
||||
glColor3f(.5,0,0); // dark red
|
||||
} else if (polygon->getProjectionType() == (PROJECTION_NEAR | PROJECTION_RIGHT)) {
|
||||
glColor3f(.5,.5,0); // dark yellow
|
||||
} else if (polygon->getProjectionType() == (PROJECTION_NEAR | PROJECTION_LEFT)) {
|
||||
glColor3f(.5,.5,.5); // gray
|
||||
} else if (polygon->getProjectionType() == (PROJECTION_NEAR | PROJECTION_LEFT | PROJECTION_BOTTOM)) {
|
||||
glColor3f(.5,0,.5); // dark magenta
|
||||
} else if (polygon->getProjectionType() == (PROJECTION_NEAR | PROJECTION_BOTTOM)) {
|
||||
glColor3f(.75,0,0); // red
|
||||
} else if (polygon->getProjectionType() == (PROJECTION_NEAR | PROJECTION_TOP)) {
|
||||
glColor3f(1,0,1); // magenta
|
||||
} else if (polygon->getProjectionType() == (PROJECTION_NEAR | PROJECTION_LEFT | PROJECTION_TOP)) {
|
||||
glColor3f(0,0,1); // Blue
|
||||
} else if (polygon->getProjectionType() == (PROJECTION_NEAR | PROJECTION_RIGHT | PROJECTION_TOP)) {
|
||||
glColor3f(0,1,0); // green
|
||||
} else if (polygon->getProjectionType() == (PROJECTION_NEAR)) {
|
||||
glColor3f(1,1,0); // yellow
|
||||
} else if (polygon->getProjectionType() == (PROJECTION_FAR | PROJECTION_RIGHT | PROJECTION_BOTTOM)) {
|
||||
glColor3f(0,.5,.5); // dark cyan
|
||||
} else {
|
||||
glColor3f(1,0,0);
|
||||
}
|
||||
|
||||
glm::vec2 firstPoint = getScaledScreenPoint(polygon->getVertex(0));
|
||||
glm::vec2 lastPoint(firstPoint);
|
||||
|
||||
for (int i = 1; i < polygon->getVertexCount(); i++) {
|
||||
glm::vec2 thisPoint = getScaledScreenPoint(polygon->getVertex(i));
|
||||
|
||||
glVertex2f(lastPoint.x, lastPoint.y);
|
||||
glVertex2f(thisPoint.x, thisPoint.y);
|
||||
lastPoint = thisPoint;
|
||||
}
|
||||
|
||||
glVertex2f(lastPoint.x, lastPoint.y);
|
||||
glVertex2f(firstPoint.x, firstPoint.y);
|
||||
}
|
||||
|
||||
// iterate our children and call render on them.
|
||||
for (int i = 0; i < CoverageMapV2::NUMBER_OF_CHILDREN; i++) {
|
||||
CoverageMap* childMap = map->getChild(i);
|
||||
if (childMap) {
|
||||
renderCoverageMapsRecursively(childMap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Application::renderRearViewMirror(const QRect& region, bool billboard) {
|
||||
bool eyeRelativeCamera = false;
|
||||
if (billboard) {
|
||||
|
@ -3332,7 +3179,7 @@ void Application::deleteVoxelAt(const VoxelDetail& voxel) {
|
|||
_voxelEditSender.sendVoxelEditMessage(PacketTypeVoxelErase, voxel);
|
||||
|
||||
// delete it locally to see the effect immediately (and in case no voxel server is present)
|
||||
_voxels.deleteVoxelAt(voxel.x, voxel.y, voxel.z, voxel.s);
|
||||
_voxels.getTree()->deleteVoxelAt(voxel.x, voxel.y, voxel.z, voxel.s);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -34,12 +34,15 @@
|
|||
#include "BandwidthMeter.h"
|
||||
#include "BuckyBalls.h"
|
||||
#include "Camera.h"
|
||||
#include "ControllerScriptingInterface.h"
|
||||
#include "DatagramProcessor.h"
|
||||
#include "Environment.h"
|
||||
#include "FileLogger.h"
|
||||
#include "GLCanvas.h"
|
||||
#include "Menu.h"
|
||||
#include "MetavoxelSystem.h"
|
||||
#include "PacketHeaders.h"
|
||||
#include "ParticleTreeRenderer.h"
|
||||
#include "PieMenu.h"
|
||||
#include "Stars.h"
|
||||
#include "ViewFrustum.h"
|
||||
|
@ -68,9 +71,6 @@
|
|||
#include "ui/LodToolsDialog.h"
|
||||
#include "ui/LogDialog.h"
|
||||
#include "ui/UpdateDialog.h"
|
||||
#include "FileLogger.h"
|
||||
#include "ParticleTreeRenderer.h"
|
||||
#include "ControllerScriptingInterface.h"
|
||||
#include "ui/Overlays.h"
|
||||
|
||||
|
||||
|
@ -154,6 +154,7 @@ public:
|
|||
Camera* getCamera() { return &_myCamera; }
|
||||
ViewFrustum* getViewFrustum() { return &_viewFrustum; }
|
||||
VoxelSystem* getVoxels() { return &_voxels; }
|
||||
VoxelTree* getVoxelTree() { return _voxels.getTree(); }
|
||||
ParticleTreeRenderer* getParticles() { return &_particles; }
|
||||
MetavoxelSystem* getMetavoxels() { return &_metavoxels; }
|
||||
VoxelSystem* getSharedVoxelSystem() { return &_sharedVoxelSystem; }
|
||||
|
@ -214,10 +215,6 @@ public:
|
|||
NodeToJurisdictionMap& getParticleServerJurisdictions() { return _particleServerJurisdictions; }
|
||||
void pasteVoxelsToOctalCode(const unsigned char* octalCodeDestination);
|
||||
|
||||
/// set a voxel which is to be rendered with a highlight
|
||||
void setHighlightVoxel(const VoxelDetail& highlightVoxel) { _highlightVoxel = highlightVoxel; }
|
||||
void setIsHighlightVoxel(bool isHighlightVoxel) { _isHighlightVoxel = isHighlightVoxel; }
|
||||
|
||||
void skipVersion(QString latestVersion);
|
||||
|
||||
signals:
|
||||
|
@ -261,12 +258,6 @@ private slots:
|
|||
void setEnable3DTVMode(bool enable3DTVMode);
|
||||
void cameraMenuChanged();
|
||||
|
||||
void renderCoverageMap();
|
||||
void renderCoverageMapsRecursively(CoverageMap* map);
|
||||
|
||||
void renderCoverageMapV2();
|
||||
void renderCoverageMapsV2Recursively(CoverageMapV2* map);
|
||||
|
||||
glm::vec2 getScaledScreenPoint(glm::vec2 projectedPoint);
|
||||
|
||||
void closeMirrorView();
|
||||
|
@ -293,11 +284,11 @@ private:
|
|||
void update(float deltaTime);
|
||||
|
||||
// Various helper functions called during update()
|
||||
void updateLOD();
|
||||
void updateMouseRay();
|
||||
void updateFaceshift();
|
||||
void updateVisage();
|
||||
void updateMyAvatarLookAtPosition();
|
||||
void updateHoverVoxels(float deltaTime, float& distance, BoxFace& face);
|
||||
void updateHandAndTouch(float deltaTime);
|
||||
void updateLeap(float deltaTime);
|
||||
void updateSixense(float deltaTime);
|
||||
|
@ -313,7 +304,6 @@ private:
|
|||
bool isLookingAtMyAvatar(Avatar* avatar);
|
||||
|
||||
void renderLookatIndicator(glm::vec3 pointOfInterest);
|
||||
void renderHighlightVoxel(VoxelDetail voxel);
|
||||
|
||||
void updateMyAvatar(float deltaTime);
|
||||
void queryOctree(NodeType_t serverType, PacketType packetType, NodeToJurisdictionMap& jurisdictions);
|
||||
|
@ -434,12 +424,6 @@ private:
|
|||
|
||||
bool _mousePressed; // true if mouse has been pressed (clear when finished)
|
||||
|
||||
VoxelDetail _hoverVoxel; // Stuff about the voxel I am hovering or clicking
|
||||
bool _isHoverVoxel;
|
||||
|
||||
VoxelDetail _highlightVoxel;
|
||||
bool _isHighlightVoxel;
|
||||
|
||||
ChatEntry _chatEntry; // chat entry field
|
||||
bool _chatEntryOn; // Whether to show the chat entry
|
||||
|
||||
|
|
|
@ -90,5 +90,4 @@ void ClipboardScriptingInterface::nudgeVoxel(float x, float y, float z, float s,
|
|||
s / (float)TREE_SCALE };
|
||||
|
||||
Application::getInstance()->nudgeVoxelsByVector(sourceVoxel, nudgeVecInTreeSpace);
|
||||
}
|
||||
|
||||
}
|
|
@ -272,7 +272,6 @@ Menu::Menu() :
|
|||
SLOT(setFilter(bool)));
|
||||
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::DisplayHands, 0, true);
|
||||
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::DisplayHandTargets, 0, false);
|
||||
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::VoxelDrumming, 0, false);
|
||||
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::PlaySlaps, 0, false);
|
||||
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::HandsCollideWithSelf, 0, false);
|
||||
|
||||
|
@ -282,11 +281,6 @@ Menu::Menu() :
|
|||
addCheckableActionToQMenuAndActionHash(timingMenu, MenuOption::TestPing, 0, true);
|
||||
addCheckableActionToQMenuAndActionHash(timingMenu, MenuOption::FrameTimer);
|
||||
addActionToQMenuAndActionHash(timingMenu, MenuOption::RunTimingTests, 0, this, SLOT(runTests()));
|
||||
addActionToQMenuAndActionHash(timingMenu,
|
||||
MenuOption::TreeStats,
|
||||
Qt::SHIFT | Qt::Key_S,
|
||||
appInstance->getVoxels(),
|
||||
SLOT(collectStatsForTreesAndVBOs()));
|
||||
|
||||
QMenu* frustumMenu = developerMenu->addMenu("View Frustum Debugging Tools");
|
||||
addCheckableActionToQMenuAndActionHash(frustumMenu, MenuOption::DisplayFrustum, Qt::SHIFT | Qt::Key_F);
|
||||
|
@ -302,62 +296,6 @@ Menu::Menu() :
|
|||
addCheckableActionToQMenuAndActionHash(renderDebugMenu, MenuOption::PipelineWarnings, Qt::CTRL | Qt::SHIFT | Qt::Key_P);
|
||||
addCheckableActionToQMenuAndActionHash(renderDebugMenu, MenuOption::SuppressShortTimings, Qt::CTRL | Qt::SHIFT | Qt::Key_S);
|
||||
|
||||
addCheckableActionToQMenuAndActionHash(renderDebugMenu, MenuOption::AutomaticallyAuditTree);
|
||||
|
||||
|
||||
addActionToQMenuAndActionHash(renderDebugMenu,
|
||||
MenuOption::ShowAllLocalVoxels,
|
||||
Qt::CTRL | Qt::Key_A,
|
||||
appInstance->getVoxels(),
|
||||
SLOT(showAllLocalVoxels()));
|
||||
|
||||
addActionToQMenuAndActionHash(renderDebugMenu,
|
||||
MenuOption::KillLocalVoxels,
|
||||
Qt::CTRL | Qt::Key_K,
|
||||
appInstance, SLOT(doKillLocalVoxels()));
|
||||
|
||||
addActionToQMenuAndActionHash(renderDebugMenu,
|
||||
MenuOption::RandomizeVoxelColors,
|
||||
Qt::CTRL | Qt::Key_R,
|
||||
appInstance->getVoxels(),
|
||||
SLOT(randomizeVoxelColors()));
|
||||
|
||||
addActionToQMenuAndActionHash(renderDebugMenu,
|
||||
MenuOption::FalseColorRandomly,
|
||||
0,
|
||||
appInstance->getVoxels(),
|
||||
SLOT(falseColorizeRandom()));
|
||||
|
||||
addActionToQMenuAndActionHash(renderDebugMenu,
|
||||
MenuOption::FalseColorEveryOtherVoxel,
|
||||
0,
|
||||
appInstance->getVoxels(),
|
||||
SLOT(falseColorizeRandomEveryOther()));
|
||||
|
||||
addActionToQMenuAndActionHash(renderDebugMenu,
|
||||
MenuOption::FalseColorByDistance,
|
||||
0,
|
||||
appInstance->getVoxels(),
|
||||
SLOT(falseColorizeDistanceFromView()));
|
||||
|
||||
addActionToQMenuAndActionHash(renderDebugMenu,
|
||||
MenuOption::FalseColorOutOfView,
|
||||
0,
|
||||
appInstance->getVoxels(),
|
||||
SLOT(falseColorizeInView()));
|
||||
|
||||
addActionToQMenuAndActionHash(renderDebugMenu,
|
||||
MenuOption::FalseColorBySource,
|
||||
0,
|
||||
appInstance->getVoxels(),
|
||||
SLOT(falseColorizeBySource()));
|
||||
|
||||
addActionToQMenuAndActionHash(renderDebugMenu,
|
||||
MenuOption::ShowTrueColors,
|
||||
Qt::CTRL | Qt::Key_T,
|
||||
appInstance->getVoxels(),
|
||||
SLOT(trueColorize()));
|
||||
|
||||
addCheckableActionToQMenuAndActionHash(renderDebugMenu,
|
||||
MenuOption::CullSharedFaces,
|
||||
Qt::CTRL | Qt::SHIFT | Qt::Key_C,
|
||||
|
@ -372,22 +310,6 @@ Menu::Menu() :
|
|||
appInstance->getVoxels(),
|
||||
SLOT(showCulledSharedFaces()));
|
||||
|
||||
addDisabledActionAndSeparator(renderDebugMenu, "Coverage Maps");
|
||||
addActionToQMenuAndActionHash(renderDebugMenu,
|
||||
MenuOption::FalseColorOccluded,
|
||||
0,
|
||||
appInstance->getVoxels(),
|
||||
SLOT(falseColorizeOccluded()));
|
||||
|
||||
addActionToQMenuAndActionHash(renderDebugMenu,
|
||||
MenuOption::FalseColorOccludedV2,
|
||||
0,
|
||||
appInstance->getVoxels(),
|
||||
SLOT(falseColorizeOccludedV2()));
|
||||
|
||||
addCheckableActionToQMenuAndActionHash(renderDebugMenu, MenuOption::CoverageMap, Qt::SHIFT | Qt::CTRL | Qt::Key_O);
|
||||
addCheckableActionToQMenuAndActionHash(renderDebugMenu, MenuOption::CoverageMapV2, Qt::SHIFT | Qt::CTRL | Qt::Key_P);
|
||||
|
||||
QMenu* audioDebugMenu = developerMenu->addMenu("Audio Debugging Tools");
|
||||
addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::AudioNoiseReduction,
|
||||
0,
|
||||
|
@ -587,9 +509,24 @@ void Menu::handleViewFrustumOffsetKeyModifier(int key) {
|
|||
}
|
||||
}
|
||||
|
||||
void Menu::addDisabledActionAndSeparator(QMenu* destinationMenu, const QString& actionName) {
|
||||
destinationMenu->addSeparator();
|
||||
(destinationMenu->addAction(actionName))->setEnabled(false);
|
||||
void Menu::addDisabledActionAndSeparator(QMenu* destinationMenu, const QString& actionName, int menuItemLocation) {
|
||||
QAction* actionBefore = NULL;
|
||||
if (menuItemLocation >= 0 && destinationMenu->actions().size() > menuItemLocation) {
|
||||
actionBefore = destinationMenu->actions()[menuItemLocation];
|
||||
}
|
||||
if (actionBefore) {
|
||||
QAction* separator = new QAction("",destinationMenu);
|
||||
destinationMenu->insertAction(actionBefore, separator);
|
||||
separator->setSeparator(true);
|
||||
|
||||
QAction* separatorText = new QAction(actionName,destinationMenu);
|
||||
separatorText->setEnabled(false);
|
||||
destinationMenu->insertAction(actionBefore, separatorText);
|
||||
|
||||
} else {
|
||||
destinationMenu->addSeparator();
|
||||
(destinationMenu->addAction(actionName))->setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
QAction* Menu::addActionToQMenuAndActionHash(QMenu* destinationMenu,
|
||||
|
@ -650,11 +587,18 @@ void Menu::removeAction(QMenu* menu, const QString& actionName) {
|
|||
}
|
||||
|
||||
void Menu::setIsOptionChecked(const QString& menuOption, bool isChecked) {
|
||||
return _actionHash.value(menuOption)->setChecked(isChecked);
|
||||
QAction* menu = _actionHash.value(menuOption);
|
||||
if (menu) {
|
||||
menu->setChecked(isChecked);
|
||||
}
|
||||
}
|
||||
|
||||
bool Menu::isOptionChecked(const QString& menuOption) {
|
||||
return _actionHash.value(menuOption)->isChecked();
|
||||
QAction* menu = _actionHash.value(menuOption);
|
||||
if (menu) {
|
||||
return menu->isChecked();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Menu::triggerOption(const QString& menuOption) {
|
||||
|
@ -1317,6 +1261,18 @@ int Menu::findPositionOfMenuItem(QMenu* menu, const QString& searchMenuItem) {
|
|||
return UNSPECIFIED_POSITION; // not found
|
||||
}
|
||||
|
||||
int Menu::positionBeforeSeparatorIfNeeded(QMenu* menu, int requestedPosition) {
|
||||
QList<QAction*> menuActions = menu->actions();
|
||||
if (requestedPosition > 1 && requestedPosition < menuActions.size()) {
|
||||
QAction* beforeRequested = menuActions[requestedPosition - 1];
|
||||
if (beforeRequested->isSeparator()) {
|
||||
requestedPosition--;
|
||||
}
|
||||
}
|
||||
return requestedPosition;
|
||||
}
|
||||
|
||||
|
||||
QMenu* Menu::addMenu(const QString& menuName) {
|
||||
QStringList menuTree = menuName.split(">");
|
||||
QMenu* addTo = NULL;
|
||||
|
@ -1362,6 +1318,21 @@ void Menu::addSeparator(const QString& menuName, const QString& separatorName) {
|
|||
}
|
||||
}
|
||||
|
||||
void Menu::removeSeparator(const QString& menuName, const QString& separatorName) {
|
||||
QMenu* menu = getMenu(menuName);
|
||||
if (menu) {
|
||||
int textAt = findPositionOfMenuItem(menu, separatorName);
|
||||
QList<QAction*> menuActions = menu->actions();
|
||||
QAction* separatorText = menuActions[textAt];
|
||||
QAction* separatorLine = menuActions[textAt - 1];
|
||||
if (separatorLine->isSeparator()) {
|
||||
menu->removeAction(separatorText);
|
||||
menu->removeAction(separatorLine);
|
||||
}
|
||||
}
|
||||
QMenuBar::repaint();
|
||||
}
|
||||
|
||||
void Menu::addMenuItem(const MenuItemProperties& properties) {
|
||||
QMenu* menuObj = getMenu(properties.menuName);
|
||||
if (menuObj) {
|
||||
|
@ -1374,6 +1345,8 @@ void Menu::addMenuItem(const MenuItemProperties& properties) {
|
|||
int requestedPosition = properties.position;
|
||||
if (requestedPosition == UNSPECIFIED_POSITION && !properties.beforeItem.isEmpty()) {
|
||||
requestedPosition = findPositionOfMenuItem(menuObj, properties.beforeItem);
|
||||
// double check that the requested location wasn't a separator label
|
||||
requestedPosition = positionBeforeSeparatorIfNeeded(menuObj, requestedPosition);
|
||||
}
|
||||
if (requestedPosition == UNSPECIFIED_POSITION && !properties.afterItem.isEmpty()) {
|
||||
int afterPosition = findPositionOfMenuItem(menuObj, properties.afterItem);
|
||||
|
@ -1382,9 +1355,11 @@ void Menu::addMenuItem(const MenuItemProperties& properties) {
|
|||
}
|
||||
}
|
||||
|
||||
QAction* menuItemAction;
|
||||
if (properties.isCheckable) {
|
||||
menuItemAction = addCheckableActionToQMenuAndActionHash(menuObj, properties.menuItemName,
|
||||
QAction* menuItemAction = NULL;
|
||||
if (properties.isSeparator) {
|
||||
addDisabledActionAndSeparator(menuObj, properties.menuItemName, requestedPosition);
|
||||
} else if (properties.isCheckable) {
|
||||
menuItemAction = addCheckableActionToQMenuAndActionHash(menuObj, properties.menuItemName,
|
||||
properties.shortcutKeySequence, properties.isChecked,
|
||||
MenuScriptingInterface::getInstance(), SLOT(menuItemTriggered()), requestedPosition);
|
||||
} else {
|
||||
|
@ -1392,7 +1367,7 @@ void Menu::addMenuItem(const MenuItemProperties& properties) {
|
|||
MenuScriptingInterface::getInstance(), SLOT(menuItemTriggered()),
|
||||
QAction::NoRole, requestedPosition);
|
||||
}
|
||||
if (shortcut) {
|
||||
if (shortcut && menuItemAction) {
|
||||
connect(shortcut, SIGNAL(activated()), menuItemAction, SLOT(trigger()));
|
||||
}
|
||||
QMenuBar::repaint();
|
||||
|
|
|
@ -84,6 +84,7 @@ public:
|
|||
void autoAdjustLOD(float currentFPS);
|
||||
void setVoxelSizeScale(float sizeScale);
|
||||
float getVoxelSizeScale() const { return _voxelSizeScale; }
|
||||
float getAvatarLODDistanceMultiplier() const { return DEFAULT_OCTREE_SIZE_SCALE / _voxelSizeScale; }
|
||||
void setBoundaryLevelAdjust(int boundaryLevelAdjust);
|
||||
int getBoundaryLevelAdjust() const { return _boundaryLevelAdjust; }
|
||||
|
||||
|
@ -124,6 +125,7 @@ public slots:
|
|||
QMenu* addMenu(const QString& menuName);
|
||||
void removeMenu(const QString& menuName);
|
||||
void addSeparator(const QString& menuName, const QString& separatorName);
|
||||
void removeSeparator(const QString& menuName, const QString& separatorName);
|
||||
void addMenuItem(const MenuItemProperties& properties);
|
||||
void removeMenuItem(const QString& menuName, const QString& menuitem);
|
||||
|
||||
|
@ -152,7 +154,8 @@ private:
|
|||
void scanMenu(QMenu* menu, settingsAction modifySetting, QSettings* set);
|
||||
|
||||
/// helper method to have separators with labels that are also compatible with OS X
|
||||
void addDisabledActionAndSeparator(QMenu* destinationMenu, const QString& actionName);
|
||||
void addDisabledActionAndSeparator(QMenu* destinationMenu, const QString& actionName,
|
||||
int menuItemLocation = UNSPECIFIED_POSITION);
|
||||
|
||||
QAction* addCheckableActionToQMenuAndActionHash(QMenu* destinationMenu,
|
||||
const QString& actionName,
|
||||
|
@ -172,6 +175,7 @@ private:
|
|||
|
||||
QAction* getMenuAction(const QString& menuName);
|
||||
int findPositionOfMenuItem(QMenu* menu, const QString& searchMenuItem);
|
||||
int positionBeforeSeparatorIfNeeded(QMenu* menu, int requestedPosition);
|
||||
QMenu* getMenu(const QString& menuName);
|
||||
|
||||
|
||||
|
@ -203,7 +207,6 @@ namespace MenuOption {
|
|||
const QString Avatars = "Avatars";
|
||||
const QString Atmosphere = "Atmosphere";
|
||||
const QString DisableAutoAdjustLOD = "Disable Automatically Adjusting LOD";
|
||||
const QString AutomaticallyAuditTree = "Automatically Audit Tree Stats";
|
||||
const QString Bandwidth = "Bandwidth Display";
|
||||
const QString BandwidthDetails = "Bandwidth Details";
|
||||
const QString BuckyBalls = "Bucky Balls";
|
||||
|
@ -213,8 +216,6 @@ namespace MenuOption {
|
|||
const QString CollideWithParticles = "Collide With Particles";
|
||||
const QString CollideWithVoxels = "Collide With Voxels";
|
||||
const QString CollideWithEnvironment = "Collide With World Boundaries";
|
||||
const QString CoverageMap = "Render Coverage Map";
|
||||
const QString CoverageMapV2 = "Render Coverage Map V2";
|
||||
const QString CullSharedFaces = "Cull Shared Voxel Faces";
|
||||
const QString DecreaseAvatarSize = "Decrease Avatar Size";
|
||||
const QString DecreaseVoxelSize = "Decrease Voxel Size";
|
||||
|
@ -231,13 +232,6 @@ namespace MenuOption {
|
|||
const QString HeadMouse = "Head Mouse";
|
||||
const QString HandsCollideWithSelf = "Collide With Self";
|
||||
const QString FaceshiftTCP = "Faceshift (TCP)";
|
||||
const QString FalseColorByDistance = "FALSE Color By Distance";
|
||||
const QString FalseColorBySource = "FALSE Color By Source";
|
||||
const QString FalseColorEveryOtherVoxel = "FALSE Color Every Other Randomly";
|
||||
const QString FalseColorOccluded = "FALSE Color Occluded Voxels";
|
||||
const QString FalseColorOccludedV2 = "FALSE Color Occluded V2 Voxels";
|
||||
const QString FalseColorOutOfView = "FALSE Color Voxel Out of View";
|
||||
const QString FalseColorRandomly = "FALSE Color Voxels Randomly";
|
||||
const QString FirstPerson = "First Person";
|
||||
const QString FrameTimer = "Show Timer";
|
||||
const QString FrustumRenderMode = "Render Mode";
|
||||
|
@ -249,7 +243,6 @@ namespace MenuOption {
|
|||
const QString GoTo = "Go To...";
|
||||
const QString IncreaseAvatarSize = "Increase Avatar Size";
|
||||
const QString IncreaseVoxelSize = "Increase Voxel Size";
|
||||
const QString KillLocalVoxels = "Kill Local Voxels";
|
||||
const QString GoHome = "Go Home";
|
||||
const QString Gravity = "Use Gravity";
|
||||
const QString LodTools = "LOD Tools";
|
||||
|
@ -274,7 +267,6 @@ namespace MenuOption {
|
|||
const QString PipelineWarnings = "Show Render Pipeline Warnings";
|
||||
const QString PlaySlaps = "Play Slaps";
|
||||
const QString Preferences = "Preferences...";
|
||||
const QString RandomizeVoxelColors = "Randomize Voxel TRUE Colors";
|
||||
const QString ReloadAllScripts = "Reload All Scripts";
|
||||
const QString RenderSkeletonCollisionProxies = "Skeleton Collision Proxies";
|
||||
const QString RenderHeadCollisionProxies = "Head Collision Proxies";
|
||||
|
@ -283,19 +275,15 @@ namespace MenuOption {
|
|||
const QString SettingsImport = "Import Settings";
|
||||
const QString Shadows = "Shadows";
|
||||
const QString SettingsExport = "Export Settings";
|
||||
const QString ShowAllLocalVoxels = "Show All Local Voxels";
|
||||
const QString ShowCulledSharedFaces = "Show Culled Shared Voxel Faces";
|
||||
const QString ShowTrueColors = "Show TRUE Colors";
|
||||
const QString SuppressShortTimings = "Suppress Timings Less than 10ms";
|
||||
const QString Stars = "Stars";
|
||||
const QString Stats = "Stats";
|
||||
const QString StopAllScripts = "Stop All Scripts";
|
||||
const QString TestPing = "Test Ping";
|
||||
const QString TreeStats = "Calculate Tree Stats";
|
||||
const QString TransmitterDrive = "Transmitter Drive";
|
||||
const QString Quit = "Quit";
|
||||
const QString Voxels = "Voxels";
|
||||
const QString VoxelDrumming = "Voxel Drumming";
|
||||
const QString VoxelMode = "Cycle Voxel Mode";
|
||||
const QString VoxelStats = "Voxel Stats";
|
||||
const QString VoxelTextures = "Voxel Textures";
|
||||
|
|
|
@ -38,6 +38,12 @@ void MenuScriptingInterface::addSeparator(const QString& menuName, const QString
|
|||
Q_ARG(const QString&, separatorName));
|
||||
}
|
||||
|
||||
void MenuScriptingInterface::removeSeparator(const QString& menuName, const QString& separatorName) {
|
||||
QMetaObject::invokeMethod(Menu::getInstance(), "removeSeparator",
|
||||
Q_ARG(const QString&, menuName),
|
||||
Q_ARG(const QString&, separatorName));
|
||||
}
|
||||
|
||||
void MenuScriptingInterface::addMenuItem(const MenuItemProperties& properties) {
|
||||
QMetaObject::invokeMethod(Menu::getInstance(), "addMenuItem", Q_ARG(const MenuItemProperties&, properties));
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ public slots:
|
|||
void removeMenu(const QString& menuName);
|
||||
|
||||
void addSeparator(const QString& menuName, const QString& separatorName);
|
||||
void removeSeparator(const QString& menuName, const QString& separatorName);
|
||||
|
||||
void addMenuItem(const MenuItemProperties& properties);
|
||||
void addMenuItem(const QString& menuName, const QString& menuitem, const QString& shortcutKey);
|
||||
|
|
|
@ -33,10 +33,7 @@ void ParticleTreeRenderer::init() {
|
|||
void ParticleTreeRenderer::update() {
|
||||
if (_tree) {
|
||||
ParticleTree* tree = static_cast<ParticleTree*>(_tree);
|
||||
if (tree->tryLockForWrite()) {
|
||||
tree->update();
|
||||
tree->unlock();
|
||||
}
|
||||
tree->update();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include <VoxelImporter.h>
|
||||
#include <Application.h>
|
||||
#include <LocalVoxelsList.h>
|
||||
|
||||
#include <QFileInfo>
|
||||
#include <QThreadPool>
|
||||
|
@ -31,6 +32,8 @@ VoxelImporter::VoxelImporter(QWidget* parent) :
|
|||
_task(NULL),
|
||||
_didImport(false)
|
||||
{
|
||||
LocalVoxelsList::getInstance()->addPersistantTree(IMPORT_TREE_NAME, &_voxelTree);
|
||||
|
||||
connect(&_voxelTree, SIGNAL(importProgress(int)), &_importDialog, SLOT(setProgressBarValue(int)));
|
||||
connect(&_importDialog, SIGNAL(canceled()), this, SLOT(cancel()));
|
||||
connect(&_importDialog, SIGNAL(accepted()), this, SLOT(import()));
|
||||
|
@ -143,11 +146,11 @@ void ImportTask::run() {
|
|||
|
||||
// Then we call the righ method for the job
|
||||
if (_filename.endsWith(".png", Qt::CaseInsensitive)) {
|
||||
voxelSystem->readFromSquareARGB32Pixels(_filename.toLocal8Bit().data());
|
||||
voxelSystem->getTree()->readFromSquareARGB32Pixels(_filename.toLocal8Bit().data());
|
||||
} else if (_filename.endsWith(".svo", Qt::CaseInsensitive)) {
|
||||
voxelSystem->readFromSVOFile(_filename.toLocal8Bit().data());
|
||||
voxelSystem->getTree()->readFromSVOFile(_filename.toLocal8Bit().data());
|
||||
} else if (_filename.endsWith(".schematic", Qt::CaseInsensitive)) {
|
||||
voxelSystem->readFromSchematicFile(_filename.toLocal8Bit().data());
|
||||
voxelSystem->getTree()->readFromSchematicFile(_filename.toLocal8Bit().data());
|
||||
} else {
|
||||
// We should never get here.
|
||||
qDebug() << "[ERROR] Invalid file extension." << endl;
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -14,7 +14,6 @@
|
|||
|
||||
#include <SharedUtil.h>
|
||||
|
||||
#include <CoverageMapV2.h>
|
||||
#include <NodeData.h>
|
||||
#include <ViewFrustum.h>
|
||||
#include <VoxelTree.h>
|
||||
|
@ -45,7 +44,7 @@ class VoxelSystem : public NodeData, public OctreeElementDeleteHook, public Octr
|
|||
friend class VoxelHideShowThread;
|
||||
|
||||
public:
|
||||
VoxelSystem(float treeScale = TREE_SCALE, int maxVoxels = DEFAULT_MAX_VOXELS_PER_SYSTEM);
|
||||
VoxelSystem(float treeScale = TREE_SCALE, int maxVoxels = DEFAULT_MAX_VOXELS_PER_SYSTEM, VoxelTree* tree = NULL);
|
||||
~VoxelSystem();
|
||||
|
||||
void setDataSourceUUID(const QUuid& dataSourceUUID) { _dataSourceUUID = dataSourceUUID; }
|
||||
|
@ -53,8 +52,8 @@ public:
|
|||
|
||||
int parseData(const QByteArray& packet);
|
||||
|
||||
bool isInitialized() { return _initialized; }
|
||||
virtual void init();
|
||||
void simulate(float deltaTime) { }
|
||||
void render();
|
||||
|
||||
void changeTree(VoxelTree* newTree);
|
||||
|
@ -68,11 +67,6 @@ public:
|
|||
|
||||
ViewFrustum* getLastCulledViewFrustum() { return &_lastCulledViewFrustum; }
|
||||
|
||||
void writeToSVOFile(const char* filename, VoxelTreeElement* element) const;
|
||||
bool readFromSVOFile(const char* filename);
|
||||
bool readFromSquareARGB32Pixels(const char* filename);
|
||||
bool readFromSchematicFile(const char* filename);
|
||||
|
||||
void setMaxVoxels(int maxVoxels);
|
||||
long int getMaxVoxels() const { return _maxVoxels; }
|
||||
unsigned long getVoxelMemoryUsageRAM() const { return _memoryUsageRAM; }
|
||||
|
@ -82,66 +76,25 @@ public:
|
|||
|
||||
void killLocalVoxels();
|
||||
|
||||
virtual void removeOutOfView();
|
||||
virtual void hideOutOfView(bool forceFullFrustum = false);
|
||||
void inspectForOcclusions();
|
||||
bool hasViewChanged();
|
||||
bool isViewChanging();
|
||||
|
||||
bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
VoxelDetail& detail, float& distance, BoxFace& face);
|
||||
|
||||
bool findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration);
|
||||
bool findCapsulePenetration(const glm::vec3& start, const glm::vec3& end, float radius, glm::vec3& penetration);
|
||||
|
||||
void deleteVoxelAt(float x, float y, float z, float s);
|
||||
VoxelTreeElement* getVoxelAt(float x, float y, float z, float s) const;
|
||||
void createVoxel(float x, float y, float z, float s,
|
||||
unsigned char red, unsigned char green, unsigned char blue, bool destructive = false);
|
||||
void createLine(glm::vec3 point1, glm::vec3 point2, float unitSize, rgbColor color, bool destructive = false);
|
||||
|
||||
void copySubTreeIntoNewTree(VoxelTreeElement* startNode, VoxelSystem* destinationTree, bool rebaseToRoot);
|
||||
void copySubTreeIntoNewTree(VoxelTreeElement* startNode, VoxelTree* destinationTree, bool rebaseToRoot);
|
||||
void copyFromTreeIntoSubTree(VoxelTree* sourceTree, VoxelTreeElement* destinationNode);
|
||||
|
||||
void recurseTreeWithOperation(RecurseOctreeOperation operation, void* extraData=NULL);
|
||||
|
||||
CoverageMapV2 myCoverageMapV2;
|
||||
CoverageMap myCoverageMap;
|
||||
|
||||
virtual void elementDeleted(OctreeElement* element);
|
||||
virtual void elementUpdated(OctreeElement* element);
|
||||
|
||||
VoxelTreeElement* getVoxelEnclosing(const glm::vec3& point);
|
||||
|
||||
signals:
|
||||
void importSize(float x, float y, float z);
|
||||
void importProgress(int progress);
|
||||
|
||||
public slots:
|
||||
void nodeAdded(SharedNodePointer node);
|
||||
void nodeKilled(SharedNodePointer node);
|
||||
|
||||
void collectStatsForTreesAndVBOs();
|
||||
|
||||
// Methods that recurse tree
|
||||
void showAllLocalVoxels();
|
||||
void randomizeVoxelColors();
|
||||
void falseColorizeRandom();
|
||||
void trueColorize();
|
||||
void falseColorizeInView();
|
||||
void falseColorizeDistanceFromView();
|
||||
void falseColorizeRandomEveryOther();
|
||||
void falseColorizeOccluded();
|
||||
void falseColorizeOccludedV2();
|
||||
void falseColorizeBySource();
|
||||
void forceRedrawEntireTree();
|
||||
void clearAllNodesBufferIndex();
|
||||
void cullSharedFaces();
|
||||
void showCulledSharedFaces();
|
||||
|
||||
void cancelImport();
|
||||
|
||||
void setDisableFastVoxelPipeline(bool disableFastVoxelPipeline);
|
||||
void setUseVoxelShader(bool useVoxelShader);
|
||||
void setVoxelsAsPoints(bool voxelsAsPoints);
|
||||
|
@ -154,18 +107,24 @@ protected:
|
|||
void setupNewVoxelsForDrawing();
|
||||
static const bool DONT_BAIL_EARLY; // by default we will bail early, if you want to force not bailing, then use this
|
||||
void setupNewVoxelsForDrawingSingleNode(bool allowBailEarly = true);
|
||||
|
||||
/// called on the hide/show thread to hide any out of view voxels and show any newly in view voxels.
|
||||
void checkForCulling();
|
||||
|
||||
/// single pass to remove old VBO data and fill it with correct current view, used when switching LOD or needing to force
|
||||
/// a full redraw of everything in view
|
||||
void recreateVoxelGeometryInView();
|
||||
|
||||
glm::vec3 computeVoxelVertex(const glm::vec3& startVertex, float voxelScale, int index) const;
|
||||
|
||||
|
||||
virtual void updateArraysDetails(glBufferIndex nodeIndex, const glm::vec3& startVertex,
|
||||
float voxelScale, const nodeColor& color);
|
||||
virtual void copyWrittenDataSegmentToReadArrays(glBufferIndex segmentStart, glBufferIndex segmentEnd);
|
||||
virtual void updateVBOSegment(glBufferIndex segmentStart, glBufferIndex segmentEnd);
|
||||
virtual void applyScaleAndBindProgram(bool texture);
|
||||
virtual void removeScaleAndReleaseProgram(bool texture);
|
||||
|
||||
|
||||
virtual void applyScaleAndBindProgram(bool texture); /// used in render() to apply shadows and textures
|
||||
virtual void removeScaleAndReleaseProgram(bool texture); /// stop the shaders for shadows and textures
|
||||
|
||||
private:
|
||||
// disallow copying of VoxelSystem objects
|
||||
|
@ -178,19 +137,6 @@ private:
|
|||
|
||||
// Operation functions for tree recursion methods
|
||||
static int _nodeCount;
|
||||
static bool randomColorOperation(OctreeElement* element, void* extraData);
|
||||
static bool falseColorizeRandomOperation(OctreeElement* element, void* extraData);
|
||||
static bool trueColorizeOperation(OctreeElement* element, void* extraData);
|
||||
static bool falseColorizeInViewOperation(OctreeElement* element, void* extraData);
|
||||
static bool falseColorizeDistanceFromViewOperation(OctreeElement* element, void* extraData);
|
||||
static bool getDistanceFromViewRangeOperation(OctreeElement* element, void* extraData);
|
||||
static bool removeOutOfViewOperation(OctreeElement* element, void* extraData);
|
||||
static bool falseColorizeRandomEveryOtherOperation(OctreeElement* element, void* extraData);
|
||||
static bool collectStatsForTreesAndVBOsOperation(OctreeElement* element, void* extraData);
|
||||
static bool falseColorizeOccludedOperation(OctreeElement* element, void* extraData);
|
||||
static bool falseColorizeSubTreeOperation(OctreeElement* element, void* extraData);
|
||||
static bool falseColorizeOccludedV2Operation(OctreeElement* element, void* extraData);
|
||||
static bool falseColorizeBySourceOperation(OctreeElement* element, void* extraData);
|
||||
static bool killSourceVoxelsOperation(OctreeElement* element, void* extraData);
|
||||
static bool forceRedrawEntireTreeOperation(OctreeElement* element, void* extraData);
|
||||
static bool clearAllNodesBufferIndexOperation(OctreeElement* element, void* extraData);
|
||||
|
@ -199,7 +145,6 @@ private:
|
|||
static bool hideOutOfViewOperation(OctreeElement* element, void* extraData);
|
||||
static bool hideAllSubTreeOperation(OctreeElement* element, void* extraData);
|
||||
static bool showAllSubTreeOperation(OctreeElement* element, void* extraData);
|
||||
static bool showAllLocalVoxelsOperation(OctreeElement* element, void* extraData);
|
||||
static bool getVoxelEnclosingOperation(OctreeElement* element, void* extraData);
|
||||
static bool recreateVoxelGeometryInViewOperation(OctreeElement* element, void* extraData);
|
||||
|
||||
|
|
|
@ -112,7 +112,8 @@ glm::quat Avatar::getWorldAlignedOrientation () const {
|
|||
}
|
||||
|
||||
float Avatar::getLODDistance() const {
|
||||
return glm::distance(Application::getInstance()->getCamera()->getPosition(), _position) / _scale;
|
||||
return Menu::getInstance()->getAvatarLODDistanceMultiplier() *
|
||||
glm::distance(Application::getInstance()->getCamera()->getPosition(), _position) / _scale;
|
||||
}
|
||||
|
||||
void Avatar::simulate(float deltaTime) {
|
||||
|
@ -135,10 +136,10 @@ void Avatar::simulate(float deltaTime) {
|
|||
|
||||
getHand()->simulate(deltaTime, false);
|
||||
_skeletonModel.setLODDistance(getLODDistance());
|
||||
_skeletonModel.simulate(deltaTime, _shouldRenderBillboard);
|
||||
glm::vec3 headPosition;
|
||||
if (!_skeletonModel.getHeadPosition(headPosition)) {
|
||||
headPosition = _position;
|
||||
glm::vec3 headPosition = _position;
|
||||
if (!_shouldRenderBillboard) {
|
||||
_skeletonModel.simulate(deltaTime);
|
||||
_skeletonModel.getHeadPosition(headPosition);
|
||||
}
|
||||
Head* head = getHead();
|
||||
head->setPosition(headPosition);
|
||||
|
@ -305,7 +306,8 @@ glm::quat Avatar::computeRotationFromBodyToWorldUp(float proportion) const {
|
|||
}
|
||||
|
||||
void Avatar::renderBody() {
|
||||
if (_shouldRenderBillboard) {
|
||||
if (_shouldRenderBillboard || !(_skeletonModel.isRenderable() && getHead()->getFaceModel().isRenderable())) {
|
||||
// render the billboard until both models are loaded
|
||||
renderBillboard();
|
||||
return;
|
||||
}
|
||||
|
@ -564,13 +566,13 @@ bool Avatar::findParticleCollisions(const glm::vec3& particleCenter, float parti
|
|||
void Avatar::setFaceModelURL(const QUrl& faceModelURL) {
|
||||
AvatarData::setFaceModelURL(faceModelURL);
|
||||
const QUrl DEFAULT_FACE_MODEL_URL = QUrl::fromLocalFile("resources/meshes/defaultAvatar_head.fst");
|
||||
getHead()->getFaceModel().setURL(_faceModelURL, DEFAULT_FACE_MODEL_URL, !isMyAvatar());
|
||||
getHead()->getFaceModel().setURL(_faceModelURL, DEFAULT_FACE_MODEL_URL, true, !isMyAvatar());
|
||||
}
|
||||
|
||||
void Avatar::setSkeletonModelURL(const QUrl& skeletonModelURL) {
|
||||
AvatarData::setSkeletonModelURL(skeletonModelURL);
|
||||
const QUrl DEFAULT_SKELETON_MODEL_URL = QUrl::fromLocalFile("resources/meshes/defaultAvatar_body.fst");
|
||||
_skeletonModel.setURL(_skeletonModelURL, DEFAULT_SKELETON_MODEL_URL, !isMyAvatar());
|
||||
_skeletonModel.setURL(_skeletonModelURL, DEFAULT_SKELETON_MODEL_URL, true, !isMyAvatar());
|
||||
}
|
||||
|
||||
void Avatar::setDisplayName(const QString& displayName) {
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
using namespace std;
|
||||
|
||||
const float FINGERTIP_COLLISION_RADIUS = 0.01f;
|
||||
const float FINGERTIP_VOXEL_SIZE = 0.05f;
|
||||
const float PALM_COLLISION_RADIUS = 0.03f;
|
||||
|
||||
|
||||
|
@ -29,7 +28,6 @@ Hand::Hand(Avatar* owningAvatar) :
|
|||
|
||||
_owningAvatar(owningAvatar),
|
||||
_renderAlpha(1.0),
|
||||
_ballColor(0.0, 0.0, 0.4),
|
||||
_collisionCenter(0,0,0),
|
||||
_collisionAge(0),
|
||||
_collisionDuration(0)
|
||||
|
@ -37,13 +35,6 @@ Hand::Hand(Avatar* owningAvatar) :
|
|||
}
|
||||
|
||||
void Hand::init() {
|
||||
// Different colors for my hand and others' hands
|
||||
if (_owningAvatar && _owningAvatar->isMyAvatar()) {
|
||||
_ballColor = glm::vec3(0.0, 0.4, 0.0);
|
||||
}
|
||||
else {
|
||||
_ballColor = glm::vec3(0.0, 0.0, 0.4);
|
||||
}
|
||||
}
|
||||
|
||||
void Hand::reset() {
|
||||
|
@ -61,61 +52,6 @@ void Hand::simulate(float deltaTime, bool isMine) {
|
|||
// Iterate hand controllers, take actions as needed
|
||||
for (size_t i = 0; i < getNumPalms(); ++i) {
|
||||
PalmData& palm = getPalms()[i];
|
||||
if (palm.isActive()) {
|
||||
FingerData& finger = palm.getFingers()[0]; // Sixense has only one finger
|
||||
glm::vec3 fingerTipPosition = finger.getTipPosition();
|
||||
|
||||
|
||||
if (palm.getControllerButtons() & BUTTON_1) {
|
||||
if (glm::length(fingerTipPosition - _lastFingerAddVoxel) > (FINGERTIP_VOXEL_SIZE / 2.f)) {
|
||||
// TODO: we need to move this code to JS so it can access the editVoxels.js color palette
|
||||
QColor paintColor(128,128,128);
|
||||
Application::getInstance()->makeVoxel(fingerTipPosition,
|
||||
FINGERTIP_VOXEL_SIZE,
|
||||
paintColor.red(),
|
||||
paintColor.green(),
|
||||
paintColor.blue(),
|
||||
true);
|
||||
_lastFingerAddVoxel = fingerTipPosition;
|
||||
}
|
||||
} else if (palm.getControllerButtons() & BUTTON_2) {
|
||||
if (glm::length(fingerTipPosition - _lastFingerDeleteVoxel) > (FINGERTIP_VOXEL_SIZE / 2.f)) {
|
||||
Application::getInstance()->removeVoxel(fingerTipPosition, FINGERTIP_VOXEL_SIZE);
|
||||
_lastFingerDeleteVoxel = fingerTipPosition;
|
||||
}
|
||||
}
|
||||
|
||||
// Voxel Drumming with fingertips if enabled
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::VoxelDrumming)) {
|
||||
VoxelTreeElement* fingerNode = Application::getInstance()->getVoxels()->getVoxelEnclosing(
|
||||
glm::vec3(fingerTipPosition / (float)TREE_SCALE));
|
||||
if (fingerNode) {
|
||||
if (!palm.getIsCollidingWithVoxel()) {
|
||||
// Collision has just started
|
||||
palm.setIsCollidingWithVoxel(true);
|
||||
handleVoxelCollision(&palm, fingerTipPosition, fingerNode, deltaTime);
|
||||
// Set highlight voxel
|
||||
VoxelDetail voxel;
|
||||
glm::vec3 pos = fingerNode->getCorner();
|
||||
voxel.x = pos.x;
|
||||
voxel.y = pos.y;
|
||||
voxel.z = pos.z;
|
||||
voxel.s = fingerNode->getScale();
|
||||
voxel.red = fingerNode->getColor()[0];
|
||||
voxel.green = fingerNode->getColor()[1];
|
||||
voxel.blue = fingerNode->getColor()[2];
|
||||
Application::getInstance()->setHighlightVoxel(voxel);
|
||||
Application::getInstance()->setIsHighlightVoxel(true);
|
||||
}
|
||||
} else {
|
||||
if (palm.getIsCollidingWithVoxel()) {
|
||||
// Collision has just ended
|
||||
palm.setIsCollidingWithVoxel(false);
|
||||
Application::getInstance()->setIsHighlightVoxel(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
palm.setLastControllerButtons(palm.getControllerButtons());
|
||||
}
|
||||
}
|
||||
|
@ -349,7 +285,6 @@ void Hand::renderLeapHands(bool isMine) {
|
|||
|
||||
const float alpha = 1.0f;
|
||||
|
||||
//const glm::vec3 handColor = _ballColor;
|
||||
const glm::vec3 handColor(1.0, 0.84, 0.66); // use the skin color
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
|
|
@ -51,7 +51,6 @@ public:
|
|||
void reset();
|
||||
void simulate(float deltaTime, bool isMine);
|
||||
void render(bool isMine);
|
||||
void setBallColor (glm::vec3 ballColor ) { _ballColor = ballColor; }
|
||||
|
||||
// getters
|
||||
const glm::vec3& getLeapFingerTipBallPosition (int ball) const { return _leapFingerTipBalls [ball].position;}
|
||||
|
@ -69,7 +68,6 @@ private:
|
|||
|
||||
Avatar* _owningAvatar;
|
||||
float _renderAlpha;
|
||||
glm::vec3 _ballColor;
|
||||
std::vector<HandBall> _leapFingerTipBalls;
|
||||
std::vector<HandBall> _leapFingerRootBalls;
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ void Head::reset() {
|
|||
|
||||
|
||||
|
||||
void Head::simulate(float deltaTime, bool isMine, bool delayLoad) {
|
||||
void Head::simulate(float deltaTime, bool isMine, bool billboard) {
|
||||
|
||||
// Update audio trailing average for rendering facial animations
|
||||
Faceshift* faceshift = Application::getInstance()->getFaceshift();
|
||||
|
@ -75,7 +75,7 @@ void Head::simulate(float deltaTime, bool isMine, bool delayLoad) {
|
|||
}
|
||||
}
|
||||
|
||||
if (!_isFaceshiftConnected) {
|
||||
if (!(_isFaceshiftConnected || billboard)) {
|
||||
// Update eye saccades
|
||||
const float AVERAGE_MICROSACCADE_INTERVAL = 0.50f;
|
||||
const float AVERAGE_SACCADE_INTERVAL = 4.0f;
|
||||
|
@ -161,11 +161,10 @@ void Head::simulate(float deltaTime, bool isMine, bool delayLoad) {
|
|||
if (!isMine) {
|
||||
_faceModel.setLODDistance(static_cast<Avatar*>(_owningAvatar)->getLODDistance());
|
||||
}
|
||||
_faceModel.simulate(deltaTime, delayLoad);
|
||||
|
||||
// the blend face may have custom eye meshes
|
||||
if (!_faceModel.getEyePositions(_leftEyePosition, _rightEyePosition)) {
|
||||
_leftEyePosition = _rightEyePosition = getPosition();
|
||||
_leftEyePosition = _rightEyePosition = getPosition();
|
||||
if (!billboard) {
|
||||
_faceModel.simulate(deltaTime);
|
||||
_faceModel.getEyePositions(_leftEyePosition, _rightEyePosition);
|
||||
}
|
||||
_eyePosition = calculateAverageEyePosition();
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ public:
|
|||
|
||||
void init();
|
||||
void reset();
|
||||
void simulate(float deltaTime, bool isMine, bool delayLoad = false);
|
||||
void simulate(float deltaTime, bool isMine, bool billboard = false);
|
||||
void render(float alpha);
|
||||
void setScale(float scale);
|
||||
void setPosition(glm::vec3 position) { _position = position; }
|
||||
|
@ -74,9 +74,9 @@ public:
|
|||
void tweakYaw(float yaw) { _tweakedYaw = yaw; }
|
||||
void tweakRoll(float roll) { _tweakedRoll = roll; }
|
||||
|
||||
float getTweakedPitch() const;
|
||||
float getTweakedYaw() const;
|
||||
float getTweakedRoll() const;
|
||||
virtual float getTweakedPitch() const;
|
||||
virtual float getTweakedYaw() const;
|
||||
virtual float getTweakedRoll() const;
|
||||
|
||||
void applyCollision(CollisionInfo& collisionInfo);
|
||||
|
||||
|
|
|
@ -677,6 +677,10 @@ void MyAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) {
|
|||
}
|
||||
|
||||
void MyAvatar::renderBody(bool forceRenderHead) {
|
||||
if (!(_skeletonModel.isRenderable() && getHead()->getFaceModel().isRenderable())) {
|
||||
return; // wait until both models are loaded
|
||||
}
|
||||
|
||||
// Render the body's voxels and head
|
||||
_skeletonModel.render(1.0f);
|
||||
|
||||
|
@ -806,7 +810,7 @@ void MyAvatar::updateCollisionWithVoxels(float deltaTime, float radius) {
|
|||
const float VOXEL_COLLISION_FREQUENCY = 0.5f;
|
||||
glm::vec3 penetration;
|
||||
float pelvisFloatingHeight = getPelvisFloatingHeight();
|
||||
if (Application::getInstance()->getVoxels()->findCapsulePenetration(
|
||||
if (Application::getInstance()->getVoxelTree()->findCapsulePenetration(
|
||||
_position - glm::vec3(0.0f, pelvisFloatingHeight - radius, 0.0f),
|
||||
_position + glm::vec3(0.0f, getSkeletonHeight() - pelvisFloatingHeight + radius, 0.0f), radius, penetration)) {
|
||||
_lastCollisionPosition = _position;
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
|
||||
using namespace std;
|
||||
|
||||
static int fbxGeometryMetaTypeId = qRegisterMetaType<FBXGeometry>();
|
||||
|
||||
template<class T> QVariant readBinaryArray(QDataStream& in) {
|
||||
quint32 arrayLength;
|
||||
quint32 encoding;
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#ifndef __interface__FBXReader__
|
||||
#define __interface__FBXReader__
|
||||
|
||||
#include <QMetaType>
|
||||
#include <QUrl>
|
||||
#include <QVarLengthArray>
|
||||
#include <QVariant>
|
||||
|
@ -167,6 +168,8 @@ public:
|
|||
QVector<FBXAttachment> attachments;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(FBXGeometry)
|
||||
|
||||
/// Reads an FST mapping from the supplied data.
|
||||
QVariantHash readMapping(const QByteArray& data);
|
||||
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
#include <cmath>
|
||||
|
||||
#include <QNetworkReply>
|
||||
#include <QRunnable>
|
||||
#include <QThreadPool>
|
||||
|
||||
#include "Application.h"
|
||||
#include "GeometryCache.h"
|
||||
|
@ -307,6 +309,21 @@ NetworkGeometry::NetworkGeometry(const QUrl& url, const QSharedPointer<NetworkGe
|
|||
_fallback(fallback) {
|
||||
}
|
||||
|
||||
bool NetworkGeometry::isLoadedWithTextures() const {
|
||||
if (!isLoaded()) {
|
||||
return false;
|
||||
}
|
||||
foreach (const NetworkMesh& mesh, _meshes) {
|
||||
foreach (const NetworkMeshPart& part, mesh.parts) {
|
||||
if ((part.diffuseTexture && !part.diffuseTexture->isLoaded()) ||
|
||||
(part.normalTexture && !part.normalTexture->isLoaded())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
QSharedPointer<NetworkGeometry> NetworkGeometry::getLODOrFallback(float distance, float& hysteresis, bool delayLoad) const {
|
||||
if (_lodParent.data() != this) {
|
||||
return _lodParent.data()->getLODOrFallback(distance, hysteresis, delayLoad);
|
||||
|
@ -428,17 +445,58 @@ void NetworkGeometry::clearLoadPriority(const QPointer<QObject>& owner) {
|
|||
}
|
||||
}
|
||||
|
||||
/// Reads geometry in a worker thread.
|
||||
class GeometryReader : public QRunnable {
|
||||
public:
|
||||
|
||||
GeometryReader(const QWeakPointer<Resource>& geometry, const QUrl& url,
|
||||
QNetworkReply* reply, const QVariantHash& mapping);
|
||||
|
||||
virtual void run();
|
||||
|
||||
private:
|
||||
|
||||
QWeakPointer<Resource> _geometry;
|
||||
QUrl _url;
|
||||
QNetworkReply* _reply;
|
||||
QVariantHash _mapping;
|
||||
};
|
||||
|
||||
GeometryReader::GeometryReader(const QWeakPointer<Resource>& geometry, const QUrl& url,
|
||||
QNetworkReply* reply, const QVariantHash& mapping) :
|
||||
_geometry(geometry),
|
||||
_url(url),
|
||||
_reply(reply),
|
||||
_mapping(mapping) {
|
||||
}
|
||||
|
||||
void GeometryReader::run() {
|
||||
QSharedPointer<Resource> geometry = _geometry.toStrongRef();
|
||||
if (geometry.isNull()) {
|
||||
_reply->deleteLater();
|
||||
return;
|
||||
}
|
||||
try {
|
||||
QMetaObject::invokeMethod(geometry.data(), "setGeometry", Q_ARG(const FBXGeometry&,
|
||||
_url.path().toLower().endsWith(".svo") ? readSVO(_reply->readAll()) : readFBX(_reply->readAll(), _mapping)));
|
||||
|
||||
} catch (const QString& error) {
|
||||
qDebug() << "Error reading " << _url << ": " << error;
|
||||
QMetaObject::invokeMethod(geometry.data(), "finishedLoading", Q_ARG(bool, false));
|
||||
}
|
||||
_reply->deleteLater();
|
||||
}
|
||||
|
||||
void NetworkGeometry::downloadFinished(QNetworkReply* reply) {
|
||||
QUrl url = reply->url();
|
||||
QByteArray data = reply->readAll();
|
||||
|
||||
if (url.path().toLower().endsWith(".fst")) {
|
||||
// it's a mapping file; parse it and get the mesh filename
|
||||
_mapping = readMapping(data);
|
||||
_mapping = readMapping(reply->readAll());
|
||||
reply->deleteLater();
|
||||
QString filename = _mapping.value("filename").toString();
|
||||
if (filename.isNull()) {
|
||||
qDebug() << "Mapping file " << url << " has no filename.";
|
||||
_failedToLoad = true;
|
||||
finishedLoading(false);
|
||||
|
||||
} else {
|
||||
QString texdir = _mapping.value("texdir").toString();
|
||||
|
@ -452,6 +510,7 @@ void NetworkGeometry::downloadFinished(QNetworkReply* reply) {
|
|||
for (QVariantHash::const_iterator it = lods.begin(); it != lods.end(); it++) {
|
||||
QSharedPointer<NetworkGeometry> geometry(new NetworkGeometry(url.resolved(it.key()),
|
||||
QSharedPointer<NetworkGeometry>(), true, _mapping, _textureBase));
|
||||
geometry->setSelf(geometry.staticCast<Resource>());
|
||||
geometry->setLODParent(_lodParent);
|
||||
_lods.insert(it.value().toFloat(), geometry);
|
||||
}
|
||||
|
@ -466,14 +525,12 @@ void NetworkGeometry::downloadFinished(QNetworkReply* reply) {
|
|||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
_geometry = url.path().toLower().endsWith(".svo") ? readSVO(data) : readFBX(data, _mapping);
|
||||
|
||||
} catch (const QString& error) {
|
||||
qDebug() << "Error reading " << url << ": " << error;
|
||||
_failedToLoad = true;
|
||||
return;
|
||||
}
|
||||
// send the reader off to the thread pool
|
||||
QThreadPool::globalInstance()->start(new GeometryReader(_self, url, reply, _mapping));
|
||||
}
|
||||
|
||||
void NetworkGeometry::setGeometry(const FBXGeometry& geometry) {
|
||||
_geometry = geometry;
|
||||
|
||||
foreach (const FBXMesh& mesh, _geometry.meshes) {
|
||||
NetworkMesh networkMesh = { QOpenGLBuffer(QOpenGLBuffer::IndexBuffer), QOpenGLBuffer(QOpenGLBuffer::VertexBuffer) };
|
||||
|
@ -567,6 +624,8 @@ void NetworkGeometry::downloadFinished(QNetworkReply* reply) {
|
|||
|
||||
_meshes.append(networkMesh);
|
||||
}
|
||||
|
||||
finishedLoading(true);
|
||||
}
|
||||
|
||||
bool NetworkMeshPart::isTranslucent() const {
|
||||
|
|
|
@ -69,8 +69,8 @@ public:
|
|||
NetworkGeometry(const QUrl& url, const QSharedPointer<NetworkGeometry>& fallback, bool delayLoad,
|
||||
const QVariantHash& mapping = QVariantHash(), const QUrl& textureBase = QUrl());
|
||||
|
||||
/// Checks whether the geometry is fulled loaded.
|
||||
bool isLoaded() const { return !_geometry.joints.isEmpty(); }
|
||||
/// Checks whether the geometry and its textures are loaded.
|
||||
bool isLoadedWithTextures() const;
|
||||
|
||||
/// Returns a pointer to the geometry appropriate for the specified distance.
|
||||
/// \param hysteresis a hysteresis parameter that prevents rapid model switching
|
||||
|
@ -90,6 +90,8 @@ protected:
|
|||
|
||||
virtual void downloadFinished(QNetworkReply* reply);
|
||||
|
||||
Q_INVOKABLE void setGeometry(const FBXGeometry& geometry);
|
||||
|
||||
private:
|
||||
|
||||
friend class GeometryCache;
|
||||
|
|
|
@ -105,13 +105,13 @@ void GlowEffect::end() {
|
|||
}
|
||||
|
||||
static void maybeBind(QOpenGLFramebufferObject* fbo) {
|
||||
if (fbo != NULL) {
|
||||
if (fbo) {
|
||||
fbo->bind();
|
||||
}
|
||||
}
|
||||
|
||||
static void maybeRelease(QOpenGLFramebufferObject* fbo) {
|
||||
if (fbo != NULL) {
|
||||
if (fbo) {
|
||||
fbo->release();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,21 +57,6 @@ QVector<Model::JointState> Model::createJointStates(const FBXGeometry& geometry)
|
|||
return jointStates;
|
||||
}
|
||||
|
||||
bool Model::isLoadedWithTextures() const {
|
||||
if (!isActive()) {
|
||||
return false;
|
||||
}
|
||||
foreach (const NetworkMesh& mesh, _geometry->getMeshes()) {
|
||||
foreach (const NetworkMeshPart& part, mesh.parts) {
|
||||
if ((part.diffuseTexture && !part.diffuseTexture->isLoaded()) ||
|
||||
(part.normalTexture && !part.normalTexture->isLoaded())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Model::init() {
|
||||
if (!_program.isLinked()) {
|
||||
switchToResourcesParentIfRequired();
|
||||
|
@ -117,32 +102,7 @@ void Model::reset() {
|
|||
|
||||
void Model::simulate(float deltaTime, bool delayLoad) {
|
||||
// update our LOD
|
||||
QVector<JointState> newJointStates;
|
||||
if (_geometry) {
|
||||
QSharedPointer<NetworkGeometry> geometry = _geometry->getLODOrFallback(_lodDistance, _lodHysteresis, delayLoad);
|
||||
if (_geometry != geometry) {
|
||||
if (!_jointStates.isEmpty()) {
|
||||
// copy the existing joint states
|
||||
const FBXGeometry& oldGeometry = _geometry->getFBXGeometry();
|
||||
const FBXGeometry& newGeometry = geometry->getFBXGeometry();
|
||||
newJointStates = createJointStates(newGeometry);
|
||||
for (QHash<QString, int>::const_iterator it = oldGeometry.jointIndices.constBegin();
|
||||
it != oldGeometry.jointIndices.constEnd(); it++) {
|
||||
int newIndex = newGeometry.jointIndices.value(it.key());
|
||||
if (newIndex != 0) {
|
||||
newJointStates[newIndex - 1] = _jointStates.at(it.value() - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
deleteGeometry();
|
||||
_dilatedTextures.clear();
|
||||
_geometry = geometry;
|
||||
}
|
||||
if (!delayLoad) {
|
||||
_geometry->setLoadPriority(this, -_lodDistance);
|
||||
_geometry->ensureLoading();
|
||||
}
|
||||
}
|
||||
QVector<JointState> newJointStates = updateGeometry(delayLoad);
|
||||
if (!isActive()) {
|
||||
return;
|
||||
}
|
||||
|
@ -447,20 +407,18 @@ float Model::getRightArmLength() const {
|
|||
return getLimbLength(getRightHandJointIndex());
|
||||
}
|
||||
|
||||
void Model::setURL(const QUrl& url, const QUrl& fallback, bool delayLoad) {
|
||||
void Model::setURL(const QUrl& url, const QUrl& fallback, bool retainCurrent, bool delayLoad) {
|
||||
// don't recreate the geometry if it's the same URL
|
||||
if (_url == url) {
|
||||
return;
|
||||
}
|
||||
_url = url;
|
||||
|
||||
// delete our local geometry and custom textures
|
||||
deleteGeometry();
|
||||
_dilatedTextures.clear();
|
||||
_lodHysteresis = NetworkGeometry::NO_HYSTERESIS;
|
||||
|
||||
// we retain a reference to the base geometry so that its reference count doesn't fall to zero
|
||||
_baseGeometry = _geometry = Application::getInstance()->getGeometryCache()->getGeometry(url, fallback, delayLoad);
|
||||
// if so instructed, keep the current geometry until the new one is loaded
|
||||
_nextBaseGeometry = _nextGeometry = Application::getInstance()->getGeometryCache()->getGeometry(url, fallback, delayLoad);
|
||||
if (!retainCurrent || !isActive() || _nextGeometry->isLoaded()) {
|
||||
applyNextGeometry();
|
||||
}
|
||||
}
|
||||
|
||||
glm::vec4 Model::computeAverageColor() const {
|
||||
|
@ -823,6 +781,61 @@ void Model::applyCollision(CollisionInfo& collision) {
|
|||
}
|
||||
}
|
||||
|
||||
QVector<Model::JointState> Model::updateGeometry(bool delayLoad) {
|
||||
QVector<JointState> newJointStates;
|
||||
if (_nextGeometry) {
|
||||
_nextGeometry = _nextGeometry->getLODOrFallback(_lodDistance, _lodHysteresis, delayLoad);
|
||||
if (!delayLoad) {
|
||||
_nextGeometry->setLoadPriority(this, -_lodDistance);
|
||||
_nextGeometry->ensureLoading();
|
||||
}
|
||||
if (_nextGeometry->isLoaded()) {
|
||||
applyNextGeometry();
|
||||
return newJointStates;
|
||||
}
|
||||
}
|
||||
if (!_geometry) {
|
||||
return newJointStates;
|
||||
}
|
||||
QSharedPointer<NetworkGeometry> geometry = _geometry->getLODOrFallback(_lodDistance, _lodHysteresis, delayLoad);
|
||||
if (_geometry != geometry) {
|
||||
if (!_jointStates.isEmpty()) {
|
||||
// copy the existing joint states
|
||||
const FBXGeometry& oldGeometry = _geometry->getFBXGeometry();
|
||||
const FBXGeometry& newGeometry = geometry->getFBXGeometry();
|
||||
newJointStates = createJointStates(newGeometry);
|
||||
for (QHash<QString, int>::const_iterator it = oldGeometry.jointIndices.constBegin();
|
||||
it != oldGeometry.jointIndices.constEnd(); it++) {
|
||||
int newIndex = newGeometry.jointIndices.value(it.key());
|
||||
if (newIndex != 0) {
|
||||
newJointStates[newIndex - 1] = _jointStates.at(it.value() - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
deleteGeometry();
|
||||
_dilatedTextures.clear();
|
||||
_geometry = geometry;
|
||||
}
|
||||
if (!delayLoad) {
|
||||
_geometry->setLoadPriority(this, -_lodDistance);
|
||||
_geometry->ensureLoading();
|
||||
}
|
||||
return newJointStates;
|
||||
}
|
||||
|
||||
void Model::applyNextGeometry() {
|
||||
// delete our local geometry and custom textures
|
||||
deleteGeometry();
|
||||
_dilatedTextures.clear();
|
||||
_lodHysteresis = NetworkGeometry::NO_HYSTERESIS;
|
||||
|
||||
// we retain a reference to the base geometry so that its reference count doesn't fall to zero
|
||||
_baseGeometry = _nextBaseGeometry;
|
||||
_geometry = _nextGeometry;
|
||||
_nextBaseGeometry.reset();
|
||||
_nextGeometry.reset();
|
||||
}
|
||||
|
||||
void Model::deleteGeometry() {
|
||||
foreach (Model* attachment, _attachments) {
|
||||
delete attachment;
|
||||
|
@ -983,18 +996,18 @@ void Model::renderMeshes(float alpha, bool translucent) {
|
|||
|
||||
Texture* diffuseMap = networkPart.diffuseTexture.data();
|
||||
if (mesh.isEye) {
|
||||
if (diffuseMap != NULL) {
|
||||
if (diffuseMap) {
|
||||
diffuseMap = (_dilatedTextures[i][j] =
|
||||
static_cast<DilatableNetworkTexture*>(diffuseMap)->getDilatedTexture(_pupilDilation)).data();
|
||||
}
|
||||
}
|
||||
glBindTexture(GL_TEXTURE_2D, diffuseMap == NULL ?
|
||||
glBindTexture(GL_TEXTURE_2D, !diffuseMap ?
|
||||
Application::getInstance()->getTextureCache()->getWhiteTextureID() : diffuseMap->getID());
|
||||
|
||||
if (!mesh.tangents.isEmpty()) {
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
Texture* normalMap = networkPart.normalTexture.data();
|
||||
glBindTexture(GL_TEXTURE_2D, normalMap == NULL ?
|
||||
glBindTexture(GL_TEXTURE_2D, !normalMap ?
|
||||
Application::getInstance()->getTextureCache()->getBlueTextureID() : normalMap->getID());
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
}
|
||||
|
|
|
@ -46,14 +46,22 @@ public:
|
|||
|
||||
bool isActive() const { return _geometry && _geometry->isLoaded(); }
|
||||
|
||||
bool isLoadedWithTextures() const;
|
||||
bool isRenderable() const { return !_meshStates.isEmpty(); }
|
||||
|
||||
bool isLoadedWithTextures() const { return _geometry && _geometry->isLoadedWithTextures(); }
|
||||
|
||||
void init();
|
||||
void reset();
|
||||
void simulate(float deltaTime, bool delayLoad = false);
|
||||
bool render(float alpha);
|
||||
|
||||
Q_INVOKABLE void setURL(const QUrl& url, const QUrl& fallback = QUrl(), bool delayLoad = false);
|
||||
/// Sets the URL of the model to render.
|
||||
/// \param fallback the URL of a fallback model to render if the requested model fails to load
|
||||
/// \param retainCurrent if true, keep rendering the current model until the new one is loaded
|
||||
/// \param delayLoad if true, don't load the model immediately; wait until actually requested
|
||||
Q_INVOKABLE void setURL(const QUrl& url, const QUrl& fallback = QUrl(),
|
||||
bool retainCurrent = false, bool delayLoad = false);
|
||||
|
||||
const QUrl& getURL() const { return _url; }
|
||||
|
||||
/// Sets the distance parameter used for LOD computations.
|
||||
|
@ -229,10 +237,14 @@ protected:
|
|||
|
||||
private:
|
||||
|
||||
QVector<JointState> updateGeometry(bool delayLoad);
|
||||
void applyNextGeometry();
|
||||
void deleteGeometry();
|
||||
void renderMeshes(float alpha, bool translucent);
|
||||
|
||||
QSharedPointer<NetworkGeometry> _baseGeometry; ///< reference required to prevent collection of base
|
||||
QSharedPointer<NetworkGeometry> _nextBaseGeometry;
|
||||
QSharedPointer<NetworkGeometry> _nextGeometry;
|
||||
float _lodDistance;
|
||||
float _lodHysteresis;
|
||||
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
#include <QGLWidget>
|
||||
#include <QNetworkReply>
|
||||
#include <QOpenGLFramebufferObject>
|
||||
#include <QRunnable>
|
||||
#include <QThreadPool>
|
||||
|
||||
#include <glm/gtc/random.hpp>
|
||||
|
||||
|
@ -38,16 +40,13 @@ TextureCache::~TextureCache() {
|
|||
foreach (GLuint id, _fileTextureIDs) {
|
||||
glDeleteTextures(1, &id);
|
||||
}
|
||||
if (_primaryFramebufferObject != NULL) {
|
||||
delete _primaryFramebufferObject;
|
||||
if (_primaryFramebufferObject) {
|
||||
glDeleteTextures(1, &_primaryDepthTextureID);
|
||||
}
|
||||
if (_secondaryFramebufferObject != NULL) {
|
||||
delete _secondaryFramebufferObject;
|
||||
}
|
||||
if (_tertiaryFramebufferObject != NULL) {
|
||||
delete _tertiaryFramebufferObject;
|
||||
}
|
||||
|
||||
delete _primaryFramebufferObject;
|
||||
delete _secondaryFramebufferObject;
|
||||
delete _tertiaryFramebufferObject;
|
||||
}
|
||||
|
||||
GLuint TextureCache::getPermutationNormalTextureID() {
|
||||
|
@ -129,13 +128,14 @@ QSharedPointer<NetworkTexture> TextureCache::getTexture(const QUrl& url, bool no
|
|||
QSharedPointer<NetworkTexture> texture = _dilatableNetworkTextures.value(url);
|
||||
if (texture.isNull()) {
|
||||
texture = QSharedPointer<NetworkTexture>(new DilatableNetworkTexture(url));
|
||||
texture->setSelf(texture);
|
||||
_dilatableNetworkTextures.insert(url, texture);
|
||||
}
|
||||
return texture;
|
||||
}
|
||||
|
||||
QOpenGLFramebufferObject* TextureCache::getPrimaryFramebufferObject() {
|
||||
if (_primaryFramebufferObject == NULL) {
|
||||
if (!_primaryFramebufferObject) {
|
||||
_primaryFramebufferObject = createFramebufferObject();
|
||||
|
||||
glGenTextures(1, &_primaryDepthTextureID);
|
||||
|
@ -161,21 +161,21 @@ GLuint TextureCache::getPrimaryDepthTextureID() {
|
|||
}
|
||||
|
||||
QOpenGLFramebufferObject* TextureCache::getSecondaryFramebufferObject() {
|
||||
if (_secondaryFramebufferObject == NULL) {
|
||||
if (!_secondaryFramebufferObject) {
|
||||
_secondaryFramebufferObject = createFramebufferObject();
|
||||
}
|
||||
return _secondaryFramebufferObject;
|
||||
}
|
||||
|
||||
QOpenGLFramebufferObject* TextureCache::getTertiaryFramebufferObject() {
|
||||
if (_tertiaryFramebufferObject == NULL) {
|
||||
if (!_tertiaryFramebufferObject) {
|
||||
_tertiaryFramebufferObject = createFramebufferObject();
|
||||
}
|
||||
return _tertiaryFramebufferObject;
|
||||
}
|
||||
|
||||
QOpenGLFramebufferObject* TextureCache::getShadowFramebufferObject() {
|
||||
if (_shadowFramebufferObject == NULL) {
|
||||
if (!_shadowFramebufferObject) {
|
||||
const int SHADOW_MAP_SIZE = 2048;
|
||||
_shadowFramebufferObject = new QOpenGLFramebufferObject(SHADOW_MAP_SIZE, SHADOW_MAP_SIZE,
|
||||
QOpenGLFramebufferObject::NoAttachment, GL_TEXTURE_2D, GL_RGB);
|
||||
|
@ -209,16 +209,16 @@ GLuint TextureCache::getShadowDepthTextureID() {
|
|||
bool TextureCache::eventFilter(QObject* watched, QEvent* event) {
|
||||
if (event->type() == QEvent::Resize) {
|
||||
QSize size = static_cast<QResizeEvent*>(event)->size();
|
||||
if (_primaryFramebufferObject != NULL && _primaryFramebufferObject->size() != size) {
|
||||
if (_primaryFramebufferObject && _primaryFramebufferObject->size() != size) {
|
||||
delete _primaryFramebufferObject;
|
||||
_primaryFramebufferObject = NULL;
|
||||
glDeleteTextures(1, &_primaryDepthTextureID);
|
||||
}
|
||||
if (_secondaryFramebufferObject != NULL && _secondaryFramebufferObject->size() != size) {
|
||||
if (_secondaryFramebufferObject && _secondaryFramebufferObject->size() != size) {
|
||||
delete _secondaryFramebufferObject;
|
||||
_secondaryFramebufferObject = NULL;
|
||||
}
|
||||
if (_tertiaryFramebufferObject != NULL && _tertiaryFramebufferObject->size() != size) {
|
||||
if (_tertiaryFramebufferObject && _tertiaryFramebufferObject->size() != size) {
|
||||
delete _tertiaryFramebufferObject;
|
||||
_tertiaryFramebufferObject = NULL;
|
||||
}
|
||||
|
@ -254,8 +254,7 @@ Texture::~Texture() {
|
|||
NetworkTexture::NetworkTexture(const QUrl& url, bool normalMap) :
|
||||
Resource(url),
|
||||
_averageColor(1.0f, 1.0f, 1.0f, 1.0f),
|
||||
_translucent(false),
|
||||
_loaded(false) {
|
||||
_translucent(false) {
|
||||
|
||||
if (!url.isValid()) {
|
||||
_loaded = true;
|
||||
|
@ -268,10 +267,31 @@ NetworkTexture::NetworkTexture(const QUrl& url, bool normalMap) :
|
|||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
void NetworkTexture::downloadFinished(QNetworkReply* reply) {
|
||||
_loaded = true;
|
||||
class ImageReader : public QRunnable {
|
||||
public:
|
||||
|
||||
ImageReader(const QWeakPointer<Resource>& texture, QNetworkReply* reply);
|
||||
|
||||
QImage image = QImage::fromData(reply->readAll());
|
||||
virtual void run();
|
||||
|
||||
private:
|
||||
|
||||
QWeakPointer<Resource> _texture;
|
||||
QNetworkReply* _reply;
|
||||
};
|
||||
|
||||
ImageReader::ImageReader(const QWeakPointer<Resource>& texture, QNetworkReply* reply) :
|
||||
_texture(texture),
|
||||
_reply(reply) {
|
||||
}
|
||||
|
||||
void ImageReader::run() {
|
||||
QSharedPointer<Resource> texture = _texture.toStrongRef();
|
||||
if (texture.isNull()) {
|
||||
_reply->deleteLater();
|
||||
return;
|
||||
}
|
||||
QImage image = QImage::fromData(_reply->readAll());
|
||||
if (image.format() != QImage::Format_ARGB32) {
|
||||
image = image.convertToFormat(QImage::Format_ARGB32);
|
||||
}
|
||||
|
@ -295,9 +315,22 @@ void NetworkTexture::downloadFinished(QNetworkReply* reply) {
|
|||
}
|
||||
}
|
||||
int imageArea = image.width() * image.height();
|
||||
_averageColor = accumulated / (imageArea * EIGHT_BIT_MAXIMUM);
|
||||
_translucent = (translucentPixels >= imageArea / 2);
|
||||
QMetaObject::invokeMethod(texture.data(), "setImage", Q_ARG(const QImage&, image),
|
||||
Q_ARG(const glm::vec4&, accumulated / (imageArea * EIGHT_BIT_MAXIMUM)),
|
||||
Q_ARG(bool, translucentPixels >= imageArea / 2));
|
||||
_reply->deleteLater();
|
||||
}
|
||||
|
||||
void NetworkTexture::downloadFinished(QNetworkReply* reply) {
|
||||
// send the reader off to the thread pool
|
||||
QThreadPool::globalInstance()->start(new ImageReader(_self, reply));
|
||||
}
|
||||
|
||||
void NetworkTexture::setImage(const QImage& image, const glm::vec4& averageColor, bool translucent) {
|
||||
_averageColor = averageColor;
|
||||
_translucent = translucent;
|
||||
|
||||
finishedLoading(true);
|
||||
imageLoaded(image);
|
||||
glBindTexture(GL_TEXTURE_2D, getID());
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width(), image.height(), 1,
|
||||
|
|
|
@ -117,8 +117,6 @@ public:
|
|||
|
||||
NetworkTexture(const QUrl& url, bool normalMap);
|
||||
|
||||
bool isLoaded() const { return _loaded; }
|
||||
|
||||
/// Returns the average color over the entire texture.
|
||||
const glm::vec4& getAverageColor() const { return _averageColor; }
|
||||
|
||||
|
@ -131,11 +129,12 @@ protected:
|
|||
virtual void downloadFinished(QNetworkReply* reply);
|
||||
virtual void imageLoaded(const QImage& image);
|
||||
|
||||
Q_INVOKABLE void setImage(const QImage& image, const glm::vec4& averageColor, bool translucent);
|
||||
|
||||
private:
|
||||
|
||||
glm::vec4 _averageColor;
|
||||
bool _translucent;
|
||||
bool _loaded;
|
||||
};
|
||||
|
||||
/// Caches derived, dilated textures.
|
||||
|
|
|
@ -1,50 +0,0 @@
|
|||
//
|
||||
// ClipboardOverlay.cpp
|
||||
// hifi
|
||||
//
|
||||
// Created by Clément Brisset on 2/20/14.
|
||||
// Copyright (c) 2014 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
// include this before QGLWidget, which includes an earlier version of OpenGL
|
||||
#include "InterfaceConfig.h"
|
||||
|
||||
#include <QGLWidget>
|
||||
#include <SharedUtil.h>
|
||||
|
||||
#include "ClipboardOverlay.h"
|
||||
#include "../Application.h"
|
||||
|
||||
static int lastVoxelCount = 0;
|
||||
|
||||
ClipboardOverlay::ClipboardOverlay() {
|
||||
}
|
||||
|
||||
ClipboardOverlay::~ClipboardOverlay() {
|
||||
}
|
||||
|
||||
void ClipboardOverlay::render() {
|
||||
if (!_visible) {
|
||||
return; // do nothing if we're not visible
|
||||
}
|
||||
|
||||
VoxelSystem* voxelSystem = Application::getInstance()->getSharedVoxelSystem();
|
||||
VoxelTree* clipboard = Application::getInstance()->getClipboard();
|
||||
if (voxelSystem->getTree() != clipboard) {
|
||||
voxelSystem->changeTree(clipboard);
|
||||
}
|
||||
|
||||
glPushMatrix();
|
||||
glTranslatef(_position.x, _position.y, _position.z);
|
||||
glScalef(_size, _size, _size);
|
||||
|
||||
// We only force the redraw when the clipboard content has changed
|
||||
if (lastVoxelCount != clipboard->getOctreeElementsCount()) {
|
||||
voxelSystem->forceRedrawEntireTree();
|
||||
lastVoxelCount = clipboard->getOctreeElementsCount();
|
||||
}
|
||||
|
||||
voxelSystem->render();
|
||||
|
||||
glPopMatrix();
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
//
|
||||
// ClipboardOverlay.h
|
||||
// hifi
|
||||
//
|
||||
// Created by Clément Brisset on 2/20/14.
|
||||
// Copyright (c) 2014 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef __interface__ClipboardOverlay__
|
||||
#define __interface__ClipboardOverlay__
|
||||
|
||||
#include "Volume3DOverlay.h"
|
||||
|
||||
class ClipboardOverlay : public Volume3DOverlay {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ClipboardOverlay();
|
||||
~ClipboardOverlay();
|
||||
|
||||
virtual void render();
|
||||
};
|
||||
|
||||
|
||||
#endif /* defined(__interface__ClipboardOverlay__) */
|
84
interface/src/ui/LocalVoxelsOverlay.cpp
Normal file
84
interface/src/ui/LocalVoxelsOverlay.cpp
Normal file
|
@ -0,0 +1,84 @@
|
|||
//
|
||||
// LocalVoxelsOverlay.cpp
|
||||
// hifi
|
||||
//
|
||||
// Created by Clément Brisset on 2/28/14.
|
||||
// Copyright (c) 2014 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
//
|
||||
// include this before QGLWidget, which includes an earlier version of OpenGL
|
||||
#include "InterfaceConfig.h"
|
||||
|
||||
#include <QGLWidget>
|
||||
#include <QScriptValue>
|
||||
|
||||
#include <VoxelSystem.h>
|
||||
#include <Application.h>
|
||||
|
||||
#include "LocalVoxelsOverlay.h"
|
||||
|
||||
QMap<QString, WeakVoxelSystemPointer> LocalVoxelsOverlay::_voxelSystemMap;
|
||||
|
||||
LocalVoxelsOverlay::LocalVoxelsOverlay() :
|
||||
Volume3DOverlay(),
|
||||
_voxelCount(0)
|
||||
{
|
||||
}
|
||||
|
||||
LocalVoxelsOverlay::~LocalVoxelsOverlay() {
|
||||
_voxelSystem->changeTree(new VoxelTree());
|
||||
_voxelSystem.clear();
|
||||
if (_voxelSystemMap.value(_treeName).isNull()) {
|
||||
_voxelSystemMap.remove(_treeName);
|
||||
}
|
||||
_tree.clear();
|
||||
LocalVoxelsList::getInstance()->remove(_treeName);
|
||||
}
|
||||
|
||||
void LocalVoxelsOverlay::update(float deltatime) {
|
||||
if (!_voxelSystem->isInitialized()) {
|
||||
_voxelSystem->init();
|
||||
}
|
||||
|
||||
if (_voxelCount != _tree->getOctreeElementsCount()) {
|
||||
_voxelCount = _tree->getOctreeElementsCount();
|
||||
_voxelSystem->forceRedrawEntireTree();
|
||||
}
|
||||
}
|
||||
|
||||
void LocalVoxelsOverlay::render() {
|
||||
if (_visible && _size > 0 && _voxelSystem && _voxelSystem->isInitialized()) {
|
||||
glPushMatrix(); {
|
||||
glTranslatef(_position.x, _position.y, _position.z);
|
||||
glScalef(_size, _size, _size);
|
||||
_voxelSystem->render();
|
||||
} glPopMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
void LocalVoxelsOverlay::setProperties(const QScriptValue &properties) {
|
||||
Volume3DOverlay::setProperties(properties);
|
||||
|
||||
QScriptValue treeName = properties.property("name");
|
||||
// if "end" property was not there, check to see if they included aliases: endPoint, or p2
|
||||
if (treeName.isValid()) {
|
||||
if ((_treeName = treeName.toString()) == DOMAIN_TREE_NAME) {
|
||||
qDebug() << "addOverlay(): Can't create overlay from domain tree";
|
||||
return;
|
||||
}
|
||||
_tree = LocalVoxelsList::getInstance()->getTree(_treeName);
|
||||
if (_tree.isNull()) {
|
||||
qDebug() << "addOverlay(): Invalid tree name";
|
||||
return;
|
||||
}
|
||||
|
||||
_voxelSystem = _voxelSystemMap[_treeName];
|
||||
if (_voxelSystem.isNull()) {
|
||||
_voxelSystem = StrongVoxelSystemPointer(new VoxelSystem(1,
|
||||
DEFAULT_MAX_VOXELS_PER_SYSTEM,
|
||||
_tree.data()));
|
||||
_voxelSystemMap.insert(_treeName, _voxelSystem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
50
interface/src/ui/LocalVoxelsOverlay.h
Normal file
50
interface/src/ui/LocalVoxelsOverlay.h
Normal file
|
@ -0,0 +1,50 @@
|
|||
//
|
||||
// LocalVoxelsOverlay.h
|
||||
// hifi
|
||||
//
|
||||
// Created by Clément Brisset on 2/28/14.
|
||||
// Copyright (c) 2014 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
// Scriptable interface for LocalVoxels
|
||||
//
|
||||
|
||||
#ifndef __hifi__LocalVoxelsOverlay__
|
||||
#define __hifi__LocalVoxelsOverlay__
|
||||
|
||||
// include this before QGLWidget, which includes an earlier version of OpenGL
|
||||
#include "InterfaceConfig.h"
|
||||
|
||||
#include <QGLWidget>
|
||||
#include <QScriptValue>
|
||||
#include <QMap>
|
||||
#include <QSharedPointer>
|
||||
#include <QWeakPointer>
|
||||
|
||||
#include <LocalVoxelsList.h>
|
||||
|
||||
#include "Volume3DOverlay.h"
|
||||
|
||||
typedef QSharedPointer<VoxelSystem> StrongVoxelSystemPointer;
|
||||
typedef QWeakPointer<VoxelSystem> WeakVoxelSystemPointer;
|
||||
|
||||
class LocalVoxelsOverlay : public Volume3DOverlay {
|
||||
Q_OBJECT
|
||||
public:
|
||||
LocalVoxelsOverlay();
|
||||
~LocalVoxelsOverlay();
|
||||
|
||||
virtual void update(float deltatime);
|
||||
virtual void render();
|
||||
|
||||
virtual void setProperties(const QScriptValue& properties);
|
||||
|
||||
private:
|
||||
static QMap<QString, WeakVoxelSystemPointer> _voxelSystemMap; // treeName/voxelSystem
|
||||
|
||||
QString _treeName;
|
||||
StrongVoxelTreePointer _tree; // so that the tree doesn't get freed
|
||||
int _voxelCount;
|
||||
StrongVoxelSystemPointer _voxelSystem;
|
||||
};
|
||||
|
||||
#endif /* defined(__hifi__LocalVoxelsOverlay__) */
|
|
@ -28,6 +28,7 @@ public:
|
|||
Overlay();
|
||||
~Overlay();
|
||||
void init(QGLWidget* parent);
|
||||
virtual void update(float deltatime) {}
|
||||
virtual void render() = 0;
|
||||
|
||||
// getters
|
||||
|
|
|
@ -12,20 +12,41 @@
|
|||
#include "Overlays.h"
|
||||
#include "Sphere3DOverlay.h"
|
||||
#include "TextOverlay.h"
|
||||
#include "ClipboardOverlay.h"
|
||||
#include "LocalVoxelsOverlay.h"
|
||||
|
||||
unsigned int Overlays::_nextOverlayID = 1;
|
||||
|
||||
Overlays::Overlays() {
|
||||
Overlays::Overlays() : _nextOverlayID(1) {
|
||||
}
|
||||
|
||||
Overlays::~Overlays() {
|
||||
QMap<unsigned int, Overlay*>::iterator it;
|
||||
for (it = _overlays2D.begin(); it != _overlays2D.end(); ++it) {
|
||||
delete _overlays2D.take(it.key());
|
||||
}
|
||||
for (it = _overlays3D.begin(); it != _overlays3D.end(); ++it) {
|
||||
delete _overlays3D.take(it.key());
|
||||
}
|
||||
while (!_overlaysToDelete.isEmpty()) {
|
||||
delete _overlaysToDelete.takeLast();
|
||||
}
|
||||
}
|
||||
|
||||
void Overlays::init(QGLWidget* parent) {
|
||||
_parent = parent;
|
||||
}
|
||||
|
||||
void Overlays::update(float deltatime) {
|
||||
foreach (Overlay* thisOverlay, _overlays2D) {
|
||||
thisOverlay->update(deltatime);
|
||||
}
|
||||
foreach (Overlay* thisOverlay, _overlays3D) {
|
||||
thisOverlay->update(deltatime);
|
||||
}
|
||||
while (!_overlaysToDelete.isEmpty()) {
|
||||
delete _overlaysToDelete.takeLast();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Overlays::render2D() {
|
||||
foreach(Overlay* thisOverlay, _overlays2D) {
|
||||
thisOverlay->render();
|
||||
|
@ -73,8 +94,8 @@ unsigned int Overlays::addOverlay(const QString& type, const QScriptValue& prope
|
|||
thisOverlay->setProperties(properties);
|
||||
created = true;
|
||||
is3D = true;
|
||||
} else if (type == "clipboard") {
|
||||
thisOverlay = new ClipboardOverlay();
|
||||
} else if (type == "localvoxels") {
|
||||
thisOverlay = new LocalVoxelsOverlay();
|
||||
thisOverlay->init(_parent);
|
||||
thisOverlay->setProperties(properties);
|
||||
created = true;
|
||||
|
@ -111,11 +132,16 @@ bool Overlays::editOverlay(unsigned int id, const QScriptValue& properties) {
|
|||
|
||||
// TODO: make multi-threaded safe
|
||||
void Overlays::deleteOverlay(unsigned int id) {
|
||||
Overlay* overlayToDelete;
|
||||
if (_overlays2D.contains(id)) {
|
||||
_overlays2D.erase(_overlays2D.find(id));
|
||||
overlayToDelete = _overlays2D.take(id);
|
||||
} else if (_overlays3D.contains(id)) {
|
||||
_overlays3D.erase(_overlays3D.find(id));
|
||||
overlayToDelete = _overlays3D.take(id);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
_overlaysToDelete.push_back(overlayToDelete);
|
||||
}
|
||||
|
||||
unsigned int Overlays::getOverlayAtPoint(const glm::vec2& point) {
|
||||
|
|
|
@ -18,6 +18,7 @@ public:
|
|||
Overlays();
|
||||
~Overlays();
|
||||
void init(QGLWidget* parent);
|
||||
void update(float deltatime);
|
||||
void render3D();
|
||||
void render2D();
|
||||
|
||||
|
@ -38,7 +39,8 @@ public slots:
|
|||
private:
|
||||
QMap<unsigned int, Overlay*> _overlays2D;
|
||||
QMap<unsigned int, Overlay*> _overlays3D;
|
||||
static unsigned int _nextOverlayID;
|
||||
QList<Overlay*> _overlaysToDelete;
|
||||
unsigned int _nextOverlayID;
|
||||
QGLWidget* _parent;
|
||||
};
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
cmake_minimum_required(VERSION 2.8)
|
||||
|
||||
set(ROOT_DIR ../..)
|
||||
set(MACRO_DIR ${ROOT_DIR}/cmake/macros)
|
||||
set(MACRO_DIR "${ROOT_DIR}/cmake/macros")
|
||||
|
||||
# setup for find modules
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/modules/")
|
||||
|
@ -13,7 +13,7 @@ include(${MACRO_DIR}/SetupHifiLibrary.cmake)
|
|||
setup_hifi_library(${TARGET_NAME})
|
||||
|
||||
include(${MACRO_DIR}/IncludeGLM.cmake)
|
||||
include_glm(${TARGET_NAME} ${ROOT_DIR})
|
||||
include_glm(${TARGET_NAME} "${ROOT_DIR}")
|
||||
|
||||
include(${MACRO_DIR}/LinkHifiLibrary.cmake)
|
||||
link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR})
|
||||
link_hifi_library(shared ${TARGET_NAME} "${ROOT_DIR}")
|
|
@ -18,8 +18,6 @@
|
|||
|
||||
#include "AudioInjector.h"
|
||||
|
||||
int abstractAudioPointerMeta = qRegisterMetaType<AbstractAudioInterface*>("AbstractAudioInterface*");
|
||||
|
||||
AudioInjector::AudioInjector(Sound* sound, const AudioInjectorOptions& injectorOptions) :
|
||||
_sound(sound),
|
||||
_options(injectorOptions)
|
||||
|
@ -53,7 +51,7 @@ void AudioInjector::injectAudio() {
|
|||
packetStream << QUuid::createUuid();
|
||||
|
||||
// pack the flag for loopback
|
||||
uchar loopbackFlag = (uchar) (_options.getLoopbackAudioInterface() == NULL);
|
||||
uchar loopbackFlag = (uchar) (!_options.getLoopbackAudioInterface());
|
||||
packetStream << loopbackFlag;
|
||||
|
||||
// pack the position for injected audio
|
||||
|
|
|
@ -18,9 +18,6 @@
|
|||
#include "AudioInjectorOptions.h"
|
||||
#include "Sound.h"
|
||||
|
||||
class AbstractAudioInterface;
|
||||
class AudioScriptingInterface;
|
||||
|
||||
class AudioInjector : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
|
|
@ -25,4 +25,26 @@ void AudioScriptingInterface::playSound(Sound* sound, const AudioInjectorOptions
|
|||
connect(injectorThread, SIGNAL(finished()), injectorThread, SLOT(deleteLater()));
|
||||
|
||||
injectorThread->start();
|
||||
}
|
||||
}
|
||||
|
||||
void AudioScriptingInterface::startDrumSound(float volume, float frequency, float duration, float decay,
|
||||
const AudioInjectorOptions* injectorOptions) {
|
||||
|
||||
Sound* sound = new Sound(volume, frequency, duration, decay);
|
||||
AudioInjector* injector = new AudioInjector(sound, *injectorOptions);
|
||||
sound->setParent(injector);
|
||||
|
||||
QThread* injectorThread = new QThread();
|
||||
|
||||
injector->moveToThread(injectorThread);
|
||||
|
||||
// start injecting when the injector thread starts
|
||||
connect(injectorThread, SIGNAL(started()), injector, SLOT(injectAudio()));
|
||||
|
||||
// connect the right slots and signals so that the AudioInjector is killed once the injection is complete
|
||||
connect(injector, SIGNAL(finished()), injector, SLOT(deleteLater()));
|
||||
connect(injector, SIGNAL(finished()), injectorThread, SLOT(quit()));
|
||||
connect(injectorThread, SIGNAL(finished()), injectorThread, SLOT(deleteLater()));
|
||||
|
||||
injectorThread->start();
|
||||
}
|
||||
|
|
|
@ -18,6 +18,8 @@ class AudioScriptingInterface : public QObject {
|
|||
Q_OBJECT
|
||||
public slots:
|
||||
static void playSound(Sound* sound, const AudioInjectorOptions* injectorOptions = NULL);
|
||||
static void startDrumSound(float volume, float frequency, float duration, float decay,
|
||||
const AudioInjectorOptions* injectorOptions = NULL);
|
||||
|
||||
};
|
||||
#endif /* defined(__hifi__AudioScriptingInterface__) */
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include <QDataStream>
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtNetwork/QNetworkAccessManager>
|
||||
|
@ -16,8 +18,51 @@
|
|||
#include <QtNetwork/QNetworkReply>
|
||||
#include <qendian.h>
|
||||
|
||||
#include <SharedUtil.h>
|
||||
|
||||
#include "AudioRingBuffer.h"
|
||||
#include "Sound.h"
|
||||
|
||||
// procedural audio version of Sound
|
||||
Sound::Sound(float volume, float frequency, float duration, float decay, QObject* parent) :
|
||||
QObject(parent)
|
||||
{
|
||||
static char monoAudioData[MAX_PACKET_SIZE];
|
||||
static int16_t* monoAudioSamples = (int16_t*)(monoAudioData);
|
||||
|
||||
float t;
|
||||
const float AUDIO_CALLBACK_MSECS = (float) NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL / (float)SAMPLE_RATE * 1000.0;
|
||||
const float MAX_VOLUME = 32000.f;
|
||||
const float MAX_DURATION = 2.f;
|
||||
const float MIN_AUDIBLE_VOLUME = 0.001f;
|
||||
const float NOISE_MAGNITUDE = 0.02f;
|
||||
const int MAX_SAMPLE_VALUE = std::numeric_limits<int16_t>::max();
|
||||
const int MIN_SAMPLE_VALUE = std::numeric_limits<int16_t>::min();
|
||||
int numSamples = NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL; // we add sounds in chunks of this many samples
|
||||
|
||||
int chunkStartingSample = 0;
|
||||
float waveFrequency = (frequency / SAMPLE_RATE) * PI_TIMES_TWO;
|
||||
while (volume > 0.f) {
|
||||
for (int i = 0; i < numSamples; i++) {
|
||||
t = (float)chunkStartingSample + (float)i;
|
||||
float sample = sinf(t * waveFrequency);
|
||||
sample += ((randFloat() - 0.5f) * NOISE_MAGNITUDE);
|
||||
sample *= volume * MAX_VOLUME;
|
||||
|
||||
monoAudioSamples[i] = glm::clamp((int)sample, MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE);
|
||||
volume *= (1.f - decay);
|
||||
}
|
||||
// add the monoAudioSamples to our actual output Byte Array
|
||||
_byteArray.append(monoAudioData, numSamples * sizeof(int16_t));
|
||||
chunkStartingSample += numSamples;
|
||||
duration = glm::clamp(duration - (AUDIO_CALLBACK_MSECS / 1000.f), 0.f, MAX_DURATION);
|
||||
//qDebug() << "decaying... _duration=" << _duration;
|
||||
if (duration == 0.f || (volume < MIN_AUDIBLE_VOLUME)) {
|
||||
volume = 0.f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Sound::Sound(const QUrl& sampleURL, QObject* parent) :
|
||||
QObject(parent)
|
||||
{
|
||||
|
|
|
@ -17,7 +17,8 @@ class QNetworkReply;
|
|||
class Sound : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
Sound(const QUrl& sampleURL, QObject* parent = 0);
|
||||
Sound(const QUrl& sampleURL, QObject* parent = NULL);
|
||||
Sound(float volume, float frequency, float duration, float decay, QObject* parent = NULL);
|
||||
|
||||
const QByteArray& getByteArray() { return _byteArray; }
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
cmake_minimum_required(VERSION 2.8)
|
||||
|
||||
set(ROOT_DIR ../..)
|
||||
set(MACRO_DIR ${ROOT_DIR}/cmake/macros)
|
||||
set(MACRO_DIR "${ROOT_DIR}/cmake/macros")
|
||||
|
||||
# setup for find modules
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/modules/")
|
||||
|
@ -16,11 +16,11 @@ setup_hifi_library(${TARGET_NAME})
|
|||
qt5_use_modules(${TARGET_NAME} Script)
|
||||
|
||||
include(${MACRO_DIR}/IncludeGLM.cmake)
|
||||
include_glm(${TARGET_NAME} ${ROOT_DIR})
|
||||
include_glm(${TARGET_NAME} "${ROOT_DIR}")
|
||||
|
||||
include(${MACRO_DIR}/LinkHifiLibrary.cmake)
|
||||
link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR})
|
||||
link_hifi_library(shared ${TARGET_NAME} "${ROOT_DIR}")
|
||||
|
||||
# link in the hifi voxels library
|
||||
link_hifi_library(octree ${TARGET_NAME} ${ROOT_DIR})
|
||||
link_hifi_library(voxels ${TARGET_NAME} ${ROOT_DIR})
|
||||
link_hifi_library(octree ${TARGET_NAME} "${ROOT_DIR}")
|
||||
link_hifi_library(voxels ${TARGET_NAME} "${ROOT_DIR}")
|
||||
|
|
|
@ -91,9 +91,9 @@ QByteArray AvatarData::toByteArray() {
|
|||
destinationBuffer += packFloatRatioToTwoByte(destinationBuffer, _targetScale);
|
||||
|
||||
// Head rotation (NOTE: This needs to become a quaternion to save two bytes)
|
||||
destinationBuffer += packFloatAngleToTwoByte(destinationBuffer, _headData->_yaw);
|
||||
destinationBuffer += packFloatAngleToTwoByte(destinationBuffer, _headData->_pitch);
|
||||
destinationBuffer += packFloatAngleToTwoByte(destinationBuffer, _headData->_roll);
|
||||
destinationBuffer += packFloatAngleToTwoByte(destinationBuffer, _headData->getTweakedYaw());
|
||||
destinationBuffer += packFloatAngleToTwoByte(destinationBuffer, _headData->getTweakedPitch());
|
||||
destinationBuffer += packFloatAngleToTwoByte(destinationBuffer, _headData->getTweakedRoll());
|
||||
|
||||
|
||||
// Head lean X,Z (head lateral and fwd/back motion relative to torso)
|
||||
|
|
|
@ -27,6 +27,7 @@ class AvatarData;
|
|||
class HeadData {
|
||||
public:
|
||||
HeadData(AvatarData* owningAvatar);
|
||||
virtual ~HeadData() { };
|
||||
|
||||
float getLeanSideways() const { return _leanSideways; }
|
||||
void setLeanSideways(float leanSideways) { _leanSideways = leanSideways; }
|
||||
|
@ -43,6 +44,10 @@ public:
|
|||
float getRoll() const { return _roll; }
|
||||
void setRoll(float roll) { _roll = glm::clamp(roll, MIN_HEAD_ROLL, MAX_HEAD_ROLL); }
|
||||
|
||||
virtual float getTweakedYaw() const { return _yaw; }
|
||||
virtual float getTweakedPitch() const { return _pitch; }
|
||||
virtual float getTweakedRoll() const { return _roll; }
|
||||
|
||||
glm::quat getOrientation() const;
|
||||
void setOrientation(const glm::quat& orientation);
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
cmake_minimum_required(VERSION 2.8)
|
||||
|
||||
set(ROOT_DIR ../..)
|
||||
set(MACRO_DIR ${ROOT_DIR}/cmake/macros)
|
||||
set(MACRO_DIR "${ROOT_DIR}/cmake/macros")
|
||||
|
||||
# setup for find modules
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/modules/")
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
cmake_minimum_required(VERSION 2.8)
|
||||
|
||||
set(ROOT_DIR ../..)
|
||||
set(MACRO_DIR ${ROOT_DIR}/cmake/macros)
|
||||
set(MACRO_DIR "${ROOT_DIR}/cmake/macros")
|
||||
|
||||
# setup for find modules
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/modules/")
|
||||
|
@ -12,13 +12,13 @@ find_package(Qt5Network REQUIRED)
|
|||
find_package(Qt5Widgets REQUIRED)
|
||||
|
||||
include(${MACRO_DIR}/AutoMTC.cmake)
|
||||
auto_mtc(${TARGET_NAME} ${ROOT_DIR})
|
||||
auto_mtc(${TARGET_NAME} "${ROOT_DIR}")
|
||||
|
||||
include(${MACRO_DIR}/SetupHifiLibrary.cmake)
|
||||
setup_hifi_library(${TARGET_NAME} ${AUTOMTC_SRC})
|
||||
setup_hifi_library(${TARGET_NAME} "${AUTOMTC_SRC}")
|
||||
|
||||
qt5_use_modules(${TARGET_NAME} Network Script Widgets)
|
||||
|
||||
include(${MACRO_DIR}/IncludeGLM.cmake)
|
||||
include_glm(${TARGET_NAME} ${ROOT_DIR})
|
||||
include_glm(${TARGET_NAME} "${ROOT_DIR}")
|
||||
|
||||
|
|
|
@ -69,7 +69,7 @@ int Bitstream::registerMetaObject(const char* className, const QMetaObject* meta
|
|||
getMetaObjects().insert(className, metaObject);
|
||||
|
||||
// register it as a subclass of itself and all of its superclasses
|
||||
for (const QMetaObject* superClass = metaObject; superClass != NULL; superClass = superClass->superClass()) {
|
||||
for (const QMetaObject* superClass = metaObject; superClass; superClass = superClass->superClass()) {
|
||||
getMetaObjectSubClasses().insert(superClass, metaObject);
|
||||
}
|
||||
return 0;
|
||||
|
|
|
@ -450,6 +450,13 @@ public:
|
|||
bool operator==(const X& first, const X& second); \
|
||||
bool operator!=(const X& first, const X& second); \
|
||||
static const int* _TypePtr##X = &X::Type;
|
||||
#elif __GNUC__
|
||||
#define DECLARE_STREAMABLE_METATYPE(X) Q_DECLARE_METATYPE(X) \
|
||||
Bitstream& operator<<(Bitstream& out, const X& obj); \
|
||||
Bitstream& operator>>(Bitstream& in, X& obj); \
|
||||
bool operator==(const X& first, const X& second); \
|
||||
bool operator!=(const X& first, const X& second); \
|
||||
__attribute__((unused)) static const int* _TypePtr##X = &X::Type;
|
||||
#else
|
||||
#define STRINGIFY(x) #x
|
||||
#define DECLARE_STREAMABLE_METATYPE(X) Q_DECLARE_METATYPE(X) \
|
||||
|
|
|
@ -784,7 +784,7 @@ void ScriptedMetavoxelGuide::setURL(const ParameterizedURL& url) {
|
|||
|
||||
bool MetavoxelVisitation::allInputNodesLeaves() const {
|
||||
foreach (MetavoxelNode* node, inputNodes) {
|
||||
if (node != NULL && !node->isLeaf()) {
|
||||
if (node && !node->isLeaf()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -792,7 +792,7 @@ bool MetavoxelVisitation::allInputNodesLeaves() const {
|
|||
}
|
||||
|
||||
AttributeValue MetavoxelVisitation::getInheritedOutputValue(int index) const {
|
||||
for (const MetavoxelVisitation* visitation = previous; visitation != NULL; visitation = visitation->previous) {
|
||||
for (const MetavoxelVisitation* visitation = previous; visitation; visitation = visitation->previous) {
|
||||
MetavoxelNode* node = visitation->outputNodes.at(index);
|
||||
if (node) {
|
||||
return node->getAttributeValue(visitor.getOutputs().at(index));
|
||||
|
|
|
@ -62,7 +62,7 @@ DelegatingItemEditorFactory::DelegatingItemEditorFactory() :
|
|||
|
||||
QWidget* DelegatingItemEditorFactory::createEditor(int userType, QWidget* parent) const {
|
||||
QWidget* editor = QItemEditorFactory::createEditor(userType, parent);
|
||||
return (editor == NULL) ? _parentFactory->createEditor(userType, parent) : editor;
|
||||
return (!editor) ? _parentFactory->createEditor(userType, parent) : editor;
|
||||
}
|
||||
|
||||
QByteArray DelegatingItemEditorFactory::valuePropertyName(int userType) const {
|
||||
|
|
|
@ -61,6 +61,8 @@ NetworkProgram::NetworkProgram(ScriptCache* cache, const QUrl& url) :
|
|||
|
||||
void NetworkProgram::downloadFinished(QNetworkReply* reply) {
|
||||
_program = QScriptProgram(QTextStream(reply).readAll(), reply->url().toString());
|
||||
reply->deleteLater();
|
||||
finishedLoading(true);
|
||||
emit loaded();
|
||||
}
|
||||
|
||||
|
|
|
@ -72,8 +72,6 @@ public:
|
|||
|
||||
ScriptCache* getCache() const { return _cache; }
|
||||
|
||||
bool isLoaded() const { return !_program.isNull(); }
|
||||
|
||||
const QScriptProgram& getProgram() const { return _program; }
|
||||
|
||||
signals:
|
||||
|
|
|
@ -163,7 +163,7 @@ void SharedObjectEditor::updateType() {
|
|||
oldObject->disconnect(this);
|
||||
}
|
||||
const QMetaObject* metaObject = _type->itemData(_type->currentIndex()).value<const QMetaObject*>();
|
||||
if (metaObject == NULL) {
|
||||
if (!metaObject) {
|
||||
_object.reset();
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
cmake_minimum_required(VERSION 2.8)
|
||||
|
||||
set(ROOT_DIR ../..)
|
||||
set(MACRO_DIR ${ROOT_DIR}/cmake/macros)
|
||||
set(MACRO_DIR "${ROOT_DIR}/cmake/macros")
|
||||
|
||||
# setup for find modules
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/modules/")
|
||||
|
@ -16,12 +16,12 @@ setup_hifi_library(${TARGET_NAME})
|
|||
qt5_use_modules(${TARGET_NAME} Widgets)
|
||||
|
||||
include(${MACRO_DIR}/IncludeGLM.cmake)
|
||||
include_glm(${TARGET_NAME} ${ROOT_DIR})
|
||||
include_glm(${TARGET_NAME} "${ROOT_DIR}")
|
||||
|
||||
include(${MACRO_DIR}/LinkHifiLibrary.cmake)
|
||||
link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR})
|
||||
link_hifi_library(shared ${TARGET_NAME} "${ROOT_DIR}")
|
||||
|
||||
# link ZLIB
|
||||
find_package(ZLIB)
|
||||
include_directories(${ZLIB_INCLUDE_DIRS})
|
||||
target_link_libraries(${TARGET_NAME} ${ZLIB_LIBRARIES})
|
||||
include_directories("${ZLIB_INCLUDE_DIRS}")
|
||||
target_link_libraries(${TARGET_NAME} "${ZLIB_LIBRARIES}")
|
||||
|
|
|
@ -62,7 +62,7 @@ bool JurisdictionSender::process() {
|
|||
_nodesRequestingJurisdictions.pop();
|
||||
SharedNodePointer node = NodeList::getInstance()->nodeWithUUID(nodeUUID);
|
||||
|
||||
if (node && node->getActiveSocket() != NULL) {
|
||||
if (node && node->getActiveSocket()) {
|
||||
_packetSender.queuePacketForSending(node, QByteArray(reinterpret_cast<char *>(bufferOut), sizeOut));
|
||||
nodeCount++;
|
||||
}
|
||||
|
|
|
@ -39,11 +39,13 @@ float boundaryDistanceForRenderLevel(unsigned int renderLevel, float voxelSizeSc
|
|||
}
|
||||
|
||||
Octree::Octree(bool shouldReaverage) :
|
||||
_rootNode(NULL),
|
||||
_isDirty(true),
|
||||
_shouldReaverage(shouldReaverage),
|
||||
_stopImport(false) {
|
||||
_rootNode = NULL;
|
||||
_isViewing = false;
|
||||
_stopImport(false),
|
||||
_lock(),
|
||||
_isViewing(false)
|
||||
{
|
||||
}
|
||||
|
||||
Octree::~Octree() {
|
||||
|
@ -150,7 +152,7 @@ void Octree::recurseNodeWithOperationDistanceSorted(OctreeElement* node, Recurse
|
|||
OctreeElement* Octree::nodeForOctalCode(OctreeElement* ancestorNode,
|
||||
const unsigned char* needleCode, OctreeElement** parentOfFoundNode) const {
|
||||
// special case for NULL octcode
|
||||
if (needleCode == NULL) {
|
||||
if (!needleCode) {
|
||||
return _rootNode;
|
||||
}
|
||||
|
||||
|
@ -330,7 +332,9 @@ void Octree::readBitstreamToTree(const unsigned char * bitstream, unsigned long
|
|||
|
||||
void Octree::deleteOctreeElementAt(float x, float y, float z, float s) {
|
||||
unsigned char* octalCode = pointToOctalCode(x,y,z,s);
|
||||
lockForWrite();
|
||||
deleteOctalCodeFromTree(octalCode);
|
||||
unlock();
|
||||
delete[] octalCode; // cleanup memory
|
||||
}
|
||||
|
||||
|
@ -497,7 +501,7 @@ void Octree::processRemoveOctreeElementsBitstream(const unsigned char* bitstream
|
|||
|
||||
// Note: this is an expensive call. Don't call it unless you really need to reaverage the entire tree (from startNode)
|
||||
void Octree::reaverageOctreeElements(OctreeElement* startNode) {
|
||||
if (startNode == NULL) {
|
||||
if (!startNode) {
|
||||
startNode = getRoot();
|
||||
}
|
||||
// if our tree is a reaveraging tree, then we do this, otherwise we don't do anything
|
||||
|
@ -586,9 +590,16 @@ bool findRayIntersectionOp(OctreeElement* node, void* extraData) {
|
|||
}
|
||||
|
||||
bool Octree::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
OctreeElement*& node, float& distance, BoxFace& face) {
|
||||
OctreeElement*& node, float& distance, BoxFace& face, bool tryLock) {
|
||||
RayArgs args = { origin / (float)(TREE_SCALE), direction, node, distance, face };
|
||||
recurseTreeWithOperation(findRayIntersectionOp, &args);
|
||||
|
||||
if (!tryLock) {
|
||||
lockForRead();
|
||||
}
|
||||
if (tryLock && tryLockForRead()) {
|
||||
recurseTreeWithOperation(findRayIntersectionOp, &args);
|
||||
unlock();
|
||||
}
|
||||
return args.found;
|
||||
}
|
||||
|
||||
|
@ -624,7 +635,7 @@ bool findSpherePenetrationOp(OctreeElement* element, void* extraData) {
|
|||
}
|
||||
|
||||
bool Octree::findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration,
|
||||
void** penetratedObject) {
|
||||
void** penetratedObject, bool tryLock) {
|
||||
|
||||
SphereArgs args = {
|
||||
center / (float)(TREE_SCALE),
|
||||
|
@ -633,9 +644,16 @@ bool Octree::findSpherePenetration(const glm::vec3& center, float radius, glm::v
|
|||
false,
|
||||
NULL };
|
||||
penetration = glm::vec3(0.0f, 0.0f, 0.0f);
|
||||
recurseTreeWithOperation(findSpherePenetrationOp, &args);
|
||||
if (penetratedObject) {
|
||||
*penetratedObject = args.penetratedObject;
|
||||
|
||||
if (!tryLock) {
|
||||
lockForRead();
|
||||
}
|
||||
if (tryLock && tryLockForRead()) {
|
||||
recurseTreeWithOperation(findSpherePenetrationOp, &args);
|
||||
if (penetratedObject) {
|
||||
*penetratedObject = args.penetratedObject;
|
||||
}
|
||||
unlock();
|
||||
}
|
||||
return args.found;
|
||||
}
|
||||
|
@ -670,17 +688,67 @@ bool findCapsulePenetrationOp(OctreeElement* node, void* extraData) {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool Octree::findCapsulePenetration(const glm::vec3& start, const glm::vec3& end, float radius, glm::vec3& penetration) {
|
||||
bool Octree::findCapsulePenetration(const glm::vec3& start, const glm::vec3& end, float radius,
|
||||
glm::vec3& penetration, bool tryLock) {
|
||||
|
||||
CapsuleArgs args = {
|
||||
start / (float)(TREE_SCALE),
|
||||
end / (float)(TREE_SCALE),
|
||||
radius / (float)(TREE_SCALE),
|
||||
penetration };
|
||||
penetration,
|
||||
false };
|
||||
penetration = glm::vec3(0.0f, 0.0f, 0.0f);
|
||||
recurseTreeWithOperation(findCapsulePenetrationOp, &args);
|
||||
|
||||
if (!tryLock) {
|
||||
lockForRead();
|
||||
}
|
||||
if (tryLock && tryLockForRead()) {
|
||||
recurseTreeWithOperation(findCapsulePenetrationOp, &args);
|
||||
unlock();
|
||||
}
|
||||
return args.found;
|
||||
}
|
||||
|
||||
class GetElementEnclosingArgs {
|
||||
public:
|
||||
OctreeElement* element;
|
||||
glm::vec3 point;
|
||||
};
|
||||
|
||||
// Find the smallest colored voxel enclosing a point (if there is one)
|
||||
bool getElementEnclosingOperation(OctreeElement* element, void* extraData) {
|
||||
GetElementEnclosingArgs* args = static_cast<GetElementEnclosingArgs*>(extraData);
|
||||
AABox elementBox = element->getAABox();
|
||||
if (elementBox.contains(args->point)) {
|
||||
if (element->hasContent() && element->isLeaf()) {
|
||||
// we've reached a solid leaf containing the point, return the node.
|
||||
args->element = element;
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// The point is not inside this voxel, so stop recursing.
|
||||
return false;
|
||||
}
|
||||
return true; // keep looking
|
||||
}
|
||||
|
||||
OctreeElement* Octree::getElementEnclosingPoint(const glm::vec3& point, bool tryLock) {
|
||||
GetElementEnclosingArgs args;
|
||||
args.point = point;
|
||||
args.element = NULL;
|
||||
|
||||
if (!tryLock) {
|
||||
lockForRead();
|
||||
}
|
||||
if (tryLock && tryLockForRead()) {
|
||||
recurseTreeWithOperation(getElementEnclosingOperation, (void*)&args);
|
||||
unlock();
|
||||
}
|
||||
return args.element;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int Octree::encodeTreeBitstream(OctreeElement* node,
|
||||
OctreePacketData* packetData, OctreeElementBag& bag,
|
||||
EncodeBitstreamParams& params) {
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
#include <set>
|
||||
#include <SimpleMovingAverage.h>
|
||||
|
||||
//#include "CoverageMap.h"
|
||||
class CoverageMap;
|
||||
class ReadBitstreamToTreeParams;
|
||||
class Octree;
|
||||
|
@ -223,12 +222,15 @@ public:
|
|||
void setDirtyBit() { _isDirty = true; }
|
||||
|
||||
bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
OctreeElement*& node, float& distance, BoxFace& face);
|
||||
OctreeElement*& node, float& distance, BoxFace& face, bool tryLock = true);
|
||||
|
||||
bool findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration,
|
||||
void** penetratedObject = NULL);
|
||||
void** penetratedObject = NULL, bool tryLock = true);
|
||||
|
||||
bool findCapsulePenetration(const glm::vec3& start, const glm::vec3& end, float radius, glm::vec3& penetration);
|
||||
bool findCapsulePenetration(const glm::vec3& start, const glm::vec3& end, float radius,
|
||||
glm::vec3& penetration, bool tryLock = true);
|
||||
|
||||
OctreeElement* getElementEnclosingPoint(const glm::vec3& point, bool tryLock = true);
|
||||
|
||||
// Note: this assumes the fileFormat is the HIO individual voxels code files
|
||||
void loadOctreeFile(const char* fileName, bool wantColorRandomizer);
|
||||
|
@ -236,16 +238,13 @@ public:
|
|||
// these will read/write files that match the wireformat, excluding the 'V' leading
|
||||
void writeToSVOFile(const char* filename, OctreeElement* node = NULL);
|
||||
bool readFromSVOFile(const char* filename);
|
||||
// reads voxels from square image with alpha as a Y-axis
|
||||
bool readFromSquareARGB32Pixels(const char *filename);
|
||||
bool readFromSchematicFile(const char* filename);
|
||||
|
||||
// Octree does not currently handle its own locking, caller must use these to lock/unlock
|
||||
void lockForRead() { lock.lockForRead(); }
|
||||
bool tryLockForRead() { return lock.tryLockForRead(); }
|
||||
void lockForWrite() { lock.lockForWrite(); }
|
||||
bool tryLockForWrite() { return lock.tryLockForWrite(); }
|
||||
void unlock() { lock.unlock(); }
|
||||
void lockForRead() { _lock.lockForRead(); }
|
||||
bool tryLockForRead() { return _lock.tryLockForRead(); }
|
||||
void lockForWrite() { _lock.lockForWrite(); }
|
||||
bool tryLockForWrite() { return _lock.tryLockForWrite(); }
|
||||
void unlock() { _lock.unlock(); }
|
||||
|
||||
unsigned long getOctreeElementsCount();
|
||||
|
||||
|
@ -330,7 +329,7 @@ protected:
|
|||
/// flushes out any Octal Codes that had to be queued
|
||||
void emptyDeleteQueue();
|
||||
|
||||
QReadWriteLock lock;
|
||||
QReadWriteLock _lock;
|
||||
|
||||
/// This tree is receiving inbound viewer datagrams.
|
||||
bool _isViewing;
|
||||
|
|
|
@ -177,7 +177,7 @@ void OctreeEditPacketSender::queuePacketToNodes(unsigned char* buffer, ssize_t l
|
|||
|
||||
foreach (const SharedNodePointer& node, NodeList::getInstance()->getNodeHash()) {
|
||||
// only send to the NodeTypes that are getMyNodeType()
|
||||
if (node->getActiveSocket() != NULL && node->getType() == getMyNodeType()) {
|
||||
if (node->getActiveSocket() && node->getType() == getMyNodeType()) {
|
||||
QUuid nodeUUID = node->getUUID();
|
||||
bool isMyJurisdiction = true;
|
||||
// we need to get the jurisdiction for this
|
||||
|
@ -226,7 +226,7 @@ void OctreeEditPacketSender::queueOctreeEditMessage(PacketType type, unsigned ch
|
|||
|
||||
foreach (const SharedNodePointer& node, NodeList::getInstance()->getNodeHash()) {
|
||||
// only send to the NodeTypes that are getMyNodeType()
|
||||
if (node->getActiveSocket() != NULL && node->getType() == getMyNodeType()) {
|
||||
if (node->getActiveSocket() && node->getType() == getMyNodeType()) {
|
||||
QUuid nodeUUID = node->getUUID();
|
||||
bool isMyJurisdiction = true;
|
||||
|
||||
|
|
|
@ -739,7 +739,7 @@ void OctreeElement::setChildAtIndex(int childIndex, OctreeElement* child) {
|
|||
_externalChildrenMemoryUsage += NUMBER_OF_CHILDREN * sizeof(OctreeElement*);
|
||||
|
||||
} else if (previousChildCount == 2 && newChildCount == 1) {
|
||||
assert(child == NULL); // we are removing a child, so this must be true!
|
||||
assert(!child); // we are removing a child, so this must be true!
|
||||
OctreeElement* previousFirstChild = _children.external[firstIndex];
|
||||
OctreeElement* previousSecondChild = _children.external[secondIndex];
|
||||
delete[] _children.external;
|
||||
|
|
|
@ -75,7 +75,7 @@ void OctreeHeadlessViewer::queryOctree() {
|
|||
|
||||
foreach (const SharedNodePointer& node, NodeList::getInstance()->getNodeHash()) {
|
||||
// only send to the NodeTypes that are serverType
|
||||
if (node->getActiveSocket() != NULL && node->getType() == serverType) {
|
||||
if (node->getActiveSocket() && node->getType() == serverType) {
|
||||
totalServers++;
|
||||
|
||||
// get the server bounds for this server
|
||||
|
@ -135,7 +135,7 @@ void OctreeHeadlessViewer::queryOctree() {
|
|||
|
||||
foreach (const SharedNodePointer& node, nodeList->getNodeHash()) {
|
||||
// only send to the NodeTypes that are serverType
|
||||
if (node->getActiveSocket() != NULL && node->getType() == serverType) {
|
||||
if (node->getActiveSocket() && node->getType() == serverType) {
|
||||
|
||||
|
||||
// get the server bounds for this server
|
||||
|
|
|
@ -68,9 +68,7 @@ bool OctreePersistThread::process() {
|
|||
usleep(USECS_TO_SLEEP);
|
||||
|
||||
// do our updates then check to save...
|
||||
_tree->lockForWrite();
|
||||
_tree->update();
|
||||
_tree->unlock();
|
||||
|
||||
quint64 now = usecTimestampNow();
|
||||
quint64 sinceLastSave = now - _lastCheck;
|
||||
|
|
|
@ -14,16 +14,32 @@
|
|||
#include <PerfStat.h>
|
||||
#include "OctreeRenderer.h"
|
||||
|
||||
OctreeRenderer::OctreeRenderer() {
|
||||
_tree = NULL;
|
||||
_viewFrustum = NULL;
|
||||
OctreeRenderer::OctreeRenderer() :
|
||||
_tree(NULL),
|
||||
_managedTree(false),
|
||||
_viewFrustum(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
void OctreeRenderer::init() {
|
||||
_tree = createTree();
|
||||
if (!_tree) {
|
||||
_tree = createTree();
|
||||
_managedTree = true;
|
||||
}
|
||||
}
|
||||
|
||||
OctreeRenderer::~OctreeRenderer() {
|
||||
if (_tree && _managedTree) {
|
||||
delete _tree;
|
||||
}
|
||||
}
|
||||
|
||||
void OctreeRenderer::setTree(Octree* newTree) {
|
||||
if (_tree && _managedTree) {
|
||||
delete _tree;
|
||||
_managedTree = false;
|
||||
}
|
||||
_tree = newTree;
|
||||
}
|
||||
|
||||
void OctreeRenderer::processDatagram(const QByteArray& dataByteArray, const SharedNodePointer& sourceNode) {
|
||||
|
|
|
@ -44,6 +44,8 @@ public:
|
|||
virtual PacketType getMyQueryMessageType() const = 0;
|
||||
virtual PacketType getExpectedPacketType() const = 0;
|
||||
virtual void renderElement(OctreeElement* element, RenderArgs* args) = 0;
|
||||
|
||||
virtual void setTree(Octree* newTree);
|
||||
|
||||
/// process incoming data
|
||||
virtual void processDatagram(const QByteArray& dataByteArray, const SharedNodePointer& sourceNode);
|
||||
|
@ -63,6 +65,7 @@ public:
|
|||
void clear();
|
||||
protected:
|
||||
Octree* _tree;
|
||||
bool _managedTree;
|
||||
ViewFrustum* _viewFrustum;
|
||||
};
|
||||
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
|
||||
#include <QtCore/QDebug>
|
||||
|
||||
//#include "CoverageMap.h"
|
||||
#include "GeometryUtil.h"
|
||||
#include "SharedUtil.h"
|
||||
#include "ViewFrustum.h"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
cmake_minimum_required(VERSION 2.8)
|
||||
|
||||
set(ROOT_DIR ../..)
|
||||
set(MACRO_DIR ${ROOT_DIR}/cmake/macros)
|
||||
set(MACRO_DIR "${ROOT_DIR}/cmake/macros")
|
||||
|
||||
# setup for find modules
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/modules/")
|
||||
|
@ -16,13 +16,13 @@ setup_hifi_library(${TARGET_NAME})
|
|||
qt5_use_modules(${TARGET_NAME} Widgets)
|
||||
|
||||
include(${MACRO_DIR}/IncludeGLM.cmake)
|
||||
include_glm(${TARGET_NAME} ${ROOT_DIR})
|
||||
include_glm(${TARGET_NAME} "${ROOT_DIR}")
|
||||
|
||||
include(${MACRO_DIR}/LinkHifiLibrary.cmake)
|
||||
link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR})
|
||||
link_hifi_library(octree ${TARGET_NAME} ${ROOT_DIR})
|
||||
link_hifi_library(shared ${TARGET_NAME} "${ROOT_DIR}")
|
||||
link_hifi_library(octree ${TARGET_NAME} "${ROOT_DIR}")
|
||||
|
||||
# link ZLIB
|
||||
find_package(ZLIB)
|
||||
include_directories(${ZLIB_INCLUDE_DIRS})
|
||||
target_link_libraries(${TARGET_NAME} ${ZLIB_LIBRARIES})
|
||||
include_directories("${ZLIB_INCLUDE_DIRS}")
|
||||
target_link_libraries(${TARGET_NAME} "${ZLIB_LIBRARIES}")
|
||||
|
|
|
@ -99,8 +99,8 @@ void ParticleTree::storeParticle(const Particle& particle, const SharedNodePoint
|
|||
if (!args.found) {
|
||||
glm::vec3 position = particle.getPosition();
|
||||
float size = std::max(MINIMUM_PARTICLE_ELEMENT_SIZE, particle.getRadius());
|
||||
ParticleTreeElement* element = (ParticleTreeElement*)getOrCreateChildElementAt(position.x, position.y, position.z, size);
|
||||
|
||||
ParticleTreeElement* element = (ParticleTreeElement*)getOrCreateChildElementAt(position.x, position.y, position.z, size);
|
||||
element->storeParticle(particle);
|
||||
}
|
||||
// what else do we need to do here to get reaveraging to work
|
||||
|
@ -149,8 +149,8 @@ void ParticleTree::addParticle(const ParticleID& particleID, const ParticlePrope
|
|||
Particle particle(particleID, properties);
|
||||
glm::vec3 position = particle.getPosition();
|
||||
float size = std::max(MINIMUM_PARTICLE_ELEMENT_SIZE, particle.getRadius());
|
||||
|
||||
ParticleTreeElement* element = (ParticleTreeElement*)getOrCreateChildElementAt(position.x, position.y, position.z, size);
|
||||
|
||||
element->storeParticle(particle);
|
||||
|
||||
_isDirty = true;
|
||||
|
@ -372,10 +372,9 @@ bool ParticleTree::findByIDOperation(OctreeElement* element, void* extraData) {
|
|||
|
||||
const Particle* ParticleTree::findParticleByID(uint32_t id, bool alreadyLocked) {
|
||||
FindByIDArgs args = { id, false, NULL };
|
||||
|
||||
if (!alreadyLocked) {
|
||||
//qDebug() << "ParticleTree::findParticleByID().... about to call lockForRead()....";
|
||||
lockForRead();
|
||||
//qDebug() << "ParticleTree::findParticleByID().... after call lockForRead()....";
|
||||
}
|
||||
recurseTreeWithOperation(findByIDOperation, &args);
|
||||
if (!alreadyLocked) {
|
||||
|
@ -460,6 +459,7 @@ bool ParticleTree::pruneOperation(OctreeElement* element, void* extraData) {
|
|||
}
|
||||
|
||||
void ParticleTree::update() {
|
||||
lockForWrite();
|
||||
_isDirty = true;
|
||||
|
||||
ParticleTreeUpdateArgs args = { };
|
||||
|
@ -486,6 +486,7 @@ void ParticleTree::update() {
|
|||
|
||||
// prune the tree...
|
||||
recurseTreeWithOperation(pruneOperation, NULL);
|
||||
unlock();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -30,12 +30,10 @@ public:
|
|||
private slots:
|
||||
/// inbound slots for external collision systems
|
||||
void forwardParticleCollisionWithVoxel(const ParticleID& particleID, const VoxelDetail& voxel) {
|
||||
qDebug() << "forwardParticleCollisionWithVoxel()";
|
||||
emit particleCollisionWithVoxel(particleID, voxel);
|
||||
}
|
||||
|
||||
void forwardParticleCollisionWithParticle(const ParticleID& idA, const ParticleID& idB) {
|
||||
qDebug() << "forwardParticleCollisionWithParticle()";
|
||||
emit particleCollisionWithParticle(idA, idB);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
cmake_minimum_required(VERSION 2.8)
|
||||
|
||||
set(ROOT_DIR ../..)
|
||||
set(MACRO_DIR ${ROOT_DIR}/cmake/macros)
|
||||
set(MACRO_DIR "${ROOT_DIR}/cmake/macros")
|
||||
|
||||
# setup for find modules
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/modules/")
|
||||
|
@ -16,15 +16,15 @@ setup_hifi_library(${TARGET_NAME})
|
|||
qt5_use_modules(${TARGET_NAME} Widgets)
|
||||
|
||||
include(${MACRO_DIR}/IncludeGLM.cmake)
|
||||
include_glm(${TARGET_NAME} ${ROOT_DIR})
|
||||
include_glm(${TARGET_NAME} "${ROOT_DIR}")
|
||||
|
||||
include(${MACRO_DIR}/LinkHifiLibrary.cmake)
|
||||
link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR})
|
||||
link_hifi_library(octree ${TARGET_NAME} ${ROOT_DIR})
|
||||
link_hifi_library(voxels ${TARGET_NAME} ${ROOT_DIR})
|
||||
link_hifi_library(particles ${TARGET_NAME} ${ROOT_DIR})
|
||||
link_hifi_library(shared ${TARGET_NAME} "${ROOT_DIR}")
|
||||
link_hifi_library(octree ${TARGET_NAME} "${ROOT_DIR}")
|
||||
link_hifi_library(voxels ${TARGET_NAME} "${ROOT_DIR}")
|
||||
link_hifi_library(particles ${TARGET_NAME} "${ROOT_DIR}")
|
||||
|
||||
# link ZLIB
|
||||
find_package(ZLIB)
|
||||
include_directories(${ZLIB_INCLUDE_DIRS})
|
||||
target_link_libraries(${TARGET_NAME} ${ZLIB_LIBRARIES})
|
||||
include_directories("${ZLIB_INCLUDE_DIRS}")
|
||||
target_link_libraries(${TARGET_NAME} "${ZLIB_LIBRARIES}")
|
||||
|
|
153
libraries/script-engine/src/LocalVoxels.cpp
Normal file
153
libraries/script-engine/src/LocalVoxels.cpp
Normal file
|
@ -0,0 +1,153 @@
|
|||
//
|
||||
// LocalVoxels.cpp
|
||||
// hifi
|
||||
//
|
||||
// Created by Clément Brisset on 2/24/14.
|
||||
// Copyright (c) 2014 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#include "LocalVoxels.h"
|
||||
|
||||
LocalVoxels::LocalVoxels(QString name) :
|
||||
QObject(NULL),
|
||||
_name(name),
|
||||
_tree(new VoxelTree(true))
|
||||
{
|
||||
LocalVoxelsList::getInstance()->insert(_name, _tree);
|
||||
}
|
||||
|
||||
LocalVoxels::~LocalVoxels() {
|
||||
_tree.clear();
|
||||
LocalVoxelsList::getInstance()->remove(_name);
|
||||
}
|
||||
|
||||
VoxelDetail LocalVoxels::getVoxelAt(float x, float y, float z, float scale) {
|
||||
// setup a VoxelDetail struct with the data
|
||||
VoxelDetail result = {0,0,0,0,0,0,0};
|
||||
if (_tree) {
|
||||
_tree->lockForRead();
|
||||
|
||||
VoxelTreeElement* voxel = static_cast<VoxelTreeElement*>(_tree->getOctreeElementAt(x / (float)TREE_SCALE,
|
||||
y / (float)TREE_SCALE,
|
||||
z / (float)TREE_SCALE,
|
||||
scale / (float)TREE_SCALE));
|
||||
_tree->unlock();
|
||||
if (voxel) {
|
||||
// Note: these need to be in voxel space because the VoxelDetail -> js converter will upscale
|
||||
result.x = voxel->getCorner().x;
|
||||
result.y = voxel->getCorner().y;
|
||||
result.z = voxel->getCorner().z;
|
||||
result.s = voxel->getScale();
|
||||
result.red = voxel->getColor()[RED_INDEX];
|
||||
result.green = voxel->getColor()[GREEN_INDEX];
|
||||
result.blue = voxel->getColor()[BLUE_INDEX];
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void LocalVoxels::setVoxelNonDestructive(float x, float y, float z, float scale,
|
||||
uchar red, uchar green, uchar blue) {
|
||||
if (_name == DOMAIN_TREE_NAME) {
|
||||
qDebug() << "LocalVoxels::setVoxelNonDestructive(): Please use the \"Voxels\" interface to modify the domain tree.";
|
||||
return;
|
||||
}
|
||||
if (_tree ) {
|
||||
_tree->createVoxel(x / (float)TREE_SCALE,
|
||||
y / (float)TREE_SCALE,
|
||||
z / (float)TREE_SCALE,
|
||||
scale / (float)TREE_SCALE,
|
||||
red, green, blue, false);
|
||||
}
|
||||
}
|
||||
|
||||
void LocalVoxels::setVoxel(float x, float y, float z, float scale,
|
||||
uchar red, uchar green, uchar blue) {
|
||||
if (_name == DOMAIN_TREE_NAME) {
|
||||
qDebug() << "LocalVoxels::setVoxel(): Please use the \"Voxels\" interface to modify the domain tree.";
|
||||
return;
|
||||
}
|
||||
if (_tree ) {
|
||||
_tree->createVoxel(x / (float)TREE_SCALE,
|
||||
y / (float)TREE_SCALE,
|
||||
z / (float)TREE_SCALE,
|
||||
scale / (float)TREE_SCALE,
|
||||
red, green, blue, true);
|
||||
}
|
||||
}
|
||||
|
||||
void LocalVoxels::eraseVoxel(float x, float y, float z, float scale) {
|
||||
if (_name == DOMAIN_TREE_NAME) {
|
||||
qDebug() << "LocalVoxels::eraseVoxel(): Please use the \"Voxels\" interface to modify the domain tree.";
|
||||
return;
|
||||
}
|
||||
if (_tree ) {
|
||||
_tree->deleteVoxelAt(x / (float)TREE_SCALE,
|
||||
y / (float)TREE_SCALE,
|
||||
z / (float)TREE_SCALE,
|
||||
scale / (float)TREE_SCALE);
|
||||
}
|
||||
}
|
||||
|
||||
void LocalVoxels::copyTo(float x, float y, float z, float scale, const QString destination) {
|
||||
if (destination == DOMAIN_TREE_NAME) {
|
||||
qDebug() << "LocalVoxels::copyTo(): Please use the \"Voxels\" interface to modify the domain tree.";
|
||||
return;
|
||||
}
|
||||
StrongVoxelTreePointer destinationTree = LocalVoxelsList::getInstance()->getTree(destination);
|
||||
VoxelTreeElement* destinationNode = destinationTree->getVoxelAt(x / (float)TREE_SCALE,
|
||||
y / (float)TREE_SCALE,
|
||||
z / (float)TREE_SCALE,
|
||||
scale / (float)TREE_SCALE);
|
||||
destinationTree->copyFromTreeIntoSubTree(_tree.data(), destinationNode);
|
||||
}
|
||||
|
||||
void LocalVoxels::pasteFrom(float x, float y, float z, float scale, const QString source) {
|
||||
if (_name == DOMAIN_TREE_NAME) {
|
||||
qDebug() << "LocalVoxels::pasteFrom(): Please use the \"Voxels\" interface to modify the domain tree.";
|
||||
return;
|
||||
}
|
||||
StrongVoxelTreePointer sourceTree = LocalVoxelsList::getInstance()->getTree(source);
|
||||
VoxelTreeElement* sourceNode = _tree->getVoxelAt(x / (float)TREE_SCALE,
|
||||
y / (float)TREE_SCALE,
|
||||
z / (float)TREE_SCALE,
|
||||
scale / (float)TREE_SCALE);
|
||||
_tree->copySubTreeIntoNewTree(sourceNode, sourceTree.data(), true);
|
||||
}
|
||||
|
||||
RayToVoxelIntersectionResult LocalVoxels::findRayIntersection(const PickRay& ray) {
|
||||
RayToVoxelIntersectionResult result;
|
||||
if (_tree) {
|
||||
OctreeElement* element;
|
||||
result.intersects = _tree->findRayIntersection(ray.origin, ray.direction, element, result.distance, result.face);
|
||||
if (result.intersects) {
|
||||
VoxelTreeElement* voxel = (VoxelTreeElement*)element;
|
||||
result.voxel.x = voxel->getCorner().x;
|
||||
result.voxel.y = voxel->getCorner().y;
|
||||
result.voxel.z = voxel->getCorner().z;
|
||||
result.voxel.s = voxel->getScale();
|
||||
result.voxel.red = voxel->getColor()[0];
|
||||
result.voxel.green = voxel->getColor()[1];
|
||||
result.voxel.blue = voxel->getColor()[2];
|
||||
result.intersection = ray.origin + (ray.direction * result.distance);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
glm::vec3 LocalVoxels::getFaceVector(const QString& face) {
|
||||
if (face == "MIN_X_FACE") {
|
||||
return glm::vec3(-1, 0, 0);
|
||||
} else if (face == "MAX_X_FACE") {
|
||||
return glm::vec3(1, 0, 0);
|
||||
} else if (face == "MIN_Y_FACE") {
|
||||
return glm::vec3(0, -1, 0);
|
||||
} else if (face == "MAX_Y_FACE") {
|
||||
return glm::vec3(0, 1, 0);
|
||||
} else if (face == "MIN_Z_FACE") {
|
||||
return glm::vec3(0, 0, -1);
|
||||
} else if (face == "MAX_Z_FACE") {
|
||||
return glm::vec3(0, 0, 1);
|
||||
}
|
||||
return glm::vec3(0, 0, 0); //error case
|
||||
}
|
90
libraries/script-engine/src/LocalVoxels.h
Normal file
90
libraries/script-engine/src/LocalVoxels.h
Normal file
|
@ -0,0 +1,90 @@
|
|||
//
|
||||
// LocalVoxels.h
|
||||
// hifi
|
||||
//
|
||||
// Created by Clément Brisset on 2/24/14.
|
||||
// Copyright (c) 2014 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef __hifi__LocalVoxels__
|
||||
#define __hifi__LocalVoxels__
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include <RegisteredMetaTypes.h>
|
||||
#include <LocalVoxelsList.h>
|
||||
|
||||
|
||||
/// object allowing JS scripters to use their own local trees
|
||||
class LocalVoxels : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
LocalVoxels(QString name);
|
||||
~LocalVoxels();
|
||||
|
||||
/// checks the local voxel tree for a voxel at the specified location and scale
|
||||
/// \param x the x-coordinate of the voxel (in meter units)
|
||||
/// \param y the y-coordinate of the voxel (in meter units)
|
||||
/// \param z the z-coordinate of the voxel (in meter units)
|
||||
/// \param scale the scale of the voxel (in meter units)
|
||||
Q_INVOKABLE VoxelDetail getVoxelAt(float x, float y, float z, float scale);
|
||||
|
||||
/// creates a non destructive voxel in the local tree
|
||||
/// \param x the x-coordinate of the voxel (in meter units)
|
||||
/// \param y the y-coordinate of the voxel (in meter units)
|
||||
/// \param z the z-coordinate of the voxel (in meter units)
|
||||
/// \param scale the scale of the voxel (in meter units)
|
||||
/// \param red the R value for RGB color of voxel
|
||||
/// \param green the G value for RGB color of voxel
|
||||
/// \param blue the B value for RGB color of voxel
|
||||
Q_INVOKABLE void setVoxelNonDestructive(float x, float y, float z, float scale, uchar red, uchar green, uchar blue);
|
||||
|
||||
/// creates a voxel in the local tree
|
||||
/// \param x the x-coordinate of the voxel (in meter units)
|
||||
/// \param y the y-coordinate of the voxel (in meter units)
|
||||
/// \param z the z-coordinate of the voxel (in meter units)
|
||||
/// \param scale the scale of the voxel (in meter units)
|
||||
/// \param red the R value for RGB color of voxel
|
||||
/// \param green the G value for RGB color of voxel
|
||||
/// \param blue the B value for RGB color of voxel
|
||||
Q_INVOKABLE void setVoxel(float x, float y, float z, float scale, uchar red, uchar green, uchar blue);
|
||||
|
||||
/// erase the voxel and its children at the given coordinate
|
||||
/// \param x the x-coordinate of the voxel (in meter units)
|
||||
/// \param y the y-coordinate of the voxel (in meter units)
|
||||
/// \param z the z-coordinate of the voxel (in meter units)
|
||||
/// \param scale the scale of the voxel (in meter units)
|
||||
Q_INVOKABLE void eraseVoxel(float x, float y, float z, float scale);
|
||||
|
||||
/// copy the given subtree onto destination's root node
|
||||
/// \param x the x-coordinate of the subtree (in meter units)
|
||||
/// \param y the y-coordinate of the subtree (in meter units)
|
||||
/// \param z the z-coordinate of the subtree (in meter units)
|
||||
/// \param scale the scale of the subtree (in meter units)
|
||||
/// \param destination LocalVoxels' destination tree
|
||||
Q_INVOKABLE void copyTo(float x, float y, float z, float scale, const QString destination);
|
||||
|
||||
///copy source in the given subtree
|
||||
/// \param x the x-coordinate of the subtree (in meter units)
|
||||
/// \param y the y-coordinate of the subtree (in meter units)
|
||||
/// \param z the z-coordinate of the subtree (in meter units)
|
||||
/// \param scale the scale of the subtree (in meter units)
|
||||
/// \param source LocalVoxels' source tree
|
||||
Q_INVOKABLE void pasteFrom(float x, float y, float z, float scale, const QString source);
|
||||
|
||||
/// If the scripting context has visible voxels, this will determine a ray intersection
|
||||
Q_INVOKABLE RayToVoxelIntersectionResult findRayIntersection(const PickRay& ray);
|
||||
|
||||
/// returns a voxel space axis aligned vector for the face, useful in doing voxel math
|
||||
Q_INVOKABLE glm::vec3 getFaceVector(const QString& face);
|
||||
|
||||
private:
|
||||
QString _name;
|
||||
StrongVoxelTreePointer _tree;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
#endif /* defined(__hifi__LocalVoxels__) */
|
|
@ -71,6 +71,7 @@ void menuItemPropertiesFromScriptValue(const QScriptValue& object, MenuItemPrope
|
|||
properties.menuItemName = object.property("menuItemName").toVariant().toString();
|
||||
properties.isCheckable = object.property("isCheckable").toVariant().toBool();
|
||||
properties.isChecked = object.property("isChecked").toVariant().toBool();
|
||||
properties.isSeparator = object.property("isSeparator").toVariant().toBool();
|
||||
|
||||
// handle the shortcut key options in order...
|
||||
QScriptValue shortcutKeyValue = object.property("shortcutKey");
|
||||
|
|
|
@ -39,6 +39,7 @@ public:
|
|||
// other properties
|
||||
bool isCheckable;
|
||||
bool isChecked;
|
||||
bool isSeparator;
|
||||
};
|
||||
Q_DECLARE_METATYPE(MenuItemProperties)
|
||||
QScriptValue menuItemPropertiesToScriptValue(QScriptEngine* engine, const MenuItemProperties& props);
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include <Sound.h>
|
||||
|
||||
#include "MenuItemProperties.h"
|
||||
#include "LocalVoxels.h"
|
||||
#include "ScriptEngine.h"
|
||||
|
||||
const unsigned int VISUAL_DATA_CALLBACK_USECS = (1.0 / 60.0) * 1000 * 1000;
|
||||
|
@ -118,6 +119,7 @@ bool ScriptEngine::setScriptContents(const QString& scriptContents) {
|
|||
}
|
||||
|
||||
Q_SCRIPT_DECLARE_QMETAOBJECT(AudioInjectorOptions, QObject*)
|
||||
Q_SCRIPT_DECLARE_QMETAOBJECT(LocalVoxels, QString)
|
||||
|
||||
void ScriptEngine::init() {
|
||||
if (_isInitialized) {
|
||||
|
@ -146,6 +148,9 @@ void ScriptEngine::init() {
|
|||
|
||||
QScriptValue injectionOptionValue = _engine.scriptValueFromQMetaObject<AudioInjectorOptions>();
|
||||
_engine.globalObject().setProperty("AudioInjectionOptions", injectionOptionValue);
|
||||
|
||||
QScriptValue localVoxelsValue = _engine.scriptValueFromQMetaObject<LocalVoxels>();
|
||||
_engine.globalObject().setProperty("LocalVoxels", localVoxelsValue);
|
||||
|
||||
registerGlobalObject("Script", this);
|
||||
registerGlobalObject("Audio", &_audioScriptingInterface);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
cmake_minimum_required(VERSION 2.8)
|
||||
|
||||
set(ROOT_DIR ../..)
|
||||
set(MACRO_DIR ${ROOT_DIR}/cmake/macros)
|
||||
set(MACRO_DIR "${ROOT_DIR}/cmake/macros")
|
||||
|
||||
set(TARGET_NAME shared)
|
||||
project(${TARGET_NAME})
|
||||
|
@ -16,18 +16,18 @@ qt5_use_modules(${TARGET_NAME} Network Widgets)
|
|||
|
||||
# include GLM
|
||||
include(${MACRO_DIR}/IncludeGLM.cmake)
|
||||
include_glm(${TARGET_NAME} ${ROOT_DIR})
|
||||
include_glm(${TARGET_NAME} "${ROOT_DIR}")
|
||||
|
||||
|
||||
set(EXTERNAL_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external)
|
||||
set(EXTERNAL_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/external")
|
||||
|
||||
if (WIN32)
|
||||
# include headers for external libraries and InterfaceConfig.
|
||||
include_directories(${EXTERNAL_ROOT_DIR})
|
||||
include_directories("${EXTERNAL_ROOT_DIR}")
|
||||
endif (WIN32)
|
||||
|
||||
# link required libraries on UNIX
|
||||
if (UNIX AND NOT APPLE)
|
||||
find_package(Threads REQUIRED)
|
||||
target_link_libraries(${TARGET_NAME} ${CMAKE_THREAD_LIBS_INIT})
|
||||
target_link_libraries(${TARGET_NAME} "${CMAKE_THREAD_LIBS_INIT}")
|
||||
endif (UNIX AND NOT APPLE)
|
||||
|
|
|
@ -35,7 +35,7 @@ const QString ACCOUNTS_GROUP = "accounts";
|
|||
|
||||
AccountManager::AccountManager() :
|
||||
_authURL(),
|
||||
_networkAccessManager(),
|
||||
_networkAccessManager(new QNetworkAccessManager(this)),
|
||||
_pendingCallbackMap(),
|
||||
_accountInfo()
|
||||
{
|
||||
|
@ -130,16 +130,16 @@ void AccountManager::invokedRequest(const QString& path, QNetworkAccessManager::
|
|||
|
||||
switch (operation) {
|
||||
case QNetworkAccessManager::GetOperation:
|
||||
networkReply = _networkAccessManager.get(authenticatedRequest);
|
||||
networkReply = _networkAccessManager->get(authenticatedRequest);
|
||||
break;
|
||||
case QNetworkAccessManager::PostOperation:
|
||||
case QNetworkAccessManager::PutOperation:
|
||||
authenticatedRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
|
||||
|
||||
if (operation == QNetworkAccessManager::PostOperation) {
|
||||
networkReply = _networkAccessManager.post(authenticatedRequest, dataByteArray);
|
||||
networkReply = _networkAccessManager->post(authenticatedRequest, dataByteArray);
|
||||
} else {
|
||||
networkReply = _networkAccessManager.put(authenticatedRequest, dataByteArray);
|
||||
networkReply = _networkAccessManager->put(authenticatedRequest, dataByteArray);
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -242,7 +242,7 @@ void AccountManager::requestAccessToken(const QString& login, const QString& pas
|
|||
request.setUrl(grantURL);
|
||||
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
|
||||
|
||||
QNetworkReply* requestReply = _networkAccessManager.post(request, postData);
|
||||
QNetworkReply* requestReply = _networkAccessManager->post(request, postData);
|
||||
connect(requestReply, &QNetworkReply::finished, this, &AccountManager::requestFinished);
|
||||
connect(requestReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(requestError(QNetworkReply::NetworkError)));
|
||||
}
|
||||
|
@ -292,4 +292,4 @@ void AccountManager::requestFinished() {
|
|||
void AccountManager::requestError(QNetworkReply::NetworkError error) {
|
||||
// TODO: error handling
|
||||
qDebug() << "AccountManager requestError - " << error;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ public:
|
|||
jsonCallbackReceiver(NULL), jsonCallbackMethod(),
|
||||
errorCallbackReceiver(NULL), errorCallbackMethod() {};
|
||||
|
||||
bool isEmpty() const { return jsonCallbackReceiver == NULL && errorCallbackReceiver == NULL; }
|
||||
bool isEmpty() const { return !jsonCallbackReceiver && !errorCallbackReceiver; }
|
||||
|
||||
QObject* jsonCallbackReceiver;
|
||||
QString jsonCallbackMethod;
|
||||
|
@ -53,6 +53,8 @@ public:
|
|||
|
||||
QString getUsername() const { return _accountInfo.getUsername(); }
|
||||
|
||||
void destroy() { delete _networkAccessManager; }
|
||||
|
||||
public slots:
|
||||
void requestFinished();
|
||||
void requestError(QNetworkReply::NetworkError error);
|
||||
|
@ -76,7 +78,7 @@ private:
|
|||
const JSONCallbackParameters& callbackParams, const QByteArray& dataByteArray);
|
||||
|
||||
QUrl _authURL;
|
||||
QNetworkAccessManager _networkAccessManager;
|
||||
QNetworkAccessManager* _networkAccessManager;
|
||||
QMap<QNetworkReply*, JSONCallbackParameters> _pendingCallbackMap;
|
||||
|
||||
DataServerAccountInfo _accountInfo;
|
||||
|
|
|
@ -72,6 +72,5 @@ void GenericThread::threadRoutine() {
|
|||
if (_isThreaded && _thread) {
|
||||
_thread->quit();
|
||||
}
|
||||
|
||||
emit finished();
|
||||
}
|
||||
|
|
|
@ -62,10 +62,7 @@ Node::Node(const QUuid& uuid, char type, const HifiSockAddr& publicSocket, const
|
|||
}
|
||||
|
||||
Node::~Node() {
|
||||
if (_linkedData) {
|
||||
delete _linkedData;
|
||||
}
|
||||
|
||||
delete _linkedData;
|
||||
delete _bytesReceivedMovingAverage;
|
||||
}
|
||||
|
||||
|
@ -98,7 +95,7 @@ void Node::activatePublicSocket() {
|
|||
}
|
||||
|
||||
void Node::recordBytesReceived(int bytesReceived) {
|
||||
if (_bytesReceivedMovingAverage == NULL) {
|
||||
if (!_bytesReceivedMovingAverage) {
|
||||
_bytesReceivedMovingAverage = new SimpleMovingAverage(100);
|
||||
}
|
||||
|
||||
|
|
|
@ -264,6 +264,11 @@ void NodeList::processNodeData(const HifiSockAddr& senderSockAddr, const QByteAr
|
|||
break;
|
||||
}
|
||||
default:
|
||||
// the node decided not to do anything with this packet
|
||||
// if it comes from a known source we should keep that node alive
|
||||
SharedNodePointer matchingNode = sendingNodeForPacket(packet);
|
||||
matchingNode->setLastHeardMicrostamp(usecTimestampNow());
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -810,7 +815,7 @@ void NodeList::activateSocketFromNodeCommunication(const QByteArray& packet, con
|
|||
|
||||
SharedNodePointer NodeList::soloNodeOfType(char nodeType) {
|
||||
|
||||
if (memchr(SOLO_NODE_TYPES, nodeType, sizeof(SOLO_NODE_TYPES)) != NULL) {
|
||||
if (memchr(SOLO_NODE_TYPES, nodeType, sizeof(SOLO_NODE_TYPES))) {
|
||||
foreach (const SharedNodePointer& node, getNodeHash()) {
|
||||
if (node->getType() == nodeType) {
|
||||
return node;
|
||||
|
|
|
@ -73,7 +73,7 @@ unsigned char* childOctalCode(const unsigned char* parentOctalCode, char childNu
|
|||
|
||||
// find the length (in number of three bit code sequences)
|
||||
// in the parent
|
||||
int parentCodeSections = parentOctalCode != NULL
|
||||
int parentCodeSections = parentOctalCode
|
||||
? numberOfThreeBitSectionsInCode(parentOctalCode)
|
||||
: 0;
|
||||
|
||||
|
@ -87,7 +87,7 @@ unsigned char* childOctalCode(const unsigned char* parentOctalCode, char childNu
|
|||
unsigned char* newCode = new unsigned char[childCodeBytes];
|
||||
|
||||
// copy the parent code to the child
|
||||
if (parentOctalCode != NULL) {
|
||||
if (parentOctalCode) {
|
||||
memcpy(newCode, parentOctalCode, parentCodeBytes);
|
||||
}
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue