mirror of
https://github.com/overte-org/overte.git
synced 2025-04-21 18:44:00 +02:00
Adding avatars back into ParticleCollisionSystem.
Had to add Application::_myAvatar to the AvatarManager list so that particles would properly collide.
This commit is contained in:
parent
c4f429dcd0
commit
167acb8873
9 changed files with 216 additions and 112 deletions
|
@ -1754,6 +1754,7 @@ void Application::init() {
|
|||
_myCamera.setMode(CAMERA_MODE_FIRST_PERSON);
|
||||
_myCamera.setModeShiftRate(1.0f);
|
||||
_myAvatar.setDisplayingLookatVectors(false);
|
||||
_avatarManager.setMyAvatar(&_myAvatar);
|
||||
|
||||
_mirrorCamera.setMode(CAMERA_MODE_MIRROR);
|
||||
_mirrorCamera.setAspectRatio((float)MIRROR_VIEW_WIDTH / (float)MIRROR_VIEW_HEIGHT);
|
||||
|
@ -1800,7 +1801,7 @@ void Application::init() {
|
|||
|
||||
_metavoxels.init();
|
||||
|
||||
_particleCollisionSystem.init(&_particleEditSender, _particles.getTree(), _voxels.getTree(), &_audio);
|
||||
_particleCollisionSystem.init(&_particleEditSender, _particles.getTree(), _voxels.getTree(), &_audio, &_avatarManager);
|
||||
|
||||
_palette.init(_glWidget->width(), _glWidget->height());
|
||||
_palette.addAction(Menu::getInstance()->getActionForOption(MenuOption::VoxelAddMode), 0, 0);
|
||||
|
@ -2314,12 +2315,7 @@ void Application::update(float deltaTime) {
|
|||
updateCursor(deltaTime); // Handle cursor updates
|
||||
|
||||
_particles.update(); // update the particles...
|
||||
|
||||
// collide the particles...
|
||||
QVector<AvatarData*> avatars;
|
||||
avatars.push_back(&_myAvatar);
|
||||
_avatarManager.getAvatarBasePointers(avatars);
|
||||
_particleCollisionSystem.update(avatars);
|
||||
_particleCollisionSystem.update(); // collide the particles...
|
||||
}
|
||||
|
||||
void Application::updateAvatar(float deltaTime) {
|
||||
|
|
|
@ -16,17 +16,28 @@
|
|||
|
||||
#include "AvatarManager.h"
|
||||
|
||||
|
||||
AvatarManager::AvatarManager(QObject* parent) :
|
||||
_lookAtTargetAvatar(),
|
||||
_lookAtOtherPosition(),
|
||||
_lookAtIndicatorScale(1.0f),
|
||||
_avatarHash(),
|
||||
_avatarFades()
|
||||
_avatarFades(),
|
||||
_myAvatar(NULL)
|
||||
{
|
||||
// register a meta type for the weak pointer we'll use for the owning avatar mixer for each avatar
|
||||
qRegisterMetaType<QWeakPointer<Node> >("NodeWeakPointer");
|
||||
}
|
||||
|
||||
void AvatarManager::setMyAvatar(MyAvatar* myAvatar) {
|
||||
if (!_myAvatar) {
|
||||
// can only ever set this once
|
||||
_myAvatar = myAvatar;
|
||||
// add _myAvatar to the list
|
||||
AvatarSharedPointer myPointer = AvatarSharedPointer(_myAvatar);
|
||||
_avatarHash.insert(MY_AVATAR_KEY, myPointer);
|
||||
}
|
||||
}
|
||||
|
||||
void AvatarManager::updateLookAtTargetAvatar(glm::vec3 &eyePosition) {
|
||||
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
||||
PerformanceWarning warn(showWarnings, "Application::updateLookatTargetAvatar()");
|
||||
|
@ -34,22 +45,26 @@ void AvatarManager::updateLookAtTargetAvatar(glm::vec3 &eyePosition) {
|
|||
Application* applicationInstance = Application::getInstance();
|
||||
|
||||
if (!applicationInstance->isMousePressed()) {
|
||||
foreach (const AvatarSharedPointer& avatar, _avatarHash) {
|
||||
float distance;
|
||||
|
||||
if (avatar->findRayIntersection(applicationInstance->getMouseRayOrigin(),
|
||||
applicationInstance->getMouseRayDirection(), distance)) {
|
||||
// rescale to compensate for head embiggening
|
||||
eyePosition = (avatar->getHead().calculateAverageEyePosition() - avatar->getHead().getScalePivot()) *
|
||||
(avatar->getScale() / avatar->getHead().getScale()) + avatar->getHead().getScalePivot();
|
||||
|
||||
_lookAtIndicatorScale = avatar->getHead().getScale();
|
||||
_lookAtOtherPosition = avatar->getHead().getPosition();
|
||||
|
||||
_lookAtTargetAvatar = avatar;
|
||||
|
||||
// found the look at target avatar, return
|
||||
return;
|
||||
glm::vec3 mouseOrigin = applicationInstance->getMouseRayOrigin();
|
||||
glm::vec3 mouseDirection = applicationInstance->getMouseRayDirection();
|
||||
|
||||
foreach (const AvatarSharedPointer& avatarPointer, _avatarHash) {
|
||||
Avatar* avatar = static_cast<Avatar*>(avatarPointer.data());
|
||||
if (avatar != static_cast<Avatar*>(_myAvatar)) {
|
||||
float distance;
|
||||
if (avatar->findRayIntersection(mouseOrigin, mouseDirection, distance)) {
|
||||
// rescale to compensate for head embiggening
|
||||
eyePosition = (avatar->getHead().calculateAverageEyePosition() - avatar->getHead().getScalePivot()) *
|
||||
(avatar->getScale() / avatar->getHead().getScale()) + avatar->getHead().getScalePivot();
|
||||
|
||||
_lookAtIndicatorScale = avatar->getHead().getScale();
|
||||
_lookAtOtherPosition = avatar->getHead().getPosition();
|
||||
|
||||
_lookAtTargetAvatar = avatarPointer;
|
||||
|
||||
// found the look at target avatar, return
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -61,20 +76,28 @@ void AvatarManager::updateAvatars(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 avatar = _avatarHash.begin();
|
||||
if (avatar != _avatarHash.end()) {
|
||||
if (avatar->data()->getOwningAvatarMixer()) {
|
||||
AvatarHash::iterator avatarIterator = _avatarHash.begin();
|
||||
while (avatarIterator != _avatarHash.end()) {
|
||||
if (MY_AVATAR_KEY == avatarIterator.key()) {
|
||||
// for now skip updates to _myAvatar because it is done explicitly in Application
|
||||
// TODO: update _myAvatar in this context
|
||||
++avatarIterator;
|
||||
continue;
|
||||
}
|
||||
Avatar* avatar = static_cast<Avatar*>(avatarIterator.value().data());
|
||||
if (avatar->getOwningAvatarMixer()) {
|
||||
// this avatar's mixer is still around, go ahead and simulate it
|
||||
avatar->data()->simulate(deltaTime, NULL);
|
||||
|
||||
Application* applicationInstance = Application::getInstance();
|
||||
|
||||
avatar->data()->setMouseRay(applicationInstance->getMouseRayOrigin(),
|
||||
applicationInstance->getMouseRayDirection());
|
||||
avatar->simulate(deltaTime, NULL);
|
||||
avatar->setMouseRay(mouseOrigin, mouseDirection);
|
||||
++avatarIterator;
|
||||
} else {
|
||||
// the mixer that owned this avatar is gone, give it to the vector of fades and kill it
|
||||
avatar = removeAvatarAtHashIterator(avatar);
|
||||
avatarIterator = erase(avatarIterator);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -88,41 +111,44 @@ void AvatarManager::renderAvatars(bool forceRenderHead, bool selfAvatarOnly) {
|
|||
}
|
||||
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
|
||||
"Application::renderAvatars()");
|
||||
bool renderLookAtVectors = Menu::getInstance()->isOptionChecked(MenuOption::LookAtVectors);
|
||||
|
||||
if (!selfAvatarOnly) {
|
||||
|
||||
// Render avatars of other nodes
|
||||
foreach (const AvatarSharedPointer& avatar, _avatarHash) {
|
||||
foreach (const AvatarSharedPointer& avatarPointer, _avatarHash) {
|
||||
Avatar* avatar = static_cast<Avatar*>(avatarPointer.data());
|
||||
if (!avatar->isInitialized()) {
|
||||
avatar->init();
|
||||
}
|
||||
avatar->render(false);
|
||||
avatar->setDisplayingLookatVectors(Menu::getInstance()->isOptionChecked(MenuOption::LookAtVectors));
|
||||
if (avatar == static_cast<Avatar*>(_myAvatar)) {
|
||||
avatar->render(forceRenderHead);
|
||||
} else {
|
||||
avatar->render(false);
|
||||
}
|
||||
avatar->setDisplayingLookatVectors(renderLookAtVectors);
|
||||
}
|
||||
|
||||
renderAvatarFades();
|
||||
} else if (_myAvatar) {
|
||||
// Render my own Avatar
|
||||
_myAvatar->render(forceRenderHead);
|
||||
_myAvatar->setDisplayingLookatVectors(renderLookAtVectors);
|
||||
}
|
||||
|
||||
// Render my own Avatar
|
||||
Avatar* myAvatar = Application::getInstance()->getAvatar();
|
||||
myAvatar->render(forceRenderHead);
|
||||
myAvatar->setDisplayingLookatVectors(Menu::getInstance()->isOptionChecked(MenuOption::LookAtVectors));
|
||||
}
|
||||
|
||||
void AvatarManager::simulateAvatarFades(float deltaTime) {
|
||||
QVector<AvatarSharedPointer>::iterator fadingAvatar = _avatarFades.begin();
|
||||
QVector<AvatarSharedPointer>::iterator fadingIterator = _avatarFades.begin();
|
||||
|
||||
while (fadingAvatar != _avatarFades.end()) {
|
||||
const float SHRINK_RATE = 0.9f;
|
||||
|
||||
fadingAvatar->data()->setTargetScale(fadingAvatar->data()->getScale() * SHRINK_RATE);
|
||||
|
||||
const float MIN_FADE_SCALE = 0.001f;
|
||||
|
||||
if (fadingAvatar->data()->getTargetScale() < MIN_FADE_SCALE) {
|
||||
fadingAvatar = _avatarFades.erase(fadingAvatar);
|
||||
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 {
|
||||
fadingAvatar->data()->simulate(deltaTime, NULL);
|
||||
avatar->simulate(deltaTime, NULL);
|
||||
++fadingIterator;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -132,29 +158,36 @@ void AvatarManager::renderAvatarFades() {
|
|||
Glower glower;
|
||||
|
||||
foreach(const AvatarSharedPointer& fadingAvatar, _avatarFades) {
|
||||
fadingAvatar->render(false);
|
||||
Avatar* avatar = static_cast<Avatar*>(fadingAvatar.data());
|
||||
avatar->render(false);
|
||||
}
|
||||
}
|
||||
|
||||
void AvatarManager::processDataServerResponse(const QString& userString, const QStringList& keyList,
|
||||
const QStringList &valueList) {
|
||||
QUuid avatarKey = QUuid(userString);
|
||||
if (avatarKey == MY_AVATAR_KEY) {
|
||||
// ignore updates to our own mesh
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < keyList.size(); i++) {
|
||||
if (valueList[i] != " ") {
|
||||
if (keyList[i] == DataServerKey::FaceMeshURL || keyList[i] == DataServerKey::SkeletonURL) {
|
||||
// mesh URL for a UUID, find avatar in our list
|
||||
AvatarSharedPointer matchingAvatar = _avatarHash.value(QUuid(userString));
|
||||
AvatarSharedPointer matchingAvatar = _avatarHash.value(avatarKey);
|
||||
if (matchingAvatar) {
|
||||
Avatar* avatar = static_cast<Avatar*>(matchingAvatar.data());
|
||||
if (keyList[i] == DataServerKey::FaceMeshURL) {
|
||||
qDebug() << "Changing mesh to" << valueList[i] << "for avatar with UUID"
|
||||
<< uuidStringWithoutCurlyBraces(QUuid(userString));
|
||||
<< uuidStringWithoutCurlyBraces(avatarKey);
|
||||
|
||||
QMetaObject::invokeMethod(&matchingAvatar->getHead().getFaceModel(),
|
||||
QMetaObject::invokeMethod(&(avatar->getHead().getFaceModel()),
|
||||
"setURL", Q_ARG(QUrl, QUrl(valueList[i])));
|
||||
} else if (keyList[i] == DataServerKey::SkeletonURL) {
|
||||
qDebug() << "Changing skeleton to" << valueList[i] << "for avatar with UUID"
|
||||
<< uuidStringWithoutCurlyBraces(QString(userString));
|
||||
<< uuidStringWithoutCurlyBraces(avatarKey.toString());
|
||||
|
||||
QMetaObject::invokeMethod(&matchingAvatar->getSkeletonModel(),
|
||||
QMetaObject::invokeMethod(&(avatar->getSkeletonModel()),
|
||||
"setURL", Q_ARG(QUrl, QUrl(valueList[i])));
|
||||
}
|
||||
}
|
||||
|
@ -178,15 +211,17 @@ void AvatarManager::processAvatarMixerDatagram(const QByteArray& datagram, const
|
|||
// only add them if mixerWeakPointer points to something (meaning that mixer is still around)
|
||||
while (bytesRead < datagram.size() && mixerWeakPointer.data()) {
|
||||
QUuid nodeUUID = QUuid::fromRfc4122(datagram.mid(bytesRead, NUM_BYTES_RFC4122_UUID));
|
||||
// TODO: skip the data if nodeUUID is same as MY_AVATAR_KEY
|
||||
|
||||
AvatarSharedPointer matchingAvatar = _avatarHash.value(nodeUUID);
|
||||
|
||||
if (!matchingAvatar) {
|
||||
// construct a new Avatar for this node
|
||||
matchingAvatar = AvatarSharedPointer(new Avatar());
|
||||
matchingAvatar->setOwningAvatarMixer(mixerWeakPointer);
|
||||
Avatar* avatar = new Avatar();
|
||||
avatar->setOwningAvatarMixer(mixerWeakPointer);
|
||||
|
||||
// insert the new avatar into our hash
|
||||
matchingAvatar = AvatarSharedPointer(avatar);
|
||||
_avatarHash.insert(nodeUUID, matchingAvatar);
|
||||
|
||||
// new UUID requires mesh and skeleton request to data-server
|
||||
|
@ -213,28 +248,27 @@ void AvatarManager::processKillAvatar(const QByteArray& datagram) {
|
|||
// remove the avatar with that UUID from our hash, if it exists
|
||||
AvatarHash::iterator matchedAvatar = _avatarHash.find(nodeUUID);
|
||||
if (matchedAvatar != _avatarHash.end()) {
|
||||
removeAvatarAtHashIterator(matchedAvatar);
|
||||
erase(matchedAvatar);
|
||||
}
|
||||
}
|
||||
|
||||
AvatarHash::iterator AvatarManager::removeAvatarAtHashIterator(const AvatarHash::iterator& iterator) {
|
||||
qDebug() << "Removing Avatar with UUID" << iterator.key() << "from AvatarManager hash.";
|
||||
_avatarFades.push_back(iterator.value());
|
||||
return _avatarHash.erase(iterator);
|
||||
AvatarHash::iterator AvatarManager::erase(const AvatarHash::iterator& iterator) {
|
||||
if (iterator.key() != MY_AVATAR_KEY) {
|
||||
qDebug() << "Removing Avatar with UUID" << iterator.key() << "from AvatarManager hash.";
|
||||
_avatarFades.push_back(iterator.value());
|
||||
return AvatarHashMap::erase(iterator);
|
||||
} else {
|
||||
// never remove _myAvatar from the list
|
||||
AvatarHash::iterator returnIterator = iterator;
|
||||
return ++returnIterator;
|
||||
}
|
||||
}
|
||||
|
||||
void AvatarManager::clearHash() {
|
||||
// clear the AvatarManager hash - typically happens on the removal of the avatar-mixer
|
||||
AvatarHash::iterator removeAvatar = _avatarHash.begin();
|
||||
|
||||
while (removeAvatar != _avatarHash.end()) {
|
||||
removeAvatar = removeAvatarAtHashIterator(removeAvatar);
|
||||
removeAvatar = erase(removeAvatar);
|
||||
}
|
||||
}
|
||||
|
||||
void AvatarManager::getAvatarBasePointers(QVector<AvatarData*>& avatars) {
|
||||
AvatarHash::iterator avatarItr = _avatarHash.begin();
|
||||
while (avatarItr != _avatarHash.end()) {
|
||||
avatars.push_back( static_cast<AvatarData*>(avatarItr.value().data()) );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,32 +13,32 @@
|
|||
#include <QtCore/QObject>
|
||||
#include <QtCore/QSharedPointer>
|
||||
|
||||
#include <AvatarHashMap.h>
|
||||
#include <DataServerClient.h>
|
||||
|
||||
#include "Avatar.h"
|
||||
|
||||
typedef QSharedPointer<Avatar> AvatarSharedPointer;
|
||||
typedef QHash<QUuid, AvatarSharedPointer> AvatarHash;
|
||||
class MyAvatar;
|
||||
|
||||
class AvatarManager : public QObject, public DataServerCallbackObject {
|
||||
const QUuid MY_AVATAR_KEY; // NULL key
|
||||
|
||||
class AvatarManager : public QObject, public DataServerCallbackObject, public AvatarHashMap {
|
||||
Q_OBJECT
|
||||
public:
|
||||
AvatarManager(QObject* parent = 0);
|
||||
|
||||
void setMyAvatar(MyAvatar* myAvatar);
|
||||
|
||||
const AvatarHash& getAvatarHash() { return _avatarHash; }
|
||||
int size() const { return _avatarHash.size(); }
|
||||
|
||||
Avatar* getLookAtTargetAvatar() const { return _lookAtTargetAvatar.data(); }
|
||||
AvatarData* getLookAtTargetAvatar() const { return _lookAtTargetAvatar.data(); }
|
||||
|
||||
void updateLookAtTargetAvatar(glm::vec3& eyePosition);
|
||||
|
||||
void updateAvatars(float deltaTime);
|
||||
void renderAvatars(bool forceRenderHead, bool selfAvatarOnly = false);
|
||||
|
||||
// virtual override
|
||||
void clearHash();
|
||||
|
||||
void getAvatarBasePointers(QVector<AvatarData*>& avatars);
|
||||
|
||||
public slots:
|
||||
void processDataServerResponse(const QString& userString, const QStringList& keyList, const QStringList& valueList);
|
||||
|
||||
|
@ -46,17 +46,20 @@ public slots:
|
|||
void processKillAvatar(const QByteArray& datagram);
|
||||
|
||||
private:
|
||||
AvatarManager(const AvatarManager& other);
|
||||
|
||||
void simulateAvatarFades(float deltaTime);
|
||||
void renderAvatarFades();
|
||||
|
||||
AvatarHash::iterator removeAvatarAtHashIterator(const AvatarHash::iterator& iterator);
|
||||
// virtual override
|
||||
AvatarHash::iterator erase(const AvatarHash::iterator& iterator);
|
||||
|
||||
QWeakPointer<Avatar> _lookAtTargetAvatar;
|
||||
QWeakPointer<AvatarData> _lookAtTargetAvatar;
|
||||
glm::vec3 _lookAtOtherPosition;
|
||||
float _lookAtIndicatorScale;
|
||||
|
||||
AvatarHash _avatarHash;
|
||||
QVector<AvatarSharedPointer> _avatarFades;
|
||||
MyAvatar* _myAvatar;
|
||||
};
|
||||
|
||||
#endif /* defined(__hifi__AvatarManager__) */
|
||||
|
|
|
@ -183,7 +183,12 @@ void Hand::updateCollisions() {
|
|||
glm::vec3 totalPenetration;
|
||||
|
||||
// check other avatars
|
||||
foreach (const AvatarSharedPointer& avatar, Application::getInstance()->getAvatarManager().getAvatarHash()) {
|
||||
foreach (const AvatarSharedPointer& avatarPointer, Application::getInstance()->getAvatarManager().getAvatarHash()) {
|
||||
Avatar* avatar = static_cast<Avatar*>(avatarPointer.data());
|
||||
if (avatar == _owningAvatar) {
|
||||
// don't collid with our own hands
|
||||
continue;
|
||||
}
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::PlaySlaps)) {
|
||||
// Check for palm collisions
|
||||
glm::vec3 myPalmPosition = palm.getPosition();
|
||||
|
@ -205,9 +210,9 @@ void Hand::updateCollisions() {
|
|||
const float PALM_COLLIDE_DURATION_MAX = 0.75f;
|
||||
const float PALM_COLLIDE_DECAY_PER_SAMPLE = 0.01f;
|
||||
Application::getInstance()->getAudio()->startDrumSound(PALM_COLLIDE_VOLUME,
|
||||
PALM_COLLIDE_FREQUENCY,
|
||||
PALM_COLLIDE_DURATION_MAX,
|
||||
PALM_COLLIDE_DECAY_PER_SAMPLE);
|
||||
PALM_COLLIDE_FREQUENCY,
|
||||
PALM_COLLIDE_DURATION_MAX,
|
||||
PALM_COLLIDE_DECAY_PER_SAMPLE);
|
||||
// If the other person's palm is in motion, move mine downward to show I was hit
|
||||
const float MIN_VELOCITY_FOR_SLAP = 0.05f;
|
||||
if (glm::length(otherPalm.getVelocity()) > MIN_VELOCITY_FOR_SLAP) {
|
||||
|
|
|
@ -791,14 +791,15 @@ void MyAvatar::updateChatCircle(float deltaTime) {
|
|||
// find all circle-enabled members and sort by distance
|
||||
QVector<SortedAvatar> sortedAvatars;
|
||||
|
||||
foreach (const AvatarSharedPointer& avatar, Application::getInstance()->getAvatarManager().getAvatarHash()) {
|
||||
SortedAvatar sortedAvatar;
|
||||
sortedAvatar.avatar = avatar.data();
|
||||
|
||||
if (!sortedAvatar.avatar->isChatCirclingEnabled()) {
|
||||
foreach (const AvatarSharedPointer& avatarPointer, Application::getInstance()->getAvatarManager().getAvatarHash()) {
|
||||
Avatar* avatar = static_cast<Avatar*>(avatarPointer.data());
|
||||
if ( ! avatar->isChatCirclingEnabled() ||
|
||||
avatar == static_cast<Avatar*>(this)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
SortedAvatar sortedAvatar;
|
||||
sortedAvatar.avatar = avatar;
|
||||
sortedAvatar.distance = glm::distance(_position, sortedAvatar.avatar->getPosition());
|
||||
sortedAvatars.append(sortedAvatar);
|
||||
}
|
||||
|
|
30
libraries/avatars/src/AvatarHashMap.cpp
Normal file
30
libraries/avatars/src/AvatarHashMap.cpp
Normal file
|
@ -0,0 +1,30 @@
|
|||
//
|
||||
// AvatarHashMap.cpp
|
||||
// hifi
|
||||
//
|
||||
// Created by Stephen AndrewMeadows on 1/28/2014.
|
||||
// Copyright (c) 2014 HighFidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#include "AvatarHashMap.h"
|
||||
|
||||
AvatarHashMap::AvatarHashMap() :
|
||||
_avatarHash()
|
||||
{
|
||||
}
|
||||
|
||||
void AvatarHashMap::insert(const QUuid& id, AvatarSharedPointer avatar) {
|
||||
_avatarHash.insert(id, avatar);
|
||||
}
|
||||
|
||||
void AvatarHashMap::clearHash() {
|
||||
AvatarHash::iterator removeAvatar = _avatarHash.begin();
|
||||
while (removeAvatar != _avatarHash.end()) {
|
||||
removeAvatar = erase(removeAvatar);
|
||||
}
|
||||
}
|
||||
|
||||
AvatarHash::iterator AvatarHashMap::erase(const AvatarHash::iterator& iterator) {
|
||||
return _avatarHash.erase(iterator);
|
||||
}
|
||||
|
37
libraries/avatars/src/AvatarHashMap.h
Normal file
37
libraries/avatars/src/AvatarHashMap.h
Normal file
|
@ -0,0 +1,37 @@
|
|||
//
|
||||
// AvatarHashMap.h
|
||||
// hifi
|
||||
//
|
||||
// Created by Stephen AndrewMeadows on 1/28/2014.
|
||||
// Copyright (c) 2014 HighFidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef __hifi__AvatarHashMap__
|
||||
#define __hifi__AvatarHashMap__
|
||||
|
||||
#include <QtCore/QHash>
|
||||
#include <QtCore/QSharedPointer>
|
||||
#include <QtCore/QUuid>
|
||||
|
||||
#include "AvatarData.h"
|
||||
|
||||
typedef QSharedPointer<AvatarData> AvatarSharedPointer;
|
||||
typedef QHash<QUuid, AvatarSharedPointer> AvatarHash;
|
||||
|
||||
class AvatarHashMap {
|
||||
public:
|
||||
AvatarHashMap();
|
||||
|
||||
const AvatarHash& getAvatarHash() { return _avatarHash; }
|
||||
int size() const { return _avatarHash.size(); }
|
||||
|
||||
virtual void insert(const QUuid& id, AvatarSharedPointer avatar);
|
||||
virtual void clearHash();
|
||||
|
||||
protected:
|
||||
virtual AvatarHash::iterator erase(const AvatarHash::iterator& iterator);
|
||||
|
||||
AvatarHash _avatarHash;
|
||||
};
|
||||
|
||||
#endif /* defined(__hifi__AvatarHashMap__) */
|
|
@ -25,11 +25,13 @@ ParticleCollisionSystem::ParticleCollisionSystem(ParticleEditPacketSender* packe
|
|||
}
|
||||
|
||||
void ParticleCollisionSystem::init(ParticleEditPacketSender* packetSender,
|
||||
ParticleTree* particles, VoxelTree* voxels, AbstractAudioInterface* audio) {
|
||||
ParticleTree* particles, VoxelTree* voxels, AbstractAudioInterface* audio,
|
||||
AvatarHashMap* avatars) {
|
||||
_packetSender = packetSender;
|
||||
_particles = particles;
|
||||
_voxels = voxels;
|
||||
_audio = audio;
|
||||
_avatars = avatars;
|
||||
}
|
||||
|
||||
ParticleCollisionSystem::~ParticleCollisionSystem() {
|
||||
|
@ -51,9 +53,8 @@ bool ParticleCollisionSystem::updateOperation(OctreeElement* element, void* extr
|
|||
}
|
||||
|
||||
|
||||
void ParticleCollisionSystem::update(QVector<AvatarData*>& avatars) {
|
||||
void ParticleCollisionSystem::update() {
|
||||
// update all particles
|
||||
_avatars.swap(avatars);
|
||||
_particles->lockForWrite();
|
||||
_particles->recurseTreeWithOperation(updateOperation, this);
|
||||
_particles->unlock();
|
||||
|
@ -147,9 +148,8 @@ const float MIN_EXPECTED_FRAME_PERIOD = 0.0167f; // 1/60th of a second
|
|||
const float HALTING_SPEED = 9.8 * MIN_EXPECTED_FRAME_PERIOD / (float)(TREE_SCALE);
|
||||
|
||||
void ParticleCollisionSystem::updateCollisionWithAvatars(Particle* particle) {
|
||||
|
||||
// particles that are in hand, don't collide with avatars
|
||||
if (particle->getInHand()) {
|
||||
if (!_avatars || particle->getInHand()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -160,9 +160,8 @@ void ParticleCollisionSystem::updateCollisionWithAvatars(Particle* particle) {
|
|||
const float COLLISION_FREQUENCY = 0.5f;
|
||||
glm::vec3 penetration;
|
||||
|
||||
// first check the selfAvatar if set...
|
||||
for (int i = 0; i < _avatars.size(); ++i) {
|
||||
AvatarData* avatar = _avatars[i];
|
||||
foreach (const AvatarSharedPointer& avatarPointer, _avatars->getAvatarHash()) {
|
||||
AvatarData* avatar = avatarPointer.data();
|
||||
CollisionInfo collisionInfo;
|
||||
collisionInfo._damping = DAMPING;
|
||||
collisionInfo._elasticity = ELASTICITY;
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <QtScript/QScriptEngine>
|
||||
#include <QtCore/QObject>
|
||||
|
||||
#include <AvatarHashMap.h>
|
||||
#include <CollisionInfo.h>
|
||||
#include <SharedUtil.h>
|
||||
#include <OctreePacketData.h>
|
||||
|
@ -37,13 +38,11 @@ public:
|
|||
AbstractAudioInterface* audio = NULL);
|
||||
|
||||
void init(ParticleEditPacketSender* packetSender, ParticleTree* particles, VoxelTree* voxels,
|
||||
AbstractAudioInterface* audio = NULL);
|
||||
AbstractAudioInterface* audio = NULL, AvatarHashMap* _avatars = NULL);
|
||||
|
||||
~ParticleCollisionSystem();
|
||||
|
||||
/// Compute collisions for particles against: other particles, voxels, and avatars
|
||||
/// \param avatars the list of avatars to collide against during this frame
|
||||
void update(QVector<AvatarData*>& avatars);
|
||||
void update();
|
||||
|
||||
void checkParticle(Particle* particle);
|
||||
void updateCollisionWithVoxels(Particle* particle);
|
||||
|
@ -60,7 +59,7 @@ private:
|
|||
ParticleTree* _particles;
|
||||
VoxelTree* _voxels;
|
||||
AbstractAudioInterface* _audio;
|
||||
QVector<AvatarData*> _avatars; // only used during update()
|
||||
AvatarHashMap* _avatars;
|
||||
};
|
||||
|
||||
#endif /* defined(__hifi__ParticleCollisionSystem__) */
|
||||
|
|
Loading…
Reference in a new issue