mirror of
https://github.com/lubosz/overte.git
synced 2025-04-23 16:14:01 +02:00
Merge pull request #11950 from hyperlogic/bug-fix/hand-scaling
Fix for hand controller avatar scaling.
This commit is contained in:
commit
a7a6dee8e0
8 changed files with 61 additions and 15 deletions
|
@ -114,7 +114,8 @@ MyAvatar::MyAvatar(QThread* thread) :
|
|||
|
||||
_skeletonModel = std::make_shared<MySkeletonModel>(this, nullptr);
|
||||
connect(_skeletonModel.get(), &Model::setURLFinished, this, &Avatar::setModelURLFinished);
|
||||
|
||||
connect(_skeletonModel.get(), &Model::rigReady, this, &Avatar::rigReady);
|
||||
connect(_skeletonModel.get(), &Model::rigReset, this, &Avatar::rigReset);
|
||||
|
||||
using namespace recording;
|
||||
_skeletonModel->flagAsCauterized();
|
||||
|
|
|
@ -1217,6 +1217,15 @@ void Avatar::setModelURLFinished(bool success) {
|
|||
}
|
||||
}
|
||||
|
||||
// rig is ready
|
||||
void Avatar::rigReady() {
|
||||
buildUnscaledEyeHeightCache();
|
||||
}
|
||||
|
||||
// rig has been reset.
|
||||
void Avatar::rigReset() {
|
||||
clearUnscaledEyeHeightCache();
|
||||
}
|
||||
|
||||
// create new model, can return an instance of a SoftAttachmentModel rather then Model
|
||||
static std::shared_ptr<Model> allocateAttachmentModel(bool isSoft, const Rig& rigOverride, bool isCauterized) {
|
||||
|
@ -1584,18 +1593,17 @@ void Avatar::ensureInScene(AvatarSharedPointer self, const render::ScenePointer&
|
|||
}
|
||||
}
|
||||
|
||||
// thread-safe
|
||||
float Avatar::getEyeHeight() const {
|
||||
|
||||
if (QThread::currentThread() != thread()) {
|
||||
float result = DEFAULT_AVATAR_EYE_HEIGHT;
|
||||
BLOCKING_INVOKE_METHOD(const_cast<Avatar*>(this), "getEyeHeight", Q_RETURN_ARG(float, result));
|
||||
return result;
|
||||
}
|
||||
|
||||
return getModelScale() * getUnscaledEyeHeight();
|
||||
}
|
||||
|
||||
// thread-safe
|
||||
float Avatar::getUnscaledEyeHeight() const {
|
||||
return _unscaledEyeHeightCache.get();
|
||||
}
|
||||
|
||||
void Avatar::buildUnscaledEyeHeightCache() {
|
||||
float skeletonHeight = getUnscaledEyeHeightFromSkeleton();
|
||||
|
||||
// Sanity check by looking at the model extents.
|
||||
|
@ -1606,12 +1614,16 @@ float Avatar::getUnscaledEyeHeight() const {
|
|||
// This helps prevent absurdly large avatars from exceeding the domain height limit.
|
||||
const float MESH_SLOP_RATIO = 1.5f;
|
||||
if (meshHeight > skeletonHeight * MESH_SLOP_RATIO) {
|
||||
return meshHeight;
|
||||
_unscaledEyeHeightCache.set(meshHeight);
|
||||
} else {
|
||||
return skeletonHeight;
|
||||
_unscaledEyeHeightCache.set(skeletonHeight);
|
||||
}
|
||||
}
|
||||
|
||||
void Avatar::clearUnscaledEyeHeightCache() {
|
||||
_unscaledEyeHeightCache.set(DEFAULT_AVATAR_EYE_HEIGHT);
|
||||
}
|
||||
|
||||
float Avatar::getUnscaledEyeHeightFromSkeleton() const {
|
||||
|
||||
// TODO: if performance becomes a concern we can cache this value rather then computing it everytime.
|
||||
|
|
|
@ -257,8 +257,8 @@ public:
|
|||
|
||||
Q_INVOKABLE virtual float getEyeHeight() const override;
|
||||
|
||||
// returns eye height of avatar in meters, ignoreing avatar scale.
|
||||
// if _targetScale is 1 then this will be identical to getEyeHeight;
|
||||
// returns eye height of avatar in meters, ignoring avatar scale.
|
||||
// if _targetScale is 1 then this will be identical to getEyeHeight.
|
||||
virtual float getUnscaledEyeHeight() const override;
|
||||
|
||||
// returns true, if an acurate eye height estimage can be obtained by inspecting the avatar model skeleton and geometry,
|
||||
|
@ -280,10 +280,17 @@ public slots:
|
|||
glm::vec3 getRightPalmPosition() const;
|
||||
glm::quat getRightPalmRotation() const;
|
||||
|
||||
// hooked up to Model::setURLFinished signal
|
||||
void setModelURLFinished(bool success);
|
||||
|
||||
// hooked up to Model::rigReady & rigReset signals
|
||||
void rigReady();
|
||||
void rigReset();
|
||||
|
||||
protected:
|
||||
float getUnscaledEyeHeightFromSkeleton() const;
|
||||
void buildUnscaledEyeHeightCache();
|
||||
void clearUnscaledEyeHeightCache();
|
||||
virtual const QString& getSessionDisplayNameForTransport() const override { return _empty; } // Save a tiny bit of bandwidth. Mixer won't look at what we send.
|
||||
QString _empty{};
|
||||
virtual void maybeUpdateSessionDisplayNameFromTransport(const QString& sessionDisplayName) override { _sessionDisplayName = sessionDisplayName; } // don't use no-op setter!
|
||||
|
@ -384,6 +391,8 @@ protected:
|
|||
|
||||
float _displayNameTargetAlpha { 1.0f };
|
||||
float _displayNameAlpha { 1.0f };
|
||||
|
||||
ThreadSafeValueCache<float> _unscaledEyeHeightCache { DEFAULT_AVATAR_EYE_HEIGHT };
|
||||
};
|
||||
|
||||
#endif // hifi_Avatar_h
|
||||
|
|
|
@ -13,4 +13,6 @@ OtherAvatar::OtherAvatar(QThread* thread) : Avatar(thread) {
|
|||
_headData = new Head(this);
|
||||
_skeletonModel = std::make_shared<SkeletonModel>(this, nullptr);
|
||||
connect(_skeletonModel.get(), &Model::setURLFinished, this, &Avatar::setModelURLFinished);
|
||||
connect(_skeletonModel.get(), &Model::rigReady, this, &Avatar::rigReady);
|
||||
connect(_skeletonModel.get(), &Model::rigReset, this, &Avatar::rigReset);
|
||||
}
|
||||
|
|
|
@ -483,8 +483,22 @@ public:
|
|||
virtual void setTargetScale(float targetScale);
|
||||
|
||||
float getDomainLimitedScale() const;
|
||||
float getDomainMinScale() const;
|
||||
float getDomainMaxScale() const;
|
||||
|
||||
/**jsdoc
|
||||
* returns the minimum scale allowed for this avatar in the current domain.
|
||||
* This value can change as the user changes avatars or when changing domains.
|
||||
* @function AvatarData.getDomainMinScale
|
||||
* @returns {number} minimum scale allowed for this avatar in the current domain.
|
||||
*/
|
||||
Q_INVOKABLE float getDomainMinScale() const;
|
||||
|
||||
/**jsdoc
|
||||
* returns the maximum scale allowed for this avatar in the current domain.
|
||||
* This value can change as the user changes avatars or when changing domains.
|
||||
* @function AvatarData.getDomainMaxScale
|
||||
* @returns {number} maximum scale allowed for this avatar in the current domain.
|
||||
*/
|
||||
Q_INVOKABLE float getDomainMaxScale() const;
|
||||
|
||||
// returns eye height of avatar in meters, ignoreing avatar scale.
|
||||
// if _targetScale is 1 then this will be identical to getEyeHeight;
|
||||
|
|
|
@ -286,6 +286,7 @@ void Model::reset() {
|
|||
if (isLoaded()) {
|
||||
const FBXGeometry& geometry = getFBXGeometry();
|
||||
_rig.reset(geometry);
|
||||
emit rigReset();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -322,6 +323,7 @@ bool Model::updateGeometry() {
|
|||
_blendedVertexBuffers.push_back(buffer);
|
||||
}
|
||||
needFullUpdate = true;
|
||||
emit rigReady();
|
||||
}
|
||||
return needFullUpdate;
|
||||
}
|
||||
|
|
|
@ -273,6 +273,8 @@ signals:
|
|||
void setURLFinished(bool success);
|
||||
void setCollisionModelURLFinished(bool success);
|
||||
void requestRenderUpdate();
|
||||
void rigReady();
|
||||
void rigReset();
|
||||
|
||||
protected:
|
||||
|
||||
|
|
|
@ -12,6 +12,10 @@
|
|||
(function () {
|
||||
var dispatcherUtils = Script.require("/~/system/libraries/controllerDispatcherUtils.js");
|
||||
|
||||
function clamp(val, min, max) {
|
||||
return Math.max(min, Math.min(max, val));
|
||||
}
|
||||
|
||||
function ScaleAvatar(hand) {
|
||||
this.hand = hand;
|
||||
this.scalingStartAvatarScale = 0;
|
||||
|
@ -61,7 +65,7 @@
|
|||
controllerData.controllerLocations[this.otherHand()].position));
|
||||
|
||||
var newAvatarScale = (scalingCurrentDistance / this.scalingStartDistance) * this.scalingStartAvatarScale;
|
||||
MyAvatar.scale = newAvatarScale;
|
||||
MyAvatar.scale = clamp(newAvatarScale, MyAvatar.getDomainMinScale(), MyAvatar.getDomainMaxScale());
|
||||
MyAvatar.scaleChanged();
|
||||
}
|
||||
return dispatcherUtils.makeRunningValues(true, [], []);
|
||||
|
|
Loading…
Reference in a new issue