mirror of
https://thingvellir.net/git/overte
synced 2025-03-27 23:52:03 +01:00
Enable transit animations
This commit is contained in:
parent
b39391ca7a
commit
96e8b060eb
4 changed files with 152 additions and 56 deletions
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in a new issue