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

This commit is contained in:
samcake 2015-12-09 16:58:56 -08:00
commit f9269523a1
61 changed files with 785 additions and 643 deletions

View file

@ -221,3 +221,36 @@ if (HIFI_MEMORY_DEBUGGING)
MESSAGE("-- Memory debugging is enabled")
endif (UNIX)
endif ()
include_application_version()
if (DEFINED DEPLOY_PACKAGE AND DEPLOY_PACKAGE)
message(STATUS "+++++ Package for deployment will be generated on this build +++++")
file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/full-stack-deployment)
set(ICONPATH_INTERFACE "$INSTDIR/${PATH_INSTALL_DATA}/interface.ico")
set(ICONPATH_STACK_MANAGER "$INSTDIR/${PATH_INSTALL_DATA}/stack-manager.ico")
string(REPLACE "/" "\\\\" ICONPATH_INTERFACE ${ICONPATH_INTERFACE})
string(REPLACE "/" "\\\\" ICONPATH_STACK_MANAGER ${ICONPATH_STACK_MANAGER})
set(CPACK_PACKAGE_NAME "High Fidelity")
set(CPACK_PACKAGE_VENDOR "High Fidelity, Inc")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "High Fidelity Interface and Stack")
set(CPACK_PACKAGE_VERSION "${BUILD_SEQ}")
set(CPACK_PACKAGE_VERSION_MAJOR "${BUILD_SEQ}")
set(CPACK_PACKAGE_VERSION_MINOR "0")
set(CPACK_PACKAGE_VERSION_PATCH "0")
set(CPACK_PACKAGE_INSTALL_DIRECTORY "High Fidelity-${BUILD_SEQ}")
set(CPACK_NSIS_EXECUTABLES_DIRECTORY ".")
set(CPACK_PACKAGE_EXECUTABLES
stack-manager "Stack Manager"
interface "Interface"
)
if (WIN32)
install(DIRECTORY ${CMAKE_BINARY_DIR}/full-stack-deployment/ DESTINATION "./")
endif (WIN32)
include(CPack)
endif ()

View file

@ -11,3 +11,4 @@ link_hifi_libraries(
include_application_version()
package_libraries_for_deployment()
consolidate_stack_components()

View file

@ -0,0 +1,27 @@
macro(CONSOLIDATE_STACK_COMPONENTS)
if (DEFINED DEPLOY_PACKAGE AND DEPLOY_PACKAGE AND WIN32)
# Copy all the output for this target into the common deployment location
add_custom_command(
TARGET ${TARGET_NAME} POST_BUILD
COMMAND "${CMAKE_COMMAND}" -E copy_directory $<TARGET_FILE_DIR:${TARGET_NAME}> ${CMAKE_BINARY_DIR}/full-stack-deployment
)
# Copy icon files for interface and stack manager
if (TARGET_NAME STREQUAL "interface" OR TARGET_NAME STREQUAL "stack-manager")
if (TARGET_NAME STREQUAL "interface")
set (ICON_FILE_PATH "${PROJECT_SOURCE_DIR}/icon/interface.ico")
set (ICON_DESTINATION_NAME "interface.ico")
elseif (TARGET_NAME STREQUAL "stack-manager")
set (ICON_FILE_PATH "${PROJECT_SOURCE_DIR}/assets/icon.ico")
set (ICON_DESTINATION_NAME "stack-manager.ico")
endif ()
add_custom_command(
TARGET ${TARGET_NAME} POST_BUILD
COMMAND "${CMAKE_COMMAND}" -E copy ${ICON_FILE_PATH} ${CMAKE_BINARY_DIR}/full-stack-deployment/${ICON_DESTINATION_NAME}
)
endif ()
endif ()
endmacro()

View file

@ -10,10 +10,15 @@
#
macro(INCLUDE_APPLICATION_VERSION)
#
# We are relying on Jenkins defined environment variables to determine the origin of this build
# and will only package if this is a PR or Release build
if (DEFINED ENV{JOB_ID})
set (DEPLOY_PACKAGE 1)
set (BUILD_SEQ $ENV{JOB_ID})
elseif (DEFINED ENV{ghprbPullId})
set (BUILD_SEQ "PR: $ENV{ghprbPullId} - Commit: $ENV{ghprbActualCommit}")
set (DEPLOY_PACKAGE 1)
set (BUILD_SEQ "PR-$ENV{ghprbPullId}")
else ()
set(BUILD_SEQ "dev")
endif ()

View file

@ -1,5 +1,5 @@
#
# CopyDllsBesideWindowsExecutable.cmake
# PackageLibrariesForDeployment.cmake
# cmake/macros
#
# Copyright 2015 High Fidelity, Inc.

View file

@ -107,7 +107,7 @@ if (WIN32 AND NOT CYGWIN)
select_library_configurations(SSL_EAY)
set(OPENSSL_LIBRARIES ${SSL_EAY_LIBRARY} ${LIB_EAY_LIBRARY})
find_path(OPENSSL_DLL_PATH NAMES ssleay32.dll PATH_SUFFIXES "bin" ${_OPENSSL_ROOT_HINTS_AND_PATHS})
elseif (MINGW)
@ -252,6 +252,15 @@ endif ()
if (WIN32)
add_paths_to_fixup_libs(${OPENSSL_DLL_PATH})
#
# For some reason fixup misses the following DLL and only copies libeay32. There's gotta be a better way to handle this
# but for now resorting to the following interm solution
if (DEFINED DEPLOY_PACKAGE AND DEPLOY_PACKAGE)
add_custom_command(
TARGET ${TARGET_NAME} POST_BUILD
COMMAND "${CMAKE_COMMAND}" -E copy ${OPENSSL_DLL_PATH}/ssleay32.dll ${CMAKE_BINARY_DIR}/full-stack-deployment/
)
endif ()
endif ()
mark_as_advanced(OPENSSL_INCLUDE_DIR OPENSSL_LIBRARIES OPENSSL_SEARCH_DIRS)

View file

@ -53,4 +53,4 @@ else()
endif()
file(GLOB RUNTIME_PLUGINS "${BUNDLE_PLUGIN_DIR}/*.${PLUGIN_EXTENSION}")
fixup_bundle("${BUNDLE_EXECUTABLE}" "${RUNTIME_PLUGINS}" "@FIXUP_LIBS@")
fixup_bundle("${BUNDLE_EXECUTABLE}" "${RUNTIME_PLUGINS}" "@FIXUP_LIBS@")

View file

@ -38,3 +38,4 @@ endif (UNIX)
include_application_version()
package_libraries_for_deployment()
consolidate_stack_components()

View file

@ -226,6 +226,7 @@
var elRescaleDimensionsButton = document.getElementById("dimension-rescale-button");
var elParentID = document.getElementById("property-parent-id");
var elParentJointIndex = document.getElementById("property-parent-joint-index");
var elRegistrationX = document.getElementById("property-reg-x");
var elRegistrationY = document.getElementById("property-reg-y");
@ -456,6 +457,7 @@
elDimensionsZ.value = properties.dimensions.z.toFixed(2);
elParentID.value = properties.parentID;
elParentJointIndex.value = properties.parentJointIndex;
elRegistrationX.value = properties.registrationPoint.x.toFixed(2);
elRegistrationY.value = properties.registrationPoint.y.toFixed(2);
@ -671,6 +673,7 @@
elDimensionsZ.addEventListener('change', dimensionsChangeFunction);
elParentID.addEventListener('change', createEmitTextPropertyUpdateFunction('parentID'));
elParentJointIndex.addEventListener('change', createEmitNumberPropertyUpdateFunction('parentJointIndex'));
var registrationChangeFunction = createEmitVec3PropertyUpdateFunction(
'registrationPoint', elRegistrationX, elRegistrationY, elRegistrationZ);
@ -1067,6 +1070,12 @@
<input type="text" id="property-parent-id">
</div>
</div>
<div class="property">
<span class="label" style="float: left; margin-right: 6px">ParentJointIndex</span>
<div class="value" style="overflow: hidden;">
<input type="text" id="property-parent-joint-index">
</div>
</div>
<div class="property">
<div class="label">Registration</div>

View file

@ -12,31 +12,57 @@
Script.include("cookies.js");
var audioOptions = new AudioEffectOptions({
maxRoomSize: 50,
bandwidth: 10000,
preDelay: 20,
lateDelay: 0,
reverbTime: 2,
earlyDiffusion: 100,
lateDiffusion: 100,
roomSize: 50,
reverbTime: 4,
damping: 0.50,
inputBandwidth: 0.8,
earlyLevel: 0,
tailLevel: 0,
dryLevel: -6,
wetLevel: -6
density: 100,
bassMult: 1.5,
bassFreq: 250,
highGain: -6,
highFreq: 3000,
modRate: 2.3,
modDepth: 50,
earlyGain: 0,
lateGain: 0,
earlyMixLeft: 20,
earlyMixRight: 20,
lateMixLeft: 90,
lateMixRight: 90,
wetDryMix: 50,
});
AudioDevice.setReverbOptions(audioOptions);
AudioDevice.setReverb(true);
print("Reverb is ON.");
var panel = new Panel(10, 200);
var panel = new Panel(10, 160);
var parameters = [
{ name: "roomSize", min: 0, max: 100, units: " feet" },
{ name: "reverbTime", min: 0, max: 10, units: " sec" },
{ name: "damping", min: 0, max: 1, units: " " },
{ name: "inputBandwidth", min: 0, max: 1, units: " " },
{ name: "earlyLevel", min: -48, max: 0, units: " dB" },
{ name: "tailLevel", min: -48, max: 0, units: " dB" },
{ name: "wetLevel", min: -48, max: 0, units: " dB" },
{ name: "bandwidth", min: 1000, max: 12000, units: " Hz" },
{ name: "preDelay", min: 0, max: 333, units: " ms" },
{ name: "lateDelay", min: 0, max: 166, units: " ms" },
{ name: "reverbTime", min: 0.1, max: 10, units: " seconds" },
{ name: "earlyDiffusion", min: 0, max: 100, units: " percent" },
{ name: "lateDiffusion", min: 0, max: 100, units: " percent" },
{ name: "roomSize", min: 0, max: 100, units: " percent" },
{ name: "density", min: 0, max: 100, units: " percent" },
{ name: "bassMult", min: 0.1, max: 4, units: " ratio" },
{ name: "bassFreq", min: 10, max: 500, units: " Hz" },
{ name: "highGain", min: -24, max: 0, units: " dB" },
{ name: "highFreq", min: 1000, max: 12000, units: " Hz" },
{ name: "modRate", min: 0.1, max: 10, units: " Hz" },
{ name: "modDepth", min: 0, max: 100, units: " percent" },
{ name: "earlyGain", min: -96, max: 24, units: " dB" },
{ name: "lateGain", min: -96, max: 24, units: " dB" },
{ name: "earlyMixLeft", min: 0, max: 100, units: " percent" },
{ name: "earlyMixRight", min: 0, max: 100, units: " percent" },
{ name: "lateMixLeft", min: 0, max: 100, units: " percent" },
{ name: "lateMixRight", min: 0, max: 100, units: " percent" },
{ name: "wetDryMix", min: 0, max: 100, units: " percent" },
]
function setter(name) {
@ -48,7 +74,7 @@ function getter(name) {
}
function displayer(units) {
return function(value) { return (value).toFixed(1) + units; };
return function(value) { return (value).toFixed(1) + units; }
}
// create a slider for each parameter

View file

@ -194,7 +194,6 @@ else (APPLE)
# link target to external libraries
if (WIN32)
# target_link_libraries(${TARGET_NAME} wsock32.lib Winmm.lib)
target_link_libraries(${TARGET_NAME} wsock32.lib Winmm.lib)
else (WIN32)
# Nothing else required on linux apparently
@ -202,3 +201,4 @@ else (APPLE)
endif (APPLE)
package_libraries_for_deployment()
consolidate_stack_components()

View file

@ -195,6 +195,8 @@ static const QString INFO_EDIT_ENTITIES_PATH = "html/edit-commands.html";
static const unsigned int THROTTLED_SIM_FRAMERATE = 15;
static const int THROTTLED_SIM_FRAME_PERIOD_MS = MSECS_PER_SECOND / THROTTLED_SIM_FRAMERATE;
static const float PHYSICS_READY_RANGE = 3.0f; // how far from avatar to check for entities that aren't ready for simulation
#ifndef __APPLE__
static const QString DESKTOP_LOCATION = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
#else
@ -1122,29 +1124,6 @@ void Application::paintGL() {
_inPaint = true;
Finally clearFlagLambda([this] { _inPaint = false; });
// Some LOD-like controls need to know a smoothly varying "potential" frame rate that doesn't
// include time waiting for vsync, and which can report a number above target if we've got the headroom.
// For example, if we're shooting for 75fps and paintWait is 3.3333ms (= 75% * 13.33ms), our deducedNonVSyncFps
// would be 100fps. In principle, a paintWait of zero would have deducedNonVSyncFps=75.
// Here we make a guess for deducedNonVSyncFps = 1 / deducedNonVSyncPeriod.
//
// Time between previous paintGL call and this one, which can vary not only with vSync misses, but also with QT timing.
// We're using this as a proxy for the time between vsync and displayEnd, below. (Not exact, but tends to be the same over time.)
// This is not the same as update(deltaTime), because the latter attempts to throttle to 60hz and also clamps to 1/4 second.
const float actualPeriod = diff / (float)USECS_PER_SECOND; // same as 1/instantaneousFps but easier for compiler to optimize
// Note that _lastPaintWait (stored at end of last call) is for the same paint cycle.
float deducedNonVSyncPeriod = actualPeriod - _lastPaintWait + _marginForDeducedFramePeriod; // plus a some non-zero time for machinery we can't measure
// We don't know how much time to allow for that, but if we went over the target period, we know it's at least the portion
// of paintWait up to the next vSync. This gives us enough of a penalty so that when actualPeriod crosses two cycles,
// the key part (and not an exagerated part) of _lastPaintWait is accounted for.
const float targetPeriod = getTargetFramePeriod();
if (_lastPaintWait > EPSILON && actualPeriod > targetPeriod) {
// Don't use C++ remainder(). It's authors are mathematically insane.
deducedNonVSyncPeriod += fmod(actualPeriod, _lastPaintWait);
}
_lastDeducedNonVSyncFps = 1.0f / deducedNonVSyncPeriod;
_lastInstantaneousFps = instantaneousFps;
auto displayPlugin = getActiveDisplayPlugin();
// FIXME not needed anymore?
_offscreenContext->makeCurrent();
@ -1401,7 +1380,6 @@ void Application::paintGL() {
Q_ASSERT(!_lockedFramebufferMap.contains(finalTexture));
_lockedFramebufferMap[finalTexture] = scratchFramebuffer;
uint64_t displayStart = usecTimestampNow();
Q_ASSERT(isCurrentContext(_offscreenContext->getContext()));
{
PROFILE_RANGE(__FUNCTION__ "/pluginSubmitScene");
@ -1410,9 +1388,6 @@ void Application::paintGL() {
}
Q_ASSERT(isCurrentContext(_offscreenContext->getContext()));
uint64_t displayEnd = usecTimestampNow();
const float displayPeriodUsec = (float)(displayEnd - displayStart); // usecs
_lastPaintWait = displayPeriodUsec / (float)USECS_PER_SECOND;
}
{
@ -1423,6 +1398,14 @@ void Application::paintGL() {
batch.resetStages();
});
}
// Some LOD-like controls need to know a smoothly varying "potential" frame rate that doesn't
// include time waiting for sync, and which can report a number above target if we've got the headroom.
// In my tests, the following is mostly less than 0.5ms, and never more than 3ms. I don't think its worth measuring during runtime.
const float paintWaitAndQTTimerAllowance = 0.001f; // seconds
// Store both values now for use by next cycle.
_lastInstantaneousFps = instantaneousFps;
_lastUnsynchronizedFps = 1.0f / (((usecTimestampNow() - now) / (float)USECS_PER_SECOND) + paintWaitAndQTTimerAllowance);
}
void Application::runTests() {
@ -2419,6 +2402,9 @@ bool Application::exportEntities(const QString& filename, const QVector<EntityIt
exportTree->addEntity(entityItem->getEntityItemID(), properties);
}
// remap IDs on export so that we aren't publishing the IDs of entities in our domain
exportTree->remapIDs();
exportTree->writeToJSONFile(filename.toLocal8Bit().constData());
// restore the main window's active state
@ -2441,6 +2427,10 @@ bool Application::exportEntities(const QString& filename, float x, float y, floa
properties.setPosition(properties.getPosition() - root);
exportTree->addEntity(id, properties);
}
// remap IDs on export so that we aren't publishing the IDs of entities in our domain
exportTree->remapIDs();
exportTree->writeToSVOFile(filename.toLocal8Bit().constData());
} else {
qCDebug(interfaceapp) << "No models were selected";
@ -2485,6 +2475,7 @@ bool Application::importEntities(const QString& urlOrFilename) {
bool success = _entityClipboard->readFromURL(url.toString());
if (success) {
_entityClipboard->remapIDs();
_entityClipboard->reaverageOctreeElements();
}
return success;
@ -2897,7 +2888,7 @@ void Application::update(float deltaTime) {
_avatarUpdate->synchronousProcess();
{
if (true || _physicsEnabled) {
PerformanceTimer perfTimer("physics");
static VectorOfMotionStates motionStates;
@ -3778,6 +3769,8 @@ void Application::domainChanged(const QString& domainHostname) {
updateWindowTitle();
clearDomainOctreeDetails();
_domainConnectionRefusals.clear();
// disable physics until we have enough information about our new location to not cause craziness.
_physicsEnabled = false;
}
void Application::handleDomainConnectionDeniedPacket(QSharedPointer<ReceivedMessage> message) {
@ -3885,6 +3878,31 @@ void Application::trackIncomingOctreePacket(ReceivedMessage& message, SharedNode
}
}
bool Application::nearbyEntitiesAreReadyForPhysics() {
// this is used to avoid the following scenario:
// A table has some items sitting on top of it. The items are at rest, meaning they aren't active in bullet.
// Someone logs in close to the table. They receive information about the items on the table before they
// receive information about the table. The items are very close to the avatar's capsule, so they become
// activated in bullet. This causes them to fall to the floor, because the table's shape isn't yet in bullet.
EntityTreePointer entityTree = _entities.getTree();
if (!entityTree) {
return false;
}
QVector<EntityItemPointer> entities;
entityTree->withReadLock([&] {
AABox box(getMyAvatar()->getPosition() - glm::vec3(PHYSICS_READY_RANGE), glm::vec3(2 * PHYSICS_READY_RANGE));
entityTree->findEntities(box, entities);
});
foreach (EntityItemPointer entity, entities) {
if (!entity->isReadyToComputeShape()) {
return false;
}
}
return true;
}
int Application::processOctreeStats(ReceivedMessage& message, SharedNodePointer sendingNode) {
// But, also identify the sender, and keep track of the contained jurisdiction root for this server
@ -3930,7 +3948,12 @@ int Application::processOctreeStats(ReceivedMessage& message, SharedNodePointer
});
});
if (!_physicsEnabled && nearbyEntitiesAreReadyForPhysics()) {
// These stats packets are sent in between full sends of a scene.
// We keep physics disabled until we've recieved a full scene and everything near the avatar in that
// scene is ready to compute its collision shape.
_physicsEnabled = true;
}
return statsMessageLength;
}

View file

@ -163,11 +163,8 @@ public:
float const HMD_TARGET_FRAME_RATE = 75.0f;
float const DESKTOP_TARGET_FRAME_RATE = 60.0f;
float getTargetFrameRate() { return isHMDMode() ? HMD_TARGET_FRAME_RATE : DESKTOP_TARGET_FRAME_RATE; }
float getTargetFramePeriod() { return isHMDMode() ? 1.0f / HMD_TARGET_FRAME_RATE : 1.0f / DESKTOP_TARGET_FRAME_RATE; } // same as 1/getTargetFrameRate, but w/compile-time division
float getLastInstanteousFps() const { return _lastInstantaneousFps; }
float getLastPaintWait() const { return _lastPaintWait; };
float getLastDeducedNonVSyncFps() const { return _lastDeducedNonVSyncFps; }
void setMarginForDeducedFramePeriod(float newValue) { _marginForDeducedFramePeriod = newValue; }
float getLastUnsynchronizedFps() const { return _lastUnsynchronizedFps; }
float getFieldOfView() { return _fieldOfView.get(); }
void setFieldOfView(float fov);
@ -395,6 +392,7 @@ private:
bool importSVOFromURL(const QString& urlString);
bool nearbyEntitiesAreReadyForPhysics();
int processOctreeStats(ReceivedMessage& message, SharedNodePointer sendingNode);
void trackIncomingOctreePacket(ReceivedMessage& message, SharedNodePointer sendingNode, bool wasStatsPacket);
@ -442,9 +440,7 @@ private:
QElapsedTimer _timerStart;
QElapsedTimer _lastTimeUpdated;
float _lastInstantaneousFps { 0.0f };
float _lastPaintWait { 0.0f };
float _lastDeducedNonVSyncFps { 0.0f };
float _marginForDeducedFramePeriod{ 0.002f }; // 2ms, adjustable
float _lastUnsynchronizedFps { 0.0f };
ShapeManager _shapeManager;
PhysicalEntitySimulation _entitySimulation;
@ -564,6 +560,7 @@ private:
bool _isForeground = true; // starts out assumed to be in foreground
bool _inPaint = false;
bool _isGLInitialized { false };
bool _physicsEnabled { false };
};
#endif // hifi_Application_h

View file

@ -201,6 +201,7 @@ void Avatar::simulate(float deltaTime) {
_skeletonModel.getRig()->copyJointsFromJointData(_jointData);
_skeletonModel.simulate(deltaTime, _hasNewJointRotations || _hasNewJointTranslations);
simulateAttachments(deltaTime);
locationChanged(); // joints changed, so if there are any children, update them.
_hasNewJointRotations = false;
_hasNewJointTranslations = false;
}
@ -868,6 +869,17 @@ glm::vec3 Avatar::getJointTranslation(int index) const {
return translation;
}
glm::quat Avatar::getAbsoluteJointRotationInObjectFrame(int index) const {
glm::quat rotation;
_skeletonModel.getAbsoluteJointRotationInRigFrame(index, rotation);
return Quaternions::Y_180 * rotation;
}
glm::vec3 Avatar::getAbsoluteJointTranslationInObjectFrame(int index) const {
glm::vec3 translation;
_skeletonModel.getAbsoluteJointTranslationInRigFrame(index, translation);
return Quaternions::Y_180 * translation;
}
int Avatar::getJointIndex(const QString& name) const {
if (QThread::currentThread() != thread()) {
@ -1145,12 +1157,12 @@ glm::quat Avatar::getRightPalmRotation() {
return rightRotation;
}
void Avatar::setPosition(const glm::vec3 position) {
void Avatar::setPosition(const glm::vec3& position) {
AvatarData::setPosition(position);
updateAttitude();
}
void Avatar::setOrientation(const glm::quat orientation) {
void Avatar::setOrientation(const glm::quat& orientation) {
AvatarData::setOrientation(orientation);
updateAttitude();
}

View file

@ -108,6 +108,9 @@ public:
virtual int getJointIndex(const QString& name) const;
virtual QStringList getJointNames() const;
virtual glm::quat getAbsoluteJointRotationInObjectFrame(int index) const override;
virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const override;
virtual void setFaceModelURL(const QUrl& faceModelURL);
virtual void setSkeletonModelURL(const QUrl& skeletonModelURL);
virtual void setAttachmentData(const QVector<AttachmentData>& attachmentData);
@ -155,8 +158,8 @@ public:
void setMotionState(AvatarMotionState* motionState) { _motionState = motionState; }
AvatarMotionState* getMotionState() { return _motionState; }
virtual void setPosition(glm::vec3 position);
virtual void setOrientation(glm::quat orientation);
virtual void setPosition(const glm::vec3& position) override;
virtual void setOrientation(const glm::quat& orientation) override;
public slots:

View file

@ -111,7 +111,6 @@ void AvatarManager::init() {
_renderDistanceController.setKP(0.0008f); // Usually about 0.6 of largest that doesn't oscillate when other parameters 0.
_renderDistanceController.setKI(0.0006f); // Big enough to bring us to target with the above KP.
_renderDistanceController.setKD(0.000001f); // A touch of kd increases the speed by which we get there.
}
void AvatarManager::updateMyAvatar(float deltaTime) {
@ -151,7 +150,7 @@ void AvatarManager::updateOtherAvatars(float deltaTime) {
// The measured value is frame rate. When the controlled value (1 / render cutoff distance)
// goes up, the render cutoff distance gets closer, the number of rendered avatars is less, and frame rate
// goes up.
const float deduced = qApp->getLastDeducedNonVSyncFps();
const float deduced = qApp->getLastUnsynchronizedFps();
const float distance = 1.0f / _renderDistanceController.update(deduced, deltaTime);
_renderDistanceAverage.updateAverage(distance);
_renderDistance = _renderDistanceAverage.getAverage();

View file

@ -622,7 +622,8 @@ QScriptValue WindowScriptingInterface::showBrowse(const QString& title, const QS
fileDialog.setAcceptMode(acceptMode);
QUrl fileUrl(directory);
if (acceptMode == QFileDialog::AcceptSave) {
fileDialog.setFileMode(QFileDialog::Directory);
// TODO -- Setting this breaks the dialog on Linux. Does it help something on other platforms?
// fileDialog.setFileMode(QFileDialog::Directory);
fileDialog.selectFile(fileUrl.fileName());
}
if (fileDialog.exec()) {

View file

@ -374,6 +374,16 @@ bool Rig::getJointRotation(int jointIndex, glm::quat& rotation) const {
}
}
bool Rig::getAbsoluteJointRotationInRigFrame(int jointIndex, glm::quat& rotation) const {
QReadLocker readLock(&_externalPoseSetLock);
if (jointIndex >= 0 && jointIndex < (int)_externalPoseSet._absolutePoses.size()) {
rotation = _externalPoseSet._absolutePoses[jointIndex].rot;
return true;
} else {
return false;
}
}
bool Rig::getJointTranslation(int jointIndex, glm::vec3& translation) const {
QReadLocker readLock(&_externalPoseSetLock);
if (jointIndex >= 0 && jointIndex < (int)_externalPoseSet._relativePoses.size()) {
@ -384,6 +394,16 @@ bool Rig::getJointTranslation(int jointIndex, glm::vec3& translation) const {
}
}
bool Rig::getAbsoluteJointTranslationInRigFrame(int jointIndex, glm::vec3& translation) const {
QReadLocker readLock(&_externalPoseSetLock);
if (jointIndex >= 0 && jointIndex < (int)_externalPoseSet._absolutePoses.size()) {
translation = _externalPoseSet._absolutePoses[jointIndex].trans;
return true;
} else {
return false;
}
}
bool Rig::getJointCombinedRotation(int jointIndex, glm::quat& result, const glm::quat& rotation) const {
// AJT: TODO: used by attachments
ASSERT(false);

View file

@ -129,10 +129,12 @@ public:
// geometry space (thread-safe)
bool getJointRotation(int jointIndex, glm::quat& rotation) const;
// geometry space (thread-safe)
bool getJointTranslation(int jointIndex, glm::vec3& translation) const;
// rig space (thread-safe)
bool getAbsoluteJointRotationInRigFrame(int jointIndex, glm::quat& rotation) const;
bool getAbsoluteJointTranslationInRigFrame(int jointIndex, glm::vec3& translation) const;
// legacy
bool getJointCombinedRotation(int jointIndex, glm::quat& result, const glm::quat& rotation) const;

View file

@ -541,26 +541,40 @@ bool AudioClient::switchOutputToAudioDevice(const QString& outputDeviceName) {
void AudioClient::configureReverb() {
ReverbParameters p;
_listenerReverb.getParameters(&p);
// for now, reuse the gverb parameters
p.sampleRate = _outputFormat.sampleRate();
p.roomSize = _reverbOptions->getRoomSize();
p.bandwidth = _reverbOptions->getBandwidth();
p.preDelay = _reverbOptions->getPreDelay();
p.lateDelay = _reverbOptions->getLateDelay();
p.reverbTime = _reverbOptions->getReverbTime();
p.highGain = -24.0f * (1.0f - _reverbOptions->getDamping());
p.bandwidth = 10000.0f * _reverbOptions->getInputBandwidth();
p.earlyGain = _reverbOptions->getEarlyLevel();
p.lateGain = _reverbOptions->getTailLevel();
p.wetDryMix = 100.0f * powf(10.0f, _reverbOptions->getWetLevel() * (1/20.0f));
p.earlyDiffusion = _reverbOptions->getEarlyDiffusion();
p.lateDiffusion = _reverbOptions->getLateDiffusion();
p.roomSize = _reverbOptions->getRoomSize();
p.density = _reverbOptions->getDensity();
p.bassMult = _reverbOptions->getBassMult();
p.bassFreq = _reverbOptions->getBassFreq();
p.highGain = _reverbOptions->getHighGain();
p.highFreq = _reverbOptions->getHighFreq();
p.modRate = _reverbOptions->getModRate();
p.modDepth = _reverbOptions->getModDepth();
p.earlyGain = _reverbOptions->getEarlyGain();
p.lateGain = _reverbOptions->getLateGain();
p.earlyMixLeft = _reverbOptions->getEarlyMixLeft();
p.earlyMixRight = _reverbOptions->getEarlyMixRight();
p.lateMixLeft = _reverbOptions->getLateMixLeft();
p.lateMixRight = _reverbOptions->getLateMixRight();
p.wetDryMix = _reverbOptions->getWetDryMix();
_listenerReverb.setParameters(&p);
// used for adding self-reverb to loopback audio
// used only for adding self-reverb to loopback audio
p.wetDryMix = 100.0f;
p.preDelay = 0.0f;
p.earlyGain = -96.0f; // disable ER
p.lateGain -= 12.0f; // quieter than listener reverb
p.lateGain -= 12.0f; // quieter than listener reverb
p.lateMixLeft = 0.0f;
p.lateMixRight = 0.0f;
_sourceReverb.setParameters(&p);
}
@ -572,10 +586,10 @@ void AudioClient::updateReverbOptions() {
_zoneReverbOptions.setReverbTime(_receivedAudioStream.getRevebTime());
reverbChanged = true;
}
if (_zoneReverbOptions.getWetLevel() != _receivedAudioStream.getWetLevel()) {
_zoneReverbOptions.setWetLevel(_receivedAudioStream.getWetLevel());
reverbChanged = true;
}
//if (_zoneReverbOptions.getWetLevel() != _receivedAudioStream.getWetLevel()) {
// _zoneReverbOptions.setWetLevel(_receivedAudioStream.getWetLevel());
// reverbChanged = true;
//}
if (_reverbOptions != &_zoneReverbOptions) {
_reverbOptions = &_zoneReverbOptions;
@ -602,17 +616,27 @@ void AudioClient::setReverb(bool reverb) {
void AudioClient::setReverbOptions(const AudioEffectOptions* options) {
// Save the new options
_scriptReverbOptions.setMaxRoomSize(options->getMaxRoomSize());
_scriptReverbOptions.setRoomSize(options->getRoomSize());
_scriptReverbOptions.setBandwidth(options->getBandwidth());
_scriptReverbOptions.setPreDelay(options->getPreDelay());
_scriptReverbOptions.setLateDelay(options->getLateDelay());
_scriptReverbOptions.setReverbTime(options->getReverbTime());
_scriptReverbOptions.setDamping(options->getDamping());
_scriptReverbOptions.setSpread(options->getSpread());
_scriptReverbOptions.setInputBandwidth(options->getInputBandwidth());
_scriptReverbOptions.setEarlyLevel(options->getEarlyLevel());
_scriptReverbOptions.setTailLevel(options->getTailLevel());
_scriptReverbOptions.setDryLevel(options->getDryLevel());
_scriptReverbOptions.setWetLevel(options->getWetLevel());
_scriptReverbOptions.setEarlyDiffusion(options->getEarlyDiffusion());
_scriptReverbOptions.setLateDiffusion(options->getLateDiffusion());
_scriptReverbOptions.setRoomSize(options->getRoomSize());
_scriptReverbOptions.setDensity(options->getDensity());
_scriptReverbOptions.setBassMult(options->getBassMult());
_scriptReverbOptions.setBassFreq(options->getBassFreq());
_scriptReverbOptions.setHighGain(options->getHighGain());
_scriptReverbOptions.setHighFreq(options->getHighFreq());
_scriptReverbOptions.setModRate(options->getModRate());
_scriptReverbOptions.setModDepth(options->getModDepth());
_scriptReverbOptions.setEarlyGain(options->getEarlyGain());
_scriptReverbOptions.setLateGain(options->getLateGain());
_scriptReverbOptions.setEarlyMixLeft(options->getEarlyMixLeft());
_scriptReverbOptions.setEarlyMixRight(options->getEarlyMixRight());
_scriptReverbOptions.setLateMixLeft(options->getLateMixLeft());
_scriptReverbOptions.setLateMixRight(options->getLateMixRight());
_scriptReverbOptions.setWetDryMix(options->getWetDryMix());
if (_reverbOptions == &_scriptReverbOptions) {
// Apply them to the reverb instances

View file

@ -10,58 +10,76 @@
#include "AudioEffectOptions.h"
static const QString MAX_ROOM_SIZE_HANDLE = "maxRoomSize";
static const QString ROOM_SIZE_HANDLE = "roomSize";
static const QString BANDWIDTH_HANDLE = "bandwidth";
static const QString PRE_DELAY_HANDLE = "preDelay";
static const QString LATE_DELAY_HANDLE = "lateDelay";
static const QString REVERB_TIME_HANDLE = "reverbTime";
static const QString DAMPIMG_HANDLE = "damping";
static const QString SPREAD_HANDLE = "spread";
static const QString INPUT_BANDWIDTH_HANDLE = "inputBandwidth";
static const QString EARLY_LEVEL_HANDLE = "earlyLevel";
static const QString TAIL_LEVEL_HANDLE = "tailLevel";
static const QString DRY_LEVEL_HANDLE = "dryLevel";
static const QString WET_LEVEL_HANDLE = "wetLevel";
static const QString EARLY_DIFFUSION_HANDLE = "earlyDiffusion";
static const QString LATE_DIFFUSION_HANDLE = "lateDiffusion";
static const QString ROOM_SIZE_HANDLE = "roomSize";
static const QString DENSITY_HANDLE = "density";
static const QString BASS_MULT_HANDLE = "bassMult";
static const QString BASS_FREQ_HANDLE = "bassFreq";
static const QString HIGH_GAIN_HANDLE = "highGain";
static const QString HIGH_FREQ_HANDLE = "highFreq";
static const QString MOD_RATE_HANDLE = "modRate";
static const QString MOD_DEPTH_HANDLE = "modDepth";
static const QString EARLY_GAIN_HANDLE = "earlyGain";
static const QString LATE_GAIN_HANDLE = "lateGain";
static const QString EARLY_MIX_LEFT_HANDLE = "earlyMixLeft";
static const QString EARLY_MIX_RIGHT_HANDLE = "earlyMixRight";
static const QString LATE_MIX_LEFT_HANDLE = "lateMixLeft";
static const QString LATE_MIX_RIGHT_HANDLE = "lateMixRight";
static const QString WET_DRY_MIX_HANDLE = "wetDryMix";
AudioEffectOptions::AudioEffectOptions(QScriptValue arguments) :
_maxRoomSize(50.0f),
_roomSize(50.0f),
_reverbTime(4.0f),
_damping(0.5f),
_spread(15.0f),
_inputBandwidth(0.75f),
_earlyLevel(-12.0f),
_tailLevel(-18.0f),
_dryLevel(0.0f),
_wetLevel(0.0f) {
if (arguments.property(MAX_ROOM_SIZE_HANDLE).isNumber()) {
_maxRoomSize = arguments.property(MAX_ROOM_SIZE_HANDLE).toNumber();
}
if (arguments.property(ROOM_SIZE_HANDLE).isNumber()) {
_roomSize = arguments.property(ROOM_SIZE_HANDLE).toNumber();
}
if (arguments.property(REVERB_TIME_HANDLE).isNumber()) {
_reverbTime = arguments.property(REVERB_TIME_HANDLE).toNumber();
}
if (arguments.property(DAMPIMG_HANDLE).isNumber()) {
_damping = arguments.property(DAMPIMG_HANDLE).toNumber();
}
if (arguments.property(SPREAD_HANDLE).isNumber()) {
_spread = arguments.property(SPREAD_HANDLE).toNumber();
}
if (arguments.property(INPUT_BANDWIDTH_HANDLE).isNumber()) {
_inputBandwidth = arguments.property(INPUT_BANDWIDTH_HANDLE).toNumber();
}
if (arguments.property(EARLY_LEVEL_HANDLE).isNumber()) {
_earlyLevel = arguments.property(EARLY_LEVEL_HANDLE).toNumber();
}
if (arguments.property(TAIL_LEVEL_HANDLE).isNumber()) {
_tailLevel = arguments.property(TAIL_LEVEL_HANDLE).toNumber();
}
if (arguments.property(DRY_LEVEL_HANDLE).isNumber()) {
_dryLevel = arguments.property(DRY_LEVEL_HANDLE).toNumber();
}
if (arguments.property(WET_LEVEL_HANDLE).isNumber()) {
_wetLevel = arguments.property(WET_LEVEL_HANDLE).toNumber();
}
static const float BANDWIDTH_DEFAULT = 10000.0f;
static const float PRE_DELAY_DEFAULT = 20.0f;
static const float LATE_DELAY_DEFAULT = 0.0f;
static const float REVERB_TIME_DEFAULT = 2.0f;
static const float EARLY_DIFFUSION_DEFAULT = 100.0f;
static const float LATE_DIFFUSION_DEFAULT = 100.0f;
static const float ROOM_SIZE_DEFAULT = 50.0f;
static const float DENSITY_DEFAULT = 100.0f;
static const float BASS_MULT_DEFAULT = 1.5f;
static const float BASS_FREQ_DEFAULT = 250.0f;
static const float HIGH_GAIN_DEFAULT = -6.0f;
static const float HIGH_FREQ_DEFAULT = 3000.0f;
static const float MOD_RATE_DEFAULT = 2.3f;
static const float MOD_DEPTH_DEFAULT = 50.0f;
static const float EARLY_GAIN_DEFAULT = 0.0f;
static const float LATE_GAIN_DEFAULT = 0.0f;
static const float EARLY_MIX_LEFT_DEFAULT = 20.0f;
static const float EARLY_MIX_RIGHT_DEFAULT = 20.0f;
static const float LATE_MIX_LEFT_DEFAULT = 90.0f;
static const float LATE_MIX_RIGHT_DEFAULT = 90.0f;
static const float WET_DRY_MIX_DEFAULT = 50.0f;
static void setOption(QScriptValue arguments, const QString name, float defaultValue, float& variable) {
variable = arguments.property(name).isNumber() ? arguments.property(name).toNumber() : defaultValue;
}
AudioEffectOptions::AudioEffectOptions(QScriptValue arguments) {
setOption(arguments, BANDWIDTH_HANDLE, BANDWIDTH_DEFAULT, _bandwidth);
setOption(arguments, PRE_DELAY_HANDLE, PRE_DELAY_DEFAULT, _preDelay);
setOption(arguments, LATE_DELAY_HANDLE, LATE_DELAY_DEFAULT, _lateDelay);
setOption(arguments, REVERB_TIME_HANDLE, REVERB_TIME_DEFAULT, _reverbTime);
setOption(arguments, EARLY_DIFFUSION_HANDLE, EARLY_DIFFUSION_DEFAULT, _earlyDiffusion);
setOption(arguments, LATE_DIFFUSION_HANDLE, LATE_DIFFUSION_DEFAULT, _lateDiffusion);
setOption(arguments, ROOM_SIZE_HANDLE, ROOM_SIZE_DEFAULT, _roomSize);
setOption(arguments, DENSITY_HANDLE, DENSITY_DEFAULT, _density);
setOption(arguments, BASS_MULT_HANDLE, BASS_MULT_DEFAULT, _bassMult);
setOption(arguments, BASS_FREQ_HANDLE, BASS_FREQ_DEFAULT, _bassFreq);
setOption(arguments, HIGH_GAIN_HANDLE, HIGH_GAIN_DEFAULT, _highGain);
setOption(arguments, HIGH_FREQ_HANDLE, HIGH_FREQ_DEFAULT, _highFreq);
setOption(arguments, MOD_RATE_HANDLE, MOD_RATE_DEFAULT, _modRate);
setOption(arguments, MOD_DEPTH_HANDLE, MOD_DEPTH_DEFAULT, _modDepth);
setOption(arguments, EARLY_GAIN_HANDLE, EARLY_GAIN_DEFAULT, _earlyGain);
setOption(arguments, LATE_GAIN_HANDLE, LATE_GAIN_DEFAULT, _lateGain);
setOption(arguments, EARLY_MIX_LEFT_HANDLE, EARLY_MIX_LEFT_DEFAULT, _earlyMixLeft);
setOption(arguments, EARLY_MIX_RIGHT_HANDLE, EARLY_MIX_RIGHT_DEFAULT, _earlyMixRight);
setOption(arguments, LATE_MIX_LEFT_HANDLE, LATE_MIX_LEFT_DEFAULT, _lateMixLeft);
setOption(arguments, LATE_MIX_RIGHT_HANDLE, LATE_MIX_RIGHT_DEFAULT, _lateMixRight);
setOption(arguments, WET_DRY_MIX_HANDLE, WET_DRY_MIX_DEFAULT, _wetDryMix);
}
AudioEffectOptions::AudioEffectOptions(const AudioEffectOptions &other) : QObject() {
@ -69,17 +87,28 @@ AudioEffectOptions::AudioEffectOptions(const AudioEffectOptions &other) : QObjec
}
AudioEffectOptions& AudioEffectOptions::operator=(const AudioEffectOptions &other) {
_maxRoomSize = other._maxRoomSize;
_roomSize = other._roomSize;
_bandwidth = other._bandwidth;
_preDelay = other._preDelay;
_lateDelay = other._lateDelay;
_reverbTime = other._reverbTime;
_damping = other._damping;
_spread = other._spread;
_inputBandwidth = other._inputBandwidth;
_earlyLevel = other._earlyLevel;
_tailLevel = other._tailLevel;
_dryLevel = other._dryLevel;
_wetLevel = other._wetLevel;
_earlyDiffusion = other._earlyDiffusion;
_lateDiffusion = other._lateDiffusion;
_roomSize = other._roomSize;
_density = other._density;
_bassMult = other._bassMult;
_bassFreq = other._bassFreq;
_highGain = other._highGain;
_highFreq = other._highFreq;
_modRate = other._modRate;
_modDepth = other._modDepth;
_earlyGain = other._earlyGain;
_lateGain = other._lateGain;
_earlyMixLeft = other._earlyMixLeft;
_earlyMixRight = other._earlyMixRight;
_lateMixLeft = other._lateMixLeft;
_lateMixRight = other._lateMixRight;
_wetDryMix = other._wetDryMix;
return *this;
}

View file

@ -15,32 +15,30 @@
#include <QtScript/QScriptContext>
#include <QtScript/QScriptEngine>
#include "AudioReverb.h"
class AudioEffectOptions : public QObject {
Q_OBJECT
// Meters Square
Q_PROPERTY(float maxRoomSize READ getMaxRoomSize WRITE setMaxRoomSize)
Q_PROPERTY(float roomSize READ getRoomSize WRITE setRoomSize)
// Seconds
Q_PROPERTY(float bandwidth READ getBandwidth WRITE setBandwidth)
Q_PROPERTY(float preDelay READ getPreDelay WRITE setPreDelay)
Q_PROPERTY(float lateDelay READ getLateDelay WRITE setLateDelay)
Q_PROPERTY(float reverbTime READ getReverbTime WRITE setReverbTime)
// Ratio between 0 and 1
Q_PROPERTY(float damping READ getDamping WRITE setDamping)
// (?) Does not appear to be set externally very often
Q_PROPERTY(float spread READ getSpread WRITE setSpread)
// Ratio between 0 and 1
Q_PROPERTY(float inputBandwidth READ getInputBandwidth WRITE setInputBandwidth)
// in dB
Q_PROPERTY(float earlyLevel READ getEarlyLevel WRITE setEarlyLevel)
Q_PROPERTY(float tailLevel READ getTailLevel WRITE setTailLevel)
Q_PROPERTY(float dryLevel READ getDryLevel WRITE setDryLevel)
Q_PROPERTY(float wetLevel READ getWetLevel WRITE setWetLevel)
Q_PROPERTY(float earlyDiffusion READ getEarlyDiffusion WRITE setEarlyDiffusion)
Q_PROPERTY(float lateDiffusion READ getLateDiffusion WRITE setLateDiffusion)
Q_PROPERTY(float roomSize READ getRoomSize WRITE setRoomSize)
Q_PROPERTY(float density READ getDensity WRITE setDensity)
Q_PROPERTY(float bassMult READ getBassMult WRITE setBassMult)
Q_PROPERTY(float bassFreq READ getBassFreq WRITE setBassFreq)
Q_PROPERTY(float highGain READ getHighGain WRITE setHighGain)
Q_PROPERTY(float highFreq READ getHighFreq WRITE setHighFreq)
Q_PROPERTY(float modRate READ getModRate WRITE setModRate)
Q_PROPERTY(float modDepth READ getModDepth WRITE setModDepth)
Q_PROPERTY(float earlyGain READ getEarlyGain WRITE setEarlyGain)
Q_PROPERTY(float lateGain READ getLateGain WRITE setLateGain)
Q_PROPERTY(float earlyMixLeft READ getEarlyMixLeft WRITE setEarlyMixLeft)
Q_PROPERTY(float earlyMixRight READ getEarlyMixRight WRITE setEarlyMixRight)
Q_PROPERTY(float lateMixLeft READ getLateMixLeft WRITE setLateMixLeft)
Q_PROPERTY(float lateMixRight READ getLateMixRight WRITE setLateMixRight)
Q_PROPERTY(float wetDryMix READ getWetDryMix WRITE setWetDryMix)
public:
AudioEffectOptions(QScriptValue arguments = QScriptValue());
@ -49,60 +47,100 @@ public:
static QScriptValue constructor(QScriptContext* context, QScriptEngine* engine);
float getRoomSize() const { return _roomSize; }
void setRoomSize(float roomSize ) { _roomSize = roomSize; }
float getBandwidth() const { return _bandwidth; }
void setBandwidth(float bandwidth) { _bandwidth = bandwidth; }
float getMaxRoomSize() const { return _maxRoomSize; }
void setMaxRoomSize(float maxRoomSize ) { _maxRoomSize = maxRoomSize; }
float getPreDelay() const { return _preDelay; }
void setPreDelay(float preDelay) { _preDelay = preDelay; }
float getLateDelay() const { return _lateDelay; }
void setLateDelay(float lateDelay) { _lateDelay = lateDelay; }
float getReverbTime() const { return _reverbTime; }
void setReverbTime(float reverbTime ) { _reverbTime = reverbTime; }
void setReverbTime(float reverbTime) { _reverbTime = reverbTime; }
float getDamping() const { return _damping; }
void setDamping(float damping ) { _damping = damping; }
float getEarlyDiffusion() const { return _earlyDiffusion; }
void setEarlyDiffusion(float earlyDiffusion) { _earlyDiffusion = earlyDiffusion; }
float getSpread() const { return _spread; }
void setSpread(float spread ) { _spread = spread; }
float getLateDiffusion() const { return _lateDiffusion; }
void setLateDiffusion(float lateDiffusion) { _lateDiffusion = lateDiffusion; }
float getInputBandwidth() const { return _inputBandwidth; }
void setInputBandwidth(float inputBandwidth ) { _inputBandwidth = inputBandwidth; }
float getRoomSize() const { return _roomSize; }
void setRoomSize(float roomSize) { _roomSize = roomSize; }
float getEarlyLevel() const { return _earlyLevel; }
void setEarlyLevel(float earlyLevel ) { _earlyLevel = earlyLevel; }
float getDensity() const { return _density; }
void setDensity(float density) { _density = density; }
float getTailLevel() const { return _tailLevel; }
void setTailLevel(float tailLevel ) { _tailLevel = tailLevel; }
float getBassMult() const { return _bassMult; }
void setBassMult(float bassMult) { _bassMult = bassMult; }
float getDryLevel() const { return _dryLevel; }
void setDryLevel(float dryLevel) { _dryLevel = dryLevel; }
float getBassFreq() const { return _bassFreq; }
void setBassFreq(float bassFreq) { _bassFreq = bassFreq; }
float getWetLevel() const { return _wetLevel; }
void setWetLevel(float wetLevel) { _wetLevel = wetLevel; }
float getHighGain() const { return _highGain; }
void setHighGain(float highGain) { _highGain = highGain; }
float getHighFreq() const { return _highFreq; }
void setHighFreq(float highFreq) { _highFreq = highFreq; }
float getModRate() const { return _modRate; }
void setModRate(float modRate) { _modRate = modRate; }
float getModDepth() const { return _modDepth; }
void setModDepth(float modDepth) { _modDepth = modDepth; }
float getEarlyGain() const { return _earlyGain; }
void setEarlyGain(float earlyGain) { _earlyGain = earlyGain; }
float getLateGain() const { return _lateGain; }
void setLateGain(float lateGain) { _lateGain = lateGain; }
float getEarlyMixLeft() const { return _earlyMixLeft; }
void setEarlyMixLeft(float earlyMixLeft) { _earlyMixLeft = earlyMixLeft; }
float getEarlyMixRight() const { return _earlyMixRight; }
void setEarlyMixRight(float earlyMixRight) { _earlyMixRight = earlyMixRight; }
float getLateMixLeft() const { return _lateMixLeft; }
void setLateMixLeft(float lateMixLeft) { _lateMixLeft = lateMixLeft; }
float getLateMixRight() const { return _lateMixRight; }
void setLateMixRight(float lateMixRight) { _lateMixRight = lateMixRight; }
float getWetDryMix() const { return _wetDryMix; }
void setWetDryMix(float wetDryMix) { _wetDryMix = wetDryMix; }
private:
// http://wiki.audacityteam.org/wiki/GVerb#Instant_Reverberb_settings
float _bandwidth; // [20, 24000] Hz
// Meters Square
float _maxRoomSize;
float _roomSize;
float _preDelay; // [0, 333] ms
float _lateDelay; // [0, 166] ms
// Seconds
float _reverbTime;
float _reverbTime; // [0.1, 100] seconds
// Ratio between 0 and 1
float _damping;
float _earlyDiffusion; // [0, 100] percent
float _lateDiffusion; // [0, 100] percent
// ? (Does not appear to be set externally very often)
float _spread;
float _roomSize; // [0, 100] percent
float _density; // [0, 100] percent
// Ratio between 0 and 1
float _inputBandwidth;
float _bassMult; // [0.1, 10] ratio
float _bassFreq; // [10, 500] Hz
float _highGain; // [-24, 0] dB
float _highFreq; // [1000, 12000] Hz
// dB
float _earlyLevel;
float _tailLevel;
float _dryLevel;
float _wetLevel;
float _modRate; // [0.1, 10] Hz
float _modDepth; // [0, 100] percent
float _earlyGain; // [-96, +24] dB
float _lateGain; // [-96, +24] dB
float _earlyMixLeft; // [0, 100] percent
float _earlyMixRight; // [0, 100] percent
float _lateMixLeft; // [0, 100] percent
float _lateMixRight; // [0, 100] percent
float _wetDryMix; // [0, 100] percent
};
#endif // hifi_AudioEffectOptions_h

View file

@ -1625,10 +1625,10 @@ void AvatarData::setBodyRoll(float bodyRoll) {
setOrientation(glm::quat(glm::radians(eulerAngles)));
}
void AvatarData::setPosition(const glm::vec3 position) {
void AvatarData::setPosition(const glm::vec3& position) {
SpatiallyNestable::setPosition(position);
}
void AvatarData::setOrientation(const glm::quat orientation) {
void AvatarData::setOrientation(const glm::quat& orientation) {
SpatiallyNestable::setOrientation(orientation);
}

View file

@ -201,8 +201,8 @@ public:
float getBodyRoll() const;
void setBodyRoll(float bodyRoll);
virtual void setPosition(glm::vec3 position);
virtual void setOrientation(glm::quat orientation);
virtual void setPosition(const glm::vec3& position) override;
virtual void setOrientation(const glm::quat& orientation) override;
void nextAttitude(glm::vec3 position, glm::quat orientation); // Can be safely called at any time.
void startCapture(); // start/end of the period in which the latest values are about to be captured for camera, etc.

View file

@ -54,6 +54,7 @@ public:
}
virtual void run() override {
OpenGLDisplayPlugin* currentPlugin{ nullptr };
Q_ASSERT(_context);
while (!_shutdown) {
if (_pendingMainThreadOperation) {
@ -81,12 +82,13 @@ public:
// Check if we have a new plugin to activate
if (_newPlugin != nullptr) {
// Deactivate the old plugin
if (_activePlugin != nullptr) {
_activePlugin->uncustomizeContext();
if (currentPlugin != nullptr) {
currentPlugin->uncustomizeContext();
currentPlugin->enableDeactivate();
}
_newPlugin->customizeContext();
_activePlugin = _newPlugin;
currentPlugin = _newPlugin;
_newPlugin = nullptr;
}
_context->doneCurrent();
@ -94,20 +96,21 @@ public:
}
// If there's no active plugin, just sleep
if (_activePlugin == nullptr) {
if (currentPlugin == nullptr) {
QThread::usleep(100);
continue;
}
// take the latest texture and present it
_context->makeCurrent();
_activePlugin->present();
currentPlugin->present();
_context->doneCurrent();
}
_context->makeCurrent();
if (_activePlugin) {
_activePlugin->uncustomizeContext();
if (currentPlugin) {
currentPlugin->uncustomizeContext();
currentPlugin->enableDeactivate();
}
_context->doneCurrent();
_context->moveToThread(qApp->thread());
@ -147,7 +150,6 @@ private:
bool _finishedMainThreadOperation { false };
QThread* _mainThread { nullptr };
OpenGLDisplayPlugin* _newPlugin { nullptr };
OpenGLDisplayPlugin* _activePlugin { nullptr };
QGLContext* _context { nullptr };
};
@ -208,11 +210,16 @@ void OpenGLDisplayPlugin::stop() {
}
void OpenGLDisplayPlugin::deactivate() {
{
Lock lock(_mutex);
_deactivateWait.wait(lock, [&]{ return _uncustomized; });
}
_timer.stop();
DisplayPlugin::deactivate();
}
void OpenGLDisplayPlugin::customizeContext() {
_uncustomized = false;
auto presentThread = DependencyManager::get<PresentThread>();
Q_ASSERT(thread() == presentThread->thread());
@ -233,6 +240,7 @@ void OpenGLDisplayPlugin::uncustomizeContext() {
_plane.reset();
}
// Pressing Alt (and Meta) key alone activates the menubar because its style inherits the
// SHMenuBarAltKeyNavigation from QWindowsStyle. This makes it impossible for a scripts to
// receive keyPress events for the Alt (and Meta) key in a reliable manner.
@ -380,3 +388,9 @@ QImage OpenGLDisplayPlugin::getScreenshot() const {
});
return result;
}
void OpenGLDisplayPlugin::enableDeactivate() {
Lock lock(_mutex);
_uncustomized = true;
_deactivateWait.notify_one();
}

View file

@ -9,6 +9,8 @@
#include "DisplayPlugin.h"
#include <condition_variable>
#include <QtCore/QTimer>
#include <GLMHelpers.h>
@ -18,8 +20,9 @@
class OpenGLDisplayPlugin : public DisplayPlugin {
protected:
using Mutex = std::recursive_mutex;
using Mutex = std::mutex;
using Lock = std::unique_lock<Mutex>;
using Condition = std::condition_variable;
public:
OpenGLDisplayPlugin();
virtual void activate() override;
@ -82,6 +85,12 @@ protected:
GLTextureEscrow _sceneTextureEscrow;
bool _vsyncSupported { false };
private:
void enableDeactivate();
Condition _deactivateWait;
bool _uncustomized{ false };
};

View file

@ -41,6 +41,7 @@ void RenderableBoxEntityItem::render(RenderArgs* args) {
Q_ASSERT(getType() == EntityTypes::Box);
Q_ASSERT(args->_batch);
if (!_procedural) {
_procedural.reset(new Procedural(this->getUserData()));
_procedural->_vertexSource = simple_vert;
@ -64,4 +65,6 @@ void RenderableBoxEntityItem::render(RenderArgs* args) {
} else {
DependencyManager::get<DeferredLightingEffect>()->renderSolidCubeInstance(batch, getTransformToCenter(), cubeColor);
}
};
static const auto triCount = DependencyManager::get<GeometryCache>()->getCubeTriangleCount();
args->_details._trianglesRendered += triCount;
}

View file

@ -44,7 +44,7 @@ RenderableModelEntityItem::~RenderableModelEntityItem() {
}
}
void RenderableModelEntityItem::setDimensions(const glm::vec3 value) {
void RenderableModelEntityItem::setDimensions(const glm::vec3& value) {
_dimensionsInitialized = true;
ModelEntityItem::setDimensions(value);
}
@ -565,20 +565,20 @@ bool RenderableModelEntityItem::contains(const glm::vec3& point) const {
return false;
}
glm::quat RenderableModelEntityItem::getJointRotation(int index) const {
glm::quat RenderableModelEntityItem::getAbsoluteJointRotationInObjectFrame(int index) const {
if (_model) {
glm::quat result;
if (_model->getJointRotation(index, result)) {
if (_model->getAbsoluteJointRotationInRigFrame(index, result)) {
return result;
}
}
return glm::quat();
}
glm::vec3 RenderableModelEntityItem::getJointTranslation(int index) const {
glm::vec3 RenderableModelEntityItem::getAbsoluteJointTranslationInObjectFrame(int index) const {
if (_model) {
glm::vec3 result;
if (_model->getJointTranslation(index, result)) {
if (_model->getAbsoluteJointTranslationInRigFrame(index, result)) {
return result;
}
}

View file

@ -28,7 +28,7 @@ public:
virtual ~RenderableModelEntityItem();
virtual void setDimensions(const glm::vec3 value) override;
virtual void setDimensions(const glm::vec3& value) override;
virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const override;
virtual bool setProperties(const EntityItemProperties& properties) override;
@ -67,9 +67,9 @@ public:
virtual bool contains(const glm::vec3& point) const override;
// these are in the frame of this object
virtual glm::quat getJointRotation(int index) const override;
virtual glm::vec3 getJointTranslation(int index) const override;
// these are in the frame of this object (model space)
virtual glm::quat getAbsoluteJointRotationInObjectFrame(int index) const override;
virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const override;
private:
void remapTextures();

View file

@ -71,4 +71,6 @@ void RenderableSphereEntityItem::render(RenderArgs* args) {
batch.setModelTransform(Transform());
DependencyManager::get<DeferredLightingEffect>()->renderSolidSphereInstance(batch, modelTransform, sphereColor);
}
};
static const auto triCount = DependencyManager::get<GeometryCache>()->getSphereTriangleCount();
args->_details._trianglesRendered += triCount;
}

View file

@ -628,71 +628,50 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
bool weOwnSimulation = _simulationOwner.matchesValidID(myNodeID);
if (args.bitstreamVersion >= VERSION_ENTITIES_HAVE_SIMULATION_OWNER_AND_ACTIONS_OVER_WIRE) {
// pack SimulationOwner and terse update properties near each other
// pack SimulationOwner and terse update properties near each other
// NOTE: the server is authoritative for changes to simOwnerID so we always unpack ownership data
// even when we would otherwise ignore the rest of the packet.
// NOTE: the server is authoritative for changes to simOwnerID so we always unpack ownership data
// even when we would otherwise ignore the rest of the packet.
if (propertyFlags.getHasProperty(PROP_SIMULATION_OWNER)) {
if (propertyFlags.getHasProperty(PROP_SIMULATION_OWNER)) {
QByteArray simOwnerData;
int bytes = OctreePacketData::unpackDataFromBytes(dataAt, simOwnerData);
SimulationOwner newSimOwner;
newSimOwner.fromByteArray(simOwnerData);
dataAt += bytes;
bytesRead += bytes;
QByteArray simOwnerData;
int bytes = OctreePacketData::unpackDataFromBytes(dataAt, simOwnerData);
SimulationOwner newSimOwner;
newSimOwner.fromByteArray(simOwnerData);
dataAt += bytes;
bytesRead += bytes;
if (wantTerseEditLogging() && _simulationOwner != newSimOwner) {
qCDebug(entities) << "sim ownership for" << getDebugName() << "is now" << newSimOwner;
}
if (_simulationOwner.set(newSimOwner)) {
_dirtyFlags |= Simulation::DIRTY_SIMULATOR_ID;
}
if (wantTerseEditLogging() && _simulationOwner != newSimOwner) {
qCDebug(entities) << "sim ownership for" << getDebugName() << "is now" << newSimOwner;
}
{ // When we own the simulation we don't accept updates to the entity's transform/velocities
// but since we're using macros below we have to temporarily modify overwriteLocalData.
bool oldOverwrite = overwriteLocalData;
overwriteLocalData = overwriteLocalData && !weOwnSimulation;
READ_ENTITY_PROPERTY(PROP_POSITION, glm::vec3, updatePosition);
READ_ENTITY_PROPERTY(PROP_ROTATION, glm::quat, updateRotation);
READ_ENTITY_PROPERTY(PROP_VELOCITY, glm::vec3, updateVelocity);
READ_ENTITY_PROPERTY(PROP_ANGULAR_VELOCITY, glm::vec3, updateAngularVelocity);
READ_ENTITY_PROPERTY(PROP_ACCELERATION, glm::vec3, setAcceleration);
overwriteLocalData = oldOverwrite;
if (_simulationOwner.set(newSimOwner)) {
_dirtyFlags |= Simulation::DIRTY_SIMULATOR_ID;
}
READ_ENTITY_PROPERTY(PROP_DIMENSIONS, glm::vec3, updateDimensions);
READ_ENTITY_PROPERTY(PROP_DENSITY, float, updateDensity);
READ_ENTITY_PROPERTY(PROP_GRAVITY, glm::vec3, updateGravity);
READ_ENTITY_PROPERTY(PROP_DAMPING, float, updateDamping);
READ_ENTITY_PROPERTY(PROP_RESTITUTION, float, updateRestitution);
READ_ENTITY_PROPERTY(PROP_FRICTION, float, updateFriction);
READ_ENTITY_PROPERTY(PROP_LIFETIME, float, updateLifetime);
READ_ENTITY_PROPERTY(PROP_SCRIPT, QString, setScript);
READ_ENTITY_PROPERTY(PROP_SCRIPT_TIMESTAMP, quint64, setScriptTimestamp);
READ_ENTITY_PROPERTY(PROP_REGISTRATION_POINT, glm::vec3, setRegistrationPoint);
} else {
// legacy order of packing here
// TODO: purge this logic in a few months from now (2015.07)
READ_ENTITY_PROPERTY(PROP_POSITION, glm::vec3, updatePosition);
READ_ENTITY_PROPERTY(PROP_DIMENSIONS, glm::vec3, updateDimensions);
READ_ENTITY_PROPERTY(PROP_ROTATION, glm::quat, updateRotation);
READ_ENTITY_PROPERTY(PROP_DENSITY, float, updateDensity);
READ_ENTITY_PROPERTY(PROP_VELOCITY, glm::vec3, updateVelocity);
READ_ENTITY_PROPERTY(PROP_GRAVITY, glm::vec3, updateGravity);
READ_ENTITY_PROPERTY(PROP_ACCELERATION, glm::vec3, setAcceleration);
READ_ENTITY_PROPERTY(PROP_DAMPING, float, updateDamping);
READ_ENTITY_PROPERTY(PROP_RESTITUTION, float, updateRestitution);
READ_ENTITY_PROPERTY(PROP_FRICTION, float, updateFriction);
READ_ENTITY_PROPERTY(PROP_LIFETIME, float, updateLifetime);
READ_ENTITY_PROPERTY(PROP_SCRIPT, QString, setScript);
READ_ENTITY_PROPERTY(PROP_SCRIPT_TIMESTAMP, quint64, setScriptTimestamp);
READ_ENTITY_PROPERTY(PROP_REGISTRATION_POINT, glm::vec3, setRegistrationPoint);
READ_ENTITY_PROPERTY(PROP_ANGULAR_VELOCITY, glm::vec3, updateAngularVelocity);
}
{ // When we own the simulation we don't accept updates to the entity's transform/velocities
// but since we're using macros below we have to temporarily modify overwriteLocalData.
bool oldOverwrite = overwriteLocalData;
overwriteLocalData = overwriteLocalData && !weOwnSimulation;
READ_ENTITY_PROPERTY(PROP_POSITION, glm::vec3, updatePosition);
READ_ENTITY_PROPERTY(PROP_ROTATION, glm::quat, updateRotation);
READ_ENTITY_PROPERTY(PROP_VELOCITY, glm::vec3, updateVelocity);
READ_ENTITY_PROPERTY(PROP_ANGULAR_VELOCITY, glm::vec3, updateAngularVelocity);
READ_ENTITY_PROPERTY(PROP_ACCELERATION, glm::vec3, setAcceleration);
overwriteLocalData = oldOverwrite;
}
READ_ENTITY_PROPERTY(PROP_DIMENSIONS, glm::vec3, updateDimensions);
READ_ENTITY_PROPERTY(PROP_DENSITY, float, updateDensity);
READ_ENTITY_PROPERTY(PROP_GRAVITY, glm::vec3, updateGravity);
READ_ENTITY_PROPERTY(PROP_DAMPING, float, updateDamping);
READ_ENTITY_PROPERTY(PROP_RESTITUTION, float, updateRestitution);
READ_ENTITY_PROPERTY(PROP_FRICTION, float, updateFriction);
READ_ENTITY_PROPERTY(PROP_LIFETIME, float, updateLifetime);
READ_ENTITY_PROPERTY(PROP_SCRIPT, QString, setScript);
READ_ENTITY_PROPERTY(PROP_SCRIPT_TIMESTAMP, quint64, setScriptTimestamp);
READ_ENTITY_PROPERTY(PROP_REGISTRATION_POINT, glm::vec3, setRegistrationPoint);
READ_ENTITY_PROPERTY(PROP_ANGULAR_DAMPING, float, updateAngularDamping);
READ_ENTITY_PROPERTY(PROP_VISIBLE, bool, setVisible);
@ -701,17 +680,6 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
READ_ENTITY_PROPERTY(PROP_LOCKED, bool, setLocked);
READ_ENTITY_PROPERTY(PROP_USER_DATA, QString, setUserData);
if (args.bitstreamVersion < VERSION_ENTITIES_HAVE_SIMULATION_OWNER_AND_ACTIONS_OVER_WIRE) {
// this code for when there is only simulatorID and no simulation priority
// we always accept the server's notion of simulatorID, so we fake overwriteLocalData as true
// before we try to READ_ENTITY_PROPERTY it
bool temp = overwriteLocalData;
overwriteLocalData = true;
READ_ENTITY_PROPERTY(PROP_SIMULATION_OWNER, QUuid, updateSimulatorID);
overwriteLocalData = temp;
}
if (args.bitstreamVersion >= VERSION_ENTITIES_HAS_MARKETPLACE_ID) {
READ_ENTITY_PROPERTY(PROP_MARKETPLACE_ID, QString, setMarketplaceID);
}
@ -1104,7 +1072,7 @@ bool EntityItem::setProperties(const EntityItemProperties& properties) {
bool somethingChanged = false;
// these affect TerseUpdate properties
SET_ENTITY_PROPERTY_FROM_PROPERTIES(simulationOwner, setSimulationOwner);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(simulationOwner, updateSimulationOwner);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(position, updatePosition);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(rotation, updateRotation);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(velocity, updateVelocity);
@ -1192,7 +1160,7 @@ const Transform EntityItem::getTransformToCenter() const {
return result;
}
void EntityItem::setDimensions(const glm::vec3 value) {
void EntityItem::setDimensions(const glm::vec3& value) {
if (value.x <= 0.0f || value.y <= 0.0f || value.z <= 0.0f) {
return;
}
@ -1324,6 +1292,13 @@ void EntityItem::updatePosition(const glm::vec3& value) {
}
if (getLocalPosition() != value) {
setLocalPosition(value);
_dirtyFlags |= Simulation::DIRTY_POSITION;
forEachDescendant([&](SpatiallyNestablePointer object) {
if (object->getNestableType() == NestableTypes::Entity) {
EntityItemPointer entity = std::static_pointer_cast<EntityItem>(object);
entity->_dirtyFlags |= Simulation::DIRTY_POSITION;
}
});
}
}
@ -1496,12 +1471,12 @@ void EntityItem::setSimulationOwner(const SimulationOwner& owner) {
_simulationOwner.set(owner);
}
void EntityItem::updateSimulatorID(const QUuid& value) {
if (wantTerseEditLogging() && _simulationOwner.getID() != value) {
qCDebug(entities) << "sim ownership for" << getDebugName() << "is now" << value;
void EntityItem::updateSimulationOwner(const SimulationOwner& owner) {
if (wantTerseEditLogging() && _simulationOwner != owner) {
qCDebug(entities) << "sim ownership for" << getDebugName() << "is now" << owner;
}
if (_simulationOwner.setID(value)) {
if (_simulationOwner.set(owner)) {
_dirtyFlags |= Simulation::DIRTY_SIMULATOR_ID;
}
}

View file

@ -178,7 +178,7 @@ public:
/// Dimensions in meters (0.0 - TREE_SCALE)
inline const glm::vec3 getDimensions() const { return getScale(); }
virtual void setDimensions(const glm::vec3 value);
virtual void setDimensions(const glm::vec3& value);
float getGlowLevel() const { return _glowLevel; }
void setGlowLevel(float glowLevel) { _glowLevel = glowLevel; }
@ -288,7 +288,7 @@ public:
quint8 getSimulationPriority() const { return _simulationOwner.getPriority(); }
QUuid getSimulatorID() const { return _simulationOwner.getID(); }
void updateSimulatorID(const QUuid& value);
void updateSimulationOwner(const SimulationOwner& owner);
void clearSimulationOwnership();
const QString& getMarketplaceID() const { return _marketplaceID; }
@ -379,8 +379,8 @@ public:
QList<EntityActionPointer> getActionsOfType(EntityActionType typeToGet);
// these are in the frame of this object
virtual glm::quat getJointRotation(int index) const { return glm::quat(); }
virtual glm::vec3 getJointTranslation(int index) const { return glm::vec3(0.0f); }
virtual glm::quat getAbsoluteJointRotationInObjectFrame(int index) const override { return glm::quat(); }
virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const override { return glm::vec3(0.0f); }
protected:

View file

@ -1780,6 +1780,12 @@ QList<QString> EntityItemProperties::listChangedProperties() {
if (zPNeighborIDChanged()) {
out += "zPNeighborID";
}
if (parentIDChanged()) {
out += "parentID";
}
if (parentJointIndexChanged()) {
out += "parentJointIndex";
}
getAnimation().listChangedProperties(out);
getKeyLight().listChangedProperties(out);
@ -1790,6 +1796,6 @@ QList<QString> EntityItemProperties::listChangedProperties() {
return out;
}
bool EntityItemProperties::parentDependentPropertyChanged() {
bool EntityItemProperties::parentDependentPropertyChanged() const {
return localPositionChanged() || positionChanged() || localRotationChanged() || rotationChanged();
}

View file

@ -83,7 +83,7 @@ public:
{ return (float)(usecTimestampNow() - getLastEdited()) / (float)USECS_PER_SECOND; }
EntityPropertyFlags getChangedProperties() const;
bool parentDependentPropertyChanged(); // was there a changed in a property that requires parent info to interpret?
bool parentDependentPropertyChanged() const; // was there a changed in a property that requires parent info to interpret?
AACube getMaximumAACube() const;
AABox getAABox() const;

View file

@ -64,7 +64,7 @@ void EntityScriptingInterface::setEntityTree(EntityTreePointer elementTree) {
}
}
EntityItemProperties convertLocationToScriptSemantics(EntityItemProperties entitySideProperties) {
EntityItemProperties convertLocationToScriptSemantics(const EntityItemProperties& entitySideProperties) {
// In EntityTree code, properties.position and properties.rotation are relative to the parent. In javascript,
// they are in world-space. The local versions are put into localPosition and localRotation and position and
// rotation are converted from local to world space.
@ -85,7 +85,7 @@ EntityItemProperties convertLocationToScriptSemantics(EntityItemProperties entit
}
EntityItemProperties convertLocationFromScriptSemantics(EntityItemProperties scriptSideProperties) {
EntityItemProperties convertLocationFromScriptSemantics(const EntityItemProperties& scriptSideProperties) {
// convert position and rotation properties from world-space to local, unless localPosition and localRotation
// are set. If they are set, they overwrite position and rotation.
EntityItemProperties entitySideProperties = scriptSideProperties;
@ -190,7 +190,7 @@ EntityItemProperties EntityScriptingInterface::getEntityProperties(QUuid identit
return convertLocationToScriptSemantics(results);
}
QUuid EntityScriptingInterface::editEntity(QUuid id, EntityItemProperties scriptSideProperties) {
QUuid EntityScriptingInterface::editEntity(QUuid id, const EntityItemProperties& scriptSideProperties) {
EntityItemProperties properties = scriptSideProperties;
EntityItemID entityID(id);
// If we have a local entity tree set, then also update it.
@ -201,17 +201,25 @@ QUuid EntityScriptingInterface::editEntity(QUuid id, EntityItemProperties script
bool updatedEntity = false;
_entityTree->withWriteLock([&] {
if (scriptSideProperties.parentDependentPropertyChanged()) {
// if the script sets a location property but didn't include parent information, grab the needed
// properties from the entity.
if (!scriptSideProperties.parentIDChanged() || !scriptSideProperties.parentJointIndexChanged()) {
EntityItemPointer entity = _entityTree->findEntityByEntityItemID(entityID);
if (entity && !scriptSideProperties.parentIDChanged()) {
properties.setParentID(entity->getParentID());
}
if (entity && !scriptSideProperties.parentJointIndexChanged()) {
properties.setParentJointIndex(entity->getParentJointIndex());
}
if (scriptSideProperties.parentDependentPropertyChanged() ||
scriptSideProperties.parentIDChanged() || scriptSideProperties.parentJointIndexChanged()) {
// All of parentID, parentJointIndex, position, rotation are needed to make sense of any of them.
// If any of these changed, pull any missing properties from the entity.
EntityItemPointer entity = _entityTree->findEntityByEntityItemID(entityID);
if (!entity) {
return;
}
if (!scriptSideProperties.parentIDChanged()) {
properties.setParentID(entity->getParentID());
}
if (!scriptSideProperties.parentJointIndexChanged()) {
properties.setParentJointIndex(entity->getParentJointIndex());
}
if (!scriptSideProperties.localPositionChanged() && !scriptSideProperties.positionChanged()) {
properties.setPosition(entity->getPosition());
}
if (!scriptSideProperties.localRotationChanged() && !scriptSideProperties.rotationChanged()) {
properties.setRotation(entity->getOrientation());
}
}
properties = convertLocationFromScriptSemantics(properties);
@ -801,19 +809,19 @@ glm::vec3 EntityScriptingInterface::localCoordsToVoxelCoords(const QUuid& entity
}
}
glm::vec3 EntityScriptingInterface::getJointTranslation(const QUuid& entityID, int jointIndex) {
glm::vec3 EntityScriptingInterface::getAbsoluteJointTranslationInObjectFrame(const QUuid& entityID, int jointIndex) {
if (auto entity = checkForTreeEntityAndTypeMatch(entityID, EntityTypes::Model)) {
auto modelEntity = std::dynamic_pointer_cast<ModelEntityItem>(entity);
return modelEntity->getJointTranslation(jointIndex);
return modelEntity->getAbsoluteJointTranslationInObjectFrame(jointIndex);
} else {
return glm::vec3(0.0f);
}
}
glm::quat EntityScriptingInterface::getJointRotation(const QUuid& entityID, int jointIndex) {
glm::quat EntityScriptingInterface::getAbsoluteJointRotationInObjectFrame(const QUuid& entityID, int jointIndex) {
if (auto entity = checkForTreeEntityAndTypeMatch(entityID, EntityTypes::Model)) {
auto modelEntity = std::dynamic_pointer_cast<ModelEntityItem>(entity);
return modelEntity->getJointRotation(jointIndex);
return modelEntity->getAbsoluteJointRotationInObjectFrame(jointIndex);
} else {
return glm::quat();
}

View file

@ -86,7 +86,7 @@ public slots:
/// edits a model updating only the included properties, will return the identified EntityItemID in case of
/// successful edit, if the input entityID is for an unknown model this function will have no effect
Q_INVOKABLE QUuid editEntity(QUuid entityID, EntityItemProperties properties);
Q_INVOKABLE QUuid editEntity(QUuid entityID, const EntityItemProperties& properties);
/// deletes a model
Q_INVOKABLE void deleteEntity(QUuid entityID);
@ -148,9 +148,9 @@ public slots:
Q_INVOKABLE glm::vec3 worldCoordsToVoxelCoords(const QUuid& entityID, glm::vec3 worldCoords);
Q_INVOKABLE glm::vec3 voxelCoordsToLocalCoords(const QUuid& entityID, glm::vec3 voxelCoords);
Q_INVOKABLE glm::vec3 localCoordsToVoxelCoords(const QUuid& entityID, glm::vec3 localCoords);
Q_INVOKABLE glm::vec3 getJointTranslation(const QUuid& entityID, int jointIndex);
Q_INVOKABLE glm::quat getJointRotation(const QUuid& entityID, int jointIndex);
Q_INVOKABLE glm::vec3 getAbsoluteJointTranslationInObjectFrame(const QUuid& entityID, int jointIndex);
Q_INVOKABLE glm::quat getAbsoluteJointRotationInObjectFrame(const QUuid& entityID, int jointIndex);
signals:
void collisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const Collision& collision);

View file

@ -24,6 +24,7 @@
#include "EntitiesLogging.h"
#include "RecurseOctreeToMapOperator.h"
#include "LogHandler.h"
#include "RemapIDOperator.h"
static const quint64 DELETED_ENTITIES_EXTRA_USECS_TO_CONSIDER = USECS_PER_MSEC * 50;
@ -740,6 +741,14 @@ void EntityTree::fixupTerseEditLogging(EntityItemProperties& properties, QList<Q
changedProperties[index] = QString("userData:") + changeHint;
}
}
if (properties.parentJointIndexChanged()) {
int index = changedProperties.indexOf("parentJointIndex");
if (index >= 0) {
quint16 value = properties.getParentJointIndex();
changedProperties[index] = QString("parentJointIndex:") + QString::number((int)value);
}
}
}
int EntityTree::processEditPacketData(ReceivedMessage& message, const unsigned char* editData, int maxLength,
@ -1186,6 +1195,11 @@ bool EntityTree::sendEntitiesOperation(OctreeElementPointer element, void* extra
return true;
}
void EntityTree::remapIDs() {
RemapIDOperator theOperator;
recurseTreeWithOperator(&theOperator);
}
bool EntityTree::writeToMap(QVariantMap& entityDescription, OctreeElementPointer element, bool skipDefaultValues) {
if (! entityDescription.contains("Entities")) {
entityDescription["Entities"] = QVariantList();

View file

@ -196,6 +196,8 @@ public:
bool wantTerseEditLogging() const { return _wantTerseEditLogging; }
void setWantTerseEditLogging(bool value) { _wantTerseEditLogging = value; }
void remapIDs();
bool writeToMap(QVariantMap& entityDescription, OctreeElementPointer element, bool skipDefaultValues);
bool readFromMap(QVariantMap& entityDescription);

View file

@ -40,7 +40,7 @@ LightEntityItem::LightEntityItem(const EntityItemID& entityItemID) : EntityItem(
_cutoff = PI;
}
void LightEntityItem::setDimensions(const glm::vec3 value) {
void LightEntityItem::setDimensions(const glm::vec3& value) {
if (_isSpotlight) {
// If we are a spotlight, treat the z value as our radius or length, and
// recalculate the x/y dimensions to properly encapsulate the spotlight.

View file

@ -23,7 +23,7 @@ public:
ALLOW_INSTANTIATION // This class can be instantiated
/// set dimensions in domain scale units (0.0 - 1.0) this will also reset radius appropriately
virtual void setDimensions(const glm::vec3 value);
virtual void setDimensions(const glm::vec3& value);
// methods for getting/setting all properties of an entity
virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const;

View file

@ -0,0 +1,33 @@
//
// RemapIDOperator.cpp
// libraries/entities/src
//
// Created by Seth Alves on 2015-12-6.
// Copyright 2015 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "EntityTree.h"
#include "RemapIDOperator.h"
QUuid RemapIDOperator::remap(const QUuid& oldID) {
if (oldID.isNull()) {
return oldID;
}
if (!_oldToNew.contains(oldID)) {
_oldToNew[oldID] = QUuid::createUuid();
}
return _oldToNew[oldID];
}
bool RemapIDOperator::postRecursion(OctreeElementPointer element) {
EntityTreeElementPointer entityTreeElement = std::static_pointer_cast<EntityTreeElement>(element);
entityTreeElement->forEachEntity([&](EntityItemPointer entityItem) {
entityItem->setID(remap(entityItem->getID()));
entityItem->setParentID(remap(entityItem->getParentID()));
});
return true;
}

View file

@ -0,0 +1,30 @@
//
// RemapIDOperator.h
// libraries/entities/src
//
// Created by Seth Alves on 2015-12-6.
// Copyright 2015 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_RemapIDOperator_h
#define hifi_RemapIDOperator_h
#include "Octree.h"
// this will change all the IDs in an EntityTree. Parent/Child relationships are maintained.
class RemapIDOperator : public RecurseOctreeOperator {
public:
RemapIDOperator() : RecurseOctreeOperator() {}
~RemapIDOperator() {}
virtual bool preRecursion(OctreeElementPointer element) { return true; }
virtual bool postRecursion(OctreeElementPointer element);
private:
QUuid remap(const QUuid& oldID);
QHash<QUuid, QUuid> _oldToNew;
};
#endif // hifi_RemapIDOperator_h

View file

@ -41,7 +41,7 @@ TextEntityItem::TextEntityItem(const EntityItemID& entityItemID) : EntityItem(en
const float TEXT_ENTITY_ITEM_FIXED_DEPTH = 0.01f;
void TextEntityItem::setDimensions(const glm::vec3 value) {
void TextEntityItem::setDimensions(const glm::vec3& value) {
// NOTE: Text Entities always have a "depth" of 1cm.
EntityItem::setDimensions(glm::vec3(value.x, value.y, TEXT_ENTITY_ITEM_FIXED_DEPTH));
}

View file

@ -23,7 +23,7 @@ public:
ALLOW_INSTANTIATION // This class can be instantiated
/// set dimensions in domain scale units (0.0 - 1.0) this will also reset radius appropriately
virtual void setDimensions(const glm::vec3 value);
virtual void setDimensions(const glm::vec3& value);
virtual ShapeType getShapeType() const { return SHAPE_TYPE_BOX; }
// methods for getting/setting all properties of an entity

View file

@ -34,7 +34,7 @@ WebEntityItem::WebEntityItem(const EntityItemID& entityItemID) : EntityItem(enti
const float WEB_ENTITY_ITEM_FIXED_DEPTH = 0.01f;
void WebEntityItem::setDimensions(const glm::vec3 value) {
void WebEntityItem::setDimensions(const glm::vec3& value) {
// NOTE: Web Entities always have a "depth" of 1cm.
EntityItem::setDimensions(glm::vec3(value.x, value.y, WEB_ENTITY_ITEM_FIXED_DEPTH));
}

View file

@ -22,7 +22,7 @@ public:
ALLOW_INSTANTIATION // This class can be instantiated
/// set dimensions in domain scale units (0.0 - 1.0) this will also reset radius appropriately
virtual void setDimensions(const glm::vec3 value);
virtual void setDimensions(const glm::vec3& value);
virtual ShapeType getShapeType() const { return SHAPE_TYPE_BOX; }
// methods for getting/setting all properties of an entity

View file

@ -296,8 +296,6 @@ void PacketReceiver::handleVerifiedMessage(QSharedPointer<ReceivedMessage> recei
if (matchingNode) {
emit dataReceived(matchingNode->getType(), receivedMessage->getSize());
matchingNode->recordBytesReceived(receivedMessage->getSize());
Node* n = matchingNode.data();
auto addr = n->getActiveSocket();
QMetaMethod metaMethod = listener.method;

View file

@ -22,8 +22,8 @@ static const int HEAD_DATA_SIZE = 512;
ReceivedMessage::ReceivedMessage(const NLPacketList& packetList)
: _data(packetList.getMessage()),
_headData(_data.mid(0, HEAD_DATA_SIZE)),
_sourceID(packetList.getSourceID()),
_numPackets(packetList.getNumPackets()),
_sourceID(packetList.getSourceID()),
_packetType(packetList.getType()),
_packetVersion(packetList.getVersion()),
_senderSockAddr(packetList.getSenderSockAddr()),
@ -34,8 +34,8 @@ ReceivedMessage::ReceivedMessage(const NLPacketList& packetList)
ReceivedMessage::ReceivedMessage(NLPacket& packet)
: _data(packet.readAll()),
_headData(_data.mid(0, HEAD_DATA_SIZE)),
_sourceID(packet.getSourceID()),
_numPackets(1),
_sourceID(packet.getSourceID()),
_packetType(packet.getType()),
_packetVersion(packet.getVersion()),
_senderSockAddr(packet.getSenderSockAddr()),

View file

@ -214,6 +214,19 @@ VertexVector tesselate(const VertexVector& startingTriangles, int count) {
return triangles;
}
size_t GeometryCache::getShapeTriangleCount(Shape shape) {
return _shapes[shape]._indexCount / VERTICES_PER_TRIANGLE;
}
size_t GeometryCache::getSphereTriangleCount() {
return getShapeTriangleCount(Sphere);
}
size_t GeometryCache::getCubeTriangleCount() {
return getShapeTriangleCount(Cube);
}
// FIXME solids need per-face vertices, but smooth shaded
// components do not. Find a way to support using draw elements
// or draw arrays as appropriate
@ -1727,3 +1740,4 @@ void GeometryCache::useSimpleDrawPipeline(gpu::Batch& batch, bool noBlend) {
batch.setPipeline(_standardDrawPipeline);
}
}

View file

@ -151,16 +151,19 @@ public:
void renderWireShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& transformBuffer, gpu::BufferPointer& colorBuffer);
void renderShape(gpu::Batch& batch, Shape shape);
void renderWireShape(gpu::Batch& batch, Shape shape);
size_t getShapeTriangleCount(Shape shape);
void renderCubeInstances(gpu::Batch& batch, size_t count, gpu::BufferPointer transformBuffer, gpu::BufferPointer colorBuffer);
void renderWireCubeInstances(gpu::Batch& batch, size_t count, gpu::BufferPointer transformBuffer, gpu::BufferPointer colorBuffer);
void renderCube(gpu::Batch& batch);
void renderWireCube(gpu::Batch& batch);
size_t getCubeTriangleCount();
void renderSphereInstances(gpu::Batch& batch, size_t count, gpu::BufferPointer transformBuffer, gpu::BufferPointer colorBuffer);
void renderWireSphereInstances(gpu::Batch& batch, size_t count, gpu::BufferPointer transformBuffer, gpu::BufferPointer colorBuffer);
void renderSphere(gpu::Batch& batch);
void renderWireSphere(gpu::Batch& batch);
size_t getSphereTriangleCount();
void renderGrid(gpu::Batch& batch, int xDivisions, int yDivisions, const glm::vec4& color);
void renderGrid(gpu::Batch& batch, int x, int y, int width, int height, int rows, int cols, const glm::vec4& color, int id = UNKNOWN_ID);

View file

@ -766,6 +766,14 @@ bool Model::getJointTranslation(int jointIndex, glm::vec3& translation) const {
return _rig->getJointTranslation(jointIndex, translation);
}
bool Model::getAbsoluteJointRotationInRigFrame(int jointIndex, glm::quat& rotation) const {
return _rig->getAbsoluteJointRotationInRigFrame(jointIndex, rotation);
}
bool Model::getAbsoluteJointTranslationInRigFrame(int jointIndex, glm::vec3& translation) const {
return _rig->getAbsoluteJointTranslationInRigFrame(jointIndex, translation);
}
bool Model::getJointCombinedRotation(int jointIndex, glm::quat& rotation) const {
return _rig->getJointCombinedRotation(jointIndex, rotation, _rotation);
}

View file

@ -166,6 +166,10 @@ public:
bool getJointRotation(int jointIndex, glm::quat& rotation) const;
bool getJointTranslation(int jointIndex, glm::vec3& translation) const;
// model frame
bool getAbsoluteJointRotationInRigFrame(int jointIndex, glm::quat& rotation) const;
bool getAbsoluteJointTranslationInRigFrame(int jointIndex, glm::vec3& translation) const;
/// Returns the index of the parent of the indexed joint, or -1 if not found.
int getParentJointIndex(int jointIndex) const;

View file

@ -65,7 +65,7 @@ void PIDController::updateHistory(float measuredValue, float dt, float error, fl
}
}
void PIDController::reportHistory() {
qCDebug(shared) << _label << "measured dt FIXME || error accumulated changed || p i d controlled";
qCDebug(shared) << _label << "measured dt || error accumulated changed || p i d controlled";
for (int i = 0; i < _history.size(); i++) {
Row& row = _history[i];
qCDebug(shared) << row.measured << row.dt <<

View file

@ -91,7 +91,7 @@ void SpatiallyNestable::forgetChild(SpatiallyNestablePointer newChild) const {
});
}
void SpatiallyNestable::setParentID(const QUuid parentID) {
void SpatiallyNestable::setParentID(const QUuid& parentID) {
if (_parentID != parentID) {
_parentID = parentID;
_parentKnowsMe = false;
@ -99,7 +99,7 @@ void SpatiallyNestable::setParentID(const QUuid parentID) {
parentChanged();
}
glm::vec3 SpatiallyNestable::worldToLocal(glm::vec3 position, QUuid parentID, int parentJointIndex) {
glm::vec3 SpatiallyNestable::worldToLocal(const glm::vec3& position, const QUuid& parentID, int parentJointIndex) {
QSharedPointer<SpatialParentFinder> parentFinder = DependencyManager::get<SpatialParentFinder>();
Transform parentTransform;
if (parentFinder) {
@ -122,7 +122,7 @@ glm::vec3 SpatiallyNestable::worldToLocal(glm::vec3 position, QUuid parentID, in
return result.getTranslation();
}
glm::quat SpatiallyNestable::worldToLocal(glm::quat orientation, QUuid parentID, int parentJointIndex) {
glm::quat SpatiallyNestable::worldToLocal(const glm::quat& orientation, const QUuid& parentID, int parentJointIndex) {
QSharedPointer<SpatialParentFinder> parentFinder = DependencyManager::get<SpatialParentFinder>();
Transform parentTransform;
if (parentFinder) {
@ -144,7 +144,7 @@ glm::quat SpatiallyNestable::worldToLocal(glm::quat orientation, QUuid parentID,
return result.getRotation();
}
glm::vec3 SpatiallyNestable::localToWorld(glm::vec3 position, QUuid parentID, int parentJointIndex) {
glm::vec3 SpatiallyNestable::localToWorld(const glm::vec3& position, const QUuid& parentID, int parentJointIndex) {
QSharedPointer<SpatialParentFinder> parentFinder = DependencyManager::get<SpatialParentFinder>();
Transform parentTransform;
if (parentFinder) {
@ -162,7 +162,7 @@ glm::vec3 SpatiallyNestable::localToWorld(glm::vec3 position, QUuid parentID, in
return result.getTranslation();
}
glm::quat SpatiallyNestable::localToWorld(glm::quat orientation, QUuid parentID, int parentJointIndex) {
glm::quat SpatiallyNestable::localToWorld(const glm::quat& orientation, const QUuid& parentID, int parentJointIndex) {
QSharedPointer<SpatialParentFinder> parentFinder = DependencyManager::get<SpatialParentFinder>();
Transform parentTransform;
if (parentFinder) {
@ -188,7 +188,7 @@ glm::vec3 SpatiallyNestable::getPosition(int jointIndex) const {
return getTransform(jointIndex).getTranslation();
}
void SpatiallyNestable::setPosition(glm::vec3 position) {
void SpatiallyNestable::setPosition(const glm::vec3& position) {
Transform parentTransform = getParentTransform();
Transform myWorldTransform;
_transformLock.withWriteLock([&] {
@ -207,7 +207,7 @@ glm::quat SpatiallyNestable::getOrientation(int jointIndex) const {
return getTransform(jointIndex).getRotation();
}
void SpatiallyNestable::setOrientation(glm::quat orientation) {
void SpatiallyNestable::setOrientation(const glm::quat& orientation) {
Transform parentTransform = getParentTransform();
Transform myWorldTransform;
_transformLock.withWriteLock([&] {
@ -232,13 +232,13 @@ const Transform SpatiallyNestable::getTransform(int jointIndex) const {
// this returns the world-space transform for this object. It finds its parent's transform (which may
// cause this object's parent to query its parent, etc) and multiplies this object's local transform onto it.
Transform worldTransform = getTransform();
Transform jointInObjectFrame = getJointTransformInObjectFrame(jointIndex);
Transform jointInObjectFrame = getAbsoluteJointTransformInObjectFrame(jointIndex);
Transform jointInWorldFrame;
Transform::mult(jointInWorldFrame, worldTransform, jointInObjectFrame);
return jointInWorldFrame;
}
void SpatiallyNestable::setTransform(const Transform transform) {
void SpatiallyNestable::setTransform(const Transform& transform) {
Transform parentTransform = getParentTransform();
_transformLock.withWriteLock([&] {
Transform::inverseMult(_transform, parentTransform, transform);
@ -259,7 +259,7 @@ glm::vec3 SpatiallyNestable::getScale(int jointIndex) const {
return getScale();
}
void SpatiallyNestable::setScale(glm::vec3 scale) {
void SpatiallyNestable::setScale(const glm::vec3& scale) {
_transformLock.withWriteLock([&] {
_transform.setScale(scale);
});
@ -274,7 +274,7 @@ const Transform SpatiallyNestable::getLocalTransform() const {
return result;
}
void SpatiallyNestable::setLocalTransform(const Transform transform) {
void SpatiallyNestable::setLocalTransform(const Transform& transform) {
_transformLock.withWriteLock([&] {
_transform = transform;
});
@ -289,7 +289,7 @@ glm::vec3 SpatiallyNestable::getLocalPosition() const {
return result;
}
void SpatiallyNestable::setLocalPosition(glm::vec3 position) {
void SpatiallyNestable::setLocalPosition(const glm::vec3& position) {
_transformLock.withWriteLock([&] {
_transform.setTranslation(position);
});
@ -304,7 +304,7 @@ glm::quat SpatiallyNestable::getLocalOrientation() const {
return result;
}
void SpatiallyNestable::setLocalOrientation(glm::quat orientation) {
void SpatiallyNestable::setLocalOrientation(const glm::quat& orientation) {
_transformLock.withWriteLock([&] {
_transform.setRotation(orientation);
});
@ -319,7 +319,7 @@ glm::vec3 SpatiallyNestable::getLocalScale() const {
return result;
}
void SpatiallyNestable::setLocalScale(glm::vec3 scale) {
void SpatiallyNestable::setLocalScale(const glm::vec3& scale) {
_transformLock.withWriteLock([&] {
_transform.setScale(scale);
});
@ -339,13 +339,13 @@ QList<SpatiallyNestablePointer> SpatiallyNestable::getChildren() const {
return children;
}
const Transform SpatiallyNestable::getJointTransformInObjectFrame(int jointIndex) const {
Transform jointInObjectFrame;
glm::vec3 position = getJointTranslation(jointIndex);
glm::quat orientation = getJointRotation(jointIndex);
jointInObjectFrame.setRotation(orientation);
jointInObjectFrame.setTranslation(position);
return jointInObjectFrame;
const Transform SpatiallyNestable::getAbsoluteJointTransformInObjectFrame(int jointIndex) const {
Transform jointTransformInObjectFrame;
glm::vec3 position = getAbsoluteJointTranslationInObjectFrame(jointIndex);
glm::quat orientation = getAbsoluteJointRotationInObjectFrame(jointIndex);
jointTransformInObjectFrame.setRotation(orientation);
jointTransformInObjectFrame.setTranslation(position);
return jointTransformInObjectFrame;
}
SpatiallyNestablePointer SpatiallyNestable::getThisPointer() const {

View file

@ -42,32 +42,32 @@ public:
virtual void setID(const QUuid& id) { _id = id; }
virtual const QUuid getParentID() const { return _parentID; }
virtual void setParentID(const QUuid parentID);
virtual void setParentID(const QUuid& parentID);
virtual quint16 getParentJointIndex() const { return _parentJointIndex; }
virtual void setParentJointIndex(quint16 parentJointIndex) { _parentJointIndex = parentJointIndex; }
static glm::vec3 worldToLocal(glm::vec3 position, QUuid parentID, int parentJointIndex);
static glm::quat worldToLocal(glm::quat orientation, QUuid parentID, int parentJointIndex);
static glm::vec3 worldToLocal(const glm::vec3& position, const QUuid& parentID, int parentJointIndex);
static glm::quat worldToLocal(const glm::quat& orientation, const QUuid& parentID, int parentJointIndex);
static glm::vec3 localToWorld(glm::vec3 position, QUuid parentID, int parentJointIndex);
static glm::quat localToWorld(glm::quat orientation, QUuid parentID, int parentJointIndex);
static glm::vec3 localToWorld(const glm::vec3& position, const QUuid& parentID, int parentJointIndex);
static glm::quat localToWorld(const glm::quat& orientation, const QUuid& parentID, int parentJointIndex);
// world frame
virtual const Transform getTransform() const;
virtual void setTransform(const Transform transform);
virtual void setTransform(const Transform& transform);
virtual Transform getParentTransform() const;
virtual glm::vec3 getPosition() const;
virtual void setPosition(glm::vec3 position);
virtual void setPosition(const glm::vec3& position);
virtual glm::quat getOrientation() const;
virtual glm::quat getOrientation(int jointIndex) const;
virtual void setOrientation(glm::quat orientation);
virtual void setOrientation(const glm::quat& orientation);
virtual glm::vec3 getScale() const;
virtual void setScale(glm::vec3 scale);
virtual void setScale(const glm::vec3& scale);
// get world-frame values for a specific joint
virtual const Transform getTransform(int jointIndex) const;
@ -76,24 +76,24 @@ public:
// object's parent's frame
virtual const Transform getLocalTransform() const;
virtual void setLocalTransform(const Transform transform);
virtual void setLocalTransform(const Transform& transform);
virtual glm::vec3 getLocalPosition() const;
virtual void setLocalPosition(glm::vec3 position);
virtual void setLocalPosition(const glm::vec3& position);
virtual glm::quat getLocalOrientation() const;
virtual void setLocalOrientation(glm::quat orientation);
virtual void setLocalOrientation(const glm::quat& orientation);
virtual glm::vec3 getLocalScale() const;
virtual void setLocalScale(glm::vec3 scale);
virtual void setLocalScale(const glm::vec3& scale);
QList<SpatiallyNestablePointer> getChildren() const;
NestableTypes::NestableType getNestableType() const { return _nestableType; }
// this object's frame
virtual const Transform getJointTransformInObjectFrame(int jointIndex) const;
virtual glm::quat getJointRotation(int index) const { assert(false); return glm::quat(); }
virtual glm::vec3 getJointTranslation(int index) const { assert(false); return glm::vec3(); }
virtual const Transform getAbsoluteJointTransformInObjectFrame(int jointIndex) const;
virtual glm::quat getAbsoluteJointRotationInObjectFrame(int index) const { assert(false); return glm::quat(); }
virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const { assert(false); return glm::vec3(); }
SpatiallyNestablePointer getThisPointer() const;

View file

@ -230,7 +230,7 @@ void OculusDisplayPlugin::internalPresent() {
viewScaleDesc.HmdToEyeViewOffset[1] = _eyeOffsets[1];
ovrLayerHeader* layers = &_sceneLayer.Header;
ovrResult result = ovr_SubmitFrame(_hmd, 0, &viewScaleDesc, &layers, 1);
ovrResult result = ovr_SubmitFrame(_hmd, frameIndex, &viewScaleDesc, &layers, 1);
if (!OVR_SUCCESS(result)) {
qDebug() << result;
}

View file

@ -1,16 +1,20 @@
set(TARGET_NAME "stack-manager")
set(BUILD_BUNDLE YES)
setup_hifi_project(Widgets Gui Svg Core Network WebKitWidgets)
add_dependencies(${TARGET_NAME} assignment-client domain-server)
include_application_version()
if (WIN32)
target_zlib()
endif ()
target_quazip()
set_target_properties(
${TARGET_NAME} PROPERTIES
EXCLUDE_FROM_ALL TRUE
)
if (UNIX)
set_target_properties(
${TARGET_NAME} PROPERTIES
EXCLUDE_FROM_ALL TRUE
)
endif (UNIX)
if (DEFINED ENV{JOB_ID})
set(PR_BUILD "false")
@ -45,4 +49,5 @@ if (APPLE)
set(SM_SRCS ${SM_SRCS} "${CMAKE_CURRENT_SOURCE_DIR}/assets/icon.icns")
endif ()
package_libraries_for_deployment()
package_libraries_for_deployment()
consolidate_stack_components()

View file

@ -81,10 +81,6 @@ void myMessageHandler(QtMsgType type, const QMessageLogContext &context, const Q
AppDelegate::AppDelegate(int argc, char* argv[]) :
QApplication(argc, argv),
_qtReady(false),
_dsReady(false),
_dsResourcesReady(false),
_acReady(false),
_domainServerProcess(NULL),
_acMonitorProcess(NULL),
_domainServerName("localhost")
@ -115,14 +111,15 @@ AppDelegate::AppDelegate(int argc, char* argv[]) :
_window = new MainWindow();
createExecutablePath();
downloadLatestExecutablesAndRequirements();
_checkVersionTimer.setInterval(0);
connect(&_checkVersionTimer, SIGNAL(timeout()), this, SLOT(checkVersion()));
_checkVersionTimer.start();
connect(this, &QApplication::aboutToQuit, this, &AppDelegate::stopStack);
_window->setRequirementsLastChecked(QDateTime::currentDateTime().toString());
_window->show();
toggleStack(true);
}
AppDelegate::~AppDelegate() {
@ -427,227 +424,6 @@ void AppDelegate::handleContentSetDownloadFinished() {
emit domainAddressChanged();
}
void AppDelegate::onFileSuccessfullyInstalled(const QUrl& url) {
if (url == GlobalData::getInstance().getRequirementsURL()) {
_qtReady = true;
} else if (url == GlobalData::getInstance().getAssignmentClientURL()) {
_acReady = true;
} else if (url == GlobalData::getInstance().getDomainServerURL()) {
_dsReady = true;
} else if (url == GlobalData::getInstance().getDomainServerResourcesURL()) {
_dsResourcesReady = true;
}
if (_qtReady && _acReady && _dsReady && _dsResourcesReady) {
_window->setRequirementsLastChecked(QDateTime::currentDateTime().toString());
_window->show();
toggleStack(true);
}
}
void AppDelegate::createExecutablePath() {
QDir launchDir(GlobalData::getInstance().getClientsLaunchPath());
QDir resourcesDir(GlobalData::getInstance().getClientsResourcesPath());
QDir logsDir(GlobalData::getInstance().getLogsPath());
if (!launchDir.exists()) {
if (QDir().mkpath(launchDir.absolutePath())) {
qDebug() << "Successfully created directory: "
<< launchDir.absolutePath();
} else {
qCritical() << "Failed to create directory: "
<< launchDir.absolutePath();
}
}
if (!resourcesDir.exists()) {
if (QDir().mkpath(resourcesDir.absolutePath())) {
qDebug() << "Successfully created directory: "
<< resourcesDir.absolutePath();
} else {
qCritical() << "Failed to create directory: "
<< resourcesDir.absolutePath();
}
}
if (!logsDir.exists()) {
if (QDir().mkpath(logsDir.absolutePath())) {
qDebug() << "Successfully created directory: "
<< logsDir.absolutePath();
} else {
qCritical() << "Failed to create directory: "
<< logsDir.absolutePath();
}
}
}
void AppDelegate::downloadLatestExecutablesAndRequirements() {
// Check if Qt is already installed
if (GlobalData::getInstance().getPlatform() == "mac") {
if (QDir(GlobalData::getInstance().getClientsLaunchPath() + "QtCore.framework").exists()) {
_qtReady = true;
}
} else if (GlobalData::getInstance().getPlatform() == "win") {
if (QFileInfo(GlobalData::getInstance().getClientsLaunchPath() + "Qt5Core.dll").exists()) {
_qtReady = true;
}
} else { // linux
if (QFileInfo(GlobalData::getInstance().getClientsLaunchPath() + "libQt5Core.so.5").exists()) {
_qtReady = true;
}
}
QFile reqZipFile(GlobalData::getInstance().getRequirementsZipPath());
QByteArray reqZipData;
if (reqZipFile.open(QIODevice::ReadOnly)) {
reqZipData = reqZipFile.readAll();
reqZipFile.close();
}
QFile resZipFile(GlobalData::getInstance().getDomainServerResourcesZipPath());
QByteArray resZipData;
if (resZipFile.open(QIODevice::ReadOnly)) {
resZipData = resZipFile.readAll();
resZipFile.close();
}
QDir resourcesDir(GlobalData::getInstance().getClientsResourcesPath());
if (!(resourcesDir.entryInfoList(QDir::AllEntries).size() < 3)) {
_dsResourcesReady = true;
}
// if the user has set hifiBuildDirectory, don't attempt to download the domain-server or assignement-client
if (GlobalData::getInstance().isGetHifiBuildDirectorySet()) {
_dsReady = true;
_acReady = true;
} else {
QByteArray dsData;
QFile dsFile(GlobalData::getInstance().getDomainServerExecutablePath());
if (dsFile.open(QIODevice::ReadOnly)) {
dsData = dsFile.readAll();
dsFile.close();
}
QByteArray acData;
QFile acFile(GlobalData::getInstance().getAssignmentClientExecutablePath());
if (acFile.open(QIODevice::ReadOnly)) {
acData = acFile.readAll();
acFile.close();
}
QNetworkRequest acReq(QUrl(GlobalData::getInstance().getAssignmentClientMD5URL()));
QNetworkReply* acReply = _manager->get(acReq);
QEventLoop acLoop;
connect(acReply, SIGNAL(finished()), &acLoop, SLOT(quit()));
acLoop.exec();
QByteArray acMd5Data = acReply->readAll().trimmed();
if (GlobalData::getInstance().getPlatform() == "win") {
// fix for reading the MD5 hash from Windows-generated
// binary data of the MD5 hash
QTextStream stream(acMd5Data);
stream >> acMd5Data;
}
// fix for Mac and Linux network accessibility
if (acMd5Data.size() == 0) {
// network is not accessible
qDebug() << "Could not connect to the internet.";
_window->show();
return;
}
qDebug() << "AC MD5: " << acMd5Data;
if (acMd5Data.toLower() == QCryptographicHash::hash(acData, QCryptographicHash::Md5).toHex()) {
_acReady = true;
}
QNetworkRequest dsReq(QUrl(GlobalData::getInstance().getDomainServerMD5URL()));
QNetworkReply* dsReply = _manager->get(dsReq);
QEventLoop dsLoop;
connect(dsReply, SIGNAL(finished()), &dsLoop, SLOT(quit()));
dsLoop.exec();
QByteArray dsMd5Data = dsReply->readAll().trimmed();
if (GlobalData::getInstance().getPlatform() == "win") {
// fix for reading the MD5 hash from Windows generated
// binary data of the MD5 hash
QTextStream stream(dsMd5Data);
stream >> dsMd5Data;
}
qDebug() << "DS MD5: " << dsMd5Data;
if (dsMd5Data.toLower() == QCryptographicHash::hash(dsData, QCryptographicHash::Md5).toHex()) {
_dsReady = true;
}
}
if (_qtReady) {
// check MD5 of requirements.zip only if Qt is found
QNetworkRequest reqZipReq(QUrl(GlobalData::getInstance().getRequirementsMD5URL()));
QNetworkReply* reqZipReply = _manager->get(reqZipReq);
QEventLoop reqZipLoop;
connect(reqZipReply, SIGNAL(finished()), &reqZipLoop, SLOT(quit()));
reqZipLoop.exec();
QByteArray reqZipMd5Data = reqZipReply->readAll().trimmed();
if (GlobalData::getInstance().getPlatform() == "win") {
// fix for reading the MD5 hash from Windows generated
// binary data of the MD5 hash
QTextStream stream(reqZipMd5Data);
stream >> reqZipMd5Data;
}
qDebug() << "Requirements ZIP MD5: " << reqZipMd5Data;
if (reqZipMd5Data.toLower() != QCryptographicHash::hash(reqZipData, QCryptographicHash::Md5).toHex()) {
_qtReady = false;
}
}
if (_dsResourcesReady) {
// check MD5 of resources.zip only if Domain Server
// resources are installed
QNetworkRequest resZipReq(QUrl(GlobalData::getInstance().getDomainServerResourcesMD5URL()));
QNetworkReply* resZipReply = _manager->get(resZipReq);
QEventLoop resZipLoop;
connect(resZipReply, SIGNAL(finished()), &resZipLoop, SLOT(quit()));
resZipLoop.exec();
QByteArray resZipMd5Data = resZipReply->readAll().trimmed();
if (GlobalData::getInstance().getPlatform() == "win") {
// fix for reading the MD5 hash from Windows generated
// binary data of the MD5 hash
QTextStream stream(resZipMd5Data);
stream >> resZipMd5Data;
}
qDebug() << "Domain Server Resources ZIP MD5: " << resZipMd5Data;
if (resZipMd5Data.toLower() != QCryptographicHash::hash(resZipData, QCryptographicHash::Md5).toHex()) {
_dsResourcesReady = false;
}
}
DownloadManager* downloadManager = 0;
if (!_qtReady || !_acReady || !_dsReady || !_dsResourcesReady) {
// initialise DownloadManager
downloadManager = new DownloadManager(_manager);
downloadManager->setWindowModality(Qt::ApplicationModal);
connect(downloadManager, SIGNAL(fileSuccessfullyInstalled(QUrl)),
SLOT(onFileSuccessfullyInstalled(QUrl)));
downloadManager->show();
} else {
_window->setRequirementsLastChecked(QDateTime::currentDateTime().toString());
_window->show();
toggleStack(true);
}
if (!_qtReady) {
downloadManager->downloadFile(GlobalData::getInstance().getRequirementsURL());
}
if (!_acReady) {
downloadManager->downloadFile(GlobalData::getInstance().getAssignmentClientURL());
}
if (!_dsReady) {
downloadManager->downloadFile(GlobalData::getInstance().getDomainServerURL());
}
if (!_dsResourcesReady) {
downloadManager->downloadFile(GlobalData::getInstance().getDomainServerResourcesURL());
}
}
void AppDelegate::checkVersion() {
QNetworkRequest latestVersionRequest((QUrl(CHECK_BUILDS_URL)));
latestVersionRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT);

View file

@ -53,7 +53,6 @@ signals:
void indexPathChangeResponse(bool wasSuccessful);
void stackStateChanged(bool isOn);
private slots:
void onFileSuccessfullyInstalled(const QUrl& url);
void requestDomainServerID();
void handleDomainIDReply();
void handleDomainGetReply();
@ -64,16 +63,10 @@ private slots:
private:
void parseCommandLine();
void createExecutablePath();
void downloadLatestExecutablesAndRequirements();
void changeDomainServerIndexPath(const QString& newPath);
QNetworkAccessManager* _manager;
bool _qtReady;
bool _dsReady;
bool _dsResourcesReady;
bool _acReady;
BackgroundProcess* _domainServerProcess;
BackgroundProcess* _acMonitorProcess;
QHash<QUuid, BackgroundProcess*> _scriptProcesses;

View file

@ -32,11 +32,8 @@ GlobalData::GlobalData() {
_resourcePath = "resources/";
_assignmentClientExecutable = "assignment-client";
_domainServerExecutable = "domain-server";
QString applicationSupportDirectory = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
if (PR_BUILD) {
applicationSupportDirectory += "/pr-binaries";
}
QString applicationSupportDirectory = QCoreApplication::applicationDirPath();
_clientsLaunchPath = QDir::toNativeSeparators(applicationSupportDirectory + "/");
_clientsResourcePath = QDir::toNativeSeparators(applicationSupportDirectory + "/" + _resourcePath);
@ -49,18 +46,6 @@ GlobalData::GlobalData() {
_domainServerExecutablePath.append(".exe");
}
_requirementsURL = urlBase + "/binaries/" + _platform + "/requirements/requirements.zip";
_requirementsZipPath = _clientsLaunchPath + "requirements.zip";
_requirementsMD5URL = urlBase + "/binaries/" + _platform + "/requirements/requirements.md5";
_assignmentClientURL = urlBase + "/binaries/" + _platform + "/assignment-client" + (_platform == "win" ? "/assignment-client.exe" : "/assignment-client");
_domainServerResourcesURL = urlBase + "/binaries/" + _platform + "/domain-server/resources.zip";
_domainServerResourcesZipPath = _clientsLaunchPath + "resources.zip";
_domainServerResourcesMD5URL = urlBase + "/binaries/" + _platform + "/domain-server/resources.md5";
_domainServerURL = urlBase + "/binaries/" + _platform + "/domain-server" + (_platform == "win" ? "/domain-server.exe" : "/domain-server");
_assignmentClientMD5URL = urlBase + "/binaries/" + _platform + "/assignment-client/assignment-client.md5";
_domainServerMD5URL = urlBase + "/binaries/" + _platform + "/domain-server/domain-server.md5";
_defaultDomain = "localhost";
_logsPath = QDir::toNativeSeparators(_clientsLaunchPath + "logs/");
_availableAssignmentTypes.insert("audio-mixer", 0);

View file

@ -9,6 +9,7 @@
#ifndef hifi_GlobalData_h
#define hifi_GlobalData_h
#include <QCoreApplication>
#include <QString>
#include <QHash>