mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-09 09:30:09 +02:00
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:
commit
711787a997
12 changed files with 46 additions and 210 deletions
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue