Merge branch 'master' of https://github.com/highfidelity/hifi into optimizeFindZones

This commit is contained in:
Brad Hefta-Gaub 2016-03-30 19:29:28 -07:00
commit b76f8509aa
39 changed files with 608 additions and 298 deletions

View file

@ -12,19 +12,16 @@ string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER)
# 0.5 public
# URL http://static.oculus.com/sdk-downloads/ovr_sdk_win_0.5.0.1.zip
# URL_MD5 d3fc4c02db9be5ff08af4ef4c97b32f9
# 0.6 public
# URL http://static.oculus.com/sdk-downloads/0.6.0.1/Public/1435190862/ovr_sdk_win_0.6.0.1.zip
# URL_MD5 4b3ef825f9a1d6d3035c9f6820687da9
# 0.8 public
# URL http://static.oculus.com/sdk-downloads/0.8.0.0/Public/1445451746/ovr_sdk_win_0.8.0.0.zip
# URL_MD5 54944b03b95149d6010f84eb701b9647
# 1.3 public
# URL http://hifi-public.s3.amazonaws.com/dependencies/ovr_sdk_win_1.3.0_public.zip
# URL_MD5 4d26faba0c1f35ff80bf674c96ed9259
if (WIN32)
ExternalProject_Add(
${EXTERNAL_NAME}
URL http://static.oculus.com/sdk-downloads/0.8.0.0/Public/1445451746/ovr_sdk_win_0.8.0.0.zip
URL_MD5 54944b03b95149d6010f84eb701b9647
URL http://hifi-public.s3.amazonaws.com/dependencies/ovr_sdk_win_1.3.0_public.zip
URL_MD5 a2dcf695e0f03a70fdd1ed7480585e82
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""
@ -33,14 +30,16 @@ if (WIN32)
ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR)
# FIXME need to account for different architectures
set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/LibOVR/Include CACHE TYPE INTERNAL)
set(LIBOVR_DIR ${SOURCE_DIR}/OculusSDK/LibOVR)
if ("${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/LibOVR/Lib/Windows/x64/Release/VS2013/LibOVR.lib CACHE TYPE INTERNAL)
set(LIBOVR_LIB_DIR ${LIBOVR_DIR}/Lib/Windows/x64/Release/VS2013 CACHE TYPE INTERNAL)
else()
set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/LibOVR/Lib/Windows/Win32/Release/VS2013/LibOVR.lib CACHE TYPE INTERNAL)
set(LIBOVR_LIB_DIR ${LIBOVR_DIR}/Lib/Windows/Win32/Release/VS2013 CACHE TYPE INTERNAL)
endif()
set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${LIBOVR_DIR}/Include CACHE TYPE INTERNAL)
set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${LIBOVR_LIB_DIR}/LibOVR.lib CACHE TYPE INTERNAL)
elseif(APPLE)
ExternalProject_Add(

View file

@ -85,8 +85,8 @@ macro(GENERATE_INSTALLERS)
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/LICENSE")
cpack_add_component(${CLIENT_COMPONENT} DISPLAY_NAME "High Fidelity Client")
cpack_add_component(${SERVER_COMPONENT} DISPLAY_NAME "High Fidelity Server")
cpack_add_component(${CLIENT_COMPONENT} DISPLAY_NAME "High Fidelity Interface")
cpack_add_component(${SERVER_COMPONENT} DISPLAY_NAME "High Fidelity Sandbox")
include(CPack)
endmacro()

View file

@ -53,7 +53,7 @@ macro(SET_PACKAGING_PARAMETERS)
set(CONSOLE_INSTALL_DIR ${DMG_SUBFOLDER_NAME})
set(INTERFACE_INSTALL_DIR ${DMG_SUBFOLDER_NAME})
set(CONSOLE_EXEC_NAME "Server Console.app")
set(CONSOLE_EXEC_NAME "Sandbox.app")
set(CONSOLE_INSTALL_APP_PATH "${CONSOLE_INSTALL_DIR}/${CONSOLE_EXEC_NAME}")
set(CONSOLE_APP_CONTENTS "${CONSOLE_INSTALL_APP_PATH}/Contents")
@ -84,12 +84,19 @@ macro(SET_PACKAGING_PARAMETERS)
# shortcut names
if (PRODUCTION_BUILD)
set(INTERFACE_SHORTCUT_NAME "High Fidelity")
set(CONSOLE_SHORTCUT_NAME "Server Console")
set(INTERFACE_SHORTCUT_NAME "Interface")
set(CONSOLE_SHORTCUT_NAME "Sandbox")
else ()
set(INTERFACE_SHORTCUT_NAME "High Fidelity - ${BUILD_VERSION}")
set(CONSOLE_SHORTCUT_NAME "Server Console - ${BUILD_VERSION}")
set(INTERFACE_SHORTCUT_NAME "Interface - ${BUILD_VERSION}")
set(CONSOLE_SHORTCUT_NAME "Sandbox - ${BUILD_VERSION}")
endif ()
set(INTERFACE_HF_SHORTCUT_NAME "High Fidelity ${INTERFACE_SHORTCUT_NAME}")
set(CONSOLE_HF_SHORTCUT_NAME "High Fidelity ${CONSOLE_SHORTCUT_NAME}")
set(PRE_SANDBOX_INTERFACE_SHORTCUT_NAME "High Fidelity")
set(PRE_SANDBOX_CONSOLE_SHORTCUT_NAME "Server Console")
# check if we need to find signtool
if (PRODUCTION_BUILD OR PR_BUILD)
find_program(SIGNTOOL_EXECUTABLE signtool PATHS "C:/Program Files (x86)/Windows Kits/8.1" PATH_SUFFIXES "bin/x64")

View file

@ -10,10 +10,14 @@
#
set(INTERFACE_SHORTCUT_NAME "@INTERFACE_SHORTCUT_NAME@")
set(INTERFACE_HF_SHORTCUT_NAME "@INTERFACE_HF_SHORTCUT_NAME@")
set(INTERFACE_WIN_EXEC_NAME "@INTERFACE_EXEC_PREFIX@.exe")
set(CONSOLE_INSTALL_SUBDIR "@CONSOLE_INSTALL_DIR@")
set(CONSOLE_SHORTCUT_NAME "@CONSOLE_SHORTCUT_NAME@")
set(CONSOLE_HF_SHORTCUT_NAME "@CONSOLE_HF_SHORTCUT_NAME@")
set(CONSOLE_WIN_EXEC_NAME "@CONSOLE_EXEC_NAME@")
set(PRE_SANDBOX_INTERFACE_SHORTCUT_NAME "@PRE_SANDBOX_INTERFACE_SHORTCUT_NAME@")
set(PRE_SANDBOX_CONSOLE_SHORTCUT_NAME "@PRE_SANDBOX_CONSOLE_SHORTCUT_NAME@")
set(DS_EXEC_NAME "@DS_EXEC_NAME@")
set(AC_EXEC_NAME "@AC_EXEC_NAME@")
set(HIGH_FIDELITY_PROTOCOL "@HIGH_FIDELITY_PROTOCOL@")

View file

@ -387,7 +387,7 @@ Function PostInstallOptionsPage
StrCpy $OffsetUnits u
${If} ${SectionIsSelected} ${@CLIENT_COMPONENT_NAME@}
${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Create a desktop shortcut for @INTERFACE_SHORTCUT_NAME@"
${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Create a desktop shortcut for @INTERFACE_HF_SHORTCUT_NAME@"
Pop $DesktopClientCheckbox
IntOp $CurrentOffset $CurrentOffset + 15
@ -396,7 +396,7 @@ Function PostInstallOptionsPage
${EndIf}
${If} ${SectionIsSelected} ${@SERVER_COMPONENT_NAME@}
${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Create a desktop shortcut for High Fidelity @CONSOLE_SHORTCUT_NAME@"
${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Create a desktop shortcut for @CONSOLE_HF_SHORTCUT_NAME@"
Pop $DesktopServerCheckbox
; set the checkbox state depending on what is present in the registry
@ -404,7 +404,7 @@ Function PostInstallOptionsPage
IntOp $CurrentOffset $CurrentOffset + 15
${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Launch High Fidelity @CONSOLE_SHORTCUT_NAME@ on startup"
${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Launch @CONSOLE_HF_SHORTCUT_NAME@ on startup"
Pop $ServerStartupCheckbox
; set the checkbox state depending on what is present in the registry
@ -414,9 +414,9 @@ Function PostInstallOptionsPage
${EndIf}
${If} ${SectionIsSelected} ${@SERVER_COMPONENT_NAME@}
${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Launch High Fidelity Server Console after install"
${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Launch @CONSOLE_HF_SHORTCUT_NAME@ after install"
${Else}
${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Launch High Fidelity after install"
${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Launch @INTERFACE_HF_SHORTCUT_NAME@ after install"
${EndIf}
Pop $LaunchNowCheckbox
@ -465,10 +465,10 @@ Function ReadPostInstallOptions
${EndIf}
${If} ${SectionIsSelected} ${@SERVER_COMPONENT_NAME@}
; check if the user asked for a desktop shortcut to Server Console
; check if the user asked for a desktop shortcut to Sandbox
${NSD_GetState} $DesktopServerCheckbox $DesktopServerState
; check if the user asked to have Server Console launched every startup
; check if the user asked to have Sandbox launched every startup
${NSD_GetState} $ServerStartupCheckbox $ServerStartupState
${EndIf}
@ -485,7 +485,7 @@ Function HandlePostInstallOptions
${If} ${SectionIsSelected} ${@CLIENT_COMPONENT_NAME@}
; check if the user asked for a desktop shortcut to High Fidelity
${If} $DesktopClientState == ${BST_CHECKED}
CreateShortCut "$DESKTOP\@INTERFACE_SHORTCUT_NAME@.lnk" "$INSTDIR\@INTERFACE_WIN_EXEC_NAME@"
CreateShortCut "$DESKTOP\@INTERFACE_HF_SHORTCUT_NAME@.lnk" "$INSTDIR\@INTERFACE_WIN_EXEC_NAME@"
!insertmacro WritePostInstallOption "@CLIENT_DESKTOP_SHORTCUT_REG_KEY@" YES
${Else}
!insertmacro WritePostInstallOption @CLIENT_DESKTOP_SHORTCUT_REG_KEY@ NO
@ -494,23 +494,23 @@ Function HandlePostInstallOptions
${EndIf}
${If} ${SectionIsSelected} ${@SERVER_COMPONENT_NAME@}
; check if the user asked for a desktop shortcut to Server Console
; check if the user asked for a desktop shortcut to Sandbox
${If} $DesktopServerState == ${BST_CHECKED}
CreateShortCut "$DESKTOP\@CONSOLE_SHORTCUT_NAME@.lnk" "$INSTDIR\@CONSOLE_INSTALL_SUBDIR@\@CONSOLE_WIN_EXEC_NAME@"
CreateShortCut "$DESKTOP\@CONSOLE_HF_SHORTCUT_NAME@.lnk" "$INSTDIR\@CONSOLE_INSTALL_SUBDIR@\@CONSOLE_WIN_EXEC_NAME@"
!insertmacro WritePostInstallOption @CONSOLE_DESKTOP_SHORTCUT_REG_KEY@ YES
${Else}
!insertmacro WritePostInstallOption @CONSOLE_DESKTOP_SHORTCUT_REG_KEY@ NO
${EndIf}
; check if the user asked to have Server Console launched every startup
; check if the user asked to have Sandbox launched every startup
${If} $ServerStartupState == ${BST_CHECKED}
; in case we added a shortcut in the global context, pull that now
SetShellVarContext all
Delete "$SMSTARTUP\@CONSOLE_SHORTCUT_NAME@.lnk"
Delete "$SMSTARTUP\@PRE_SANDBOX_CONSOLE_SHORTCUT_NAME@.lnk"
; make a startup shortcut in this user's current context
SetShellVarContext current
CreateShortCut "$SMSTARTUP\@CONSOLE_SHORTCUT_NAME@.lnk" "$INSTDIR\@CONSOLE_INSTALL_SUBDIR@\@CONSOLE_WIN_EXEC_NAME@"
CreateShortCut "$SMSTARTUP\@CONSOLE_HF_SHORTCUT_NAME@.lnk" "$INSTDIR\@CONSOLE_INSTALL_SUBDIR@\@CONSOLE_WIN_EXEC_NAME@"
; reset the shell var context back
SetShellVarContext all
@ -589,6 +589,19 @@ Section "-Core installation"
Delete "$INSTDIR\version"
Delete "$INSTDIR\xinput1_3.dll"
; Delete old desktop shortcuts before they were renamed during Sandbox rename
Delete "$DESKTOP\@PRE_SANDBOX_INTERFACE_SHORTCUT_NAME@.lnk"
Delete "$DESKTOP\@PRE_SANDBOX_CONSOLE_SHORTCUT_NAME@.lnk"
; Delete old Start Menu shortcuts before Sandbox rename
Delete "$SMPROGRAMS\$STARTMENU_FOLDER\@PRE_SANDBOX_INTERFACE_SHORTCUT_NAME@.lnk"
Delete "$SMPROGRAMS\$STARTMENU_FOLDER\@PRE_SANDBOX_CONSOLE_SHORTCUT_NAME@.lnk"
; Delete old startup item for Server Console before Sandbox rename
SetShellVarContext current
Delete "$SMSTARTUP\@PRE_SANDBOX_CONSOLE_SHORTCUT_NAME@.lnk"
SetShellVarContext all
; Rename the incorrectly cased Raleway font
Rename "$INSTDIR\resources\qml\styles-uit\RalewaySemibold.qml" "$INSTDIR\resources\qml\styles-uit\RalewaySemiBold.qml"
@ -724,8 +737,8 @@ SectionEnd
!macroend
!macro CheckForRunningApplications action prompter
!insertmacro PromptForRunningApplication "@INTERFACE_WIN_EXEC_NAME@" "High Fidelity client" ${action} ${prompter}
!insertmacro PromptForRunningApplication "@CONSOLE_WIN_EXEC_NAME@" "Server Console" ${action} ${prompter}
!insertmacro PromptForRunningApplication "@INTERFACE_WIN_EXEC_NAME@" "@CONSOLE_SHORTCUT_NAME@" ${action} ${prompter}
!insertmacro PromptForRunningApplication "@CONSOLE_WIN_EXEC_NAME@" "@INTERFACE_SHORTCUT_NAME@" ${action} ${prompter}
!insertmacro PromptForRunningApplication "@DS_EXEC_NAME@" "Domain Server" ${action} ${prompter}
!insertmacro PromptForRunningApplication "@AC_EXEC_NAME@" "Assignment Client" ${action} ${prompter}
!macroend
@ -869,12 +882,12 @@ Section "Uninstall"
Delete "$SMPROGRAMS\$MUI_TEMP\Uninstall.lnk"
Delete "$SMPROGRAMS\$MUI_TEMP\@INTERFACE_SHORTCUT_NAME@.lnk"
Delete "$SMPROGRAMS\$MUI_TEMP\@CONSOLE_SHORTCUT_NAME@.lnk"
Delete "$DESKTOP\@INTERFACE_SHORTCUT_NAME@.lnk"
Delete "$DESKTOP\@CONSOLE_SHORTCUT_NAME@.lnk"
Delete "$DESKTOP\@INTERFACE_HF_SHORTCUT_NAME@.lnk"
Delete "$DESKTOP\@CONSOLE_HF_SHORTCUT_NAME@.lnk"
; if it exists, delete the startup shortcut for the current user
SetShellVarContext current
Delete "$SMSTARTUP\@CONSOLE_SHORTCUT_NAME@.lnk"
Delete "$SMSTARTUP\@CONSOLE_HF_SHORTCUT_NAME@.lnk"
SetShellVarContext all
@CPACK_NSIS_DELETE_ICONS@

View file

@ -19,6 +19,7 @@
#include <QtNetwork/QNetworkRequest>
#include <LimitedNodeList.h>
#include <NetworkAccessManager.h>
#include <NetworkingConstants.h>
#include <udt/PacketHeaders.h>
#include <SharedUtil.h>
@ -33,7 +34,8 @@ IceServer::IceServer(int argc, char* argv[]) :
_id(QUuid::createUuid()),
_serverSocket(),
_activePeers(),
_httpManager(QHostAddress::AnyIPv4, ICE_SERVER_MONITORING_PORT, QString("%1/web/").arg(QCoreApplication::applicationDirPath()), this)
_httpManager(QHostAddress::AnyIPv4, ICE_SERVER_MONITORING_PORT, QString("%1/web/").arg(QCoreApplication::applicationDirPath()), this),
_lastInactiveCheckTimestamp(QDateTime::currentMSecsSinceEpoch())
{
// start the ice-server socket
qDebug() << "ice-server socket is listening on" << ICE_SERVER_DEFAULT_PORT;
@ -68,8 +70,6 @@ bool IceServer::packetVersionMatch(const udt::Packet& packet) {
void IceServer::processPacket(std::unique_ptr<udt::Packet> packet) {
_lastPacketTimestamp = QDateTime::currentMSecsSinceEpoch();
auto nlPacket = NLPacket::fromBase(std::move(packet));
// make sure that this packet at least looks like something we can read
@ -201,8 +201,8 @@ bool IceServer::isVerifiedHeartbeat(const QUuid& domainID, const QByteArray& pla
void IceServer::requestDomainPublicKey(const QUuid& domainID) {
// send a request to the metaverse API for the public key for this domain
QNetworkAccessManager* manager = new QNetworkAccessManager { this };
connect(manager, &QNetworkAccessManager::finished, this, &IceServer::publicKeyReplyFinished);
auto& networkAccessManager = NetworkAccessManager::getInstance();
connect(&networkAccessManager, &QNetworkAccessManager::finished, this, &IceServer::publicKeyReplyFinished);
QUrl publicKeyURL { NetworkingConstants::METAVERSE_SERVER_URL };
QString publicKeyPath = QString("/api/v1/domains/%1/public_key").arg(uuidStringWithoutCurlyBraces(domainID));
@ -213,7 +213,7 @@ void IceServer::requestDomainPublicKey(const QUuid& domainID) {
qDebug() << "Requesting public key for domain with ID" << domainID;
manager->get(publicKeyRequest);
networkAccessManager.get(publicKeyRequest);
}
void IceServer::publicKeyReplyFinished(QNetworkReply* reply) {
@ -281,6 +281,8 @@ void IceServer::sendPeerInformationPacket(const NetworkPeer& peer, const HifiSoc
void IceServer::clearInactivePeers() {
NetworkPeerHash::iterator peerItem = _activePeers.begin();
_lastInactiveCheckTimestamp = QDateTime::currentMSecsSinceEpoch();
while (peerItem != _activePeers.end()) {
SharedNetworkPeer peer = peerItem.value();
@ -309,11 +311,14 @@ bool IceServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url, b
const quint64 MAX_PACKET_GAP_MS_FOR_STUCK_SOCKET = 10 * 1000;
int statusNumber = (QDateTime::currentMSecsSinceEpoch() - _lastPacketTimestamp > MAX_PACKET_GAP_MS_FOR_STUCK_SOCKET)
? 1 : 0;
auto sinceLastInactiveCheck = QDateTime::currentMSecsSinceEpoch() - _lastInactiveCheckTimestamp;
int statusNumber = (sinceLastInactiveCheck > MAX_PACKET_GAP_MS_FOR_STUCK_SOCKET) ? 1 : 0;
connection->respond(HTTPConnection::StatusCode200, QByteArray::number(statusNumber));
return true;
}
}
return true;
return false;
}

View file

@ -58,7 +58,7 @@ private:
using DomainPublicKeyHash = std::unordered_map<QUuid, RSAUniquePtr>;
DomainPublicKeyHash _domainPublicKeys;
quint64 _lastPacketTimestamp;
quint64 _lastInactiveCheckTimestamp;
};
#endif // hifi_IceServer_h

View file

@ -1489,11 +1489,15 @@ void Application::paintGL() {
// FIXME not needed anymore?
_offscreenContext->makeCurrent();
displayPlugin->updateHeadPose(_frameCount);
displayPlugin->beginFrameRender(_frameCount);
// update the avatar with a fresh HMD pose
getMyAvatar()->updateFromHMDSensorMatrix(getHMDSensorPose());
// update sensorToWorldMatrix for camera and hand controllers
getMyAvatar()->updateSensorToWorldMatrix();
auto lodManager = DependencyManager::get<LODManager>();
@ -2006,6 +2010,12 @@ void Application::keyPressEvent(QKeyEvent* event) {
}
break;
case Qt::Key_Y:
if (isShifted && isMeta) {
getActiveDisplayPlugin()->cycleDebugOutput();
}
break;
case Qt::Key_B:
if (isMeta) {
auto offscreenUi = DependencyManager::get<OffscreenUi>();
@ -2571,11 +2581,6 @@ void Application::idle(uint64_t now) {
return; // bail early, nothing to do here.
}
checkChangeCursor();
Stats::getInstance()->updateStats();
AvatarInputs::getInstance()->update();
// These tasks need to be done on our first idle, because we don't want the showing of
// overlay subwindows to do a showDesktop() until after the first time through
static bool firstIdle = true;
@ -2624,6 +2629,11 @@ void Application::idle(uint64_t now) {
// We're going to execute idle processing, so restart the last idle timer
_lastTimeUpdated.start();
checkChangeCursor();
Stats::getInstance()->updateStats();
AvatarInputs::getInstance()->update();
{
static uint64_t lastIdleStart{ now };
uint64_t idleStartToStartDuration = now - lastIdleStart;
@ -3390,9 +3400,6 @@ void Application::update(float deltaTime) {
qApp->updateMyAvatarLookAtPosition();
// update sensorToWorldMatrix for camera and hand controllers
myAvatar->updateSensorToWorldMatrix();
{
PROFILE_RANGE_EX("MyAvatar", 0xffff00ff, (uint64_t)getActiveDisplayPlugin()->presentCount());
avatarManager->updateMyAvatar(deltaTime);

View file

@ -81,6 +81,9 @@ namespace controller {
// Triggers
LT,
RT,
// Grips (Oculus touch squeeze)
LG,
RG,
NUM_STANDARD_AXES,
LZ = LT,
RZ = RT

View file

@ -552,9 +552,9 @@ float OpenGLDisplayPlugin::presentRate() {
{
Lock lock(_mutex);
result = _usecsPerFrame.getAverage();
result = 1.0f / result;
result *= USECS_PER_SECOND;
}
result = 1.0f / result;
result *= USECS_PER_SECOND;
return result;
}

View file

@ -17,9 +17,9 @@
#include <GLMHelpers.h>
#include <SimpleMovingAverage.h>
#include <gl/OglplusHelpers.h>
#include <gl/GLEscrow.h>
#define THREADED_PRESENT 1
#include <gl/GLEscrow.h>
class OpenGLDisplayPlugin : public DisplayPlugin {
protected:

View file

@ -69,10 +69,11 @@ void HmdDisplayPlugin::compositeOverlay() {
// set the alpha
Uniform<float>(*_program, _alphaUniform).Set(overlayAlpha);
auto eyePoses = _currentPresentFrameInfo.eyePoses;
_sphereSection->Use();
for_each_eye([&](Eye eye) {
eyeViewport(eye);
auto modelView = glm::inverse(_currentRenderEyePoses[eye]); // *glm::translate(mat4(), vec3(0, 0, -1));
auto modelView = glm::inverse(eyePoses[eye]); // *glm::translate(mat4(), vec3(0, 0, -1));
auto mvp = _eyeProjections[eye] * modelView;
Uniform<glm::mat4>(*_program, _mvpUniform).Set(mvp);
_sphereSection->Draw();
@ -95,10 +96,10 @@ void HmdDisplayPlugin::compositePointer() {
// Mouse pointer
_plane->Use();
// Reconstruct the headpose from the eye poses
auto headPosition = (vec3(_currentRenderEyePoses[Left][3]) + vec3(_currentRenderEyePoses[Right][3])) / 2.0f;
auto headPosition = vec3(_currentPresentFrameInfo.headPose[3]);
for_each_eye([&](Eye eye) {
eyeViewport(eye);
auto reticleTransform = compositorHelper->getReticleTransform(_currentRenderEyePoses[eye], headPosition);
auto reticleTransform = compositorHelper->getReticleTransform(_currentPresentFrameInfo.eyePoses[eye], headPosition);
auto mvp = _eyeProjections[eye] * reticleTransform;
Uniform<glm::mat4>(*_program, _mvpUniform).Set(mvp);
_plane->Draw();
@ -160,15 +161,28 @@ void HmdDisplayPlugin::internalPresent() {
void HmdDisplayPlugin::setEyeRenderPose(uint32_t frameIndex, Eye eye, const glm::mat4& pose) {
Lock lock(_mutex);
_renderEyePoses[frameIndex][eye] = pose;
FrameInfo& frame = _frameInfos[frameIndex];
frame.eyePoses[eye] = pose;
}
void HmdDisplayPlugin::updateFrameData() {
// Check if we have old frame data to discard
{
Lock lock(_mutex);
auto itr = _frameInfos.find(_currentRenderFrameIndex);
if (itr != _frameInfos.end()) {
_frameInfos.erase(itr);
}
}
Parent::updateFrameData();
Lock lock(_mutex);
_currentRenderEyePoses = _renderEyePoses[_currentRenderFrameIndex];
{
Lock lock(_mutex);
_currentPresentFrameInfo = _frameInfos[_currentRenderFrameIndex];
}
}
glm::mat4 HmdDisplayPlugin::getHeadPose() const {
return _headPoseCache.get();
return _currentRenderFrameInfo.get().headPose;
}

View file

@ -28,6 +28,16 @@ public:
virtual glm::mat4 getHeadPose() const override;
using EyePoses = std::array<glm::mat4, 2>;
struct FrameInfo {
EyePoses eyePoses;
glm::mat4 headPose;
double sensorSampleTime { 0 };
double predictedDisplayTime { 0 };
};
protected:
virtual void hmdPresent() = 0;
virtual bool isHmdMounted() const = 0;
@ -46,10 +56,10 @@ protected:
glm::mat4 _cullingProjection;
glm::uvec2 _renderTargetSize;
float _ipd { 0.064f };
using EyePoses = std::array<glm::mat4, 2>;
QMap<uint32_t, EyePoses> _renderEyePoses;
EyePoses _currentRenderEyePoses;
ThreadSafeValueCache<glm::mat4> _headPoseCache { glm::mat4() };
QMap<uint32_t, FrameInfo> _frameInfos;
FrameInfo _currentPresentFrameInfo;
ThreadSafeValueCache<FrameInfo> _currentRenderFrameInfo;
private:
bool _enablePreview { false };

View file

@ -122,7 +122,7 @@ public:
}
// will query the underlying hmd api to compute the most recent head pose
virtual void updateHeadPose(uint32_t frameIndex) {}
virtual void beginFrameRender(uint32_t frameIndex) {}
// returns a copy of the most recent head pose, computed via updateHeadPose
virtual glm::mat4 getHeadPose() const {
@ -142,6 +142,8 @@ public:
virtual float presentRate() { return -1.0f; }
uint32_t presentCount() const { return _presentedFrameIndex; }
virtual void cycleDebugOutput() {}
static const QString& MENU_PATH();
signals:

View file

@ -538,7 +538,7 @@ void Model::setVisibleInScene(bool newValue, std::shared_ptr<render::Scene> scen
pendingChanges.resetItem(item, _modelMeshRenderItems[item]);
}
foreach (auto item, _collisionRenderItems.keys()) {
pendingChanges.resetItem(item, _modelMeshRenderItems[item]);
pendingChanges.resetItem(item, _collisionRenderItems[item]);
}
scene->enqueuePendingChanges(pendingChanges);
}

View file

@ -16,8 +16,13 @@
using namespace render;
void PendingChanges::resetItem(ItemID id, const PayloadPointer& payload) {
_resetItems.push_back(id);
_resetPayloads.push_back(payload);
if (payload) {
_resetItems.push_back(id);
_resetPayloads.push_back(payload);
} else {
qDebug() << "WARNING: PendingChanges::resetItem with a null payload!";
removeItem(id);
}
}
void PendingChanges::removeItem(ItemID id) {

View file

@ -23,6 +23,7 @@
template <typename T>
class ThreadSafeValueCache {
public:
ThreadSafeValueCache() {}
ThreadSafeValueCache(const T& v) : _value { v } {}
// returns atomic copy of the cached value.

View file

@ -12,14 +12,19 @@
#include "OculusHelpers.h"
void OculusBaseDisplayPlugin::resetSensors() {
ovr_RecenterPose(_session);
ovr_RecenterTrackingOrigin(_session);
}
void OculusBaseDisplayPlugin::updateHeadPose(uint32_t frameIndex) {
auto displayTime = ovr_GetPredictedDisplayTime(_session, frameIndex);
auto trackingState = ovr_GetTrackingState(_session, displayTime, true);
mat4 headPose = toGlm(trackingState.HeadPose.ThePose);
_headPoseCache.set(headPose);
void OculusBaseDisplayPlugin::beginFrameRender(uint32_t frameIndex) {
FrameInfo frame;
frame.sensorSampleTime = ovr_GetTimeInSeconds();;
frame.predictedDisplayTime = ovr_GetPredictedDisplayTime(_session, frameIndex);
auto trackingState = ovr_GetTrackingState(_session, frame.predictedDisplayTime, ovrTrue);
frame.headPose = toGlm(trackingState.HeadPose.ThePose);
_currentRenderFrameInfo.set(frame);
Lock lock(_mutex);
_frameInfos[frameIndex] = frame;
}
bool OculusBaseDisplayPlugin::isSupported() const {
@ -42,36 +47,30 @@ bool OculusBaseDisplayPlugin::internalActivate() {
_hmdDesc = ovr_GetHmdDesc(_session);
_ipd = ovr_GetFloat(_session, OVR_KEY_IPD, _ipd);
glm::uvec2 eyeSizes[2];
_viewScaleDesc.HmdSpaceToWorldScaleInMeters = 1.0f;
_ipd = 0;
ovr_for_each_eye([&](ovrEyeType eye) {
_eyeFovs[eye] = _hmdDesc.DefaultEyeFov[eye];
ovrEyeRenderDesc& erd = _eyeRenderDescs[eye] = ovr_GetRenderDesc(_session, eye, _eyeFovs[eye]);
ovrMatrix4f ovrPerspectiveProjection =
ovrMatrix4f_Projection(erd.Fov, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP, ovrProjection_RightHanded);
ovrMatrix4f_Projection(erd.Fov, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP, ovrProjection_ClipRangeOpenGL);
_eyeProjections[eye] = toGlm(ovrPerspectiveProjection);
_eyeOffsets[eye] = glm::translate(mat4(), toGlm(erd.HmdToEyeViewOffset));
_eyeOffsets[eye] = glm::translate(mat4(), toGlm(erd.HmdToEyeOffset));
eyeSizes[eye] = toGlm(ovr_GetFovTextureSize(_session, eye, erd.Fov, 1.0f));
_viewScaleDesc.HmdToEyeViewOffset[eye] = erd.HmdToEyeViewOffset;
_viewScaleDesc.HmdToEyeOffset[eye] = erd.HmdToEyeOffset;
_ipd += glm::abs(glm::length(toGlm(erd.HmdToEyeOffset)));
});
auto combinedFov = _eyeFovs[0];
combinedFov.LeftTan = combinedFov.RightTan = std::max(combinedFov.LeftTan, combinedFov.RightTan);
_cullingProjection = toGlm(ovrMatrix4f_Projection(combinedFov, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP, ovrProjection_RightHanded));
_cullingProjection = toGlm(ovrMatrix4f_Projection(combinedFov, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP, ovrProjection_ClipRangeOpenGL));
_renderTargetSize = uvec2(
eyeSizes[0].x + eyeSizes[1].x,
std::max(eyeSizes[0].y, eyeSizes[1].y));
if (!OVR_SUCCESS(ovr_ConfigureTracking(_session,
ovrTrackingCap_Orientation | ovrTrackingCap_Position | ovrTrackingCap_MagYawCorrection, 0))) {
logWarning("Failed to attach to sensor device");
}
// Parent class relies on our _session intialization, so it must come after that.
memset(&_sceneLayer, 0, sizeof(ovrLayerEyeFov));
_sceneLayer.Header.Type = ovrLayerType_EyeFov;
_sceneLayer.Header.Flags = ovrLayerFlag_TextureOriginAtBottomLeft;

View file

@ -20,7 +20,8 @@ public:
// Stereo specific methods
virtual void resetSensors() override final;
virtual void updateHeadPose(uint32_t frameIndex) override;
virtual void beginFrameRender(uint32_t frameIndex) override;
protected:
void customizeContext() override;
@ -28,9 +29,8 @@ protected:
void internalDeactivate() override;
protected:
ovrSession _session;
ovrSession _session { nullptr };
ovrGraphicsLuid _luid;
float _ipd{ OVR_DEFAULT_IPD };
ovrEyeRenderDesc _eyeRenderDescs[2];
ovrFovPort _eyeFovs[2];
ovrHmdDesc _hmdDesc;

View file

@ -0,0 +1,219 @@
//
// OculusControllerManager.cpp
// input-plugins/src/input-plugins
//
// Created by Bradley Austin Davis 2016/03/04.
// Copyright 2013-2016 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "OculusControllerManager.h"
#include <QtCore/QLoggingCategory>
#include <plugins/PluginContainer.h>
#include <controllers/UserInputMapper.h>
#include <controllers/StandardControls.h>
#include <PerfStat.h>
#include <PathUtils.h>
#include "OculusHelpers.h"
Q_DECLARE_LOGGING_CATEGORY(oculus)
static const QString MENU_PARENT = "Avatar";
static const QString MENU_NAME = "Oculus Touch Controllers";
static const QString MENU_PATH = MENU_PARENT + ">" + MENU_NAME;
const QString OculusControllerManager::NAME = "Oculus";
bool OculusControllerManager::isSupported() const {
return oculusAvailable();
}
bool OculusControllerManager::activate() {
InputPlugin::activate();
if (!_session) {
_session = acquireOculusSession();
}
Q_ASSERT(_session);
// register with UserInputMapper
auto userInputMapper = DependencyManager::get<controller::UserInputMapper>();
if (_remote) {
userInputMapper->registerDevice(_remote);
}
if (_touch) {
userInputMapper->registerDevice(_touch);
}
return true;
}
void OculusControllerManager::deactivate() {
InputPlugin::deactivate();
if (_session) {
releaseOculusSession();
_session = nullptr;
}
// unregister with UserInputMapper
auto userInputMapper = DependencyManager::get<controller::UserInputMapper>();
if (_touch) {
userInputMapper->removeDevice(_touch->getDeviceID());
}
if (_remote) {
userInputMapper->removeDevice(_remote->getDeviceID());
}
}
void OculusControllerManager::pluginUpdate(float deltaTime, const controller::InputCalibrationData& inputCalibrationData, bool jointsCaptured) {
PerformanceTimer perfTimer("OculusControllerManager::TouchDevice::update");
if (!OVR_SUCCESS(ovr_GetInputState(_session, ovrControllerType_Touch, &_inputState))) {
qCWarning(oculus) << "Unable to read oculus input state";
return;
}
if (_touch) {
_touch->update(deltaTime, inputCalibrationData, jointsCaptured);
}
if (_remote) {
_remote->update(deltaTime, inputCalibrationData, jointsCaptured);
}
}
void OculusControllerManager::pluginFocusOutEvent() {
if (_touch) {
_touch->focusOutEvent();
}
if (_remote) {
_remote->focusOutEvent();
}
}
using namespace controller;
static const std::vector<std::pair<ovrButton, StandardButtonChannel>> BUTTON_MAP { {
{ ovrButton_X, X },
{ ovrButton_Y, Y },
{ ovrButton_A, A },
{ ovrButton_B, B },
{ ovrButton_LThumb, LS },
{ ovrButton_RThumb, RS },
{ ovrButton_LShoulder, LB },
{ ovrButton_RShoulder, RB },
} };
static const std::vector<std::pair<ovrTouch, StandardButtonChannel>> TOUCH_MAP { {
{ ovrTouch_X, LEFT_SECONDARY_THUMB_TOUCH },
{ ovrTouch_Y, LEFT_SECONDARY_THUMB_TOUCH },
{ ovrTouch_A, RIGHT_SECONDARY_THUMB_TOUCH },
{ ovrTouch_B, RIGHT_SECONDARY_THUMB_TOUCH },
{ ovrTouch_LIndexTrigger, LEFT_PRIMARY_INDEX_TOUCH },
{ ovrTouch_RIndexTrigger, RIGHT_PRIMARY_INDEX_TOUCH },
{ ovrTouch_LThumb, LS_TOUCH },
{ ovrTouch_RThumb, RS_TOUCH },
{ ovrTouch_LThumbUp, LEFT_THUMB_UP },
{ ovrTouch_RThumbUp, RIGHT_THUMB_UP },
{ ovrTouch_LIndexPointing, LEFT_INDEX_POINT },
{ ovrTouch_RIndexPointing, RIGHT_INDEX_POINT },
} };
void OculusControllerManager::TouchDevice::update(float deltaTime, const controller::InputCalibrationData& inputCalibrationData, bool jointsCaptured) {
_poseStateMap.clear();
_buttonPressedMap.clear();
if (!jointsCaptured) {
int numTrackedControllers = 0;
static const auto REQUIRED_HAND_STATUS = ovrStatus_OrientationTracked & ovrStatus_PositionTracked;
auto tracking = ovr_GetTrackingState(_parent._session, 0, false);
ovr_for_each_hand([&](ovrHandType hand) {
++numTrackedControllers;
if (REQUIRED_HAND_STATUS == (tracking.HandStatusFlags[hand] & REQUIRED_HAND_STATUS)) {
handlePose(deltaTime, inputCalibrationData, hand, tracking.HandPoses[hand]);
}
});
}
using namespace controller;
// Axes
const auto& inputState = _parent._inputState;
_axisStateMap[LX] = inputState.Thumbstick[ovrHand_Left].x;
_axisStateMap[LY] = inputState.Thumbstick[ovrHand_Left].y;
_axisStateMap[LT] = inputState.IndexTrigger[ovrHand_Left];
_axisStateMap[LG] = inputState.HandTrigger[ovrHand_Left];
_axisStateMap[RX] = inputState.Thumbstick[ovrHand_Right].x;
_axisStateMap[RY] = inputState.Thumbstick[ovrHand_Right].y;
_axisStateMap[RT] = inputState.IndexTrigger[ovrHand_Right];
_axisStateMap[RG] = inputState.HandTrigger[ovrHand_Right];
// Buttons
for (const auto& pair : BUTTON_MAP) {
if (inputState.Buttons & pair.first) {
_buttonPressedMap.insert(pair.second);
}
}
// Touches
for (const auto& pair : TOUCH_MAP) {
if (inputState.Touches & pair.first) {
_buttonPressedMap.insert(pair.second);
}
}
}
void OculusControllerManager::TouchDevice::focusOutEvent() {
_axisStateMap.clear();
_buttonPressedMap.clear();
};
void OculusControllerManager::TouchDevice::handlePose(float deltaTime,
const controller::InputCalibrationData& inputCalibrationData, ovrHandType hand,
const ovrPoseStatef& handPose) {
auto poseId = hand == ovrHand_Left ? controller::LEFT_HAND : controller::RIGHT_HAND;
auto& pose = _poseStateMap[poseId];
pose.translation = toGlm(handPose.ThePose.Position);
pose.rotation = toGlm(handPose.ThePose.Orientation);
pose.angularVelocity = toGlm(handPose.AngularVelocity);
pose.velocity = toGlm(handPose.LinearVelocity);
}
controller::Input::NamedVector OculusControllerManager::TouchDevice::getAvailableInputs() const {
using namespace controller;
QVector<Input::NamedPair> availableInputs{
// Trackpad analogs
makePair(LX, "LX"),
makePair(LY, "LY"),
makePair(RX, "RX"),
makePair(RY, "RY"),
// trigger analogs
makePair(LT, "LT"),
makePair(RT, "RT"),
makePair(LB, "LB"),
makePair(RB, "RB"),
makePair(LS, "LS"),
makePair(RS, "RS"),
makePair(LEFT_HAND, "LeftHand"),
makePair(RIGHT_HAND, "RightHand"),
makePair(LEFT_PRIMARY_THUMB, "LeftPrimaryThumb"),
makePair(LEFT_SECONDARY_THUMB, "LeftSecondaryThumb"),
makePair(RIGHT_PRIMARY_THUMB, "RightPrimaryThumb"),
makePair(RIGHT_SECONDARY_THUMB, "RightSecondaryThumb"),
};
return availableInputs;
}
QString OculusControllerManager::TouchDevice::getDefaultMappingConfig() const {
static const QString MAPPING_JSON = PathUtils::resourcesPath() + "/controllers/touch.json";
return MAPPING_JSON;
}

View file

@ -0,0 +1,81 @@
//
// Created by Bradley Austin Davis on 2016/03/04
// Copyright 2013-2016 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi__OculusControllerManager
#define hifi__OculusControllerManager
#include <QObject>
#include <unordered_set>
#include <GLMHelpers.h>
#include <controllers/InputDevice.h>
#include <plugins/InputPlugin.h>
#include <OVR_CAPI.h>
class OculusControllerManager : public InputPlugin {
Q_OBJECT
public:
// Plugin functions
bool isSupported() const override;
bool isJointController() const override { return true; }
const QString& getName() const override { return NAME; }
bool activate() override;
void deactivate() override;
void pluginFocusOutEvent() override;
void pluginUpdate(float deltaTime, const controller::InputCalibrationData& inputCalibrationData, bool jointsCaptured) override;
private:
class OculusInputDevice : public controller::InputDevice {
public:
OculusInputDevice(OculusControllerManager& parent, const QString& name) : controller::InputDevice(name), _parent(parent) {}
OculusControllerManager& _parent;
friend class OculusControllerManager;
};
class RemoteDevice : public OculusInputDevice {
public:
using Pointer = std::shared_ptr<RemoteDevice>;
RemoteDevice(OculusControllerManager& parent) : OculusInputDevice(parent, "Oculus Remote") {}
controller::Input::NamedVector getAvailableInputs() const override;
QString getDefaultMappingConfig() const override;
void update(float deltaTime, const controller::InputCalibrationData& inputCalibrationData, bool jointsCaptured) override;
void focusOutEvent() override;
friend class OculusControllerManager;
};
class TouchDevice : public OculusInputDevice {
public:
using Pointer = std::shared_ptr<TouchDevice>;
TouchDevice(OculusControllerManager& parent) : OculusInputDevice(parent, "Oculus Touch") {}
controller::Input::NamedVector getAvailableInputs() const override;
QString getDefaultMappingConfig() const override;
void update(float deltaTime, const controller::InputCalibrationData& inputCalibrationData, bool jointsCaptured) override;
void focusOutEvent() override;
private:
void handlePose(float deltaTime, const controller::InputCalibrationData& inputCalibrationData, ovrHandType hand, const ovrPoseStatef& handPose);
int _trackedControllers { 0 };
friend class OculusControllerManager;
};
ovrSession _session { nullptr };
ovrInputState _inputState {};
RemoteDevice::Pointer _remote;
TouchDevice::Pointer _touch;
static const QString NAME;
};
#endif // hifi__OculusControllerManager

View file

@ -10,6 +10,23 @@
#include "OculusHelpers.h"
const QString OculusDisplayPlugin::NAME("Oculus Rift");
static ovrPerfHudMode currentDebugMode = ovrPerfHud_Off;
bool OculusDisplayPlugin::internalActivate() {
bool result = Parent::internalActivate();
currentDebugMode = ovrPerfHud_Off;
if (result && _session) {
ovr_SetInt(_session, OVR_PERF_HUD_MODE, currentDebugMode);
}
return result;
}
void OculusDisplayPlugin::cycleDebugOutput() {
if (_session) {
currentDebugMode = static_cast<ovrPerfHudMode>((currentDebugMode + 1) % ovrPerfHud_Count);
ovr_SetInt(_session, OVR_PERF_HUD_MODE, currentDebugMode);
}
}
void OculusDisplayPlugin::customizeContext() {
Parent::customizeContext();
@ -48,12 +65,6 @@ void blit(const SrcFbo& srcFbo, const DstFbo& dstFbo) {
});
}
void OculusDisplayPlugin::updateFrameData() {
Parent::updateFrameData();
_sceneLayer.RenderPose[ovrEyeType::ovrEye_Left] = ovrPoseFromGlm(_currentRenderEyePoses[Left]);
_sceneLayer.RenderPose[ovrEyeType::ovrEye_Right] = ovrPoseFromGlm(_currentRenderEyePoses[Right]);
}
void OculusDisplayPlugin::hmdPresent() {
PROFILE_RANGE_EX(__FUNCTION__, 0xff00ff00, (uint64_t)_currentRenderFrameIndex)
@ -63,12 +74,15 @@ void OculusDisplayPlugin::hmdPresent() {
}
blit(_compositeFramebuffer, _sceneFbo);
_sceneFbo->Commit();
{
_sceneLayer.SensorSampleTime = _currentPresentFrameInfo.sensorSampleTime;
_sceneLayer.RenderPose[ovrEyeType::ovrEye_Left] = ovrPoseFromGlm(_currentPresentFrameInfo.headPose);
_sceneLayer.RenderPose[ovrEyeType::ovrEye_Right] = ovrPoseFromGlm(_currentPresentFrameInfo.headPose);
ovrLayerHeader* layers = &_sceneLayer.Header;
ovrResult result = ovr_SubmitFrame(_session, _currentRenderFrameIndex, &_viewScaleDesc, &layers, 1);
if (!OVR_SUCCESS(result)) {
logWarning("Failed to present");
}
}
_sceneFbo->Increment();
}

View file

@ -22,12 +22,13 @@ public:
float getTargetFrameRate() override { return TARGET_RATE_Oculus; }
protected:
bool internalActivate() override;
void hmdPresent() override;
// FIXME update with Oculus API call once it's available in the SDK
bool isHmdMounted() const override { return true; }
void customizeContext() override;
void uncustomizeContext() override;
void updateFrameData() override;
void cycleDebugOutput() override;
private:
static const QString NAME;

View file

@ -9,7 +9,10 @@
#include "OculusHelpers.h"
#include <atomic>
#include <QtCore/QLoggingCategory>
#include <QtCore/QFile>
#include <QtCore/QDir>
using Mutex = std::mutex;
using Lock = std::unique_lock<Mutex>;
@ -38,9 +41,23 @@ void logFatal(const char* what) {
qFatal(error.c_str());
}
static const QString OCULUS_RUNTIME_PATH { "C:\\Program Files (x86)\\Oculus\\Support\\oculus-runtime" };
static const QString GOOD_OCULUS_RUNTIME_FILE { OCULUS_RUNTIME_PATH + "\\LibOVRRT64_1.dll" };
bool oculusAvailable() {
ovrDetectResult detect = ovr_Detect(0);
return (detect.IsOculusServiceRunning && detect.IsOculusHMDConnected);
if (!detect.IsOculusServiceRunning || !detect.IsOculusHMDConnected) {
return false;
}
// HACK Explicitly check for the presence of the 1.0 runtime DLL, and fail if it
// doesn't exist
if (!QFile(GOOD_OCULUS_RUNTIME_FILE).exists()) {
qCWarning(oculus) << "Oculus Runtime detected, but no 1.x DLL present: \"" + GOOD_OCULUS_RUNTIME_FILE + "\"";
return false;
}
return true;
}
ovrSession acquireOculusSession() {
@ -98,9 +115,9 @@ SwapFramebufferWrapper::~SwapFramebufferWrapper() {
destroyColor();
}
void SwapFramebufferWrapper::Increment() {
++color->CurrentIndex;
color->CurrentIndex %= color->TextureCount;
void SwapFramebufferWrapper::Commit() {
auto result = ovr_CommitTextureSwapChain(_session, color);
Q_ASSERT(OVR_SUCCESS(result));
}
void SwapFramebufferWrapper::Resize(const uvec2 & size) {
@ -114,7 +131,7 @@ void SwapFramebufferWrapper::Resize(const uvec2 & size) {
void SwapFramebufferWrapper::destroyColor() {
if (color) {
ovr_DestroySwapTextureSet(_session, color);
ovr_DestroyTextureSwapChain(_session, color);
color = nullptr;
}
}
@ -122,13 +139,30 @@ void SwapFramebufferWrapper::destroyColor() {
void SwapFramebufferWrapper::initColor() {
destroyColor();
if (!OVR_SUCCESS(ovr_CreateSwapTextureSetGL(_session, GL_SRGB8_ALPHA8, size.x, size.y, &color))) {
ovrTextureSwapChainDesc desc = {};
desc.Type = ovrTexture_2D;
desc.ArraySize = 1;
desc.Width = size.x;
desc.Height = size.y;
desc.MipLevels = 1;
desc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB;
desc.SampleCount = 1;
desc.StaticImage = ovrFalse;
ovrResult result = ovr_CreateTextureSwapChainGL(_session, &desc, &color);
if (!OVR_SUCCESS(result)) {
logFatal("Failed to create swap textures");
}
for (int i = 0; i < color->TextureCount; ++i) {
ovrGLTexture& ovrTex = (ovrGLTexture&)color->Textures[i];
glBindTexture(GL_TEXTURE_2D, ovrTex.OGL.TexId);
int length = 0;
result = ovr_GetTextureSwapChainLength(_session, color, &length);
if (!OVR_SUCCESS(result) || !length) {
qFatal("Unable to count swap chain textures");
}
for (int i = 0; i < length; ++i) {
GLuint chainTexId;
ovr_GetTextureSwapChainBufferGL(_session, color, i, &chainTexId);
glBindTexture(GL_TEXTURE_2D, chainTexId);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
@ -141,8 +175,11 @@ void SwapFramebufferWrapper::initDone() {
}
void SwapFramebufferWrapper::onBind(oglplus::Framebuffer::Target target) {
ovrGLTexture& tex = (ovrGLTexture&)(color->Textures[color->CurrentIndex]);
glFramebufferTexture2D(toEnum(target), GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex.OGL.TexId, 0);
int curIndex;
ovr_GetTextureSwapChainCurrentIndex(_session, color, &curIndex);
GLuint curTexId;
ovr_GetTextureSwapChainBufferGL(_session, color, curIndex, &curTexId);
glFramebufferTexture2D(toEnum(target), GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, curTexId, 0);
}
void SwapFramebufferWrapper::onUnbind(oglplus::Framebuffer::Target target) {

View file

@ -111,10 +111,10 @@ inline ovrPosef ovrPoseFromGlm(const glm::mat4 & m) {
// then submit it and increment to the next texture.
// The Oculus SDK manages the creation and destruction of
// the textures
struct SwapFramebufferWrapper : public FramebufferWrapper<ovrSwapTextureSet*, void*> {
struct SwapFramebufferWrapper : public FramebufferWrapper<ovrTextureSwapChain, void*> {
SwapFramebufferWrapper(const ovrSession& session);
~SwapFramebufferWrapper();
void Increment();
void Commit();
void Resize(const uvec2 & size);
protected:
void initColor() override final;

View file

@ -18,6 +18,7 @@
#include "OculusDisplayPlugin.h"
#include "OculusDebugDisplayPlugin.h"
#include "OculusControllerManager.h"
class OculusProvider : public QObject, public DisplayProvider, InputProvider
{
@ -51,8 +52,6 @@ public:
}
virtual InputPluginList getInputPlugins() override {
// FIXME pending full oculus input API and hardware
#if 0
static std::once_flag once;
std::call_once(once, [&] {
InputPluginPointer plugin(new OculusControllerManager());
@ -60,7 +59,6 @@ public:
_inputPlugins.push_back(plugin);
}
});
#endif
return _inputPlugins;
}

View file

@ -35,10 +35,14 @@ void OculusLegacyDisplayPlugin::resetSensors() {
ovrHmd_RecenterPose(_hmd);
}
void OculusLegacyDisplayPlugin::updateHeadPose(uint32_t frameIndex) {
void OculusLegacyDisplayPlugin::beginFrameRender(uint32_t frameIndex) {
FrameInfo frame;
frame.predictedDisplayTime = frame.sensorSampleTime = ovr_GetTimeInSeconds();
_trackingState = ovrHmd_GetTrackingState(_hmd, frame.predictedDisplayTime);
frame.headPose = toGlm(_trackingState.HeadPose.ThePose);
_currentRenderFrameInfo.set(frame);
Lock lock(_mutex);
_trackingState = ovrHmd_GetTrackingState(_hmd, ovr_GetTimeInSeconds());
_headPoseCache.set(toGlm(_trackingState.HeadPose.ThePose));
_frameInfos[frameIndex] = frame;
}
bool OculusLegacyDisplayPlugin::isSupported() const {

View file

@ -26,7 +26,7 @@ public:
// Stereo specific methods
virtual void resetSensors() override;
virtual void updateHeadPose(uint32_t frameIndex) override;
virtual void beginFrameRender(uint32_t frameIndex) override;
virtual float getTargetFrameRate() override;

View file

@ -121,22 +121,23 @@ void OpenVrDisplayPlugin::resetSensors() {
_sensorResetMat = glm::inverse(cancelOutRollAndPitch(m));
}
void OpenVrDisplayPlugin::updateHeadPose(uint32_t frameIndex) {
void OpenVrDisplayPlugin::beginFrameRender(uint32_t frameIndex) {
float displayFrequency = _system->GetFloatTrackedDeviceProperty(vr::k_unTrackedDeviceIndex_Hmd, vr::Prop_DisplayFrequency_Float);
float frameDuration = 1.f / displayFrequency;
float vsyncToPhotons = _system->GetFloatTrackedDeviceProperty(vr::k_unTrackedDeviceIndex_Hmd, vr::Prop_SecondsFromVsyncToPhotons_Float);
double displayFrequency = _system->GetFloatTrackedDeviceProperty(vr::k_unTrackedDeviceIndex_Hmd, vr::Prop_DisplayFrequency_Float);
double frameDuration = 1.f / displayFrequency;
double vsyncToPhotons = _system->GetFloatTrackedDeviceProperty(vr::k_unTrackedDeviceIndex_Hmd, vr::Prop_SecondsFromVsyncToPhotons_Float);
FrameInfo frame;
#if THREADED_PRESENT
// 3 frames of prediction + vsyncToPhotons = 44ms total
const float NUM_PREDICTION_FRAMES = 3.0f;
float predictedSecondsFromNow = NUM_PREDICTION_FRAMES * frameDuration + vsyncToPhotons;
const double NUM_PREDICTION_FRAMES = 3.0f;
frame.predictedDisplayTime = NUM_PREDICTION_FRAMES * frameDuration + vsyncToPhotons;
#else
float predictedSecondsFromNow = frameDuration + vsyncToPhotons;
frame.predictedDisplayTime = frameDuration + vsyncToPhotons;
#endif
vr::TrackedDevicePose_t predictedTrackedDevicePose[vr::k_unMaxTrackedDeviceCount];
_system->GetDeviceToAbsoluteTrackingPose(vr::TrackingUniverseStanding, predictedSecondsFromNow, predictedTrackedDevicePose, vr::k_unMaxTrackedDeviceCount);
_system->GetDeviceToAbsoluteTrackingPose(vr::TrackingUniverseStanding, frame.predictedDisplayTime, predictedTrackedDevicePose, vr::k_unMaxTrackedDeviceCount);
// copy and process predictedTrackedDevicePoses
for (int i = 0; i < vr::k_unMaxTrackedDeviceCount; i++) {
@ -145,8 +146,11 @@ void OpenVrDisplayPlugin::updateHeadPose(uint32_t frameIndex) {
_trackedDeviceLinearVelocities[i] = transformVectorFast(_sensorResetMat, toGlm(_trackedDevicePose[i].vVelocity));
_trackedDeviceAngularVelocities[i] = transformVectorFast(_sensorResetMat, toGlm(_trackedDevicePose[i].vAngularVelocity));
}
frame.headPose = _trackedDevicePoseMat4[0];
_currentRenderFrameInfo.set(frame);
_headPoseCache.set(_trackedDevicePoseMat4[0]);
Lock lock(_mutex);
_frameInfos[frameIndex] = frame;
}
void OpenVrDisplayPlugin::hmdPresent() {

View file

@ -27,7 +27,7 @@ public:
// Stereo specific methods
virtual void resetSensors() override;
virtual void updateHeadPose(uint32_t frameIndex) override;
virtual void beginFrameRender(uint32_t frameIndex) override;
protected:
bool internalActivate() override;

View file

@ -1,5 +1,6 @@
Server\ Console-*/
server-console-*/
Sandbox-*/
electron-packager/
npm-debug.log
logs/

View file

@ -23,7 +23,7 @@ add_dependencies(${TARGET_NAME} assignment-client domain-server)
# set the packaged console folder depending on platform, so we can copy it
if (APPLE)
set(PACKAGED_CONSOLE_FOLDER "Server\\ Console-darwin-x64/${CONSOLE_EXEC_NAME}")
set(PACKAGED_CONSOLE_FOLDER "Sandbox-darwin-x64/${CONSOLE_EXEC_NAME}")
elseif (WIN32)
set(PACKAGED_CONSOLE_FOLDER "server-console-win32-x64")
elseif (UNIX)

View file

@ -23,12 +23,12 @@ var options = {
arch: "x64",
platform: platform,
icon: "resources/" + iconName,
ignore: "logs|(S|s)erver(\\s|-)(C|c)onsole-\\S+|electron-packager|README.md|CMakeLists.txt|packager.js|.gitignore"
ignore: "logs|(S|s)erver(\\s|-)(C|c)onsole-\\S+|(S|s)andbox-\\S+|electron-packager|README.md|CMakeLists.txt|packager.js|.gitignore"
}
const EXEC_NAME = "server-console";
const SHORT_NAME = "Server Console";
const FULL_NAME = "High Fidelity Server Console";
const SHORT_NAME = "Sandbox";
const FULL_NAME = "High Fidelity Sandbox";
// setup per OS options
if (osType == "Darwin") {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View file

@ -111,8 +111,8 @@ function shutdown() {
dialog.showMessageBox({
type: 'question',
buttons: ['Yes', 'No'],
title: 'Stopping Server Console',
message: 'Quitting will stop your Server Console and your Home domain will no longer be running.\nDo you wish to continue?'
title: 'Stopping High Fidelity Sandbox',
message: 'Quitting will stop your Sandbox and your Home domain will no longer be running.\nDo you wish to continue?'
}, shutdownCallback);
} else {
shutdownCallback(0);
@ -212,7 +212,7 @@ var shouldQuit = app.makeSingleInstance(function(commandLine, workingDirectory)
});
if (shouldQuit) {
console.warn("Another instance of the Server Console is already running - this instance will quit.");
console.warn("Another instance of the Sandbox is already running - this instance will quit.");
app.quit();
return;
}
@ -237,7 +237,7 @@ function binaryMissingMessage(displayName, executableName, required) {
var message = "The " + displayName + " executable was not found.\n";
if (required) {
message += "It is required for the Server Console to run.\n\n";
message += "It is required for the High Fidelity Sandbox to run.\n\n";
} else {
message += "\n";
}
@ -250,7 +250,7 @@ function binaryMissingMessage(displayName, executableName, required) {
message += paths.join("\n");
} else {
message += "It is expected to be found beside this executable.\n";
message += "You may need to re-install the Server Console.";
message += "You may need to re-install the High Fidelity Sandbox.";
}
return message;
@ -347,134 +347,6 @@ function goHomeClicked() {
}
}
function stackManagerBasePath() {
var dataPath = 'High Fidelity/Stack Manager/resources';
if (process.platform == "win32") {
return path.resolve(osHomeDir(), 'AppData/Local', dataPath);
} else if (process.platform == "darwin") {
return path.resolve(osHomeDir(), 'Library/Application Support', dataPath);
} else {
return ""
}
}
function isStackManagerContentPresent() {
var modelsPath = path.resolve(stackManagerBasePath(), 'models.json.gz');
try {
var stats = fs.lstatSync(modelsPath);
if (stats.isFile()) {
console.log("Stack Manager entities file discovered at " + modelsPath)
// we found a content file
return true;
}
} catch (e) {
console.log("Stack Manager entities file not found at " + modelsPath);
}
}
function promptToMigrateContent() {
dialog.showMessageBox({
type: 'question',
buttons: ['Yes', 'No'],
title: 'Migrate Content',
message: 'Are you sure?\n\nThis will stop your home server and replace everything in your home with your content from Stack Manager.'
}, function(index) {
if (index == 0) {
if (homeServer.state != ProcessGroupStates.STOPPED) {
var stopThenMigrateCallback = function(processGroup) {
if (isShuttingDown) {
homeServer.removeListener('state-update', stopThenMigrateCallback);
} else if (processGroup.state == ProcessGroupStates.STOPPED) {
performContentMigration();
homeServer.removeListener('state-update', stopThenMigrateCallback);
}
};
homeServer.on('state-update', stopThenMigrateCallback);
homeServer.stop();
} else {
performContentMigration();
}
}
});
}
function performContentMigration() {
// check if there is a models file to migrate
var modelsPath = path.resolve(stackManagerBasePath(), 'models.json.gz');
try {
var stats = fs.lstatSync(modelsPath);
} catch (e) {
// no entities file
dialog.showMessageBox({
type: 'info',
buttons: ['OK'],
title: 'Models File Not Found',
message: 'There is no models file at ' + modelsPath + '\n\nStack Manager content migration can not proceed.'
}, null);
return;
}
function showMigrationCompletionDialog(copyError) {
if (!copyError) {
// show message for successful migration
dialog.showMessageBox({
type: 'info',
buttons: ['OK'],
title: 'Migration Complete',
message: 'Your Stack Manager content has been migrated.\n\nYour home server will now be restarted.'
}, null);
} else {
// show error message for copy fail
dialog.showMessageBox({
type: 'info',
buttons: ['OK'],
title: 'Migration Failed',
message: 'There was an error copying your Stack Manager content: ' + copyError + '\n\nPlease try again.'
}, null);
}
}
// we have a models file, try and copy it
var newModelsPath = path.resolve(getAssignmentClientResourcesDirectory(), 'entities/models.json.gz')
console.log("Copying Stack Manager entity file from " + modelsPath + " to " + newModelsPath);
try {
fs.copySync(modelsPath, newModelsPath);
// check if there are any assets to copy
var oldAssetsPath = path.resolve(stackManagerBasePath(), 'assets');
var assets = fs.readdirSync(oldAssetsPath);
if (assets.length > 0) {
// assume this means the directory is not empty
// and that we should copy it
var newAssetsPath = path.resolve(getAssignmentClientResourcesDirectory(), 'assets');
console.log("Copying Stack Manager assets from " + oldAssetsPath + " to " + newAssetsPath);
// attempt to copy the assets folder
fs.copySync(oldAssetsPath, newAssetsPath, {
preserveTimestamps: true
});
}
showMigrationCompletionDialog(null);
} catch (error) {
showMigrationCompletionDialog(error);
}
homeServer.start();
}
var logWindow = null;
var labels = {
@ -530,12 +402,6 @@ var labels = {
shell.openExternal('http://localhost:40100/settings/?action=share')
}
},
migrateContent: {
label: 'Migrate Stack Manager Content',
click: function() {
promptToMigrateContent();
}
},
shuttingDown: {
label: "Shutting down...",
enabled: false
@ -569,13 +435,6 @@ function buildMenuArray(serverState) {
menuArray.push(labels.share);
menuArray.push(separator);
menuArray.push(labels.quit);
var foundStackManagerContent = isStackManagerContentPresent();
if (foundStackManagerContent) {
// add a separator and the stack manager content migration option
menuArray.splice(menuArray.length - 1, 0, labels.migrateContent, separator);
}
}
@ -724,7 +583,7 @@ function maybeShowSplash() {
var window = new BrowserWindow({
icon: appIcon,
width: 1600 * zoomFactor,
height: 737 * zoomFactor,
height: 650 * zoomFactor,
center: true,
frame: true,
useContentSize: true,
@ -770,7 +629,7 @@ app.on('ready', function() {
// Create tray icon
tray = new Tray(trayIcons[ProcessGroupStates.STOPPED]);
tray.setToolTip('High Fidelity Server Console');
tray.setToolTip('High Fidelity Sandbox');
tray.on('click', function() {
tray.popUpContextMenu(tray.menu);

View file

@ -122,11 +122,6 @@ h2 {
#main-content {
height: 350px;
border-bottom: 2px solid #F5F6F6;
}
#existing-resources-area {
padding-top: 20px;
}
.footer {
@ -143,4 +138,4 @@ h2 {
input[type="checkbox"] {
-webkit-transform: scale(1.4);
display: inline-block;
}
}

View file

@ -23,7 +23,7 @@ High Fidelity is now installed and your Home domain is ready for you to explore.
</p>
<p>
You can make your home yours by uploading your own models and scripts, and adding items from the Market.
You can make your home yours by uploading your own models and scripts.
</p>
@ -67,12 +67,6 @@ You can make your home yours by uploading your own models and scripts, and addin
</script>
</div>
</div>
<div id="existing-resources-area">
<p>
<h2>Your existing Stack Manager content is safe.</h2>
Server Console comes with demo content but does not overwrite your data. <a target="_blank" href="https://docs.highfidelity.com/v1.0/docs/migrate-sm-to-sc">See our guide to importing content previously managed with Stack Manager</a>.
</p>
</div>
</div>
<div class="bottom">
<div class="content footer">

View file

@ -795,3 +795,35 @@ void OctreeTests::modelItemTests() {
#endif
}
void OctreeTests::elementAddChildTests() {
EntityTreePointer tree = std::make_shared<EntityTree>();
auto elem = tree->createNewElement();
QCOMPARE((bool)elem->getChildAtIndex(0), false);
elem->addChildAtIndex(0);
QCOMPARE((bool)elem->getChildAtIndex(0), true);
const int MAX_CHILD_INDEX = 8;
for (int i = 0; i < MAX_CHILD_INDEX; i++) {
for (int j = 0; j < MAX_CHILD_INDEX; j++) {
auto e = tree->createNewElement();
// add a single child.
auto firstChild = e->addChildAtIndex(i);
QCOMPARE(e->getChildAtIndex(i), firstChild);
if (i != j) {
// add a second child.
auto secondChild = e->addChildAtIndex(j);
QCOMPARE(e->getChildAtIndex(i), firstChild);
QCOMPARE(e->getChildAtIndex(j), secondChild);
// remove scecond child.
e->removeChildAtIndex(j);
QCOMPARE((bool)e->getChildAtIndex(j), false);
}
QCOMPARE(e->getChildAtIndex(i), firstChild);
}
}
}

View file

@ -25,6 +25,8 @@ private slots:
// This test is fine
void modelItemTests();
void elementAddChildTests();
// TODO: Break these into separate test functions
};