Enable transit animations

This commit is contained in:
luiscuenca 2018-09-18 12:42:37 -07:00
parent b39391ca7a
commit 96e8b060eb
4 changed files with 152 additions and 56 deletions

View file

@ -79,13 +79,21 @@ AvatarManager::AvatarManager(QObject* parent) :
} }
}); });
const float AVATAR_TRANSIT_MAX_DISTANCE = 1.0f; const float AVATAR_TRANSIT_TRIGGER_DISTANCE = 1.0f;
const int AVATAR_TRANSIT_FRAME_COUNT = 11; // Based on testing const int AVATAR_TRANSIT_FRAME_COUNT = 11; // Based on testing
const int AVATAR_TRANSIT_FRAMES_PER_METER = 3; // Based on testing const int AVATAR_TRANSIT_FRAMES_PER_METER = 3; // Based on testing
_avatarTransitMaxDistance = AVATAR_TRANSIT_MAX_DISTANCE; const QString START_ANIMATION_URL = "https://hifi-content.s3.amazonaws.com/luis/test_scripts/transitApp/animations/teleport01_warp.fbx";
_avatarTransitFrameCount = AVATAR_TRANSIT_FRAME_COUNT; const QString MIDDLE_ANIMATION_URL = "https://hifi-content.s3.amazonaws.com/luis/test_scripts/transitApp/animations/teleport01_warp.fbx";
_avatarTransitFramesPerMeter = AVATAR_TRANSIT_FRAMES_PER_METER; const QString END_ANIMATION_URL = "https://hifi-content.s3.amazonaws.com/luis/test_scripts/transitApp/animations/teleport01_warp.fbx";
_transitConfig._totalFrames = AVATAR_TRANSIT_FRAME_COUNT;
_transitConfig._triggerDistance = AVATAR_TRANSIT_TRIGGER_DISTANCE;
_transitConfig._framesPerMeter = AVATAR_TRANSIT_FRAMES_PER_METER;
_transitConfig._isDistanceBased = true;
_transitConfig._startTransitAnimation = AvatarTransit::TransitAnimation(START_ANIMATION_URL, 30, 0, 10);
_transitConfig._middleTransitAnimation = AvatarTransit::TransitAnimation(MIDDLE_ANIMATION_URL, 30, 11, 0);
_transitConfig._endTransitAnimation = AvatarTransit::TransitAnimation(END_ANIMATION_URL, 30, 12, 38);
} }
AvatarSharedPointer AvatarManager::addAvatar(const QUuid& sessionUUID, const QWeakPointer<Node>& mixerWeakPointer) { AvatarSharedPointer AvatarManager::addAvatar(const QUuid& sessionUUID, const QWeakPointer<Node>& mixerWeakPointer) {
@ -133,26 +141,37 @@ void AvatarManager::setSpace(workload::SpacePointer& space ) {
_space = space; _space = space;
} }
void AvatarManager::playTransitAnimations(AvatarTransit::Status status) {
auto startAnimation = _transitConfig._startTransitAnimation;
auto middleAnimation = _transitConfig._middleTransitAnimation;
auto endAnimation = _transitConfig._endTransitAnimation;
switch (status) {
case AvatarTransit::Status::START_FRAME:
_myAvatar->overrideAnimation(startAnimation._animationUrl, startAnimation._fps, false, startAnimation._firstFrame, startAnimation._firstFrame + startAnimation._frameCount);
break;
case AvatarTransit::Status::START_TRANSIT:
_myAvatar->overrideAnimation(middleAnimation._animationUrl, middleAnimation._fps, false, middleAnimation._firstFrame, middleAnimation._firstFrame + middleAnimation._frameCount);
break;
case AvatarTransit::Status::END_TRANSIT:
_myAvatar->overrideAnimation(endAnimation._animationUrl, endAnimation._fps, false, endAnimation._firstFrame, endAnimation._firstFrame + endAnimation._frameCount);
break;
case AvatarTransit::Status::END_FRAME:
_myAvatar->restoreAnimation();
break;
}
}
void AvatarManager::updateMyAvatar(float deltaTime) { void AvatarManager::updateMyAvatar(float deltaTime) {
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
PerformanceWarning warn(showWarnings, "AvatarManager::updateMyAvatar()"); PerformanceWarning warn(showWarnings, "AvatarManager::updateMyAvatar()");
/*
std::shared_ptr<AvatarTransit> transit = _myAvatar->getTransit(); AvatarTransit::Status status = _myAvatar->updateTransit(_myAvatar->getWorldPosition(), _transitConfig);
bool initTransit = false;
if (!transit->isTransiting()) { if (_transitConfig._playAnimation) {
initTransit = transit->update(_myAvatar->getWorldPosition(), _avatarTransitFrameCount, _avatarTransitFramesPerMeter, _avatarTransitDistanceBased, _avatarTransitMaxDistance); playTransitAnimations(status);
if (initTransit) {
_myAvatar->getSkeletonModel()->getRig().restoreAnimation();
_myAvatar->getSkeletonModel()->getRig().overrideAnimation("https://hifi-content.s3.amazonaws.com/luis/test_scripts/transit_app/animations/teleport01_warp.fbx", 30, false, 0, 49);
}
}
if (transit->isTransiting()){
glm::vec3 nextPosition;
if (!transit->getNextPosition(nextPosition)) {
_myAvatar->getSkeletonModel()->getRig().restoreAnimation();
}
} }
*/
_myAvatar->update(deltaTime); _myAvatar->update(deltaTime);
render::Transaction transaction; render::Transaction transaction;
_myAvatar->updateRenderItem(transaction); _myAvatar->updateRenderItem(transaction);
@ -276,7 +295,7 @@ void AvatarManager::updateOtherAvatars(float deltaTime) {
} }
// smooth other avatars positions // smooth other avatars positions
{ {
avatar->_transit.update(avatar->_globalPosition, _avatarTransitFrameCount, _avatarTransitFramesPerMeter, _avatarTransitDistanceBased, _avatarTransitMaxDistance); avatar->_transit.update(avatar->_globalPosition, _transitConfig);
} }
avatar->simulate(deltaTime, inView); avatar->simulate(deltaTime, inView);
@ -866,3 +885,30 @@ void AvatarManager::setAvatarSortCoefficient(const QString& name, const QScriptV
doc.insert("data", palData); doc.insert("data", palData);
return doc.toVariantMap(); return doc.toVariantMap();
} }
QVariantMap AvatarManager::getAvatarTransitData() {
QVariantMap result;
result["frameCount"] = _transitConfig._totalFrames;
result["framesPerMeter"] = _transitConfig._framesPerMeter;
result["isDistanceBased"] = _transitConfig._isDistanceBased;
result["triggerDistance"] = _transitConfig._triggerDistance;
result["playAnimation"] = _transitConfig._playAnimation;
return result;
}
void AvatarManager::setAvatarTransitData(const QVariantMap& data) {
if (data.contains("frameCount")) {
_transitConfig._totalFrames = data["frameCount"].toInt();
}
if (data.contains("framesPerMeter")) {
_transitConfig._framesPerMeter = data["framesPerMeter"].toInt();
}
if (data.contains("isDistanceBased")) {
_transitConfig._isDistanceBased = data["isDistanceBased"].toBool();
}
if (data.contains("triggerDistance")) {
_transitConfig._triggerDistance = data["triggerDistance"].toDouble();
}
if (data.contains("playAnimation")) {
_transitConfig._playAnimation = data["playAnimation"].toBool();
}
}

View file

@ -178,14 +178,8 @@ public:
*/ */
Q_INVOKABLE QVariantMap getPalData(const QList<QString> specificAvatarIdentifiers = QList<QString>()); Q_INVOKABLE QVariantMap getPalData(const QList<QString> specificAvatarIdentifiers = QList<QString>());
Q_INVOKABLE void setAvatarTransitDistanceBased(bool isDistanceBased) { _avatarTransitDistanceBased = isDistanceBased; } Q_INVOKABLE QVariantMap getAvatarTransitData();
Q_INVOKABLE void setAvatarTransitMaxDistance(float maxDistance) { _avatarTransitMaxDistance = maxDistance; } Q_INVOKABLE void setAvatarTransitData(const QVariantMap& data);
Q_INVOKABLE void setAvatarTransitFrameCount(int frameCount) { _avatarTransitFrameCount = frameCount; }
Q_INVOKABLE void setAvatarTransitFramesPerMeter(int frameCount) { _avatarTransitFramesPerMeter = frameCount; }
Q_INVOKABLE bool getAvatarTransitDistanceBased() { return _avatarTransitDistanceBased; }
Q_INVOKABLE float getAvatarTransitMaxDistance() { return _avatarTransitMaxDistance; }
Q_INVOKABLE int getAvatarTransitFrameCount() { return _avatarTransitFrameCount; }
Q_INVOKABLE int getAvatarTransitFramesPerMeter() { return _avatarTransitFramesPerMeter; }
float getMyAvatarSendRate() const { return _myAvatarSendRate.rate(); } float getMyAvatarSendRate() const { return _myAvatarSendRate.rate(); }
int getIdentityRequestsSent() const { return _identityRequestsSent; } int getIdentityRequestsSent() const { return _identityRequestsSent; }
@ -212,6 +206,7 @@ private:
AvatarSharedPointer newSharedAvatar() override; AvatarSharedPointer newSharedAvatar() override;
void handleRemovedAvatar(const AvatarSharedPointer& removedAvatar, KillAvatarReason removalReason = KillAvatarReason::NoReason) override; void handleRemovedAvatar(const AvatarSharedPointer& removedAvatar, KillAvatarReason removalReason = KillAvatarReason::NoReason) override;
void playTransitAnimations(AvatarTransit::Status status);
QVector<AvatarSharedPointer> _avatarsToFade; QVector<AvatarSharedPointer> _avatarsToFade;
QVector<AvatarSharedPointer> _avatarsToCopy; QVector<AvatarSharedPointer> _avatarsToCopy;
@ -237,11 +232,7 @@ private:
// Other avatars smooth transit global configuration // Other avatars smooth transit global configuration
bool _avatarTransitDistanceBased { true }; AvatarTransit::TransitConfig _transitConfig;
float _avatarTransitMaxDistance;
int _avatarTransitFrameCount;
int _avatarTransitFramesPerMeter;
}; };
#endif // hifi_AvatarManager_h #endif // hifi_AvatarManager_h

View file

@ -113,29 +113,27 @@ void Avatar::setShowNamesAboveHeads(bool show) {
showNamesAboveHeads = show; showNamesAboveHeads = show;
} }
bool AvatarTransit::update(const glm::vec3& avatarPosition, int totalFrames, int framesPerMeter, bool isDistanceBased, float maxDistance) { AvatarTransit::Status AvatarTransit::update(const glm::vec3& avatarPosition, const AvatarTransit::TransitConfig& config) {
bool starting = false;
glm::vec3 currentPosition = _isTransiting ? _currentPosition : avatarPosition; glm::vec3 currentPosition = _isTransiting ? _currentPosition : avatarPosition;
float oneFrameDistance = glm::length(currentPosition - _lastPosition); float oneFrameDistance = glm::length(currentPosition - _lastPosition);
if (oneFrameDistance > maxDistance && !_isTransiting) { if (oneFrameDistance > config._triggerDistance && !_isTransiting) {
start(_lastPosition, currentPosition, totalFrames, framesPerMeter, isDistanceBased); start(_lastPosition, currentPosition, config);
starting = true; }
} return updatePosition(avatarPosition);
updatePosition(avatarPosition);
return starting;
} }
void AvatarTransit::start(const glm::vec3& startPosition, const glm::vec3& endPosition, int totalFrames, int framesPerMeter, bool isDistanceBased) { void AvatarTransit::start(const glm::vec3& startPosition, const glm::vec3& endPosition, const AvatarTransit::TransitConfig& config) {
_startPosition = startPosition; _startPosition = startPosition;
_endPosition = endPosition; _endPosition = endPosition;
_framesBefore = config._startTransitAnimation._frameCount;
_framesAfter = config._endTransitAnimation._frameCount;
_step = 0; _step = 0;
if (!isDistanceBased) { if (!config._isDistanceBased) {
calculateSteps(totalFrames); calculateSteps(config._totalFrames);
} else { } else {
float distance = glm::length(_endPosition - _startPosition); float distance = glm::length(_endPosition - _startPosition);
calculateSteps(framesPerMeter * distance); calculateSteps(config._framesPerMeter * distance);
} }
_isTransiting = true; _isTransiting = true;
} }
@ -145,22 +143,42 @@ void AvatarTransit::calculateSteps(int stepCount) {
glm::vec3 transitLine = _endPosition - startPosition; glm::vec3 transitLine = _endPosition - startPosition;
glm::vec3 direction = glm::normalize(transitLine); glm::vec3 direction = glm::normalize(transitLine);
glm::vec3 stepVector = (glm::length(transitLine) / stepCount) * direction; glm::vec3 stepVector = (glm::length(transitLine) / stepCount) * direction;
for (auto i = 0; i < stepCount; i++) { int totalSteps = stepCount + _framesBefore + _framesAfter;
glm::vec3 localStep = _transitSteps.size() > 0 ? _transitSteps[i-1] + stepVector : _startPosition + stepVector; for (auto i = 0; i < totalSteps; i++) {
_transitSteps.push_back(localStep); if (i < _framesBefore) {
_transitSteps.push_back(_startPosition);
} else if (i >= stepCount + _framesBefore) {
_transitSteps.push_back(_endPosition);
} else {
glm::vec3 localStep = _transitSteps.size() > _framesBefore ? _transitSteps[i - 1] + stepVector : _startPosition + stepVector;
_transitSteps.push_back(localStep);
}
} }
} }
void AvatarTransit::updatePosition(const glm::vec3& avatarPosition) { AvatarTransit::Status AvatarTransit::updatePosition(const glm::vec3& avatarPosition) {
Status status = Status::IDLE;
_lastPosition = _isTransiting ? _currentPosition : avatarPosition; _lastPosition = _isTransiting ? _currentPosition : avatarPosition;
if (_isTransiting) { if (_isTransiting) {
int lastIdx = (int)_transitSteps.size() - 1; int lastIdx = (int)_transitSteps.size() - 1;
_isTransiting = _step < lastIdx; _isTransiting = _step < lastIdx;
if (_isTransiting) { if (_isTransiting) {
if (_step == 0) {
status = Status::START_FRAME;
qDebug() << "Transit starting";
} else if (_step == _framesBefore - 1) {
status = Status::START_TRANSIT;
} else if (_step == (int)_transitSteps.size() - _framesAfter) {
status = Status::END_TRANSIT;
}
_step++; _step++;
_currentPosition = _transitSteps[_step]; _currentPosition = _transitSteps[_step];
} else {
status = Status::END_FRAME;
qDebug() << "Transit ending";
} }
} }
return status;
} }
bool AvatarTransit::getNextPosition(glm::vec3& nextPosition) { bool AvatarTransit::getNextPosition(glm::vec3& nextPosition) {
@ -1936,6 +1954,11 @@ float Avatar::getUnscaledEyeHeightFromSkeleton() const {
} }
} }
AvatarTransit::Status Avatar::updateTransit(const glm::vec3& avatarPosition, const AvatarTransit::TransitConfig& config) {
std::lock_guard<std::mutex> lock(_transitLock);
return _transit.update(avatarPosition, config);
}
void Avatar::addMaterial(graphics::MaterialLayer material, const std::string& parentMaterialName) { void Avatar::addMaterial(graphics::MaterialLayer material, const std::string& parentMaterialName) {
std::lock_guard<std::mutex> lock(_materialsLock); std::lock_guard<std::mutex> lock(_materialsLock);
_materials[parentMaterialName].push(material); _materials[parentMaterialName].push(material);

View file

@ -52,21 +52,55 @@ class Texture;
class AvatarTransit { class AvatarTransit {
public: public:
enum Status {
IDLE = 0,
START_FRAME,
START_TRANSIT,
TRANSITING,
END_TRANSIT,
END_FRAME
};
struct TransitAnimation {
TransitAnimation() {};
TransitAnimation(const QString& animationUrl, int fps, int firstFrame, int frameCount) :
_firstFrame(firstFrame), _frameCount(frameCount), _animationUrl(animationUrl), _fps(fps) {};
int _firstFrame;
int _frameCount;
QString _animationUrl;
int _fps;
};
struct TransitConfig {
TransitConfig() {};
int _totalFrames { 0 };
int _framesPerMeter { 0 };
bool _isDistanceBased { false };
float _triggerDistance { 0 };
bool _playAnimation { false };
TransitAnimation _startTransitAnimation;
TransitAnimation _middleTransitAnimation;
TransitAnimation _endTransitAnimation;
};
AvatarTransit() {}; AvatarTransit() {};
bool update(const glm::vec3& avatarPosition, int totalFrames, int framesPerMeter, bool isDistanceBased, float maxDistance); Status update(const glm::vec3& avatarPosition, const TransitConfig& config);
void start(const glm::vec3& startPosition, const glm::vec3& endPosition, int totalFrames, int framesPerMeter, bool isDistanceBased);
bool getNextPosition(glm::vec3& nextPosition);
bool isTransiting() { return _isTransiting; }; bool isTransiting() { return _isTransiting; };
glm::vec3 getCurrentPosition() { return _currentPosition; }; glm::vec3 getCurrentPosition() { return _currentPosition; };
bool getNextPosition(glm::vec3& nextPosition);
int getCurrentStep() { return _step; }; int getCurrentStep() { return _step; };
private: private:
void calculateSteps(int stepCount); void calculateSteps(int stepCount);
void updatePosition(const glm::vec3& avatarPosition); Status updatePosition(const glm::vec3& avatarPosition);
void start(const glm::vec3& startPosition, const glm::vec3& endPosition, const TransitConfig& config);
bool _isTransiting{ false }; bool _isTransiting{ false };
glm::vec3 _startPosition; glm::vec3 _startPosition;
glm::vec3 _endPosition; glm::vec3 _endPosition;
glm::vec3 _currentPosition; glm::vec3 _currentPosition;
int _framesBefore { 0 };
int _framesAfter { 0 };
std::vector<glm::vec3> _transitSteps; std::vector<glm::vec3> _transitSteps;
glm::vec3 _lastPosition; glm::vec3 _lastPosition;
int _step { 0 }; int _step { 0 };
@ -385,6 +419,7 @@ public:
std::shared_ptr<AvatarTransit> getTransit() { return std::make_shared<AvatarTransit>(_transit); }; std::shared_ptr<AvatarTransit> getTransit() { return std::make_shared<AvatarTransit>(_transit); };
AvatarTransit::Status updateTransit(const glm::vec3& avatarPosition, const AvatarTransit::TransitConfig& config);
signals: signals:
void targetScaleChanged(float targetScale); void targetScaleChanged(float targetScale);
@ -520,6 +555,7 @@ protected:
RateCounter<> _skeletonModelSimulationRate; RateCounter<> _skeletonModelSimulationRate;
RateCounter<> _jointDataSimulationRate; RateCounter<> _jointDataSimulationRate;
protected: protected:
class AvatarEntityDataHash { class AvatarEntityDataHash {
public: public:
@ -544,7 +580,7 @@ protected:
float _modelScale { 1.0f }; float _modelScale { 1.0f };
AvatarTransit _transit; AvatarTransit _transit;
std::mutex _transitLock;
static int _jointConesID; static int _jointConesID;