overte/interface/src/avatar/AvatarManager.cpp

172 lines
6.3 KiB
C++

//
// AvatarManager.cpp
// interface/src/avatar
//
// Created by Stephen Birarda on 1/23/2014.
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include <string>
#include <glm/gtx/string_cast.hpp>
#include <PerfStat.h>
#include <UUID.h>
#include "Application.h"
#include "Avatar.h"
#include "Menu.h"
#include "MyAvatar.h"
#include "AvatarManager.h"
// We add _myAvatar into the hash with all the other AvatarData, and we use the default NULL QUid as the key.
const QUuid MY_AVATAR_KEY; // NULL key
AvatarManager::AvatarManager(QObject* parent) :
_avatarFades() {
// register a meta type for the weak pointer we'll use for the owning avatar mixer for each avatar
qRegisterMetaType<QWeakPointer<Node> >("NodeWeakPointer");
_myAvatar = QSharedPointer<MyAvatar>(new MyAvatar());
}
void AvatarManager::init() {
_myAvatar->init();
_myAvatar->setPosition(START_LOCATION);
_myAvatar->setDisplayingLookatVectors(false);
_avatarHash.insert(MY_AVATAR_KEY, _myAvatar);
}
void AvatarManager::updateOtherAvatars(float deltaTime) {
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
PerformanceWarning warn(showWarnings, "Application::updateAvatars()");
Application* applicationInstance = Application::getInstance();
glm::vec3 mouseOrigin = applicationInstance->getMouseRayOrigin();
glm::vec3 mouseDirection = applicationInstance->getMouseRayDirection();
// simulate avatars
AvatarHash::iterator avatarIterator = _avatarHash.begin();
while (avatarIterator != _avatarHash.end()) {
AvatarSharedPointer sharedAvatar = avatarIterator.value();
Avatar* avatar = reinterpret_cast<Avatar*>(sharedAvatar.data());
if (sharedAvatar == _myAvatar || !avatar->isInitialized()) {
// DO NOT update _myAvatar! Its update has already been done earlier in the main loop.
// DO NOT update uninitialized Avatars
++avatarIterator;
continue;
}
if (!shouldKillAvatar(sharedAvatar)) {
// this avatar's mixer is still around, go ahead and simulate it
avatar->simulate(deltaTime);
avatar->setMouseRay(mouseOrigin, mouseDirection);
++avatarIterator;
} else {
// the mixer that owned this avatar is gone, give it to the vector of fades and kill it
avatarIterator = erase(avatarIterator);
}
}
// simulate avatar fades
simulateAvatarFades(deltaTime);
}
void AvatarManager::renderAvatars(Avatar::RenderMode renderMode, bool selfAvatarOnly) {
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
"Application::renderAvatars()");
bool renderLookAtVectors = Menu::getInstance()->isOptionChecked(MenuOption::LookAtVectors);
glm::vec3 cameraPosition = Application::getInstance()->getCamera()->getPosition();
if (!selfAvatarOnly) {
foreach (const AvatarSharedPointer& avatarPointer, _avatarHash) {
Avatar* avatar = static_cast<Avatar*>(avatarPointer.data());
if (!avatar->isInitialized()) {
continue;
}
avatar->render(cameraPosition, renderMode);
avatar->setDisplayingLookatVectors(renderLookAtVectors);
}
renderAvatarFades(cameraPosition, renderMode);
} else {
// just render myAvatar
_myAvatar->render(cameraPosition, renderMode);
_myAvatar->setDisplayingLookatVectors(renderLookAtVectors);
}
}
void AvatarManager::simulateAvatarFades(float deltaTime) {
QVector<AvatarSharedPointer>::iterator fadingIterator = _avatarFades.begin();
const float SHRINK_RATE = 0.9f;
const float MIN_FADE_SCALE = 0.001f;
while (fadingIterator != _avatarFades.end()) {
Avatar* avatar = static_cast<Avatar*>(fadingIterator->data());
avatar->setTargetScale(avatar->getScale() * SHRINK_RATE);
if (avatar->getTargetScale() < MIN_FADE_SCALE) {
fadingIterator = _avatarFades.erase(fadingIterator);
} else {
avatar->simulate(deltaTime);
++fadingIterator;
}
}
}
void AvatarManager::renderAvatarFades(const glm::vec3& cameraPosition, Avatar::RenderMode renderMode) {
// render avatar fades
Glower glower(renderMode == Avatar::NORMAL_RENDER_MODE ? 1.0f : 0.0f);
foreach(const AvatarSharedPointer& fadingAvatar, _avatarFades) {
Avatar* avatar = static_cast<Avatar*>(fadingAvatar.data());
if (avatar != static_cast<Avatar*>(_myAvatar.data()) && avatar->isInitialized()) {
avatar->render(cameraPosition, renderMode);
}
}
}
void AvatarManager::processAvatarMixerDatagram(const QByteArray& datagram, const QWeakPointer<Node>& mixerWeakPointer) {
switch (packetTypeForPacket(datagram)) {
case PacketTypeBulkAvatarData:
processAvatarDataPacket(datagram, mixerWeakPointer);
break;
case PacketTypeAvatarIdentity:
processAvatarIdentityPacket(datagram, mixerWeakPointer);
break;
case PacketTypeAvatarBillboard:
processAvatarBillboardPacket(datagram, mixerWeakPointer);
break;
case PacketTypeKillAvatar:
processKillAvatar(datagram);
break;
default:
break;
}
}
AvatarHash::iterator AvatarManager::erase(const AvatarHash::iterator& iterator) {
if (iterator.key() != MY_AVATAR_KEY) {
qDebug() << "Removing Avatar with UUID" << iterator.key() << "from AvatarManager hash.";
if (reinterpret_cast<Avatar*>(iterator.value().data())->isInitialized()) {
_avatarFades.push_back(iterator.value());
}
return AvatarHashMap::erase(iterator);
} else {
// never remove _myAvatar from the list
AvatarHash::iterator returnIterator = iterator;
return ++returnIterator;
}
}
void AvatarManager::clearOtherAvatars() {
// clear any avatars that came from an avatar-mixer
AvatarHash::iterator removeAvatar = _avatarHash.begin();
while (removeAvatar != _avatarHash.end()) {
removeAvatar = erase(removeAvatar);
}
_myAvatar->clearLookAtTargetAvatar();
}