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_FRAMES_PER_METER = 3; // Based on testing
_avatarTransitMaxDistance = AVATAR_TRANSIT_MAX_DISTANCE;
_avatarTransitFrameCount = AVATAR_TRANSIT_FRAME_COUNT;
_avatarTransitFramesPerMeter = AVATAR_TRANSIT_FRAMES_PER_METER;
const QString START_ANIMATION_URL = "https://hifi-content.s3.amazonaws.com/luis/test_scripts/transitApp/animations/teleport01_warp.fbx";
const QString MIDDLE_ANIMATION_URL = "https://hifi-content.s3.amazonaws.com/luis/test_scripts/transitApp/animations/teleport01_warp.fbx";
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) {
@ -133,26 +141,37 @@ void AvatarManager::setSpace(workload::SpacePointer& 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) {
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
PerformanceWarning warn(showWarnings, "AvatarManager::updateMyAvatar()");
/*
std::shared_ptr<AvatarTransit> transit = _myAvatar->getTransit();
bool initTransit = false;
if (!transit->isTransiting()) {
initTransit = transit->update(_myAvatar->getWorldPosition(), _avatarTransitFrameCount, _avatarTransitFramesPerMeter, _avatarTransitDistanceBased, _avatarTransitMaxDistance);
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();
}
AvatarTransit::Status status = _myAvatar->updateTransit(_myAvatar->getWorldPosition(), _transitConfig);
if (_transitConfig._playAnimation) {
playTransitAnimations(status);
}
*/
_myAvatar->update(deltaTime);
render::Transaction transaction;
_myAvatar->updateRenderItem(transaction);
@ -276,7 +295,7 @@ void AvatarManager::updateOtherAvatars(float deltaTime) {
}
// smooth other avatars positions
{
avatar->_transit.update(avatar->_globalPosition, _avatarTransitFrameCount, _avatarTransitFramesPerMeter, _avatarTransitDistanceBased, _avatarTransitMaxDistance);
avatar->_transit.update(avatar->_globalPosition, _transitConfig);
}
avatar->simulate(deltaTime, inView);
@ -866,3 +885,30 @@ void AvatarManager::setAvatarSortCoefficient(const QString& name, const QScriptV
doc.insert("data", palData);
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 void setAvatarTransitDistanceBased(bool isDistanceBased) { _avatarTransitDistanceBased = isDistanceBased; }
Q_INVOKABLE void setAvatarTransitMaxDistance(float maxDistance) { _avatarTransitMaxDistance = maxDistance; }
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; }
Q_INVOKABLE QVariantMap getAvatarTransitData();
Q_INVOKABLE void setAvatarTransitData(const QVariantMap& data);
float getMyAvatarSendRate() const { return _myAvatarSendRate.rate(); }
int getIdentityRequestsSent() const { return _identityRequestsSent; }
@ -212,6 +206,7 @@ private:
AvatarSharedPointer newSharedAvatar() override;
void handleRemovedAvatar(const AvatarSharedPointer& removedAvatar, KillAvatarReason removalReason = KillAvatarReason::NoReason) override;
void playTransitAnimations(AvatarTransit::Status status);
QVector<AvatarSharedPointer> _avatarsToFade;
QVector<AvatarSharedPointer> _avatarsToCopy;
@ -237,11 +232,7 @@ private:
// Other avatars smooth transit global configuration
bool _avatarTransitDistanceBased { true };
float _avatarTransitMaxDistance;
int _avatarTransitFrameCount;
int _avatarTransitFramesPerMeter;
AvatarTransit::TransitConfig _transitConfig;
};
#endif // hifi_AvatarManager_h

View file

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

View file

@ -52,21 +52,55 @@ class Texture;
class AvatarTransit {
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() {};
bool update(const glm::vec3& avatarPosition, int totalFrames, int framesPerMeter, bool isDistanceBased, float maxDistance);
void start(const glm::vec3& startPosition, const glm::vec3& endPosition, int totalFrames, int framesPerMeter, bool isDistanceBased);
bool getNextPosition(glm::vec3& nextPosition);
Status update(const glm::vec3& avatarPosition, const TransitConfig& config);
bool isTransiting() { return _isTransiting; };
glm::vec3 getCurrentPosition() { return _currentPosition; };
bool getNextPosition(glm::vec3& nextPosition);
int getCurrentStep() { return _step; };
private:
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 };
glm::vec3 _startPosition;
glm::vec3 _endPosition;
glm::vec3 _currentPosition;
int _framesBefore { 0 };
int _framesAfter { 0 };
std::vector<glm::vec3> _transitSteps;
glm::vec3 _lastPosition;
int _step { 0 };
@ -385,6 +419,7 @@ public:
std::shared_ptr<AvatarTransit> getTransit() { return std::make_shared<AvatarTransit>(_transit); };
AvatarTransit::Status updateTransit(const glm::vec3& avatarPosition, const AvatarTransit::TransitConfig& config);
signals:
void targetScaleChanged(float targetScale);
@ -520,6 +555,7 @@ protected:
RateCounter<> _skeletonModelSimulationRate;
RateCounter<> _jointDataSimulationRate;
protected:
class AvatarEntityDataHash {
public:
@ -544,7 +580,7 @@ protected:
float _modelScale { 1.0f };
AvatarTransit _transit;
std::mutex _transitLock;
static int _jointConesID;