mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 01:24:03 +02:00
fix avatar scale animation and avatar render debug
This commit is contained in:
parent
40e223cb82
commit
662c34c266
8 changed files with 117 additions and 70 deletions
|
@ -192,6 +192,7 @@ void Avatar::animateScaleChanges(float deltaTime) {
|
|||
_isAnimatingScale = false;
|
||||
}
|
||||
setScale(glm::vec3(animatedScale)); // avatar scale is uniform
|
||||
_hasNewJointData = true;
|
||||
|
||||
// TODO: rebuilding the shape constantly is somehwat expensive.
|
||||
// We should only rebuild after significant change.
|
||||
|
@ -200,8 +201,12 @@ void Avatar::animateScaleChanges(float deltaTime) {
|
|||
}
|
||||
|
||||
void Avatar::setTargetScale(float targetScale) {
|
||||
AvatarData::setTargetScale(targetScale);
|
||||
_isAnimatingScale = true;
|
||||
float newValue = glm::clamp(targetScale, MIN_AVATAR_SCALE, MAX_AVATAR_SCALE);
|
||||
if (_targetScale != newValue) {
|
||||
_targetScale = newValue;
|
||||
_scaleChanged = usecTimestampNow();
|
||||
_isAnimatingScale = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Avatar::updateAvatarEntities() {
|
||||
|
|
|
@ -285,6 +285,7 @@ protected:
|
|||
|
||||
void addToScene(AvatarSharedPointer self);
|
||||
void ensureInScene(AvatarSharedPointer self);
|
||||
bool isInScene() const { return render::Item::isValidID(_renderItemID); }
|
||||
|
||||
// Some rate tracking support
|
||||
RateCounter<> _simulationRate;
|
||||
|
|
|
@ -100,15 +100,16 @@ void AvatarManager::init() {
|
|||
_avatarHash.insert(MY_AVATAR_KEY, _myAvatar);
|
||||
}
|
||||
|
||||
_shouldRender = DependencyManager::get<SceneScriptingInterface>()->shouldRenderAvatars();
|
||||
connect(DependencyManager::get<SceneScriptingInterface>().data(), &SceneScriptingInterface::shouldRenderAvatarsChanged,
|
||||
this, &AvatarManager::updateAvatarRenderStatus, Qt::QueuedConnection);
|
||||
|
||||
render::ScenePointer scene = qApp->getMain3DScene();
|
||||
render::Transaction transaction;
|
||||
if (DependencyManager::get<SceneScriptingInterface>()->shouldRenderAvatars()) {
|
||||
if (_shouldRender) {
|
||||
render::ScenePointer scene = qApp->getMain3DScene();
|
||||
render::Transaction transaction;
|
||||
_myAvatar->addToScene(_myAvatar, scene, transaction);
|
||||
scene->enqueueTransaction(transaction);
|
||||
}
|
||||
scene->enqueueTransaction(transaction);
|
||||
}
|
||||
|
||||
void AvatarManager::updateMyAvatar(float deltaTime) {
|
||||
|
@ -181,30 +182,24 @@ void AvatarManager::updateOtherAvatars(float deltaTime) {
|
|||
// DO NOT update or fade out uninitialized Avatars
|
||||
return true; // ignore it
|
||||
}
|
||||
if (avatar->shouldDie()) {
|
||||
removeAvatar(avatar->getID());
|
||||
return true; // ignore it
|
||||
}
|
||||
if (avatar->isDead()) {
|
||||
return true; // ignore it
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
render::Transaction transaction;
|
||||
uint64_t startTime = usecTimestampNow();
|
||||
const uint64_t UPDATE_BUDGET = 2000; // usec
|
||||
uint64_t updateExpiry = startTime + UPDATE_BUDGET;
|
||||
|
||||
int numAvatarsUpdated = 0;
|
||||
int numAVatarsNotUpdated = 0;
|
||||
|
||||
render::Transaction transaction;
|
||||
while (!sortedAvatars.empty()) {
|
||||
const AvatarPriority& sortData = sortedAvatars.top();
|
||||
const auto& avatar = std::static_pointer_cast<Avatar>(sortData.avatar);
|
||||
|
||||
// for ALL avatars...
|
||||
avatar->ensureInScene(avatar);
|
||||
if (_shouldRender) {
|
||||
avatar->ensureInScene(avatar);
|
||||
}
|
||||
if (!avatar->getMotionState()) {
|
||||
ShapeInfo shapeInfo;
|
||||
avatar->computeShapeInfo(shapeInfo);
|
||||
|
@ -218,6 +213,10 @@ void AvatarManager::updateOtherAvatars(float deltaTime) {
|
|||
}
|
||||
}
|
||||
avatar->animateScaleChanges(deltaTime);
|
||||
if (avatar->shouldDie()) {
|
||||
avatar->die();
|
||||
removeAvatar(avatar->getID());
|
||||
}
|
||||
|
||||
const float OUT_OF_VIEW_THRESHOLD = 0.5f * AvatarData::OUT_OF_VIEW_PENALTY;
|
||||
uint64_t now = usecTimestampNow();
|
||||
|
@ -259,10 +258,21 @@ void AvatarManager::updateOtherAvatars(float deltaTime) {
|
|||
sortedAvatars.pop();
|
||||
}
|
||||
|
||||
if (_shouldRender) {
|
||||
QVector<AvatarSharedPointer>::iterator itr = _avatarsToFade.begin();
|
||||
while (itr != _avatarsToFade.end() && usecTimestampNow() > updateExpiry) {
|
||||
auto avatar = std::static_pointer_cast<Avatar>(*itr);
|
||||
avatar->animateScaleChanges(deltaTime);
|
||||
avatar->simulate(deltaTime, true);
|
||||
avatar->updateRenderItem(transaction);
|
||||
++itr;
|
||||
}
|
||||
qApp->getMain3DScene()->enqueueTransaction(transaction);
|
||||
}
|
||||
|
||||
_avatarSimulationTime = (float)(usecTimestampNow() - startTime) / (float)USECS_PER_MSEC;
|
||||
_numAvatarsUpdated = numAvatarsUpdated;
|
||||
_numAvatarsNotUpdated = numAVatarsNotUpdated;
|
||||
qApp->getMain3DScene()->enqueueTransaction(transaction);
|
||||
|
||||
simulateAvatarFades(deltaTime);
|
||||
}
|
||||
|
@ -277,38 +287,68 @@ void AvatarManager::postUpdate(float deltaTime) {
|
|||
}
|
||||
|
||||
void AvatarManager::simulateAvatarFades(float deltaTime) {
|
||||
QVector<AvatarSharedPointer>::iterator fadingIterator = _avatarsToFade.begin();
|
||||
QVector<AvatarSharedPointer>::iterator itr = _avatarsToFade.begin();
|
||||
|
||||
const float SHRINK_RATE = 0.15f;
|
||||
const float MIN_FADE_SCALE = MIN_AVATAR_SCALE;
|
||||
|
||||
render::ScenePointer scene = qApp->getMain3DScene();
|
||||
render::Transaction transaction;
|
||||
while (fadingIterator != _avatarsToFade.end()) {
|
||||
auto avatar = std::static_pointer_cast<Avatar>(*fadingIterator);
|
||||
while (itr != _avatarsToFade.end()) {
|
||||
auto avatar = std::static_pointer_cast<Avatar>(*itr);
|
||||
avatar->setTargetScale(avatar->getUniformScale() * SHRINK_RATE);
|
||||
avatar->animateScaleChanges(deltaTime);
|
||||
if (avatar->getTargetScale() <= MIN_FADE_SCALE) {
|
||||
avatar->removeFromScene(*fadingIterator, scene, transaction);
|
||||
// fading to zero is such a rare event we push unique transaction for each one
|
||||
removeAvatar(avatar->getID());
|
||||
if (avatar->isInScene()) {
|
||||
render::ScenePointer scene = qApp->getMain3DScene();
|
||||
render::Transaction transaction;
|
||||
avatar->removeFromScene(*itr, scene, transaction);
|
||||
scene->enqueueTransaction(transaction);
|
||||
}
|
||||
|
||||
// only remove from _avatarsToFade if we're sure its motionState has been removed from PhysicsEngine
|
||||
if (_motionStatesToRemoveFromPhysics.empty()) {
|
||||
fadingIterator = _avatarsToFade.erase(fadingIterator);
|
||||
itr = _avatarsToFade.erase(itr);
|
||||
} else {
|
||||
++fadingIterator;
|
||||
++itr;
|
||||
}
|
||||
} else {
|
||||
const bool inView = true; // HACK
|
||||
avatar->simulate(deltaTime, inView);
|
||||
++fadingIterator;
|
||||
++itr;
|
||||
}
|
||||
}
|
||||
scene->enqueueTransaction(transaction);
|
||||
}
|
||||
|
||||
AvatarSharedPointer AvatarManager::newSharedAvatar() {
|
||||
std::shared_ptr<Avatar> avatar = std::make_shared<Avatar>(std::make_shared<Rig>());
|
||||
avatar->addToScene(avatar);
|
||||
return avatar;
|
||||
return std::make_shared<Avatar>(std::make_shared<Rig>());
|
||||
}
|
||||
|
||||
void AvatarManager::processAvatarDataPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode) {
|
||||
PerformanceTimer perfTimer("receiveAvatar");
|
||||
// enumerate over all of the avatars in this packet
|
||||
// only add them if mixerWeakPointer points to something (meaning that mixer is still around)
|
||||
while (message->getBytesLeftToRead()) {
|
||||
AvatarSharedPointer avatarData = parseAvatarData(message, sendingNode);
|
||||
if (avatarData) {
|
||||
auto avatar = std::static_pointer_cast<Avatar>(avatarData);
|
||||
if (avatar->isInScene()) {
|
||||
if (!_shouldRender) {
|
||||
// rare transition so we process pending changes immediately
|
||||
render::ScenePointer scene = qApp->getMain3DScene();
|
||||
render::Transaction transaction;
|
||||
avatar->removeFromScene(avatar, scene, transaction);
|
||||
scene->enqueueTransaction(transaction);
|
||||
}
|
||||
} else if (_shouldRender) {
|
||||
// very rare transition so we process pending changes immediately
|
||||
render::ScenePointer scene = qApp->getMain3DScene();
|
||||
render::Transaction transaction;
|
||||
avatar->addToScene(avatar, scene, transaction);
|
||||
scene->enqueueTransaction(transaction);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AvatarManager::handleRemovedAvatar(const AvatarSharedPointer& removedAvatar, KillAvatarReason removalReason) {
|
||||
|
@ -458,26 +498,23 @@ void AvatarManager::handleCollisionEvents(const CollisionEvents& collisionEvents
|
|||
}
|
||||
|
||||
void AvatarManager::updateAvatarRenderStatus(bool shouldRenderAvatars) {
|
||||
if (DependencyManager::get<SceneScriptingInterface>()->shouldRenderAvatars()) {
|
||||
_shouldRender = shouldRenderAvatars;
|
||||
render::ScenePointer scene = qApp->getMain3DScene();
|
||||
render::Transaction transaction;
|
||||
if (_shouldRender) {
|
||||
for (auto avatarData : _avatarHash) {
|
||||
auto avatar = std::static_pointer_cast<Avatar>(avatarData);
|
||||
render::ScenePointer scene = qApp->getMain3DScene();
|
||||
render::Transaction transaction;
|
||||
avatar->addToScene(avatar, scene, transaction);
|
||||
scene->enqueueTransaction(transaction);
|
||||
}
|
||||
} else {
|
||||
for (auto avatarData : _avatarHash) {
|
||||
auto avatar = std::static_pointer_cast<Avatar>(avatarData);
|
||||
render::ScenePointer scene = qApp->getMain3DScene();
|
||||
render::Transaction transaction;
|
||||
avatar->removeFromScene(avatar, scene, transaction);
|
||||
scene->enqueueTransaction(transaction);
|
||||
}
|
||||
}
|
||||
scene->enqueueTransaction(transaction);
|
||||
}
|
||||
|
||||
|
||||
AvatarSharedPointer AvatarManager::getAvatarBySessionID(const QUuid& sessionID) const {
|
||||
if (sessionID == AVATAR_SELF_ID || sessionID == _myAvatar->getSessionUUID()) {
|
||||
return _myAvatar;
|
||||
|
|
|
@ -91,6 +91,9 @@ public slots:
|
|||
void setShouldShowReceiveStats(bool shouldShowReceiveStats) { _shouldShowReceiveStats = shouldShowReceiveStats; }
|
||||
void updateAvatarRenderStatus(bool shouldRenderAvatars);
|
||||
|
||||
protected slots:
|
||||
void processAvatarDataPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode) override;
|
||||
|
||||
private:
|
||||
explicit AvatarManager(QObject* parent = 0);
|
||||
explicit AvatarManager(const AvatarManager& other);
|
||||
|
@ -100,12 +103,6 @@ private:
|
|||
AvatarSharedPointer newSharedAvatar() override;
|
||||
void handleRemovedAvatar(const AvatarSharedPointer& removedAvatar, KillAvatarReason removalReason = KillAvatarReason::NoReason) override;
|
||||
|
||||
/* TODO: maintain these lists
|
||||
QVector<AvatarSharedPointer> _avatarsToRemoveFromScene;
|
||||
QVector<AvatarSharedPointer> _avatarsToAddToScene;
|
||||
QVector<AvatarSharedPointer> _avatarsToRemoveFromPhysicsEngine;
|
||||
QVector<AvatarSharedPointer> _avatarsToAddToPhysicsEngine;
|
||||
*/
|
||||
QVector<AvatarSharedPointer> _avatarsToFade;
|
||||
|
||||
SetOfAvatarMotionStates _motionStatesThatMightUpdate;
|
||||
|
@ -125,6 +122,7 @@ private:
|
|||
int _numAvatarsUpdated { 0 };
|
||||
int _numAvatarsNotUpdated { 0 };
|
||||
float _avatarSimulationTime { 0.0f };
|
||||
bool _shouldRender { true };
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(AvatarManager::LocalLight)
|
||||
|
|
|
@ -54,6 +54,7 @@
|
|||
#include "DebugDraw.h"
|
||||
#include "EntityEditPacketSender.h"
|
||||
#include "MovingEntitiesOperator.h"
|
||||
#include "SceneScriptingInterface.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
@ -1634,7 +1635,7 @@ void MyAvatar::postUpdate(float deltaTime) {
|
|||
Avatar::postUpdate(deltaTime);
|
||||
|
||||
render::ScenePointer scene = qApp->getMain3DScene();
|
||||
if (_skeletonModel->initWhenReady(scene)) {
|
||||
if (DependencyManager::get<SceneScriptingInterface>()->shouldRenderAvatars() && _skeletonModel->initWhenReady(scene)) {
|
||||
initHeadBones();
|
||||
_skeletonModel->setCauterizeBoneSet(_headBoneSet);
|
||||
_fstAnimGraphOverrideUrl = _skeletonModel->getGeometry()->getAnimGraphOverrideUrl();
|
||||
|
|
|
@ -123,6 +123,7 @@ void AvatarData::setTargetScale(float targetScale) {
|
|||
if (_targetScale != newValue) {
|
||||
_targetScale = newValue;
|
||||
_scaleChanged = usecTimestampNow();
|
||||
_avatarScaleChanged = _scaleChanged;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -80,13 +80,10 @@ AvatarSharedPointer AvatarHashMap::addAvatar(const QUuid& sessionUUID, const QWe
|
|||
|
||||
AvatarSharedPointer AvatarHashMap::newOrExistingAvatar(const QUuid& sessionUUID, const QWeakPointer<Node>& mixerWeakPointer) {
|
||||
QWriteLocker locker(&_hashLock);
|
||||
|
||||
auto avatar = _avatarHash.value(sessionUUID);
|
||||
|
||||
if (!avatar) {
|
||||
avatar = addAvatar(sessionUUID, mixerWeakPointer);
|
||||
}
|
||||
|
||||
return avatar;
|
||||
}
|
||||
|
||||
|
@ -103,27 +100,33 @@ void AvatarHashMap::processAvatarDataPacket(QSharedPointer<ReceivedMessage> mess
|
|||
// enumerate over all of the avatars in this packet
|
||||
// only add them if mixerWeakPointer points to something (meaning that mixer is still around)
|
||||
while (message->getBytesLeftToRead()) {
|
||||
QUuid sessionUUID = QUuid::fromRfc4122(message->readWithoutCopy(NUM_BYTES_RFC4122_UUID));
|
||||
parseAvatarData(message, sendingNode);
|
||||
}
|
||||
}
|
||||
|
||||
int positionBeforeRead = message->getPosition();
|
||||
AvatarSharedPointer AvatarHashMap::parseAvatarData(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode) {
|
||||
QUuid sessionUUID = QUuid::fromRfc4122(message->readWithoutCopy(NUM_BYTES_RFC4122_UUID));
|
||||
|
||||
QByteArray byteArray = message->readWithoutCopy(message->getBytesLeftToRead());
|
||||
int positionBeforeRead = message->getPosition();
|
||||
|
||||
// make sure this isn't our own avatar data or for a previously ignored node
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
QByteArray byteArray = message->readWithoutCopy(message->getBytesLeftToRead());
|
||||
|
||||
if (sessionUUID != _lastOwnerSessionUUID && (!nodeList->isIgnoringNode(sessionUUID) || nodeList->getRequestsDomainListData())) {
|
||||
auto avatar = newOrExistingAvatar(sessionUUID, sendingNode);
|
||||
// make sure this isn't our own avatar data or for a previously ignored node
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
|
||||
// have the matching (or new) avatar parse the data from the packet
|
||||
int bytesRead = avatar->parseDataFromBuffer(byteArray);
|
||||
message->seek(positionBeforeRead + bytesRead);
|
||||
} else {
|
||||
// create a dummy AvatarData class to throw this data on the ground
|
||||
AvatarData dummyData;
|
||||
int bytesRead = dummyData.parseDataFromBuffer(byteArray);
|
||||
message->seek(positionBeforeRead + bytesRead);
|
||||
}
|
||||
if (sessionUUID != _lastOwnerSessionUUID && (!nodeList->isIgnoringNode(sessionUUID) || nodeList->getRequestsDomainListData())) {
|
||||
auto avatar = newOrExistingAvatar(sessionUUID, sendingNode);
|
||||
|
||||
// have the matching (or new) avatar parse the data from the packet
|
||||
int bytesRead = avatar->parseDataFromBuffer(byteArray);
|
||||
message->seek(positionBeforeRead + bytesRead);
|
||||
return avatar;
|
||||
} else {
|
||||
// create a dummy AvatarData class to throw this data on the ground
|
||||
AvatarData dummyData;
|
||||
int bytesRead = dummyData.parseDataFromBuffer(byteArray);
|
||||
message->seek(positionBeforeRead + bytesRead);
|
||||
return std::make_shared<AvatarData>();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -49,11 +49,11 @@ signals:
|
|||
|
||||
public slots:
|
||||
bool isAvatarInRange(const glm::vec3 & position, const float range);
|
||||
|
||||
private slots:
|
||||
|
||||
protected slots:
|
||||
void sessionUUIDChanged(const QUuid& sessionUUID, const QUuid& oldUUID);
|
||||
|
||||
void processAvatarDataPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode);
|
||||
|
||||
virtual void processAvatarDataPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode);
|
||||
void processAvatarIdentityPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode);
|
||||
void processKillAvatar(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode);
|
||||
void processExitingSpaceBubble(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode);
|
||||
|
@ -61,12 +61,13 @@ private slots:
|
|||
protected:
|
||||
AvatarHashMap();
|
||||
|
||||
virtual AvatarSharedPointer parseAvatarData(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode);
|
||||
virtual AvatarSharedPointer newSharedAvatar();
|
||||
virtual AvatarSharedPointer addAvatar(const QUuid& sessionUUID, const QWeakPointer<Node>& mixerWeakPointer);
|
||||
AvatarSharedPointer newOrExistingAvatar(const QUuid& sessionUUID, const QWeakPointer<Node>& mixerWeakPointer);
|
||||
virtual AvatarSharedPointer findAvatar(const QUuid& sessionUUID) const; // uses a QReadLocker on the hashLock
|
||||
virtual void removeAvatar(const QUuid& sessionUUID, KillAvatarReason removalReason = KillAvatarReason::NoReason);
|
||||
|
||||
|
||||
virtual void handleRemovedAvatar(const AvatarSharedPointer& removedAvatar, KillAvatarReason removalReason = KillAvatarReason::NoReason);
|
||||
|
||||
AvatarHash _avatarHash;
|
||||
|
|
Loading…
Reference in a new issue