Merge branch 'master' of https://github.com/highfidelity/hifi into team-teaching

This commit is contained in:
ZappoMan 2015-06-02 11:25:23 -07:00
commit 5459b8402c
6 changed files with 87 additions and 19 deletions

View file

@ -12,6 +12,12 @@ We have a [homebrew formulas repository](https://github.com/highfidelity/homebre
*Our [qt5 homebrew formula](https://raw.github.com/highfidelity/homebrew-formulas/master/qt5.rb) is for a patched version of Qt 5.4.x stable that removes wireless network scanning that can reduce real-time audio performance. We recommended you use this formula to install Qt.* *Our [qt5 homebrew formula](https://raw.github.com/highfidelity/homebrew-formulas/master/qt5.rb) is for a patched version of Qt 5.4.x stable that removes wireless network scanning that can reduce real-time audio performance. We recommended you use this formula to install Qt.*
###Qt
Assuming you've installed Qt 5 using the homebrew instructions above, you'll need to set QT_CMAKE_PREFIX_PATH so CMake can find your installation of Qt. For Qt 5.4.1 installed via homebrew, set QT_CMAKE_PREFIX_PATH as follows.
export QT_CMAKE_PREFIX_PATH=/usr/local/Cellar/qt5/5.4.1/lib/cmake
###Xcode ###Xcode
If Xcode is your editor of choice, you can ask CMake to generate Xcode project files instead of Unix Makefiles. If Xcode is your editor of choice, you can ask CMake to generate Xcode project files instead of Unix Makefiles.
@ -19,4 +25,4 @@ If Xcode is your editor of choice, you can ask CMake to generate Xcode project f
After running cmake, you will have the make files or Xcode project file necessary to build all of the components. Open the hifi.xcodeproj file, choose ALL_BUILD from the Product > Scheme menu (or target drop down), and click Run. After running cmake, you will have the make files or Xcode project file necessary to build all of the components. Open the hifi.xcodeproj file, choose ALL_BUILD from the Product > Scheme menu (or target drop down), and click Run.
If the build completes successfully, you will have built targets for all components located in the `build/${target_name}/Debug` directories. If the build completes successfully, you will have built targets for all components located in the `build/${target_name}/Debug` directories.

View file

@ -3,8 +3,8 @@ set(EXTERNAL_NAME polyvox)
include(ExternalProject) include(ExternalProject)
ExternalProject_Add( ExternalProject_Add(
${EXTERNAL_NAME} ${EXTERNAL_NAME}
URL http://hifi-public.s3.amazonaws.com/dependencies/polyvox-master-2015-5-27.zip URL http://hifi-public.s3.amazonaws.com/dependencies/polyvox.zip
URL_MD5 e3dd09a24df4db29ba370e3bea753388 URL_MD5 904b840328278c9b36fa7a14be730c34
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
BINARY_DIR ${EXTERNAL_PROJECT_PREFIX}/build BINARY_DIR ${EXTERNAL_PROJECT_PREFIX}/build
LOG_DOWNLOAD 1 LOG_DOWNLOAD 1
@ -45,7 +45,7 @@ else ()
endif () endif ()
if (WIN32) if (WIN32)
set(${EXTERNAL_NAME_UPPER}_CORE_LIBRARY ${INSTALL_DIR}/PolyVoxCore/lib/PolyVoxCore.lib CACHE FILEPATH "polyvox core library") set(${EXTERNAL_NAME_UPPER}_CORE_LIBRARY ${INSTALL_DIR}/PolyVoxCore/lib/PolyVoxCore.lib CACHE FILEPATH "polyvox core library")
# set(${EXTERNAL_NAME_UPPER}_UTIL_LIBRARY ${INSTALL_DIR}/PolyVoxUtil/lib/PolyVoxUtil.lib CACHE FILEPATH "polyvox util library") # set(${EXTERNAL_NAME_UPPER}_UTIL_LIBRARY ${INSTALL_DIR}/PolyVoxUtil/lib/PolyVoxUtil.lib CACHE FILEPATH "polyvox util library")
elseif (APPLE) elseif (APPLE)

View file

@ -93,22 +93,24 @@ void Head::simulate(float deltaTime, bool isMine, bool billboard) {
if (_isFaceTrackerConnected) { if (_isFaceTrackerConnected) {
_blendshapeCoefficients = faceTracker->getBlendshapeCoefficients(); _blendshapeCoefficients = faceTracker->getBlendshapeCoefficients();
if (typeid(*faceTracker) == typeid(DdeFaceTracker) if (typeid(*faceTracker) == typeid(DdeFaceTracker)) {
&& Menu::getInstance()->isOptionChecked(MenuOption::UseAudioForMouth)) {
calculateMouthShapes(); if (Menu::getInstance()->isOptionChecked(MenuOption::UseAudioForMouth)) {
calculateMouthShapes();
const int JAW_OPEN_BLENDSHAPE = 21; const int JAW_OPEN_BLENDSHAPE = 21;
const int MMMM_BLENDSHAPE = 34; const int MMMM_BLENDSHAPE = 34;
const int FUNNEL_BLENDSHAPE = 40; const int FUNNEL_BLENDSHAPE = 40;
const int SMILE_LEFT_BLENDSHAPE = 28; const int SMILE_LEFT_BLENDSHAPE = 28;
const int SMILE_RIGHT_BLENDSHAPE = 29; const int SMILE_RIGHT_BLENDSHAPE = 29;
_blendshapeCoefficients[JAW_OPEN_BLENDSHAPE] += _audioJawOpen; _blendshapeCoefficients[JAW_OPEN_BLENDSHAPE] += _audioJawOpen;
_blendshapeCoefficients[SMILE_LEFT_BLENDSHAPE] += _mouth4; _blendshapeCoefficients[SMILE_LEFT_BLENDSHAPE] += _mouth4;
_blendshapeCoefficients[SMILE_RIGHT_BLENDSHAPE] += _mouth4; _blendshapeCoefficients[SMILE_RIGHT_BLENDSHAPE] += _mouth4;
_blendshapeCoefficients[MMMM_BLENDSHAPE] += _mouth2; _blendshapeCoefficients[MMMM_BLENDSHAPE] += _mouth2;
_blendshapeCoefficients[FUNNEL_BLENDSHAPE] += _mouth3; _blendshapeCoefficients[FUNNEL_BLENDSHAPE] += _mouth3;
}
applyEyelidOffset(getFinalOrientationInWorldFrame());
} }
} }
} }
@ -203,6 +205,9 @@ void Head::simulate(float deltaTime, bool isMine, bool billboard) {
_mouth3, _mouth3,
_mouth4, _mouth4,
_blendshapeCoefficients); _blendshapeCoefficients);
applyEyelidOffset(getOrientation());
} else { } else {
_saccade = glm::vec3(); _saccade = glm::vec3();
} }
@ -218,7 +223,6 @@ void Head::simulate(float deltaTime, bool isMine, bool billboard) {
} }
} }
_eyePosition = calculateAverageEyePosition(); _eyePosition = calculateAverageEyePosition();
} }
void Head::calculateMouthShapes() { void Head::calculateMouthShapes() {
@ -249,6 +253,32 @@ void Head::calculateMouthShapes() {
_mouth4 = glm::mix(_audioJawOpen, _mouth4, SMILE_PERIOD + randFloat() * SMILE_RANDOM_PERIOD); _mouth4 = glm::mix(_audioJawOpen, _mouth4, SMILE_PERIOD + randFloat() * SMILE_RANDOM_PERIOD);
} }
void Head::applyEyelidOffset(glm::quat headOrientation) {
// Adjusts the eyelid blendshape coefficients so that the eyelid follows the iris as the head pitches.
glm::quat eyeRotation = rotationBetween(headOrientation * IDENTITY_FRONT, getCorrectedLookAtPosition() - _eyePosition);
eyeRotation = eyeRotation * glm::angleAxis(safeEulerAngles(headOrientation).y, IDENTITY_UP); // Rotation w.r.t. head
float eyePitch = safeEulerAngles(eyeRotation).x;
const float EYE_PITCH_TO_COEFFICIENT = 1.6f; // Empirically determined
const float MAX_EYELID_OFFSET = 0.8f; // So that don't fully close eyes when looking way down
float eyelidOffset = glm::clamp(-eyePitch * EYE_PITCH_TO_COEFFICIENT, -1.0f, MAX_EYELID_OFFSET);
for (int i = 0; i < 2; i++) {
const int LEFT_EYE = 8;
float eyeCoefficient = _blendshapeCoefficients[i] - _blendshapeCoefficients[LEFT_EYE + i]; // Raw value
eyeCoefficient = glm::clamp(eyelidOffset + eyeCoefficient * (1.0f - eyelidOffset), -1.0f, 1.0f);
if (eyeCoefficient > 0.0f) {
_blendshapeCoefficients[i] = eyeCoefficient;
_blendshapeCoefficients[LEFT_EYE + i] = 0.0f;
} else {
_blendshapeCoefficients[i] = 0.0f;
_blendshapeCoefficients[LEFT_EYE + i] = -eyeCoefficient;
}
}
}
void Head::relaxLean(float deltaTime) { void Head::relaxLean(float deltaTime) {
// restore rotation, lean to neutral positions // restore rotation, lean to neutral positions
const float LEAN_RELAXATION_PERIOD = 0.25f; // seconds const float LEAN_RELAXATION_PERIOD = 0.25f; // seconds

View file

@ -155,6 +155,7 @@ private:
// private methods // private methods
void renderLookatVectors(RenderArgs* renderArgs, glm::vec3 leftEyePosition, glm::vec3 rightEyePosition, glm::vec3 lookatPosition); void renderLookatVectors(RenderArgs* renderArgs, glm::vec3 leftEyePosition, glm::vec3 rightEyePosition, glm::vec3 lookatPosition);
void calculateMouthShapes(); void calculateMouthShapes();
void applyEyelidOffset(glm::quat headOrientation);
friend class FaceModel; friend class FaceModel;
}; };

View file

@ -17,4 +17,10 @@ find_package(PolyVox REQUIRED)
target_include_directories(${TARGET_NAME} SYSTEM PUBLIC ${POLYVOX_INCLUDE_DIRS}) target_include_directories(${TARGET_NAME} SYSTEM PUBLIC ${POLYVOX_INCLUDE_DIRS})
target_link_libraries(${TARGET_NAME} ${POLYVOX_LIBRARIES}) target_link_libraries(${TARGET_NAME} ${POLYVOX_LIBRARIES})
# for changing the pitch of collision sounds
add_dependency_external_projects(soxr)
find_package(Soxr REQUIRED)
target_link_libraries(${TARGET_NAME} ${SOXR_LIBRARIES})
target_include_directories(${TARGET_NAME} SYSTEM PRIVATE ${SOXR_INCLUDE_DIRS})
link_hifi_libraries(shared gpu script-engine render render-utils) link_hifi_libraries(shared gpu script-engine render render-utils)

View file

@ -28,6 +28,8 @@
#include <ScriptEngine.h> #include <ScriptEngine.h>
#include <TextureCache.h> #include <TextureCache.h>
#include <SoundCache.h> #include <SoundCache.h>
#include <soxr.h>
#include <AudioConstants.h>
#include "EntityTreeRenderer.h" #include "EntityTreeRenderer.h"
@ -1203,7 +1205,30 @@ void EntityTreeRenderer::playEntityCollisionSound(const QUuid& myNodeID, EntityT
options.stereo = sound->isStereo(); options.stereo = sound->isStereo();
options.position = position; options.position = position;
options.volume = volume; options.volume = volume;
AudioInjector* injector = new AudioInjector(sound.data(), options);
// Shift the pitch down by ln(1 + (size / COLLISION_SIZE_FOR_STANDARD_PITCH)) / ln(2)
const float COLLISION_SIZE_FOR_STANDARD_PITCH = 0.2f;
QByteArray samples = sound->getByteArray();
soxr_io_spec_t spec = soxr_io_spec(SOXR_INT16_I, SOXR_INT16_I);
soxr_quality_spec_t qualitySpec = soxr_quality_spec(SOXR_MQ, 0);
const int channelCount = sound->isStereo() ? 2 : 1;
const float factor = log(1.0f + (entity->getMaximumAACube().getLargestDimension() / COLLISION_SIZE_FOR_STANDARD_PITCH)) / log(2);
const int standardRate = AudioConstants::SAMPLE_RATE;
const int resampledRate = standardRate * factor;
const int nInputSamples = samples.size() / sizeof(int16_t);
const int nOutputSamples = nInputSamples * factor;
QByteArray resampled(nOutputSamples * sizeof(int16_t), '\0');
const int16_t* receivedSamples = reinterpret_cast<const int16_t*>(samples.data());
soxr_error_t soxError = soxr_oneshot(standardRate, resampledRate, channelCount,
receivedSamples, nInputSamples, NULL,
reinterpret_cast<int16_t*>(resampled.data()), nOutputSamples, NULL,
&spec, &qualitySpec, 0);
if (soxError) {
qCDebug(entitiesrenderer) << "Unable to resample" << collisionSoundURL << "from" << nInputSamples << "@" << standardRate << "to" << nOutputSamples << "@" << resampledRate;
resampled = samples;
}
AudioInjector* injector = new AudioInjector(resampled, options);
injector->setLocalAudioInterface(_localAudioInterface); injector->setLocalAudioInterface(_localAudioInterface);
injector->triggerDeleteAfterFinish(); injector->triggerDeleteAfterFinish();
QThread* injectorThread = new QThread(); QThread* injectorThread = new QThread();