Merge pull request #6981 from howard-stearns/animate-iff-visible-with-step2-billboard-removal

Animate iff visible with step2 billboard removal
This commit is contained in:
Brad Hefta-Gaub 2016-02-01 13:54:25 -08:00
commit 711787a997
12 changed files with 46 additions and 210 deletions

View file

@ -181,7 +181,6 @@ using namespace std;
static QTimer locationUpdateTimer; static QTimer locationUpdateTimer;
static QTimer balanceUpdateTimer; static QTimer balanceUpdateTimer;
static QTimer identityPacketTimer; static QTimer identityPacketTimer;
static QTimer billboardPacketTimer;
static QTimer pingTimer; static QTimer pingTimer;
static const QString SNAPSHOT_EXTENSION = ".jpg"; static const QString SNAPSHOT_EXTENSION = ".jpg";
@ -632,10 +631,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
connect(&identityPacketTimer, &QTimer::timeout, getMyAvatar(), &MyAvatar::sendIdentityPacket); connect(&identityPacketTimer, &QTimer::timeout, getMyAvatar(), &MyAvatar::sendIdentityPacket);
identityPacketTimer.start(AVATAR_IDENTITY_PACKET_SEND_INTERVAL_MSECS); identityPacketTimer.start(AVATAR_IDENTITY_PACKET_SEND_INTERVAL_MSECS);
// send the billboard packet for our avatar every few seconds
connect(&billboardPacketTimer, &QTimer::timeout, getMyAvatar(), &MyAvatar::sendBillboardPacket);
billboardPacketTimer.start(AVATAR_BILLBOARD_PACKET_SEND_INTERVAL_MSECS);
QString cachePath = QStandardPaths::writableLocation(QStandardPaths::DataLocation); QString cachePath = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
QNetworkDiskCache* cache = new QNetworkDiskCache(); QNetworkDiskCache* cache = new QNetworkDiskCache();
@ -1032,7 +1027,6 @@ void Application::cleanupBeforeQuit() {
locationUpdateTimer.stop(); locationUpdateTimer.stop();
balanceUpdateTimer.stop(); balanceUpdateTimer.stop();
identityPacketTimer.stop(); identityPacketTimer.stop();
billboardPacketTimer.stop();
pingTimer.stop(); pingTimer.stop();
QMetaObject::invokeMethod(&_settingsTimer, "stop", Qt::BlockingQueuedConnection); QMetaObject::invokeMethod(&_settingsTimer, "stop", Qt::BlockingQueuedConnection);
@ -3538,23 +3532,6 @@ glm::vec3 Application::getAvatarPosition() const {
return getMyAvatar()->getPosition(); return getMyAvatar()->getPosition();
} }
QImage Application::renderAvatarBillboard(RenderArgs* renderArgs) {
const int BILLBOARD_SIZE = 64;
// Need to make sure the gl context is current here
_offscreenContext->makeCurrent();
renderArgs->_renderMode = RenderArgs::DEFAULT_RENDER_MODE;
renderRearViewMirror(renderArgs, QRect(0, 0, BILLBOARD_SIZE, BILLBOARD_SIZE), true);
auto primaryFbo = DependencyManager::get<FramebufferCache>()->getPrimaryFramebuffer();
QImage image(BILLBOARD_SIZE, BILLBOARD_SIZE, QImage::Format_ARGB32);
renderArgs->_context->downloadFramebuffer(primaryFbo, glm::ivec4(0, 0, BILLBOARD_SIZE, BILLBOARD_SIZE), image);
return image;
}
ViewFrustum* Application::getViewFrustum() { ViewFrustum* Application::getViewFrustum() {
#ifdef DEBUG #ifdef DEBUG
if (QThread::currentThread() == activeRenderingThread) { if (QThread::currentThread() == activeRenderingThread) {
@ -3684,7 +3661,7 @@ namespace render {
} }
void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool selfAvatarOnly, bool billboard) { void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool selfAvatarOnly) {
// FIXME: This preRender call is temporary until we create a separate render::scene for the mirror rendering. // FIXME: This preRender call is temporary until we create a separate render::scene for the mirror rendering.
// Then we can move this logic into the Avatar::simulate call. // Then we can move this logic into the Avatar::simulate call.
@ -3750,18 +3727,6 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se
}); });
} }
if (!billboard) {
DependencyManager::get<DeferredLightingEffect>()->setAmbientLightMode(getRenderAmbientLight());
auto skyStage = DependencyManager::get<SceneScriptingInterface>()->getSkyStage();
DependencyManager::get<DeferredLightingEffect>()->setGlobalLight(skyStage->getSunLight()->getDirection(), skyStage->getSunLight()->getColor(), skyStage->getSunLight()->getIntensity(), skyStage->getSunLight()->getAmbientIntensity());
auto skybox = model::SkyboxPointer();
if (skyStage->getBackgroundMode() == model::SunSkyStage::SKY_BOX) {
skybox = skyStage->getSkybox();
}
DependencyManager::get<DeferredLightingEffect>()->setGlobalSkybox(skybox);
}
{ {
PerformanceTimer perfTimer("SceneProcessPendingChanges"); PerformanceTimer perfTimer("SceneProcessPendingChanges");
_main3DScene->enqueuePendingChanges(pendingChanges); _main3DScene->enqueuePendingChanges(pendingChanges);
@ -3785,7 +3750,7 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se
activeRenderingThread = nullptr; activeRenderingThread = nullptr;
} }
void Application::renderRearViewMirror(RenderArgs* renderArgs, const QRect& region, bool billboard) { void Application::renderRearViewMirror(RenderArgs* renderArgs, const QRect& region) {
auto originalViewport = renderArgs->_viewport; auto originalViewport = renderArgs->_viewport;
// Grab current viewport to reset it at the end // Grab current viewport to reset it at the end
@ -3795,12 +3760,7 @@ void Application::renderRearViewMirror(RenderArgs* renderArgs, const QRect& regi
auto myAvatar = getMyAvatar(); auto myAvatar = getMyAvatar();
// bool eyeRelativeCamera = false; // bool eyeRelativeCamera = false;
if (billboard) { if (!AvatarInputs::getInstance()->mirrorZoomed()) {
fov = BILLBOARD_FIELD_OF_VIEW; // degees
_mirrorCamera.setPosition(myAvatar->getPosition() +
myAvatar->getOrientation() * glm::vec3(0.0f, 0.0f, -1.0f) * BILLBOARD_DISTANCE * myAvatar->getScale());
} else if (!AvatarInputs::getInstance()->mirrorZoomed()) {
_mirrorCamera.setPosition(myAvatar->getChestPosition() + _mirrorCamera.setPosition(myAvatar->getChestPosition() +
myAvatar->getOrientation() * glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_REARVIEW_BODY_DISTANCE * myAvatar->getScale()); myAvatar->getOrientation() * glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_REARVIEW_BODY_DISTANCE * myAvatar->getScale());
@ -3829,20 +3789,15 @@ void Application::renderRearViewMirror(RenderArgs* renderArgs, const QRect& regi
// set the bounds of rear mirror view // set the bounds of rear mirror view
gpu::Vec4i viewport; // the region is in device independent coordinates; must convert to device
if (billboard) { float ratio = (float)QApplication::desktop()->windowHandle()->devicePixelRatio() * getRenderResolutionScale();
viewport = gpu::Vec4i(0, 0, region.width(), region.height()); int width = region.width() * ratio;
} else { int height = region.height() * ratio;
// if not rendering the billboard, the region is in device independent coordinates; must convert to device gpu::Vec4i viewport = gpu::Vec4i(0, 0, width, height);
float ratio = (float)QApplication::desktop()->windowHandle()->devicePixelRatio() * getRenderResolutionScale();
int width = region.width() * ratio;
int height = region.height() * ratio;
viewport = gpu::Vec4i(0, 0, width, height);
}
renderArgs->_viewport = viewport; renderArgs->_viewport = viewport;
// render rear mirror view // render rear mirror view
displaySide(renderArgs, _mirrorCamera, true, billboard); displaySide(renderArgs, _mirrorCamera, true);
renderArgs->_viewport = originalViewport; renderArgs->_viewport = originalViewport;
} }

View file

@ -168,8 +168,6 @@ public:
virtual controller::ScriptingInterface* getControllerScriptingInterface() { return _controllerScriptingInterface; } virtual controller::ScriptingInterface* getControllerScriptingInterface() { return _controllerScriptingInterface; }
virtual void registerScriptEngineWithApplicationServices(ScriptEngine* scriptEngine) override; virtual void registerScriptEngineWithApplicationServices(ScriptEngine* scriptEngine) override;
QImage renderAvatarBillboard(RenderArgs* renderArgs);
virtual ViewFrustum* getCurrentViewFrustum() { return getDisplayViewFrustum(); } virtual ViewFrustum* getCurrentViewFrustum() { return getDisplayViewFrustum(); }
virtual QThread* getMainThread() { return thread(); } virtual QThread* getMainThread() { return thread(); }
virtual PickRay computePickRay(float x, float y) const; virtual PickRay computePickRay(float x, float y) const;
@ -344,7 +342,7 @@ private:
glm::vec3 getSunDirection(); glm::vec3 getSunDirection();
void renderRearViewMirror(RenderArgs* renderArgs, const QRect& region, bool billboard = false); void renderRearViewMirror(RenderArgs* renderArgs, const QRect& region);
int sendNackPackets(); int sendNackPackets();
@ -357,7 +355,7 @@ private:
void initializeAcceptedFiles(); void initializeAcceptedFiles();
int getRenderAmbientLight() const; int getRenderAmbientLight() const;
void displaySide(RenderArgs* renderArgs, Camera& whichCamera, bool selfAvatarOnly = false, bool billboard = false); void displaySide(RenderArgs* renderArgs, Camera& whichCamera, bool selfAvatarOnly = false);
bool importSVOFromURL(const QString& urlString); bool importSVOFromURL(const QString& urlString);

View file

@ -9,7 +9,6 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// //
#include <avatar/AvatarManager.h>
#include <SettingHandle.h> #include <SettingHandle.h>
#include <Util.h> #include <Util.h>
@ -34,7 +33,6 @@ void LODManager::setRenderDistanceInverseHighLimit(float newValue) {
} }
LODManager::LODManager() { LODManager::LODManager() {
calculateAvatarLODDistanceMultiplier();
setRenderDistanceInverseHighLimit(renderDistanceInverseHighLimit.get()); setRenderDistanceInverseHighLimit(renderDistanceInverseHighLimit.get());
setRenderDistanceInverseLowLimit(1.0f / (float)TREE_SCALE); setRenderDistanceInverseLowLimit(1.0f / (float)TREE_SCALE);
@ -182,7 +180,6 @@ void LODManager::autoAdjustLOD(float currentFPS) {
} }
if (changed) { if (changed) {
calculateAvatarLODDistanceMultiplier();
auto lodToolsDialog = DependencyManager::get<DialogsManager>()->getLodToolsDialog(); auto lodToolsDialog = DependencyManager::get<DialogsManager>()->getLodToolsDialog();
if (lodToolsDialog) { if (lodToolsDialog) {
lodToolsDialog->reloadSliders(); lodToolsDialog->reloadSliders();
@ -292,11 +289,6 @@ bool LODManager::shouldRender(const RenderArgs* args, const AABox& bounds) {
void LODManager::setOctreeSizeScale(float sizeScale) { void LODManager::setOctreeSizeScale(float sizeScale) {
_octreeSizeScale = sizeScale; _octreeSizeScale = sizeScale;
calculateAvatarLODDistanceMultiplier();
}
void LODManager::calculateAvatarLODDistanceMultiplier() {
_avatarLODDistanceMultiplier = AVATAR_TO_ENTITY_RATIO / (_octreeSizeScale / DEFAULT_OCTREE_SIZE_SCALE);
} }
void LODManager::setBoundaryLevelAdjust(int boundaryLevelAdjust) { void LODManager::setBoundaryLevelAdjust(int boundaryLevelAdjust) {

View file

@ -46,10 +46,6 @@ const float ADJUST_LOD_UP_BY = 1.1f;
const float ADJUST_LOD_MIN_SIZE_SCALE = 1.0f; const float ADJUST_LOD_MIN_SIZE_SCALE = 1.0f;
const float ADJUST_LOD_MAX_SIZE_SCALE = DEFAULT_OCTREE_SIZE_SCALE; const float ADJUST_LOD_MAX_SIZE_SCALE = DEFAULT_OCTREE_SIZE_SCALE;
// The ratio of "visibility" of avatars to other content. A value larger than 1 will mean Avatars "cull" later than entities
// do. But both are still culled using the same angular size logic.
const float AVATAR_TO_ENTITY_RATIO = 2.0f;
class RenderArgs; class RenderArgs;
class AABox; class AABox;
@ -68,8 +64,6 @@ public:
Q_INVOKABLE void setHMDLODDecreaseFPS(float value) { _hmdLODDecreaseFPS = value; } Q_INVOKABLE void setHMDLODDecreaseFPS(float value) { _hmdLODDecreaseFPS = value; }
Q_INVOKABLE float getHMDLODDecreaseFPS() const { return _hmdLODDecreaseFPS; } Q_INVOKABLE float getHMDLODDecreaseFPS() const { return _hmdLODDecreaseFPS; }
Q_INVOKABLE float getHMDLODIncreaseFPS() const { return glm::min(_hmdLODDecreaseFPS + INCREASE_LOD_GAP, MAX_LIKELY_HMD_FPS); } Q_INVOKABLE float getHMDLODIncreaseFPS() const { return glm::min(_hmdLODDecreaseFPS + INCREASE_LOD_GAP, MAX_LIKELY_HMD_FPS); }
Q_INVOKABLE float getAvatarLODDistanceMultiplier() const { return _avatarLODDistanceMultiplier; }
// User Tweakable LOD Items // User Tweakable LOD Items
Q_INVOKABLE QString getLODFeedbackText(); Q_INVOKABLE QString getLODFeedbackText();
@ -116,13 +110,11 @@ signals:
private: private:
LODManager(); LODManager();
void calculateAvatarLODDistanceMultiplier();
bool _automaticLODAdjust = true; bool _automaticLODAdjust = true;
float _desktopLODDecreaseFPS = DEFAULT_DESKTOP_LOD_DOWN_FPS; float _desktopLODDecreaseFPS = DEFAULT_DESKTOP_LOD_DOWN_FPS;
float _hmdLODDecreaseFPS = DEFAULT_HMD_LOD_DOWN_FPS; float _hmdLODDecreaseFPS = DEFAULT_HMD_LOD_DOWN_FPS;
float _avatarLODDistanceMultiplier;
float _octreeSizeScale = DEFAULT_OCTREE_SIZE_SCALE; float _octreeSizeScale = DEFAULT_OCTREE_SIZE_SCALE;
int _boundaryLevelAdjust = 0; int _boundaryLevelAdjust = 0;

View file

@ -94,7 +94,6 @@ Avatar::Avatar(RigPointer rig) :
_worldUpDirection(DEFAULT_UP_DIRECTION), _worldUpDirection(DEFAULT_UP_DIRECTION),
_moving(false), _moving(false),
_initialized(false), _initialized(false),
_shouldRenderBillboard(true),
_voiceSphereID(GeometryCache::UNKNOWN_ID) _voiceSphereID(GeometryCache::UNKNOWN_ID)
{ {
// we may have been created in the network thread, but we live in the main thread // we may have been created in the network thread, but we live in the main thread
@ -115,13 +114,10 @@ Avatar::~Avatar() {
} }
} }
const float BILLBOARD_LOD_DISTANCE = 40.0f;
void Avatar::init() { void Avatar::init() {
getHead()->init(); getHead()->init();
_skeletonModel.init(); _skeletonModel.init();
_initialized = true; _initialized = true;
_shouldRenderBillboard = (getLODDistance() >= BILLBOARD_LOD_DISTANCE);
} }
glm::vec3 Avatar::getChestPosition() const { glm::vec3 Avatar::getChestPosition() const {
@ -141,12 +137,14 @@ glm::quat Avatar::getWorldAlignedOrientation () const {
} }
AABox Avatar::getBounds() const { AABox Avatar::getBounds() const {
return AABox(); // Our skeleton models are rigged, and this method call safely produces the static bounds of the model.
} // Except, that getPartBounds produces an infinite, uncentered bounding box when the model is not yet parsed,
// and we want a centered one. NOTE: There is code that may never try to render, and thus never load and get the
float Avatar::getLODDistance() const { // real model bounds, if this is unrealistically small.
return DependencyManager::get<LODManager>()->getAvatarLODDistanceMultiplier() * if (!_skeletonModel.isRenderable()) {
glm::distance(qApp->getCamera()->getPosition(), getPosition()) / getUniformScale(); return AABox(getPosition(), getUniformScale()); // approximately 2m tall, scaled to user request.
}
return _skeletonModel.getPartBounds(0, 0, getPosition(), getOrientation());
} }
void Avatar::animateScaleChanges(float deltaTime) { void Avatar::animateScaleChanges(float deltaTime) {
@ -176,20 +174,22 @@ void Avatar::simulate(float deltaTime) {
} }
animateScaleChanges(deltaTime); animateScaleChanges(deltaTime);
// update the billboard render flag // update the shouldAnimate flag to match whether or not we will render the avatar.
const float BILLBOARD_HYSTERESIS_PROPORTION = 0.1f; const float MINIMUM_VISIBILITY_FOR_ON = 0.4f;
if (_shouldRenderBillboard) { const float MAXIMUM_VISIBILITY_FOR_OFF = 0.6f;
if (getLODDistance() < BILLBOARD_LOD_DISTANCE * (1.0f - BILLBOARD_HYSTERESIS_PROPORTION)) { float visibility = qApp->getViewFrustum()->calculateRenderAccuracy(getBounds(), DependencyManager::get<LODManager>()->getOctreeSizeScale());
_shouldRenderBillboard = false; if (!_shouldAnimate) {
qCDebug(interfaceapp) << "Unbillboarding" << (isMyAvatar() ? "myself" : getSessionUUID()) << "for LOD" << getLODDistance(); if (visibility > MINIMUM_VISIBILITY_FOR_ON) {
_shouldAnimate = true;
qCDebug(interfaceapp) << "Restoring" << (isMyAvatar() ? "myself" : getSessionUUID()) << "for visibility" << visibility;
} }
} else if (getLODDistance() > BILLBOARD_LOD_DISTANCE * (1.0f + BILLBOARD_HYSTERESIS_PROPORTION)) { } else if (visibility < MAXIMUM_VISIBILITY_FOR_OFF) {
_shouldRenderBillboard = true; _shouldAnimate = false;
qCDebug(interfaceapp) << "Billboarding" << (isMyAvatar() ? "myself" : getSessionUUID()) << "for LOD" << getLODDistance(); qCDebug(interfaceapp) << "Optimizing" << (isMyAvatar() ? "myself" : getSessionUUID()) << "for visibility" << visibility;
} }
// simple frustum check // simple frustum check
float boundingRadius = getBillboardSize(); float boundingRadius = getBoundingRadius();
bool inViewFrustum = qApp->getViewFrustum()->sphereInFrustum(getPosition(), boundingRadius) != bool inViewFrustum = qApp->getViewFrustum()->sphereInFrustum(getPosition(), boundingRadius) !=
ViewFrustum::OUTSIDE; ViewFrustum::OUTSIDE;
@ -198,7 +198,7 @@ void Avatar::simulate(float deltaTime) {
getHand()->simulate(deltaTime, false); getHand()->simulate(deltaTime, false);
} }
if (!_shouldRenderBillboard && !_shouldSkipRender && inViewFrustum) { if (_shouldAnimate && !_shouldSkipRender && inViewFrustum) {
{ {
PerformanceTimer perfTimer("skeleton"); PerformanceTimer perfTimer("skeleton");
_skeletonModel.getRig()->copyJointsFromJointData(_jointData); _skeletonModel.getRig()->copyJointsFromJointData(_jointData);
@ -214,7 +214,7 @@ void Avatar::simulate(float deltaTime) {
Head* head = getHead(); Head* head = getHead();
head->setPosition(headPosition); head->setPosition(headPosition);
head->setScale(getUniformScale()); head->setScale(getUniformScale());
head->simulate(deltaTime, false, _shouldRenderBillboard); head->simulate(deltaTime, false, _shouldAnimate);
} }
} }
@ -389,7 +389,7 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) {
} }
// simple frustum check // simple frustum check
float boundingRadius = getBillboardSize(); float boundingRadius = getBoundingRadius();
ViewFrustum* frustum = nullptr; ViewFrustum* frustum = nullptr;
if (renderArgs->_renderMode == RenderArgs::SHADOW_RENDER_MODE) { if (renderArgs->_renderMode == RenderArgs::SHADOW_RENDER_MODE) {
frustum = qApp->getShadowViewFrustum(); frustum = qApp->getShadowViewFrustum();
@ -567,10 +567,7 @@ void Avatar::renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, floa
fixupModelsInScene(); fixupModelsInScene();
{ {
if (_shouldRenderBillboard || !(_skeletonModel.isRenderable() && getHead()->getFaceModel().isRenderable())) { if (_skeletonModel.isRenderable() && getHead()->getFaceModel().isRenderable()) {
// render the billboard until both models are loaded
renderBillboard(renderArgs);
} else {
getHead()->render(renderArgs, 1.0f, renderFrustum); getHead()->render(renderArgs, 1.0f, renderFrustum);
} }
@ -617,50 +614,8 @@ void Avatar::updateJointMappings() {
// no-op; joint mappings come from skeleton model // no-op; joint mappings come from skeleton model
} }
void Avatar::renderBillboard(RenderArgs* renderArgs) { float Avatar::getBoundingRadius() const {
// FIXME disabling the billboard because it doesn't appear to work reliably return getBounds().getLargestDimension() / 2.0f;
// the billboard is ending up with a random texture and position.
return;
if (_billboard.isEmpty()) {
return;
}
if (!_billboardTexture) {
// Using a unique URL ensures we don't get another avatar's texture from TextureCache
QUrl uniqueUrl = QUrl(QUuid::createUuid().toString());
_billboardTexture = DependencyManager::get<TextureCache>()->getTexture(
uniqueUrl, DEFAULT_TEXTURE, _billboard);
}
if (!_billboardTexture || !_billboardTexture->isLoaded()) {
return;
}
// rotate about vertical to face the camera
glm::quat rotation = getOrientation();
glm::vec3 cameraVector = glm::inverse(rotation) * (qApp->getCamera()->getPosition() - getPosition());
rotation = rotation * glm::angleAxis(atan2f(-cameraVector.x, -cameraVector.z), glm::vec3(0.0f, 1.0f, 0.0f));
// compute the size from the billboard camera parameters and scale
float size = getBillboardSize();
Transform transform;
transform.setTranslation(getPosition());
transform.setRotation(rotation);
transform.setScale(size);
glm::vec2 topLeft(-1.0f, -1.0f);
glm::vec2 bottomRight(1.0f, 1.0f);
glm::vec2 texCoordTopLeft(0.0f, 0.0f);
glm::vec2 texCoordBottomRight(1.0f, 1.0f);
gpu::Batch& batch = *renderArgs->_batch;
PROFILE_RANGE_BATCH(batch, __FUNCTION__);
batch.setResourceTexture(0, _billboardTexture->getGPUTexture());
DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch, true);
DependencyManager::get<GeometryCache>()->renderQuad(batch, topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight,
glm::vec4(1.0f, 1.0f, 1.0f, 1.0f));
}
float Avatar::getBillboardSize() const {
return getUniformScale() * BILLBOARD_DISTANCE * glm::tan(glm::radians(BILLBOARD_FIELD_OF_VIEW / 2.0f));
} }
#ifdef DEBUG #ifdef DEBUG
@ -672,7 +627,7 @@ void debugValue(const QString& str, const glm::vec3& value) {
void debugValue(const QString& str, const float& value) { void debugValue(const QString& str, const float& value) {
if (glm::isnan(value) || glm::isinf(value)) { if (glm::isnan(value) || glm::isinf(value)) {
qCWarning(interfaceapp) << "debugValue() " << str << value; qCWarning(interfaceapp) << "debugValue() " << str << value;
} }
}; };
#define DEBUG_VALUE(str, value) debugValue(str, value) #define DEBUG_VALUE(str, value) debugValue(str, value)
#else #else
@ -693,11 +648,11 @@ glm::vec3 Avatar::getDisplayNamePosition() const {
namePosition += bodyUpDirection * headHeight * SLIGHTLY_ABOVE; namePosition += bodyUpDirection * headHeight * SLIGHTLY_ABOVE;
} else { } else {
const float HEAD_PROPORTION = 0.75f; const float HEAD_PROPORTION = 0.75f;
float billboardSize = getBillboardSize(); float size = getBoundingRadius();
DEBUG_VALUE("_position =", getPosition()); DEBUG_VALUE("_position =", getPosition());
DEBUG_VALUE("billboardSize =", billboardSize); DEBUG_VALUE("size =", size);
namePosition = getPosition() + bodyUpDirection * (billboardSize * HEAD_PROPORTION); namePosition = getPosition() + bodyUpDirection * (size * HEAD_PROPORTION);
} }
if (glm::any(glm::isnan(namePosition)) || glm::any(glm::isinf(namePosition))) { if (glm::any(glm::isnan(namePosition)) || glm::any(glm::isinf(namePosition))) {
@ -1001,12 +956,6 @@ void Avatar::setAttachmentData(const QVector<AttachmentData>& attachmentData) {
*/ */
} }
void Avatar::setBillboard(const QByteArray& billboard) {
AvatarData::setBillboard(billboard);
// clear out any existing billboard texture
_billboardTexture.reset();
}
int Avatar::parseDataFromBuffer(const QByteArray& buffer) { int Avatar::parseDataFromBuffer(const QByteArray& buffer) {
startUpdate(); startUpdate();

View file

@ -38,9 +38,6 @@ namespace render {
static const float SCALING_RATIO = .05f; static const float SCALING_RATIO = .05f;
static const float SMOOTHING_RATIO = .05f; // 0 < ratio < 1 static const float SMOOTHING_RATIO = .05f; // 0 < ratio < 1
static const float BILLBOARD_FIELD_OF_VIEW = 30.0f; // degrees
static const float BILLBOARD_DISTANCE = 5.56f; // meters
extern const float CHAT_MESSAGE_SCALE; extern const float CHAT_MESSAGE_SCALE;
extern const float CHAT_MESSAGE_HEIGHT; extern const float CHAT_MESSAGE_HEIGHT;
@ -119,7 +116,6 @@ public:
virtual void setFaceModelURL(const QUrl& faceModelURL) override; virtual void setFaceModelURL(const QUrl& faceModelURL) override;
virtual void setSkeletonModelURL(const QUrl& skeletonModelURL) override; virtual void setSkeletonModelURL(const QUrl& skeletonModelURL) override;
virtual void setAttachmentData(const QVector<AttachmentData>& attachmentData) override; virtual void setAttachmentData(const QVector<AttachmentData>& attachmentData) override;
virtual void setBillboard(const QByteArray& billboard) override;
void setShowDisplayName(bool showDisplayName); void setShowDisplayName(bool showDisplayName);
@ -254,14 +250,11 @@ protected:
private: private:
bool _initialized; bool _initialized;
NetworkTexturePointer _billboardTexture; bool _shouldAnimate { true };
bool _shouldRenderBillboard;
bool _shouldSkipRender { false }; bool _shouldSkipRender { false };
bool _isLookAtTarget; bool _isLookAtTarget;
void renderBillboard(RenderArgs* renderArgs); float getBoundingRadius() const;
float getBillboardSize() const;
static int _jointConesID; static int _jointConesID;

View file

@ -33,10 +33,6 @@ void AvatarUpdate::synchronousProcess() {
auto frameCount = qApp->getFrameCount(); auto frameCount = qApp->getFrameCount();
_headPose = qApp->getActiveDisplayPlugin()->getHeadPose(frameCount); _headPose = qApp->getActiveDisplayPlugin()->getHeadPose(frameCount);
if (_updateBillboard) {
DependencyManager::get<AvatarManager>()->getMyAvatar()->doUpdateBillboard();
}
if (!isThreaded()) { if (!isThreaded()) {
process(); process();
} }

View file

@ -22,13 +22,11 @@ class AvatarUpdate : public GenericThread {
public: public:
AvatarUpdate(); AvatarUpdate();
void synchronousProcess(); void synchronousProcess();
void setRequestBillboardUpdate(bool needsUpdate) { _updateBillboard = needsUpdate; }
private: private:
virtual bool process(); // No reason for other classes to invoke this. virtual bool process(); // No reason for other classes to invoke this.
quint64 _lastAvatarUpdate; // microsoeconds quint64 _lastAvatarUpdate; // microsoeconds
quint64 _targetInterval; // microseconds quint64 _targetInterval; // microseconds
bool _updateBillboard;
// Goes away if Application::getActiveDisplayPlugin() and friends are made thread safe: // Goes away if Application::getActiveDisplayPlugin() and friends are made thread safe:
public: public:

View file

@ -97,7 +97,6 @@ MyAvatar::MyAvatar(RigPointer rig) :
_characterController(this), _characterController(this),
_lookAtTargetAvatar(), _lookAtTargetAvatar(),
_shouldRender(true), _shouldRender(true),
_billboardValid(false),
_eyeContactTarget(LEFT_EYE), _eyeContactTarget(LEFT_EYE),
_realWorldFieldOfView("realWorldFieldOfView", _realWorldFieldOfView("realWorldFieldOfView",
DEFAULT_REAL_WORLD_FIELD_OF_VIEW_DEGREES), DEFAULT_REAL_WORLD_FIELD_OF_VIEW_DEGREES),
@ -229,7 +228,7 @@ void MyAvatar::reset(bool andReload) {
} }
// Reset dynamic state. // Reset dynamic state.
_wasPushing = _isPushing = _isBraking = _billboardValid = false; _wasPushing = _isPushing = _isBraking = false;
_follow.deactivate(); _follow.deactivate();
_skeletonModel.reset(); _skeletonModel.reset();
getHead()->reset(); getHead()->reset();
@ -364,9 +363,6 @@ void MyAvatar::simulate(float deltaTime) {
recorder->recordFrame(FRAME_TYPE, toFrame(*this)); recorder->recordFrame(FRAME_TYPE, toFrame(*this));
} }
// consider updating our billboard
maybeUpdateBillboard();
locationChanged(); locationChanged();
// if a entity-child of this avatar has moved outside of its queryAACube, update the cube and tell the entity server. // if a entity-child of this avatar has moved outside of its queryAACube, update the cube and tell the entity server.
EntityTreeRenderer* entityTreeRenderer = qApp->getEntities(); EntityTreeRenderer* entityTreeRenderer = qApp->getEntities();
@ -983,14 +979,12 @@ void MyAvatar::setFaceModelURL(const QUrl& faceModelURL) {
Avatar::setFaceModelURL(faceModelURL); Avatar::setFaceModelURL(faceModelURL);
render::ScenePointer scene = qApp->getMain3DScene(); render::ScenePointer scene = qApp->getMain3DScene();
getHead()->getFaceModel().setVisibleInScene(_prevShouldDrawHead, scene); getHead()->getFaceModel().setVisibleInScene(_prevShouldDrawHead, scene);
_billboardValid = false;
} }
void MyAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) { void MyAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) {
Avatar::setSkeletonModelURL(skeletonModelURL); Avatar::setSkeletonModelURL(skeletonModelURL);
render::ScenePointer scene = qApp->getMain3DScene(); render::ScenePointer scene = qApp->getMain3DScene();
_billboardValid = false;
_skeletonModel.setVisibleInScene(true, scene); _skeletonModel.setVisibleInScene(true, scene);
_headBoneSet.clear(); _headBoneSet.clear();
} }
@ -1043,7 +1037,6 @@ void MyAvatar::setAttachmentData(const QVector<AttachmentData>& attachmentData)
return; return;
} }
Avatar::setAttachmentData(attachmentData); Avatar::setAttachmentData(attachmentData);
_billboardValid = false;
} }
glm::vec3 MyAvatar::getSkeletonPosition() const { glm::vec3 MyAvatar::getSkeletonPosition() const {
@ -1583,33 +1576,6 @@ bool findAvatarAvatarPenetration(const glm::vec3 positionA, float radiusA, float
return false; return false;
} }
void MyAvatar::maybeUpdateBillboard() {
qApp->getAvatarUpdater()->setRequestBillboardUpdate(false);
if (_billboardValid || !(_skeletonModel.isLoadedWithTextures() && getHead()->getFaceModel().isLoadedWithTextures())) {
return;
}
for (auto& model : _attachmentModels) {
if (!model->isLoadedWithTextures()) {
return;
}
}
qApp->getAvatarUpdater()->setRequestBillboardUpdate(true);
}
void MyAvatar::doUpdateBillboard() {
RenderArgs renderArgs(qApp->getGPUContext());
QImage image = qApp->renderAvatarBillboard(&renderArgs);
_billboard.clear();
QBuffer buffer(&_billboard);
buffer.open(QIODevice::WriteOnly);
image.save(&buffer, "PNG");
#ifdef DEBUG
image.save("billboard.png", "PNG");
#endif
_billboardValid = true;
sendBillboardPacket();
}
bool MyAvatar::isHovering() const { bool MyAvatar::isHovering() const {
return _characterController.isHovering(); return _characterController.isHovering();
} }

View file

@ -223,7 +223,6 @@ public:
static const float ZOOM_MAX; static const float ZOOM_MAX;
static const float ZOOM_DEFAULT; static const float ZOOM_DEFAULT;
void doUpdateBillboard();
void destroyAnimGraph(); void destroyAnimGraph();
AudioListenerMode getAudioListenerMode() { return _audioListenerMode; } AudioListenerMode getAudioListenerMode() { return _audioListenerMode; }
@ -340,7 +339,6 @@ private:
AvatarWeakPointer _lookAtTargetAvatar; AvatarWeakPointer _lookAtTargetAvatar;
glm::vec3 _targetAvatarPosition; glm::vec3 _targetAvatarPosition;
bool _shouldRender; bool _shouldRender;
bool _billboardValid;
float _oculusYawOffset; float _oculusYawOffset;
eyeContactTarget _eyeContactTarget; eyeContactTarget _eyeContactTarget;
@ -355,7 +353,6 @@ private:
glm::vec3 applyScriptedMotor(float deltaTime, const glm::vec3& velocity); glm::vec3 applyScriptedMotor(float deltaTime, const glm::vec3& velocity);
void updatePosition(float deltaTime); void updatePosition(float deltaTime);
void updateCollisionSound(const glm::vec3& penetration, float deltaTime, float frequency); void updateCollisionSound(const glm::vec3& penetration, float deltaTime, float frequency);
void maybeUpdateBillboard();
void initHeadBones(); void initHeadBones();
void initAnimGraph(); void initAnimGraph();

View file

@ -1113,7 +1113,7 @@ void Model::deleteGeometry() {
_blendedBlendshapeCoefficients.clear(); _blendedBlendshapeCoefficients.clear();
} }
AABox Model::getPartBounds(int meshIndex, int partIndex, glm::vec3 modelPosition, glm::quat modelOrientation) { AABox Model::getPartBounds(int meshIndex, int partIndex, glm::vec3 modelPosition, glm::quat modelOrientation) const {
if (!_geometry || !_geometry->isLoaded()) { if (!_geometry || !_geometry->isLoaded()) {
return AABox(); return AABox();

View file

@ -89,7 +89,7 @@ public:
bool isVisible() const { return _isVisible; } bool isVisible() const { return _isVisible; }
void updateRenderItems(); void updateRenderItems();
AABox getPartBounds(int meshIndex, int partIndex, glm::vec3 modelPosition, glm::quat modelOrientation); AABox getPartBounds(int meshIndex, int partIndex, glm::vec3 modelPosition, glm::quat modelOrientation) const;
bool maybeStartBlender(); bool maybeStartBlender();