mirror of
https://github.com/overte-org/overte.git
synced 2025-04-26 07:16:25 +02:00
Merge branch 'master' of https://github.com/worklist/hifi into compressed_packets
This commit is contained in:
commit
a590f384a6
24 changed files with 529 additions and 64 deletions
6
.gitignore
vendored
6
.gitignore
vendored
|
@ -35,5 +35,9 @@ interface/external/Leap/lib/
|
||||||
interface/external/Leap/samples/
|
interface/external/Leap/samples/
|
||||||
interface/external/Leap/util/
|
interface/external/Leap/util/
|
||||||
|
|
||||||
|
# Ignore Sixense
|
||||||
|
interface/external/Sixense/include/
|
||||||
|
interface/external/Sixense/lib/
|
||||||
|
|
||||||
|
# Ignore interfaceCache for Linux users
|
||||||
|
interface/interfaceCache/
|
||||||
|
|
44
cmake/modules/FindSixense.cmake
Normal file
44
cmake/modules/FindSixense.cmake
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
# Try to find the Sixense controller library
|
||||||
|
#
|
||||||
|
# You must provide a SIXENSE_ROOT_DIR which contains lib and include directories
|
||||||
|
#
|
||||||
|
# Once done this will define
|
||||||
|
#
|
||||||
|
# SIXENSE_FOUND - system found Sixense
|
||||||
|
# SIXENSE_INCLUDE_DIRS - the Sixense include directory
|
||||||
|
# SIXENSE_LIBRARIES - Link this to use Sixense
|
||||||
|
#
|
||||||
|
# Created on 11/15/2013 by Andrzej Kapolka
|
||||||
|
# Copyright (c) 2013 High Fidelity
|
||||||
|
#
|
||||||
|
|
||||||
|
if (SIXENSE_LIBRARIES AND SIXENSE_INCLUDE_DIRS)
|
||||||
|
# in cache already
|
||||||
|
set(SIXENSE_FOUND TRUE)
|
||||||
|
else (SIXENSE_LIBRARIES AND SIXENSE_INCLUDE_DIRS)
|
||||||
|
find_path(SIXENSE_INCLUDE_DIRS sixense.h ${SIXENSE_ROOT_DIR}/include)
|
||||||
|
|
||||||
|
if (APPLE)
|
||||||
|
find_library(SIXENSE_LIBRARIES libsixense_x64.dylib ${SIXENSE_ROOT_DIR}/lib/osx_x64/release_dll)
|
||||||
|
elseif (UNIX)
|
||||||
|
find_library(SIXENSE_LIBRARIES libsixense_x64.so ${SIXENSE_ROOT_DIR}/lib/linux_x64/release)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
if (SIXENSE_INCLUDE_DIRS AND SIXENSE_LIBRARIES)
|
||||||
|
set(SIXENSE_FOUND TRUE)
|
||||||
|
endif (SIXENSE_INCLUDE_DIRS AND SIXENSE_LIBRARIES)
|
||||||
|
|
||||||
|
if (SIXENSE_FOUND)
|
||||||
|
if (NOT SIXENSE_FIND_QUIETLY)
|
||||||
|
message(STATUS "Found Sixense: ${SIXENSE_LIBRARIES}")
|
||||||
|
endif (NOT SIXENSE_FIND_QUIETLY)
|
||||||
|
else (SIXENSE_FOUND)
|
||||||
|
if (SIXENSE_FIND_REQUIRED)
|
||||||
|
message(FATAL_ERROR "Could not find Sixense")
|
||||||
|
endif (SIXENSE_FIND_REQUIRED)
|
||||||
|
endif (SIXENSE_FOUND)
|
||||||
|
|
||||||
|
# show the SIXENSE_INCLUDE_DIRS and SIXENSE_LIBRARIES variables only in the advanced view
|
||||||
|
mark_as_advanced(SIXENSE_INCLUDE_DIRS SIXENSE_LIBRARIES)
|
||||||
|
|
||||||
|
endif (SIXENSE_LIBRARIES AND SIXENSE_INCLUDE_DIRS)
|
|
@ -15,6 +15,7 @@ set(LEAP_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external/Leap)
|
||||||
set(MOTIONDRIVER_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external/MotionDriver)
|
set(MOTIONDRIVER_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external/MotionDriver)
|
||||||
set(PORTAUDIO_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external/PortAudio)
|
set(PORTAUDIO_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external/PortAudio)
|
||||||
set(OPENCV_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external/OpenCV)
|
set(OPENCV_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external/OpenCV)
|
||||||
|
set(SIXENSE_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external/Sixense)
|
||||||
set(UVCCAMERACONTROL_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external/UVCCameraControl)
|
set(UVCCAMERACONTROL_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external/UVCCameraControl)
|
||||||
|
|
||||||
if (APPLE)
|
if (APPLE)
|
||||||
|
@ -95,6 +96,7 @@ find_package(Leap)
|
||||||
find_package(MotionDriver)
|
find_package(MotionDriver)
|
||||||
find_package(OpenCV)
|
find_package(OpenCV)
|
||||||
find_package(OpenNI)
|
find_package(OpenNI)
|
||||||
|
find_package(Sixense)
|
||||||
find_package(UVCCameraControl)
|
find_package(UVCCameraControl)
|
||||||
find_package(ZLIB)
|
find_package(ZLIB)
|
||||||
|
|
||||||
|
@ -106,6 +108,14 @@ if (OPENNI_FOUND AND NOT DISABLE_OPENNI)
|
||||||
target_link_libraries(${TARGET_NAME} ${OPENNI_LIBRARIES})
|
target_link_libraries(${TARGET_NAME} ${OPENNI_LIBRARIES})
|
||||||
endif (OPENNI_FOUND AND NOT DISABLE_OPENNI)
|
endif (OPENNI_FOUND AND NOT DISABLE_OPENNI)
|
||||||
|
|
||||||
|
# likewise with Sixense library for Razer Hydra
|
||||||
|
if (SIXENSE_FOUND AND NOT DISABLE_SIXENSE)
|
||||||
|
add_definitions(-DHAVE_SIXENSE)
|
||||||
|
include_directories(SYSTEM ${SIXENSE_INCLUDE_DIRS})
|
||||||
|
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -isystem ${SIXENSE_INCLUDE_DIRS}")
|
||||||
|
target_link_libraries(${TARGET_NAME} ${SIXENSE_LIBRARIES})
|
||||||
|
endif (SIXENSE_FOUND AND NOT DISABLE_SIXENSE)
|
||||||
|
|
||||||
qt5_use_modules(${TARGET_NAME} Core Gui Multimedia Network OpenGL Svg WebKit WebKitWidgets)
|
qt5_use_modules(${TARGET_NAME} Core Gui Multimedia Network OpenGL Svg WebKit WebKitWidgets)
|
||||||
|
|
||||||
# include headers for interface and InterfaceConfig.
|
# include headers for interface and InterfaceConfig.
|
||||||
|
|
11
interface/external/Sixense/readme.txt
vendored
Normal file
11
interface/external/Sixense/readme.txt
vendored
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
|
||||||
|
Instructions for adding the Sixense driver to Interface
|
||||||
|
Andrzej Kapolka, November 18, 2013
|
||||||
|
|
||||||
|
NOTE: Without doing step 2, you will crash at program start time.
|
||||||
|
|
||||||
|
1. Copy the Sixense sdk folders (lib, include) into the interface/external/Sixense folder. This readme.txt should be there as well.
|
||||||
|
|
||||||
|
2. IMPORTANT: Copy the file interface/external/Sixense/lib/osx_x64/release_dll/libsixense_x64.dylib to /usr/lib
|
||||||
|
|
||||||
|
3. Delete your build directory, run cmake and build, and you should be all set.
|
|
@ -2189,8 +2189,10 @@ void Application::updateHandAndTouch(float deltaTime) {
|
||||||
float TOUCH_YAW_SCALE = -0.25f;
|
float TOUCH_YAW_SCALE = -0.25f;
|
||||||
float TOUCH_PITCH_SCALE = -12.5f;
|
float TOUCH_PITCH_SCALE = -12.5f;
|
||||||
float FIXED_TOUCH_TIMESTEP = 0.016f;
|
float FIXED_TOUCH_TIMESTEP = 0.016f;
|
||||||
|
const float MAX_PITCH = 90.0f;
|
||||||
_yawFromTouch += ((_touchAvgX - _lastTouchAvgX) * TOUCH_YAW_SCALE * FIXED_TOUCH_TIMESTEP);
|
_yawFromTouch += ((_touchAvgX - _lastTouchAvgX) * TOUCH_YAW_SCALE * FIXED_TOUCH_TIMESTEP);
|
||||||
_pitchFromTouch += ((_touchAvgY - _lastTouchAvgY) * TOUCH_PITCH_SCALE * FIXED_TOUCH_TIMESTEP);
|
_pitchFromTouch = glm::clamp(_pitchFromTouch + (_touchAvgY - _lastTouchAvgY) * TOUCH_PITCH_SCALE *
|
||||||
|
FIXED_TOUCH_TIMESTEP, -MAX_PITCH, MAX_PITCH);
|
||||||
_lastTouchAvgX = _touchAvgX;
|
_lastTouchAvgX = _touchAvgX;
|
||||||
_lastTouchAvgY = _touchAvgY;
|
_lastTouchAvgY = _touchAvgY;
|
||||||
}
|
}
|
||||||
|
@ -2202,7 +2204,14 @@ void Application::updateLeap(float deltaTime) {
|
||||||
|
|
||||||
LeapManager::enableFakeFingers(Menu::getInstance()->isOptionChecked(MenuOption::SimulateLeapHand));
|
LeapManager::enableFakeFingers(Menu::getInstance()->isOptionChecked(MenuOption::SimulateLeapHand));
|
||||||
_myAvatar.getHand().setRaveGloveActive(Menu::getInstance()->isOptionChecked(MenuOption::TestRaveGlove));
|
_myAvatar.getHand().setRaveGloveActive(Menu::getInstance()->isOptionChecked(MenuOption::TestRaveGlove));
|
||||||
LeapManager::nextFrame(_myAvatar);
|
LeapManager::nextFrame();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application::updateSixense() {
|
||||||
|
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
||||||
|
PerformanceWarning warn(showWarnings, "Application::updateSixense()");
|
||||||
|
|
||||||
|
_sixenseManager.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::updateSerialDevices(float deltaTime) {
|
void Application::updateSerialDevices(float deltaTime) {
|
||||||
|
@ -2412,6 +2421,7 @@ void Application::update(float deltaTime) {
|
||||||
updateMouseVoxels(deltaTime, mouseRayOrigin, mouseRayDirection, distance, face); // UI/UX related to voxels
|
updateMouseVoxels(deltaTime, mouseRayOrigin, mouseRayDirection, distance, face); // UI/UX related to voxels
|
||||||
updateHandAndTouch(deltaTime); // Update state for touch sensors
|
updateHandAndTouch(deltaTime); // Update state for touch sensors
|
||||||
updateLeap(deltaTime); // Leap finger-sensing device
|
updateLeap(deltaTime); // Leap finger-sensing device
|
||||||
|
updateSixense(); // Razer Hydra controllers
|
||||||
updateSerialDevices(deltaTime); // Read serial port interface devices
|
updateSerialDevices(deltaTime); // Read serial port interface devices
|
||||||
updateAvatar(deltaTime); // Sample hardware, update view frustum if needed, and send avatar data to mixer/nodes
|
updateAvatar(deltaTime); // Sample hardware, update view frustum if needed, and send avatar data to mixer/nodes
|
||||||
updateThreads(deltaTime); // If running non-threaded, then give the threads some time to process...
|
updateThreads(deltaTime); // If running non-threaded, then give the threads some time to process...
|
||||||
|
@ -4092,6 +4102,7 @@ void Application::resetSensors() {
|
||||||
}
|
}
|
||||||
_webcam.reset();
|
_webcam.reset();
|
||||||
_faceshift.reset();
|
_faceshift.reset();
|
||||||
|
LeapManager::reset();
|
||||||
QCursor::setPos(_headMouseX, _headMouseY);
|
QCursor::setPos(_headMouseX, _headMouseY);
|
||||||
_myAvatar.reset();
|
_myAvatar.reset();
|
||||||
_myTransmitter.resetLevels();
|
_myTransmitter.resetLevels();
|
||||||
|
@ -4188,9 +4199,11 @@ void Application::nodeKilled(Node* node) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// also clean up scene stats for that server
|
// also clean up scene stats for that server
|
||||||
|
_voxelSceneStatsLock.lockForWrite();
|
||||||
if (_voxelServerSceneStats.find(nodeUUID) != _voxelServerSceneStats.end()) {
|
if (_voxelServerSceneStats.find(nodeUUID) != _voxelServerSceneStats.end()) {
|
||||||
_voxelServerSceneStats.erase(nodeUUID);
|
_voxelServerSceneStats.erase(nodeUUID);
|
||||||
}
|
}
|
||||||
|
_voxelSceneStatsLock.unlock();
|
||||||
} else if (node->getLinkedData() == _lookatTargetAvatar) {
|
} else if (node->getLinkedData() == _lookatTargetAvatar) {
|
||||||
_lookatTargetAvatar = NULL;
|
_lookatTargetAvatar = NULL;
|
||||||
}
|
}
|
||||||
|
@ -4211,27 +4224,13 @@ int Application::parseVoxelStats(unsigned char* messageData, ssize_t messageLeng
|
||||||
QUuid nodeUUID = voxelServer->getUUID();
|
QUuid nodeUUID = voxelServer->getUUID();
|
||||||
|
|
||||||
// now that we know the node ID, let's add these stats to the stats for that node...
|
// now that we know the node ID, let's add these stats to the stats for that node...
|
||||||
|
_voxelSceneStatsLock.lockForWrite();
|
||||||
if (_voxelServerSceneStats.find(nodeUUID) != _voxelServerSceneStats.end()) {
|
if (_voxelServerSceneStats.find(nodeUUID) != _voxelServerSceneStats.end()) {
|
||||||
VoxelSceneStats& oldStats = _voxelServerSceneStats[nodeUUID];
|
_voxelServerSceneStats[nodeUUID].unpackFromMessage(messageData, messageLength);
|
||||||
|
|
||||||
// this if construct is a little strange because we aren't quite using it yet. But
|
|
||||||
// we want to keep this logic in here for now because we plan to use it soon to determine
|
|
||||||
// additional network optimization states and better rate control
|
|
||||||
if (!oldStats.isMoving() && temp.isMoving()) {
|
|
||||||
// we think we are starting to move
|
|
||||||
_voxelServerSceneStats[nodeUUID].unpackFromMessage(messageData, messageLength);
|
|
||||||
} else if (oldStats.isMoving() && !temp.isMoving()) {
|
|
||||||
// we think we are done moving
|
|
||||||
_voxelServerSceneStats[nodeUUID].unpackFromMessage(messageData, messageLength);
|
|
||||||
} else if (!oldStats.isMoving() && !temp.isMoving()) {
|
|
||||||
// we think we are still not moving
|
|
||||||
} else {
|
|
||||||
// we think we are still moving
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
_voxelServerSceneStats[nodeUUID] = temp;
|
_voxelServerSceneStats[nodeUUID] = temp;
|
||||||
}
|
}
|
||||||
|
_voxelSceneStatsLock.unlock();
|
||||||
|
|
||||||
VoxelPositionSize rootDetails;
|
VoxelPositionSize rootDetails;
|
||||||
voxelDetailsForCode(temp.getJurisdictionRoot(), rootDetails);
|
voxelDetailsForCode(temp.getJurisdictionRoot(), rootDetails);
|
||||||
|
|
|
@ -50,6 +50,7 @@
|
||||||
#include "avatar/HandControl.h"
|
#include "avatar/HandControl.h"
|
||||||
#include "devices/Faceshift.h"
|
#include "devices/Faceshift.h"
|
||||||
#include "devices/SerialInterface.h"
|
#include "devices/SerialInterface.h"
|
||||||
|
#include "devices/SixenseManager.h"
|
||||||
#include "devices/Webcam.h"
|
#include "devices/Webcam.h"
|
||||||
#include "renderer/AmbientOcclusionEffect.h"
|
#include "renderer/AmbientOcclusionEffect.h"
|
||||||
#include "renderer/GeometryCache.h"
|
#include "renderer/GeometryCache.h"
|
||||||
|
@ -136,6 +137,8 @@ public:
|
||||||
Swatch* getSwatch() { return &_swatch; }
|
Swatch* getSwatch() { return &_swatch; }
|
||||||
QMainWindow* getWindow() { return _window; }
|
QMainWindow* getWindow() { return _window; }
|
||||||
NodeToVoxelSceneStats* getVoxelSceneStats() { return &_voxelServerSceneStats; }
|
NodeToVoxelSceneStats* getVoxelSceneStats() { return &_voxelServerSceneStats; }
|
||||||
|
void lockVoxelSceneStats() { _voxelSceneStatsLock.lockForRead(); }
|
||||||
|
void unlockVoxelSceneStats() { _voxelSceneStatsLock.unlock(); }
|
||||||
|
|
||||||
QNetworkAccessManager* getNetworkAccessManager() { return _networkAccessManager; }
|
QNetworkAccessManager* getNetworkAccessManager() { return _networkAccessManager; }
|
||||||
GeometryCache* getGeometryCache() { return &_geometryCache; }
|
GeometryCache* getGeometryCache() { return &_geometryCache; }
|
||||||
|
@ -242,6 +245,7 @@ private:
|
||||||
glm::vec3& eyePosition);
|
glm::vec3& eyePosition);
|
||||||
void updateHandAndTouch(float deltaTime);
|
void updateHandAndTouch(float deltaTime);
|
||||||
void updateLeap(float deltaTime);
|
void updateLeap(float deltaTime);
|
||||||
|
void updateSixense();
|
||||||
void updateSerialDevices(float deltaTime);
|
void updateSerialDevices(float deltaTime);
|
||||||
void updateThreads(float deltaTime);
|
void updateThreads(float deltaTime);
|
||||||
void updateMyAvatarSimulation(float deltaTime);
|
void updateMyAvatarSimulation(float deltaTime);
|
||||||
|
@ -337,6 +341,8 @@ private:
|
||||||
|
|
||||||
Faceshift _faceshift;
|
Faceshift _faceshift;
|
||||||
|
|
||||||
|
SixenseManager _sixenseManager;
|
||||||
|
|
||||||
Camera _myCamera; // My view onto the world
|
Camera _myCamera; // My view onto the world
|
||||||
Camera _viewFrustumOffsetCamera; // The camera we use to sometimes show the view frustum from an offset mode
|
Camera _viewFrustumOffsetCamera; // The camera we use to sometimes show the view frustum from an offset mode
|
||||||
Camera _mirrorCamera; // Cammera for mirror view
|
Camera _mirrorCamera; // Cammera for mirror view
|
||||||
|
@ -454,6 +460,7 @@ private:
|
||||||
|
|
||||||
NodeToJurisdictionMap _voxelServerJurisdictions;
|
NodeToJurisdictionMap _voxelServerJurisdictions;
|
||||||
NodeToVoxelSceneStats _voxelServerSceneStats;
|
NodeToVoxelSceneStats _voxelServerSceneStats;
|
||||||
|
QReadWriteLock _voxelSceneStatsLock;
|
||||||
|
|
||||||
std::vector<VoxelFade> _voxelFades;
|
std::vector<VoxelFade> _voxelFades;
|
||||||
};
|
};
|
||||||
|
|
|
@ -72,7 +72,8 @@ Menu::Menu() :
|
||||||
MenuOption::AboutApp,
|
MenuOption::AboutApp,
|
||||||
0,
|
0,
|
||||||
this,
|
this,
|
||||||
SLOT(aboutApp()));
|
SLOT(aboutApp()),
|
||||||
|
QAction::AboutRole);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
(addActionToQMenuAndActionHash(fileMenu,
|
(addActionToQMenuAndActionHash(fileMenu,
|
||||||
|
@ -120,7 +121,9 @@ Menu::Menu() :
|
||||||
MenuOption::Quit,
|
MenuOption::Quit,
|
||||||
Qt::CTRL | Qt::Key_Q,
|
Qt::CTRL | Qt::Key_Q,
|
||||||
appInstance,
|
appInstance,
|
||||||
SLOT(quit()));
|
SLOT(quit()),
|
||||||
|
QAction::QuitRole);
|
||||||
|
|
||||||
|
|
||||||
QMenu* editMenu = addMenu("Edit");
|
QMenu* editMenu = addMenu("Edit");
|
||||||
|
|
||||||
|
@ -128,7 +131,8 @@ Menu::Menu() :
|
||||||
MenuOption::Preferences,
|
MenuOption::Preferences,
|
||||||
Qt::CTRL | Qt::Key_Comma,
|
Qt::CTRL | Qt::Key_Comma,
|
||||||
this,
|
this,
|
||||||
SLOT(editPreferences()));
|
SLOT(editPreferences()),
|
||||||
|
QAction::PreferencesRole);
|
||||||
|
|
||||||
addDisabledActionAndSeparator(editMenu, "Voxels");
|
addDisabledActionAndSeparator(editMenu, "Voxels");
|
||||||
|
|
||||||
|
@ -243,6 +247,7 @@ Menu::Menu() :
|
||||||
MenuOption::TurnWithHead,
|
MenuOption::TurnWithHead,
|
||||||
0,
|
0,
|
||||||
true);
|
true);
|
||||||
|
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::MoveWithLean, 0, false);
|
||||||
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::HeadMouse, 0, false);
|
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::HeadMouse, 0, false);
|
||||||
|
|
||||||
|
|
||||||
|
@ -361,6 +366,7 @@ Menu::Menu() :
|
||||||
|
|
||||||
addCheckableActionToQMenuAndActionHash(raveGloveOptionsMenu, MenuOption::SimulateLeapHand);
|
addCheckableActionToQMenuAndActionHash(raveGloveOptionsMenu, MenuOption::SimulateLeapHand);
|
||||||
addCheckableActionToQMenuAndActionHash(raveGloveOptionsMenu, MenuOption::DisplayLeapHands, 0, true);
|
addCheckableActionToQMenuAndActionHash(raveGloveOptionsMenu, MenuOption::DisplayLeapHands, 0, true);
|
||||||
|
addCheckableActionToQMenuAndActionHash(raveGloveOptionsMenu, MenuOption::LeapDrive, 0, false);
|
||||||
addCheckableActionToQMenuAndActionHash(raveGloveOptionsMenu, MenuOption::TestRaveGlove);
|
addCheckableActionToQMenuAndActionHash(raveGloveOptionsMenu, MenuOption::TestRaveGlove);
|
||||||
|
|
||||||
QMenu* trackingOptionsMenu = developerMenu->addMenu("Tracking Options");
|
QMenu* trackingOptionsMenu = developerMenu->addMenu("Tracking Options");
|
||||||
|
@ -679,7 +685,8 @@ QAction* Menu::addActionToQMenuAndActionHash(QMenu* destinationMenu,
|
||||||
const QString actionName,
|
const QString actionName,
|
||||||
const QKeySequence& shortcut,
|
const QKeySequence& shortcut,
|
||||||
const QObject* receiver,
|
const QObject* receiver,
|
||||||
const char* member) {
|
const char* member,
|
||||||
|
QAction::MenuRole role) {
|
||||||
QAction* action;
|
QAction* action;
|
||||||
|
|
||||||
if (receiver && member) {
|
if (receiver && member) {
|
||||||
|
@ -688,6 +695,7 @@ QAction* Menu::addActionToQMenuAndActionHash(QMenu* destinationMenu,
|
||||||
action = destinationMenu->addAction(actionName);
|
action = destinationMenu->addAction(actionName);
|
||||||
action->setShortcut(shortcut);
|
action->setShortcut(shortcut);
|
||||||
}
|
}
|
||||||
|
action->setMenuRole(role);
|
||||||
|
|
||||||
_actionHash.insert(actionName, action);
|
_actionHash.insert(actionName, action);
|
||||||
|
|
||||||
|
|
|
@ -113,7 +113,9 @@ private:
|
||||||
const QString actionName,
|
const QString actionName,
|
||||||
const QKeySequence& shortcut = 0,
|
const QKeySequence& shortcut = 0,
|
||||||
const QObject* receiver = NULL,
|
const QObject* receiver = NULL,
|
||||||
const char* member = NULL);
|
const char* member = NULL,
|
||||||
|
QAction::MenuRole role = QAction::NoRole);
|
||||||
|
|
||||||
QAction* addCheckableActionToQMenuAndActionHash(QMenu* destinationMenu,
|
QAction* addCheckableActionToQMenuAndActionHash(QMenu* destinationMenu,
|
||||||
const QString actionName,
|
const QString actionName,
|
||||||
const QKeySequence& shortcut = 0,
|
const QKeySequence& shortcut = 0,
|
||||||
|
@ -198,6 +200,7 @@ namespace MenuOption {
|
||||||
const QString GoHome = "Go Home";
|
const QString GoHome = "Go Home";
|
||||||
const QString Gravity = "Use Gravity";
|
const QString Gravity = "Use Gravity";
|
||||||
const QString ParticleCloud = "Particle Cloud";
|
const QString ParticleCloud = "Particle Cloud";
|
||||||
|
const QString LeapDrive = "Leap Drive";
|
||||||
const QString LodTools = "LOD Tools";
|
const QString LodTools = "LOD Tools";
|
||||||
const QString Log = "Log";
|
const QString Log = "Log";
|
||||||
const QString Login = "Login";
|
const QString Login = "Login";
|
||||||
|
@ -205,6 +208,7 @@ namespace MenuOption {
|
||||||
const QString LookAtVectors = "Look-at Vectors";
|
const QString LookAtVectors = "Look-at Vectors";
|
||||||
const QString LowRes = "Lower Resolution While Moving";
|
const QString LowRes = "Lower Resolution While Moving";
|
||||||
const QString Mirror = "Mirror";
|
const QString Mirror = "Mirror";
|
||||||
|
const QString MoveWithLean = "Move with Lean";
|
||||||
const QString NewVoxelCullingMode = "New Voxel Culling Mode";
|
const QString NewVoxelCullingMode = "New Voxel Culling Mode";
|
||||||
const QString NudgeVoxels = "Nudge";
|
const QString NudgeVoxels = "Nudge";
|
||||||
const QString OcclusionCulling = "Occlusion Culling";
|
const QString OcclusionCulling = "Occlusion Culling";
|
||||||
|
|
|
@ -101,6 +101,8 @@ enum DriveKeys {
|
||||||
DOWN,
|
DOWN,
|
||||||
ROT_LEFT,
|
ROT_LEFT,
|
||||||
ROT_RIGHT,
|
ROT_RIGHT,
|
||||||
|
ROT_UP,
|
||||||
|
ROT_DOWN,
|
||||||
MAX_DRIVE_KEYS
|
MAX_DRIVE_KEYS
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -264,7 +264,7 @@ void Hand::renderLeapHands() {
|
||||||
for (size_t i = 0; i < getNumPalms(); ++i) {
|
for (size_t i = 0; i < getNumPalms(); ++i) {
|
||||||
PalmData& palm = getPalms()[i];
|
PalmData& palm = getPalms()[i];
|
||||||
if (palm.isActive()) {
|
if (palm.isActive()) {
|
||||||
const float palmThickness = 0.002f;
|
const float palmThickness = 0.02f;
|
||||||
glColor4f(handColor.r, handColor.g, handColor.b, 0.25);
|
glColor4f(handColor.r, handColor.g, handColor.b, 0.25);
|
||||||
glm::vec3 tip = palm.getPosition();
|
glm::vec3 tip = palm.getPosition();
|
||||||
glm::vec3 root = palm.getPosition() + palm.getNormal() * palmThickness;
|
glm::vec3 root = palm.getPosition() + palm.getNormal() * palmThickness;
|
||||||
|
|
|
@ -27,6 +27,7 @@ using namespace std;
|
||||||
|
|
||||||
const glm::vec3 DEFAULT_UP_DIRECTION(0.0f, 1.0f, 0.0f);
|
const glm::vec3 DEFAULT_UP_DIRECTION(0.0f, 1.0f, 0.0f);
|
||||||
const float YAW_MAG = 500.0;
|
const float YAW_MAG = 500.0;
|
||||||
|
const float PITCH_MAG = 100.0f;
|
||||||
const float COLLISION_RADIUS_SCALAR = 1.2; // pertains to avatar-to-avatar collisions
|
const float COLLISION_RADIUS_SCALAR = 1.2; // pertains to avatar-to-avatar collisions
|
||||||
const float COLLISION_BALL_FORCE = 200.0; // pertains to avatar-to-avatar collisions
|
const float COLLISION_BALL_FORCE = 200.0; // pertains to avatar-to-avatar collisions
|
||||||
const float COLLISION_BODY_FORCE = 30.0; // pertains to avatar-to-avatar collisions
|
const float COLLISION_BODY_FORCE = 30.0; // pertains to avatar-to-avatar collisions
|
||||||
|
@ -42,6 +43,7 @@ MyAvatar::MyAvatar(Node* owningNode) :
|
||||||
_mousePressed(false),
|
_mousePressed(false),
|
||||||
_bodyPitchDelta(0.0f),
|
_bodyPitchDelta(0.0f),
|
||||||
_bodyRollDelta(0.0f),
|
_bodyRollDelta(0.0f),
|
||||||
|
_mousePitchDelta(0.0f),
|
||||||
_shouldJump(false),
|
_shouldJump(false),
|
||||||
_gravity(0.0f, -1.0f, 0.0f),
|
_gravity(0.0f, -1.0f, 0.0f),
|
||||||
_distanceToNearestAvatar(std::numeric_limits<float>::max()),
|
_distanceToNearestAvatar(std::numeric_limits<float>::max()),
|
||||||
|
@ -57,7 +59,7 @@ MyAvatar::MyAvatar(Node* owningNode) :
|
||||||
_moveTargetStepCounter(0)
|
_moveTargetStepCounter(0)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < MAX_DRIVE_KEYS; i++) {
|
for (int i = 0; i < MAX_DRIVE_KEYS; i++) {
|
||||||
_driveKeys[i] = false;
|
_driveKeys[i] = 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
_collisionRadius = _height * COLLISION_RADIUS_SCALE;
|
_collisionRadius = _height * COLLISION_RADIUS_SCALE;
|
||||||
|
@ -368,6 +370,8 @@ void MyAvatar::simulate(float deltaTime, Transmitter* transmitter) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const float MAX_PITCH = 90.0f;
|
||||||
|
|
||||||
// Update avatar head rotation with sensor data
|
// Update avatar head rotation with sensor data
|
||||||
void MyAvatar::updateFromGyrosAndOrWebcam(float pitchFromTouch, bool turnWithHead) {
|
void MyAvatar::updateFromGyrosAndOrWebcam(float pitchFromTouch, bool turnWithHead) {
|
||||||
Faceshift* faceshift = Application::getInstance()->getFaceshift();
|
Faceshift* faceshift = Application::getInstance()->getFaceshift();
|
||||||
|
@ -375,6 +379,7 @@ void MyAvatar::updateFromGyrosAndOrWebcam(float pitchFromTouch, bool turnWithHea
|
||||||
Webcam* webcam = Application::getInstance()->getWebcam();
|
Webcam* webcam = Application::getInstance()->getWebcam();
|
||||||
glm::vec3 estimatedPosition, estimatedRotation;
|
glm::vec3 estimatedPosition, estimatedRotation;
|
||||||
|
|
||||||
|
float combinedPitch = glm::clamp(pitchFromTouch + _mousePitchDelta, -MAX_PITCH, MAX_PITCH);
|
||||||
if (faceshift->isActive()) {
|
if (faceshift->isActive()) {
|
||||||
estimatedPosition = faceshift->getHeadTranslation();
|
estimatedPosition = faceshift->getHeadTranslation();
|
||||||
estimatedRotation = safeEulerAngles(faceshift->getHeadRotation());
|
estimatedRotation = safeEulerAngles(faceshift->getHeadRotation());
|
||||||
|
@ -395,8 +400,8 @@ void MyAvatar::updateFromGyrosAndOrWebcam(float pitchFromTouch, bool turnWithHea
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (!_leadingAvatar) {
|
if (!_leadingAvatar) {
|
||||||
_head.setMousePitch(pitchFromTouch);
|
_head.setMousePitch(combinedPitch);
|
||||||
_head.setPitch(pitchFromTouch);
|
_head.setPitch(combinedPitch);
|
||||||
}
|
}
|
||||||
_head.getVideoFace().clearFrame();
|
_head.getVideoFace().clearFrame();
|
||||||
|
|
||||||
|
@ -408,7 +413,7 @@ void MyAvatar::updateFromGyrosAndOrWebcam(float pitchFromTouch, bool turnWithHea
|
||||||
_head.setLeanForward(glm::mix(_head.getLeanForward(), 0.0f, RESTORE_RATE));
|
_head.setLeanForward(glm::mix(_head.getLeanForward(), 0.0f, RESTORE_RATE));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_head.setMousePitch(pitchFromTouch);
|
_head.setMousePitch(combinedPitch);
|
||||||
|
|
||||||
if (webcam->isActive()) {
|
if (webcam->isActive()) {
|
||||||
estimatedPosition = webcam->getEstimatedPosition();
|
estimatedPosition = webcam->getEstimatedPosition();
|
||||||
|
@ -444,12 +449,35 @@ void MyAvatar::updateFromGyrosAndOrWebcam(float pitchFromTouch, bool turnWithHea
|
||||||
_head.setRoll(estimatedRotation.z * AVATAR_HEAD_ROLL_MAGNIFY);
|
_head.setRoll(estimatedRotation.z * AVATAR_HEAD_ROLL_MAGNIFY);
|
||||||
|
|
||||||
// Update torso lean distance based on accelerometer data
|
// Update torso lean distance based on accelerometer data
|
||||||
const float TORSO_LENGTH = _scale * 0.5f;
|
const float TORSO_LENGTH = 0.5f;
|
||||||
|
glm::vec3 relativePosition = estimatedPosition - glm::vec3(0.0f, -TORSO_LENGTH, 0.0f);
|
||||||
const float MAX_LEAN = 45.0f;
|
const float MAX_LEAN = 45.0f;
|
||||||
_head.setLeanSideways(glm::clamp(glm::degrees(atanf(estimatedPosition.x * _leanScale / TORSO_LENGTH)),
|
_head.setLeanSideways(glm::clamp(glm::degrees(atanf(relativePosition.x * _leanScale / TORSO_LENGTH)),
|
||||||
-MAX_LEAN, MAX_LEAN));
|
-MAX_LEAN, MAX_LEAN));
|
||||||
_head.setLeanForward(glm::clamp(glm::degrees(atanf(estimatedPosition.z * _leanScale / TORSO_LENGTH)),
|
_head.setLeanForward(glm::clamp(glm::degrees(atanf(relativePosition.z * _leanScale / TORSO_LENGTH)),
|
||||||
-MAX_LEAN, MAX_LEAN));
|
-MAX_LEAN, MAX_LEAN));
|
||||||
|
|
||||||
|
// if Faceshift drive is enabled, set the avatar drive based on the head position
|
||||||
|
if (!Menu::getInstance()->isOptionChecked(MenuOption::MoveWithLean)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const float ANGULAR_DRIVE_SCALE = 0.1f;
|
||||||
|
const float ANGULAR_DEAD_ZONE = 0.3f;
|
||||||
|
setDriveKeys(FWD, glm::clamp(-_head.getLeanForward() * ANGULAR_DRIVE_SCALE - ANGULAR_DEAD_ZONE, 0.0f, 1.0f));
|
||||||
|
setDriveKeys(BACK, glm::clamp(_head.getLeanForward() * ANGULAR_DRIVE_SCALE - ANGULAR_DEAD_ZONE, 0.0f, 1.0f));
|
||||||
|
setDriveKeys(LEFT, glm::clamp(_head.getLeanSideways() * ANGULAR_DRIVE_SCALE - ANGULAR_DEAD_ZONE, 0.0f, 1.0f));
|
||||||
|
setDriveKeys(RIGHT, glm::clamp(-_head.getLeanSideways() * ANGULAR_DRIVE_SCALE - ANGULAR_DEAD_ZONE, 0.0f, 1.0f));
|
||||||
|
|
||||||
|
// only consider going up if we're not going in any of the four horizontal directions
|
||||||
|
if (_driveKeys[FWD] == 0.0f && _driveKeys[BACK] == 0.0f && _driveKeys[LEFT] == 0.0f && _driveKeys[RIGHT] == 0.0f) {
|
||||||
|
const float LINEAR_DRIVE_SCALE = 5.0f;
|
||||||
|
const float LINEAR_DEAD_ZONE = 0.95f;
|
||||||
|
float torsoDelta = glm::length(relativePosition) - TORSO_LENGTH;
|
||||||
|
setDriveKeys(UP, glm::clamp(torsoDelta * LINEAR_DRIVE_SCALE - LINEAR_DEAD_ZONE, 0.0f, 1.0f));
|
||||||
|
|
||||||
|
} else {
|
||||||
|
setDriveKeys(UP, 0.0f);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static TextRenderer* textRenderer() {
|
static TextRenderer* textRenderer() {
|
||||||
|
@ -707,14 +735,16 @@ void MyAvatar::updateThrust(float deltaTime, Transmitter * transmitter) {
|
||||||
const float THRUST_JUMP = 120.f;
|
const float THRUST_JUMP = 120.f;
|
||||||
|
|
||||||
// Add Thrusts from keyboard
|
// Add Thrusts from keyboard
|
||||||
if (_driveKeys[FWD]) {_thrust += _scale * THRUST_MAG_FWD * _thrustMultiplier * deltaTime * front;}
|
_thrust += _driveKeys[FWD] * _scale * THRUST_MAG_FWD * _thrustMultiplier * deltaTime * front;
|
||||||
if (_driveKeys[BACK]) {_thrust -= _scale * THRUST_MAG_BACK * _thrustMultiplier * deltaTime * front;}
|
_thrust -= _driveKeys[BACK] * _scale * THRUST_MAG_BACK * _thrustMultiplier * deltaTime * front;
|
||||||
if (_driveKeys[RIGHT]) {_thrust += _scale * THRUST_MAG_LATERAL * _thrustMultiplier * deltaTime * right;}
|
_thrust += _driveKeys[RIGHT] * _scale * THRUST_MAG_LATERAL * _thrustMultiplier * deltaTime * right;
|
||||||
if (_driveKeys[LEFT]) {_thrust -= _scale * THRUST_MAG_LATERAL * _thrustMultiplier * deltaTime * right;}
|
_thrust -= _driveKeys[LEFT] * _scale * THRUST_MAG_LATERAL * _thrustMultiplier * deltaTime * right;
|
||||||
if (_driveKeys[UP]) {_thrust += _scale * THRUST_MAG_UP * _thrustMultiplier * deltaTime * up;}
|
_thrust += _driveKeys[UP] * _scale * THRUST_MAG_UP * _thrustMultiplier * deltaTime * up;
|
||||||
if (_driveKeys[DOWN]) {_thrust -= _scale * THRUST_MAG_DOWN * _thrustMultiplier * deltaTime * up;}
|
_thrust -= _driveKeys[DOWN] * _scale * THRUST_MAG_DOWN * _thrustMultiplier * deltaTime * up;
|
||||||
if (_driveKeys[ROT_RIGHT]) {_bodyYawDelta -= YAW_MAG * deltaTime;}
|
_bodyYawDelta -= _driveKeys[ROT_RIGHT] * YAW_MAG * deltaTime;
|
||||||
if (_driveKeys[ROT_LEFT]) {_bodyYawDelta += YAW_MAG * deltaTime;}
|
_bodyYawDelta += _driveKeys[ROT_LEFT] * YAW_MAG * deltaTime;
|
||||||
|
_mousePitchDelta = min(_mousePitchDelta + _driveKeys[ROT_UP] * PITCH_MAG * deltaTime, MAX_PITCH);
|
||||||
|
_mousePitchDelta = max(_mousePitchDelta - _driveKeys[ROT_DOWN] * PITCH_MAG * deltaTime, -MAX_PITCH);
|
||||||
|
|
||||||
// If thrust keys are being held down, slowly increase thrust to allow reaching great speeds
|
// If thrust keys are being held down, slowly increase thrust to allow reaching great speeds
|
||||||
if (_driveKeys[FWD] || _driveKeys[BACK] || _driveKeys[RIGHT] || _driveKeys[LEFT] || _driveKeys[UP] || _driveKeys[DOWN]) {
|
if (_driveKeys[FWD] || _driveKeys[BACK] || _driveKeys[RIGHT] || _driveKeys[LEFT] || _driveKeys[UP] || _driveKeys[DOWN]) {
|
||||||
|
|
|
@ -54,7 +54,7 @@ public:
|
||||||
void loadData(QSettings* settings);
|
void loadData(QSettings* settings);
|
||||||
|
|
||||||
// Set what driving keys are being pressed to control thrust levels
|
// Set what driving keys are being pressed to control thrust levels
|
||||||
void setDriveKeys(int key, bool val) { _driveKeys[key] = val; };
|
void setDriveKeys(int key, float val) { _driveKeys[key] = val; };
|
||||||
bool getDriveKeys(int key) { return _driveKeys[key]; };
|
bool getDriveKeys(int key) { return _driveKeys[key]; };
|
||||||
void jump() { _shouldJump = true; };
|
void jump() { _shouldJump = true; };
|
||||||
|
|
||||||
|
@ -66,8 +66,9 @@ private:
|
||||||
bool _mousePressed;
|
bool _mousePressed;
|
||||||
float _bodyPitchDelta;
|
float _bodyPitchDelta;
|
||||||
float _bodyRollDelta;
|
float _bodyRollDelta;
|
||||||
|
float _mousePitchDelta;
|
||||||
bool _shouldJump;
|
bool _shouldJump;
|
||||||
int _driveKeys[MAX_DRIVE_KEYS];
|
float _driveKeys[MAX_DRIVE_KEYS];
|
||||||
glm::vec3 _gravity;
|
glm::vec3 _gravity;
|
||||||
float _distanceToNearestAvatar; // How close is the nearest avatar?
|
float _distanceToNearestAvatar; // How close is the nearest avatar?
|
||||||
Avatar* _interactingOther;
|
Avatar* _interactingOther;
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
|
|
||||||
#include <SharedUtil.h>
|
#include <SharedUtil.h>
|
||||||
|
|
||||||
|
#include "Application.h"
|
||||||
#include "Faceshift.h"
|
#include "Faceshift.h"
|
||||||
#include "Menu.h"
|
#include "Menu.h"
|
||||||
#include "Util.h"
|
#include "Util.h"
|
||||||
|
|
|
@ -6,12 +6,16 @@
|
||||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "LeapManager.h"
|
|
||||||
#include "avatar/Avatar.h"
|
|
||||||
#include <Leap.h>
|
|
||||||
#include <dlfcn.h> // needed for RTLD_LAZY
|
#include <dlfcn.h> // needed for RTLD_LAZY
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
|
#include <Leap.h>
|
||||||
|
|
||||||
|
#include "Application.h"
|
||||||
|
#include "LeapManager.h"
|
||||||
|
#include "Menu.h"
|
||||||
|
|
||||||
// Uncomment the next line to use Leap-smoothed stabilized (slower) data.
|
// Uncomment the next line to use Leap-smoothed stabilized (slower) data.
|
||||||
//#define USE_STABILIZED_DATA
|
//#define USE_STABILIZED_DATA
|
||||||
|
|
||||||
|
@ -19,6 +23,7 @@ bool LeapManager::_libraryExists = false;
|
||||||
bool LeapManager::_doFakeFingers = false;
|
bool LeapManager::_doFakeFingers = false;
|
||||||
Leap::Controller* LeapManager::_controller = NULL;
|
Leap::Controller* LeapManager::_controller = NULL;
|
||||||
HifiLeapListener* LeapManager::_listener = NULL;
|
HifiLeapListener* LeapManager::_listener = NULL;
|
||||||
|
glm::vec3 LeapManager::_baseDrivePosition(0.0f, 150.0f, 0.0f); // experimentally derived
|
||||||
|
|
||||||
class HifiLeapListener : public Leap::Listener {
|
class HifiLeapListener : public Leap::Listener {
|
||||||
public:
|
public:
|
||||||
|
@ -44,6 +49,25 @@ void LeapManager::initialize() {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PalmData* getRightmostPalm() {
|
||||||
|
PalmData* rightmostPalm = NULL;
|
||||||
|
Hand& hand = Application::getInstance()->getAvatar()->getHand();
|
||||||
|
for (int i = 0; i < hand.getNumPalms(); i++) {
|
||||||
|
PalmData* palm = &hand.getPalms()[i];
|
||||||
|
if (palm->isActive() && (rightmostPalm == NULL || palm->getRawPosition().x > rightmostPalm->getRawPosition().x)) {
|
||||||
|
rightmostPalm = palm;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rightmostPalm;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LeapManager::reset() {
|
||||||
|
PalmData* rightmostPalm = getRightmostPalm();
|
||||||
|
if (rightmostPalm != NULL) {
|
||||||
|
_baseDrivePosition = rightmostPalm->getRawPosition();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void LeapManager::terminate() {
|
void LeapManager::terminate() {
|
||||||
delete _listener;
|
delete _listener;
|
||||||
delete _controller;
|
delete _controller;
|
||||||
|
@ -51,9 +75,10 @@ void LeapManager::terminate() {
|
||||||
_controller = NULL;
|
_controller = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LeapManager::nextFrame(Avatar& avatar) {
|
void LeapManager::nextFrame() {
|
||||||
// Apply the frame data directly to the avatar.
|
// Apply the frame data directly to the avatar.
|
||||||
Hand& hand = avatar.getHand();
|
MyAvatar* avatar = Application::getInstance()->getAvatar();
|
||||||
|
Hand& hand = avatar->getHand();
|
||||||
|
|
||||||
// If we actually get valid Leap data, this will be set to true;
|
// If we actually get valid Leap data, this will be set to true;
|
||||||
bool gotRealData = false;
|
bool gotRealData = false;
|
||||||
|
@ -244,6 +269,55 @@ void LeapManager::nextFrame(Avatar& avatar) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hand.updateFingerTrails();
|
hand.updateFingerTrails();
|
||||||
|
|
||||||
|
// if Leap drive is enabled, drive avatar based on Leap input
|
||||||
|
if (!Menu::getInstance()->isOptionChecked(MenuOption::LeapDrive)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
glm::vec3 relativePosition;
|
||||||
|
glm::vec3 eulerAngles;
|
||||||
|
PalmData* rightmostPalm = getRightmostPalm();
|
||||||
|
if (rightmostPalm != NULL) {
|
||||||
|
relativePosition = rightmostPalm->getRawPosition() - _baseDrivePosition;
|
||||||
|
|
||||||
|
glm::vec3 directionSum;
|
||||||
|
int activeFingerCount = 0;
|
||||||
|
for (int i = 0; i < rightmostPalm->getNumFingers(); i++) {
|
||||||
|
FingerData& finger = rightmostPalm->getFingers()[i];
|
||||||
|
glm::vec3 fingerVector = finger.getTipRawPosition() - rightmostPalm->getRawPosition();
|
||||||
|
if (finger.isActive() && glm::length(fingerVector) > EPSILON) {
|
||||||
|
directionSum += glm::normalize(fingerVector);
|
||||||
|
activeFingerCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const int MIN_DIRECTION_FINGER_COUNT = 3;
|
||||||
|
glm::vec3 right;
|
||||||
|
if (activeFingerCount >= MIN_DIRECTION_FINGER_COUNT) {
|
||||||
|
right = glm::normalize(glm::cross(glm::normalize(directionSum), -rightmostPalm->getRawNormal()));
|
||||||
|
|
||||||
|
} else {
|
||||||
|
right = glm::normalize(glm::cross(IDENTITY_FRONT, -rightmostPalm->getRawNormal()));
|
||||||
|
}
|
||||||
|
eulerAngles = safeEulerAngles(glm::quat_cast(glm::mat3(right, -rightmostPalm->getRawNormal(),
|
||||||
|
glm::cross(right, -rightmostPalm->getRawNormal()))));
|
||||||
|
}
|
||||||
|
const float LINEAR_DRIVE_SCALE = 0.01f;
|
||||||
|
const float LINEAR_DEAD_ZONE = 0.25f;
|
||||||
|
avatar->setDriveKeys(FWD, glm::clamp(-relativePosition.z * LINEAR_DRIVE_SCALE - LINEAR_DEAD_ZONE, 0.0f, 1.0f));
|
||||||
|
avatar->setDriveKeys(BACK, glm::clamp(relativePosition.z * LINEAR_DRIVE_SCALE - LINEAR_DEAD_ZONE, 0.0f, 1.0f));
|
||||||
|
avatar->setDriveKeys(LEFT, glm::clamp(-relativePosition.x * LINEAR_DRIVE_SCALE - LINEAR_DEAD_ZONE, 0.0f, 1.0f));
|
||||||
|
avatar->setDriveKeys(RIGHT, glm::clamp(relativePosition.x * LINEAR_DRIVE_SCALE - LINEAR_DEAD_ZONE, 0.0f, 1.0f));
|
||||||
|
avatar->setDriveKeys(UP, glm::clamp(relativePosition.y * LINEAR_DRIVE_SCALE - LINEAR_DEAD_ZONE, 0.0f, 1.0f));
|
||||||
|
avatar->setDriveKeys(DOWN, glm::clamp(-relativePosition.y * LINEAR_DRIVE_SCALE - LINEAR_DEAD_ZONE, 0.0f, 1.0f));
|
||||||
|
|
||||||
|
const float ANGULAR_DRIVE_SCALE = 0.05f;
|
||||||
|
const float ANGULAR_DEAD_ZONE = 0.75f;
|
||||||
|
avatar->setDriveKeys(ROT_LEFT, glm::clamp(glm::max(eulerAngles.y, eulerAngles.z) * ANGULAR_DRIVE_SCALE -
|
||||||
|
ANGULAR_DEAD_ZONE, 0.0f, 1.0f));
|
||||||
|
avatar->setDriveKeys(ROT_RIGHT, glm::clamp(glm::max(-eulerAngles.y, -eulerAngles.z) * ANGULAR_DRIVE_SCALE -
|
||||||
|
ANGULAR_DEAD_ZONE, 0.0f, 1.0f));
|
||||||
|
avatar->setDriveKeys(ROT_UP, glm::clamp(eulerAngles.x * ANGULAR_DRIVE_SCALE - ANGULAR_DEAD_ZONE, 0.0f, 1.0f));
|
||||||
|
avatar->setDriveKeys(ROT_DOWN, glm::clamp(-eulerAngles.x * ANGULAR_DRIVE_SCALE - ANGULAR_DEAD_ZONE, 0.0f, 1.0f));
|
||||||
}
|
}
|
||||||
|
|
||||||
void LeapManager::enableFakeFingers(bool enable) {
|
void LeapManager::enableFakeFingers(bool enable) {
|
||||||
|
|
|
@ -21,7 +21,7 @@ namespace Leap {
|
||||||
|
|
||||||
class LeapManager {
|
class LeapManager {
|
||||||
public:
|
public:
|
||||||
static void nextFrame(Avatar& avatar); // called once per frame to get new Leap data
|
static void nextFrame(); // called once per frame to get new Leap data
|
||||||
static bool controllersExist(); // Returns true if there's at least one active Leap plugged in
|
static bool controllersExist(); // Returns true if there's at least one active Leap plugged in
|
||||||
static void enableFakeFingers(bool enable); // put fake data in if there's no Leap plugged in
|
static void enableFakeFingers(bool enable); // put fake data in if there's no Leap plugged in
|
||||||
static const std::vector<glm::vec3>& getFingerTips();
|
static const std::vector<glm::vec3>& getFingerTips();
|
||||||
|
@ -30,6 +30,7 @@ public:
|
||||||
static const std::vector<glm::vec3>& getHandNormals();
|
static const std::vector<glm::vec3>& getHandNormals();
|
||||||
static std::string statusString();
|
static std::string statusString();
|
||||||
static void initialize();
|
static void initialize();
|
||||||
|
static void reset();
|
||||||
static void terminate();
|
static void terminate();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -37,6 +38,7 @@ private:
|
||||||
static bool _doFakeFingers;
|
static bool _doFakeFingers;
|
||||||
static Leap::Controller* _controller;
|
static Leap::Controller* _controller;
|
||||||
static HifiLeapListener* _listener;
|
static HifiLeapListener* _listener;
|
||||||
|
static glm::vec3 _baseDrivePosition;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* defined(__hifi__LeapManager__) */
|
#endif /* defined(__hifi__LeapManager__) */
|
||||||
|
|
87
interface/src/devices/SixenseManager.cpp
Normal file
87
interface/src/devices/SixenseManager.cpp
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
//
|
||||||
|
// Sixense.cpp
|
||||||
|
// interface
|
||||||
|
//
|
||||||
|
// Created by Andrzej Kapolka on 11/15/13.
|
||||||
|
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifdef HAVE_SIXENSE
|
||||||
|
#include "sixense.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "Application.h"
|
||||||
|
#include "SixenseManager.h"
|
||||||
|
|
||||||
|
SixenseManager::SixenseManager() {
|
||||||
|
#ifdef HAVE_SIXENSE
|
||||||
|
sixenseInit();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
SixenseManager::~SixenseManager() {
|
||||||
|
#ifdef HAVE_SIXENSE
|
||||||
|
sixenseExit();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void SixenseManager::update() {
|
||||||
|
#ifdef HAVE_SIXENSE
|
||||||
|
if (sixenseGetNumActiveControllers() == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
MyAvatar* avatar = Application::getInstance()->getAvatar();
|
||||||
|
Hand& hand = avatar->getHand();
|
||||||
|
hand.getPalms().clear();
|
||||||
|
|
||||||
|
int maxControllers = sixenseGetMaxControllers();
|
||||||
|
for (int i = 0; i < maxControllers; i++) {
|
||||||
|
if (!sixenseIsControllerEnabled(i)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
sixenseControllerData data;
|
||||||
|
sixenseGetNewestData(i, &data);
|
||||||
|
|
||||||
|
// drive avatar with joystick and triggers
|
||||||
|
if (data.controller_index) {
|
||||||
|
avatar->setDriveKeys(ROT_LEFT, qMax(0.0f, -data.joystick_x));
|
||||||
|
avatar->setDriveKeys(ROT_RIGHT, qMax(0.0f, data.joystick_x));
|
||||||
|
avatar->setDriveKeys(ROT_UP, qMax(0.0f, data.joystick_y));
|
||||||
|
avatar->setDriveKeys(ROT_DOWN, qMax(0.0f, -data.joystick_y));
|
||||||
|
avatar->setDriveKeys(UP, data.trigger);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
avatar->setDriveKeys(FWD, qMax(0.0f, data.joystick_y));
|
||||||
|
avatar->setDriveKeys(BACK, qMax(0.0f, -data.joystick_y));
|
||||||
|
avatar->setDriveKeys(LEFT, qMax(0.0f, -data.joystick_x));
|
||||||
|
avatar->setDriveKeys(RIGHT, qMax(0.0f, data.joystick_x));
|
||||||
|
avatar->setDriveKeys(DOWN, data.trigger);
|
||||||
|
}
|
||||||
|
|
||||||
|
// set palm position and normal based on Hydra position/orientation
|
||||||
|
PalmData palm(&hand);
|
||||||
|
palm.setActive(true);
|
||||||
|
glm::vec3 position(-data.pos[0], data.pos[1], -data.pos[2]);
|
||||||
|
palm.setRawPosition(position);
|
||||||
|
glm::quat rotation(data.rot_quat[3], -data.rot_quat[0], data.rot_quat[1], -data.rot_quat[2]);
|
||||||
|
const glm::vec3 PALM_VECTOR(0.0f, -1.0f, 0.0f);
|
||||||
|
palm.setRawNormal(rotation * PALM_VECTOR);
|
||||||
|
|
||||||
|
// initialize the "finger" based on the direction
|
||||||
|
FingerData finger(&palm, &hand);
|
||||||
|
finger.setActive(true);
|
||||||
|
finger.setRawRootPosition(position);
|
||||||
|
const glm::vec3 FINGER_VECTOR(0.0f, 0.0f, 100.0f);
|
||||||
|
finger.setRawTipPosition(position + rotation * FINGER_VECTOR);
|
||||||
|
|
||||||
|
// three fingers indicates to the skeleton that we have enough data to determine direction
|
||||||
|
palm.getFingers().clear();
|
||||||
|
palm.getFingers().push_back(finger);
|
||||||
|
palm.getFingers().push_back(finger);
|
||||||
|
palm.getFingers().push_back(finger);
|
||||||
|
|
||||||
|
hand.getPalms().push_back(palm);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
22
interface/src/devices/SixenseManager.h
Normal file
22
interface/src/devices/SixenseManager.h
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
//
|
||||||
|
// SixenseManager.h
|
||||||
|
// interface
|
||||||
|
//
|
||||||
|
// Created by Andrzej Kapolka on 11/15/13.
|
||||||
|
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef __interface__SixenseManager__
|
||||||
|
#define __interface__SixenseManager__
|
||||||
|
|
||||||
|
/// Handles interaction with the Sixense SDK (e.g., Razer Hydra).
|
||||||
|
class SixenseManager {
|
||||||
|
public:
|
||||||
|
|
||||||
|
SixenseManager();
|
||||||
|
~SixenseManager();
|
||||||
|
|
||||||
|
void update();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* defined(__interface__SixenseManager__) */
|
|
@ -154,6 +154,8 @@ void VoxelStatsDialog::paintEvent(QPaintEvent* event) {
|
||||||
unsigned long totalNodes = 0;
|
unsigned long totalNodes = 0;
|
||||||
unsigned long totalInternal = 0;
|
unsigned long totalInternal = 0;
|
||||||
unsigned long totalLeaves = 0;
|
unsigned long totalLeaves = 0;
|
||||||
|
|
||||||
|
Application::getInstance()->lockVoxelSceneStats();
|
||||||
NodeToVoxelSceneStats* sceneStats = Application::getInstance()->getVoxelSceneStats();
|
NodeToVoxelSceneStats* sceneStats = Application::getInstance()->getVoxelSceneStats();
|
||||||
for(NodeToVoxelSceneStatsIterator i = sceneStats->begin(); i != sceneStats->end(); i++) {
|
for(NodeToVoxelSceneStatsIterator i = sceneStats->begin(); i != sceneStats->end(); i++) {
|
||||||
//const QUuid& uuid = i->first;
|
//const QUuid& uuid = i->first;
|
||||||
|
@ -176,6 +178,7 @@ void VoxelStatsDialog::paintEvent(QPaintEvent* event) {
|
||||||
sendingMode << "S";
|
sendingMode << "S";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Application::getInstance()->unlockVoxelSceneStats();
|
||||||
sendingMode << " - " << serverCount << " servers";
|
sendingMode << " - " << serverCount << " servers";
|
||||||
if (movingServerCount > 0) {
|
if (movingServerCount > 0) {
|
||||||
sendingMode << " <SCENE NOT STABLE>";
|
sendingMode << " <SCENE NOT STABLE>";
|
||||||
|
|
|
@ -189,17 +189,22 @@ int VoxelServer::civetwebRequestHandler(struct mg_connection* connection) {
|
||||||
|
|
||||||
// display voxel file load time
|
// display voxel file load time
|
||||||
if (theServer->isInitialLoadComplete()) {
|
if (theServer->isInitialLoadComplete()) {
|
||||||
tm* voxelsLoadedAtLocal = localtime(theServer->getLoadCompleted());
|
time_t* loadCompleted = theServer->getLoadCompleted();
|
||||||
const int MAX_TIME_LENGTH = 128;
|
if (loadCompleted) {
|
||||||
char buffer[MAX_TIME_LENGTH];
|
tm* voxelsLoadedAtLocal = localtime(loadCompleted);
|
||||||
strftime(buffer, MAX_TIME_LENGTH, "%m/%d/%Y %X", voxelsLoadedAtLocal);
|
const int MAX_TIME_LENGTH = 128;
|
||||||
mg_printf(connection, "Voxels Loaded At: %s", buffer);
|
char buffer[MAX_TIME_LENGTH];
|
||||||
|
strftime(buffer, MAX_TIME_LENGTH, "%m/%d/%Y %X", voxelsLoadedAtLocal);
|
||||||
|
mg_printf(connection, "Voxels Loaded At: %s", buffer);
|
||||||
|
|
||||||
// Convert now to tm struct for UTC
|
// Convert now to tm struct for UTC
|
||||||
tm* voxelsLoadedAtUTM = gmtime(theServer->getLoadCompleted());
|
tm* voxelsLoadedAtUTM = gmtime(theServer->getLoadCompleted());
|
||||||
if (gmtm != NULL) {
|
if (gmtm != NULL) {
|
||||||
strftime(buffer, MAX_TIME_LENGTH, "%m/%d/%Y %X", voxelsLoadedAtUTM);
|
strftime(buffer, MAX_TIME_LENGTH, "%m/%d/%Y %X", voxelsLoadedAtUTM);
|
||||||
mg_printf(connection, " [%s UTM] ", buffer);
|
mg_printf(connection, " [%s UTM] ", buffer);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
mg_printf(connection, "%s", "Voxel Persist Disabled...\r\n");
|
||||||
}
|
}
|
||||||
mg_printf(connection, "%s", "\r\n");
|
mg_printf(connection, "%s", "\r\n");
|
||||||
|
|
||||||
|
@ -259,7 +264,7 @@ int VoxelServer::civetwebRequestHandler(struct mg_connection* connection) {
|
||||||
|
|
||||||
// display inbound packet stats
|
// display inbound packet stats
|
||||||
mg_printf(connection, "%s", "<b>Voxel Edit Statistics... <a href='/resetStats'>[RESET]</a></b>\r\n");
|
mg_printf(connection, "%s", "<b>Voxel Edit Statistics... <a href='/resetStats'>[RESET]</a></b>\r\n");
|
||||||
uint64_t averageTransitTimePerPacket = theServer->_voxelServerPacketProcessor->getAverateTransitTimePerPacket();
|
uint64_t averageTransitTimePerPacket = theServer->_voxelServerPacketProcessor->getAverageTransitTimePerPacket();
|
||||||
uint64_t averageProcessTimePerPacket = theServer->_voxelServerPacketProcessor->getAverageProcessTimePerPacket();
|
uint64_t averageProcessTimePerPacket = theServer->_voxelServerPacketProcessor->getAverageProcessTimePerPacket();
|
||||||
uint64_t averageLockWaitTimePerPacket = theServer->_voxelServerPacketProcessor->getAverageLockWaitTimePerPacket();
|
uint64_t averageLockWaitTimePerPacket = theServer->_voxelServerPacketProcessor->getAverageLockWaitTimePerPacket();
|
||||||
uint64_t averageProcessTimePerVoxel = theServer->_voxelServerPacketProcessor->getAverageProcessTimePerVoxel();
|
uint64_t averageProcessTimePerVoxel = theServer->_voxelServerPacketProcessor->getAverageProcessTimePerVoxel();
|
||||||
|
@ -297,7 +302,7 @@ int VoxelServer::civetwebRequestHandler(struct mg_connection* connection) {
|
||||||
mg_printf(connection, "\r\n Stats for sender %d uuid: %s\r\n", senderNumber,
|
mg_printf(connection, "\r\n Stats for sender %d uuid: %s\r\n", senderNumber,
|
||||||
senderID.toString().toLocal8Bit().constData());
|
senderID.toString().toLocal8Bit().constData());
|
||||||
|
|
||||||
averageTransitTimePerPacket = senderStats.getAverateTransitTimePerPacket();
|
averageTransitTimePerPacket = senderStats.getAverageTransitTimePerPacket();
|
||||||
averageProcessTimePerPacket = senderStats.getAverageProcessTimePerPacket();
|
averageProcessTimePerPacket = senderStats.getAverageProcessTimePerPacket();
|
||||||
averageLockWaitTimePerPacket = senderStats.getAverageLockWaitTimePerPacket();
|
averageLockWaitTimePerPacket = senderStats.getAverageLockWaitTimePerPacket();
|
||||||
averageProcessTimePerVoxel = senderStats.getAverageProcessTimePerVoxel();
|
averageProcessTimePerVoxel = senderStats.getAverageProcessTimePerVoxel();
|
||||||
|
@ -305,6 +310,8 @@ int VoxelServer::civetwebRequestHandler(struct mg_connection* connection) {
|
||||||
totalVoxelsProcessed = senderStats.getTotalVoxelsProcessed();
|
totalVoxelsProcessed = senderStats.getTotalVoxelsProcessed();
|
||||||
totalPacketsProcessed = senderStats.getTotalPacketsProcessed();
|
totalPacketsProcessed = senderStats.getTotalPacketsProcessed();
|
||||||
|
|
||||||
|
averageVoxelsPerPacket = totalPacketsProcessed == 0 ? 0 : totalVoxelsProcessed / totalPacketsProcessed;
|
||||||
|
|
||||||
mg_printf(connection, " Total Inbound Packets: %s packets\r\n",
|
mg_printf(connection, " Total Inbound Packets: %s packets\r\n",
|
||||||
locale.toString((uint)totalPacketsProcessed).rightJustified(COLUMN_WIDTH, ' ').toLocal8Bit().constData());
|
locale.toString((uint)totalPacketsProcessed).rightJustified(COLUMN_WIDTH, ' ').toLocal8Bit().constData());
|
||||||
mg_printf(connection, " Total Inbound Voxels: %s voxels\r\n",
|
mg_printf(connection, " Total Inbound Voxels: %s voxels\r\n",
|
||||||
|
|
|
@ -20,7 +20,7 @@ class SingleSenderStats {
|
||||||
public:
|
public:
|
||||||
SingleSenderStats();
|
SingleSenderStats();
|
||||||
|
|
||||||
uint64_t getAverateTransitTimePerPacket() const { return _totalPackets == 0 ? 0 : _totalTransitTime / _totalPackets; }
|
uint64_t getAverageTransitTimePerPacket() const { return _totalPackets == 0 ? 0 : _totalTransitTime / _totalPackets; }
|
||||||
uint64_t getAverageProcessTimePerPacket() const { return _totalPackets == 0 ? 0 : _totalProcessTime / _totalPackets; }
|
uint64_t getAverageProcessTimePerPacket() const { return _totalPackets == 0 ? 0 : _totalProcessTime / _totalPackets; }
|
||||||
uint64_t getAverageLockWaitTimePerPacket() const { return _totalPackets == 0 ? 0 : _totalLockWaitTime / _totalPackets; }
|
uint64_t getAverageLockWaitTimePerPacket() const { return _totalPackets == 0 ? 0 : _totalLockWaitTime / _totalPackets; }
|
||||||
uint64_t getTotalVoxelsProcessed() const { return _totalVoxelsInPacket; }
|
uint64_t getTotalVoxelsProcessed() const { return _totalVoxelsInPacket; }
|
||||||
|
@ -48,7 +48,7 @@ class VoxelServerPacketProcessor : public ReceivedPacketProcessor {
|
||||||
public:
|
public:
|
||||||
VoxelServerPacketProcessor(VoxelServer* myServer);
|
VoxelServerPacketProcessor(VoxelServer* myServer);
|
||||||
|
|
||||||
uint64_t getAverateTransitTimePerPacket() const { return _totalPackets == 0 ? 0 : _totalTransitTime / _totalPackets; }
|
uint64_t getAverageTransitTimePerPacket() const { return _totalPackets == 0 ? 0 : _totalTransitTime / _totalPackets; }
|
||||||
uint64_t getAverageProcessTimePerPacket() const { return _totalPackets == 0 ? 0 : _totalProcessTime / _totalPackets; }
|
uint64_t getAverageProcessTimePerPacket() const { return _totalPackets == 0 ? 0 : _totalProcessTime / _totalPackets; }
|
||||||
uint64_t getAverageLockWaitTimePerPacket() const { return _totalPackets == 0 ? 0 : _totalLockWaitTime / _totalPackets; }
|
uint64_t getAverageLockWaitTimePerPacket() const { return _totalPackets == 0 ? 0 : _totalLockWaitTime / _totalPackets; }
|
||||||
uint64_t getTotalVoxelsProcessed() const { return _totalVoxelsInPacket; }
|
uint64_t getTotalVoxelsProcessed() const { return _totalVoxelsInPacket; }
|
||||||
|
|
|
@ -510,6 +510,7 @@ void VoxelNode::storeTwoChildren(VoxelNode* childOne, VoxelNode* childTwo) {
|
||||||
const int newChildCount = 2;
|
const int newChildCount = 2;
|
||||||
_externalChildrenMemoryUsage += newChildCount * sizeof(VoxelNode*);
|
_externalChildrenMemoryUsage += newChildCount * sizeof(VoxelNode*);
|
||||||
_children.external = new VoxelNode*[newChildCount];
|
_children.external = new VoxelNode*[newChildCount];
|
||||||
|
memset(_children.external, 0, sizeof(VoxelNode*) * newChildCount);
|
||||||
}
|
}
|
||||||
_children.external[0] = childOne;
|
_children.external[0] = childOne;
|
||||||
_children.external[1] = childTwo;
|
_children.external[1] = childTwo;
|
||||||
|
@ -620,6 +621,7 @@ void VoxelNode::storeThreeChildren(VoxelNode* childOne, VoxelNode* childTwo, Vox
|
||||||
const int newChildCount = 3;
|
const int newChildCount = 3;
|
||||||
_externalChildrenMemoryUsage += newChildCount * sizeof(VoxelNode*);
|
_externalChildrenMemoryUsage += newChildCount * sizeof(VoxelNode*);
|
||||||
_children.external = new VoxelNode*[newChildCount];
|
_children.external = new VoxelNode*[newChildCount];
|
||||||
|
memset(_children.external, 0, sizeof(VoxelNode*) * newChildCount);
|
||||||
}
|
}
|
||||||
_children.external[0] = childOne;
|
_children.external[0] = childOne;
|
||||||
_children.external[1] = childTwo;
|
_children.external[1] = childTwo;
|
||||||
|
@ -1004,6 +1006,8 @@ void VoxelNode::setChildAtIndex(int childIndex, VoxelNode* child) {
|
||||||
_childrenExternal = true;
|
_childrenExternal = true;
|
||||||
const int newChildCount = 4;
|
const int newChildCount = 4;
|
||||||
_children.external = new VoxelNode*[newChildCount];
|
_children.external = new VoxelNode*[newChildCount];
|
||||||
|
memset(_children.external, 0, sizeof(VoxelNode*) * newChildCount);
|
||||||
|
|
||||||
_externalChildrenMemoryUsage += newChildCount * sizeof(VoxelNode*);
|
_externalChildrenMemoryUsage += newChildCount * sizeof(VoxelNode*);
|
||||||
|
|
||||||
_children.external[0] = childOne;
|
_children.external[0] = childOne;
|
||||||
|
@ -1072,6 +1076,7 @@ void VoxelNode::setChildAtIndex(int childIndex, VoxelNode* child) {
|
||||||
// 4 or more children, one item being added, we know we're stored externally, we just figure out where to insert
|
// 4 or more children, one item being added, we know we're stored externally, we just figure out where to insert
|
||||||
// this child pointer into our external list
|
// this child pointer into our external list
|
||||||
VoxelNode** newExternalList = new VoxelNode*[newChildCount];
|
VoxelNode** newExternalList = new VoxelNode*[newChildCount];
|
||||||
|
memset(newExternalList, 0, sizeof(VoxelNode*) * newChildCount);
|
||||||
|
|
||||||
int copiedCount = 0;
|
int copiedCount = 0;
|
||||||
for (int ordinal = 1; ordinal <= newChildCount; ordinal++) {
|
for (int ordinal = 1; ordinal <= newChildCount; ordinal++) {
|
||||||
|
|
|
@ -28,6 +28,97 @@ VoxelSceneStats::VoxelSceneStats() :
|
||||||
_isStarted = false;
|
_isStarted = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// copy constructor
|
||||||
|
VoxelSceneStats::VoxelSceneStats(const VoxelSceneStats& other) :
|
||||||
|
_jurisdictionRoot(NULL) {
|
||||||
|
copyFromOther(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy assignment
|
||||||
|
VoxelSceneStats& VoxelSceneStats::operator=(const VoxelSceneStats& other) {
|
||||||
|
copyFromOther(other);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VoxelSceneStats::copyFromOther(const VoxelSceneStats& other) {
|
||||||
|
_totalEncodeTime = other._totalEncodeTime;
|
||||||
|
_encodeStart = other._encodeStart;
|
||||||
|
|
||||||
|
_packets = other._packets;
|
||||||
|
_bytes = other._bytes;
|
||||||
|
_passes = other._passes;
|
||||||
|
|
||||||
|
_totalVoxels = other._totalVoxels;
|
||||||
|
_totalInternal = other._totalInternal;
|
||||||
|
_totalLeaves = other._totalLeaves;
|
||||||
|
|
||||||
|
_traversed = other._traversed;
|
||||||
|
_internal = other._internal;
|
||||||
|
_leaves = other._leaves;
|
||||||
|
|
||||||
|
_skippedDistance = other._skippedDistance;
|
||||||
|
_internalSkippedDistance = other._internalSkippedDistance;
|
||||||
|
_leavesSkippedDistance = other._leavesSkippedDistance;
|
||||||
|
|
||||||
|
_skippedOutOfView = other._skippedOutOfView;
|
||||||
|
_internalSkippedOutOfView = other._internalSkippedOutOfView;
|
||||||
|
_leavesSkippedOutOfView = other._leavesSkippedOutOfView;
|
||||||
|
|
||||||
|
_skippedWasInView = other._skippedWasInView;
|
||||||
|
_internalSkippedWasInView = other._internalSkippedWasInView;
|
||||||
|
_leavesSkippedWasInView = other._leavesSkippedWasInView;
|
||||||
|
|
||||||
|
_skippedNoChange = other._skippedNoChange;
|
||||||
|
_internalSkippedNoChange = other._internalSkippedNoChange;
|
||||||
|
_leavesSkippedNoChange = other._leavesSkippedNoChange;
|
||||||
|
|
||||||
|
_skippedOccluded = other._skippedOccluded;
|
||||||
|
_internalSkippedOccluded = other._internalSkippedOccluded;
|
||||||
|
_leavesSkippedOccluded = other._leavesSkippedOccluded;
|
||||||
|
|
||||||
|
_colorSent = other._colorSent;
|
||||||
|
_internalColorSent = other._internalColorSent;
|
||||||
|
_leavesColorSent = other._leavesColorSent;
|
||||||
|
|
||||||
|
_didntFit = other._didntFit;
|
||||||
|
_internalDidntFit = other._internalDidntFit;
|
||||||
|
_leavesDidntFit = other._leavesDidntFit;
|
||||||
|
|
||||||
|
_colorBitsWritten = other._colorBitsWritten;
|
||||||
|
_existsBitsWritten = other._existsBitsWritten;
|
||||||
|
_existsInPacketBitsWritten = other._existsInPacketBitsWritten;
|
||||||
|
_treesRemoved = other._treesRemoved;
|
||||||
|
|
||||||
|
// before copying the jurisdictions, delete any current values...
|
||||||
|
if (_jurisdictionRoot) {
|
||||||
|
delete[] _jurisdictionRoot;
|
||||||
|
_jurisdictionRoot = NULL;
|
||||||
|
}
|
||||||
|
for (int i=0; i < _jurisdictionEndNodes.size(); i++) {
|
||||||
|
if (_jurisdictionEndNodes[i]) {
|
||||||
|
delete[] _jurisdictionEndNodes[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_jurisdictionEndNodes.clear();
|
||||||
|
|
||||||
|
// Now copy the values from the other
|
||||||
|
if (other._jurisdictionRoot) {
|
||||||
|
int bytes = bytesRequiredForCodeLength(numberOfThreeBitSectionsInCode(other._jurisdictionRoot));
|
||||||
|
_jurisdictionRoot = new unsigned char[bytes];
|
||||||
|
memcpy(_jurisdictionRoot, other._jurisdictionRoot, bytes);
|
||||||
|
}
|
||||||
|
for (int i=0; i < other._jurisdictionEndNodes.size(); i++) {
|
||||||
|
unsigned char* endNodeCode = other._jurisdictionEndNodes[i];
|
||||||
|
if (endNodeCode) {
|
||||||
|
int bytes = bytesRequiredForCodeLength(numberOfThreeBitSectionsInCode(endNodeCode));
|
||||||
|
unsigned char* endNodeCodeCopy = new unsigned char[bytes];
|
||||||
|
memcpy(endNodeCodeCopy, endNodeCode, bytes);
|
||||||
|
_jurisdictionEndNodes.push_back(endNodeCodeCopy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
VoxelSceneStats::~VoxelSceneStats() {
|
VoxelSceneStats::~VoxelSceneStats() {
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
@ -48,6 +139,15 @@ void VoxelSceneStats::sceneStarted(bool isFullScene, bool isMoving, VoxelNode* r
|
||||||
delete[] _jurisdictionRoot;
|
delete[] _jurisdictionRoot;
|
||||||
_jurisdictionRoot = NULL;
|
_jurisdictionRoot = NULL;
|
||||||
}
|
}
|
||||||
|
// clear existing endNodes before copying new ones...
|
||||||
|
for (int i=0; i < _jurisdictionEndNodes.size(); i++) {
|
||||||
|
if (_jurisdictionEndNodes[i]) {
|
||||||
|
delete[] _jurisdictionEndNodes[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_jurisdictionEndNodes.clear();
|
||||||
|
|
||||||
|
// setup jurisdictions
|
||||||
if (jurisdictionMap) {
|
if (jurisdictionMap) {
|
||||||
unsigned char* jurisdictionRoot = jurisdictionMap->getRootOctalCode();
|
unsigned char* jurisdictionRoot = jurisdictionMap->getRootOctalCode();
|
||||||
if (jurisdictionRoot) {
|
if (jurisdictionRoot) {
|
||||||
|
@ -56,6 +156,7 @@ void VoxelSceneStats::sceneStarted(bool isFullScene, bool isMoving, VoxelNode* r
|
||||||
memcpy(_jurisdictionRoot, jurisdictionRoot, bytes);
|
memcpy(_jurisdictionRoot, jurisdictionRoot, bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// copy new endNodes...
|
||||||
for (int i=0; i < jurisdictionMap->getEndNodeCount(); i++) {
|
for (int i=0; i < jurisdictionMap->getEndNodeCount(); i++) {
|
||||||
unsigned char* endNodeCode = jurisdictionMap->getEndNodeOctalCode(i);
|
unsigned char* endNodeCode = jurisdictionMap->getEndNodeOctalCode(i);
|
||||||
if (endNodeCode) {
|
if (endNodeCode) {
|
||||||
|
@ -436,6 +537,20 @@ int VoxelSceneStats::unpackFromMessage(unsigned char* sourceBuffer, int availabl
|
||||||
memcpy(&_treesRemoved, sourceBuffer, sizeof(_treesRemoved));
|
memcpy(&_treesRemoved, sourceBuffer, sizeof(_treesRemoved));
|
||||||
sourceBuffer += sizeof(_treesRemoved);
|
sourceBuffer += sizeof(_treesRemoved);
|
||||||
|
|
||||||
|
// before allocating new juridiction, clean up existing ones
|
||||||
|
if (_jurisdictionRoot) {
|
||||||
|
delete[] _jurisdictionRoot;
|
||||||
|
_jurisdictionRoot = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// clear existing endNodes before copying new ones...
|
||||||
|
for (int i=0; i < _jurisdictionEndNodes.size(); i++) {
|
||||||
|
if (_jurisdictionEndNodes[i]) {
|
||||||
|
delete[] _jurisdictionEndNodes[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_jurisdictionEndNodes.clear();
|
||||||
|
|
||||||
// read the root jurisdiction
|
// read the root jurisdiction
|
||||||
int bytes = 0;
|
int bytes = 0;
|
||||||
memcpy(&bytes, sourceBuffer, sizeof(bytes));
|
memcpy(&bytes, sourceBuffer, sizeof(bytes));
|
||||||
|
|
|
@ -27,6 +27,9 @@ public:
|
||||||
~VoxelSceneStats();
|
~VoxelSceneStats();
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
|
VoxelSceneStats(const VoxelSceneStats& other); // copy constructor
|
||||||
|
VoxelSceneStats& operator= (const VoxelSceneStats& other); // copy assignment
|
||||||
|
|
||||||
/// Call when beginning the computation of a scene. Initializes internal structures
|
/// Call when beginning the computation of a scene. Initializes internal structures
|
||||||
void sceneStarted(bool fullScene, bool moving, VoxelNode* root, JurisdictionMap* jurisdictionMap);
|
void sceneStarted(bool fullScene, bool moving, VoxelNode* root, JurisdictionMap* jurisdictionMap);
|
||||||
|
|
||||||
|
@ -144,6 +147,9 @@ public:
|
||||||
unsigned long getTotalLeaves() const { return _totalLeaves; }
|
unsigned long getTotalLeaves() const { return _totalLeaves; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
void copyFromOther(const VoxelSceneStats& other);
|
||||||
|
|
||||||
bool _isReadyToSend;
|
bool _isReadyToSend;
|
||||||
unsigned char _statsMessage[MAX_PACKET_SIZE];
|
unsigned char _statsMessage[MAX_PACKET_SIZE];
|
||||||
int _statsMessageLength;
|
int _statsMessageLength;
|
||||||
|
|
|
@ -272,8 +272,31 @@ int main(int argc, const char * argv[])
|
||||||
} else {
|
} else {
|
||||||
qDebug() << "Unexpected number of parameters for getOctCode\n";
|
qDebug() << "Unexpected number of parameters for getOctCode\n";
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char* DECODE_OCTCODE = "--decodeOctCode";
|
||||||
|
const char* decodeParam = getCmdOption(argc, argv, DECODE_OCTCODE);
|
||||||
|
if (decodeParam) {
|
||||||
|
|
||||||
|
QString decodeParamsString(decodeParam);
|
||||||
|
unsigned char* octalCodeToDecode = hexStringToOctalCode(decodeParamsString);
|
||||||
|
|
||||||
|
VoxelPositionSize details;
|
||||||
|
voxelDetailsForCode(octalCodeToDecode, details);
|
||||||
|
|
||||||
|
delete[] octalCodeToDecode;
|
||||||
|
|
||||||
|
qDebug() << "octal code to decode: " << decodeParamsString << "\n";
|
||||||
|
qDebug() << "Details for Octal Code:\n";
|
||||||
|
qDebug() << " x:" << details.x << "[" << details.x * TREE_SCALE << "]" << "\n";
|
||||||
|
qDebug() << " y:" << details.y << "[" << details.y * TREE_SCALE << "]" << "\n";
|
||||||
|
qDebug() << " z:" << details.z << "[" << details.z * TREE_SCALE << "]" << "\n";
|
||||||
|
qDebug() << " s:" << details.s << "[" << details.s * TREE_SCALE << "]" << "\n";
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Handles taking and SVO and splitting it into multiple SVOs based on
|
// Handles taking and SVO and splitting it into multiple SVOs based on
|
||||||
// jurisdiction details
|
// jurisdiction details
|
||||||
const char* SPLIT_SVO = "--splitSVO";
|
const char* SPLIT_SVO = "--splitSVO";
|
||||||
|
|
Loading…
Reference in a new issue