From c9cdaadeb51490e3f4e892413234913d9302e524 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Wed, 30 Aug 2017 15:46:36 -0700 Subject: [PATCH] Better scale support in SpatiallyNestable class. Previously avatar used SpatiallyNestable scale to keep track of model rendering scale. It now uses a new member variable _modelScale instead. This is important because the notion of "Avatar" space does NOT include scale, so this is now reflected correctly in the SpatiallyNestable class. Similarly, EntityItems no longer stuff dimensions into the SpatiallyNestable scale field. a new _dimensions member variable is used instead. The SpatiallyNestable scale field for entities should always be one. Parent joints can now have scale if getAbsoluteJointScaleInObjectFrame() returns a non-zero scale. This is used in the case of the faux SENSOR_TO_WORLD_MATRIX_INDEX joint. Overlays now ignore the SpatiallyNestable scale, and render using only orientation, position and dimensions. Added qDebug stream support for Transform class. --- interface/src/Application.cpp | 6 +- interface/src/avatar/MyAvatar.cpp | 34 ++++- interface/src/avatar/MyAvatar.h | 1 + interface/src/ui/PreferencesDialog.cpp | 4 +- interface/src/ui/overlays/ModelOverlay.cpp | 18 +-- interface/src/ui/overlays/OverlaysPayload.cpp | 2 +- interface/src/ui/overlays/Web3DOverlay.cpp | 11 +- .../src/avatars-renderer/Avatar.cpp | 42 +++--- .../src/avatars-renderer/Avatar.h | 7 +- .../src/avatars-renderer/SkeletonModel.cpp | 6 +- libraries/entities/src/EntityItem.cpp | 9 +- libraries/entities/src/EntityItem.h | 3 +- libraries/entities/src/PolyLineEntityItem.cpp | 2 +- libraries/entities/src/PolyLineEntityItem.h | 2 - libraries/shared/src/SpatiallyNestable.cpp | 124 +++++++----------- libraries/shared/src/SpatiallyNestable.h | 17 +-- libraries/shared/src/Transform.cpp | 7 + libraries/shared/src/Transform.h | 4 +- 18 files changed, 146 insertions(+), 153 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index d9cbdd9b06..901b300277 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2463,7 +2463,7 @@ void Application::paintGL() { PerformanceTimer perfTimer("CameraUpdates"); auto myAvatar = getMyAvatar(); - boomOffset = myAvatar->getScale() * myAvatar->getBoomLength() * -IDENTITY_FORWARD; + boomOffset = myAvatar->getModelScale() * myAvatar->getBoomLength() * -IDENTITY_FORWARD; // The render mode is default or mirror if the camera is in mirror mode, assigned further below renderArgs._renderMode = RenderArgs::DEFAULT_RENDER_MODE; @@ -2516,14 +2516,14 @@ void Application::paintGL() { hmdOffset.x = -hmdOffset.x; _myCamera.setPosition(myAvatar->getDefaultEyePosition() - + glm::vec3(0, _raiseMirror * myAvatar->getUniformScale(), 0) + + glm::vec3(0, _raiseMirror * myAvatar->getModelScale(), 0) + mirrorBodyOrientation * glm::vec3(0.0f, 0.0f, 1.0f) * MIRROR_FULLSCREEN_DISTANCE * _scaleMirror + mirrorBodyOrientation * hmdOffset); } else { _myCamera.setOrientation(myAvatar->getOrientation() * glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f))); _myCamera.setPosition(myAvatar->getDefaultEyePosition() - + glm::vec3(0, _raiseMirror * myAvatar->getUniformScale(), 0) + + glm::vec3(0, _raiseMirror * myAvatar->getModelScale(), 0) + (myAvatar->getOrientation() * glm::quat(glm::vec3(0.0f, _rotateMirror, 0.0f))) * glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_FULLSCREEN_DISTANCE * _scaleMirror); } diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 91af85a108..eca61d95c8 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -558,7 +558,7 @@ void MyAvatar::simulate(float deltaTime) { headPosition = getPosition(); } head->setPosition(headPosition); - head->setScale(getUniformScale()); + head->setScale(getModelScale()); head->simulate(deltaTime); } @@ -1223,7 +1223,7 @@ void MyAvatar::updateLookAtTargetAvatar() { float distanceTo = glm::length(avatar->getHead()->getEyePosition() - cameraPosition); avatar->setIsLookAtTarget(false); if (!avatar->isMyAvatar() && avatar->isInitialized() && - (distanceTo < GREATEST_LOOKING_AT_DISTANCE * getUniformScale())) { + (distanceTo < GREATEST_LOOKING_AT_DISTANCE * getModelScale())) { float radius = glm::length(avatar->getHead()->getEyePosition() - avatar->getHead()->getRightEyePosition()); float angleTo = coneSphereAngle(getHead()->getEyePosition(), lookForward, avatar->getHead()->getEyePosition(), radius); if (angleTo < (smallestAngleTo * (isCurrentTarget ? KEEP_LOOKING_AT_CURRENT_ANGLE_FACTOR : 1.0f))) { @@ -1465,7 +1465,7 @@ glm::vec3 MyAvatar::getSkeletonPosition() const { void MyAvatar::rebuildCollisionShape() { // compute localAABox - float scale = getUniformScale(); + float scale = getModelScale(); float radius = scale * _skeletonModel->getBoundingCapsuleRadius(); float height = scale * _skeletonModel->getBoundingCapsuleHeight() + 2.0f * radius; glm::vec3 corner(-radius, -0.5f * height, -radius); @@ -1896,7 +1896,7 @@ void MyAvatar::preDisplaySide(RenderArgs* renderArgs) { const float RENDER_HEAD_CUTOFF_DISTANCE = 0.3f; bool MyAvatar::cameraInsideHead(const glm::vec3& cameraPosition) const { - return glm::length(cameraPosition - getHeadPosition()) < (RENDER_HEAD_CUTOFF_DISTANCE * getUniformScale()); + return glm::length(cameraPosition - getHeadPosition()) < (RENDER_HEAD_CUTOFF_DISTANCE * getModelScale()); } bool MyAvatar::shouldRenderHead(const RenderArgs* renderArgs) const { @@ -2251,7 +2251,7 @@ void MyAvatar::restrictScaleFromDomainSettings(const QJsonObject& domainSettings _targetScale = clampedScale; } - setScale(glm::vec3(_targetScale)); + setModelScale(_targetScale); rebuildCollisionShape(); settings.endGroup(); } @@ -2940,6 +2940,30 @@ glm::mat4 MyAvatar::computeCameraRelativeHandControllerMatrix(const glm::mat4& c return glm::inverse(avatarMatrix) * controllerWorldMatrix; } +glm::vec3 MyAvatar::getAbsoluteJointScaleInObjectFrame(int index) const { + if (index < 0) { + index += numeric_limits::max() + 1; // 65536 + } + + // only sensor to world matrix has non identity scale. + switch (index) { + case CAMERA_RELATIVE_CONTROLLER_LEFTHAND_INDEX: { + auto pose = getControllerPoseInSensorFrame(controller::Action::LEFT_HAND); + glm::mat4 controllerSensorMatrix = createMatFromQuatAndPos(pose.rotation, pose.translation); + glm::mat4 result = computeCameraRelativeHandControllerMatrix(controllerSensorMatrix); + return extractScale(result); + } + case CAMERA_RELATIVE_CONTROLLER_RIGHTHAND_INDEX: { + auto pose = getControllerPoseInSensorFrame(controller::Action::RIGHT_HAND); + glm::mat4 controllerSensorMatrix = createMatFromQuatAndPos(pose.rotation, pose.translation); + glm::mat4 result = computeCameraRelativeHandControllerMatrix(controllerSensorMatrix); + return extractScale(result); + } + default: + return Avatar::getAbsoluteJointScaleInObjectFrame(index); + } +} + glm::quat MyAvatar::getAbsoluteJointRotationInObjectFrame(int index) const { if (index < 0) { index += numeric_limits::max() + 1; // 65536 diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 1c7cd559a6..07ad61b271 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -513,6 +513,7 @@ public: Q_INVOKABLE void setCharacterControllerEnabled(bool enabled); // deprecated Q_INVOKABLE bool getCharacterControllerEnabled(); // deprecated + virtual glm::vec3 getAbsoluteJointScaleInObjectFrame(int index) const override; virtual glm::quat getAbsoluteJointRotationInObjectFrame(int index) const override; virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const override; diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index 8f59d46cc8..fb451f6b0e 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -193,8 +193,8 @@ void setupPreferences() { preferences->addPreference(new PrimaryHandPreference(AVATAR_TUNING, "Dominant Hand", getter, setter)); } { - auto getter = [=]()->float { return myAvatar->getUniformScale(); }; - auto setter = [=](float value) { myAvatar->setTargetScale(value); }; + auto getter = [=]()->float { return myAvatar->getModelScale(); }; + auto setter = [=](float value) { myAvatar->setModelScale(value); }; auto preference = new SpinnerSliderPreference(AVATAR_TUNING, "Avatar Scale", getter, setter); preference->setStep(0.05f); preference->setDecimals(2); diff --git a/interface/src/ui/overlays/ModelOverlay.cpp b/interface/src/ui/overlays/ModelOverlay.cpp index 0bed07891e..c0d352bcae 100644 --- a/interface/src/ui/overlays/ModelOverlay.cpp +++ b/interface/src/ui/overlays/ModelOverlay.cpp @@ -46,13 +46,15 @@ void ModelOverlay::update(float deltatime) { if (_updateModel) { _updateModel = false; _model->setSnapModelToCenter(true); + Transform transform = getTransform(); + transform.setScale(1.0f); // disable inherited scale if (_scaleToFit) { - _model->setScaleToFit(true, getScale() * getDimensions()); + _model->setScaleToFit(true, transform.getScale() * getDimensions()); } else { - _model->setScale(getScale()); + _model->setScale(transform.getScale()); } - _model->setRotation(getRotation()); - _model->setTranslation(getPosition()); + _model->setRotation(transform.getRotation()); + _model->setTranslation(transform.getTranslation()); _model->setURL(_url); _model->simulate(deltatime, true); } else { @@ -93,13 +95,13 @@ void ModelOverlay::setProperties(const QVariantMap& properties) { auto origPosition = getPosition(); auto origRotation = getRotation(); auto origDimensions = getDimensions(); - auto origScale = getScale(); + auto origScale = getSNScale(); Base3DOverlay::setProperties(properties); auto scale = properties["scale"]; if (scale.isValid()) { - setScale(vec3FromVariant(scale)); + setSNScale(vec3FromVariant(scale)); } auto dimensions = properties["dimensions"]; @@ -112,7 +114,7 @@ void ModelOverlay::setProperties(const QVariantMap& properties) { _scaleToFit = false; } - if (origPosition != getPosition() || origRotation != getRotation() || origDimensions != getDimensions() || origScale != getScale()) { + if (origPosition != getPosition() || origRotation != getRotation() || origDimensions != getDimensions() || origScale != getSNScale()) { _updateModel = true; } @@ -194,7 +196,7 @@ QVariant ModelOverlay::getProperty(const QString& property) { return vec3toVariant(getDimensions()); } if (property == "scale") { - return vec3toVariant(getScale()); + return vec3toVariant(getSNScale()); } if (property == "textures") { if (_modelTextures.size() > 0) { diff --git a/interface/src/ui/overlays/OverlaysPayload.cpp b/interface/src/ui/overlays/OverlaysPayload.cpp index f2684a4368..887bf7ff8e 100644 --- a/interface/src/ui/overlays/OverlaysPayload.cpp +++ b/interface/src/ui/overlays/OverlaysPayload.cpp @@ -74,7 +74,7 @@ namespace render { glm::vec3 myAvatarPosition = avatar->getPosition(); float angle = glm::degrees(glm::angle(myAvatarRotation)); glm::vec3 axis = glm::axis(myAvatarRotation); - float myAvatarScale = avatar->getUniformScale(); + float myAvatarScale = avatar->getModelScale(); Transform transform = Transform(); transform.setTranslation(myAvatarPosition); transform.setRotation(glm::angleAxis(angle, axis)); diff --git a/interface/src/ui/overlays/Web3DOverlay.cpp b/interface/src/ui/overlays/Web3DOverlay.cpp index 104082dee4..d56a90e8fe 100644 --- a/interface/src/ui/overlays/Web3DOverlay.cpp +++ b/interface/src/ui/overlays/Web3DOverlay.cpp @@ -199,7 +199,6 @@ QString Web3DOverlay::pickURL() { } } - void Web3DOverlay::loadSourceURL() { if (!_webSurface) { return; @@ -302,19 +301,11 @@ void Web3DOverlay::render(RenderArgs* args) { emit resizeWebSurface(); } - vec2 halfSize = getSize() / 2.0f; vec4 color(toGlm(getColor()), getAlpha()); Transform transform = getTransform(); - - // FIXME: applyTransformTo causes tablet overlay to detach from tablet entity. - // Perhaps rather than deleting the following code it should be run only if isFacingAvatar() is true? - /* - applyTransformTo(transform, true); - setTransform(transform); - */ - + transform.setScale(1.0f); // ignore inherited scale factor from parents if (glm::length2(getDimensions()) != 1.0f) { transform.postScale(vec3(getDimensions(), 1.0f)); } diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index fc0ee1df7b..4e8f2ad572 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -107,7 +107,7 @@ Avatar::Avatar(QThread* thread) : // we may have been created in the network thread, but we live in the main thread moveToThread(thread); - setScale(glm::vec3(1.0f)); // avatar scale is uniform + setModelScale(1.0f); // avatar scale is uniform auto geometryCache = DependencyManager::get(); _nameRectGeometryID = geometryCache->allocateID(); @@ -156,14 +156,14 @@ glm::vec3 Avatar::getNeckPosition() const { AABox Avatar::getBounds() const { if (!_skeletonModel->isRenderable() || _skeletonModel->needsFixupInScene()) { // approximately 2m tall, scaled to user request. - return AABox(getPosition() - glm::vec3(getUniformScale()), getUniformScale() * 2.0f); + return AABox(getPosition() - glm::vec3(getModelScale()), getModelScale() * 2.0f); } return _skeletonModel->getRenderableMeshBound(); } void Avatar::animateScaleChanges(float deltaTime) { if (_isAnimatingScale) { - float currentScale = getUniformScale(); + float currentScale = getModelScale(); float desiredScale = getDomainLimitedScale(); // use exponential decay toward the domain limit clamped scale @@ -178,7 +178,7 @@ void Avatar::animateScaleChanges(float deltaTime) { animatedScale = desiredScale; _isAnimatingScale = false; } - setScale(glm::vec3(animatedScale)); // avatar scale is uniform + setModelScale(animatedScale); // avatar scale is uniform // flag the joints as having changed for force update to RenderItem _hasNewJointData = true; @@ -365,7 +365,7 @@ void Avatar::simulate(float deltaTime, bool inView) { } head->setPosition(headPosition); } - head->setScale(getUniformScale()); + head->setScale(getModelScale()); head->simulate(deltaTime); } else { // a non-full update is still required so that the position, rotation, scale and bounds of the skeletonModel are updated. @@ -423,7 +423,7 @@ bool Avatar::isLookingAtMe(AvatarSharedPointer avatar) const { glm::vec3 theirLookAt = dynamic_pointer_cast(avatar)->getHead()->getLookAtPosition(); glm::vec3 myEyePosition = getHead()->getEyePosition(); - return glm::distance(theirLookAt, myEyePosition) <= (HEAD_SPHERE_RADIUS * getUniformScale()); + return glm::distance(theirLookAt, myEyePosition) <= (HEAD_SPHERE_RADIUS * getModelScale()); } void Avatar::slamPosition(const glm::vec3& newPosition) { @@ -654,7 +654,7 @@ void Avatar::render(RenderArgs* renderArgs) { if (showCollisionShapes && shouldRenderHead(renderArgs) && _skeletonModel->isRenderable()) { PROFILE_RANGE_BATCH(batch, __FUNCTION__":skeletonBoundingCollisionShapes"); const float BOUNDING_SHAPE_ALPHA = 0.7f; - _skeletonModel->renderBoundingCollisionShapes(renderArgs, *renderArgs->_batch, getUniformScale(), BOUNDING_SHAPE_ALPHA); + _skeletonModel->renderBoundingCollisionShapes(renderArgs, *renderArgs->_batch, getModelScale(), BOUNDING_SHAPE_ALPHA); } if (showReceiveStats || showNamesAboveHeads) { @@ -727,9 +727,9 @@ void Avatar::simulateAttachments(float deltaTime) { } else { if (_skeletonModel->getJointPositionInWorldFrame(jointIndex, jointPosition) && _skeletonModel->getJointRotationInWorldFrame(jointIndex, jointRotation)) { - model->setTranslation(jointPosition + jointRotation * attachment.translation * getUniformScale()); + model->setTranslation(jointPosition + jointRotation * attachment.translation * getModelScale()); model->setRotation(jointRotation * attachment.rotation); - float scale = getUniformScale() * attachment.scale; + float scale = getModelScale() * attachment.scale; model->setScaleToFit(true, model->getNaturalDimensions() * scale, true); // hack to force rescale model->setSnapModelToCenter(false); // hack to force resnap model->setSnapModelToCenter(true); @@ -889,7 +889,7 @@ void Avatar::renderDisplayName(gpu::Batch& batch, const ViewFrustum& view, const } void Avatar::setSkeletonOffset(const glm::vec3& offset) { - const float MAX_OFFSET_LENGTH = getUniformScale() * 0.5f; + const float MAX_OFFSET_LENGTH = getModelScale() * 0.5f; float offsetLength = glm::length(offset); if (offsetLength > MAX_OFFSET_LENGTH) { _skeletonOffset = (MAX_OFFSET_LENGTH / offsetLength) * offset; @@ -990,11 +990,8 @@ glm::quat Avatar::getAbsoluteJointRotationInObjectFrame(int index) const { switch (index) { case SENSOR_TO_WORLD_MATRIX_INDEX: { glm::mat4 sensorToWorldMatrix = getSensorToWorldMatrix(); - bool success; - Transform avatarTransform; - Transform::mult(avatarTransform, getParentTransform(success), getLocalTransform()); - glm::mat4 invAvatarMat = avatarTransform.getInverseMatrix(); - glm::mat4 finalMat = invAvatarMat * sensorToWorldMatrix; + glm::mat4 avatarMatrix = getLocalTransform().getMatrix(); + glm::mat4 finalMat = glm::inverse(avatarMatrix) * sensorToWorldMatrix; return glmExtractRotation(finalMat); } case CONTROLLER_LEFTHAND_INDEX: { @@ -1031,11 +1028,8 @@ glm::vec3 Avatar::getAbsoluteJointTranslationInObjectFrame(int index) const { switch (index) { case SENSOR_TO_WORLD_MATRIX_INDEX: { glm::mat4 sensorToWorldMatrix = getSensorToWorldMatrix(); - bool success; - Transform avatarTransform; - Transform::mult(avatarTransform, getParentTransform(success), getLocalTransform()); - glm::mat4 invAvatarMat = avatarTransform.getInverseMatrix(); - glm::mat4 finalMat = invAvatarMat * sensorToWorldMatrix; + glm::mat4 avatarMatrix = getLocalTransform().getMatrix(); + glm::mat4 finalMat = glm::inverse(avatarMatrix) * sensorToWorldMatrix; return extractTranslation(finalMat); } case CONTROLLER_LEFTHAND_INDEX: { @@ -1064,7 +1058,6 @@ glm::vec3 Avatar::getAbsoluteJointTranslationInObjectFrame(int index) const { } } -#ifdef SPATIALLY_NESTABLE_SCALE_SUPPORT glm::vec3 Avatar::getAbsoluteJointScaleInObjectFrame(int index) const { if (index < 0) { index += numeric_limits::max() + 1; // 65536 @@ -1080,7 +1073,6 @@ glm::vec3 Avatar::getAbsoluteJointScaleInObjectFrame(int index) const { return AvatarData::getAbsoluteJointScaleInObjectFrame(index); } } -#endif void Avatar::invalidateJointIndicesCache() const { QWriteLocker writeLock(&_modelJointIndicesCacheLock); @@ -1170,7 +1162,7 @@ glm::vec3 Avatar::getJointPosition(const QString& name) const { void Avatar::scaleVectorRelativeToPosition(glm::vec3 &positionToScale) const { //Scale a world space vector as if it was relative to the position - positionToScale = getPosition() + getUniformScale() * (positionToScale - getPosition()); + positionToScale = getPosition() + getModelScale() * (positionToScale - getPosition()); } void Avatar::setSkeletonModelURL(const QUrl& skeletonModelURL) { @@ -1372,7 +1364,7 @@ void Avatar::updateDisplayNameAlpha(bool showDisplayName) { // virtual void Avatar::computeShapeInfo(ShapeInfo& shapeInfo) { - float uniformScale = getUniformScale(); + float uniformScale = getModelScale(); shapeInfo.setCapsuleY(uniformScale * _skeletonModel->getBoundingCapsuleRadius(), 0.5f * uniformScale * _skeletonModel->getBoundingCapsuleHeight()); shapeInfo.setOffset(uniformScale * _skeletonModel->getBoundingCapsuleOffset()); @@ -1581,7 +1573,7 @@ float Avatar::getEyeHeight() const { // TODO: if performance becomes a concern we can cache this value rather then computing it everytime. // Makes assumption that the y = 0 plane in geometry is the ground plane. // We also make that assumption in Rig::computeAvatarBoundingCapsule() - float avatarScale = getUniformScale(); + float avatarScale = getModelScale(); if (_skeletonModel) { auto& rig = _skeletonModel->getRig(); int headTopJoint = rig.indexOfJoint("HeadTop_End"); diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index 7b0819655a..75d9afeb90 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h @@ -108,7 +108,6 @@ public: SkeletonModelPointer getSkeletonModel() { return _skeletonModel; } const SkeletonModelPointer getSkeletonModel() const { return _skeletonModel; } glm::vec3 getChestPosition() const; - float getUniformScale() const { return getScale().y; } const Head* getHead() const { return static_cast(_headData); } Head* getHead() { return static_cast(_headData); } @@ -151,9 +150,7 @@ public: */ Q_INVOKABLE virtual glm::vec3 getAbsoluteDefaultJointTranslationInObjectFrame(int index) const; -#ifdef SPATIALLY_NESTABLE_SCALE_SUPPORT virtual glm::vec3 getAbsoluteJointScaleInObjectFrame(int index) const override; -#endif virtual glm::quat getAbsoluteJointRotationInObjectFrame(int index) const override; virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const override; virtual bool setAbsoluteJointRotationInObjectFrame(int index, const glm::quat& rotation) override { return false; } @@ -263,6 +260,9 @@ public: */ Q_INVOKABLE float getEyeHeight() const; + float getModelScale() const { return _modelScale; } + void setModelScale(float scale) { _modelScale = scale; } + public slots: // FIXME - these should be migrated to use Pose data instead @@ -365,6 +365,7 @@ private: bool _isAnimatingScale { false }; bool _mustFadeIn { false }; bool _isFading { false }; + float _modelScale { 1.0f }; static int _jointConesID; diff --git a/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.cpp b/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.cpp index c0d5fc07d7..eaa62ecb0a 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.cpp @@ -121,7 +121,7 @@ void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) { void SkeletonModel::updateAttitude(const glm::quat& orientation) { setTranslation(_owningAvatar->getSkeletonPosition()); setRotation(orientation * Quaternions::Y_180); - setScale(glm::vec3(1.0f, 1.0f, 1.0f) * _owningAvatar->getScale()); + setScale(glm::vec3(1.0f, 1.0f, 1.0f) * _owningAvatar->getModelScale()); } // Called by Avatar::simulate after it has set the joint states (fullUpdate true if changed), @@ -294,7 +294,7 @@ bool SkeletonModel::getEyePositions(glm::vec3& firstEyePosition, glm::vec3& seco } glm::vec3 SkeletonModel::getDefaultEyeModelPosition() const { - return _owningAvatar->getScale() * _defaultEyeModelPosition; + return _owningAvatar->getModelScale() * _defaultEyeModelPosition; } float DENSITY_OF_WATER = 1000.0f; // kg/m^3 @@ -316,7 +316,7 @@ void SkeletonModel::computeBoundingShape() { float radius, height; glm::vec3 offset; _rig.computeAvatarBoundingCapsule(geometry, radius, height, offset); - float invScale = 1.0f / _owningAvatar->getUniformScale(); + float invScale = 1.0f / _owningAvatar->getModelScale(); _boundingCapsuleRadius = invScale * radius; _boundingCapsuleHeight = invScale * height; _boundingCapsuleLocalOffset = invScale * offset; diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 0c120d586c..6b57c79713 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -42,7 +42,8 @@ EntityItem::EntityItem(const EntityItemID& entityItemID) : setLocalVelocity(ENTITY_ITEM_DEFAULT_VELOCITY); setLocalAngularVelocity(ENTITY_ITEM_DEFAULT_ANGULAR_VELOCITY); // explicitly set transform parts to set dirty flags used by batch rendering - setScale(ENTITY_ITEM_DEFAULT_DIMENSIONS); + locationChanged(); + dimensionsChanged(); quint64 now = usecTimestampNow(); _lastSimulated = now; _lastUpdated = now; @@ -1382,7 +1383,11 @@ void EntityItem::setDimensions(const glm::vec3& value) { if (value.x <= 0.0f || value.y <= 0.0f || value.z <= 0.0f) { return; } - setScale(value); + if (_dimensions != value) { + _dimensions = value; + locationChanged(); + dimensionsChanged(); + } } /// The maximum bounding cube for the entity, independent of it's rotation. diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 84742587e9..a95f7ba316 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -179,7 +179,7 @@ public: void setDescription(const QString& value); /// Dimensions in meters (0.0 - TREE_SCALE) - inline const glm::vec3 getDimensions() const { return getScale(); } + inline const glm::vec3 getDimensions() const { return _dimensions; } virtual void setDimensions(const glm::vec3& value); float getLocalRenderAlpha() const; @@ -470,6 +470,7 @@ protected: virtual void dimensionsChanged() override; + glm::vec3 _dimensions { ENTITY_ITEM_DEFAULT_DIMENSIONS }; EntityTypes::EntityType _type { EntityTypes::Unknown }; quint64 _lastSimulated { 0 }; // last time this entity called simulate(), this includes velocity, angular velocity, // and physics changes diff --git a/libraries/entities/src/PolyLineEntityItem.cpp b/libraries/entities/src/PolyLineEntityItem.cpp index 23a5c88900..ad9686bdf2 100644 --- a/libraries/entities/src/PolyLineEntityItem.cpp +++ b/libraries/entities/src/PolyLineEntityItem.cpp @@ -176,7 +176,7 @@ void PolyLineEntityItem::calculateScaleAndRegistrationPoint() { } // if Polyline has only one or fewer points, use default dimension settings - SpatiallyNestable::setScale(newScale); + setDimensions(newScale); EntityItem::setRegistrationPoint(newRegistrationPoint); } diff --git a/libraries/entities/src/PolyLineEntityItem.h b/libraries/entities/src/PolyLineEntityItem.h index 4860e3d4a4..9fbc6c60a1 100644 --- a/libraries/entities/src/PolyLineEntityItem.h +++ b/libraries/entities/src/PolyLineEntityItem.h @@ -91,8 +91,6 @@ class PolyLineEntityItem : public EntityItem { // disable these external interfaces as PolyLineEntities caculate their own dimensions based on the points they contain virtual void setRegistrationPoint(const glm::vec3& value) override {}; - virtual void setScale(const glm::vec3& scale) override {}; - virtual void setScale(float value) override {}; virtual void debugDump() const override; static const float DEFAULT_LINE_WIDTH; diff --git a/libraries/shared/src/SpatiallyNestable.cpp b/libraries/shared/src/SpatiallyNestable.cpp index 0bf7a8b95d..c20ce90cd6 100644 --- a/libraries/shared/src/SpatiallyNestable.cpp +++ b/libraries/shared/src/SpatiallyNestable.cpp @@ -84,12 +84,7 @@ Transform SpatiallyNestable::getParentTransform(bool& success, int depth) const return result; } if (parent) { -#ifdef SPATIALLY_NESTABLE_SCALE_SUPPORT result = parent->getTransform(_parentJointIndex, success, depth + 1); -#else - Transform parentTransform = parent->getTransform(_parentJointIndex, success, depth + 1); - result = parentTransform.setScale(1.0f); // TODO: scaling -#endif } return result; } @@ -161,7 +156,6 @@ void SpatiallyNestable::setParentJointIndex(quint16 parentJointIndex) { glm::vec3 SpatiallyNestable::worldToLocal(const glm::vec3& position, const QUuid& parentID, int parentJointIndex, bool& success) { - Transform result; QSharedPointer parentFinder = DependencyManager::get(); if (!parentFinder) { success = false; @@ -185,25 +179,17 @@ glm::vec3 SpatiallyNestable::worldToLocal(const glm::vec3& position, if (!success) { return glm::vec3(0.0f); } -#ifndef SPATIALLY_NESTABLE_SCALE_SUPPORT - parentTransform.setScale(1.0f); // TODO: scale -#endif } success = true; - Transform positionTransform; - positionTransform.setTranslation(position); - Transform myWorldTransform; - Transform::mult(myWorldTransform, parentTransform, positionTransform); - myWorldTransform.setTranslation(position); - Transform::inverseMult(result, parentTransform, myWorldTransform); - return result.getTranslation(); + Transform invParentTransform; + parentTransform.evalInverse(invParentTransform); + return invParentTransform.transform(position); } glm::quat SpatiallyNestable::worldToLocal(const glm::quat& orientation, const QUuid& parentID, int parentJointIndex, bool& success) { - Transform result; QSharedPointer parentFinder = DependencyManager::get(); if (!parentFinder) { success = false; @@ -227,19 +213,11 @@ glm::quat SpatiallyNestable::worldToLocal(const glm::quat& orientation, if (!success) { return glm::quat(); } -#ifndef SPATIALLY_NESTABLE_SCALE_SUPPORT - parentTransform.setScale(1.0f); // TODO: scale -#endif } success = true; - Transform orientationTransform; - orientationTransform.setRotation(orientation); - Transform myWorldTransform; - Transform::mult(myWorldTransform, parentTransform, orientationTransform); - myWorldTransform.setRotation(orientation); - Transform::inverseMult(result, parentTransform, myWorldTransform); - return result.getRotation(); + glm::quat invParentOrientation = glm::inverse(parentTransform.getRotation()); + return invParentOrientation * orientation; } glm::vec3 SpatiallyNestable::worldToLocalVelocity(const glm::vec3& velocity, const QUuid& parentID, @@ -301,9 +279,6 @@ glm::vec3 SpatiallyNestable::localToWorld(const glm::vec3& position, if (!success) { return glm::vec3(0.0f); } -#ifndef SPATIALLY_NESTABLE_SCALE_SUPPORT - parentTransform.setScale(1.0f); // TODO: scale -#endif } success = true; @@ -645,9 +620,6 @@ const Transform SpatiallyNestable::getTransform(int jointIndex, bool& success, i } Transform worldTransform = getTransform(success, depth); -#ifndef SPATIALLY_NESTABLE_SCALE_SUPPORT - worldTransform.setScale(1.0f); // TODO: scale -#endif if (!success) { return jointInWorldFrame; } @@ -686,61 +658,51 @@ bool SpatiallyNestable::setTransform(const Transform& transform) { return success; } -glm::vec3 SpatiallyNestable::getScale() const { - // TODO: scale - glm::vec3 result; - _transformLock.withReadLock([&] { - result = _transform.getScale(); - }); +glm::vec3 SpatiallyNestable::getSNScale() const { + bool success; + auto result = getSNScale(success); + #ifdef WANT_DEBUG + if (!success) { + qCDebug(shared) << "Warning -- getScale failed" << getID(); + } + #endif return result; } -glm::vec3 SpatiallyNestable::getScale(int jointIndex) const { - // TODO: scale - return getScale(); +glm::vec3 SpatiallyNestable::getSNScale(bool& success) const { + return getTransform(success).getScale(); } -void SpatiallyNestable::setScale(const glm::vec3& scale) { +glm::vec3 SpatiallyNestable::getSNScale(int jointIndex, bool& success) const { + return getTransform(jointIndex, success).getScale(); +} + +void SpatiallyNestable::setSNScale(const glm::vec3& scale) { + bool success; + setSNScale(scale, success); +} + +void SpatiallyNestable::setSNScale(const glm::vec3& scale, bool& success) { // guard against introducing NaN into the transform if (isNaN(scale)) { - qCDebug(shared) << "SpatiallyNestable::setScale -- scale contains NaN"; + success = false; return; } bool changed = false; - // TODO: scale + Transform parentTransform = getParentTransform(success); + Transform myWorldTransform; _transformLock.withWriteLock([&] { - if (_transform.getScale() != scale) { - _transform.setScale(scale); + Transform::mult(myWorldTransform, parentTransform, _transform); + if (myWorldTransform.getScale() != scale) { changed = true; + myWorldTransform.setScale(scale); + Transform::inverseMult(_transform, parentTransform, myWorldTransform); _scaleChanged = usecTimestampNow(); } }); - if (changed) { - dimensionsChanged(); - } -} - -void SpatiallyNestable::setScale(float value) { - // guard against introducing NaN into the transform - if (value <= 0.0f) { - qCDebug(shared) << "SpatiallyNestable::setScale -- scale is zero or negative value"; - return; - } - - bool changed = false; - // TODO: scale - _transformLock.withWriteLock([&] { - glm::vec3 beforeScale = _transform.getScale(); - _transform.setScale(value); - if (_transform.getScale() != beforeScale) { - changed = true; - _scaleChanged = usecTimestampNow(); - } - }); - - if (changed) { - dimensionsChanged(); + if (success && changed) { + locationChanged(); } } @@ -857,8 +819,7 @@ void SpatiallyNestable::setLocalAngularVelocity(const glm::vec3& angularVelocity }); } -glm::vec3 SpatiallyNestable::getLocalScale() const { - // TODO: scale +glm::vec3 SpatiallyNestable::getLocalSNScale() const { glm::vec3 result; _transformLock.withReadLock([&] { result = _transform.getScale(); @@ -866,7 +827,7 @@ glm::vec3 SpatiallyNestable::getLocalScale() const { return result; } -void SpatiallyNestable::setLocalScale(const glm::vec3& scale) { +void SpatiallyNestable::setLocalSNScale(const glm::vec3& scale) { // guard against introducing NaN into the transform if (isNaN(scale)) { qCDebug(shared) << "SpatiallyNestable::setLocalScale -- scale contains NaN"; @@ -874,7 +835,6 @@ void SpatiallyNestable::setLocalScale(const glm::vec3& scale) { } bool changed = false; - // TODO: scale _transformLock.withWriteLock([&] { if (_transform.getScale() != scale) { _transform.setScale(scale); @@ -918,10 +878,8 @@ const Transform SpatiallyNestable::getAbsoluteJointTransformInObjectFrame(int jo Transform jointTransformInObjectFrame; glm::vec3 position = getAbsoluteJointTranslationInObjectFrame(jointIndex); glm::quat orientation = getAbsoluteJointRotationInObjectFrame(jointIndex); -#ifdef SPATIALLY_NESTABLE_SCALE_SUPPORT glm::vec3 scale = getAbsoluteJointScaleInObjectFrame(jointIndex); jointTransformInObjectFrame.setScale(scale); -#endif jointTransformInObjectFrame.setRotation(orientation); jointTransformInObjectFrame.setTranslation(position); return jointTransformInObjectFrame; @@ -1214,3 +1172,13 @@ QString SpatiallyNestable::nestableTypeToString(NestableType nestableType) { return "unknown"; } } + +void SpatiallyNestable::dump(const QString& prefix) const { + qDebug().noquote() << prefix << "id = " << getID(); + qDebug().noquote() << prefix << "transform = " << _transform; + bool success; + SpatiallyNestablePointer parent = getParentPointer(success); + if (success && parent) { + parent->dump(prefix + " "); + } +} diff --git a/libraries/shared/src/SpatiallyNestable.h b/libraries/shared/src/SpatiallyNestable.h index cb3dba754a..4195efc553 100644 --- a/libraries/shared/src/SpatiallyNestable.h +++ b/libraries/shared/src/SpatiallyNestable.h @@ -111,14 +111,15 @@ public: virtual AACube getQueryAACube(bool& success) const; virtual AACube getQueryAACube() const; - virtual glm::vec3 getScale() const; - virtual void setScale(const glm::vec3& scale); - virtual void setScale(float value); + virtual glm::vec3 getSNScale() const; + virtual glm::vec3 getSNScale(bool& success) const; + virtual void setSNScale(const glm::vec3& scale); + virtual void setSNScale(const glm::vec3& scale, bool& success); // get world-frame values for a specific joint virtual const Transform getTransform(int jointIndex, bool& success, int depth = 0) const; virtual glm::vec3 getPosition(int jointIndex, bool& success) const; - virtual glm::vec3 getScale(int jointIndex) const; + virtual glm::vec3 getSNScale(int jointIndex, bool& success) const; // object's parent's frame virtual const Transform getLocalTransform() const; @@ -136,8 +137,8 @@ public: virtual glm::vec3 getLocalAngularVelocity() const; virtual void setLocalAngularVelocity(const glm::vec3& angularVelocity); - virtual glm::vec3 getLocalScale() const; - virtual void setLocalScale(const glm::vec3& scale); + virtual glm::vec3 getLocalSNScale() const; + virtual void setLocalSNScale(const glm::vec3& scale); QList getChildren() const; bool hasChildren() const; @@ -146,9 +147,7 @@ public: // this object's frame virtual const Transform getAbsoluteJointTransformInObjectFrame(int jointIndex) const; -#ifdef SPATIALLY_NESTABLE_SCALE_SUPPORT virtual glm::vec3 getAbsoluteJointScaleInObjectFrame(int index) const { return glm::vec3(1.0f); } -#endif virtual glm::quat getAbsoluteJointRotationInObjectFrame(int index) const { return glm::quat(); } virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const { return glm::vec3(); } virtual bool setAbsoluteJointRotationInObjectFrame(int index, const glm::quat& rotation) { return false; } @@ -193,6 +192,8 @@ public: bool tranlationChangedSince(quint64 time) const { return _translationChanged > time; } bool rotationChangedSince(quint64 time) const { return _rotationChanged > time; } + void dump(const QString& prefix = "") const; + protected: const NestableType _nestableType; // EntityItem or an AvatarData QUuid _id; diff --git a/libraries/shared/src/Transform.cpp b/libraries/shared/src/Transform.cpp index c51b3dae4b..3e29c38add 100644 --- a/libraries/shared/src/Transform.cpp +++ b/libraries/shared/src/Transform.cpp @@ -150,3 +150,10 @@ QJsonObject Transform::toJson(const Transform& transform) { } return result; } + +QDebug& operator<<(QDebug& debug, const Transform& transform) { + debug << "Transform, trans = (" << transform._translation.x << transform._translation.y << transform._translation.z << "), rot = (" + << transform._rotation.x << transform._rotation.y << transform._rotation.z << transform._rotation.w << "), scale = (" + << transform._scale.x << transform._scale.y << transform._scale.z << ")"; + return debug; +} diff --git a/libraries/shared/src/Transform.h b/libraries/shared/src/Transform.h index 38d47695f7..316fcb2f04 100644 --- a/libraries/shared/src/Transform.h +++ b/libraries/shared/src/Transform.h @@ -38,6 +38,7 @@ inline bool isValidScale(float scale) { class Transform { public: + friend QDebug& operator<<(QDebug& debug, const Transform& transform); using Pointer = std::shared_ptr; typedef glm::mat4 Mat4; typedef glm::mat3 Mat3; @@ -170,7 +171,6 @@ protected: }; typedef std::bitset Flags; - // TRS Quat _rotation; Vec3 _scale; @@ -202,6 +202,8 @@ protected: Mat4& getCachedMatrix(Mat4& result) const; }; +QDebug& operator<<(QDebug& debug, const Transform& transform); + inline Transform& Transform::setIdentity() { _translation = Vec3(0.0f); _rotation = Quat(1.0f, 0.0f, 0.0f, 0.0f);