From 852edec9e76d6dfe04965f9c3a5e9c1cc59a10c4 Mon Sep 17 00:00:00 2001 From: HifiExperiments Date: Thu, 18 Feb 2021 22:15:12 -0800 Subject: [PATCH] entities with billboardMode != none use local rotation so parent rotation doesn't affect them --- .../src/RenderableEntityItem.cpp | 17 +++++++++++------ .../src/RenderableEntityItem.h | 11 ++++++----- .../src/RenderableModelEntityItem.cpp | 5 +++-- .../src/RenderablePolyLineEntityItem.cpp | 6 +++--- .../src/RenderablePolyLineEntityItem.h | 2 +- .../src/RenderablePolyVoxEntityItem.cpp | 5 +++-- .../src/RenderableShapeEntityItem.cpp | 7 ++----- .../src/RenderableShapeEntityItem.h | 4 ---- .../src/RenderableTextEntityItem.cpp | 12 ++++++------ libraries/entities/src/EntityItem.cpp | 13 +++++++++++++ libraries/entities/src/EntityItem.h | 1 + libraries/entities/src/EntityTreeElement.cpp | 10 ++++++---- libraries/entities/src/GizmoEntityItem.cpp | 10 ++++++---- libraries/entities/src/ModelEntityItem.cpp | 13 +++++++++++++ libraries/entities/src/ModelEntityItem.h | 1 + libraries/entities/src/PolyVoxEntityItem.cpp | 7 ++++--- libraries/entities/src/ShapeEntityItem.cpp | 10 ++++++---- libraries/render-utils/src/Model.cpp | 3 ++- libraries/shared/src/SpatiallyNestable.cpp | 11 +++++++++++ libraries/shared/src/SpatiallyNestable.h | 1 + 20 files changed, 99 insertions(+), 50 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableEntityItem.cpp b/libraries/entities-renderer/src/RenderableEntityItem.cpp index b2670e3bcee..3e13b301df2 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableEntityItem.cpp @@ -368,6 +368,11 @@ bool EntityRenderer::needsRenderUpdate() const { return needsRenderUpdateFromEntity(_entity); } +Transform EntityRenderer::getTransformToCenterWithMaybeOnlyLocalRotation(const EntityItemPointer& entity, bool& success) const { + return entity->getBillboardMode() == BillboardMode::NONE ? entity->getTransformToCenter(success) : + entity->getTransformToCenterWithOnlyLocalRotation(success); +} + // Returns true if the item in question needs to have updateInScene called because of changes in the entity bool EntityRenderer::needsRenderUpdateFromEntity(const EntityItemPointer& entity) const { if (entity->needsRenderUpdate()) { @@ -379,12 +384,12 @@ bool EntityRenderer::needsRenderUpdateFromEntity(const EntityItemPointer& entity } bool success = false; - auto bound = _entity->getAABox(success); + auto bound = entity->getAABox(success); if (success && _bound != bound) { return true; } - auto newModelTransform = _entity->getTransformToCenter(success); + auto newModelTransform = getTransformToCenterWithMaybeOnlyLocalRotation(entity, success); // FIXME can we use a stale model transform here? if (success && newModelTransform != _modelTransform) { return true; @@ -401,15 +406,15 @@ bool EntityRenderer::needsRenderUpdateFromEntity(const EntityItemPointer& entity return false; } -void EntityRenderer::updateModelTransformAndBound() { +void EntityRenderer::updateModelTransformAndBound(const EntityItemPointer& entity) { bool success = false; - auto newModelTransform = _entity->getTransformToCenter(success); + auto newModelTransform = getTransformToCenterWithMaybeOnlyLocalRotation(entity, success); if (success) { _modelTransform = newModelTransform; } success = false; - auto bound = _entity->getAABox(success); + auto bound = entity->getAABox(success); if (success) { _bound = bound; } @@ -429,7 +434,7 @@ void EntityRenderer::doRenderUpdateSynchronous(const ScenePointer& scene, Transa _prevIsTransparent = transparent; - updateModelTransformAndBound(); + updateModelTransformAndBound(entity); _moving = entity->isMovingRelativeToParent(); _visible = entity->getVisible(); diff --git a/libraries/entities-renderer/src/RenderableEntityItem.h b/libraries/entities-renderer/src/RenderableEntityItem.h index 7f0e1e16ee2..9392d61e757 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.h +++ b/libraries/entities-renderer/src/RenderableEntityItem.h @@ -101,7 +101,7 @@ class EntityRenderer : public QObject, public std::enable_shared_from_this std::shared_ptr asTypedEntity() { return std::static_pointer_cast(_entity); } static void makeStatusGetters(const EntityItemPointer& entity, Item::Status::Getters& statusGetters); const Transform& getModelTransform() const; + Transform getTransformToCenterWithMaybeOnlyLocalRotation(const EntityItemPointer& entity, bool& success) const; + Item::Bound _bound; SharedSoundPointer _collisionSound; QUuid _changeHandlerId; @@ -154,6 +152,9 @@ class EntityRenderer : public QObject, public std::enable_shared_from_this diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 4d3a79c9afe..3c245e5d4ff 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -115,11 +115,12 @@ bool RenderableModelEntityItem::needsUpdateModelBounds() const { } bool success; - auto transform = getTransform(success); + auto transform = getBillboardMode() == BillboardMode::NONE ? getTransform(success) : getTransformWithOnlyLocalRotation(success); if (success) { if (model->getTranslation() != transform.getTranslation()) { return true; } + if (model->getRotation() != transform.getRotation()) { return true; } @@ -171,7 +172,7 @@ void RenderableModelEntityItem::updateModelBounds() { } bool success; - auto transform = getTransform(success); + auto transform = getBillboardMode() == BillboardMode::NONE ? getTransform(success) : getTransformWithOnlyLocalRotation(success); if (success && (model->getTranslation() != transform.getTranslation() || model->getRotation() != transform.getRotation())) { model->setTransformNoUpdateRenderItems(transform); diff --git a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp index 65e9f57b027..e4bb6952a77 100644 --- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp @@ -41,13 +41,13 @@ PolyLineEntityRenderer::PolyLineEntityRenderer(const EntityItemPointer& entity) } } -void PolyLineEntityRenderer::updateModelTransformAndBound() { +void PolyLineEntityRenderer::updateModelTransformAndBound(const EntityItemPointer& entity) { bool success = false; - auto newModelTransform = _entity->getTransformToCenter(success); + auto newModelTransform = getTransformToCenterWithMaybeOnlyLocalRotation(entity, success); if (success) { _modelTransform = newModelTransform; - auto lineEntity = std::static_pointer_cast(_entity); + auto lineEntity = std::static_pointer_cast(entity); AABox bound; lineEntity->computeTightLocalBoundingBox(bound); bound.transform(newModelTransform); diff --git a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h index c4fbb9a7762..6e5068c24f3 100644 --- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h +++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h @@ -25,7 +25,7 @@ class PolyLineEntityRenderer : public TypedEntityRenderer { public: PolyLineEntityRenderer(const EntityItemPointer& entity); - void updateModelTransformAndBound() override; + void updateModelTransformAndBound(const EntityItemPointer& entity) override; virtual bool isTransparent() const override; diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index 859accf01ae..5c8374b9379 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -1785,8 +1785,9 @@ void PolyVoxEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& s void PolyVoxEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) { _lastVoxelToLocalMatrix = entity->voxelToLocalMatrix(); - _position = entity->getWorldPosition(); - _orientation = entity->getWorldOrientation(); + bool success; + _position = entity->getCenterPosition(success); + _orientation = entity->getBillboardMode() == BillboardMode::NONE ? entity->getWorldOrientation() : entity->getLocalOrientation(); _lastVoxelVolumeSize = entity->getVoxelVolumeSize(); _params->setSubData(0, vec4(_lastVoxelVolumeSize, 0.0)); graphics::MeshPointer newMesh; diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp index 674d7c297da..35739c24305 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp @@ -56,15 +56,12 @@ void ShapeEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this, entity] { withWriteLock([&] { _shape = entity->getShape(); - _position = entity->getWorldPosition(); - _dimensions = entity->getUnscaledDimensions(); // get unscaled to avoid scaling twice - _orientation = entity->getWorldOrientation(); _renderTransform = getModelTransform(); // contains parent scale, if this entity scales with its parent if (_shape == entity::Sphere) { _renderTransform.postScale(SPHERE_ENTITY_SCALE); } - _renderTransform.postScale(_dimensions); + _renderTransform.postScale(entity->getUnscaledDimensions()); }); }); } @@ -248,7 +245,7 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) { outColor = procedural->getColor(outColor); outColor.a *= procedural->isFading() ? Interpolate::calculateFadeRatio(procedural->getFadeStartTime()) : 1.0f; withReadLock([&] { - procedural->prepare(batch, _position, _dimensions, _orientation, _created, ProceduralProgramKey(outColor.a < 1.0f)); + procedural->prepare(batch, transform.getTranslation(), transform.getScale(), transform.getRotation(), _created, ProceduralProgramKey(outColor.a < 1.0f)); }); if (render::ShapeKey(args->_globalShapeKey).isWireframe() || _primitiveMode == PrimitiveMode::LINES) { diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.h b/libraries/entities-renderer/src/RenderableShapeEntityItem.h index fe62ad48b9d..403d3893781 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.h +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.h @@ -45,10 +45,6 @@ class ShapeEntityRenderer : public TypedEntityRenderer { std::shared_ptr _material { std::make_shared() }; glm::vec3 _color { NAN }; float _alpha { NAN }; - - glm::vec3 _position; - glm::vec3 _dimensions; - glm::quat _orientation; }; } } diff --git a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp index 16d9afb913b..3d658d85117 100644 --- a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp @@ -292,12 +292,12 @@ void entities::TextPayload::render(RenderArgs* args) { } auto textRenderable = std::static_pointer_cast(renderable); - Transform modelTransform; + Transform transform; glm::vec3 dimensions; glm::vec4 textColor; textRenderable->withReadLock([&] { - modelTransform = textRenderable->_renderTransform; + transform = textRenderable->_renderTransform; dimensions = textRenderable->_dimensions; float fadeRatio = textRenderable->_isFading ? Interpolate::calculateFadeRatio(textRenderable->_fadeStartTime) : 1.0f; @@ -313,13 +313,13 @@ void entities::TextPayload::render(RenderArgs* args) { return; } - modelTransform.setRotation(BillboardModeHelpers::getBillboardRotation(modelTransform.getTranslation(), modelTransform.getRotation(), textRenderable->_billboardMode, + transform.setRotation(BillboardModeHelpers::getBillboardRotation(transform.getTranslation(), transform.getRotation(), textRenderable->_billboardMode, args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? BillboardModeHelpers::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition())); float scale = textRenderable->_lineHeight / textRenderer->getFontSize(); - modelTransform.postTranslate(glm::vec3(-0.5, 0.5, 1.0f + EPSILON / dimensions.z)); - modelTransform.setScale(scale); - batch.setModelTransform(modelTransform); + transform.postTranslate(glm::vec3(-0.5, 0.5, 1.0f + EPSILON / dimensions.z)); + transform.setScale(scale); + batch.setModelTransform(transform); glm::vec2 bounds = glm::vec2(dimensions.x - (textRenderable->_leftMargin + textRenderable->_rightMargin), dimensions.y - (textRenderable->_topMargin + textRenderable->_bottomMargin)); textRenderer->draw(batch, textRenderable->_leftMargin / scale, -textRenderable->_topMargin / scale, bounds / scale, scale, diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 9d3947ab563..6e761698c91 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -1620,6 +1620,19 @@ const Transform EntityItem::getTransformToCenter(bool& success) const { return result; } +const Transform EntityItem::getTransformToCenterWithOnlyLocalRotation(bool& success) const { + Transform result = getTransformWithOnlyLocalRotation(success); + glm::vec3 pivot = getPivot(); + if (pivot != ENTITY_ITEM_ZERO_VEC3) { + result.postTranslate(pivot); + } + glm::vec3 registrationPoint = getRegistrationPoint(); + if (registrationPoint != ENTITY_ITEM_HALF_VEC3) { // If it is not already centered, translate to center + result.postTranslate((ENTITY_ITEM_HALF_VEC3 - registrationPoint) * getScaledDimensions()); // Position to center + } + return result; +} + /// The maximum bounding cube for the entity, independent of it's rotation. /// This accounts for the registration point (upon which rotation occurs around). /// diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 152e0039131..b08817044a6 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -190,6 +190,7 @@ class EntityItem : public QObject, public SpatiallyNestable, public ReadWriteLoc void setCenterPosition(const glm::vec3& position); const Transform getTransformToCenter(bool& success) const; + const Transform getTransformToCenterWithOnlyLocalRotation(bool& success) const; void requiresRecalcBoxes(); diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index 90c185be8b6..f330058a787 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -218,8 +218,9 @@ EntityItemID EntityTreeElement::evalDetailedRayIntersection(const glm::vec3& ori // extents is the entity relative, scaled, centered extents of the entity glm::vec3 position = entity->getWorldPosition(); glm::mat4 translation = glm::translate(position); - glm::quat orientation = entity->getWorldOrientation(); - glm::mat4 rotation = glm::mat4_cast(BillboardModeHelpers::getBillboardRotation(position, orientation, entity->getBillboardMode(), + BillboardMode billboardMode = entity->getBillboardMode(); + glm::quat orientation = billboardMode == BillboardMode::NONE ? entity->getWorldOrientation() : entity->getLocalOrientation(); + glm::mat4 rotation = glm::mat4_cast(BillboardModeHelpers::getBillboardRotation(position, orientation, billboardMode, viewFrustumPos, entity->getRotateForPicking())); glm::mat4 entityToWorldMatrix = translation * rotation; glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix); @@ -368,8 +369,9 @@ EntityItemID EntityTreeElement::evalDetailedParabolaIntersection(const glm::vec3 // extents is the entity relative, scaled, centered extents of the entity glm::vec3 position = entity->getWorldPosition(); glm::mat4 translation = glm::translate(position); - glm::quat orientation = entity->getWorldOrientation(); - glm::mat4 rotation = glm::mat4_cast(BillboardModeHelpers::getBillboardRotation(position, orientation, entity->getBillboardMode(), + BillboardMode billboardMode = entity->getBillboardMode(); + glm::quat orientation = billboardMode == BillboardMode::NONE ? entity->getWorldOrientation() : entity->getLocalOrientation(); + glm::mat4 rotation = glm::mat4_cast(BillboardModeHelpers::getBillboardRotation(position, orientation, billboardMode, viewFrustumPos, entity->getRotateForPicking())); glm::mat4 entityToWorldMatrix = translation * rotation; glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix); diff --git a/libraries/entities/src/GizmoEntityItem.cpp b/libraries/entities/src/GizmoEntityItem.cpp index 694371d739d..b6c5713c1ac 100644 --- a/libraries/entities/src/GizmoEntityItem.cpp +++ b/libraries/entities/src/GizmoEntityItem.cpp @@ -108,10 +108,11 @@ bool GizmoEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const QVariantMap& extraInfo, bool precisionPicking) const { glm::vec3 dimensions = getScaledDimensions(); glm::vec2 xyDimensions(dimensions.x, dimensions.z); - glm::quat rotation = getWorldOrientation(); + BillboardMode billboardMode = getBillboardMode(); + glm::quat rotation = billboardMode == BillboardMode::NONE ? getWorldOrientation() : getLocalOrientation(); rotation *= glm::angleAxis(-(float)M_PI_2, Vectors::RIGHT); glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); - rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, getBillboardMode(), viewFrustumPos); + rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, billboardMode, viewFrustumPos); if (findRayRectangleIntersection(origin, direction, rotation, position, xyDimensions, distance)) { glm::vec3 hitPosition = origin + (distance * direction); @@ -143,10 +144,11 @@ bool GizmoEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin, //// Scale the dimensions by the diameter glm::vec3 dimensions = getScaledDimensions(); glm::vec2 xyDimensions(dimensions.x, dimensions.z); - glm::quat rotation = getWorldOrientation(); + BillboardMode billboardMode = getBillboardMode(); + glm::quat rotation = billboardMode == BillboardMode::NONE ? getWorldOrientation() : getLocalOrientation(); rotation *= glm::angleAxis(-(float)M_PI_2, Vectors::RIGHT); glm::vec3 position = getWorldPosition(); - rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, getBillboardMode(), viewFrustumPos); + rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, billboardMode, viewFrustumPos); glm::quat inverseRot = glm::inverse(rotation); glm::vec3 localOrigin = inverseRot * (origin - position); diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index 61362896eed..321e92b9f0d 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -330,6 +330,19 @@ const Transform ModelEntityItem::getTransform(bool& success, int depth) const { return worldTransform; } + +const Transform ModelEntityItem::getTransformWithOnlyLocalRotation(bool& success, int depth) const { + const Transform parentTransform = getParentTransform(success, depth); + Transform localTransform = getLocalTransform(); + localTransform.postScale(getModelScale()); + + Transform worldTransform; + Transform::mult(worldTransform, parentTransform, localTransform); + worldTransform.setRotation(localTransform.getRotation()); + + return worldTransform; +} + void ModelEntityItem::setCompoundShapeURL(const QString& url) { withWriteLock([&] { if (_compoundShapeURL.get() != url) { diff --git a/libraries/entities/src/ModelEntityItem.h b/libraries/entities/src/ModelEntityItem.h index 6e92b225a12..a00327251c7 100644 --- a/libraries/entities/src/ModelEntityItem.h +++ b/libraries/entities/src/ModelEntityItem.h @@ -71,6 +71,7 @@ class ModelEntityItem : public EntityItem { virtual void setScaledDimensions(const glm::vec3& value) override; virtual const Transform getTransform(bool& success, int depth = 0) const override; + virtual const Transform getTransformWithOnlyLocalRotation(bool& success, int depth = 0) const override; virtual const Transform getTransform() const override; static const QString DEFAULT_COMPOUND_SHAPE_URL; diff --git a/libraries/entities/src/PolyVoxEntityItem.cpp b/libraries/entities/src/PolyVoxEntityItem.cpp index 5ed9f69b5af..49dc0d7c905 100644 --- a/libraries/entities/src/PolyVoxEntityItem.cpp +++ b/libraries/entities/src/PolyVoxEntityItem.cpp @@ -378,14 +378,15 @@ glm::mat4 PolyVoxEntityItem::localToVoxelMatrix() const { } glm::mat4 PolyVoxEntityItem::voxelToWorldMatrix(bool includeBillboard) const { - glm::quat orientation = getWorldOrientation(); glm::vec3 position = getWorldPosition(); glm::mat4 translation = glm::translate(position); glm::mat4 rotation; if (includeBillboard) { - rotation = glm::mat4_cast(BillboardModeHelpers::getBillboardRotation(position, orientation, getBillboardMode(), BillboardModeHelpers::getPrimaryViewFrustumPosition())); + BillboardMode billboardMode = getBillboardMode(); + glm::quat orientation = billboardMode == BillboardMode::NONE ? getWorldOrientation() : getLocalOrientation(); + rotation = glm::mat4_cast(BillboardModeHelpers::getBillboardRotation(position, orientation, billboardMode, BillboardModeHelpers::getPrimaryViewFrustumPosition())); } else { - rotation = glm::mat4_cast(orientation); + rotation = glm::mat4_cast(getWorldOrientation()); } return translation * rotation * voxelToLocalMatrix(); } diff --git a/libraries/entities/src/ShapeEntityItem.cpp b/libraries/entities/src/ShapeEntityItem.cpp index 7858e62f7d3..4349eefd2d9 100644 --- a/libraries/entities/src/ShapeEntityItem.cpp +++ b/libraries/entities/src/ShapeEntityItem.cpp @@ -277,9 +277,10 @@ bool ShapeEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const float& distance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const { glm::vec3 dimensions = getScaledDimensions(); - glm::quat rotation = getWorldOrientation(); + BillboardMode billboardMode = getBillboardMode(); + glm::quat rotation = billboardMode == BillboardMode::NONE ? getWorldOrientation() : getLocalOrientation(); glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); - rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, getBillboardMode(), viewFrustumPos); + rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, billboardMode, viewFrustumPos); // determine the ray in the frame of the entity transformed from a unit sphere glm::mat4 entityToWorldMatrix = glm::translate(position) * glm::mat4_cast(rotation) * glm::scale(dimensions); @@ -309,9 +310,10 @@ bool ShapeEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const { glm::vec3 dimensions = getScaledDimensions(); - glm::quat rotation = getWorldOrientation(); + BillboardMode billboardMode = getBillboardMode(); + glm::quat rotation = billboardMode == BillboardMode::NONE ? getWorldOrientation() : getLocalOrientation(); glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); - rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, getBillboardMode(), viewFrustumPos); + rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, billboardMode, viewFrustumPos); // determine the parabola in the frame of the entity transformed from a unit sphere glm::mat4 entityToWorldMatrix = glm::translate(position) * glm::mat4_cast(rotation) * glm::scale(dimensions); diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 1c9fdc50d6d..5d0273c7bf1 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -114,7 +114,8 @@ Transform Model::getTransform() const { return transform; } else if (_spatiallyNestableOverride) { bool success; - Transform transform = _spatiallyNestableOverride->getTransform(success); + Transform transform = _billboardMode == BillboardMode::NONE ? _spatiallyNestableOverride->getTransform(success) : + _spatiallyNestableOverride->getTransformWithOnlyLocalRotation(success); if (success) { transform.setScale(getScale()); return transform; diff --git a/libraries/shared/src/SpatiallyNestable.cpp b/libraries/shared/src/SpatiallyNestable.cpp index c1c1fd38d9d..670b03611b0 100644 --- a/libraries/shared/src/SpatiallyNestable.cpp +++ b/libraries/shared/src/SpatiallyNestable.cpp @@ -754,6 +754,17 @@ const Transform SpatiallyNestable::getTransform(bool& success, int depth) const return result; } +const Transform SpatiallyNestable::getTransformWithOnlyLocalRotation(bool& success, int depth) const { + Transform result; + // return a world-space transform for this object's location + Transform parentTransform = getParentTransform(success, depth); + _transformLock.withReadLock([&] { + Transform::mult(result, parentTransform, _transform); + result.setRotation(_transform.getRotation()); + }); + return result; +} + const Transform SpatiallyNestable::getTransform() const { bool success; Transform result = getTransform(success); diff --git a/libraries/shared/src/SpatiallyNestable.h b/libraries/shared/src/SpatiallyNestable.h index 01e3b045add..29f23afdfbc 100644 --- a/libraries/shared/src/SpatiallyNestable.h +++ b/libraries/shared/src/SpatiallyNestable.h @@ -82,6 +82,7 @@ class SpatiallyNestable : public std::enable_shared_from_this // world frame virtual const Transform getTransform(bool& success, int depth = 0) const; + virtual const Transform getTransformWithOnlyLocalRotation(bool& success, int depth = 0) const; virtual const Transform getTransform() const; virtual void setTransform(const Transform& transform, bool& success); virtual bool setTransform(const Transform& transform);