Merge pull request #10245 from AndrewMeadows/avatar-renderer-002

more cleanup in preparation for moving Avatar class to lib
This commit is contained in:
Brad Davis 2017-05-02 10:37:22 -07:00 committed by GitHub
commit 425405f72d
16 changed files with 153 additions and 200 deletions

View file

@ -5423,9 +5423,6 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri
entityScriptingInterface->setPacketSender(&_entityEditSender);
entityScriptingInterface->setEntityTree(getEntities()->getTree());
// AvatarManager has some custom types
AvatarManager::registerMetaTypes(scriptEngine);
// give the script engine to the RecordingScriptingInterface for its callbacks
DependencyManager::get<RecordingScriptingInterface>()->setScriptEngine(scriptEngine);

View file

@ -13,9 +13,8 @@
#include "Camera.h"
#include <EntityItem.h>
#include <EntityTypes.h>
// TODO: come up with a better name than "FancyCamera"
class FancyCamera : public Camera {
Q_OBJECT

View file

@ -495,12 +495,15 @@ Menu::Menu() {
qApp, SLOT(setActiveEyeTracker()));
#endif
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::AvatarReceiveStats, 0, false,
avatarManager.data(), SLOT(setShouldShowReceiveStats(bool)));
action = addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::AvatarReceiveStats, 0, false);
connect(action, &QAction::triggered, [this]{ Avatar::setShowReceiveStats(isOptionChecked(MenuOption::AvatarReceiveStats)); });
action = addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::ShowBoundingCollisionShapes, 0, false);
connect(action, &QAction::triggered, [this]{ Avatar::setShowCollisionShapes(isOptionChecked(MenuOption::ShowBoundingCollisionShapes)); });
action = addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::ShowMyLookAtVectors, 0, false);
connect(action, &QAction::triggered, [this]{ Avatar::setShowMyLookAtVectors(isOptionChecked(MenuOption::ShowMyLookAtVectors)); });
action = addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::ShowOtherLookAtVectors, 0, false);
connect(action, &QAction::triggered, [this]{ Avatar::setShowOtherLookAtVectors(isOptionChecked(MenuOption::ShowOtherLookAtVectors)); });
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::RenderBoundingCollisionShapes);
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::RenderMyLookAtVectors, 0, false);
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::RenderOtherLookAtVectors, 0, false);
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::FixGaze, 0, false);
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::AnimDebugDrawDefaultPose, 0, false,
avatar.get(), SLOT(setEnableDebugDrawDefaultPose(bool)));

View file

@ -145,9 +145,6 @@ namespace MenuOption {
const QString Quit = "Quit";
const QString ReloadAllScripts = "Reload All Scripts";
const QString ReloadContent = "Reload Content (Clears all caches)";
const QString RenderBoundingCollisionShapes = "Show Bounding Collision Shapes";
const QString RenderMyLookAtVectors = "Show My Eye Vectors";
const QString RenderOtherLookAtVectors = "Show Other Eye Vectors";
const QString RenderMaxTextureMemory = "Maximum Texture Memory";
const QString RenderMaxTextureAutomatic = "Automatic Texture Memory";
const QString RenderMaxTexture4MB = "4 MB";
@ -173,8 +170,11 @@ namespace MenuOption {
const QString SendWrongDSConnectVersion = "Send wrong DS connect version";
const QString SendWrongProtocolVersion = "Send wrong protocol version";
const QString SetHomeLocation = "Set Home Location";
const QString ShowDSConnectTable = "Show Domain Connection Timing";
const QString ShowBordersEntityNodes = "Show Entity Nodes";
const QString ShowBoundingCollisionShapes = "Show Bounding Collision Shapes";
const QString ShowDSConnectTable = "Show Domain Connection Timing";
const QString ShowMyLookAtVectors = "Show My Eye Vectors";
const QString ShowOtherLookAtVectors = "Show Other Eye Vectors";
const QString ShowRealtimeEntityStats = "Show Realtime Entity Stats";
const QString StandingHMDSensorMode = "Standing HMD Sensor Mode";
const QString SimulateEyeTracking = "Simulate";

View file

@ -28,10 +28,8 @@
#include <VariantMapToScriptValue.h>
#include <DebugDraw.h>
#include "AvatarManager.h"
#include "AvatarMotionState.h"
#include "Camera.h"
#include "Menu.h"
#include "InterfaceLogging.h"
#include "SceneScriptingInterface.h"
#include "SoftAttachmentModel.h"
@ -59,7 +57,6 @@ namespace render {
auto avatarPtr = static_pointer_cast<Avatar>(avatar);
if (avatarPtr->isInitialized() && args) {
PROFILE_RANGE_BATCH(*args->_batch, "renderAvatarPayload");
// TODO AVATARS_RENDERER: remove need for qApp
avatarPtr->render(args);
}
}
@ -74,6 +71,31 @@ namespace render {
}
}
static bool showReceiveStats = false;
void Avatar::setShowReceiveStats(bool receiveStats) {
showReceiveStats = receiveStats;
}
static bool showMyLookAtVectors = false;
void Avatar::setShowMyLookAtVectors(bool showMine) {
showMyLookAtVectors = showMine;
}
static bool showOtherLookAtVectors = false;
void Avatar::setShowOtherLookAtVectors(bool showOthers) {
showOtherLookAtVectors = showOthers;
}
static bool showCollisionShapes = false;
void Avatar::setShowCollisionShapes(bool render) {
showCollisionShapes = render;
}
static bool showNamesAboveHeads = false;
void Avatar::setShowNamesAboveHeads(bool show) {
showNamesAboveHeads = show;
}
Avatar::Avatar(QThread* thread, RigPointer rig) :
AvatarData(),
_skeletonOffset(0.0f),
@ -126,11 +148,6 @@ Avatar::~Avatar() {
});
}
if (_motionState) {
delete _motionState;
_motionState = nullptr;
}
auto geometryCache = DependencyManager::get<GeometryCache>();
if (geometryCache) {
geometryCache->releaseID(_nameRectGeometryID);
@ -350,7 +367,7 @@ void Avatar::simulate(float deltaTime, bool inView) {
_smoothPositionTimer += deltaTime;
if (_smoothPositionTimer < _smoothPositionTime) {
AvatarData::setPosition(
lerp(_smoothPositionInitial,
lerp(_smoothPositionInitial,
_smoothPositionTarget,
easeInOutQuad(glm::clamp(_smoothPositionTimer / _smoothPositionTime, 0.0f, 1.0f)))
);
@ -363,7 +380,7 @@ void Avatar::simulate(float deltaTime, bool inView) {
_smoothOrientationTimer += deltaTime;
if (_smoothOrientationTimer < _smoothOrientationTime) {
AvatarData::setOrientation(
slerp(_smoothOrientationInitial,
slerp(_smoothOrientationInitial,
_smoothOrientationTarget,
easeInOutQuad(glm::clamp(_smoothOrientationTimer / _smoothOrientationTime, 0.0f, 1.0f)))
);
@ -535,14 +552,7 @@ void Avatar::updateRenderItem(render::Transaction& transaction) {
void Avatar::postUpdate(float deltaTime) {
bool renderLookAtVectors;
if (isMyAvatar()) {
renderLookAtVectors = Menu::getInstance()->isOptionChecked(MenuOption::RenderMyLookAtVectors);
} else {
renderLookAtVectors = Menu::getInstance()->isOptionChecked(MenuOption::RenderOtherLookAtVectors);
}
if (renderLookAtVectors) {
if (isMyAvatar() ? showMyLookAtVectors : showOtherLookAtVectors) {
const float EYE_RAY_LENGTH = 10.0;
const glm::vec4 BLUE(0.0f, 0.0f, 1.0f, 1.0f);
const glm::vec4 RED(1.0f, 0.0f, 0.0f, 1.0f);
@ -583,7 +593,6 @@ void Avatar::render(RenderArgs* renderArgs) {
bool havePosition, haveRotation;
if (_handState & LEFT_HAND_POINTING_FLAG) {
if (_handState & IS_FINGER_POINTING_FLAG) {
int leftIndexTip = getJointIndex("LeftHandIndex4");
int leftIndexTipJoint = getJointIndex("LeftHandIndex3");
@ -636,44 +645,25 @@ void Avatar::render(RenderArgs* renderArgs) {
return;
}
glm::vec3 toTarget = frustum.getPosition() - getPosition();
float distanceToTarget = glm::length(toTarget);
fixupModelsInScene(renderArgs->_scene);
{
fixupModelsInScene(renderArgs->_scene);
if (renderArgs->_renderMode != RenderArgs::SHADOW_RENDER_MODE) {
// add local lights
const float BASE_LIGHT_DISTANCE = 2.0f;
const float LIGHT_FALLOFF_RADIUS = 0.01f;
const float LIGHT_EXPONENT = 1.0f;
const float LIGHT_CUTOFF = glm::radians(80.0f);
float distance = BASE_LIGHT_DISTANCE * getUniformScale();
glm::vec3 position = _skeletonModel->getTranslation();
glm::quat orientation = getOrientation();
foreach (const AvatarManager::LocalLight& light, DependencyManager::get<AvatarManager>()->getLocalLights()) {
glm::vec3 direction = orientation * light.direction;
DependencyManager::get<DeferredLightingEffect>()->addSpotLight(position - direction * distance,
distance * 2.0f, light.color, 0.5f, LIGHT_FALLOFF_RADIUS, orientation, LIGHT_EXPONENT, LIGHT_CUTOFF);
}
}
bool renderBounding = Menu::getInstance()->isOptionChecked(MenuOption::RenderBoundingCollisionShapes);
if (renderBounding && shouldRenderHead(renderArgs) && _skeletonModel->isRenderable()) {
PROFILE_RANGE_BATCH(batch, __FUNCTION__":skeletonBoundingCollisionShapes");
const float BOUNDING_SHAPE_ALPHA = 0.7f;
_skeletonModel->renderBoundingCollisionShapes(*renderArgs->_batch, getUniformScale(), BOUNDING_SHAPE_ALPHA);
}
if (showCollisionShapes && shouldRenderHead(renderArgs) && _skeletonModel->isRenderable()) {
PROFILE_RANGE_BATCH(batch, __FUNCTION__":skeletonBoundingCollisionShapes");
const float BOUNDING_SHAPE_ALPHA = 0.7f;
_skeletonModel->renderBoundingCollisionShapes(*renderArgs->_batch, getUniformScale(), BOUNDING_SHAPE_ALPHA);
}
const float DISPLAYNAME_DISTANCE = 20.0f;
setShowDisplayName(distanceToTarget < DISPLAYNAME_DISTANCE);
if (!isMyAvatar() || renderArgs->_cameraMode != (int8_t)CAMERA_MODE_FIRST_PERSON) {
auto& frustum = renderArgs->getViewFrustum();
auto textPosition = getDisplayNamePosition();
if (frustum.pointIntersectsFrustum(textPosition)) {
renderDisplayName(batch, frustum, textPosition);
if (showReceiveStats || showNamesAboveHeads) {
glm::vec3 toTarget = frustum.getPosition() - getPosition();
float distanceToTarget = glm::length(toTarget);
const float DISPLAYNAME_DISTANCE = 20.0f;
updateDisplayNameAlpha(distanceToTarget < DISPLAYNAME_DISTANCE);
if (!isMyAvatar() || renderArgs->_cameraMode != (int8_t)CAMERA_MODE_FIRST_PERSON) {
auto& frustum = renderArgs->getViewFrustum();
auto textPosition = getDisplayNamePosition();
if (frustum.pointIntersectsFrustum(textPosition)) {
renderDisplayName(batch, frustum, textPosition);
}
}
}
}
@ -829,7 +819,7 @@ Transform Avatar::calculateDisplayNameTransform(const ViewFrustum& view, const g
void Avatar::renderDisplayName(gpu::Batch& batch, const ViewFrustum& view, const glm::vec3& textPosition) const {
PROFILE_RANGE_BATCH(batch, __FUNCTION__);
bool shouldShowReceiveStats = DependencyManager::get<AvatarManager>()->shouldShowReceiveStats() && !isMyAvatar();
bool shouldShowReceiveStats = showReceiveStats && !isMyAvatar();
// If we have nothing to draw, or it's totally transparent, or it's too close or behind the camera, return
static const float CLIP_DISTANCE = 0.2f;
@ -1200,8 +1190,8 @@ int Avatar::parseDataFromBuffer(const QByteArray& buffer) {
const float MOVE_DISTANCE_THRESHOLD = 0.001f;
_moving = glm::distance(oldPosition, getPosition()) > MOVE_DISTANCE_THRESHOLD;
if (_moving && _motionState) {
_motionState->addDirtyFlags(Simulation::DIRTY_POSITION);
if (_moving) {
addPhysicsFlags(Simulation::DIRTY_POSITION);
}
if (_moving || _hasNewJointData) {
locationChanged();
@ -1284,8 +1274,8 @@ float Avatar::getPelvisFloatingHeight() const {
return -_skeletonModel->getBindExtents().minimum.y;
}
void Avatar::setShowDisplayName(bool showDisplayName) {
if (!Menu::getInstance()->isOptionChecked(MenuOption::NamesAboveHeads)) {
void Avatar::updateDisplayNameAlpha(bool showDisplayName) {
if (!(showNamesAboveHeads || showReceiveStats)) {
_displayNameAlpha = 0.0f;
return;
}
@ -1323,14 +1313,18 @@ void Avatar::getCapsule(glm::vec3& start, glm::vec3& end, float& radius) {
radius = halfExtents.x;
}
void Avatar::setMotionState(AvatarMotionState* motionState) {
_motionState = motionState;
}
// virtual
void Avatar::rebuildCollisionShape() {
if (_motionState) {
_motionState->addDirtyFlags(Simulation::DIRTY_SHAPE);
addPhysicsFlags(Simulation::DIRTY_SHAPE);
}
void Avatar::setPhysicsCallback(AvatarPhysicsCallback cb) {
_physicsCallback = cb;
}
void Avatar::addPhysicsFlags(uint32_t flags) {
if (_physicsCallback) {
_physicsCallback(flags);
}
}
@ -1493,16 +1487,16 @@ QList<QVariant> Avatar::getSkeleton() {
void Avatar::addToScene(AvatarSharedPointer myHandle, const render::ScenePointer& scene) {
if (scene) {
render::Transaction transaction;
auto nodelist = DependencyManager::get<NodeList>();
if (DependencyManager::get<SceneScriptingInterface>()->shouldRenderAvatars()
&& !nodelist->isIgnoringNode(getSessionUUID())
&& !nodelist->isRadiusIgnoringNode(getSessionUUID())) {
render::Transaction transaction;
addToScene(myHandle, scene, transaction);
scene->enqueueTransaction(transaction);
}
scene->enqueueTransaction(transaction);
} else {
qCWarning(interfaceapp) << "AvatarManager::addAvatar() : Unexpected null scene, possibly during application shutdown";
qCWarning(interfaceapp) << "Avatar::addAvatar() : Unexpected null scene, possibly during application shutdown";
}
}

View file

@ -11,6 +11,7 @@
#ifndef hifi_Avatar_h
#define hifi_Avatar_h
#include <functional>
#include <glm/glm.hpp>
#include <glm/gtc/quaternion.hpp>
@ -48,9 +49,10 @@ enum ScreenTintLayer {
NUM_SCREEN_TINT_LAYERS
};
class AvatarMotionState;
class Texture;
using AvatarPhysicsCallback = std::function<void(uint32_t)>;
class Avatar : public AvatarData {
Q_OBJECT
@ -66,6 +68,12 @@ class Avatar : public AvatarData {
Q_PROPERTY(glm::vec3 skeletonOffset READ getSkeletonOffset WRITE setSkeletonOffset)
public:
static void setShowReceiveStats(bool receiveStats);
static void setShowMyLookAtVectors(bool showMine);
static void setShowOtherLookAtVectors(bool showOthers);
static void setShowCollisionShapes(bool render);
static void setShowNamesAboveHeads(bool show);
explicit Avatar(QThread* thread, RigPointer rig = nullptr);
~Avatar();
@ -148,7 +156,7 @@ public:
virtual void setSkeletonModelURL(const QUrl& skeletonModelURL) override;
virtual void setAttachmentData(const QVector<AttachmentData>& attachmentData) override;
void setShowDisplayName(bool showDisplayName);
void updateDisplayNameAlpha(bool showDisplayName);
virtual void setSessionDisplayName(const QString& sessionDisplayName) override { }; // no-op
virtual int parseDataFromBuffer(const QByteArray& buffer) override;
@ -185,8 +193,6 @@ public:
virtual void computeShapeInfo(ShapeInfo& shapeInfo);
void getCapsule(glm::vec3& start, glm::vec3& end, float& radius);
AvatarMotionState* getMotionState() { return _motionState; }
using SpatiallyNestable::setPosition;
virtual void setPosition(const glm::vec3& position) override;
using SpatiallyNestable::setOrientation;
@ -238,6 +244,17 @@ public:
return (lerpValue*(4.0f - 2.0f * lerpValue) - 1.0f);
}
float getBoundingRadius() const;
void addToScene(AvatarSharedPointer self, const render::ScenePointer& scene);
void ensureInScene(AvatarSharedPointer self, const render::ScenePointer& scene);
bool isInScene() const { return render::Item::isValidID(_renderItemID); }
bool isMoving() const { return _moving; }
//void setMotionState(AvatarMotionState* motionState);
void setPhysicsCallback(AvatarPhysicsCallback cb);
void addPhysicsFlags(uint32_t flags);
bool isInPhysicsSimulation() const { return _physicsCallback != nullptr; }
public slots:
@ -251,7 +268,6 @@ public slots:
void setModelURLFinished(bool success);
protected:
friend class AvatarManager;
const float SMOOTH_TIME_POSITION = 0.125f;
const float SMOOTH_TIME_ORIENTATION = 0.075f;
@ -260,8 +276,6 @@ protected:
QString _empty{};
virtual void maybeUpdateSessionDisplayNameFromTransport(const QString& sessionDisplayName) override { _sessionDisplayName = sessionDisplayName; } // don't use no-op setter!
void setMotionState(AvatarMotionState* motionState);
SkeletonModelPointer _skeletonModel;
glm::vec3 _skeletonOffset;
std::vector<std::shared_ptr<Model>> _attachmentModels;
@ -315,10 +329,6 @@ protected:
ThreadSafeValueCache<glm::vec3> _rightPalmPositionCache { glm::vec3() };
ThreadSafeValueCache<glm::quat> _rightPalmRotationCache { glm::quat() };
void addToScene(AvatarSharedPointer self, const render::ScenePointer& scene);
void ensureInScene(AvatarSharedPointer self, const render::ScenePointer& scene);
bool isInScene() const { return render::Item::isValidID(_renderItemID); }
// Some rate tracking support
RateCounter<> _simulationRate;
RateCounter<> _simulationInViewRate;
@ -354,13 +364,15 @@ private:
bool _isLookAtTarget { false };
bool _isAnimatingScale { false };
float getBoundingRadius() const;
static int _jointConesID;
int _voiceSphereID;
AvatarMotionState* _motionState = nullptr;
AvatarPhysicsCallback _physicsCallback { nullptr };
float _displayNameTargetAlpha { 1.0f };
float _displayNameAlpha { 1.0f };
};
#endif // hifi_Avatar_h

View file

@ -50,23 +50,6 @@ static const quint64 MIN_TIME_BETWEEN_MY_AVATAR_DATA_SENDS = USECS_PER_SECOND /
// 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
static QScriptValue localLightToScriptValue(QScriptEngine* engine, const AvatarManager::LocalLight& light) {
QScriptValue object = engine->newObject();
object.setProperty("direction", vec3toScriptValue(engine, light.direction));
object.setProperty("color", vec3toScriptValue(engine, light.color));
return object;
}
static void localLightFromScriptValue(const QScriptValue& value, AvatarManager::LocalLight& light) {
vec3FromScriptValue(value.property("direction"), light.direction);
vec3FromScriptValue(value.property("color"), light.color);
}
void AvatarManager::registerMetaTypes(QScriptEngine* engine) {
qScriptRegisterMetaType(engine, localLightToScriptValue, localLightFromScriptValue);
qScriptRegisterSequenceMetaType<QVector<AvatarManager::LocalLight> >(engine);
}
AvatarManager::AvatarManager(QObject* parent) :
_avatarsToFade(),
_myAvatar(std::make_shared<MyAvatar>(qApp->thread(), std::make_shared<Rig>()))
@ -91,6 +74,7 @@ AvatarManager::AvatarManager(QObject* parent) :
}
AvatarManager::~AvatarManager() {
assert(_motionStates.empty());
}
void AvatarManager::init() {
@ -145,10 +129,9 @@ float AvatarManager::getAvatarUpdateRate(const QUuid& sessionID, const QString&
float AvatarManager::getAvatarSimulationRate(const QUuid& sessionID, const QString& rateName) const {
auto avatar = std::static_pointer_cast<Avatar>(getAvatarBySessionID(sessionID));
return avatar ? avatar->getSimulationRate(rateName) : 0.0f;
return avatar ? avatar->getSimulationRate(rateName) : 0.0f;
}
void AvatarManager::updateOtherAvatars(float deltaTime) {
// lock the hash for read to check the size
QReadLocker lock(&_hashLock);
@ -200,16 +183,15 @@ void AvatarManager::updateOtherAvatars(float deltaTime) {
if (_shouldRender) {
avatar->ensureInScene(avatar, qApp->getMain3DScene());
}
if (!avatar->getMotionState()) {
if (!avatar->isInPhysicsSimulation()) {
ShapeInfo shapeInfo;
avatar->computeShapeInfo(shapeInfo);
btCollisionShape* shape = const_cast<btCollisionShape*>(ObjectMotionState::getShapeManager()->getShape(shapeInfo));
if (shape) {
// don't add to the simulation now, instead put it on a list to be added later
AvatarMotionState* motionState = new AvatarMotionState(avatar.get(), shape);
avatar->setMotionState(motionState);
AvatarMotionState* motionState = new AvatarMotionState(avatar, shape);
avatar->setPhysicsCallback([=] (uint32_t flags) { motionState->addDirtyFlags(flags); });
_motionStates.insert(avatar.get(), motionState);
_motionStatesToAddToPhysics.insert(motionState);
_motionStatesThatMightUpdate.insert(motionState);
}
}
avatar->animateScaleChanges(deltaTime);
@ -294,30 +276,24 @@ void AvatarManager::simulateAvatarFades(float deltaTime) {
const float MIN_FADE_SCALE = MIN_AVATAR_SCALE;
QReadLocker locker(&_hashLock);
QVector<AvatarSharedPointer>::iterator itr = _avatarsToFade.begin();
while (itr != _avatarsToFade.end()) {
auto avatar = std::static_pointer_cast<Avatar>(*itr);
QVector<AvatarSharedPointer>::iterator avatarItr = _avatarsToFade.begin();
while (avatarItr != _avatarsToFade.end()) {
auto avatar = std::static_pointer_cast<Avatar>(*avatarItr);
avatar->setTargetScale(avatar->getUniformScale() * SHRINK_RATE);
avatar->animateScaleChanges(deltaTime);
if (avatar->getTargetScale() <= MIN_FADE_SCALE) {
// fading to zero is such a rare event we push unique transaction for each one
// fading to zero is such a rare event we push a unique transaction for each
if (avatar->isInScene()) {
const render::ScenePointer& scene = qApp->getMain3DScene();
render::Transaction transaction;
avatar->removeFromScene(*itr, scene, transaction);
avatar->removeFromScene(*avatarItr, scene, transaction);
scene->enqueueTransaction(transaction);
}
// only remove from _avatarsToFade if we're sure its motionState has been removed from PhysicsEngine
if (_motionStatesToRemoveFromPhysics.empty()) {
itr = _avatarsToFade.erase(itr);
} else {
++itr;
}
avatarItr = _avatarsToFade.erase(avatarItr);
} else {
const bool inView = true; // HACK
avatar->simulate(deltaTime, inView);
++itr;
++avatarItr;
}
}
}
@ -329,15 +305,15 @@ AvatarSharedPointer AvatarManager::newSharedAvatar() {
void AvatarManager::handleRemovedAvatar(const AvatarSharedPointer& removedAvatar, KillAvatarReason removalReason) {
AvatarHashMap::handleRemovedAvatar(removedAvatar, removalReason);
// removedAvatar is a shared pointer to an AvatarData but we need to get to the derived Avatar
// class in this context so we can call methods that don't exist at the base class.
// remove from physics
auto avatar = std::static_pointer_cast<Avatar>(removedAvatar);
AvatarMotionState* motionState = avatar->getMotionState();
if (motionState) {
_motionStatesThatMightUpdate.remove(motionState);
avatar->setPhysicsCallback(nullptr);
AvatarMotionStateMap::iterator itr = _motionStates.find(avatar.get());
if (itr != _motionStates.end()) {
AvatarMotionState* motionState = *itr;
_motionStatesToAddToPhysics.remove(motionState);
_motionStatesToRemoveFromPhysics.push_back(motionState);
_motionStates.erase(itr);
}
if (removalReason == KillAvatarReason::TheirAvatarEnteredYourBubble) {
@ -373,11 +349,15 @@ void AvatarManager::clearOtherAvatars() {
++avatarIterator;
}
}
assert(scene);
scene->enqueueTransaction(transaction);
_myAvatar->clearLookAtTargetAvatar();
}
void AvatarManager::deleteAllAvatars() {
assert(_motionStates.empty()); // should have called clearOtherAvatars() before getting here
deleteMotionStates();
QReadLocker locker(&_hashLock);
AvatarHash::iterator avatarIterator = _avatarHash.begin();
while (avatarIterator != _avatarHash.end()) {
@ -387,27 +367,18 @@ void AvatarManager::deleteAllAvatars() {
}
}
void AvatarManager::setLocalLights(const QVector<AvatarManager::LocalLight>& localLights) {
if (QThread::currentThread() != thread()) {
QMetaObject::invokeMethod(this, "setLocalLights", Q_ARG(const QVector<AvatarManager::LocalLight>&, localLights));
return;
void AvatarManager::deleteMotionStates() {
// delete motionstates that were removed from physics last frame
for (auto state : _motionStatesToDelete) {
delete state;
}
_localLights = localLights;
}
QVector<AvatarManager::LocalLight> AvatarManager::getLocalLights() const {
if (QThread::currentThread() != thread()) {
QVector<AvatarManager::LocalLight> result;
QMetaObject::invokeMethod(const_cast<AvatarManager*>(this), "getLocalLights", Qt::BlockingQueuedConnection,
Q_RETURN_ARG(QVector<AvatarManager::LocalLight>, result));
return result;
}
return _localLights;
_motionStatesToDelete.clear();
}
void AvatarManager::getObjectsToRemoveFromPhysics(VectorOfMotionStates& result) {
result.clear();
result.swap(_motionStatesToRemoveFromPhysics);
deleteMotionStates();
result = _motionStatesToRemoveFromPhysics;
_motionStatesToDelete.swap(_motionStatesToRemoveFromPhysics);
}
void AvatarManager::getObjectsToAddToPhysics(VectorOfMotionStates& result) {
@ -420,10 +391,12 @@ void AvatarManager::getObjectsToAddToPhysics(VectorOfMotionStates& result) {
void AvatarManager::getObjectsToChange(VectorOfMotionStates& result) {
result.clear();
for (auto state : _motionStatesThatMightUpdate) {
if (state->_dirtyFlags > 0) {
result.push_back(state);
AvatarMotionStateMap::iterator motionStateItr = _motionStates.begin();
while (motionStateItr != _motionStates.end()) {
if ((*motionStateItr)->getIncomingDirtyFlags() != 0) {
result.push_back(*motionStateItr);
}
++motionStateItr;
}
}

View file

@ -62,18 +62,6 @@ public:
void clearOtherAvatars();
void deleteAllAvatars();
bool shouldShowReceiveStats() const { return _shouldShowReceiveStats; }
class LocalLight {
public:
glm::vec3 color;
glm::vec3 direction;
};
Q_INVOKABLE void setLocalLights(const QVector<AvatarManager::LocalLight>& localLights);
Q_INVOKABLE QVector<AvatarManager::LocalLight> getLocalLights() const;
void getObjectsToRemoveFromPhysics(VectorOfMotionStates& motionStates);
void getObjectsToAddToPhysics(VectorOfMotionStates& motionStates);
void getObjectsToChange(VectorOfMotionStates& motionStates);
@ -95,7 +83,6 @@ public:
float getMyAvatarSendRate() const { return _myAvatarSendRate.rate(); }
public slots:
void setShouldShowReceiveStats(bool shouldShowReceiveStats) { _shouldShowReceiveStats = shouldShowReceiveStats; }
void updateAvatarRenderStatus(bool shouldRenderAvatars);
private:
@ -105,21 +92,20 @@ private:
void simulateAvatarFades(float deltaTime);
AvatarSharedPointer newSharedAvatar() override;
void deleteMotionStates();
void handleRemovedAvatar(const AvatarSharedPointer& removedAvatar, KillAvatarReason removalReason = KillAvatarReason::NoReason) override;
QVector<AvatarSharedPointer> _avatarsToFade;
QSet<AvatarMotionState*> _motionStatesThatMightUpdate;
using AvatarMotionStateMap = QMap<Avatar*, AvatarMotionState*>;
AvatarMotionStateMap _motionStates;
VectorOfMotionStates _motionStatesToRemoveFromPhysics;
VectorOfMotionStates _motionStatesToDelete;
SetOfMotionStates _motionStatesToAddToPhysics;
std::shared_ptr<MyAvatar> _myAvatar;
quint64 _lastSendAvatarDataTime = 0; // Controls MyAvatar send data rate.
QVector<AvatarManager::LocalLight> _localLights;
bool _shouldShowReceiveStats = false;
std::list<QPointer<AudioInjector>> _collisionInjectors;
RateCounter<> _myAvatarSendRate;
@ -129,7 +115,4 @@ private:
bool _shouldRender { true };
};
Q_DECLARE_METATYPE(AvatarManager::LocalLight)
Q_DECLARE_METATYPE(QVector<AvatarManager::LocalLight>)
#endif // hifi_AvatarManager_h

View file

@ -17,7 +17,7 @@
#include "AvatarMotionState.h"
#include "BulletUtil.h"
AvatarMotionState::AvatarMotionState(Avatar* avatar, const btCollisionShape* shape) : ObjectMotionState(shape), _avatar(avatar) {
AvatarMotionState::AvatarMotionState(AvatarSharedPointer avatar, const btCollisionShape* shape) : ObjectMotionState(shape), _avatar(avatar) {
assert(_avatar);
_type = MOTIONSTATE_TYPE_AVATAR;
if (_shape) {
@ -49,7 +49,7 @@ PhysicsMotionType AvatarMotionState::computePhysicsMotionType() const {
// virtual and protected
const btCollisionShape* AvatarMotionState::computeNewShape() {
ShapeInfo shapeInfo;
_avatar->computeShapeInfo(shapeInfo);
std::static_pointer_cast<Avatar>(_avatar)->computeShapeInfo(shapeInfo);
return getShapeManager()->getShape(shapeInfo);
}
@ -130,7 +130,7 @@ glm::vec3 AvatarMotionState::getObjectAngularVelocity() const {
// virtual
glm::vec3 AvatarMotionState::getObjectGravity() const {
return _avatar->getAcceleration();
return std::static_pointer_cast<Avatar>(_avatar)->getAcceleration();
}
// virtual

View file

@ -20,7 +20,7 @@ class Avatar;
class AvatarMotionState : public ObjectMotionState {
public:
AvatarMotionState(Avatar* avatar, const btCollisionShape* shape);
AvatarMotionState(AvatarSharedPointer avatar, const btCollisionShape* shape);
virtual PhysicsMotionType getMotionType() const override { return _motionType; }
@ -74,11 +74,7 @@ protected:
virtual bool isReadyToComputeShape() const override { return true; }
virtual const btCollisionShape* computeNewShape() override;
// The AvatarMotionState keeps a RAW backpointer to its Avatar because all AvatarMotionState
// instances are "owned" by their corresponding Avatar instance and are deleted in the Avatar dtor.
// In other words, it is impossible for the Avatar to be deleted out from under its MotionState.
// In conclusion: weak pointer shennanigans would be pure overhead.
Avatar* _avatar; // do NOT use smartpointer here, no need for weakpointer
AvatarSharedPointer _avatar;
uint32_t _dirtyFlags;
};

View file

@ -63,8 +63,6 @@ AvatarData::AvatarData() :
_keyState(NO_KEY_DOWN),
_forceFaceTrackerConnected(false),
_headData(NULL),
_displayNameTargetAlpha(1.0f),
_displayNameAlpha(1.0f),
_errorLogExpiry(0),
_owningAvatarMixer(),
_targetVelocity(0.0f)

View file

@ -692,9 +692,6 @@ protected:
QString _sessionDisplayName { };
QUrl cannonicalSkeletonModelURL(const QUrl& empty) const;
float _displayNameTargetAlpha;
float _displayNameAlpha;
QHash<QString, int> _jointIndices; ///< 1-based, since zero is returned for missing keys
QStringList _jointNames; ///< in order of depth-first traversal

View file

@ -170,7 +170,7 @@ protected:
bool _hasInternalKinematicChanges { false };
};
typedef QSet<ObjectMotionState*> SetOfMotionStates;
typedef QVector<ObjectMotionState*> VectorOfMotionStates;
using SetOfMotionStates = QSet<ObjectMotionState*>;
using VectorOfMotionStates = QVector<ObjectMotionState*>;
#endif // hifi_ObjectMotionState_h

View file

@ -220,6 +220,7 @@ void PhysicsEngine::removeObjects(const SetOfMotionStates& objects) {
body->setMotionState(nullptr);
delete body;
}
object->clearIncomingDirtyFlags();
}
}

View file

@ -41,8 +41,8 @@ public:
void* _b; // ObjectMotionState pointer
};
typedef std::map<ContactKey, ContactInfo> ContactMap;
typedef std::vector<Collision> CollisionEvents;
using ContactMap = std::map<ContactKey, ContactInfo>;
using CollisionEvents = std::vector<Collision>;
class PhysicsEngine {
public:

View file

@ -130,8 +130,8 @@ public:
bool _enableTexturing { true };
RenderDetails _details;
render::ScenePointer _scene; // HACK
int8_t _cameraMode { -1 }; // HACK
render::ScenePointer _scene;
int8_t _cameraMode { -1 };
};
#endif // hifi_RenderArgs_h