mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-10 02:53:01 +02:00
Merge pull request #10146 from AndrewMeadows/avoid-invisible-avatars-002
avoid invisible avatars redux
This commit is contained in:
commit
bf16309917
9 changed files with 173 additions and 118 deletions
|
@ -1802,10 +1802,11 @@ Application::~Application() {
|
||||||
_physicsEngine->setCharacterController(nullptr);
|
_physicsEngine->setCharacterController(nullptr);
|
||||||
|
|
||||||
// remove avatars from physics engine
|
// remove avatars from physics engine
|
||||||
DependencyManager::get<AvatarManager>()->clearAllAvatars();
|
DependencyManager::get<AvatarManager>()->clearOtherAvatars();
|
||||||
VectorOfMotionStates motionStates;
|
VectorOfMotionStates motionStates;
|
||||||
DependencyManager::get<AvatarManager>()->getObjectsToRemoveFromPhysics(motionStates);
|
DependencyManager::get<AvatarManager>()->getObjectsToRemoveFromPhysics(motionStates);
|
||||||
_physicsEngine->removeObjects(motionStates);
|
_physicsEngine->removeObjects(motionStates);
|
||||||
|
DependencyManager::get<AvatarManager>()->deleteAllAvatars();
|
||||||
|
|
||||||
DependencyManager::destroy<AvatarManager>();
|
DependencyManager::destroy<AvatarManager>();
|
||||||
DependencyManager::destroy<AnimationCache>();
|
DependencyManager::destroy<AnimationCache>();
|
||||||
|
|
|
@ -193,6 +193,9 @@ void Avatar::animateScaleChanges(float deltaTime) {
|
||||||
}
|
}
|
||||||
setScale(glm::vec3(animatedScale)); // avatar scale is uniform
|
setScale(glm::vec3(animatedScale)); // avatar scale is uniform
|
||||||
|
|
||||||
|
// flag the joints as having changed for force update to RenderItem
|
||||||
|
_hasNewJointData = true;
|
||||||
|
|
||||||
// TODO: rebuilding the shape constantly is somehwat expensive.
|
// TODO: rebuilding the shape constantly is somehwat expensive.
|
||||||
// We should only rebuild after significant change.
|
// We should only rebuild after significant change.
|
||||||
rebuildCollisionShape();
|
rebuildCollisionShape();
|
||||||
|
@ -200,8 +203,12 @@ void Avatar::animateScaleChanges(float deltaTime) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Avatar::setTargetScale(float targetScale) {
|
void Avatar::setTargetScale(float targetScale) {
|
||||||
AvatarData::setTargetScale(targetScale);
|
float newValue = glm::clamp(targetScale, MIN_AVATAR_SCALE, MAX_AVATAR_SCALE);
|
||||||
_isAnimatingScale = true;
|
if (_targetScale != newValue) {
|
||||||
|
_targetScale = newValue;
|
||||||
|
_scaleChanged = usecTimestampNow();
|
||||||
|
_isAnimatingScale = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Avatar::updateAvatarEntities() {
|
void Avatar::updateAvatarEntities() {
|
||||||
|
@ -476,7 +483,7 @@ static TextRenderer3D* textRenderer(TextRendererType type) {
|
||||||
return displayNameRenderer;
|
return displayNameRenderer;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Avatar::addToScene(AvatarSharedPointer self, std::shared_ptr<render::Scene> scene, render::Transaction& transaction) {
|
void Avatar::addToScene(AvatarSharedPointer self, std::shared_ptr<render::Scene> scene, render::Transaction& transaction) {
|
||||||
auto avatarPayload = new render::Payload<AvatarData>(self);
|
auto avatarPayload = new render::Payload<AvatarData>(self);
|
||||||
auto avatarPayloadPointer = Avatar::PayloadPointer(avatarPayload);
|
auto avatarPayloadPointer = Avatar::PayloadPointer(avatarPayload);
|
||||||
_renderItemID = scene->allocateID();
|
_renderItemID = scene->allocateID();
|
||||||
|
@ -486,9 +493,6 @@ bool Avatar::addToScene(AvatarSharedPointer self, std::shared_ptr<render::Scene>
|
||||||
for (auto& attachmentModel : _attachmentModels) {
|
for (auto& attachmentModel : _attachmentModels) {
|
||||||
attachmentModel->addToScene(scene, transaction);
|
attachmentModel->addToScene(scene, transaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
_inScene = true;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Avatar::removeFromScene(AvatarSharedPointer self, std::shared_ptr<render::Scene> scene, render::Transaction& transaction) {
|
void Avatar::removeFromScene(AvatarSharedPointer self, std::shared_ptr<render::Scene> scene, render::Transaction& transaction) {
|
||||||
|
@ -498,7 +502,6 @@ void Avatar::removeFromScene(AvatarSharedPointer self, std::shared_ptr<render::S
|
||||||
for (auto& attachmentModel : _attachmentModels) {
|
for (auto& attachmentModel : _attachmentModels) {
|
||||||
attachmentModel->removeFromScene(scene, transaction);
|
attachmentModel->removeFromScene(scene, transaction);
|
||||||
}
|
}
|
||||||
_inScene = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Avatar::updateRenderItem(render::Transaction& transaction) {
|
void Avatar::updateRenderItem(render::Transaction& transaction) {
|
||||||
|
@ -1450,7 +1453,7 @@ void Avatar::addToScene(AvatarSharedPointer myHandle) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void Avatar::ensureInScene(AvatarSharedPointer self) {
|
void Avatar::ensureInScene(AvatarSharedPointer self) {
|
||||||
if (!_inScene) {
|
if (!render::Item::isValidID(_renderItemID)) {
|
||||||
addToScene(self);
|
addToScene(self);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,7 +81,7 @@ public:
|
||||||
|
|
||||||
virtual void render(RenderArgs* renderArgs, const glm::vec3& cameraPosition);
|
virtual void render(RenderArgs* renderArgs, const glm::vec3& cameraPosition);
|
||||||
|
|
||||||
bool addToScene(AvatarSharedPointer self, std::shared_ptr<render::Scene> scene,
|
void addToScene(AvatarSharedPointer self, std::shared_ptr<render::Scene> scene,
|
||||||
render::Transaction& transaction);
|
render::Transaction& transaction);
|
||||||
|
|
||||||
void removeFromScene(AvatarSharedPointer self, std::shared_ptr<render::Scene> scene,
|
void removeFromScene(AvatarSharedPointer self, std::shared_ptr<render::Scene> scene,
|
||||||
|
@ -305,6 +305,7 @@ protected:
|
||||||
|
|
||||||
void addToScene(AvatarSharedPointer self);
|
void addToScene(AvatarSharedPointer self);
|
||||||
void ensureInScene(AvatarSharedPointer self);
|
void ensureInScene(AvatarSharedPointer self);
|
||||||
|
bool isInScene() const { return render::Item::isValidID(_renderItemID); }
|
||||||
|
|
||||||
// Some rate tracking support
|
// Some rate tracking support
|
||||||
RateCounter<> _simulationRate;
|
RateCounter<> _simulationRate;
|
||||||
|
@ -330,7 +331,6 @@ private:
|
||||||
int _nameRectGeometryID { 0 };
|
int _nameRectGeometryID { 0 };
|
||||||
bool _initialized;
|
bool _initialized;
|
||||||
bool _isLookAtTarget { false };
|
bool _isLookAtTarget { false };
|
||||||
bool _inScene { false };
|
|
||||||
bool _isAnimatingScale { false };
|
bool _isAnimatingScale { false };
|
||||||
|
|
||||||
float getBoundingRadius() const;
|
float getBoundingRadius() const;
|
||||||
|
|
|
@ -68,7 +68,7 @@ void AvatarManager::registerMetaTypes(QScriptEngine* engine) {
|
||||||
}
|
}
|
||||||
|
|
||||||
AvatarManager::AvatarManager(QObject* parent) :
|
AvatarManager::AvatarManager(QObject* parent) :
|
||||||
_avatarFades(),
|
_avatarsToFade(),
|
||||||
_myAvatar(std::make_shared<MyAvatar>(std::make_shared<Rig>()))
|
_myAvatar(std::make_shared<MyAvatar>(std::make_shared<Rig>()))
|
||||||
{
|
{
|
||||||
// register a meta type for the weak pointer we'll use for the owning avatar mixer for each avatar
|
// register a meta type for the weak pointer we'll use for the owning avatar mixer for each avatar
|
||||||
|
@ -100,15 +100,16 @@ void AvatarManager::init() {
|
||||||
_avatarHash.insert(MY_AVATAR_KEY, _myAvatar);
|
_avatarHash.insert(MY_AVATAR_KEY, _myAvatar);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_shouldRender = DependencyManager::get<SceneScriptingInterface>()->shouldRenderAvatars();
|
||||||
connect(DependencyManager::get<SceneScriptingInterface>().data(), &SceneScriptingInterface::shouldRenderAvatarsChanged,
|
connect(DependencyManager::get<SceneScriptingInterface>().data(), &SceneScriptingInterface::shouldRenderAvatarsChanged,
|
||||||
this, &AvatarManager::updateAvatarRenderStatus, Qt::QueuedConnection);
|
this, &AvatarManager::updateAvatarRenderStatus, Qt::QueuedConnection);
|
||||||
|
|
||||||
render::ScenePointer scene = qApp->getMain3DScene();
|
if (_shouldRender) {
|
||||||
render::Transaction transaction;
|
render::ScenePointer scene = qApp->getMain3DScene();
|
||||||
if (DependencyManager::get<SceneScriptingInterface>()->shouldRenderAvatars()) {
|
render::Transaction transaction;
|
||||||
_myAvatar->addToScene(_myAvatar, scene, transaction);
|
_myAvatar->addToScene(_myAvatar, scene, transaction);
|
||||||
|
scene->enqueueTransaction(transaction);
|
||||||
}
|
}
|
||||||
scene->enqueueTransaction(transaction);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AvatarManager::updateMyAvatar(float deltaTime) {
|
void AvatarManager::updateMyAvatar(float deltaTime) {
|
||||||
|
@ -151,7 +152,7 @@ float AvatarManager::getAvatarSimulationRate(const QUuid& sessionID, const QStri
|
||||||
void AvatarManager::updateOtherAvatars(float deltaTime) {
|
void AvatarManager::updateOtherAvatars(float deltaTime) {
|
||||||
// lock the hash for read to check the size
|
// lock the hash for read to check the size
|
||||||
QReadLocker lock(&_hashLock);
|
QReadLocker lock(&_hashLock);
|
||||||
if (_avatarHash.size() < 2 && _avatarFades.isEmpty()) {
|
if (_avatarHash.size() < 2 && _avatarsToFade.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
|
@ -181,30 +182,24 @@ void AvatarManager::updateOtherAvatars(float deltaTime) {
|
||||||
// DO NOT update or fade out uninitialized Avatars
|
// DO NOT update or fade out uninitialized Avatars
|
||||||
return true; // ignore it
|
return true; // ignore it
|
||||||
}
|
}
|
||||||
if (avatar->shouldDie()) {
|
|
||||||
removeAvatar(avatar->getID());
|
|
||||||
return true; // ignore it
|
|
||||||
}
|
|
||||||
if (avatar->isDead()) {
|
|
||||||
return true; // ignore it
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
render::Transaction transaction;
|
|
||||||
uint64_t startTime = usecTimestampNow();
|
uint64_t startTime = usecTimestampNow();
|
||||||
const uint64_t UPDATE_BUDGET = 2000; // usec
|
const uint64_t UPDATE_BUDGET = 2000; // usec
|
||||||
uint64_t updateExpiry = startTime + UPDATE_BUDGET;
|
uint64_t updateExpiry = startTime + UPDATE_BUDGET;
|
||||||
|
|
||||||
int numAvatarsUpdated = 0;
|
int numAvatarsUpdated = 0;
|
||||||
int numAVatarsNotUpdated = 0;
|
int numAVatarsNotUpdated = 0;
|
||||||
|
|
||||||
|
render::Transaction transaction;
|
||||||
while (!sortedAvatars.empty()) {
|
while (!sortedAvatars.empty()) {
|
||||||
const AvatarPriority& sortData = sortedAvatars.top();
|
const AvatarPriority& sortData = sortedAvatars.top();
|
||||||
const auto& avatar = std::static_pointer_cast<Avatar>(sortData.avatar);
|
const auto& avatar = std::static_pointer_cast<Avatar>(sortData.avatar);
|
||||||
|
|
||||||
// for ALL avatars...
|
// for ALL avatars...
|
||||||
avatar->ensureInScene(avatar);
|
if (_shouldRender) {
|
||||||
|
avatar->ensureInScene(avatar);
|
||||||
|
}
|
||||||
if (!avatar->getMotionState()) {
|
if (!avatar->getMotionState()) {
|
||||||
ShapeInfo shapeInfo;
|
ShapeInfo shapeInfo;
|
||||||
avatar->computeShapeInfo(shapeInfo);
|
avatar->computeShapeInfo(shapeInfo);
|
||||||
|
@ -218,6 +213,10 @@ void AvatarManager::updateOtherAvatars(float deltaTime) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
avatar->animateScaleChanges(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;
|
const float OUT_OF_VIEW_THRESHOLD = 0.5f * AvatarData::OUT_OF_VIEW_PENALTY;
|
||||||
uint64_t now = usecTimestampNow();
|
uint64_t now = usecTimestampNow();
|
||||||
|
@ -259,10 +258,24 @@ void AvatarManager::updateOtherAvatars(float deltaTime) {
|
||||||
sortedAvatars.pop();
|
sortedAvatars.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_shouldRender) {
|
||||||
|
if (!_avatarsToFade.empty()) {
|
||||||
|
QReadLocker lock(&_hashLock);
|
||||||
|
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;
|
_avatarSimulationTime = (float)(usecTimestampNow() - startTime) / (float)USECS_PER_MSEC;
|
||||||
_numAvatarsUpdated = numAvatarsUpdated;
|
_numAvatarsUpdated = numAvatarsUpdated;
|
||||||
_numAvatarsNotUpdated = numAVatarsNotUpdated;
|
_numAvatarsNotUpdated = numAVatarsNotUpdated;
|
||||||
qApp->getMain3DScene()->enqueueTransaction(transaction);
|
|
||||||
|
|
||||||
simulateAvatarFades(deltaTime);
|
simulateAvatarFades(deltaTime);
|
||||||
}
|
}
|
||||||
|
@ -277,54 +290,76 @@ void AvatarManager::postUpdate(float deltaTime) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void AvatarManager::simulateAvatarFades(float deltaTime) {
|
void AvatarManager::simulateAvatarFades(float deltaTime) {
|
||||||
QVector<AvatarSharedPointer>::iterator fadingIterator = _avatarFades.begin();
|
if (_avatarsToFade.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const float SHRINK_RATE = 0.15f;
|
const float SHRINK_RATE = 0.15f;
|
||||||
const float MIN_FADE_SCALE = MIN_AVATAR_SCALE;
|
const float MIN_FADE_SCALE = MIN_AVATAR_SCALE;
|
||||||
|
|
||||||
render::ScenePointer scene = qApp->getMain3DScene();
|
QReadLocker locker(&_hashLock);
|
||||||
render::Transaction transaction;
|
QVector<AvatarSharedPointer>::iterator itr = _avatarsToFade.begin();
|
||||||
while (fadingIterator != _avatarFades.end()) {
|
while (itr != _avatarsToFade.end()) {
|
||||||
auto avatar = std::static_pointer_cast<Avatar>(*fadingIterator);
|
auto avatar = std::static_pointer_cast<Avatar>(*itr);
|
||||||
avatar->setTargetScale(avatar->getUniformScale() * SHRINK_RATE);
|
avatar->setTargetScale(avatar->getUniformScale() * SHRINK_RATE);
|
||||||
avatar->animateScaleChanges(deltaTime);
|
avatar->animateScaleChanges(deltaTime);
|
||||||
if (avatar->getTargetScale() <= MIN_FADE_SCALE) {
|
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
|
||||||
// only remove from _avatarFades if we're sure its motionState has been removed from PhysicsEngine
|
if (avatar->isInScene()) {
|
||||||
|
render::ScenePointer scene = qApp->getMain3DScene();
|
||||||
|
render::Transaction transaction;
|
||||||
|
avatar->removeFromScene(*itr, scene, transaction);
|
||||||
|
if (scene) {
|
||||||
|
scene->enqueueTransaction(transaction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// only remove from _avatarsToFade if we're sure its motionState has been removed from PhysicsEngine
|
||||||
if (_motionStatesToRemoveFromPhysics.empty()) {
|
if (_motionStatesToRemoveFromPhysics.empty()) {
|
||||||
fadingIterator = _avatarFades.erase(fadingIterator);
|
itr = _avatarsToFade.erase(itr);
|
||||||
} else {
|
} else {
|
||||||
++fadingIterator;
|
++itr;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const bool inView = true; // HACK
|
const bool inView = true; // HACK
|
||||||
avatar->simulate(deltaTime, inView);
|
avatar->simulate(deltaTime, inView);
|
||||||
++fadingIterator;
|
++itr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
scene->enqueueTransaction(transaction);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AvatarSharedPointer AvatarManager::newSharedAvatar() {
|
AvatarSharedPointer AvatarManager::newSharedAvatar() {
|
||||||
return std::make_shared<Avatar>(std::make_shared<Rig>());
|
return std::make_shared<Avatar>(std::make_shared<Rig>());
|
||||||
}
|
}
|
||||||
|
|
||||||
AvatarSharedPointer AvatarManager::addAvatar(const QUuid& sessionUUID, const QWeakPointer<Node>& mixerWeakPointer) {
|
void AvatarManager::processAvatarDataPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode) {
|
||||||
auto newAvatar = AvatarHashMap::addAvatar(sessionUUID, mixerWeakPointer);
|
PerformanceTimer perfTimer("receiveAvatar");
|
||||||
auto rawRenderableAvatar = std::static_pointer_cast<Avatar>(newAvatar);
|
// enumerate over all of the avatars in this packet
|
||||||
|
// only add them if mixerWeakPointer points to something (meaning that mixer is still around)
|
||||||
rawRenderableAvatar->addToScene(rawRenderableAvatar);
|
while (message->getBytesLeftToRead()) {
|
||||||
|
AvatarSharedPointer avatarData = parseAvatarData(message, sendingNode);
|
||||||
return newAvatar;
|
if (avatarData) {
|
||||||
}
|
auto avatar = std::static_pointer_cast<Avatar>(avatarData);
|
||||||
|
if (avatar->isInScene()) {
|
||||||
// virtual
|
if (!_shouldRender) {
|
||||||
void AvatarManager::removeAvatar(const QUuid& sessionUUID, KillAvatarReason removalReason) {
|
// rare transition so we process the transaction immediately
|
||||||
QWriteLocker locker(&_hashLock);
|
render::ScenePointer scene = qApp->getMain3DScene();
|
||||||
|
if (scene) {
|
||||||
auto removedAvatar = _avatarHash.take(sessionUUID);
|
render::Transaction transaction;
|
||||||
if (removedAvatar) {
|
avatar->removeFromScene(avatar, scene, transaction);
|
||||||
handleRemovedAvatar(removedAvatar, removalReason);
|
scene->enqueueTransaction(transaction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (_shouldRender) {
|
||||||
|
// very rare transition so we process the transaction immediately
|
||||||
|
render::ScenePointer scene = qApp->getMain3DScene();
|
||||||
|
if (scene) {
|
||||||
|
render::Transaction transaction;
|
||||||
|
avatar->addToScene(avatar, scene, transaction);
|
||||||
|
scene->enqueueTransaction(transaction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -353,35 +388,46 @@ void AvatarManager::handleRemovedAvatar(const AvatarSharedPointer& removedAvatar
|
||||||
DependencyManager::get<NodeList>()->removeFromIgnoreMuteSets(avatar->getSessionUUID());
|
DependencyManager::get<NodeList>()->removeFromIgnoreMuteSets(avatar->getSessionUUID());
|
||||||
DependencyManager::get<UsersScriptingInterface>()->avatarDisconnected(avatar->getSessionUUID());
|
DependencyManager::get<UsersScriptingInterface>()->avatarDisconnected(avatar->getSessionUUID());
|
||||||
}
|
}
|
||||||
_avatarFades.push_back(removedAvatar);
|
_avatarsToFade.push_back(removedAvatar);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AvatarManager::clearOtherAvatars() {
|
void AvatarManager::clearOtherAvatars() {
|
||||||
// clear any avatars that came from an avatar-mixer
|
// Remove other avatars from the world but don't actually remove them from _avatarHash
|
||||||
QWriteLocker locker(&_hashLock);
|
// each will either be removed on timeout or will re-added to the world on receipt of update.
|
||||||
|
render::ScenePointer scene = qApp->getMain3DScene();
|
||||||
|
render::Transaction transaction;
|
||||||
|
|
||||||
|
QReadLocker locker(&_hashLock);
|
||||||
AvatarHash::iterator avatarIterator = _avatarHash.begin();
|
AvatarHash::iterator avatarIterator = _avatarHash.begin();
|
||||||
while (avatarIterator != _avatarHash.end()) {
|
while (avatarIterator != _avatarHash.end()) {
|
||||||
auto avatar = std::static_pointer_cast<Avatar>(avatarIterator.value());
|
auto avatar = std::static_pointer_cast<Avatar>(avatarIterator.value());
|
||||||
if (avatar == _myAvatar || !avatar->isInitialized()) {
|
if (avatar != _myAvatar) {
|
||||||
// don't remove myAvatar or uninitialized avatars from the list
|
if (avatar->isInScene()) {
|
||||||
++avatarIterator;
|
avatar->removeFromScene(avatar, scene, transaction);
|
||||||
} else {
|
}
|
||||||
auto removedAvatar = avatarIterator.value();
|
AvatarMotionState* motionState = avatar->getMotionState();
|
||||||
avatarIterator = _avatarHash.erase(avatarIterator);
|
if (motionState) {
|
||||||
|
_motionStatesThatMightUpdate.remove(motionState);
|
||||||
handleRemovedAvatar(removedAvatar);
|
_motionStatesToAddToPhysics.remove(motionState);
|
||||||
|
_motionStatesToRemoveFromPhysics.push_back(motionState);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
++avatarIterator;
|
||||||
|
}
|
||||||
|
if (scene) {
|
||||||
|
scene->enqueueTransaction(transaction);
|
||||||
}
|
}
|
||||||
_myAvatar->clearLookAtTargetAvatar();
|
_myAvatar->clearLookAtTargetAvatar();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AvatarManager::clearAllAvatars() {
|
void AvatarManager::deleteAllAvatars() {
|
||||||
clearOtherAvatars();
|
QReadLocker locker(&_hashLock);
|
||||||
|
AvatarHash::iterator avatarIterator = _avatarHash.begin();
|
||||||
QWriteLocker locker(&_hashLock);
|
while (avatarIterator != _avatarHash.end()) {
|
||||||
|
auto avatar = std::static_pointer_cast<Avatar>(avatarIterator.value());
|
||||||
handleRemovedAvatar(_myAvatar);
|
avatarIterator = _avatarHash.erase(avatarIterator);
|
||||||
|
avatar->die();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AvatarManager::setLocalLights(const QVector<AvatarManager::LocalLight>& localLights) {
|
void AvatarManager::setLocalLights(const QVector<AvatarManager::LocalLight>& localLights) {
|
||||||
|
@ -475,26 +521,25 @@ void AvatarManager::handleCollisionEvents(const CollisionEvents& collisionEvents
|
||||||
}
|
}
|
||||||
|
|
||||||
void AvatarManager::updateAvatarRenderStatus(bool shouldRenderAvatars) {
|
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) {
|
for (auto avatarData : _avatarHash) {
|
||||||
auto avatar = std::static_pointer_cast<Avatar>(avatarData);
|
auto avatar = std::static_pointer_cast<Avatar>(avatarData);
|
||||||
render::ScenePointer scene = qApp->getMain3DScene();
|
|
||||||
render::Transaction transaction;
|
|
||||||
avatar->addToScene(avatar, scene, transaction);
|
avatar->addToScene(avatar, scene, transaction);
|
||||||
scene->enqueueTransaction(transaction);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (auto avatarData : _avatarHash) {
|
for (auto avatarData : _avatarHash) {
|
||||||
auto avatar = std::static_pointer_cast<Avatar>(avatarData);
|
auto avatar = std::static_pointer_cast<Avatar>(avatarData);
|
||||||
render::ScenePointer scene = qApp->getMain3DScene();
|
|
||||||
render::Transaction transaction;
|
|
||||||
avatar->removeFromScene(avatar, scene, transaction);
|
avatar->removeFromScene(avatar, scene, transaction);
|
||||||
scene->enqueueTransaction(transaction);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (scene) {
|
||||||
|
scene->enqueueTransaction(transaction);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
AvatarSharedPointer AvatarManager::getAvatarBySessionID(const QUuid& sessionID) const {
|
AvatarSharedPointer AvatarManager::getAvatarBySessionID(const QUuid& sessionID) const {
|
||||||
if (sessionID == AVATAR_SELF_ID || sessionID == _myAvatar->getSessionUUID()) {
|
if (sessionID == AVATAR_SELF_ID || sessionID == _myAvatar->getSessionUUID()) {
|
||||||
return _myAvatar;
|
return _myAvatar;
|
||||||
|
|
|
@ -53,7 +53,7 @@ public:
|
||||||
void postUpdate(float deltaTime);
|
void postUpdate(float deltaTime);
|
||||||
|
|
||||||
void clearOtherAvatars();
|
void clearOtherAvatars();
|
||||||
void clearAllAvatars();
|
void deleteAllAvatars();
|
||||||
|
|
||||||
bool shouldShowReceiveStats() const { return _shouldShowReceiveStats; }
|
bool shouldShowReceiveStats() const { return _shouldShowReceiveStats; }
|
||||||
|
|
||||||
|
@ -91,8 +91,8 @@ public slots:
|
||||||
void setShouldShowReceiveStats(bool shouldShowReceiveStats) { _shouldShowReceiveStats = shouldShowReceiveStats; }
|
void setShouldShowReceiveStats(bool shouldShowReceiveStats) { _shouldShowReceiveStats = shouldShowReceiveStats; }
|
||||||
void updateAvatarRenderStatus(bool shouldRenderAvatars);
|
void updateAvatarRenderStatus(bool shouldRenderAvatars);
|
||||||
|
|
||||||
private slots:
|
protected slots:
|
||||||
virtual void removeAvatar(const QUuid& sessionUUID, KillAvatarReason removalReason = KillAvatarReason::NoReason) override;
|
void processAvatarDataPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit AvatarManager(QObject* parent = 0);
|
explicit AvatarManager(QObject* parent = 0);
|
||||||
|
@ -100,12 +100,15 @@ private:
|
||||||
|
|
||||||
void simulateAvatarFades(float deltaTime);
|
void simulateAvatarFades(float deltaTime);
|
||||||
|
|
||||||
// virtual overrides
|
AvatarSharedPointer newSharedAvatar() override;
|
||||||
virtual AvatarSharedPointer newSharedAvatar() override;
|
void handleRemovedAvatar(const AvatarSharedPointer& removedAvatar, KillAvatarReason removalReason = KillAvatarReason::NoReason) override;
|
||||||
virtual AvatarSharedPointer addAvatar(const QUuid& sessionUUID, const QWeakPointer<Node>& mixerWeakPointer) override;
|
|
||||||
virtual void handleRemovedAvatar(const AvatarSharedPointer& removedAvatar, KillAvatarReason removalReason = KillAvatarReason::NoReason) override;
|
QVector<AvatarSharedPointer> _avatarsToFade;
|
||||||
|
|
||||||
|
SetOfAvatarMotionStates _motionStatesThatMightUpdate;
|
||||||
|
VectorOfMotionStates _motionStatesToRemoveFromPhysics;
|
||||||
|
SetOfMotionStates _motionStatesToAddToPhysics;
|
||||||
|
|
||||||
QVector<AvatarSharedPointer> _avatarFades;
|
|
||||||
std::shared_ptr<MyAvatar> _myAvatar;
|
std::shared_ptr<MyAvatar> _myAvatar;
|
||||||
quint64 _lastSendAvatarDataTime = 0; // Controls MyAvatar send data rate.
|
quint64 _lastSendAvatarDataTime = 0; // Controls MyAvatar send data rate.
|
||||||
|
|
||||||
|
@ -115,14 +118,11 @@ private:
|
||||||
|
|
||||||
std::list<QPointer<AudioInjector>> _collisionInjectors;
|
std::list<QPointer<AudioInjector>> _collisionInjectors;
|
||||||
|
|
||||||
SetOfAvatarMotionStates _motionStatesThatMightUpdate;
|
|
||||||
SetOfMotionStates _motionStatesToAddToPhysics;
|
|
||||||
VectorOfMotionStates _motionStatesToRemoveFromPhysics;
|
|
||||||
|
|
||||||
RateCounter<> _myAvatarSendRate;
|
RateCounter<> _myAvatarSendRate;
|
||||||
int _numAvatarsUpdated { 0 };
|
int _numAvatarsUpdated { 0 };
|
||||||
int _numAvatarsNotUpdated { 0 };
|
int _numAvatarsNotUpdated { 0 };
|
||||||
float _avatarSimulationTime { 0.0f };
|
float _avatarSimulationTime { 0.0f };
|
||||||
|
bool _shouldRender { true };
|
||||||
};
|
};
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(AvatarManager::LocalLight)
|
Q_DECLARE_METATYPE(AvatarManager::LocalLight)
|
||||||
|
|
|
@ -54,6 +54,7 @@
|
||||||
#include "DebugDraw.h"
|
#include "DebugDraw.h"
|
||||||
#include "EntityEditPacketSender.h"
|
#include "EntityEditPacketSender.h"
|
||||||
#include "MovingEntitiesOperator.h"
|
#include "MovingEntitiesOperator.h"
|
||||||
|
#include "SceneScriptingInterface.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
@ -1634,7 +1635,7 @@ void MyAvatar::postUpdate(float deltaTime) {
|
||||||
Avatar::postUpdate(deltaTime);
|
Avatar::postUpdate(deltaTime);
|
||||||
|
|
||||||
render::ScenePointer scene = qApp->getMain3DScene();
|
render::ScenePointer scene = qApp->getMain3DScene();
|
||||||
if (_skeletonModel->initWhenReady(scene)) {
|
if (DependencyManager::get<SceneScriptingInterface>()->shouldRenderAvatars() && _skeletonModel->initWhenReady(scene)) {
|
||||||
initHeadBones();
|
initHeadBones();
|
||||||
_skeletonModel->setCauterizeBoneSet(_headBoneSet);
|
_skeletonModel->setCauterizeBoneSet(_headBoneSet);
|
||||||
_fstAnimGraphOverrideUrl = _skeletonModel->getGeometry()->getAnimGraphOverrideUrl();
|
_fstAnimGraphOverrideUrl = _skeletonModel->getGeometry()->getAnimGraphOverrideUrl();
|
||||||
|
|
|
@ -123,6 +123,7 @@ void AvatarData::setTargetScale(float targetScale) {
|
||||||
if (_targetScale != newValue) {
|
if (_targetScale != newValue) {
|
||||||
_targetScale = newValue;
|
_targetScale = newValue;
|
||||||
_scaleChanged = usecTimestampNow();
|
_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) {
|
AvatarSharedPointer AvatarHashMap::newOrExistingAvatar(const QUuid& sessionUUID, const QWeakPointer<Node>& mixerWeakPointer) {
|
||||||
QWriteLocker locker(&_hashLock);
|
QWriteLocker locker(&_hashLock);
|
||||||
|
|
||||||
auto avatar = _avatarHash.value(sessionUUID);
|
auto avatar = _avatarHash.value(sessionUUID);
|
||||||
|
|
||||||
if (!avatar) {
|
if (!avatar) {
|
||||||
avatar = addAvatar(sessionUUID, mixerWeakPointer);
|
avatar = addAvatar(sessionUUID, mixerWeakPointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
return avatar;
|
return avatar;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,27 +100,33 @@ void AvatarHashMap::processAvatarDataPacket(QSharedPointer<ReceivedMessage> mess
|
||||||
// enumerate over all of the avatars in this packet
|
// enumerate over all of the avatars in this packet
|
||||||
// only add them if mixerWeakPointer points to something (meaning that mixer is still around)
|
// only add them if mixerWeakPointer points to something (meaning that mixer is still around)
|
||||||
while (message->getBytesLeftToRead()) {
|
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
|
QByteArray byteArray = message->readWithoutCopy(message->getBytesLeftToRead());
|
||||||
auto nodeList = DependencyManager::get<NodeList>();
|
|
||||||
|
|
||||||
if (sessionUUID != _lastOwnerSessionUUID && (!nodeList->isIgnoringNode(sessionUUID) || nodeList->getRequestsDomainListData())) {
|
// make sure this isn't our own avatar data or for a previously ignored node
|
||||||
auto avatar = newOrExistingAvatar(sessionUUID, sendingNode);
|
auto nodeList = DependencyManager::get<NodeList>();
|
||||||
|
|
||||||
// have the matching (or new) avatar parse the data from the packet
|
if (sessionUUID != _lastOwnerSessionUUID && (!nodeList->isIgnoringNode(sessionUUID) || nodeList->getRequestsDomainListData())) {
|
||||||
int bytesRead = avatar->parseDataFromBuffer(byteArray);
|
auto avatar = newOrExistingAvatar(sessionUUID, sendingNode);
|
||||||
message->seek(positionBeforeRead + bytesRead);
|
|
||||||
} else {
|
// have the matching (or new) avatar parse the data from the packet
|
||||||
// create a dummy AvatarData class to throw this data on the ground
|
int bytesRead = avatar->parseDataFromBuffer(byteArray);
|
||||||
AvatarData dummyData;
|
message->seek(positionBeforeRead + bytesRead);
|
||||||
int bytesRead = dummyData.parseDataFromBuffer(byteArray);
|
return avatar;
|
||||||
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);
|
||||||
|
return std::make_shared<AvatarData>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -49,11 +49,11 @@ signals:
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
bool isAvatarInRange(const glm::vec3 & position, const float range);
|
bool isAvatarInRange(const glm::vec3 & position, const float range);
|
||||||
|
|
||||||
private slots:
|
protected slots:
|
||||||
void sessionUUIDChanged(const QUuid& sessionUUID, const QUuid& oldUUID);
|
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 processAvatarIdentityPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode);
|
||||||
void processKillAvatar(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode);
|
void processKillAvatar(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode);
|
||||||
void processExitingSpaceBubble(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode);
|
void processExitingSpaceBubble(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode);
|
||||||
|
@ -61,12 +61,13 @@ private slots:
|
||||||
protected:
|
protected:
|
||||||
AvatarHashMap();
|
AvatarHashMap();
|
||||||
|
|
||||||
|
virtual AvatarSharedPointer parseAvatarData(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode);
|
||||||
virtual AvatarSharedPointer newSharedAvatar();
|
virtual AvatarSharedPointer newSharedAvatar();
|
||||||
virtual AvatarSharedPointer addAvatar(const QUuid& sessionUUID, const QWeakPointer<Node>& mixerWeakPointer);
|
virtual AvatarSharedPointer addAvatar(const QUuid& sessionUUID, const QWeakPointer<Node>& mixerWeakPointer);
|
||||||
AvatarSharedPointer newOrExistingAvatar(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 AvatarSharedPointer findAvatar(const QUuid& sessionUUID) const; // uses a QReadLocker on the hashLock
|
||||||
virtual void removeAvatar(const QUuid& sessionUUID, KillAvatarReason removalReason = KillAvatarReason::NoReason);
|
virtual void removeAvatar(const QUuid& sessionUUID, KillAvatarReason removalReason = KillAvatarReason::NoReason);
|
||||||
|
|
||||||
virtual void handleRemovedAvatar(const AvatarSharedPointer& removedAvatar, KillAvatarReason removalReason = KillAvatarReason::NoReason);
|
virtual void handleRemovedAvatar(const AvatarSharedPointer& removedAvatar, KillAvatarReason removalReason = KillAvatarReason::NoReason);
|
||||||
|
|
||||||
AvatarHash _avatarHash;
|
AvatarHash _avatarHash;
|
||||||
|
|
Loading…
Reference in a new issue