mirror of
https://github.com/lubosz/overte.git
synced 2025-04-08 07:22:43 +02:00
Fix for hand controller avatar scaling.
* Added getDomainMaxScale() and getDomainMinScale() to JS api. * Updated scaleAvatar controller module to use this to prevent scaling past the limits. * Made sure that getDomainMaxScale() getDomainMinScale() and getUnscaledEyeHeight are thread safe, so that they can be invoked on the script thread. * Added signals to Model class that can be used to let observers know when the Rig has finished initializing it's skeleton. and also when the skeleton is no longer valid. These hooks are used to cache the unscaled eye height of the avatar.
This commit is contained in:
parent
ed231fa4a1
commit
542af47e9e
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