diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index a8dbb2f4fc..1e3df955ba 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -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()->setScriptEngine(scriptEngine); diff --git a/interface/src/FancyCamera.h b/interface/src/FancyCamera.h index cd231cd929..66f7a07dbd 100644 --- a/interface/src/FancyCamera.h +++ b/interface/src/FancyCamera.h @@ -13,9 +13,8 @@ #include "Camera.h" -#include +#include -// TODO: come up with a better name than "FancyCamera" class FancyCamera : public Camera { Q_OBJECT diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index fcd539ca7d..9688694287 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -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))); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 479a78e7c2..250d2241ac 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -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"; diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index ce8ec44f6c..3bd4c663d2 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -28,10 +28,8 @@ #include #include -#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); 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(); 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()->getLocalLights()) { - glm::vec3 direction = orientation * light.direction; - DependencyManager::get()->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()->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 Avatar::getSkeleton() { void Avatar::addToScene(AvatarSharedPointer myHandle, const render::ScenePointer& scene) { if (scene) { - render::Transaction transaction; auto nodelist = DependencyManager::get(); if (DependencyManager::get()->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"; } } diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index 14d1da530a..f86bf35bd9 100644 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -11,6 +11,7 @@ #ifndef hifi_Avatar_h #define hifi_Avatar_h +#include #include #include @@ -48,9 +49,10 @@ enum ScreenTintLayer { NUM_SCREEN_TINT_LAYERS }; -class AvatarMotionState; class Texture; +using AvatarPhysicsCallback = std::function; + 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) 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> _attachmentModels; @@ -315,10 +329,6 @@ protected: ThreadSafeValueCache _rightPalmPositionCache { glm::vec3() }; ThreadSafeValueCache _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 diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index c4bcb67a16..04ab1531ba 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -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 >(engine); -} - AvatarManager::AvatarManager(QObject* parent) : _avatarsToFade(), _myAvatar(std::make_shared(qApp->thread(), std::make_shared())) @@ -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(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(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::iterator itr = _avatarsToFade.begin(); - while (itr != _avatarsToFade.end()) { - auto avatar = std::static_pointer_cast(*itr); + QVector::iterator avatarItr = _avatarsToFade.begin(); + while (avatarItr != _avatarsToFade.end()) { + auto avatar = std::static_pointer_cast(*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(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& localLights) { - if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(this, "setLocalLights", Q_ARG(const QVector&, localLights)); - return; +void AvatarManager::deleteMotionStates() { + // delete motionstates that were removed from physics last frame + for (auto state : _motionStatesToDelete) { + delete state; } - _localLights = localLights; -} - -QVector AvatarManager::getLocalLights() const { - if (QThread::currentThread() != thread()) { - QVector result; - QMetaObject::invokeMethod(const_cast(this), "getLocalLights", Qt::BlockingQueuedConnection, - Q_RETURN_ARG(QVector, 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; } } diff --git a/interface/src/avatar/AvatarManager.h b/interface/src/avatar/AvatarManager.h index 45f1a597eb..c67088a4be 100644 --- a/interface/src/avatar/AvatarManager.h +++ b/interface/src/avatar/AvatarManager.h @@ -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& localLights); - Q_INVOKABLE QVector 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 _avatarsToFade; - QSet _motionStatesThatMightUpdate; + using AvatarMotionStateMap = QMap; + AvatarMotionStateMap _motionStates; VectorOfMotionStates _motionStatesToRemoveFromPhysics; + VectorOfMotionStates _motionStatesToDelete; SetOfMotionStates _motionStatesToAddToPhysics; std::shared_ptr _myAvatar; quint64 _lastSendAvatarDataTime = 0; // Controls MyAvatar send data rate. - QVector _localLights; - - bool _shouldShowReceiveStats = false; - std::list> _collisionInjectors; RateCounter<> _myAvatarSendRate; @@ -129,7 +115,4 @@ private: bool _shouldRender { true }; }; -Q_DECLARE_METATYPE(AvatarManager::LocalLight) -Q_DECLARE_METATYPE(QVector) - #endif // hifi_AvatarManager_h diff --git a/interface/src/avatar/AvatarMotionState.cpp b/interface/src/avatar/AvatarMotionState.cpp index 335245670b..ffa99e3990 100644 --- a/interface/src/avatar/AvatarMotionState.cpp +++ b/interface/src/avatar/AvatarMotionState.cpp @@ -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)->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)->getAcceleration(); } // virtual diff --git a/interface/src/avatar/AvatarMotionState.h b/interface/src/avatar/AvatarMotionState.h index 98b2b69373..a8dd7327ca 100644 --- a/interface/src/avatar/AvatarMotionState.h +++ b/interface/src/avatar/AvatarMotionState.h @@ -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; }; diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 6c265ef1b6..cb819c6b20 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -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) diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index b2cc912007..b4c79470de 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -692,9 +692,6 @@ protected: QString _sessionDisplayName { }; QUrl cannonicalSkeletonModelURL(const QUrl& empty) const; - float _displayNameTargetAlpha; - float _displayNameAlpha; - QHash _jointIndices; ///< 1-based, since zero is returned for missing keys QStringList _jointNames; ///< in order of depth-first traversal diff --git a/libraries/physics/src/ObjectMotionState.h b/libraries/physics/src/ObjectMotionState.h index 1d258560c3..4230f636b3 100644 --- a/libraries/physics/src/ObjectMotionState.h +++ b/libraries/physics/src/ObjectMotionState.h @@ -170,7 +170,7 @@ protected: bool _hasInternalKinematicChanges { false }; }; -typedef QSet SetOfMotionStates; -typedef QVector VectorOfMotionStates; +using SetOfMotionStates = QSet; +using VectorOfMotionStates = QVector; #endif // hifi_ObjectMotionState_h diff --git a/libraries/physics/src/PhysicsEngine.cpp b/libraries/physics/src/PhysicsEngine.cpp index ca6889485a..87a15eb264 100644 --- a/libraries/physics/src/PhysicsEngine.cpp +++ b/libraries/physics/src/PhysicsEngine.cpp @@ -220,6 +220,7 @@ void PhysicsEngine::removeObjects(const SetOfMotionStates& objects) { body->setMotionState(nullptr); delete body; } + object->clearIncomingDirtyFlags(); } } diff --git a/libraries/physics/src/PhysicsEngine.h b/libraries/physics/src/PhysicsEngine.h index 9f2f1aff5c..07de0e7b5c 100644 --- a/libraries/physics/src/PhysicsEngine.h +++ b/libraries/physics/src/PhysicsEngine.h @@ -41,8 +41,8 @@ public: void* _b; // ObjectMotionState pointer }; -typedef std::map ContactMap; -typedef std::vector CollisionEvents; +using ContactMap = std::map; +using CollisionEvents = std::vector; class PhysicsEngine { public: diff --git a/libraries/shared/src/RenderArgs.h b/libraries/shared/src/RenderArgs.h index 10a9a20287..f44d736e1a 100644 --- a/libraries/shared/src/RenderArgs.h +++ b/libraries/shared/src/RenderArgs.h @@ -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