mirror of
https://github.com/overte-org/overte.git
synced 2025-08-04 11:35:20 +02:00
Time-based frames, max distance and setting animation from script
This commit is contained in:
parent
96e8b060eb
commit
cad8425c7b
4 changed files with 118 additions and 75 deletions
|
@ -91,9 +91,11 @@ AvatarManager::AvatarManager(QObject* parent) :
|
|||
_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);
|
||||
|
||||
_transitConfig._startTransitAnimation = AvatarTransit::TransitAnimation(START_ANIMATION_URL, 0, 14);
|
||||
_transitConfig._middleTransitAnimation = AvatarTransit::TransitAnimation(MIDDLE_ANIMATION_URL, 15, 0);
|
||||
_transitConfig._endTransitAnimation = AvatarTransit::TransitAnimation(END_ANIMATION_URL, 16, 38);
|
||||
|
||||
}
|
||||
|
||||
AvatarSharedPointer AvatarManager::addAvatar(const QUuid& sessionUUID, const QWeakPointer<Node>& mixerWeakPointer) {
|
||||
|
@ -145,28 +147,39 @@ void AvatarManager::playTransitAnimations(AvatarTransit::Status status) {
|
|||
auto startAnimation = _transitConfig._startTransitAnimation;
|
||||
auto middleAnimation = _transitConfig._middleTransitAnimation;
|
||||
auto endAnimation = _transitConfig._endTransitAnimation;
|
||||
|
||||
const float REFERENCE_FPS = 30.0f;
|
||||
|
||||
switch (status) {
|
||||
case AvatarTransit::Status::START_FRAME:
|
||||
_myAvatar->overrideAnimation(startAnimation._animationUrl, startAnimation._fps, false, startAnimation._firstFrame, startAnimation._firstFrame + startAnimation._frameCount);
|
||||
qDebug() << "START_FRAME";
|
||||
_myAvatar->overrideAnimation(startAnimation._animationUrl, REFERENCE_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);
|
||||
qDebug() << "START_TRANSIT";
|
||||
_myAvatar->overrideAnimation(middleAnimation._animationUrl, REFERENCE_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);
|
||||
qDebug() << "END_TRANSIT";
|
||||
_myAvatar->overrideAnimation(endAnimation._animationUrl, REFERENCE_FPS, false, endAnimation._firstFrame, endAnimation._firstFrame + endAnimation._frameCount);
|
||||
break;
|
||||
case AvatarTransit::Status::END_FRAME:
|
||||
qDebug() << "END_FRAME";
|
||||
_myAvatar->restoreAnimation();
|
||||
break;
|
||||
case AvatarTransit::Status::IDLE:
|
||||
break;
|
||||
case AvatarTransit::Status::TRANSITING:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void AvatarManager::updateMyAvatar(float deltaTime) {
|
||||
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
||||
PerformanceWarning warn(showWarnings, "AvatarManager::updateMyAvatar()");
|
||||
|
||||
AvatarTransit::Status status = _myAvatar->updateTransit(_myAvatar->getWorldPosition(), _transitConfig);
|
||||
AvatarTransit::Status status = _myAvatar->updateTransit(deltaTime, _myAvatar->getWorldPosition(), _transitConfig);
|
||||
|
||||
if (_transitConfig._playAnimation) {
|
||||
playTransitAnimations(status);
|
||||
|
@ -295,7 +308,7 @@ void AvatarManager::updateOtherAvatars(float deltaTime) {
|
|||
}
|
||||
// smooth other avatars positions
|
||||
{
|
||||
avatar->_transit.update(avatar->_globalPosition, _transitConfig);
|
||||
avatar->_transit.update(deltaTime, avatar->_globalPosition, _transitConfig);
|
||||
}
|
||||
|
||||
avatar->simulate(deltaTime, inView);
|
||||
|
@ -911,4 +924,37 @@ void AvatarManager::setAvatarSortCoefficient(const QString& name, const QScriptV
|
|||
if (data.contains("playAnimation")) {
|
||||
_transitConfig._playAnimation = data["playAnimation"].toBool();
|
||||
}
|
||||
}
|
||||
|
||||
AvatarTransit::TransitAnimation AvatarManager::getAnimationFromJsonObject(const QJsonObject& object) {
|
||||
QString animationUrl;
|
||||
int firstFrame = 0;
|
||||
int frameCount = 0;
|
||||
if (object.contains("animationUrl")) {
|
||||
animationUrl = object["animationUrl"].toString();
|
||||
}
|
||||
if (object.contains("firstFrame")) {
|
||||
firstFrame = object["firstFrame"].toInt();
|
||||
}
|
||||
if (object.contains("frameCount")) {
|
||||
frameCount = object["frameCount"].toInt();
|
||||
}
|
||||
return AvatarTransit::TransitAnimation(animationUrl, firstFrame, frameCount);
|
||||
}
|
||||
|
||||
void AvatarManager::setAvatarTransitAnimationData(const QVariantMap& data) {
|
||||
AvatarTransit::TransitAnimation startAnimation, middleAnimation, endAnimation;
|
||||
|
||||
if (data.contains("startAnimation")) {
|
||||
QJsonObject object = data["startAnimation"].toJsonObject();
|
||||
_transitConfig._startTransitAnimation = getAnimationFromJsonObject(object);
|
||||
}
|
||||
if (data.contains("middleAnimation")) {
|
||||
QJsonObject object = data["middleAnimation"].toJsonObject();
|
||||
_transitConfig._middleTransitAnimation = getAnimationFromJsonObject(object);
|
||||
}
|
||||
if (data.contains("endAnimation")) {
|
||||
QJsonObject object = data["endAnimation"].toJsonObject();
|
||||
_transitConfig._endTransitAnimation = getAnimationFromJsonObject(object);
|
||||
}
|
||||
}
|
|
@ -180,6 +180,7 @@ public:
|
|||
|
||||
Q_INVOKABLE QVariantMap getAvatarTransitData();
|
||||
Q_INVOKABLE void setAvatarTransitData(const QVariantMap& data);
|
||||
Q_INVOKABLE void setAvatarTransitAnimationData(const QVariantMap& data);
|
||||
|
||||
float getMyAvatarSendRate() const { return _myAvatarSendRate.rate(); }
|
||||
int getIdentityRequestsSent() const { return _identityRequestsSent; }
|
||||
|
@ -208,6 +209,8 @@ private:
|
|||
void handleRemovedAvatar(const AvatarSharedPointer& removedAvatar, KillAvatarReason removalReason = KillAvatarReason::NoReason) override;
|
||||
void playTransitAnimations(AvatarTransit::Status status);
|
||||
|
||||
AvatarTransit::TransitAnimation getAnimationFromJsonObject(const QJsonObject& object);
|
||||
|
||||
QVector<AvatarSharedPointer> _avatarsToFade;
|
||||
QVector<AvatarSharedPointer> _avatarsToCopy;
|
||||
|
||||
|
|
|
@ -113,70 +113,63 @@ void Avatar::setShowNamesAboveHeads(bool show) {
|
|||
showNamesAboveHeads = show;
|
||||
}
|
||||
|
||||
AvatarTransit::Status AvatarTransit::update(const glm::vec3& avatarPosition, const AvatarTransit::TransitConfig& config) {
|
||||
AvatarTransit::Status AvatarTransit::update(float deltaTime, const glm::vec3& avatarPosition, const AvatarTransit::TransitConfig& config) {
|
||||
glm::vec3 currentPosition = _isTransiting ? _currentPosition : avatarPosition;
|
||||
float oneFrameDistance = glm::length(currentPosition - _lastPosition);
|
||||
if (oneFrameDistance > config._triggerDistance && !_isTransiting) {
|
||||
start(_lastPosition, currentPosition, config);
|
||||
const float MAX_TRANSIT_DISTANCE = 20.0f;
|
||||
if (oneFrameDistance > config._triggerDistance && oneFrameDistance < MAX_TRANSIT_DISTANCE && !_isTransiting) {
|
||||
start(deltaTime, _lastPosition, currentPosition, config);
|
||||
}
|
||||
return updatePosition(avatarPosition);
|
||||
_lastPosition = currentPosition;
|
||||
return updatePosition(deltaTime);
|
||||
}
|
||||
|
||||
void AvatarTransit::start(const glm::vec3& startPosition, const glm::vec3& endPosition, const AvatarTransit::TransitConfig& config) {
|
||||
void AvatarTransit::start(float deltaTime, 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 (!config._isDistanceBased) {
|
||||
calculateSteps(config._totalFrames);
|
||||
} else {
|
||||
float distance = glm::length(_endPosition - _startPosition);
|
||||
calculateSteps(config._framesPerMeter * distance);
|
||||
}
|
||||
|
||||
_transitLine = endPosition - startPosition;
|
||||
_totalDistance = glm::length(_transitLine);
|
||||
const float REFERENCE_FRAMES_PER_SECOND = 30.0f;
|
||||
|
||||
int framesBefore = config._playAnimation ? config._startTransitAnimation._frameCount : 0;
|
||||
int framesAfter = config._playAnimation ? config._endTransitAnimation._frameCount : 0;
|
||||
_timeBefore = (float)framesBefore / REFERENCE_FRAMES_PER_SECOND;
|
||||
_timeAfter = (float)framesAfter / REFERENCE_FRAMES_PER_SECOND;
|
||||
|
||||
int transitFrames = (!config._isDistanceBased) ? config._totalFrames : config._framesPerMeter * _totalDistance;
|
||||
_transitTime = (float)transitFrames / REFERENCE_FRAMES_PER_SECOND;
|
||||
_totalTime = _transitTime + _timeBefore + _timeAfter;
|
||||
_currentTime = 0.0f;
|
||||
_isTransiting = true;
|
||||
}
|
||||
|
||||
void AvatarTransit::calculateSteps(int stepCount) {
|
||||
glm::vec3 startPosition = _isTransiting ? _transitSteps[_step] : _startPosition;
|
||||
_transitSteps.clear();
|
||||
glm::vec3 transitLine = _endPosition - startPosition;
|
||||
glm::vec3 direction = glm::normalize(transitLine);
|
||||
glm::vec3 stepVector = (glm::length(transitLine) / stepCount) * direction;
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AvatarTransit::Status AvatarTransit::updatePosition(const glm::vec3& avatarPosition) {
|
||||
AvatarTransit::Status AvatarTransit::updatePosition(float deltaTime) {
|
||||
Status status = Status::IDLE;
|
||||
_lastPosition = _isTransiting ? _currentPosition : avatarPosition;
|
||||
if (_isTransiting) {
|
||||
int lastIdx = (int)_transitSteps.size() - 1;
|
||||
_isTransiting = _step < lastIdx;
|
||||
if (_isTransiting) {
|
||||
if (_step == 0) {
|
||||
float nextTime = _currentTime + deltaTime;
|
||||
glm::vec3 newPosition;
|
||||
if (nextTime < _timeBefore) {
|
||||
_currentPosition = _startPosition;
|
||||
if (_currentTime == 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 if (nextTime >= _totalTime - _timeAfter) {
|
||||
if (_currentTime < _totalTime - _timeAfter) {
|
||||
status = Status::END_TRANSIT;
|
||||
} else if (nextTime >= _totalTime) {
|
||||
status = Status::END_FRAME;
|
||||
_isTransiting = false;
|
||||
}
|
||||
_currentPosition = _endPosition;
|
||||
} else {
|
||||
status = Status::END_FRAME;
|
||||
qDebug() << "Transit ending";
|
||||
}
|
||||
if (_currentTime <= _timeBefore) {
|
||||
status = Status::START_TRANSIT;
|
||||
}
|
||||
float percentageIntoTransit = (nextTime - _timeBefore) / _transitTime;
|
||||
_currentPosition = _startPosition + percentageIntoTransit * _transitLine;
|
||||
}
|
||||
_currentTime = nextTime;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
@ -521,7 +514,6 @@ void Avatar::simulate(float deltaTime, bool inView) {
|
|||
if (_transit.isTransiting()) {
|
||||
glm::vec3 nextPosition;
|
||||
if (_transit.getNextPosition(nextPosition)) {
|
||||
// setWorldPosition(nextPosition);
|
||||
_globalPosition = nextPosition;
|
||||
_globalPositionChanged = usecTimestampNow();
|
||||
if (!hasParent()) {
|
||||
|
@ -540,7 +532,7 @@ void Avatar::simulate(float deltaTime, bool inView) {
|
|||
PROFILE_RANGE(simulation, "updateJoints");
|
||||
if (inView) {
|
||||
Head* head = getHead();
|
||||
if (true) {
|
||||
if (_hasNewJointData || _transit.isTransiting()) {
|
||||
_skeletonModel->getRig().copyJointsFromJointData(_jointData);
|
||||
glm::mat4 rootTransform = glm::scale(_skeletonModel->getScale()) * glm::translate(_skeletonModel->getOffset());
|
||||
_skeletonModel->getRig().computeExternalPoses(rootTransform);
|
||||
|
@ -1954,9 +1946,9 @@ float Avatar::getUnscaledEyeHeightFromSkeleton() const {
|
|||
}
|
||||
}
|
||||
|
||||
AvatarTransit::Status Avatar::updateTransit(const glm::vec3& avatarPosition, const AvatarTransit::TransitConfig& config) {
|
||||
AvatarTransit::Status Avatar::updateTransit(float deltaTime, const glm::vec3& avatarPosition, const AvatarTransit::TransitConfig& config) {
|
||||
std::lock_guard<std::mutex> lock(_transitLock);
|
||||
return _transit.update(avatarPosition, config);
|
||||
return _transit.update(deltaTime, avatarPosition, config);
|
||||
}
|
||||
|
||||
void Avatar::addMaterial(graphics::MaterialLayer material, const std::string& parentMaterialName) {
|
||||
|
|
|
@ -63,12 +63,11 @@ public:
|
|||
|
||||
struct TransitAnimation {
|
||||
TransitAnimation() {};
|
||||
TransitAnimation(const QString& animationUrl, int fps, int firstFrame, int frameCount) :
|
||||
_firstFrame(firstFrame), _frameCount(frameCount), _animationUrl(animationUrl), _fps(fps) {};
|
||||
TransitAnimation(const QString& animationUrl, int firstFrame, int frameCount) :
|
||||
_firstFrame(firstFrame), _frameCount(frameCount), _animationUrl(animationUrl) {};
|
||||
int _firstFrame;
|
||||
int _frameCount;
|
||||
QString _animationUrl;
|
||||
int _fps;
|
||||
};
|
||||
|
||||
struct TransitConfig {
|
||||
|
@ -83,27 +82,30 @@ public:
|
|||
TransitAnimation _endTransitAnimation;
|
||||
};
|
||||
|
||||
|
||||
AvatarTransit() {};
|
||||
Status update(const glm::vec3& avatarPosition, const TransitConfig& config);
|
||||
Status update(float deltaTime, 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);
|
||||
Status updatePosition(const glm::vec3& avatarPosition);
|
||||
void start(const glm::vec3& startPosition, const glm::vec3& endPosition, const TransitConfig& config);
|
||||
Status updatePosition(float deltaTime);
|
||||
void start(float deltaTime, 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 };
|
||||
|
||||
glm::vec3 _transitLine;
|
||||
float _totalDistance { 0.0f };
|
||||
float _totalTime { 0.0f };
|
||||
float _currentTime { 0.0f };
|
||||
float _transitTime { 0.0f };
|
||||
float _timeBefore { 0.0f };
|
||||
float _timeAfter { 0.0f };
|
||||
};
|
||||
|
||||
class Avatar : public AvatarData, public scriptable::ModelProvider {
|
||||
|
@ -419,7 +421,7 @@ public:
|
|||
|
||||
std::shared_ptr<AvatarTransit> getTransit() { return std::make_shared<AvatarTransit>(_transit); };
|
||||
|
||||
AvatarTransit::Status updateTransit(const glm::vec3& avatarPosition, const AvatarTransit::TransitConfig& config);
|
||||
AvatarTransit::Status updateTransit(float deltaTime, const glm::vec3& avatarPosition, const AvatarTransit::TransitConfig& config);
|
||||
signals:
|
||||
void targetScaleChanged(float targetScale);
|
||||
|
||||
|
|
Loading…
Reference in a new issue