merging with upstream

This commit is contained in:
Sam Gateau 2015-06-02 14:48:53 -07:00
commit 3c7eb4de6d
13 changed files with 162 additions and 78 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.*
###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
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.
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)
ExternalProject_Add(
${EXTERNAL_NAME}
URL http://hifi-public.s3.amazonaws.com/dependencies/polyvox-master-2015-5-27.zip
URL_MD5 e3dd09a24df4db29ba370e3bea753388
URL http://hifi-public.s3.amazonaws.com/dependencies/polyvox.zip
URL_MD5 904b840328278c9b36fa7a14be730c34
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
BINARY_DIR ${EXTERNAL_PROJECT_PREFIX}/build
LOG_DOWNLOAD 1
@ -45,7 +45,7 @@ else ()
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}_UTIL_LIBRARY ${INSTALL_DIR}/PolyVoxUtil/lib/PolyVoxUtil.lib CACHE FILEPATH "polyvox util library")
elseif (APPLE)

View file

@ -3495,7 +3495,9 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se
{
PerformanceTimer perfTimer("EngineRun");
render::RenderContext renderContext;
renderArgs->_shouldRender = LODManager::shouldRender;
renderContext.args = renderArgs;
renderArgs->_viewFrustum = getDisplayViewFrustum();
_renderEngine->setRenderContext(renderContext);

View file

@ -217,6 +217,47 @@ QString LODManager::getLODFeedbackText() {
return result;
}
bool LODManager::shouldRender(const RenderArgs* args, const AABox& bounds) {
const float maxScale = (float)TREE_SCALE;
const float octreeToMeshRatio = 4.0f; // must be this many times closer to a mesh than a voxel to see it.
float octreeSizeScale = args->_sizeScale;
int boundaryLevelAdjust = args->_boundaryLevelAdjust;
float visibleDistanceAtMaxScale = boundaryDistanceForRenderLevel(boundaryLevelAdjust, octreeSizeScale) / octreeToMeshRatio;
float distanceToCamera = glm::length(bounds.calcCenter() - args->_viewFrustum->getPosition());
float largestDimension = bounds.getLargestDimension();
static bool shouldRenderTableNeedsBuilding = true;
static QMap<float, float> shouldRenderTable;
if (shouldRenderTableNeedsBuilding) {
float SMALLEST_SCALE_IN_TABLE = 0.001f; // 1mm is plenty small
float scale = maxScale;
float factor = 1.0f;
while (scale > SMALLEST_SCALE_IN_TABLE) {
scale /= 2.0f;
factor /= 2.0f;
shouldRenderTable[scale] = factor;
}
shouldRenderTableNeedsBuilding = false;
}
float closestScale = maxScale;
float visibleDistanceAtClosestScale = visibleDistanceAtMaxScale;
QMap<float, float>::const_iterator lowerBound = shouldRenderTable.lowerBound(largestDimension);
if (lowerBound != shouldRenderTable.constEnd()) {
closestScale = lowerBound.key();
visibleDistanceAtClosestScale = visibleDistanceAtMaxScale * lowerBound.value();
}
if (closestScale < largestDimension) {
visibleDistanceAtClosestScale *= 2.0f;
}
return distanceToCamera <= visibleDistanceAtClosestScale;
};
// TODO: This is essentially the same logic used to render octree cells, but since models are more detailed then octree cells
// I've added a voxelToModelRatio that adjusts how much closer to a model you have to be to see it.
bool LODManager::shouldRenderMesh(float largestDimension, float distanceToCamera) {

View file

@ -49,6 +49,8 @@ const float ADJUST_LOD_MAX_SIZE_SCALE = DEFAULT_OCTREE_SIZE_SCALE;
// do. But both are still culled using the same angular size logic.
const float AVATAR_TO_ENTITY_RATIO = 2.0f;
class RenderArgs;
class AABox;
class LODManager : public QObject, public Dependency {
Q_OBJECT
@ -79,6 +81,7 @@ public:
Q_INVOKABLE float getLODDecreaseFPS();
Q_INVOKABLE float getLODIncreaseFPS();
static bool shouldRender(const RenderArgs* args, const AABox& bounds);
bool shouldRenderMesh(float largestDimension, float distanceToCamera);
void autoAdjustLOD(float currentFPS);

View file

@ -93,22 +93,24 @@ void Head::simulate(float deltaTime, bool isMine, bool billboard) {
if (_isFaceTrackerConnected) {
_blendshapeCoefficients = faceTracker->getBlendshapeCoefficients();
if (typeid(*faceTracker) == typeid(DdeFaceTracker)
&& Menu::getInstance()->isOptionChecked(MenuOption::UseAudioForMouth)) {
if (typeid(*faceTracker) == typeid(DdeFaceTracker)) {
calculateMouthShapes();
if (Menu::getInstance()->isOptionChecked(MenuOption::UseAudioForMouth)) {
calculateMouthShapes();
const int JAW_OPEN_BLENDSHAPE = 21;
const int MMMM_BLENDSHAPE = 34;
const int FUNNEL_BLENDSHAPE = 40;
const int SMILE_LEFT_BLENDSHAPE = 28;
const int SMILE_RIGHT_BLENDSHAPE = 29;
_blendshapeCoefficients[JAW_OPEN_BLENDSHAPE] += _audioJawOpen;
_blendshapeCoefficients[SMILE_LEFT_BLENDSHAPE] += _mouth4;
_blendshapeCoefficients[SMILE_RIGHT_BLENDSHAPE] += _mouth4;
_blendshapeCoefficients[MMMM_BLENDSHAPE] += _mouth2;
_blendshapeCoefficients[FUNNEL_BLENDSHAPE] += _mouth3;
const int JAW_OPEN_BLENDSHAPE = 21;
const int MMMM_BLENDSHAPE = 34;
const int FUNNEL_BLENDSHAPE = 40;
const int SMILE_LEFT_BLENDSHAPE = 28;
const int SMILE_RIGHT_BLENDSHAPE = 29;
_blendshapeCoefficients[JAW_OPEN_BLENDSHAPE] += _audioJawOpen;
_blendshapeCoefficients[SMILE_LEFT_BLENDSHAPE] += _mouth4;
_blendshapeCoefficients[SMILE_RIGHT_BLENDSHAPE] += _mouth4;
_blendshapeCoefficients[MMMM_BLENDSHAPE] += _mouth2;
_blendshapeCoefficients[FUNNEL_BLENDSHAPE] += _mouth3;
}
applyEyelidOffset(getFinalOrientationInWorldFrame());
}
}
}
@ -203,6 +205,9 @@ void Head::simulate(float deltaTime, bool isMine, bool billboard) {
_mouth3,
_mouth4,
_blendshapeCoefficients);
applyEyelidOffset(getOrientation());
} else {
_saccade = glm::vec3();
}
@ -218,7 +223,6 @@ void Head::simulate(float deltaTime, bool isMine, bool billboard) {
}
}
_eyePosition = calculateAverageEyePosition();
}
void Head::calculateMouthShapes() {
@ -249,6 +253,32 @@ void Head::calculateMouthShapes() {
_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) {
// restore rotation, lean to neutral positions
const float LEAN_RELAXATION_PERIOD = 0.25f; // seconds

View file

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

View file

@ -17,4 +17,10 @@ find_package(PolyVox REQUIRED)
target_include_directories(${TARGET_NAME} SYSTEM PUBLIC ${POLYVOX_INCLUDE_DIRS})
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)

View file

@ -28,6 +28,8 @@
#include <ScriptEngine.h>
#include <TextureCache.h>
#include <SoundCache.h>
#include <soxr.h>
#include <AudioConstants.h>
#include "EntityTreeRenderer.h"
@ -1203,7 +1205,30 @@ void EntityTreeRenderer::playEntityCollisionSound(const QUuid& myNodeID, EntityT
options.stereo = sound->isStereo();
options.position = position;
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->triggerDeleteAfterFinish();
QThread* injectorThread = new QThread();

View file

@ -662,7 +662,7 @@ void EntityItem::adjustEditPacketForClockSkew(unsigned char* editPacketBuffer, s
memcpy(&lastEditedInLocalTime, dataAt, sizeof(lastEditedInLocalTime));
quint64 lastEditedInServerTime = lastEditedInLocalTime + clockSkew;
memcpy(dataAt, &lastEditedInServerTime, sizeof(lastEditedInServerTime));
#if 1 //def WANT_DEBUG
#ifdef WANT_DEBUG
qCDebug(entities, "EntityItem::adjustEditPacketForClockSkew()...");
qCDebug(entities) << " lastEditedInLocalTime: " << lastEditedInLocalTime;
qCDebug(entities) << " clockSkew: " << clockSkew;

View file

@ -310,10 +310,14 @@ void Model::init() {
RenderKey(RenderKey::HAS_TANGENTS | RenderKey::HAS_SPECULAR),
modelNormalMapVertex, modelNormalSpecularMapPixel);
_renderPipelineLib.addRenderPipeline(
RenderKey(RenderKey::IS_TRANSLUCENT),
modelVertex, modelTranslucentPixel);
RenderKey(RenderKey::IS_TRANSLUCENT),
modelVertex, modelTranslucentPixel);
// FIXME Ignore lightmap for translucents meshpart
_renderPipelineLib.addRenderPipeline(
RenderKey(RenderKey::IS_TRANSLUCENT | RenderKey::HAS_LIGHTMAP),
modelVertex, modelTranslucentPixel);
_renderPipelineLib.addRenderPipeline(
RenderKey(RenderKey::HAS_TANGENTS | RenderKey::IS_TRANSLUCENT),

View file

@ -55,44 +55,6 @@ void DrawSceneTask::run(const SceneContextPointer& sceneContext, const RenderCon
Job::~Job() {
}
/*
bool LODManager::shouldRenderMesh(float largestDimension, float distanceToCamera) {
const float octreeToMeshRatio = 4.0f; // must be this many times closer to a mesh than a voxel to see it.
float octreeSizeScale = getOctreeSizeScale();
int boundaryLevelAdjust = getBoundaryLevelAdjust();
float maxScale = (float)TREE_SCALE;
float visibleDistanceAtMaxScale = boundaryDistanceForRenderLevel(boundaryLevelAdjust, octreeSizeScale) / octreeToMeshRatio;
if (_shouldRenderTableNeedsRebuilding) {
_shouldRenderTable.clear();
float SMALLEST_SCALE_IN_TABLE = 0.001f; // 1mm is plenty small
float scale = maxScale;
float visibleDistanceAtScale = visibleDistanceAtMaxScale;
while (scale > SMALLEST_SCALE_IN_TABLE) {
scale /= 2.0f;
visibleDistanceAtScale /= 2.0f;
_shouldRenderTable[scale] = visibleDistanceAtScale;
}
_shouldRenderTableNeedsRebuilding = false;
}
float closestScale = maxScale;
float visibleDistanceAtClosestScale = visibleDistanceAtMaxScale;
QMap<float, float>::const_iterator lowerBound = _shouldRenderTable.lowerBound(largestDimension);
if (lowerBound != _shouldRenderTable.constEnd()) {
closestScale = lowerBound.key();
visibleDistanceAtClosestScale = lowerBound.value();
}
if (closestScale < largestDimension) {
visibleDistanceAtClosestScale *= 2.0f;
}
return (distanceToCamera <= visibleDistanceAtClosestScale);
}*/
void render::cullItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDs& inItems, ItemIDs& outItems) {
PerformanceTimer perfTimer("cullItems");
assert(renderContext->args);
@ -114,13 +76,10 @@ void render::cullItems(const SceneContextPointer& sceneContext, const RenderCont
// TODO: some entity types (like lights) might want to be rendered even
// when they are outside of the view frustum...
float distance = args->_viewFrustum->distanceToCamera(bound.calcCenter());
bool outOfView = args->_viewFrustum->boxInFrustum(bound) == ViewFrustum::OUTSIDE;
if (!outOfView) {
bool bigEnoughToRender = true; //_viewState->shouldRenderMesh(bound.getLargestDimension(), distance);
bool bigEnoughToRender = (args->_shouldRender) ? args->_shouldRender(args, bound) : true;
if (bigEnoughToRender) {
outItems.push_back(id); // One more Item to render
args->_itemsRendered++;
@ -130,8 +89,7 @@ void render::cullItems(const SceneContextPointer& sceneContext, const RenderCont
} else {
args->_itemsOutOfView++;
}
}
}
}
struct ItemBound {
@ -144,16 +102,16 @@ struct ItemBound {
ItemBound(float centerDepth, float nearDepth, float farDepth, ItemID id) : _centerDepth(centerDepth), _nearDepth(nearDepth), _farDepth(farDepth), _id(id) {}
};
struct FrontToBackSort {
bool operator() (const ItemBound& left, const ItemBound& right) {
return (left._centerDepth < right._centerDepth);
}
struct FrontToBackSort {
bool operator() (const ItemBound& left, const ItemBound& right) {
return (left._centerDepth < right._centerDepth);
}
};
struct BackToFrontSort {
bool operator() (const ItemBound& left, const ItemBound& right) {
return (left._centerDepth > right._centerDepth);
}
struct BackToFrontSort {
bool operator() (const ItemBound& left, const ItemBound& right) {
return (left._centerDepth > right._centerDepth);
}
};
void render::depthSortItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, bool frontToBack, const ItemIDs& inItems, ItemIDs& outItems) {

View file

@ -12,8 +12,11 @@
#ifndef hifi_RenderArgs_h
#define hifi_RenderArgs_h
class ViewFrustum;
#include <functional>
class AABox;
class OctreeRenderer;
class ViewFrustum;
namespace gpu {
class Batch;
class Context;
@ -21,6 +24,8 @@ class Context;
class RenderArgs {
public:
typedef std::function<bool(const RenderArgs* args, const AABox& bounds)> ShoudRenderFunctor;
enum RenderMode { DEFAULT_RENDER_MODE, SHADOW_RENDER_MODE, DIFFUSE_RENDER_MODE, NORMAL_RENDER_MODE, MIRROR_RENDER_MODE };
enum RenderSide { MONO, STEREO_LEFT, STEREO_RIGHT };
@ -40,6 +45,7 @@ public:
RenderSide renderSide = MONO,
DebugFlags debugFlags = RENDER_DEBUG_NONE,
gpu::Batch* batch = nullptr,
ShoudRenderFunctor shouldRender = nullptr,
int elementsTouched = 0,
int itemsRendered = 0,
@ -66,6 +72,7 @@ public:
_renderSide(renderSide),
_debugFlags(debugFlags),
_batch(batch),
_shouldRender(shouldRender),
_elementsTouched(elementsTouched),
_itemsRendered(itemsRendered),
@ -94,6 +101,7 @@ public:
RenderSide _renderSide;
DebugFlags _debugFlags;
gpu::Batch* _batch;
ShoudRenderFunctor _shouldRender;
int _elementsTouched;
int _itemsRendered;