From 7069e48073de69b5836f617cc77c693932a1a369 Mon Sep 17 00:00:00 2001 From: HifiExperiments Date: Wed, 16 Dec 2020 21:01:56 -0800 Subject: [PATCH 01/33] working on pivot --- interface/src/ui/Stats.h | 8 +-- .../src/avatars-renderer/SkeletonModel.cpp | 6 +- .../src/EntityTreeRenderer.h | 8 +-- .../src/RenderableModelEntityItem.cpp | 24 ++++++-- .../src/RenderableModelEntityItem.h | 3 +- .../src/RenderablePolyVoxEntityItem.cpp | 6 +- libraries/entities/src/EntityItem.cpp | 54 +++++++++++------- libraries/entities/src/EntityItem.h | 1 + .../entities/src/EntityItemProperties.cpp | 9 +++ libraries/entities/src/EntityItemProperties.h | 1 + libraries/entities/src/EntityPropertyFlags.h | 19 ++++--- libraries/entities/src/EntityTreeElement.cpp | 57 +++++++++---------- libraries/entities/src/ModelEntityItem.cpp | 19 +++++++ libraries/entities/src/ModelEntityItem.h | 4 ++ libraries/render-utils/src/Model.cpp | 42 ++++++++------ libraries/render-utils/src/Model.h | 7 ++- 16 files changed, 167 insertions(+), 101 deletions(-) diff --git a/interface/src/ui/Stats.h b/interface/src/ui/Stats.h index 27ab375a42..ebd65de612 100644 --- a/interface/src/ui/Stats.h +++ b/interface/src/ui/Stats.h @@ -248,9 +248,9 @@ private: \ * Read-only. * @property {string} lodStatus - Description of the current LOD. * Read-only. - * @property {string} numEntityUpdates - The number of entity updates that happened last frame. + * @property {number} numEntityUpdates - The number of entity updates that happened last frame. * Read-only. - * @property {string} numNeededEntityUpdates - The total number of entity updates scheduled for last frame. + * @property {number} numNeededEntityUpdates - The total number of entity updates scheduled for last frame. * Read-only. * @property {string} timingStats - Details of the average time (ms) spent in and number of calls made to different parts of * the code. Provided only if timingExpanded is true. Only the top 10 items are provided if @@ -547,8 +547,8 @@ class Stats : public QQuickItem { STATS_PROPERTY(int, lodAngle, 0) STATS_PROPERTY(int, lodTargetFramerate, 0) STATS_PROPERTY(QString, lodStatus, QString()) - STATS_PROPERTY(int, numEntityUpdates, 0) - STATS_PROPERTY(int, numNeededEntityUpdates, 0) + STATS_PROPERTY(quint64, numEntityUpdates, 0) + STATS_PROPERTY(quint64, numNeededEntityUpdates, 0) STATS_PROPERTY(QString, timingStats, QString()) STATS_PROPERTY(QString, gameUpdateStats, QString()) STATS_PROPERTY(int, serverElements, 0) diff --git a/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.cpp b/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.cpp index 4950b86f75..5ac808d3fb 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.cpp @@ -156,17 +156,13 @@ void SkeletonModel::simulate(float deltaTime, bool fullUpdate) { updateAttitude(_owningAvatar->getWorldOrientation()); setBlendshapeCoefficients(_owningAvatar->getHead()->getSummedBlendshapeCoefficients()); + Parent::simulate(deltaTime, fullUpdate); if (fullUpdate) { - - Parent::simulate(deltaTime, fullUpdate); - // let rig compute the model offset glm::vec3 registrationPoint; if (_rig.getModelRegistrationPoint(registrationPoint)) { setOffset(registrationPoint); } - } else { - Parent::simulate(deltaTime, fullUpdate); } // FIXME: This texture loading logic should probably live in Avatar, to mirror RenderableModelEntityItem, diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.h b/libraries/entities-renderer/src/EntityTreeRenderer.h index f7623aad10..009e5f6c4f 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.h +++ b/libraries/entities-renderer/src/EntityTreeRenderer.h @@ -136,8 +136,8 @@ public: static bool addMaterialToAvatar(const QUuid& avatarID, graphics::MaterialLayer material, const std::string& parentMaterialName); static bool removeMaterialFromAvatar(const QUuid& avatarID, graphics::MaterialPointer material, const std::string& parentMaterialName); - int getPrevNumEntityUpdates() const { return _prevNumEntityUpdates; } - int getPrevTotalNeededEntityUpdates() const { return _prevTotalNeededEntityUpdates; } + size_t getPrevNumEntityUpdates() const { return _prevNumEntityUpdates; } + size_t getPrevTotalNeededEntityUpdates() const { return _prevTotalNeededEntityUpdates; } signals: void enterEntity(const EntityItemID& entityItemID); @@ -253,8 +253,8 @@ private: ReadWriteLockable _changedEntitiesGuard; std::unordered_set _changedEntities; - int _prevNumEntityUpdates { 0 }; - int _prevTotalNeededEntityUpdates { 0 }; + size_t _prevNumEntityUpdates { 0 }; + size_t _prevTotalNeededEntityUpdates { 0 }; std::unordered_set _renderablesToUpdate; std::unordered_map _entitiesInScene; diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index d6b7313ae7..940bf55e86 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -149,10 +149,11 @@ void RenderableModelEntityItem::updateModelBounds() { bool overridingModelTransform = model->isOverridingModelTransformAndOffset(); glm::vec3 scaledDimensions = getScaledDimensions(); glm::vec3 registrationPoint = getRegistrationPoint(); + bool needsSimulate = false; if (!overridingModelTransform && (model->getScaleToFitDimensions() != scaledDimensions || model->getRegistrationPoint() != registrationPoint || - !model->getIsScaledToFit() || _needsToRescaleModel)) { + !model->getIsScaledToFit() || _useOriginalPivot == model->getSnapModelToRegistrationPoint())) { // The machinery for updateModelBounds will give existing models the opportunity to fix their // translation/rotation/scale/registration. The first two are straightforward, but the latter two // have guards to make sure they don't happen after they've already been set. Here we reset those guards. @@ -162,9 +163,10 @@ void RenderableModelEntityItem::updateModelBounds() { // now recalculate the bounds and registration model->setScaleToFit(true, scaledDimensions); - model->setSnapModelToRegistrationPoint(true, registrationPoint); + model->setSnapModelToRegistrationPoint(!_useOriginalPivot, registrationPoint); updateRenderItems = true; - model->scaleToFit(); + needsSimulate = true; + locationChanged(); _needsToRescaleModel = false; } @@ -176,7 +178,7 @@ void RenderableModelEntityItem::updateModelBounds() { updateRenderItems = true; } - if (_needsInitialSimulation || _needsJointSimulation || isAnimatingSomething()) { + if (_needsInitialSimulation || _needsJointSimulation || needsSimulate || isAnimatingSomething()) { // NOTE: on isAnimatingSomething() we need to call Model::simulate() which calls Rig::updateRig() // TODO: there is opportunity to further optimize the isAnimatingSomething() case. model->simulate(0.0f); @@ -222,6 +224,16 @@ EntityItemProperties RenderableModelEntityItem::getProperties(const EntityProper return properties; } +glm::vec3 RenderableModelEntityItem::getPivot() const { + auto model = getModel(); + auto raycastOffset = EntityItem::getPivot(); + if (!model || !model->isLoaded() || !_useOriginalPivot) { + return raycastOffset; + } + + return raycastOffset + model->getOriginalOffset(); +} + bool RenderableModelEntityItem::supportsDetailedIntersection() const { return true; } @@ -452,7 +464,7 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) { pointCollection[i][j] = scaleToFit * (pointCollection[i][j] + model->getOffset()) - registrationOffset; } } - shapeInfo.setParams(type, 0.5f * extents, getCompoundShapeURL()); + shapeInfo.setParams(type, 0.5f * extents, getCompoundShapeURL() + model->getSnapModelToRegistrationPoint()); adjustShapeInfoByRegistration(shapeInfo); } else if (type >= SHAPE_TYPE_SIMPLE_HULL && type <= SHAPE_TYPE_STATIC_MESH) { updateModelBounds(); @@ -685,7 +697,7 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) { } } - shapeInfo.setParams(type, 0.5f * extents.size(), getModelURL()); + shapeInfo.setParams(type, 0.5f * extents.size(), getModelURL() + model->getSnapModelToRegistrationPoint()); adjustShapeInfoByRegistration(shapeInfo); } else { EntityItem::computeShapeInfo(shapeInfo); diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index 4501f6d88c..1ef11b6906 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -42,7 +42,7 @@ protected: void setModel(const ModelPointer& model); ModelPointer getModel() const; - bool _needsInitialSimulation{ true }; + bool _needsInitialSimulation { true }; private: ModelPointer _model; }; @@ -63,6 +63,7 @@ public: virtual EntityItemProperties getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const override; void updateModelBounds(); + glm::vec3 getPivot() const override; virtual bool supportsDetailedIntersection() const override; virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, OctreeElementPointer& element, float& distance, diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index f0a6684654..d779409e9c 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -723,8 +723,10 @@ ShapeType RenderablePolyVoxEntityItem::getShapeType() const { } void RenderablePolyVoxEntityItem::setRegistrationPoint(const glm::vec3& value) { - if (value != _registrationPoint) { - _shapeReady = false; + if (value != getRegistrationPoint()) { + withWriteLock([&] { + _shapeReady = false; + }); EntityItem::setRegistrationPoint(value); startUpdates(); } diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index d7a5e992e1..48490aeb51 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -1607,8 +1607,13 @@ void EntityItem::recordCreationTime() { const Transform EntityItem::getTransformToCenter(bool& success) const { Transform result = getTransform(success); - if (getRegistrationPoint() != ENTITY_ITEM_HALF_VEC3) { // If it is not already centered, translate to center - result.postTranslate((ENTITY_ITEM_HALF_VEC3 - getRegistrationPoint()) * getScaledDimensions()); // Position to center + 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; } @@ -1624,7 +1629,8 @@ AACube EntityItem::getMaximumAACube(bool& success) const { // we want to compute the furthestExtent that an entity can extend out from its "position" // to do this we compute the max of these two vec3s: registration and 1-registration // and then scale by dimensions - glm::vec3 maxExtents = getScaledDimensions() * glm::max(_registrationPoint, glm::vec3(1.0f) - _registrationPoint); + glm::vec3 offset = getScaledDimensions() * getRegistrationPoint() + getPivot(); + glm::vec3 maxExtents = glm::max(offset, glm::vec3(1.0f) - offset); // there exists a sphere that contains maxExtents for all rotations float radius = glm::length(maxExtents); @@ -1650,9 +1656,12 @@ AACube EntityItem::getMinimumAACube(bool& success) const { if (success) { _recalcMinAACube = false; glm::vec3 dimensions = getScaledDimensions(); - glm::vec3 unrotatedMinRelativeToEntity = - (dimensions * _registrationPoint); - glm::vec3 unrotatedMaxRelativeToEntity = dimensions * (glm::vec3(1.0f, 1.0f, 1.0f) - _registrationPoint); + glm::vec3 registrationPoint = getRegistrationPoint(); + glm::vec3 pivot = getPivot(); + glm::vec3 unrotatedMinRelativeToEntity = -(dimensions * registrationPoint); + glm::vec3 unrotatedMaxRelativeToEntity = dimensions * (ENTITY_ITEM_ONE_VEC3 - registrationPoint); Extents extents = { unrotatedMinRelativeToEntity, unrotatedMaxRelativeToEntity }; + extents.shiftBy(pivot); extents.rotate(getWorldOrientation()); // shift the extents to be relative to the position/registration point @@ -1680,9 +1689,12 @@ AABox EntityItem::getAABox(bool& success) const { if (success) { _recalcAABox = false; glm::vec3 dimensions = getScaledDimensions(); - glm::vec3 unrotatedMinRelativeToEntity = - (dimensions * _registrationPoint); - glm::vec3 unrotatedMaxRelativeToEntity = dimensions * (glm::vec3(1.0f, 1.0f, 1.0f) - _registrationPoint); + glm::vec3 registrationPoint = getRegistrationPoint(); + glm::vec3 pivot = getPivot(); + glm::vec3 unrotatedMinRelativeToEntity = -(dimensions * registrationPoint); + glm::vec3 unrotatedMaxRelativeToEntity = dimensions * (ENTITY_ITEM_ONE_VEC3 - registrationPoint); Extents extents = { unrotatedMinRelativeToEntity, unrotatedMaxRelativeToEntity }; + extents.shiftBy(pivot); extents.rotate(getWorldOrientation()); // shift the extents to be relative to the position/registration point @@ -1723,11 +1735,10 @@ float EntityItem::getRadius() const { } void EntityItem::adjustShapeInfoByRegistration(ShapeInfo& info) const { - if (_registrationPoint != ENTITY_ITEM_DEFAULT_REGISTRATION_POINT) { - glm::mat4 scale = glm::scale(getScaledDimensions()); - glm::mat4 registration = scale * glm::translate(ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint()); - glm::vec3 regTransVec = glm::vec3(registration[3]); // extract position component from matrix - info.setOffset(regTransVec); + glm::vec3 registrationPoint = getRegistrationPoint(); + if (registrationPoint != ENTITY_ITEM_DEFAULT_REGISTRATION_POINT) { + glm::vec3 registration = (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - registrationPoint) * getScaledDimensions(); + info.setOffset(registration); } } @@ -1739,7 +1750,7 @@ bool EntityItem::contains(const glm::vec3& point) const { // anything with shapeType == SPHERE must collide as a bounding sphere in the world-frame regardless of dimensions // therefore we must do math using an unscaled localPoint relative to sphere center glm::vec3 dimensions = getScaledDimensions(); - glm::vec3 localPoint = point - (getWorldPosition() + getWorldOrientation() * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint()))); + glm::vec3 localPoint = point - (getWorldPosition() + getWorldOrientation() * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint()) + getPivot())); const float HALF_SQUARED = 0.25f; return glm::length2(localPoint) < HALF_SQUARED * glm::length2(dimensions); } @@ -1797,11 +1808,16 @@ float EntityItem::getVolumeEstimate() const { } void EntityItem::setRegistrationPoint(const glm::vec3& value) { - if (value != _registrationPoint) { - withWriteLock([&] { + bool changed = false; + withWriteLock([&] { + if (value != _registrationPoint) { _registrationPoint = glm::clamp(value, glm::vec3(ENTITY_ITEM_MIN_REGISTRATION_POINT), glm::vec3(ENTITY_ITEM_MAX_REGISTRATION_POINT)); - }); + changed = true; + } + }); + + if (changed) { dimensionsChanged(); // Registration Point affects the bounding box markDirtyFlags(Simulation::DIRTY_SHAPE); } @@ -2892,11 +2908,9 @@ QString EntityItem::getCollisionSoundURL() const { } glm::vec3 EntityItem::getRegistrationPoint() const { - glm::vec3 result; - withReadLock([&] { - result = _registrationPoint; + return resultWithReadLock([&] { + return _registrationPoint; }); - return result; } float EntityItem::getAngularDamping() const { diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 2a6952fc0d..e12c2d864b 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -204,6 +204,7 @@ public: virtual glm::vec3 getScaledDimensions() const; virtual void setScaledDimensions(const glm::vec3& value); virtual glm::vec3 getRaycastDimensions() const { return getScaledDimensions(); } + virtual glm::vec3 getPivot() const { return glm::vec3(0.0f); } // pivot offset for positioning, mainly for model entities glm::vec3 getUnscaledDimensions() const; virtual void setUnscaledDimensions(const glm::vec3& value); diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index ff55137a03..06e981238d 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -538,6 +538,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_RELAY_PARENT_JOINTS, relayParentJoints); CHECK_PROPERTY_CHANGE(PROP_GROUP_CULLED, groupCulled); CHECK_PROPERTY_CHANGE(PROP_BLENDSHAPE_COEFFICIENTS, blendshapeCoefficients); + CHECK_PROPERTY_CHANGE(PROP_USE_ORIGINAL_PIVOT, useOriginalPivot); changedProperties += _animation.getChangedProperties(); // Light @@ -1733,6 +1734,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_RELAY_PARENT_JOINTS, relayParentJoints); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_GROUP_CULLED, groupCulled); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_BLENDSHAPE_COEFFICIENTS, blendshapeCoefficients); + COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_USE_ORIGINAL_PIVOT, useOriginalPivot); if (!psuedoPropertyFlagsButDesiredEmpty) { _animation.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties); } @@ -2142,6 +2144,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool COPY_PROPERTY_FROM_QSCRIPTVALUE(relayParentJoints, bool, setRelayParentJoints); COPY_PROPERTY_FROM_QSCRIPTVALUE(groupCulled, bool, setGroupCulled); COPY_PROPERTY_FROM_QSCRIPTVALUE(blendshapeCoefficients, QString, setBlendshapeCoefficients); + COPY_PROPERTY_FROM_QSCRIPTVALUE(useOriginalPivot, bool, setUseOriginalPivot); _animation.copyFromScriptValue(object, _defaultSettings); // Light @@ -2434,6 +2437,7 @@ void EntityItemProperties::merge(const EntityItemProperties& other) { COPY_PROPERTY_IF_CHANGED(relayParentJoints); COPY_PROPERTY_IF_CHANGED(groupCulled); COPY_PROPERTY_IF_CHANGED(blendshapeCoefficients); + COPY_PROPERTY_IF_CHANGED(useOriginalPivot); _animation.merge(other._animation); // Light @@ -2790,6 +2794,7 @@ bool EntityItemProperties::getPropertyInfo(const QString& propertyName, EntityPr ADD_PROPERTY_TO_MAP(PROP_RELAY_PARENT_JOINTS, RelayParentJoints, relayParentJoints, bool); ADD_PROPERTY_TO_MAP(PROP_GROUP_CULLED, GroupCulled, groupCulled, bool); ADD_PROPERTY_TO_MAP(PROP_BLENDSHAPE_COEFFICIENTS, BlendshapeCoefficients, blendshapeCoefficients, QString); + ADD_PROPERTY_TO_MAP(PROP_USE_ORIGINAL_PIVOT, UseOriginalPivot, useOriginalPivot, bool); { // Animation ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_URL, Animation, animation, URL, url); ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_ALLOW_TRANSLATION, Animation, animation, AllowTranslation, allowTranslation); @@ -4129,6 +4134,7 @@ void EntityItemProperties::markAllChanged() { _relayParentJointsChanged = true; _groupCulledChanged = true; _blendshapeCoefficientsChanged = true; + _useOriginalPivotChanged = true; _animation.markAllChanged(); // Light @@ -4701,6 +4707,9 @@ QList EntityItemProperties::listChangedProperties() { if (blendshapeCoefficientsChanged()) { out += "blendshapeCoefficients"; } + if (useOriginalPivotChanged()) { + out += "useOriginalPivot"; + } getAnimation().listChangedProperties(out); // Light diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index f7fde73430..f056187d4f 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -302,6 +302,7 @@ public: DEFINE_PROPERTY(PROP_RELAY_PARENT_JOINTS, RelayParentJoints, relayParentJoints, bool, ENTITY_ITEM_DEFAULT_RELAY_PARENT_JOINTS); DEFINE_PROPERTY_REF(PROP_GROUP_CULLED, GroupCulled, groupCulled, bool, false); DEFINE_PROPERTY_REF(PROP_BLENDSHAPE_COEFFICIENTS, BlendshapeCoefficients, blendshapeCoefficients, QString, ""); + DEFINE_PROPERTY_REF(PROP_USE_ORIGINAL_PIVOT, UseOriginalPivot, useOriginalPivot, bool, false); DEFINE_PROPERTY_GROUP(Animation, animation, AnimationPropertyGroup); // Light diff --git a/libraries/entities/src/EntityPropertyFlags.h b/libraries/entities/src/EntityPropertyFlags.h index 93bb8a89a7..35c1f9a908 100644 --- a/libraries/entities/src/EntityPropertyFlags.h +++ b/libraries/entities/src/EntityPropertyFlags.h @@ -218,16 +218,17 @@ enum EntityPropertyList { PROP_RELAY_PARENT_JOINTS = PROP_DERIVED_6, PROP_GROUP_CULLED = PROP_DERIVED_7, PROP_BLENDSHAPE_COEFFICIENTS = PROP_DERIVED_8, + PROP_USE_ORIGINAL_PIVOT = PROP_DERIVED_9, // Animation - PROP_ANIMATION_URL = PROP_DERIVED_9, - PROP_ANIMATION_ALLOW_TRANSLATION = PROP_DERIVED_10, - PROP_ANIMATION_FPS = PROP_DERIVED_11, - PROP_ANIMATION_FRAME_INDEX = PROP_DERIVED_12, - PROP_ANIMATION_PLAYING = PROP_DERIVED_13, - PROP_ANIMATION_LOOP = PROP_DERIVED_14, - PROP_ANIMATION_FIRST_FRAME = PROP_DERIVED_15, - PROP_ANIMATION_LAST_FRAME = PROP_DERIVED_16, - PROP_ANIMATION_HOLD = PROP_DERIVED_17, + PROP_ANIMATION_URL = PROP_DERIVED_10, + PROP_ANIMATION_ALLOW_TRANSLATION = PROP_DERIVED_11, + PROP_ANIMATION_FPS = PROP_DERIVED_12, + PROP_ANIMATION_FRAME_INDEX = PROP_DERIVED_13, + PROP_ANIMATION_PLAYING = PROP_DERIVED_14, + PROP_ANIMATION_LOOP = PROP_DERIVED_15, + PROP_ANIMATION_FIRST_FRAME = PROP_DERIVED_16, + PROP_ANIMATION_LAST_FRAME = PROP_DERIVED_17, + PROP_ANIMATION_HOLD = PROP_DERIVED_18, // Light PROP_IS_SPOTLIGHT = PROP_DERIVED_0, diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index 9af0bbfdb6..16b6ccac9b 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -205,10 +205,7 @@ EntityItemID EntityTreeElement::evalDetailedRayIntersection(const glm::vec3& ori // (this is faster and more likely to cull results than the filter check below so we do it first) bool success; AABox entityBox = entity->getAABox(success); - if (!success) { - return; - } - if (!entityBox.rayHitsBoundingSphere(origin, direction)) { + if (!success || !entityBox.rayHitsBoundingSphere(origin, direction)) { return; } @@ -226,7 +223,7 @@ EntityItemID EntityTreeElement::evalDetailedRayIntersection(const glm::vec3& ori glm::vec3 dimensions = entity->getRaycastDimensions(); glm::vec3 registrationPoint = entity->getRegistrationPoint(); - glm::vec3 corner = -(dimensions * registrationPoint); + glm::vec3 corner = -(dimensions * registrationPoint) + entity->getPivot(); AABox entityFrameBox(corner, dimensions); @@ -244,6 +241,9 @@ EntityItemID EntityTreeElement::evalDetailedRayIntersection(const glm::vec3& ori // now ask the entity if we actually intersect if (entity->supportsDetailedIntersection()) { QVariantMap localExtraInfo; + if (entity->getName().contains("boop")) { + qDebug() << entity->getName() << entity->getPivot() << entityFrameBox; + } if (entity->findDetailedRayIntersection(origin, direction, element, localDistance, localFace, localSurfaceNormal, localExtraInfo, searchFilter.isPrecise())) { if (localDistance < distance) { @@ -277,11 +277,12 @@ bool EntityTreeElement::findSpherePenetration(const glm::vec3& center, float rad bool result = false; withReadLock([&] { foreach(EntityItemPointer entity, _entityItems) { - glm::vec3 entityCenter = entity->getWorldPosition(); + bool success; + glm::vec3 entityCenter = entity->getCenterPosition(success); float entityRadius = entity->getRadius(); // don't penetrate yourself - if (entityCenter == center && entityRadius == radius) { + if (!success || (entityCenter == center && entityRadius == radius)) { return; } @@ -349,15 +350,12 @@ EntityItemID EntityTreeElement::evalDetailedParabolaIntersection(const glm::vec3 // (this is faster and more likely to cull results than the filter check below so we do it first) bool success; AABox entityBox = entity->getAABox(success); - if (!success) { - return; - } // Instead of checking parabolaInstersectsBoundingSphere here, we are just going to check if the plane // defined by the parabola slices the sphere. The solution to parabolaIntersectsBoundingSphere is cubic, // the solution to which is more computationally expensive than the quadratic AABox::findParabolaIntersection // below - if (!entityBox.parabolaPlaneIntersectsBoundingSphere(origin, velocity, acceleration, normal)) { + if (!success || !entityBox.parabolaPlaneIntersectsBoundingSphere(origin, velocity, acceleration, normal)) { return; } @@ -375,7 +373,7 @@ EntityItemID EntityTreeElement::evalDetailedParabolaIntersection(const glm::vec3 glm::vec3 dimensions = entity->getRaycastDimensions(); glm::vec3 registrationPoint = entity->getRegistrationPoint(); - glm::vec3 corner = -(dimensions * registrationPoint); + glm::vec3 corner = -(dimensions * registrationPoint) + entity->getPivot(); AABox entityFrameBox(corner, dimensions); @@ -445,7 +443,6 @@ void EntityTreeElement::evalEntitiesInSphere(const glm::vec3& position, float ra bool success; AABox entityBox = entity->getAABox(success); - // if the sphere doesn't intersect with our world frame AABox, we don't need to consider the more complex case glm::vec3 penetration; if (success && entityBox.findSpherePenetration(position, radius, penetration)) { @@ -464,10 +461,9 @@ void EntityTreeElement::evalEntitiesInSphere(const glm::vec3& position, float ra float entityTrueRadius = dimensions.x / 2.0f; bool success; - if (findSphereSpherePenetration(position, radius, entity->getCenterPosition(success), entityTrueRadius, penetration)) { - if (success) { - foundEntities.push_back(entity->getID()); - } + glm::vec3 center = entity->getCenterPosition(success); + if (success && findSphereSpherePenetration(position, radius, center, entityTrueRadius, penetration)) { + foundEntities.push_back(entity->getID()); } } else { // determine the worldToEntityMatrix that doesn't include scale because @@ -478,7 +474,7 @@ void EntityTreeElement::evalEntitiesInSphere(const glm::vec3& position, float ra glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix); glm::vec3 registrationPoint = entity->getRegistrationPoint(); - glm::vec3 corner = -(dimensions * registrationPoint); + glm::vec3 corner = -(dimensions * registrationPoint) + entity->getPivot(); AABox entityFrameBox(corner, dimensions); @@ -499,7 +495,6 @@ void EntityTreeElement::evalEntitiesInSphereWithType(const glm::vec3& position, bool success; AABox entityBox = entity->getAABox(success); - // if the sphere doesn't intersect with our world frame AABox, we don't need to consider the more complex case glm::vec3 penetration; if (success && entityBox.findSpherePenetration(position, radius, penetration)) { @@ -518,10 +513,9 @@ void EntityTreeElement::evalEntitiesInSphereWithType(const glm::vec3& position, float entityTrueRadius = dimensions.x / 2.0f; bool success; - if (findSphereSpherePenetration(position, radius, entity->getCenterPosition(success), entityTrueRadius, penetration)) { - if (success) { - foundEntities.push_back(entity->getID()); - } + glm::vec3 center = entity->getCenterPosition(success); + if (success && findSphereSpherePenetration(position, radius, center, entityTrueRadius, penetration)) { + foundEntities.push_back(entity->getID()); } } else { // determine the worldToEntityMatrix that doesn't include scale because @@ -532,7 +526,7 @@ void EntityTreeElement::evalEntitiesInSphereWithType(const glm::vec3& position, glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix); glm::vec3 registrationPoint = entity->getRegistrationPoint(); - glm::vec3 corner = -(dimensions * registrationPoint); + glm::vec3 corner = -(dimensions * registrationPoint) + entity->getPivot(); AABox entityFrameBox(corner, dimensions); @@ -575,12 +569,11 @@ void EntityTreeElement::evalEntitiesInSphereWithName(const glm::vec3& position, // NOTE: entity->getRadius() doesn't return the true radius, it returns the radius of the // maximum bounding sphere, which is actually larger than our actual radius float entityTrueRadius = dimensions.x / 2.0f; - bool success; - if (findSphereSpherePenetration(position, radius, entity->getCenterPosition(success), entityTrueRadius, penetration)) { - if (success) { - foundEntities.push_back(entity->getID()); - } + glm::vec3 center = entity->getCenterPosition(success); + + if (success && findSphereSpherePenetration(position, radius, center, entityTrueRadius, penetration)) { + foundEntities.push_back(entity->getID()); } } else { // determine the worldToEntityMatrix that doesn't include scale because @@ -591,7 +584,7 @@ void EntityTreeElement::evalEntitiesInSphereWithName(const glm::vec3& position, glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix); glm::vec3 registrationPoint = entity->getRegistrationPoint(); - glm::vec3 corner = -(dimensions * registrationPoint); + glm::vec3 corner = -(dimensions * registrationPoint) + entity->getPivot(); AABox entityFrameBox(corner, dimensions); @@ -612,6 +605,7 @@ void EntityTreeElement::evalEntitiesInCube(const AACube& cube, PickFilter search bool success; AABox entityBox = entity->getAABox(success); + // FIXME - handle entity->getShapeType() == SHAPE_TYPE_SPHERE case better // FIXME - consider allowing the entity to determine penetration so that // entities could presumably dull actuall hull testing if they wanted to @@ -642,6 +636,7 @@ void EntityTreeElement::evalEntitiesInBox(const AABox& box, PickFilter searchFil bool success; AABox entityBox = entity->getAABox(success); + // FIXME - handle entity->getShapeType() == SHAPE_TYPE_SPHERE case better // FIXME - consider allowing the entity to determine penetration so that // entities could presumably dull actuall hull testing if they wanted to @@ -680,7 +675,7 @@ void EntityTreeElement::evalEntitiesInFrustum(const ViewFrustum& frustum, PickFi }); } -void EntityTreeElement::getEntities(EntityItemFilter& filter, QVector& foundEntities) { +void EntityTreeElement::getEntities(EntityItemFilter& filter, QVector& foundEntities) { forEachEntity([&](EntityItemPointer entity) { if (filter(entity)) { foundEntities.push_back(entity); diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index 4716db6a41..50fd1f267a 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -73,6 +73,7 @@ EntityItemProperties ModelEntityItem::getProperties(const EntityPropertyFlags& d COPY_ENTITY_PROPERTY_TO_PROPERTIES(relayParentJoints, getRelayParentJoints); COPY_ENTITY_PROPERTY_TO_PROPERTIES(groupCulled, getGroupCulled); COPY_ENTITY_PROPERTY_TO_PROPERTIES(blendshapeCoefficients, getBlendshapeCoefficients); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(useOriginalPivot, getUseOriginalPivot); withReadLock([&] { _animationProperties.getProperties(properties); }); @@ -96,6 +97,7 @@ bool ModelEntityItem::setSubClassProperties(const EntityItemProperties& properti SET_ENTITY_PROPERTY_FROM_PROPERTIES(relayParentJoints, setRelayParentJoints); SET_ENTITY_PROPERTY_FROM_PROPERTIES(groupCulled, setGroupCulled); SET_ENTITY_PROPERTY_FROM_PROPERTIES(blendshapeCoefficients, setBlendshapeCoefficients); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(useOriginalPivot, setUseOriginalPivot); withWriteLock([&] { AnimationPropertyGroup animationProperties = _animationProperties; @@ -130,6 +132,7 @@ int ModelEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, READ_ENTITY_PROPERTY(PROP_RELAY_PARENT_JOINTS, bool, setRelayParentJoints); READ_ENTITY_PROPERTY(PROP_GROUP_CULLED, bool, setGroupCulled); READ_ENTITY_PROPERTY(PROP_BLENDSHAPE_COEFFICIENTS, QString, setBlendshapeCoefficients); + READ_ENTITY_PROPERTY(PROP_USE_ORIGINAL_PIVOT, bool, setUseOriginalPivot); // grab a local copy of _animationProperties to avoid multiple locks int bytesFromAnimation; @@ -169,6 +172,7 @@ EntityPropertyFlags ModelEntityItem::getEntityProperties(EncodeBitstreamParams& requestedProperties += PROP_RELAY_PARENT_JOINTS; requestedProperties += PROP_GROUP_CULLED; requestedProperties += PROP_BLENDSHAPE_COEFFICIENTS; + requestedProperties += PROP_USE_ORIGINAL_PIVOT; requestedProperties += _animationProperties.getEntityProperties(params); return requestedProperties; @@ -198,6 +202,7 @@ void ModelEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBit APPEND_ENTITY_PROPERTY(PROP_RELAY_PARENT_JOINTS, getRelayParentJoints()); APPEND_ENTITY_PROPERTY(PROP_GROUP_CULLED, getGroupCulled()); APPEND_ENTITY_PROPERTY(PROP_BLENDSHAPE_COEFFICIENTS, getBlendshapeCoefficients()); + APPEND_ENTITY_PROPERTY(PROP_USE_ORIGINAL_PIVOT, getUseOriginalPivot()); withReadLock([&] { _animationProperties.appendSubclassData(packetData, params, entityTreeElementExtraEncodeData, requestedProperties, @@ -251,6 +256,7 @@ void ModelEntityItem::debugDump() const { qCDebug(entities) << " model URL:" << getModelURL(); qCDebug(entities) << " compound shape URL:" << getCompoundShapeURL(); qCDebug(entities) << " blendshapeCoefficients:" << getBlendshapeCoefficients(); + qCDebug(entities) << " useOrigialPivot:" << getUseOriginalPivot(); } void ModelEntityItem::setShapeType(ShapeType type) { @@ -713,3 +719,16 @@ QVector ModelEntityItem::getBlendshapeCoefficientVector() { return _blendshapeCoefficientsVector; }); } + +void ModelEntityItem::setUseOriginalPivot(bool value) { + withWriteLock([&] { + _needsRenderUpdate |= _useOriginalPivot != value; + _useOriginalPivot = value; + }); +} + +bool ModelEntityItem::getUseOriginalPivot() const { + return resultWithReadLock([&] { + return _useOriginalPivot; + }); +} diff --git a/libraries/entities/src/ModelEntityItem.h b/libraries/entities/src/ModelEntityItem.h index b835b48d13..6e92b225a1 100644 --- a/libraries/entities/src/ModelEntityItem.h +++ b/libraries/entities/src/ModelEntityItem.h @@ -119,6 +119,9 @@ public: bool blendshapesChanged() const { return _blendshapesChanged; } QVector getBlendshapeCoefficientVector(); + bool getUseOriginalPivot() const; + void setUseOriginalPivot(bool useOriginalPivot); + private: void setAnimationSettings(const QString& value); // only called for old bitstream format bool applyNewAnimationProperties(AnimationPropertyGroup newProperties); @@ -152,6 +155,7 @@ protected: bool _relayParentJoints; bool _groupCulled { false }; QVariantMap _blendshapeCoefficientsMap; + bool _useOriginalPivot { false }; ThreadSafeValueCache _compoundShapeURL; diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 1015c87038..3ce43e059e 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -151,6 +151,7 @@ void Model::setOffset(const glm::vec3& offset) { // if someone manually sets our offset, then we are no longer snapped to center _snapModelToRegistrationPoint = false; _snappedToRegistrationPoint = false; + _needsTransformUpdate = true; } void Model::calculateTextureInfo() { @@ -344,6 +345,9 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g // extents is the entity relative, scaled, centered extents of the entity glm::mat4 modelToWorldMatrix = createMatFromQuatAndPos(_rotation, _translation); + if (!_snapModelToRegistrationPoint) { + modelToWorldMatrix = modelToWorldMatrix * glm::translate(getOriginalOffset()); + } glm::mat4 worldToModelMatrix = glm::inverse(modelToWorldMatrix); Extents modelExtents = getMeshExtents(); // NOTE: unrotated @@ -375,8 +379,7 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g calculateTriangleSets(hfmModel); } - glm::mat4 meshToModelMatrix = glm::scale(_scale) * glm::translate(_offset); - glm::mat4 meshToWorldMatrix = modelToWorldMatrix * meshToModelMatrix; + glm::mat4 meshToWorldMatrix = createMatFromQuatAndPos(_rotation, _translation) * (glm::scale(_scale) * glm::translate(_offset)); glm::mat4 worldToMeshMatrix = glm::inverse(meshToWorldMatrix); glm::vec3 meshFrameOrigin = glm::vec3(worldToMeshMatrix * glm::vec4(origin, 1.0f)); @@ -499,6 +502,9 @@ bool Model::findParabolaIntersectionAgainstSubMeshes(const glm::vec3& origin, co // extents is the entity relative, scaled, centered extents of the entity glm::mat4 modelToWorldMatrix = createMatFromQuatAndPos(_rotation, _translation); + if (!_snapModelToRegistrationPoint) { + modelToWorldMatrix = modelToWorldMatrix * glm::translate(getOriginalOffset()); + } glm::mat4 worldToModelMatrix = glm::inverse(modelToWorldMatrix); Extents modelExtents = getMeshExtents(); // NOTE: unrotated @@ -531,8 +537,7 @@ bool Model::findParabolaIntersectionAgainstSubMeshes(const glm::vec3& origin, co calculateTriangleSets(hfmModel); } - glm::mat4 meshToModelMatrix = glm::scale(_scale) * glm::translate(_offset); - glm::mat4 meshToWorldMatrix = modelToWorldMatrix * meshToModelMatrix; + glm::mat4 meshToWorldMatrix = createMatFromQuatAndPos(_rotation, _translation) * (glm::scale(_scale) * glm::translate(_offset)); glm::mat4 worldToMeshMatrix = glm::inverse(meshToWorldMatrix); glm::vec3 meshFrameOrigin = glm::vec3(worldToMeshMatrix * glm::vec4(origin, 1.0f)); @@ -1182,17 +1187,8 @@ glm::vec3 Model::getNaturalDimensions() const { } Extents Model::getMeshExtents() const { - if (!isLoaded()) { - return Extents(); - } - const Extents& extents = getHFMModel().meshExtents; - - // even though our caller asked for "unscaled" we need to include any fst scaling, translation, and rotation, which - // is captured in the offset matrix - glm::vec3 minimum = glm::vec3(getHFMModel().offset * glm::vec4(extents.minimum, 1.0f)); - glm::vec3 maximum = glm::vec3(getHFMModel().offset * glm::vec4(extents.maximum, 1.0f)); - Extents scaledExtents = { minimum * _scale, maximum * _scale }; - return scaledExtents; + Extents extents = getUnscaledMeshExtents(); + return { extents.minimum * _scale, extents.maximum * _scale}; } Extents Model::getUnscaledMeshExtents() const { @@ -1406,6 +1402,7 @@ void Model::setSnapModelToRegistrationPoint(bool snapModelToRegistrationPoint, c _snapModelToRegistrationPoint = snapModelToRegistrationPoint; _registrationPoint = clampedRegistrationPoint; _snappedToRegistrationPoint = false; // force re-centering + _needsTransformUpdate = true; } } @@ -1417,6 +1414,15 @@ void Model::snapToRegistrationPoint() { _snappedToRegistrationPoint = true; } +glm::vec3 Model::getOriginalOffset() const { + Extents modelMeshExtents = getUnscaledMeshExtents(); + glm::vec3 dimensions = (modelMeshExtents.maximum - modelMeshExtents.minimum); + glm::vec3 offset = modelMeshExtents.minimum + (dimensions * _registrationPoint); + glm::mat4 transform = glm::scale(_scale) * glm::translate(offset); + return transform[3]; +} + + void Model::setUseDualQuaternionSkinning(bool value) { _useDualQuaternionSkinning = value; } @@ -1424,7 +1430,7 @@ void Model::setUseDualQuaternionSkinning(bool value) { void Model::simulate(float deltaTime, bool fullUpdate) { DETAILED_PROFILE_RANGE(simulation_detail, __FUNCTION__); fullUpdate = updateGeometry() || fullUpdate || (_scaleToFit && !_scaledToFit) - || (_snapModelToRegistrationPoint && !_snappedToRegistrationPoint); + || (_snapModelToRegistrationPoint && !_snappedToRegistrationPoint) || _needsTransformUpdate; if (isLoaded() && fullUpdate) { onInvalidate(); @@ -1437,8 +1443,10 @@ void Model::simulate(float deltaTime, bool fullUpdate) { snapToRegistrationPoint(); } // update the world space transforms for all joints - glm::mat4 parentTransform = glm::scale(_scale) * glm::translate(_offset); + glm::mat4 parentTransform = glm::scale(_scale) * (_snapModelToRegistrationPoint ? + glm::translate(_offset) : glm::translate(getNaturalDimensions() * (0.5f - _registrationPoint))); updateRig(deltaTime, parentTransform); + _needsTransformUpdate = false; } } diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 1e7ab55d5a..7b606840f5 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -167,6 +167,7 @@ public: void setSnapModelToRegistrationPoint(bool snapModelToRegistrationPoint, const glm::vec3& registrationPoint); bool getSnapModelToRegistrationPoint() { return _snapModelToRegistrationPoint; } + bool getSnappedToRegistrationPoint() { return _snappedToRegistrationPoint; } virtual void simulate(float deltaTime, bool fullUpdate = true); virtual void updateClusterMatrices(); @@ -203,6 +204,7 @@ public: void setOffset(const glm::vec3& offset); const glm::vec3& getOffset() const { return _offset; } + glm::vec3 getOriginalOffset() const; void setScaleToFit(bool scaleToFit, float largestDimension = 0.0f, bool forceRescale = false); void setScaleToFit(bool scaleToFit, const glm::vec3& dimensions, bool forceRescale = false); @@ -348,6 +350,7 @@ public: virtual bool replaceScriptableModelMeshPart(scriptable::ScriptableModelBasePointer model, int meshIndex, int partIndex) override; void scaleToFit(); + void snapToRegistrationPoint(); bool getUseDualQuaternionSkinning() const { return _useDualQuaternionSkinning; } void setUseDualQuaternionSkinning(bool value); @@ -409,14 +412,14 @@ protected: bool _snapModelToRegistrationPoint; /// is the model's offset automatically adjusted to a registration point in model space bool _snappedToRegistrationPoint; /// are we currently snapped to a registration point - glm::vec3 _registrationPoint = glm::vec3(0.5f); /// the point in model space our center is snapped to + glm::vec3 _registrationPoint { glm::vec3(0.5f) }; /// the point in model space our center is snapped to + bool _needsTransformUpdate { false }; std::vector _meshStates; virtual void initJointStates(); void setScaleInternal(const glm::vec3& scale); - void snapToRegistrationPoint(); virtual void updateRig(float deltaTime, glm::mat4 parentTransform); From 1475cae504083e8076d6d78fa80918e613529bd1 Mon Sep 17 00:00:00 2001 From: HifiExperiments Date: Wed, 23 Dec 2020 21:29:59 -0800 Subject: [PATCH 02/33] wip --- .../src/avatars-renderer/SkeletonModel.cpp | 4 ++-- .../avatars-renderer/src/avatars-renderer/SkeletonModel.h | 2 +- libraries/entities/src/EntityTreeElement.cpp | 3 --- libraries/render-utils/src/Model.cpp | 7 +++++-- libraries/render-utils/src/Model.h | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.cpp b/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.cpp index 5ac808d3fb..b1c9f7262e 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.cpp @@ -152,11 +152,11 @@ void SkeletonModel::updateAttitude(const glm::quat& orientation) { // Called by Avatar::simulate after it has set the joint states (fullUpdate true if changed), // but just before head has been simulated. -void SkeletonModel::simulate(float deltaTime, bool fullUpdate) { +void SkeletonModel::simulate(float deltaTime, bool fullUpdate, bool skeleton) { updateAttitude(_owningAvatar->getWorldOrientation()); setBlendshapeCoefficients(_owningAvatar->getHead()->getSummedBlendshapeCoefficients()); - Parent::simulate(deltaTime, fullUpdate); + Parent::simulate(deltaTime, fullUpdate, true); if (fullUpdate) { // let rig compute the model offset glm::vec3 registrationPoint; diff --git a/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.h b/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.h index e24d969461..b21c414c37 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.h +++ b/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.h @@ -36,7 +36,7 @@ public: void initJointStates() override; - void simulate(float deltaTime, bool fullUpdate = true) override; + void simulate(float deltaTime, bool fullUpdate = true, bool skeleton = false) override; glm::vec3 avoidCrossedEyes(const glm::vec3& lookAt); void updateRig(float deltaTime, glm::mat4 parentTransform) override; void updateAttitude(const glm::quat& orientation); diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index 16b6ccac9b..66d44d89de 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -241,9 +241,6 @@ EntityItemID EntityTreeElement::evalDetailedRayIntersection(const glm::vec3& ori // now ask the entity if we actually intersect if (entity->supportsDetailedIntersection()) { QVariantMap localExtraInfo; - if (entity->getName().contains("boop")) { - qDebug() << entity->getName() << entity->getPivot() << entityFrameBox; - } if (entity->findDetailedRayIntersection(origin, direction, element, localDistance, localFace, localSurfaceNormal, localExtraInfo, searchFilter.isPrecise())) { if (localDistance < distance) { diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 78ff17a8ef..0194b838cc 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -362,6 +362,9 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g // we can use the AABox's intersection by mapping our origin and direction into the model frame // and testing intersection there. if (modelFrameBox.findRayIntersection(modelFrameOrigin, modelFrameDirection, 1.0f / modelFrameDirection, distance, face, surfaceNormal)) { + if (getURL().toString().toLower().contains("sink")) { + qDebug() << "boop" << modelFrameBox; + } QMutexLocker locker(&_mutex); float bestDistance = FLT_MAX; @@ -1427,7 +1430,7 @@ void Model::setUseDualQuaternionSkinning(bool value) { _useDualQuaternionSkinning = value; } -void Model::simulate(float deltaTime, bool fullUpdate) { +void Model::simulate(float deltaTime, bool fullUpdate, bool skeleton) { DETAILED_PROFILE_RANGE(simulation_detail, __FUNCTION__); fullUpdate = updateGeometry() || fullUpdate || (_scaleToFit && !_scaledToFit) || (_snapModelToRegistrationPoint && !_snappedToRegistrationPoint) || _needsTransformUpdate; @@ -1443,7 +1446,7 @@ void Model::simulate(float deltaTime, bool fullUpdate) { snapToRegistrationPoint(); } // update the world space transforms for all joints - glm::mat4 parentTransform = glm::scale(_scale) * (_snapModelToRegistrationPoint ? + glm::mat4 parentTransform = glm::scale(_scale) * ((_snapModelToRegistrationPoint || skeleton) ? glm::translate(_offset) : glm::translate(getNaturalDimensions() * (0.5f - _registrationPoint))); updateRig(deltaTime, parentTransform); _needsTransformUpdate = false; diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 7b606840f5..800bfc7e15 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -169,7 +169,7 @@ public: bool getSnapModelToRegistrationPoint() { return _snapModelToRegistrationPoint; } bool getSnappedToRegistrationPoint() { return _snappedToRegistrationPoint; } - virtual void simulate(float deltaTime, bool fullUpdate = true); + virtual void simulate(float deltaTime, bool fullUpdate = true, bool skeleton = false); virtual void updateClusterMatrices(); virtual void updateBlendshapes(); From 002271a4cc8d859b79ec65732bc7d64ae9421fe0 Mon Sep 17 00:00:00 2001 From: HifiExperiments Date: Fri, 1 Jan 2021 21:42:51 -0800 Subject: [PATCH 03/33] finishing touches --- .../src/avatars-renderer/SkeletonModel.cpp | 5 +-- .../src/avatars-renderer/SkeletonModel.h | 2 +- .../src/RenderableModelEntityItem.cpp | 5 +-- libraries/render-utils/src/Model.cpp | 33 +++++++++++++------ libraries/render-utils/src/Model.h | 3 +- scripts/system/create/edit.js | 1 + scripts/system/create/qml/NewModelDialog.qml | 8 ++++- 7 files changed, 40 insertions(+), 17 deletions(-) diff --git a/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.cpp b/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.cpp index b1c9f7262e..15ff09d13d 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.cpp @@ -33,6 +33,7 @@ SkeletonModel::SkeletonModel(Avatar* owningAvatar, QObject* parent) : { // SkeletonModels, and by extention Avatars, use Dual Quaternion skinning. _useDualQuaternionSkinning = true; + _forceOffset = true; // Avatars all cast shadow setCanCastShadow(true); @@ -152,11 +153,11 @@ void SkeletonModel::updateAttitude(const glm::quat& orientation) { // Called by Avatar::simulate after it has set the joint states (fullUpdate true if changed), // but just before head has been simulated. -void SkeletonModel::simulate(float deltaTime, bool fullUpdate, bool skeleton) { +void SkeletonModel::simulate(float deltaTime, bool fullUpdate) { updateAttitude(_owningAvatar->getWorldOrientation()); setBlendshapeCoefficients(_owningAvatar->getHead()->getSummedBlendshapeCoefficients()); - Parent::simulate(deltaTime, fullUpdate, true); + Parent::simulate(deltaTime, fullUpdate); if (fullUpdate) { // let rig compute the model offset glm::vec3 registrationPoint; diff --git a/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.h b/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.h index b21c414c37..e24d969461 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.h +++ b/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.h @@ -36,7 +36,7 @@ public: void initJointStates() override; - void simulate(float deltaTime, bool fullUpdate = true, bool skeleton = false) override; + void simulate(float deltaTime, bool fullUpdate = true) override; glm::vec3 avoidCrossedEyes(const glm::vec3& lookAt); void updateRig(float deltaTime, glm::mat4 parentTransform) override; void updateAttitude(const glm::quat& orientation); diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index f58df45a31..7efc988bb4 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -152,8 +152,9 @@ void RenderableModelEntityItem::updateModelBounds() { bool needsSimulate = false; if (!overridingModelTransform && (model->getScaleToFitDimensions() != scaledDimensions || - model->getRegistrationPoint() != registrationPoint || - !model->getIsScaledToFit() || _useOriginalPivot == model->getSnapModelToRegistrationPoint())) { + model->getRegistrationPoint() != registrationPoint || + !model->getIsScaledToFit() || _needsToRescaleModel || + _useOriginalPivot == model->getSnapModelToRegistrationPoint())) { // The machinery for updateModelBounds will give existing models the opportunity to fix their // translation/rotation/scale/registration. The first two are straightforward, but the latter two // have guards to make sure they don't happen after they've already been set. Here we reset those guards. diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 0194b838cc..a58bfd6f5b 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -344,7 +344,8 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g } // extents is the entity relative, scaled, centered extents of the entity - glm::mat4 modelToWorldMatrix = createMatFromQuatAndPos(_rotation, _translation); + glm::mat4 transRot = createMatFromQuatAndPos(_rotation, _translation); + glm::mat4 modelToWorldMatrix = transRot; if (!_snapModelToRegistrationPoint) { modelToWorldMatrix = modelToWorldMatrix * glm::translate(getOriginalOffset()); } @@ -362,9 +363,6 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g // we can use the AABox's intersection by mapping our origin and direction into the model frame // and testing intersection there. if (modelFrameBox.findRayIntersection(modelFrameOrigin, modelFrameDirection, 1.0f / modelFrameDirection, distance, face, surfaceNormal)) { - if (getURL().toString().toLower().contains("sink")) { - qDebug() << "boop" << modelFrameBox; - } QMutexLocker locker(&_mutex); float bestDistance = FLT_MAX; @@ -382,7 +380,14 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g calculateTriangleSets(hfmModel); } - glm::mat4 meshToWorldMatrix = createMatFromQuatAndPos(_rotation, _translation) * (glm::scale(_scale) * glm::translate(_offset)); + glm::mat4 meshToWorldMatrix = transRot; + if (_snapModelToRegistrationPoint || _forceOffset) { + meshToWorldMatrix = meshToWorldMatrix * (glm::scale(_scale) * glm::translate(_offset)); + } else { + Extents unscaledExtents = getUnscaledMeshExtents(); + glm::vec3 unscaledDimensions = unscaledExtents.maximum - unscaledExtents.minimum; + meshToWorldMatrix = meshToWorldMatrix * (glm::scale(_scale) * glm::translate(unscaledDimensions * (0.5f - _registrationPoint))); + } glm::mat4 worldToMeshMatrix = glm::inverse(meshToWorldMatrix); glm::vec3 meshFrameOrigin = glm::vec3(worldToMeshMatrix * glm::vec4(origin, 1.0f)); @@ -504,7 +509,8 @@ bool Model::findParabolaIntersectionAgainstSubMeshes(const glm::vec3& origin, co } // extents is the entity relative, scaled, centered extents of the entity - glm::mat4 modelToWorldMatrix = createMatFromQuatAndPos(_rotation, _translation); + glm::mat4 transRot = createMatFromQuatAndPos(_rotation, _translation); + glm::mat4 modelToWorldMatrix = transRot; if (!_snapModelToRegistrationPoint) { modelToWorldMatrix = modelToWorldMatrix * glm::translate(getOriginalOffset()); } @@ -540,7 +546,14 @@ bool Model::findParabolaIntersectionAgainstSubMeshes(const glm::vec3& origin, co calculateTriangleSets(hfmModel); } - glm::mat4 meshToWorldMatrix = createMatFromQuatAndPos(_rotation, _translation) * (glm::scale(_scale) * glm::translate(_offset)); + glm::mat4 meshToWorldMatrix = transRot; + if (_snapModelToRegistrationPoint || _forceOffset) { + meshToWorldMatrix = meshToWorldMatrix * (glm::scale(_scale) * glm::translate(_offset)); + } else { + Extents unscaledExtents = getUnscaledMeshExtents(); + glm::vec3 unscaledDimensions = unscaledExtents.maximum - unscaledExtents.minimum; + meshToWorldMatrix = meshToWorldMatrix * (glm::scale(_scale) * glm::translate(unscaledDimensions * (0.5f - _registrationPoint))); + } glm::mat4 worldToMeshMatrix = glm::inverse(meshToWorldMatrix); glm::vec3 meshFrameOrigin = glm::vec3(worldToMeshMatrix * glm::vec4(origin, 1.0f)); @@ -1420,7 +1433,7 @@ void Model::snapToRegistrationPoint() { glm::vec3 Model::getOriginalOffset() const { Extents modelMeshExtents = getUnscaledMeshExtents(); glm::vec3 dimensions = (modelMeshExtents.maximum - modelMeshExtents.minimum); - glm::vec3 offset = modelMeshExtents.minimum + (dimensions * _registrationPoint); + glm::vec3 offset = modelMeshExtents.minimum + (0.5f * dimensions); glm::mat4 transform = glm::scale(_scale) * glm::translate(offset); return transform[3]; } @@ -1430,7 +1443,7 @@ void Model::setUseDualQuaternionSkinning(bool value) { _useDualQuaternionSkinning = value; } -void Model::simulate(float deltaTime, bool fullUpdate, bool skeleton) { +void Model::simulate(float deltaTime, bool fullUpdate) { DETAILED_PROFILE_RANGE(simulation_detail, __FUNCTION__); fullUpdate = updateGeometry() || fullUpdate || (_scaleToFit && !_scaledToFit) || (_snapModelToRegistrationPoint && !_snappedToRegistrationPoint) || _needsTransformUpdate; @@ -1446,7 +1459,7 @@ void Model::simulate(float deltaTime, bool fullUpdate, bool skeleton) { snapToRegistrationPoint(); } // update the world space transforms for all joints - glm::mat4 parentTransform = glm::scale(_scale) * ((_snapModelToRegistrationPoint || skeleton) ? + glm::mat4 parentTransform = glm::scale(_scale) * ((_snapModelToRegistrationPoint || _forceOffset) ? glm::translate(_offset) : glm::translate(getNaturalDimensions() * (0.5f - _registrationPoint))); updateRig(deltaTime, parentTransform); _needsTransformUpdate = false; diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 800bfc7e15..aa5df1a3dd 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -169,7 +169,7 @@ public: bool getSnapModelToRegistrationPoint() { return _snapModelToRegistrationPoint; } bool getSnappedToRegistrationPoint() { return _snappedToRegistrationPoint; } - virtual void simulate(float deltaTime, bool fullUpdate = true, bool skeleton = false); + virtual void simulate(float deltaTime, bool fullUpdate = true); virtual void updateClusterMatrices(); virtual void updateBlendshapes(); @@ -414,6 +414,7 @@ protected: bool _snappedToRegistrationPoint; /// are we currently snapped to a registration point glm::vec3 _registrationPoint { glm::vec3(0.5f) }; /// the point in model space our center is snapped to bool _needsTransformUpdate { false }; + bool _forceOffset { false }; std::vector _meshStates; diff --git a/scripts/system/create/edit.js b/scripts/system/create/edit.js index fc3d4fc10f..96dbf4637d 100644 --- a/scripts/system/create/edit.js +++ b/scripts/system/create/edit.js @@ -737,6 +737,7 @@ var toolBar = (function () { grabbable: result.grabbable }, dynamic: dynamic, + useOriginalPivot: result.useOriginalPivot }); } } diff --git a/scripts/system/create/qml/NewModelDialog.qml b/scripts/system/create/qml/NewModelDialog.qml index 758706a79b..807ab1cd56 100644 --- a/scripts/system/create/qml/NewModelDialog.qml +++ b/scripts/system/create/qml/NewModelDialog.qml @@ -120,6 +120,11 @@ Rectangle { height: 600 spacing: 10 + CheckBox { + id: useOriginalPivot + text: qsTr("Use Original Pivot") + } + CheckBox { id: grabbable text: qsTr("Grabbable") @@ -219,7 +224,8 @@ Rectangle { url: modelURL.text, dynamic: dynamic.checked, collisionShapeIndex: collisionType.currentIndex, - grabbable: grabbable.checked + grabbable: grabbable.checked, + useOriginalPivot: useOriginalPivot.checked } }); } From 20e0c241634832cb159f49edeab0d4a707466d53 Mon Sep 17 00:00:00 2001 From: HifiExperiments Date: Fri, 1 Jan 2021 23:42:06 -0800 Subject: [PATCH 04/33] cleanup + create --- .../src/RenderableModelEntityItem.cpp | 6 +++--- libraries/entities/src/EntityItem.cpp | 8 ++++---- libraries/hfm/src/hfm/HFM.cpp | 2 +- libraries/render-utils/src/Model.cpp | 13 +++---------- libraries/render-utils/src/Model.h | 1 - .../create/assets/data/createAppTooltips.json | 3 +++ .../entityProperties/html/js/entityProperties.js | 5 +++++ 7 files changed, 19 insertions(+), 19 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 7efc988bb4..f7baa4e894 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -227,12 +227,12 @@ EntityItemProperties RenderableModelEntityItem::getProperties(const EntityProper glm::vec3 RenderableModelEntityItem::getPivot() const { auto model = getModel(); - auto raycastOffset = EntityItem::getPivot(); + auto pivot = EntityItem::getPivot(); if (!model || !model->isLoaded() || !_useOriginalPivot) { - return raycastOffset; + return pivot; } - return raycastOffset + model->getOriginalOffset(); + return pivot + model->getOriginalOffset(); } bool RenderableModelEntityItem::supportsDetailedIntersection() const { diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 48490aeb51..3996920572 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -1628,16 +1628,16 @@ AACube EntityItem::getMaximumAACube(bool& success) const { _recalcMaxAACube = false; // we want to compute the furthestExtent that an entity can extend out from its "position" // to do this we compute the max of these two vec3s: registration and 1-registration - // and then scale by dimensions - glm::vec3 offset = getScaledDimensions() * getRegistrationPoint() + getPivot(); - glm::vec3 maxExtents = glm::max(offset, glm::vec3(1.0f) - offset); + // and then scale by dimensions and add the absolute value of the pivot + glm::vec3 registrationPoint = getRegistrationPoint(); + glm::vec3 maxExtents = getScaledDimensions() * glm::max(registrationPoint, glm::vec3(1.0f) - registrationPoint); // there exists a sphere that contains maxExtents for all rotations float radius = glm::length(maxExtents); // put a cube around the sphere // TODO? replace _maxAACube with _boundingSphereRadius - glm::vec3 minimumCorner = centerOfRotation - glm::vec3(radius, radius, radius); + glm::vec3 minimumCorner = (centerOfRotation + getPivot()) - glm::vec3(radius, radius, radius); _maxAACube = AACube(minimumCorner, radius * 2.0f); } } else { diff --git a/libraries/hfm/src/hfm/HFM.cpp b/libraries/hfm/src/hfm/HFM.cpp index 8fb0720c0d..dd13d6d4f3 100644 --- a/libraries/hfm/src/hfm/HFM.cpp +++ b/libraries/hfm/src/hfm/HFM.cpp @@ -104,7 +104,7 @@ bool HFMModel::convexHullContains(const glm::vec3& point) const { auto checkEachPrimitive = [=](HFMMesh& mesh, QVector indices, int primitiveSize) -> bool { // Check whether the point is "behind" all the primitives. // But first must transform from model-frame into mesh-frame - glm::vec3 transformedPoint = glm::vec3(glm::inverse(mesh.modelTransform) * glm::vec4(point, 1.0f)); + glm::vec3 transformedPoint = glm::vec3(glm::inverse(offset * mesh.modelTransform) * glm::vec4(point, 1.0f)); int verticesSize = mesh.vertices.size(); for (int j = 0; j < indices.size() - 2; // -2 in case the vertices aren't the right size -- we access j + 2 below diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index a58bfd6f5b..44dbc00f70 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -151,7 +151,6 @@ void Model::setOffset(const glm::vec3& offset) { // if someone manually sets our offset, then we are no longer snapped to center _snapModelToRegistrationPoint = false; _snappedToRegistrationPoint = false; - _needsTransformUpdate = true; } void Model::calculateTextureInfo() { @@ -384,9 +383,7 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g if (_snapModelToRegistrationPoint || _forceOffset) { meshToWorldMatrix = meshToWorldMatrix * (glm::scale(_scale) * glm::translate(_offset)); } else { - Extents unscaledExtents = getUnscaledMeshExtents(); - glm::vec3 unscaledDimensions = unscaledExtents.maximum - unscaledExtents.minimum; - meshToWorldMatrix = meshToWorldMatrix * (glm::scale(_scale) * glm::translate(unscaledDimensions * (0.5f - _registrationPoint))); + meshToWorldMatrix = meshToWorldMatrix * (glm::scale(_scale) * glm::translate(getNaturalDimensions() * (0.5f - _registrationPoint))); } glm::mat4 worldToMeshMatrix = glm::inverse(meshToWorldMatrix); @@ -550,9 +547,7 @@ bool Model::findParabolaIntersectionAgainstSubMeshes(const glm::vec3& origin, co if (_snapModelToRegistrationPoint || _forceOffset) { meshToWorldMatrix = meshToWorldMatrix * (glm::scale(_scale) * glm::translate(_offset)); } else { - Extents unscaledExtents = getUnscaledMeshExtents(); - glm::vec3 unscaledDimensions = unscaledExtents.maximum - unscaledExtents.minimum; - meshToWorldMatrix = meshToWorldMatrix * (glm::scale(_scale) * glm::translate(unscaledDimensions * (0.5f - _registrationPoint))); + meshToWorldMatrix = meshToWorldMatrix * (glm::scale(_scale) * glm::translate(getNaturalDimensions() * (0.5f - _registrationPoint))); } glm::mat4 worldToMeshMatrix = glm::inverse(meshToWorldMatrix); @@ -1418,7 +1413,6 @@ void Model::setSnapModelToRegistrationPoint(bool snapModelToRegistrationPoint, c _snapModelToRegistrationPoint = snapModelToRegistrationPoint; _registrationPoint = clampedRegistrationPoint; _snappedToRegistrationPoint = false; // force re-centering - _needsTransformUpdate = true; } } @@ -1446,7 +1440,7 @@ void Model::setUseDualQuaternionSkinning(bool value) { void Model::simulate(float deltaTime, bool fullUpdate) { DETAILED_PROFILE_RANGE(simulation_detail, __FUNCTION__); fullUpdate = updateGeometry() || fullUpdate || (_scaleToFit && !_scaledToFit) - || (_snapModelToRegistrationPoint && !_snappedToRegistrationPoint) || _needsTransformUpdate; + || (_snapModelToRegistrationPoint && !_snappedToRegistrationPoint); if (isLoaded() && fullUpdate) { onInvalidate(); @@ -1462,7 +1456,6 @@ void Model::simulate(float deltaTime, bool fullUpdate) { glm::mat4 parentTransform = glm::scale(_scale) * ((_snapModelToRegistrationPoint || _forceOffset) ? glm::translate(_offset) : glm::translate(getNaturalDimensions() * (0.5f - _registrationPoint))); updateRig(deltaTime, parentTransform); - _needsTransformUpdate = false; } } diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index aa5df1a3dd..9bf828f9fb 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -413,7 +413,6 @@ protected: bool _snapModelToRegistrationPoint; /// is the model's offset automatically adjusted to a registration point in model space bool _snappedToRegistrationPoint; /// are we currently snapped to a registration point glm::vec3 _registrationPoint { glm::vec3(0.5f) }; /// the point in model space our center is snapped to - bool _needsTransformUpdate { false }; bool _forceOffset { false }; std::vector _meshStates; diff --git a/scripts/system/create/assets/data/createAppTooltips.json b/scripts/system/create/assets/data/createAppTooltips.json index 478793ab78..7c70a8dea8 100644 --- a/scripts/system/create/assets/data/createAppTooltips.json +++ b/scripts/system/create/assets/data/createAppTooltips.json @@ -601,6 +601,9 @@ "groupCulled": { "tooltip": "If false, individual pieces of the entity may be culled by the render engine. If true, either the entire entity will be culled, or it won't at all." }, + "useOriginalPivot": { + "tooltip": "If false, the model will be centered based on its content, ignoring any offset in the model itself. If true, the model will respect its original offset." + }, "webColor": { "tooltip": "The tint of the web entity." }, diff --git a/scripts/system/create/entityProperties/html/js/entityProperties.js b/scripts/system/create/entityProperties/html/js/entityProperties.js index f3f92a887e..592808bd15 100644 --- a/scripts/system/create/entityProperties/html/js/entityProperties.js +++ b/scripts/system/create/entityProperties/html/js/entityProperties.js @@ -614,6 +614,11 @@ const GROUPS = [ propertyID: "compoundShapeURL", hideIfCertified: true, }, + { + label: "Use Original Pivot", + type: "bool", + propertyID: "useOriginalPivot", + }, { label: "Animation", type: "string", From 5dc45e895cda958d95525414e5247ecd61561c7d Mon Sep 17 00:00:00 2001 From: HifiExperiments Date: Sat, 2 Jan 2021 19:18:54 -0800 Subject: [PATCH 05/33] more fixes and create checkbox defaults to checked --- libraries/entities-renderer/src/RenderableModelEntityItem.cpp | 2 +- libraries/entities/src/EntityItem.cpp | 2 +- scripts/system/create/qml/NewModelDialog.qml | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 1ac34a2170..3f72527d72 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -167,7 +167,6 @@ void RenderableModelEntityItem::updateModelBounds() { model->setSnapModelToRegistrationPoint(!_useOriginalPivot, registrationPoint); updateRenderItems = true; needsSimulate = true; - locationChanged(); _needsToRescaleModel = false; } @@ -183,6 +182,7 @@ void RenderableModelEntityItem::updateModelBounds() { // NOTE: on isAnimatingSomething() we need to call Model::simulate() which calls Rig::updateRig() // TODO: there is opportunity to further optimize the isAnimatingSomething() case. model->simulate(0.0f); + locationChanged(); _needsInitialSimulation = false; _needsJointSimulation = false; updateRenderItems = true; diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 3996920572..f7bd0266fa 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -1637,7 +1637,7 @@ AACube EntityItem::getMaximumAACube(bool& success) const { // put a cube around the sphere // TODO? replace _maxAACube with _boundingSphereRadius - glm::vec3 minimumCorner = (centerOfRotation + getPivot()) - glm::vec3(radius, radius, radius); + glm::vec3 minimumCorner = (centerOfRotation + getWorldOrientation() * getPivot()) - glm::vec3(radius, radius, radius); _maxAACube = AACube(minimumCorner, radius * 2.0f); } } else { diff --git a/scripts/system/create/qml/NewModelDialog.qml b/scripts/system/create/qml/NewModelDialog.qml index 807ab1cd56..c03e7c1c35 100644 --- a/scripts/system/create/qml/NewModelDialog.qml +++ b/scripts/system/create/qml/NewModelDialog.qml @@ -123,6 +123,7 @@ Rectangle { CheckBox { id: useOriginalPivot text: qsTr("Use Original Pivot") + checked: true } CheckBox { From 6e0bad814e0e513a4b363059d4cf43e609e2627a Mon Sep 17 00:00:00 2001 From: HifiExperiments Date: Sun, 3 Jan 2021 20:33:08 -0800 Subject: [PATCH 06/33] working on billboard mode for all entity types --- .../src/RenderableEntityItem.cpp | 40 +++++++++++-------- .../src/RenderableEntityItem.h | 4 +- .../src/RenderableGizmoEntityItem.cpp | 9 +++-- .../src/RenderableGridEntityItem.cpp | 4 +- .../src/RenderableImageEntityItem.cpp | 12 ------ .../src/RenderableImageEntityItem.h | 2 - .../src/RenderableLineEntityItem.cpp | 1 + .../src/RenderableMaterialEntityItem.cpp | 11 ++--- .../RenderableParticleEffectEntityItem.cpp | 2 + .../src/RenderablePolyLineEntityItem.cpp | 4 +- .../src/RenderableShapeEntityItem.cpp | 15 ++++--- .../src/RenderableTextEntityItem.cpp | 37 +++++------------ .../src/RenderableTextEntityItem.h | 2 - .../src/RenderableWebEntityItem.cpp | 16 +------- .../src/RenderableWebEntityItem.h | 2 - libraries/entities/src/EntityItem.cpp | 30 +++++++++++++- libraries/entities/src/EntityItem.h | 7 +++- .../entities/src/EntityItemProperties.cpp | 32 ++++++--------- libraries/entities/src/EntityItemProperties.h | 2 +- libraries/entities/src/EntityPropertyFlags.h | 2 +- libraries/entities/src/GizmoEntityItem.cpp | 3 ++ libraries/entities/src/ImageEntityItem.cpp | 37 +++-------------- libraries/entities/src/ImageEntityItem.h | 5 --- libraries/entities/src/TextEntityItem.cpp | 37 +++-------------- libraries/entities/src/TextEntityItem.h | 6 --- libraries/entities/src/WebEntityItem.cpp | 35 +++------------- libraries/entities/src/WebEntityItem.h | 5 --- libraries/networking/src/udt/PacketHeaders.h | 1 + 28 files changed, 134 insertions(+), 229 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableEntityItem.cpp b/libraries/entities-renderer/src/RenderableEntityItem.cpp index b116423b75..fdb971e7a3 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableEntityItem.cpp @@ -138,7 +138,14 @@ EntityRenderer::~EntityRenderer() {} // Item::Bound EntityRenderer::getBound() { - return _bound; + auto bound = _bound; + if (_billboardMode != BillboardMode::NONE) { + glm::vec3 dimensions = bound.getScale(); + float max = glm::max(dimensions.x, glm::max(dimensions.y, dimensions.z)); + const float SQRT_2 = 1.41421356237f; + bound.setScaleStayCentered(glm::vec3(SQRT_2 * max)); + } + return bound; } ShapeKey EntityRenderer::getShapeKey() { @@ -198,12 +205,9 @@ uint32_t EntityRenderer::metaFetchMetaSubItems(ItemIDs& subItems) const { } bool EntityRenderer::passesZoneOcclusionTest(const std::unordered_set& containingZones) const { - auto renderWithZones = resultWithReadLock>([&] { - return _renderWithZones; - }); - if (!renderWithZones.isEmpty()) { + if (!_renderWithZones.isEmpty()) { if (!containingZones.empty()) { - for (auto renderWithZone : renderWithZones) { + for (auto renderWithZone : _renderWithZones) { if (containingZones.find(renderWithZone) != containingZones.end()) { return true; } @@ -429,20 +433,24 @@ void EntityRenderer::doRenderUpdateSynchronous(const ScenePointer& scene, Transa _moving = entity->isMovingRelativeToParent(); _visible = entity->getVisible(); - setIsVisibleInSecondaryCamera(entity->isVisibleInSecondaryCamera()); - setRenderLayer(entity->getRenderLayer()); - _primitiveMode = entity->getPrimitiveMode(); - _canCastShadow = entity->getCanCastShadow(); - setCullWithParent(entity->getCullWithParent()); - _cauterized = entity->getCauterized(); - if (entity->needsZoneOcclusionUpdate()) { - entity->resetNeedsZoneOcclusionUpdate(); - _renderWithZones = entity->getRenderWithZones(); - } entity->setNeedsRenderUpdate(false); }); } +void EntityRenderer::doRenderUpdateAsynchronous(const EntityItemPointer& entity) { + setIsVisibleInSecondaryCamera(entity->isVisibleInSecondaryCamera()); + setRenderLayer(entity->getRenderLayer()); + _billboardMode = entity->getBillboardMode(); + _primitiveMode = entity->getPrimitiveMode(); + _canCastShadow = entity->getCanCastShadow(); + setCullWithParent(entity->getCullWithParent()); + _cauterized = entity->getCauterized(); + if (entity->needsZoneOcclusionUpdate()) { + entity->resetNeedsZoneOcclusionUpdate(); + _renderWithZones = entity->getRenderWithZones(); + } +} + void EntityRenderer::onAddToScene(const EntityItemPointer& entity) { QObject::connect(this, &EntityRenderer::requestRenderUpdate, this, [this] { auto renderer = DependencyManager::get(); diff --git a/libraries/entities-renderer/src/RenderableEntityItem.h b/libraries/entities-renderer/src/RenderableEntityItem.h index ca3e024338..4afcd6e231 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.h +++ b/libraries/entities-renderer/src/RenderableEntityItem.h @@ -95,8 +95,7 @@ protected: // Will be called by the lambda posted to the scene in updateInScene. // This function will execute on the rendering thread, so you cannot use network caches to fetch // data in this method if using multi-threaded rendering - - virtual void doRenderUpdateAsynchronous(const EntityItemPointer& entity) { } + virtual void doRenderUpdateAsynchronous(const EntityItemPointer& entity); // Called by the `render` method after `needsRenderUpdate` virtual void doRender(RenderArgs* args) = 0; @@ -135,6 +134,7 @@ protected: RenderLayer _renderLayer { RenderLayer::WORLD }; PrimitiveMode _primitiveMode { PrimitiveMode::SOLID }; QVector _renderWithZones; + BillboardMode _billboardMode; bool _cauterized { false }; bool _moving { false }; Transform _renderTransform; diff --git a/libraries/entities-renderer/src/RenderableGizmoEntityItem.cpp b/libraries/entities-renderer/src/RenderableGizmoEntityItem.cpp index 6928454eb0..caf5bde729 100644 --- a/libraries/entities-renderer/src/RenderableGizmoEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableGizmoEntityItem.cpp @@ -242,18 +242,19 @@ void GizmoEntityRenderer::doRender(RenderArgs* args) { bool hasTickMarks = _ringProperties.getHasTickMarks(); glm::vec4 tickProperties = glm::vec4(_ringProperties.getMajorTickMarksAngle(), _ringProperties.getMajorTickMarksLength(), _ringProperties.getMinorTickMarksAngle(), _ringProperties.getMinorTickMarksLength()); - bool forward; - bool wireframe; + bool transparent; withReadLock([&] { transform = _renderTransform; transparent = isTransparent(); - wireframe = render::ShapeKey(args->_globalShapeKey).isWireframe() || _primitiveMode == PrimitiveMode::LINES; - forward = _renderLayer != RenderLayer::WORLD || args->_renderMethod == Args::RenderMethod::FORWARD; }); + bool wireframe = render::ShapeKey(args->_globalShapeKey).isWireframe() || _primitiveMode == PrimitiveMode::LINES; + bool forward = _renderLayer != RenderLayer::WORLD || args->_renderMethod == Args::RenderMethod::FORWARD; + geometryCache->bindSimpleProgram(batch, false, transparent, wireframe, true, true, forward, graphics::MaterialKey::CULL_NONE); + transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, args->getViewFrustum().getPosition())); batch.setModelTransform(transform); // Background circle diff --git a/libraries/entities-renderer/src/RenderableGridEntityItem.cpp b/libraries/entities-renderer/src/RenderableGridEntityItem.cpp index 35702c63e4..87b916e41b 100644 --- a/libraries/entities-renderer/src/RenderableGridEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableGridEntityItem.cpp @@ -77,17 +77,17 @@ void GridEntityRenderer::doRender(RenderArgs* args) { color = EntityRenderer::calculatePulseColor(color, _pulseProperties, _created); glm::vec3 dimensions; Transform renderTransform; - bool forward; withReadLock([&] { dimensions = _dimensions; renderTransform = _renderTransform; - forward = _renderLayer != RenderLayer::WORLD || args->_renderMethod == Args::RenderMethod::FORWARD; }); if (!_visible || color.a == 0.0f) { return; } + bool forward = _renderLayer != RenderLayer::WORLD || args->_renderMethod == Args::RenderMethod::FORWARD; + auto batch = args->_batch; Transform transform; diff --git a/libraries/entities-renderer/src/RenderableImageEntityItem.cpp b/libraries/entities-renderer/src/RenderableImageEntityItem.cpp index b9b30ea9c7..878fcad6e4 100644 --- a/libraries/entities-renderer/src/RenderableImageEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableImageEntityItem.cpp @@ -58,7 +58,6 @@ void ImageEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPoint _color = entity->getColor(); _alpha = entity->getAlpha(); _pulseProperties = entity->getPulseProperties(); - _billboardMode = entity->getBillboardMode(); if (!_textureIsLoaded) { emit requestRenderUpdate(); @@ -66,17 +65,6 @@ void ImageEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPoint _textureIsLoaded = _texture && (_texture->isLoaded() || _texture->isFailed()); } -Item::Bound ImageEntityRenderer::getBound() { - auto bound = Parent::getBound(); - if (_billboardMode != BillboardMode::NONE) { - glm::vec3 dimensions = bound.getScale(); - float max = glm::max(dimensions.x, glm::max(dimensions.y, dimensions.z)); - const float SQRT_2 = 1.41421356237f; - bound.setScaleStayCentered(glm::vec3(SQRT_2 * max)); - } - return bound; -} - ShapeKey ImageEntityRenderer::getShapeKey() { auto builder = render::ShapeKey::Builder().withoutCullFace().withDepthBias(); if (isTransparent()) { diff --git a/libraries/entities-renderer/src/RenderableImageEntityItem.h b/libraries/entities-renderer/src/RenderableImageEntityItem.h index 35d60a230f..2359dcc6d1 100644 --- a/libraries/entities-renderer/src/RenderableImageEntityItem.h +++ b/libraries/entities-renderer/src/RenderableImageEntityItem.h @@ -23,7 +23,6 @@ public: ~ImageEntityRenderer(); protected: - Item::Bound getBound() override; ShapeKey getShapeKey() override; bool isTransparent() const override; @@ -44,7 +43,6 @@ private: glm::u8vec3 _color; float _alpha; PulsePropertyGroup _pulseProperties; - BillboardMode _billboardMode; int _geometryId { 0 }; }; diff --git a/libraries/entities-renderer/src/RenderableLineEntityItem.cpp b/libraries/entities-renderer/src/RenderableLineEntityItem.cpp index 6e2be1b41e..1964f1bdda 100644 --- a/libraries/entities-renderer/src/RenderableLineEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableLineEntityItem.cpp @@ -48,6 +48,7 @@ void LineEntityRenderer::doRender(RenderArgs* args) { Transform transform = Transform(); transform.setTranslation(modelTransform.getTranslation()); transform.setRotation(modelTransform.getRotation()); + transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, args->getViewFrustum().getPosition())); batch.setModelTransform(transform); if (_linePoints.size() > 1) { DependencyManager::get()->bindSimpleProgram(batch, false, false, false, false, true, diff --git a/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp b/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp index 3d2e59518c..f7631f3e35 100644 --- a/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp @@ -259,9 +259,9 @@ void MaterialEntityRenderer::doRender(RenderArgs* args) { textureTransform.setRotation(glm::vec3(0, 0, glm::radians(_materialMappingRot))); textureTransform.setScale(glm::vec3(_materialMappingScale, 1)); - Transform renderTransform; + Transform transform; withReadLock([&] { - renderTransform = _renderTransform; + transform = _renderTransform; }); if (!drawMaterial) { @@ -272,7 +272,8 @@ void MaterialEntityRenderer::doRender(RenderArgs* args) { proceduralRender = true; } - batch.setModelTransform(renderTransform); + transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, args->getViewFrustum().getPosition())); + batch.setModelTransform(transform); if (!proceduralRender) { drawMaterial->setTextureTransforms(textureTransform, MaterialMappingMode::UV, true); @@ -287,8 +288,8 @@ void MaterialEntityRenderer::doRender(RenderArgs* args) { auto proceduralDrawMaterial = std::static_pointer_cast(drawMaterial); glm::vec4 outColor = glm::vec4(drawMaterial->getAlbedo(), drawMaterial->getOpacity()); outColor = proceduralDrawMaterial->getColor(outColor); - proceduralDrawMaterial->prepare(batch, renderTransform.getTranslation(), renderTransform.getScale(), - renderTransform.getRotation(), _created, ProceduralProgramKey(outColor.a < 1.0f)); + proceduralDrawMaterial->prepare(batch, transform.getTranslation(), transform.getScale(), + transform.getRotation(), _created, ProceduralProgramKey(outColor.a < 1.0f)); if (render::ShapeKey(args->_globalShapeKey).isWireframe() || _primitiveMode == PrimitiveMode::LINES) { DependencyManager::get()->renderWireSphere(batch, outColor); } else { diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index e53e52d105..91f922c7c7 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -455,7 +455,9 @@ void ParticleEffectEntityRenderer::doRender(RenderArgs* args) { color.finish = EntityRenderer::calculatePulseColor(_particleProperties.getColorFinish(), _pulseProperties, _created); color.spread = EntityRenderer::calculatePulseColor(_particleProperties.getColorSpread(), _pulseProperties, _created); + transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, args->getViewFrustum().getPosition())); batch.setModelTransform(transform); + batch.setUniformBuffer(0, _uniformBuffer); batch.setInputFormat(_vertexFormat); batch.setInputBuffer(0, _particleBuffer, 0, sizeof(GpuParticle)); diff --git a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp index f98a54d594..47b1186c59 100644 --- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp @@ -325,8 +325,10 @@ void PolyLineEntityRenderer::doRender(RenderArgs* args) { buildPipelines(); } - batch.setPipeline(_pipelines[{args->_renderMethod, isTransparent()}]); + transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, args->getViewFrustum().getPosition())); batch.setModelTransform(transform); + + batch.setPipeline(_pipelines[{args->_renderMethod, isTransparent()}]); batch.setResourceTexture(0, texture); batch.draw(gpu::TRIANGLE_STRIP, (gpu::uint32)(2 * _numVertices), 0); } diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp index 06ccdef753..87dbbd068b 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp @@ -221,14 +221,11 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) { graphics::MultiMaterial materials; auto geometryCache = DependencyManager::get(); GeometryCache::Shape geometryShape = geometryCache->getShapeForEntityShape(_shape); - PrimitiveMode primitiveMode; - RenderLayer renderLayer; glm::vec4 outColor; Pipeline pipelineType; + Transform transform; withReadLock([&] { - primitiveMode = _primitiveMode; - renderLayer = _renderLayer; - batch.setModelTransform(_renderTransform); // use a transform with scale, rotation, registration point and translation + transform = _renderTransform; materials = _materials["0"]; pipelineType = getPipelineType(materials); auto& schema = materials.getSchemaBuffer().get(); @@ -241,6 +238,8 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) { return; } + transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, args->getViewFrustum().getPosition())); + if (pipelineType == Pipeline::PROCEDURAL) { auto procedural = std::static_pointer_cast(materials.top().material); outColor = procedural->getColor(outColor); @@ -249,7 +248,7 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) { procedural->prepare(batch, _position, _dimensions, _orientation, _created, ProceduralProgramKey(outColor.a < 1.0f)); }); - if (render::ShapeKey(args->_globalShapeKey).isWireframe() || primitiveMode == PrimitiveMode::LINES) { + if (render::ShapeKey(args->_globalShapeKey).isWireframe() || _primitiveMode == PrimitiveMode::LINES) { geometryCache->renderWireShape(batch, geometryShape, outColor); } else { geometryCache->renderShape(batch, geometryShape, outColor); @@ -258,8 +257,8 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) { // FIXME, support instanced multi-shape rendering using multidraw indirect outColor.a *= _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f; render::ShapePipelinePointer pipeline = geometryCache->getShapePipelinePointer(outColor.a < 1.0f, false, - renderLayer != RenderLayer::WORLD || args->_renderMethod == Args::RenderMethod::FORWARD, materials.top().material->getCullFaceMode()); - if (render::ShapeKey(args->_globalShapeKey).isWireframe() || primitiveMode == PrimitiveMode::LINES) { + _renderLayer != RenderLayer::WORLD || args->_renderMethod == Args::RenderMethod::FORWARD, materials.top().material->getCullFaceMode()); + if (render::ShapeKey(args->_globalShapeKey).isWireframe() || _primitiveMode == PrimitiveMode::LINES) { geometryCache->renderWireShapeInstance(args, batch, geometryShape, outColor, pipeline); } else { geometryCache->renderSolidShapeInstance(args, batch, geometryShape, outColor, pipeline); diff --git a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp index 04ad86c7e1..acbbb57bd4 100644 --- a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp @@ -54,17 +54,6 @@ bool TextEntityRenderer::isTextTransparent() const { }); } -Item::Bound TextEntityRenderer::getBound() { - auto bound = Parent::getBound(); - if (_billboardMode != BillboardMode::NONE) { - glm::vec3 dimensions = bound.getScale(); - float max = glm::max(dimensions.x, glm::max(dimensions.y, dimensions.z)); - const float SQRT_2 = 1.41421356237f; - bound.setScaleStayCentered(glm::vec3(SQRT_2 * max)); - } - return bound; -} - ItemKey TextEntityRenderer::getKey() { return ItemKey::Builder(Parent::getKey()).withMetaCullGroup(); } @@ -111,7 +100,6 @@ void TextEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointe _textAlpha = entity->getTextAlpha(); _backgroundColor = toGlm(entity->getBackgroundColor()); _backgroundAlpha = entity->getBackgroundAlpha(); - _billboardMode = entity->getBillboardMode(); _leftMargin = entity->getLeftMargin(); _rightMargin = entity->getRightMargin(); _topMargin = entity->getTopMargin(); @@ -130,13 +118,9 @@ void TextEntityRenderer::doRender(RenderArgs* args) { gpu::Batch& batch = *args->_batch; glm::vec4 backgroundColor; - Transform modelTransform; - PrimitiveMode primitiveMode; - RenderLayer renderLayer; + Transform transform; withReadLock([&] { - modelTransform = _renderTransform; - primitiveMode = _primitiveMode; - renderLayer = _renderLayer; + transform = _renderTransform; float fadeRatio = _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f; backgroundColor = glm::vec4(_backgroundColor, fadeRatio * _backgroundAlpha); @@ -147,14 +131,14 @@ void TextEntityRenderer::doRender(RenderArgs* args) { return; } - modelTransform.setRotation(EntityItem::getBillboardRotation(modelTransform.getTranslation(), modelTransform.getRotation(), _billboardMode, args->getViewFrustum().getPosition())); - batch.setModelTransform(modelTransform); + transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, args->getViewFrustum().getPosition())); + batch.setModelTransform(transform); auto geometryCache = DependencyManager::get(); // FIXME: we want to use instanced rendering here, but if textAlpha < 1 and backgroundAlpha < 1, the transparency sorting will be wrong //render::ShapePipelinePointer pipeline = geometryCache->getShapePipelinePointer(backgroundColor.a < 1.0f, _unlit, - // renderLayer != RenderLayer::WORLD || args->_renderMethod == Args::RenderMethod::FORWARD); - //if (render::ShapeKey(args->_globalShapeKey).isWireframe() || primitiveMode == PrimitiveMode::LINES) { + // _renderLayer != RenderLayer::WORLD || args->_renderMethod == Args::RenderMethod::FORWARD); + //if (render::ShapeKey(args->_globalShapeKey).isWireframe() || _primitiveMode == PrimitiveMode::LINES) { // geometryCache->renderWireShapeInstance(args, batch, GeometryCache::Quad, backgroundColor, pipeline); //} else { // geometryCache->renderSolidShapeInstance(args, batch, GeometryCache::Quad, backgroundColor, pipeline); @@ -309,21 +293,18 @@ void entities::TextPayload::render(RenderArgs* args) { Transform modelTransform; glm::vec3 dimensions; - BillboardMode billboardMode; glm::vec4 textColor; - bool forward; textRenderable->withReadLock([&] { modelTransform = textRenderable->_renderTransform; dimensions = textRenderable->_dimensions; - billboardMode = textRenderable->_billboardMode; float fadeRatio = textRenderable->_isFading ? Interpolate::calculateFadeRatio(textRenderable->_fadeStartTime) : 1.0f; textColor = glm::vec4(textRenderable->_textColor, fadeRatio * textRenderable->_textAlpha); - - forward = textRenderable->_renderLayer != RenderLayer::WORLD || args->_renderMethod == render::Args::FORWARD; }); + bool forward = textRenderable->_renderLayer != RenderLayer::WORLD || args->_renderMethod == render::Args::FORWARD; + textColor = EntityRenderer::calculatePulseColor(textColor, textRenderable->_pulseProperties, textRenderable->_created); glm::vec3 effectColor = EntityRenderer::calculatePulseColor(textRenderable->_effectColor, textRenderable->_pulseProperties, textRenderable->_created); @@ -331,7 +312,7 @@ void entities::TextPayload::render(RenderArgs* args) { return; } - modelTransform.setRotation(EntityItem::getBillboardRotation(modelTransform.getTranslation(), modelTransform.getRotation(), billboardMode, args->getViewFrustum().getPosition())); + modelTransform.setRotation(EntityItem::getBillboardRotation(modelTransform.getTranslation(), modelTransform.getRotation(), textRenderable->_billboardMode, args->getViewFrustum().getPosition())); float scale = textRenderable->_lineHeight / textRenderer->getFontSize(); modelTransform.postTranslate(glm::vec3(-0.5, 0.5, 1.0f + EPSILON / dimensions.z)); diff --git a/libraries/entities-renderer/src/RenderableTextEntityItem.h b/libraries/entities-renderer/src/RenderableTextEntityItem.h index 51651d98ba..1564c98644 100644 --- a/libraries/entities-renderer/src/RenderableTextEntityItem.h +++ b/libraries/entities-renderer/src/RenderableTextEntityItem.h @@ -33,7 +33,6 @@ public: protected: bool isTransparent() const override; bool isTextTransparent() const; - Item::Bound getBound() override; ShapeKey getShapeKey() override; ItemKey getKey() override; virtual uint32_t metaFetchMetaSubItems(ItemIDs& subItems) const override; @@ -63,7 +62,6 @@ private: float _topMargin; float _bottomMargin; - BillboardMode _billboardMode; glm::vec3 _dimensions; QString _font { "" }; diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index 8b41a85cf8..93d1b9974e 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -167,7 +167,6 @@ void WebEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene _color = entity->getColor(); _alpha = entity->getAlpha(); _pulseProperties = entity->getPulseProperties(); - _billboardMode = entity->getBillboardMode(); if (_contentType == ContentType::NoContent) { _tryingToBuildURL = newSourceURL; @@ -257,17 +256,6 @@ void WebEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene }); } -Item::Bound WebEntityRenderer::getBound() { - auto bound = Parent::getBound(); - if (_billboardMode != BillboardMode::NONE) { - glm::vec3 dimensions = bound.getScale(); - float max = glm::max(dimensions.x, glm::max(dimensions.y, dimensions.z)); - const float SQRT_2 = 1.41421356237f; - bound.setScaleStayCentered(glm::vec3(SQRT_2 * max)); - } - return bound; -} - void WebEntityRenderer::doRender(RenderArgs* args) { PerformanceTimer perfTimer("WebEntityRenderer::render"); withWriteLock([&] { @@ -297,14 +285,12 @@ void WebEntityRenderer::doRender(RenderArgs* args) { gpu::Batch& batch = *args->_batch; glm::vec4 color; Transform transform; - bool forward; bool transparent; withReadLock([&] { float fadeRatio = _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f; color = glm::vec4(toGlm(_color), _alpha * fadeRatio); color = EntityRenderer::calculatePulseColor(color, _pulseProperties, _created); transform = _renderTransform; - forward = _renderLayer != RenderLayer::WORLD || args->_renderMethod == render::Args::FORWARD; transparent = isTransparent(); }); @@ -312,6 +298,8 @@ void WebEntityRenderer::doRender(RenderArgs* args) { return; } + bool forward = _renderLayer != RenderLayer::WORLD || args->_renderMethod == render::Args::FORWARD; + batch.setResourceTexture(0, _texture); transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, args->getViewFrustum().getPosition())); diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.h b/libraries/entities-renderer/src/RenderableWebEntityItem.h index 63ec722811..ee1fa36c02 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.h +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.h @@ -59,7 +59,6 @@ protected: virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) override; virtual void doRender(RenderArgs* args) override; virtual bool isTransparent() const override; - Item::Bound getBound() override; virtual bool wantsHandControllerPointerEvents() const override { return true; } virtual bool wantsKeyboardFocus() const override { return true; } @@ -90,7 +89,6 @@ private: glm::u8vec3 _color; float _alpha { 1.0f }; PulsePropertyGroup _pulseProperties; - BillboardMode _billboardMode; QString _sourceURL; uint16_t _dpi; diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index d7a5e992e1..657d778090 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -107,6 +107,7 @@ EntityPropertyFlags EntityItem::getEntityProperties(EncodeBitstreamParams& param requestedProperties += PROP_PRIMITIVE_MODE; requestedProperties += PROP_IGNORE_PICK_INTERSECTION; requestedProperties += PROP_RENDER_WITH_ZONES; + requestedProperties += PROP_BILLBOARD_MODE; requestedProperties += _grabProperties.getEntityProperties(params); // Physics @@ -303,6 +304,7 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet APPEND_ENTITY_PROPERTY(PROP_PRIMITIVE_MODE, (uint32_t)getPrimitiveMode()); APPEND_ENTITY_PROPERTY(PROP_IGNORE_PICK_INTERSECTION, getIgnorePickIntersection()); APPEND_ENTITY_PROPERTY(PROP_RENDER_WITH_ZONES, getRenderWithZones()); + APPEND_ENTITY_PROPERTY(PROP_BILLBOARD_MODE, (uint32_t)getBillboardMode()); withReadLock([&] { _grabProperties.appendSubclassData(packetData, params, entityTreeElementExtraEncodeData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState); @@ -875,6 +877,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef READ_ENTITY_PROPERTY(PROP_PRIMITIVE_MODE, PrimitiveMode, setPrimitiveMode); READ_ENTITY_PROPERTY(PROP_IGNORE_PICK_INTERSECTION, bool, setIgnorePickIntersection); READ_ENTITY_PROPERTY(PROP_RENDER_WITH_ZONES, QVector, setRenderWithZones); + READ_ENTITY_PROPERTY(PROP_BILLBOARD_MODE, BillboardMode, setBillboardMode); withWriteLock([&] { int bytesFromGrab = _grabProperties.readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args, propertyFlags, overwriteLocalData, @@ -1358,6 +1361,7 @@ EntityItemProperties EntityItem::getProperties(const EntityPropertyFlags& desire COPY_ENTITY_PROPERTY_TO_PROPERTIES(primitiveMode, getPrimitiveMode); COPY_ENTITY_PROPERTY_TO_PROPERTIES(ignorePickIntersection, getIgnorePickIntersection); COPY_ENTITY_PROPERTY_TO_PROPERTIES(renderWithZones, getRenderWithZones); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(billboardMode, getBillboardMode); withReadLock([&] { _grabProperties.getProperties(properties); }); @@ -1508,6 +1512,7 @@ bool EntityItem::setProperties(const EntityItemProperties& properties) { SET_ENTITY_PROPERTY_FROM_PROPERTIES(primitiveMode, setPrimitiveMode); SET_ENTITY_PROPERTY_FROM_PROPERTIES(ignorePickIntersection, setIgnorePickIntersection); SET_ENTITY_PROPERTY_FROM_PROPERTIES(renderWithZones, setRenderWithZones); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(billboardMode, setBillboardMode); withWriteLock([&] { bool grabPropertiesChanged = _grabProperties.setProperties(properties); somethingChanged |= grabPropertiesChanged; @@ -1905,6 +1910,16 @@ void EntityItem::setScaledDimensions(const glm::vec3& value) { setUnscaledDimensions(value / parentScale); } +glm::vec3 EntityItem::getRaycastDimensions() const { + glm::vec3 dimensions = getScaledDimensions(); + if (getBillboardMode() != BillboardMode::NONE) { + float max = glm::max(dimensions.x, glm::max(dimensions.y, dimensions.z)); + const float SQRT_2 = 1.41421356237f; + return glm::vec3(SQRT_2 * max); + } + return dimensions; +} + void EntityItem::setUnscaledDimensions(const glm::vec3& value) { glm::vec3 newDimensions = glm::max(value, glm::vec3(ENTITY_ITEM_MIN_DIMENSION)); const float MIN_SCALE_CHANGE_SQUARED = 1.0e-6f; @@ -3591,4 +3606,17 @@ QVector EntityItem::getRenderWithZones() const { return resultWithReadLock>([&] { return _renderWithZones; }); -} \ No newline at end of file +} + +BillboardMode EntityItem::getBillboardMode() const { + return resultWithReadLock([&] { + return _billboardMode; + }); +} + +void EntityItem::setBillboardMode(BillboardMode value) { + withWriteLock([&] { + _needsRenderUpdate |= _billboardMode != value; + _billboardMode = value; + }); +} diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 2a6952fc0d..69b9abe376 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -203,7 +203,7 @@ public: /// Dimensions in meters (0.0 - TREE_SCALE) virtual glm::vec3 getScaledDimensions() const; virtual void setScaledDimensions(const glm::vec3& value); - virtual glm::vec3 getRaycastDimensions() const { return getScaledDimensions(); } + virtual glm::vec3 getRaycastDimensions() const; glm::vec3 getUnscaledDimensions() const; virtual void setUnscaledDimensions(const glm::vec3& value); @@ -587,6 +587,9 @@ public: bool needsZoneOcclusionUpdate() const { return _needsZoneOcclusionUpdate; } void resetNeedsZoneOcclusionUpdate() { withWriteLock([&] { _needsZoneOcclusionUpdate = false; }); } + void setBillboardMode(BillboardMode value); + BillboardMode getBillboardMode() const; + signals: void spaceUpdate(std::pair data); @@ -778,6 +781,8 @@ protected: QVector _renderWithZones; mutable bool _needsZoneOcclusionUpdate { false }; + BillboardMode _billboardMode { BillboardMode::NONE }; + bool _cullWithParent { false }; mutable bool _needsRenderUpdate { false }; diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index ff55137a03..870ed09515 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -433,6 +433,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_PRIMITIVE_MODE, primitiveMode); CHECK_PROPERTY_CHANGE(PROP_IGNORE_PICK_INTERSECTION, ignorePickIntersection); CHECK_PROPERTY_CHANGE(PROP_RENDER_WITH_ZONES, renderWithZones); + CHECK_PROPERTY_CHANGE(PROP_BILLBOARD_MODE, billboardMode); changedProperties += _grab.getChangedProperties(); // Physics @@ -493,7 +494,6 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_ALPHA, alpha); changedProperties += _pulse.getChangedProperties(); CHECK_PROPERTY_CHANGE(PROP_TEXTURES, textures); - CHECK_PROPERTY_CHANGE(PROP_BILLBOARD_MODE, billboardMode); // Particles CHECK_PROPERTY_CHANGE(PROP_MAX_PARTICLES, maxParticles); @@ -811,6 +811,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * @property {Uuid[]} renderWithZones=[]] - A list of entity IDs representing with which zones this entity should render. * If it is empty, this entity will render normally. Otherwise, this entity will only render if your avatar is within * one of the zones in this list. + * @property {BillboardMode} billboardMode="none" - Whether the entity is billboarded to face the camera. * * @property {Entities.Grab} grab - The entity's grab-related properties. * @@ -1332,7 +1333,6 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * @property {Entities.TextEffect} textEffect="none" - The effect that is applied to the text. * @property {Color} textEffectColor=255,255,255 - The color of the effect. * @property {number} textEffectThickness=0.2 - The magnitude of the text effect, range 0.00.5. - * @property {BillboardMode} billboardMode="none" - Whether the entity is billboarded to face the camera. * @property {boolean} faceCamera - true if billboardMode is "yaw", false * if it isn't. Setting this property to false sets the billboardMode to "none". *

Deprecated: This property is deprecated and will be removed.

@@ -1368,7 +1368,6 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * @property {number} alpha=1 - The opacity of the web surface. * @property {Entities.Pulse} pulse - Color and alpha pulse. *

Deprecated: This property is deprecated and will be removed.

- * @property {BillboardMode} billboardMode="none" - Whether the entity is billboarded to face the camera. * @property {boolean} faceCamera - true if billboardMode is "yaw", false * if it isn't. Setting this property to false sets the billboardMode to "none". *

Deprecated: This property is deprecated and will be removed.

@@ -1487,7 +1486,6 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * @property {number} alpha=1 - The opacity of the image. * @property {Entities.Pulse} pulse - Color and alpha pulse. *

Deprecated: This property is deprecated and will be removed.

- * @property {BillboardMode} billboardMode="none" - Whether the entity is billboarded to face the camera. * @property {boolean} faceCamera - true if billboardMode is "yaw", false * if it isn't. Setting this property to false sets the billboardMode to "none". *

Deprecated: This property is deprecated and will be removed.

@@ -1611,6 +1609,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_PRIMITIVE_MODE, primitiveMode, getPrimitiveModeAsString()); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_IGNORE_PICK_INTERSECTION, ignorePickIntersection); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_RENDER_WITH_ZONES, renderWithZones); + COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_BILLBOARD_MODE, billboardMode, getBillboardModeAsString()); _grab.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties); // Physics @@ -1766,7 +1765,6 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool // Text only if (_type == EntityTypes::Text) { _pulse.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties); - COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_BILLBOARD_MODE, billboardMode, getBillboardModeAsString()); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_TEXT, text); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LINE_HEIGHT, lineHeight); @@ -1816,7 +1814,6 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool COPY_PROPERTY_TO_QSCRIPTVALUE_TYPED(PROP_COLOR, color, u8vec3Color); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ALPHA, alpha); _pulse.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties); - COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_BILLBOARD_MODE, billboardMode, getBillboardModeAsString()); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_SOURCE_URL, sourceUrl); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_DPI, dpi); @@ -1884,7 +1881,6 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool COPY_PROPERTY_TO_QSCRIPTVALUE_TYPED(PROP_COLOR, color, u8vec3Color); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ALPHA, alpha); _pulse.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties); - COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_BILLBOARD_MODE, billboardMode, getBillboardModeAsString()); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_IMAGE_URL, imageURL); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_EMISSIVE, emissive); @@ -2032,6 +2028,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(primitiveMode, PrimitiveMode); COPY_PROPERTY_FROM_QSCRIPTVALUE(ignorePickIntersection, bool, setIgnorePickIntersection); COPY_PROPERTY_FROM_QSCRIPTVALUE(renderWithZones, qVectorQUuid, setRenderWithZones); + COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(billboardMode, BillboardMode); _grab.copyFromScriptValue(object, _defaultSettings); // Physics @@ -2097,7 +2094,6 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool COPY_PROPERTY_FROM_QSCRIPTVALUE(alpha, float, setAlpha); _pulse.copyFromScriptValue(object, _defaultSettings); COPY_PROPERTY_FROM_QSCRIPTVALUE(textures, QString, setTextures); - COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(billboardMode, BillboardMode); // Particles COPY_PROPERTY_FROM_QSCRIPTVALUE(maxParticles, quint32, setMaxParticles); @@ -2329,6 +2325,7 @@ void EntityItemProperties::merge(const EntityItemProperties& other) { COPY_PROPERTY_IF_CHANGED(primitiveMode); COPY_PROPERTY_IF_CHANGED(ignorePickIntersection); COPY_PROPERTY_IF_CHANGED(renderWithZones); + COPY_PROPERTY_IF_CHANGED(billboardMode); _grab.merge(other._grab); // Physics @@ -2389,7 +2386,6 @@ void EntityItemProperties::merge(const EntityItemProperties& other) { COPY_PROPERTY_IF_CHANGED(alpha); _pulse.merge(other._pulse); COPY_PROPERTY_IF_CHANGED(textures); - COPY_PROPERTY_IF_CHANGED(billboardMode); // Particles COPY_PROPERTY_IF_CHANGED(maxParticles); @@ -2625,6 +2621,7 @@ bool EntityItemProperties::getPropertyInfo(const QString& propertyName, EntityPr ADD_PROPERTY_TO_MAP(PROP_PRIMITIVE_MODE, PrimitiveMode, primitiveMode, PrimitiveMode); ADD_PROPERTY_TO_MAP(PROP_IGNORE_PICK_INTERSECTION, IgnorePickIntersection, ignorePickIntersection, bool); ADD_PROPERTY_TO_MAP(PROP_RENDER_WITH_ZONES, RenderWithZones, renderWithZones, QVector); + ADD_PROPERTY_TO_MAP(PROP_BILLBOARD_MODE, BillboardMode, billboardMode, BillboardMode); { // Grab ADD_GROUP_PROPERTY_TO_MAP(PROP_GRAB_GRABBABLE, Grab, grab, Grabbable, grabbable); ADD_GROUP_PROPERTY_TO_MAP(PROP_GRAB_KINEMATIC, Grab, grab, GrabKinematic, grabKinematic); @@ -2721,7 +2718,6 @@ bool EntityItemProperties::getPropertyInfo(const QString& propertyName, EntityPr ADD_GROUP_PROPERTY_TO_MAP(PROP_PULSE_ALPHA_MODE, Pulse, pulse, AlphaMode, alphaMode); } ADD_PROPERTY_TO_MAP(PROP_TEXTURES, Textures, textures, QString); - ADD_PROPERTY_TO_MAP(PROP_BILLBOARD_MODE, BillboardMode, billboardMode, BillboardMode); // Particles ADD_PROPERTY_TO_MAP_WITH_RANGE(PROP_MAX_PARTICLES, MaxParticles, maxParticles, quint32, @@ -3117,6 +3113,7 @@ OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketTy APPEND_ENTITY_PROPERTY(PROP_PRIMITIVE_MODE, (uint32_t)properties.getPrimitiveMode()); APPEND_ENTITY_PROPERTY(PROP_IGNORE_PICK_INTERSECTION, properties.getIgnorePickIntersection()); APPEND_ENTITY_PROPERTY(PROP_RENDER_WITH_ZONES, properties.getRenderWithZones()); + APPEND_ENTITY_PROPERTY(PROP_BILLBOARD_MODE, (uint32_t)properties.getBillboardMode()); _staticGrab.setProperties(properties); _staticGrab.appendToEditPacket(packetData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState); @@ -3249,7 +3246,6 @@ OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketTy _staticPulse.setProperties(properties); _staticPulse.appendToEditPacket(packetData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState); - APPEND_ENTITY_PROPERTY(PROP_BILLBOARD_MODE, (uint32_t)properties.getBillboardMode()); APPEND_ENTITY_PROPERTY(PROP_TEXT, properties.getText()); APPEND_ENTITY_PROPERTY(PROP_LINE_HEIGHT, properties.getLineHeight()); @@ -3321,7 +3317,6 @@ OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketTy _staticPulse.setProperties(properties); _staticPulse.appendToEditPacket(packetData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState); - APPEND_ENTITY_PROPERTY(PROP_BILLBOARD_MODE, (uint32_t)properties.getBillboardMode()); APPEND_ENTITY_PROPERTY(PROP_SOURCE_URL, properties.getSourceUrl()); APPEND_ENTITY_PROPERTY(PROP_DPI, properties.getDPI()); @@ -3384,7 +3379,6 @@ OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketTy _staticPulse.setProperties(properties); _staticPulse.appendToEditPacket(packetData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState); - APPEND_ENTITY_PROPERTY(PROP_BILLBOARD_MODE, (uint32_t)properties.getBillboardMode()); APPEND_ENTITY_PROPERTY(PROP_IMAGE_URL, properties.getImageURL()); APPEND_ENTITY_PROPERTY(PROP_EMISSIVE, properties.getEmissive()); @@ -3610,6 +3604,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_PRIMITIVE_MODE, PrimitiveMode, setPrimitiveMode); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_IGNORE_PICK_INTERSECTION, bool, setIgnorePickIntersection); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_RENDER_WITH_ZONES, QVector, setRenderWithZones); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_BILLBOARD_MODE, BillboardMode, setBillboardMode); properties.getGrab().decodeFromEditPacket(propertyFlags, dataAt, processedBytes); // Physics @@ -3736,7 +3731,6 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int if (properties.getType() == EntityTypes::Text) { properties.getPulse().decodeFromEditPacket(propertyFlags, dataAt, processedBytes); - READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_BILLBOARD_MODE, BillboardMode, setBillboardMode); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_TEXT, QString, setText); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LINE_HEIGHT, float, setLineHeight); @@ -3797,7 +3791,6 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COLOR, u8vec3Color, setColor); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ALPHA, float, setAlpha); properties.getPulse().decodeFromEditPacket(propertyFlags, dataAt, processedBytes); - READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_BILLBOARD_MODE, BillboardMode, setBillboardMode); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SOURCE_URL, QString, setSourceUrl); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_DPI, uint16_t, setDPI); @@ -3857,7 +3850,6 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COLOR, u8vec3Color, setColor); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ALPHA, float, setAlpha); properties.getPulse().decodeFromEditPacket(propertyFlags, dataAt, processedBytes); - READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_BILLBOARD_MODE, BillboardMode, setBillboardMode); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_IMAGE_URL, QString, setImageURL); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_EMISSIVE, bool, setEmissive); @@ -4031,6 +4023,7 @@ void EntityItemProperties::markAllChanged() { _primitiveModeChanged = true; _ignorePickIntersectionChanged = true; _renderWithZonesChanged = true; + _billboardModeChanged = true; _grab.markAllChanged(); // Physics @@ -4084,7 +4077,6 @@ void EntityItemProperties::markAllChanged() { _alphaChanged = true; _pulse.markAllChanged(); _texturesChanged = true; - _billboardModeChanged = true; // Particles _maxParticlesChanged = true; @@ -4439,6 +4431,9 @@ QList EntityItemProperties::listChangedProperties() { if (renderWithZonesChanged()) { out += "renderWithZones"; } + if (billboardModeChanged()) { + out += "billboardMode"; + } getGrab().listChangedProperties(out); // Physics @@ -4574,9 +4569,6 @@ QList EntityItemProperties::listChangedProperties() { if (texturesChanged()) { out += "textures"; } - if (billboardModeChanged()) { - out += "billboardMode"; - } // Particles if (maxParticlesChanged()) { diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index f7fde73430..e431465884 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -197,6 +197,7 @@ public: DEFINE_PROPERTY_REF_ENUM(PROP_PRIMITIVE_MODE, PrimitiveMode, primitiveMode, PrimitiveMode, PrimitiveMode::SOLID); DEFINE_PROPERTY(PROP_IGNORE_PICK_INTERSECTION, IgnorePickIntersection, ignorePickIntersection, bool, false); DEFINE_PROPERTY_REF(PROP_RENDER_WITH_ZONES, RenderWithZones, renderWithZones, QVector, QVector()); + DEFINE_PROPERTY_REF_ENUM(PROP_BILLBOARD_MODE, BillboardMode, billboardMode, BillboardMode, BillboardMode::NONE); DEFINE_PROPERTY_GROUP(Grab, grab, GrabPropertyGroup); // Physics @@ -257,7 +258,6 @@ public: DEFINE_PROPERTY(PROP_ALPHA, Alpha, alpha, float, ENTITY_ITEM_DEFAULT_ALPHA); DEFINE_PROPERTY_GROUP(Pulse, pulse, PulsePropertyGroup); DEFINE_PROPERTY_REF(PROP_TEXTURES, Textures, textures, QString, ""); - DEFINE_PROPERTY_REF_ENUM(PROP_BILLBOARD_MODE, BillboardMode, billboardMode, BillboardMode, BillboardMode::NONE); // Particles DEFINE_PROPERTY(PROP_MAX_PARTICLES, MaxParticles, maxParticles, quint32, particle::DEFAULT_MAX_PARTICLES); diff --git a/libraries/entities/src/EntityPropertyFlags.h b/libraries/entities/src/EntityPropertyFlags.h index 93bb8a89a7..6029d9f5ec 100644 --- a/libraries/entities/src/EntityPropertyFlags.h +++ b/libraries/entities/src/EntityPropertyFlags.h @@ -45,6 +45,7 @@ enum EntityPropertyList { PROP_PRIMITIVE_MODE, PROP_IGNORE_PICK_INTERSECTION, PROP_RENDER_WITH_ZONES, + PROP_BILLBOARD_MODE, // Grab PROP_GRAB_GRABBABLE, PROP_GRAB_KINEMATIC, @@ -122,7 +123,6 @@ enum EntityPropertyList { PROP_PULSE_COLOR_MODE, PROP_PULSE_ALPHA_MODE, PROP_TEXTURES, - PROP_BILLBOARD_MODE, //////////////////////////////////////////////////////////////////////////////////////////////////// // ATTENTION: add new shared EntityItem properties to the list ABOVE this line diff --git a/libraries/entities/src/GizmoEntityItem.cpp b/libraries/entities/src/GizmoEntityItem.cpp index 47c9afd168..7ca1230fb1 100644 --- a/libraries/entities/src/GizmoEntityItem.cpp +++ b/libraries/entities/src/GizmoEntityItem.cpp @@ -111,6 +111,9 @@ bool GizmoEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::quat rotation = getWorldOrientation(); rotation = glm::angleAxis(-(float)M_PI_2, rotation * Vectors::RIGHT) * rotation; glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); + withReadLock([&] { + rotation = EntityItem::getBillboardRotation(position, rotation, _billboardMode, EntityItem::getPrimaryViewFrustumPosition()); + }); if (findRayRectangleIntersection(origin, direction, rotation, position, xyDimensions, distance)) { glm::vec3 hitPosition = origin + (distance * direction); diff --git a/libraries/entities/src/ImageEntityItem.cpp b/libraries/entities/src/ImageEntityItem.cpp index 6a8c457b0a..fb59a85647 100644 --- a/libraries/entities/src/ImageEntityItem.cpp +++ b/libraries/entities/src/ImageEntityItem.cpp @@ -35,7 +35,6 @@ EntityItemProperties ImageEntityItem::getProperties(const EntityPropertyFlags& d withReadLock([&] { _pulseProperties.getProperties(properties); }); - COPY_ENTITY_PROPERTY_TO_PROPERTIES(billboardMode, getBillboardMode); COPY_ENTITY_PROPERTY_TO_PROPERTIES(imageURL, getImageURL); COPY_ENTITY_PROPERTY_TO_PROPERTIES(emissive, getEmissive); @@ -55,7 +54,6 @@ bool ImageEntityItem::setSubClassProperties(const EntityItemProperties& properti somethingChanged |= pulsePropertiesChanged; _needsRenderUpdate |= pulsePropertiesChanged; }); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(billboardMode, setBillboardMode); SET_ENTITY_PROPERTY_FROM_PROPERTIES(imageURL, setImageURL); SET_ENTITY_PROPERTY_FROM_PROPERTIES(emissive, setEmissive); @@ -82,7 +80,6 @@ int ImageEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, bytesRead += bytesFromPulse; dataAt += bytesFromPulse; }); - READ_ENTITY_PROPERTY(PROP_BILLBOARD_MODE, BillboardMode, setBillboardMode); READ_ENTITY_PROPERTY(PROP_IMAGE_URL, QString, setImageURL); READ_ENTITY_PROPERTY(PROP_EMISSIVE, bool, setEmissive); @@ -98,7 +95,6 @@ EntityPropertyFlags ImageEntityItem::getEntityProperties(EncodeBitstreamParams& requestedProperties += PROP_COLOR; requestedProperties += PROP_ALPHA; requestedProperties += _pulseProperties.getEntityProperties(params); - requestedProperties += PROP_BILLBOARD_MODE; requestedProperties += PROP_IMAGE_URL; requestedProperties += PROP_EMISSIVE; @@ -124,7 +120,6 @@ void ImageEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBit _pulseProperties.appendSubclassData(packetData, params, entityTreeElementExtraEncodeData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState); }); - APPEND_ENTITY_PROPERTY(PROP_BILLBOARD_MODE, (uint32_t)getBillboardMode()); APPEND_ENTITY_PROPERTY(PROP_IMAGE_URL, getImageURL()); APPEND_ENTITY_PROPERTY(PROP_EMISSIVE, getEmissive()); @@ -132,16 +127,6 @@ void ImageEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBit APPEND_ENTITY_PROPERTY(PROP_SUB_IMAGE, getSubImage()); } -glm::vec3 ImageEntityItem::getRaycastDimensions() const { - glm::vec3 dimensions = getScaledDimensions(); - if (getBillboardMode() != BillboardMode::NONE) { - float max = glm::max(dimensions.x, glm::max(dimensions.y, dimensions.z)); - const float SQRT_2 = 1.41421356237f; - return glm::vec3(SQRT_2 * max); - } - return dimensions; -} - bool ImageEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, @@ -150,7 +135,9 @@ bool ImageEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec2 xyDimensions(dimensions.x, dimensions.y); glm::quat rotation = getWorldOrientation(); glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); - rotation = EntityItem::getBillboardRotation(position, rotation, _billboardMode, EntityItem::getPrimaryViewFrustumPosition()); + withReadLock([&] { + rotation = EntityItem::getBillboardRotation(position, rotation, _billboardMode, EntityItem::getPrimaryViewFrustumPosition()); + }); if (findRayRectangleIntersection(origin, direction, rotation, position, xyDimensions, distance)) { glm::vec3 forward = rotation * Vectors::FRONT; @@ -174,6 +161,9 @@ bool ImageEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin, glm::vec2 xyDimensions(dimensions.x, dimensions.y); glm::quat rotation = getWorldOrientation(); glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); + withReadLock([&] { + rotation = EntityItem::getBillboardRotation(position, rotation, _billboardMode, EntityItem::getPrimaryViewFrustumPosition()); + }); glm::quat inverseRot = glm::inverse(rotation); glm::vec3 localOrigin = inverseRot * (origin - position); @@ -240,21 +230,6 @@ void ImageEntityItem::setKeepAspectRatio(bool keepAspectRatio) { }); } -BillboardMode ImageEntityItem::getBillboardMode() const { - BillboardMode result; - withReadLock([&] { - result = _billboardMode; - }); - return result; -} - -void ImageEntityItem::setBillboardMode(BillboardMode value) { - withWriteLock([&] { - _needsRenderUpdate |= _billboardMode != value; - _billboardMode = value; - }); -} - QRect ImageEntityItem::getSubImage() const { QRect result; withReadLock([&] { diff --git a/libraries/entities/src/ImageEntityItem.h b/libraries/entities/src/ImageEntityItem.h index bca67dc738..0a90f93f9d 100644 --- a/libraries/entities/src/ImageEntityItem.h +++ b/libraries/entities/src/ImageEntityItem.h @@ -43,7 +43,6 @@ public: EntityPropertyFlags& propertyFlags, bool overwriteLocalData, bool& somethingChanged) override; - glm::vec3 getRaycastDimensions() const override; virtual bool supportsDetailedIntersection() const override { return true; } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, OctreeElementPointer& element, float& distance, @@ -63,9 +62,6 @@ public: void setKeepAspectRatio(bool keepAspectRatio); bool getKeepAspectRatio() const; - void setBillboardMode(BillboardMode value); - BillboardMode getBillboardMode() const; - void setSubImage(const QRect& subImage); QRect getSubImage() const; @@ -81,7 +77,6 @@ protected: glm::u8vec3 _color; float _alpha; PulsePropertyGroup _pulseProperties; - BillboardMode _billboardMode; QString _imageURL; bool _emissive { false }; diff --git a/libraries/entities/src/TextEntityItem.cpp b/libraries/entities/src/TextEntityItem.cpp index a996319463..906e28288b 100644 --- a/libraries/entities/src/TextEntityItem.cpp +++ b/libraries/entities/src/TextEntityItem.cpp @@ -53,7 +53,6 @@ EntityItemProperties TextEntityItem::getProperties(const EntityPropertyFlags& de withReadLock([&] { _pulseProperties.getProperties(properties); }); - COPY_ENTITY_PROPERTY_TO_PROPERTIES(billboardMode, getBillboardMode); COPY_ENTITY_PROPERTY_TO_PROPERTIES(text, getText); COPY_ENTITY_PROPERTY_TO_PROPERTIES(lineHeight, getLineHeight); @@ -81,7 +80,6 @@ bool TextEntityItem::setSubClassProperties(const EntityItemProperties& propertie somethingChanged |= pulsePropertiesChanged; _needsRenderUpdate |= pulsePropertiesChanged; }); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(billboardMode, setBillboardMode); SET_ENTITY_PROPERTY_FROM_PROPERTIES(text, setText); SET_ENTITY_PROPERTY_FROM_PROPERTIES(lineHeight, setLineHeight); @@ -117,7 +115,6 @@ int TextEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, bytesRead += bytesFromPulse; dataAt += bytesFromPulse; }); - READ_ENTITY_PROPERTY(PROP_BILLBOARD_MODE, BillboardMode, setBillboardMode); READ_ENTITY_PROPERTY(PROP_TEXT, QString, setText); READ_ENTITY_PROPERTY(PROP_LINE_HEIGHT, float, setLineHeight); @@ -142,7 +139,6 @@ EntityPropertyFlags TextEntityItem::getEntityProperties(EncodeBitstreamParams& p EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params); requestedProperties += _pulseProperties.getEntityProperties(params); - requestedProperties += PROP_BILLBOARD_MODE; requestedProperties += PROP_TEXT; requestedProperties += PROP_LINE_HEIGHT; @@ -177,7 +173,6 @@ void TextEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBits _pulseProperties.appendSubclassData(packetData, params, entityTreeElementExtraEncodeData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState); }); - APPEND_ENTITY_PROPERTY(PROP_BILLBOARD_MODE, (uint32_t)getBillboardMode()); APPEND_ENTITY_PROPERTY(PROP_TEXT, getText()); APPEND_ENTITY_PROPERTY(PROP_LINE_HEIGHT, getLineHeight()); @@ -196,16 +191,6 @@ void TextEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBits APPEND_ENTITY_PROPERTY(PROP_TEXT_EFFECT_THICKNESS, getTextEffectThickness()); } -glm::vec3 TextEntityItem::getRaycastDimensions() const { - glm::vec3 dimensions = getScaledDimensions(); - if (getBillboardMode() != BillboardMode::NONE) { - float max = glm::max(dimensions.x, glm::max(dimensions.y, dimensions.z)); - const float SQRT_2 = 1.41421356237f; - return glm::vec3(SQRT_2 * max); - } - return dimensions; -} - bool TextEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, @@ -214,7 +199,9 @@ bool TextEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec2 xyDimensions(dimensions.x, dimensions.y); glm::quat rotation = getWorldOrientation(); glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); - rotation = EntityItem::getBillboardRotation(position, rotation, _billboardMode, EntityItem::getPrimaryViewFrustumPosition()); + withReadLock([&] { + rotation = EntityItem::getBillboardRotation(position, rotation, _billboardMode, EntityItem::getPrimaryViewFrustumPosition()); + }); if (findRayRectangleIntersection(origin, direction, rotation, position, xyDimensions, distance)) { glm::vec3 forward = rotation * Vectors::FRONT; @@ -238,6 +225,9 @@ bool TextEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin, c glm::vec2 xyDimensions(dimensions.x, dimensions.y); glm::quat rotation = getWorldOrientation(); glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); + withReadLock([&] { + rotation = EntityItem::getBillboardRotation(position, rotation, _billboardMode, EntityItem::getPrimaryViewFrustumPosition()); + }); glm::quat inverseRot = glm::inverse(rotation); glm::vec3 localOrigin = inverseRot * (origin - position); @@ -339,21 +329,6 @@ float TextEntityItem::getBackgroundAlpha() const { }); } -BillboardMode TextEntityItem::getBillboardMode() const { - BillboardMode result; - withReadLock([&] { - result = _billboardMode; - }); - return result; -} - -void TextEntityItem::setBillboardMode(BillboardMode value) { - withWriteLock([&] { - _needsRenderUpdate |= _billboardMode != value; - _billboardMode = value; - }); -} - void TextEntityItem::setLeftMargin(float value) { withWriteLock([&] { _needsRenderUpdate |= _leftMargin != value; diff --git a/libraries/entities/src/TextEntityItem.h b/libraries/entities/src/TextEntityItem.h index 91496708f6..7827ab1b85 100644 --- a/libraries/entities/src/TextEntityItem.h +++ b/libraries/entities/src/TextEntityItem.h @@ -48,7 +48,6 @@ public: EntityPropertyFlags& propertyFlags, bool overwriteLocalData, bool& somethingChanged) override; - glm::vec3 getRaycastDimensions() const override; virtual bool supportsDetailedIntersection() const override { return true; } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, OctreeElementPointer& element, float& distance, @@ -82,9 +81,6 @@ public: float getBackgroundAlpha() const; void setBackgroundAlpha(float value); - BillboardMode getBillboardMode() const; - void setBillboardMode(BillboardMode value); - static const float DEFAULT_MARGIN; float getLeftMargin() const; void setLeftMargin(float value); @@ -117,8 +113,6 @@ public: PulsePropertyGroup getPulseProperties() const; private: - BillboardMode _billboardMode; - QString _text; float _lineHeight; glm::u8vec3 _textColor; diff --git a/libraries/entities/src/WebEntityItem.cpp b/libraries/entities/src/WebEntityItem.cpp index 61a1ed18c5..f88b40b2ee 100644 --- a/libraries/entities/src/WebEntityItem.cpp +++ b/libraries/entities/src/WebEntityItem.cpp @@ -54,7 +54,6 @@ EntityItemProperties WebEntityItem::getProperties(const EntityPropertyFlags& des withReadLock([&] { _pulseProperties.getProperties(properties); }); - COPY_ENTITY_PROPERTY_TO_PROPERTIES(billboardMode, getBillboardMode); COPY_ENTITY_PROPERTY_TO_PROPERTIES(sourceUrl, getSourceUrl); COPY_ENTITY_PROPERTY_TO_PROPERTIES(dpi, getDPI); @@ -76,7 +75,6 @@ bool WebEntityItem::setSubClassProperties(const EntityItemProperties& properties somethingChanged |= pulsePropertiesChanged; _needsRenderUpdate |= pulsePropertiesChanged; }); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(billboardMode, setBillboardMode); SET_ENTITY_PROPERTY_FROM_PROPERTIES(sourceUrl, setSourceUrl); SET_ENTITY_PROPERTY_FROM_PROPERTIES(dpi, setDPI); @@ -106,7 +104,6 @@ int WebEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, i bytesRead += bytesFromPulse; dataAt += bytesFromPulse; }); - READ_ENTITY_PROPERTY(PROP_BILLBOARD_MODE, BillboardMode, setBillboardMode); READ_ENTITY_PROPERTY(PROP_SOURCE_URL, QString, setSourceUrl); READ_ENTITY_PROPERTY(PROP_DPI, uint16_t, setDPI); @@ -124,7 +121,6 @@ EntityPropertyFlags WebEntityItem::getEntityProperties(EncodeBitstreamParams& pa requestedProperties += PROP_COLOR; requestedProperties += PROP_ALPHA; requestedProperties += _pulseProperties.getEntityProperties(params); - requestedProperties += PROP_BILLBOARD_MODE; requestedProperties += PROP_SOURCE_URL; requestedProperties += PROP_DPI; @@ -151,7 +147,6 @@ void WebEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBitst _pulseProperties.appendSubclassData(packetData, params, entityTreeElementExtraEncodeData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState); }); - APPEND_ENTITY_PROPERTY(PROP_BILLBOARD_MODE, (uint32_t)getBillboardMode()); APPEND_ENTITY_PROPERTY(PROP_SOURCE_URL, getSourceUrl()); APPEND_ENTITY_PROPERTY(PROP_DPI, getDPI()); @@ -162,16 +157,6 @@ void WebEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBitst APPEND_ENTITY_PROPERTY(PROP_WEB_USE_BACKGROUND, getUseBackground()); } -glm::vec3 WebEntityItem::getRaycastDimensions() const { - glm::vec3 dimensions = getScaledDimensions(); - if (getBillboardMode() != BillboardMode::NONE) { - float max = glm::max(dimensions.x, glm::max(dimensions.y, dimensions.z)); - const float SQRT_2 = 1.41421356237f; - return glm::vec3(SQRT_2 * max); - } - return dimensions; -} - bool WebEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, @@ -180,7 +165,9 @@ bool WebEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const g glm::vec2 xyDimensions(dimensions.x, dimensions.y); glm::quat rotation = getWorldOrientation(); glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); - rotation = EntityItem::getBillboardRotation(position, rotation, _billboardMode, EntityItem::getPrimaryViewFrustumPosition()); + withReadLock([&] { + rotation = EntityItem::getBillboardRotation(position, rotation, _billboardMode, EntityItem::getPrimaryViewFrustumPosition()); + }); if (findRayRectangleIntersection(origin, direction, rotation, position, xyDimensions, distance)) { glm::vec3 forward = rotation * Vectors::FRONT; @@ -205,6 +192,9 @@ bool WebEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin, co glm::vec2 xyDimensions(dimensions.x, dimensions.y); glm::quat rotation = getWorldOrientation(); glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); + withReadLock([&] { + rotation = EntityItem::getBillboardRotation(position, rotation, _billboardMode, EntityItem::getPrimaryViewFrustumPosition()); + }); glm::quat inverseRot = glm::inverse(rotation); glm::vec3 localOrigin = inverseRot * (origin - position); @@ -259,19 +249,6 @@ float WebEntityItem::getAlpha() const { }); } -BillboardMode WebEntityItem::getBillboardMode() const { - return resultWithReadLock([&] { - return _billboardMode; - }); -} - -void WebEntityItem::setBillboardMode(BillboardMode value) { - withWriteLock([&] { - _needsRenderUpdate |= _billboardMode != value; - _billboardMode = value; - }); -} - void WebEntityItem::setSourceUrl(const QString& value) { withWriteLock([&] { _needsRenderUpdate |= _sourceUrl != value; diff --git a/libraries/entities/src/WebEntityItem.h b/libraries/entities/src/WebEntityItem.h index 4b39261bfb..0a3db2ea78 100644 --- a/libraries/entities/src/WebEntityItem.h +++ b/libraries/entities/src/WebEntityItem.h @@ -45,7 +45,6 @@ public: EntityPropertyFlags& propertyFlags, bool overwriteLocalData, bool& somethingChanged) override; - glm::vec3 getRaycastDimensions() const override; virtual bool supportsDetailedIntersection() const override { return true; } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, OctreeElementPointer& element, float& distance, @@ -62,9 +61,6 @@ public: float getAlpha() const; void setAlpha(float alpha); - void setBillboardMode(BillboardMode value); - BillboardMode getBillboardMode() const; - static const QString DEFAULT_SOURCE_URL; void setSourceUrl(const QString& value); QString getSourceUrl() const; @@ -96,7 +92,6 @@ protected: glm::u8vec3 _color; float _alpha { 1.0f }; PulsePropertyGroup _pulseProperties; - BillboardMode _billboardMode; QString _sourceUrl; uint16_t _dpi; diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index fc74f4459c..94fe2ca71f 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -283,6 +283,7 @@ enum class EntityVersion : PacketVersion { ZoneOcclusion, ModelBlendshapes, TransparentWeb, + AllBillboardMode, // Add new versions above here NUM_PACKET_TYPE, From 030524c3ee061fef1d683e08049846ea31af471d Mon Sep 17 00:00:00 2001 From: HifiExperiments Date: Sun, 3 Jan 2021 21:03:11 -0800 Subject: [PATCH 07/33] CR and actually send property over wire --- libraries/entities/src/EntityItemProperties.cpp | 4 ++++ libraries/networking/src/udt/PacketHeaders.h | 1 + libraries/render-utils/src/Model.cpp | 2 +- 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 06e981238d..7fa1d11d3b 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -1003,6 +1003,8 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * @property {string} blendshapeCoefficients - A JSON string of a map of blendshape names to values. Only stores set values. * When editing this property, only coefficients that you are editing will change; it will not explicitly reset other * coefficients. + * @property {boolean} useOriginalPivot=false - If false, the model will be centered based on its content, ignoring any offset + * in the model itself. If true, the model will respect its original offset. * @property {string} textures="" - A JSON string of texture name, URL pairs used when rendering the model in place of the * model's original textures. Use a texture name from the originalTextures property to override that texture. * Only the texture names and URLs to be overridden need be specified; original textures are used where there are no @@ -3236,6 +3238,7 @@ OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketTy APPEND_ENTITY_PROPERTY(PROP_RELAY_PARENT_JOINTS, properties.getRelayParentJoints()); APPEND_ENTITY_PROPERTY(PROP_GROUP_CULLED, properties.getGroupCulled()); APPEND_ENTITY_PROPERTY(PROP_BLENDSHAPE_COEFFICIENTS, properties.getBlendshapeCoefficients()); + APPEND_ENTITY_PROPERTY(PROP_USE_ORIGINAL_PIVOT, properties.getUseOriginalPivot()); _staticAnimation.setProperties(properties); _staticAnimation.appendToEditPacket(packetData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState); @@ -3725,6 +3728,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_RELAY_PARENT_JOINTS, bool, setRelayParentJoints); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_GROUP_CULLED, bool, setGroupCulled); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_BLENDSHAPE_COEFFICIENTS, QString, setBlendshapeCoefficients); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_USE_ORIGINAL_PIVOT, bool, setUseOriginalPivot); properties.getAnimation().decodeFromEditPacket(propertyFlags, dataAt, processedBytes); } diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index fc74f4459c..5c98cf6fdd 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -283,6 +283,7 @@ enum class EntityVersion : PacketVersion { ZoneOcclusion, ModelBlendshapes, TransparentWeb, + UseOriginalPivot, // Add new versions above here NUM_PACKET_TYPE, diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 44dbc00f70..521214354e 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -1199,7 +1199,7 @@ glm::vec3 Model::getNaturalDimensions() const { Extents Model::getMeshExtents() const { Extents extents = getUnscaledMeshExtents(); - return { extents.minimum * _scale, extents.maximum * _scale}; + return { extents.minimum * _scale, extents.maximum * _scale }; } Extents Model::getUnscaledMeshExtents() const { From 1ccdfe37a6dbfabee5dc82ba5bb3788480aad8ed Mon Sep 17 00:00:00 2001 From: HifiExperiments <53453710+HifiExperiments@users.noreply.github.com> Date: Mon, 4 Jan 2021 12:14:35 -0800 Subject: [PATCH 08/33] Update libraries/entities/src/EntityItemProperties.cpp Co-authored-by: David Rowe --- libraries/entities/src/EntityItemProperties.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 7fa1d11d3b..b09c2b3938 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -1003,8 +1003,8 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * @property {string} blendshapeCoefficients - A JSON string of a map of blendshape names to values. Only stores set values. * When editing this property, only coefficients that you are editing will change; it will not explicitly reset other * coefficients. - * @property {boolean} useOriginalPivot=false - If false, the model will be centered based on its content, ignoring any offset - * in the model itself. If true, the model will respect its original offset. + * @property {boolean} useOriginalPivot=false - If false, the model will be centered based on its content, + * ignoring any offset in the model itself. If true, the model will respect its original offset. * @property {string} textures="" - A JSON string of texture name, URL pairs used when rendering the model in place of the * model's original textures. Use a texture name from the originalTextures property to override that texture. * Only the texture names and URLs to be overridden need be specified; original textures are used where there are no From bef0c79b677ab4287068465383a7f918873396e1 Mon Sep 17 00:00:00 2001 From: HifiExperiments Date: Sun, 10 Jan 2021 16:03:04 -0800 Subject: [PATCH 09/33] billboard mode working on most entity types --- interface/src/Application.cpp | 15 ++++- .../src/RenderableGizmoEntityItem.cpp | 3 +- .../src/RenderableGridEntityItem.cpp | 2 + .../src/RenderableImageEntityItem.cpp | 3 +- .../src/RenderableLineEntityItem.cpp | 4 +- .../src/RenderableMaterialEntityItem.cpp | 3 +- .../RenderableParticleEffectEntityItem.cpp | 1 - .../src/RenderablePolyLineEntityItem.cpp | 3 +- .../src/RenderablePolyVoxEntityItem.cpp | 64 +++---------------- .../src/RenderablePolyVoxEntityItem.h | 10 +-- .../src/RenderableShapeEntityItem.cpp | 7 +- .../src/RenderableTextEntityItem.cpp | 6 +- .../src/RenderableWebEntityItem.cpp | 3 +- libraries/entities/src/EntityItem.cpp | 2 +- libraries/entities/src/EntityItem.h | 6 +- libraries/entities/src/EntityTreeElement.cpp | 30 ++++++--- libraries/entities/src/GizmoEntityItem.cpp | 9 ++- libraries/entities/src/GridEntityItem.cpp | 54 ++++++++++++++++ libraries/entities/src/GridEntityItem.h | 10 +++ libraries/entities/src/ImageEntityItem.cpp | 8 +-- libraries/entities/src/ImageEntityItem.h | 2 +- libraries/entities/src/PolyVoxEntityItem.cpp | 18 ++++-- libraries/entities/src/PolyVoxEntityItem.h | 4 +- libraries/entities/src/ShapeEntityItem.cpp | 30 +++++++-- libraries/entities/src/TextEntityItem.cpp | 8 +-- libraries/entities/src/TextEntityItem.h | 2 +- libraries/entities/src/WebEntityItem.cpp | 8 +-- libraries/entities/src/WebEntityItem.h | 2 +- 28 files changed, 188 insertions(+), 129 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index cc46d8591b..c1911151d8 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2455,13 +2455,18 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo DependencyManager::get()->setPrecisionPicking(rayPickID, value); }); - EntityItem::setBillboardRotationOperator([](const glm::vec3& position, const glm::quat& rotation, BillboardMode billboardMode, const glm::vec3& frustumPos) { + EntityItem::setBillboardRotationOperator([](const glm::vec3& position, const glm::quat& rotation, BillboardMode billboardMode, const glm::vec3& frustumPos, bool rotate90x) { + const glm::quat ROTATE_90X = glm::angleAxis(-(float)M_PI_2, Vectors::RIGHT); if (billboardMode == BillboardMode::YAW) { //rotate about vertical to face the camera glm::vec3 dPosition = frustumPos - position; // If x and z are 0, atan(x, z) is undefined, so default to 0 degrees float yawRotation = dPosition.x == 0.0f && dPosition.z == 0.0f ? 0.0f : glm::atan(dPosition.x, dPosition.z); - return glm::quat(glm::vec3(0.0f, yawRotation, 0.0f)); + glm::quat result = glm::quat(glm::vec3(0.0f, yawRotation, 0.0f)); + if (rotate90x) { + result *= ROTATE_90X; + } + return result; } else if (billboardMode == BillboardMode::FULL) { // use the referencial from the avatar, y isn't always up glm::vec3 avatarUP = DependencyManager::get()->getMyAvatar()->getWorldOrientation() * Vectors::UP; @@ -2470,7 +2475,11 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo // make sure s is not NaN for any component if (glm::length2(s) > 0.0f) { - return glm::conjugate(glm::toQuat(glm::lookAt(frustumPos, position, avatarUP))); + glm::quat result = glm::conjugate(glm::toQuat(glm::lookAt(frustumPos, position, avatarUP))); + if (rotate90x) { + result *= ROTATE_90X; + } + return result; } } return rotation; diff --git a/libraries/entities-renderer/src/RenderableGizmoEntityItem.cpp b/libraries/entities-renderer/src/RenderableGizmoEntityItem.cpp index caf5bde729..368aa59b5e 100644 --- a/libraries/entities-renderer/src/RenderableGizmoEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableGizmoEntityItem.cpp @@ -254,7 +254,8 @@ void GizmoEntityRenderer::doRender(RenderArgs* args) { geometryCache->bindSimpleProgram(batch, false, transparent, wireframe, true, true, forward, graphics::MaterialKey::CULL_NONE); - transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, args->getViewFrustum().getPosition())); + transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, + args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? EntityItem::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition(), true)); batch.setModelTransform(transform); // Background circle diff --git a/libraries/entities-renderer/src/RenderableGridEntityItem.cpp b/libraries/entities-renderer/src/RenderableGridEntityItem.cpp index 87b916e41b..777ddda934 100644 --- a/libraries/entities-renderer/src/RenderableGridEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableGridEntityItem.cpp @@ -103,6 +103,8 @@ void GridEntityRenderer::doRender(RenderArgs* args) { } else { transform.setTranslation(renderTransform.getTranslation()); } + transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, + args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? EntityItem::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition())); batch->setModelTransform(transform); auto minCorner = glm::vec2(-0.5f, -0.5f); diff --git a/libraries/entities-renderer/src/RenderableImageEntityItem.cpp b/libraries/entities-renderer/src/RenderableImageEntityItem.cpp index 878fcad6e4..34f48e25f6 100644 --- a/libraries/entities-renderer/src/RenderableImageEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableImageEntityItem.cpp @@ -97,7 +97,8 @@ void ImageEntityRenderer::doRender(RenderArgs* args) { Q_ASSERT(args->_batch); gpu::Batch* batch = args->_batch; - transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, args->getViewFrustum().getPosition())); + transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, + args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? EntityItem::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition())); batch->setModelTransform(transform); batch->setResourceTexture(0, _texture->getGPUTexture()); diff --git a/libraries/entities-renderer/src/RenderableLineEntityItem.cpp b/libraries/entities-renderer/src/RenderableLineEntityItem.cpp index 1964f1bdda..f8a3230f86 100644 --- a/libraries/entities-renderer/src/RenderableLineEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableLineEntityItem.cpp @@ -47,8 +47,8 @@ void LineEntityRenderer::doRender(RenderArgs* args) { const auto& modelTransform = getModelTransform(); Transform transform = Transform(); transform.setTranslation(modelTransform.getTranslation()); - transform.setRotation(modelTransform.getRotation()); - transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, args->getViewFrustum().getPosition())); + transform.setRotation(EntityItem::getBillboardRotation(modelTransform.getTranslation(), modelTransform.getRotation(), _billboardMode, + args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? EntityItem::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition())); batch.setModelTransform(transform); if (_linePoints.size() > 1) { DependencyManager::get()->bindSimpleProgram(batch, false, false, false, false, true, diff --git a/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp b/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp index f7631f3e35..ac28dd517c 100644 --- a/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp @@ -272,7 +272,8 @@ void MaterialEntityRenderer::doRender(RenderArgs* args) { proceduralRender = true; } - transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, args->getViewFrustum().getPosition())); + transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, + args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? EntityItem::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition())); batch.setModelTransform(transform); if (!proceduralRender) { diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index 91f922c7c7..4fe6bc8f93 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -455,7 +455,6 @@ void ParticleEffectEntityRenderer::doRender(RenderArgs* args) { color.finish = EntityRenderer::calculatePulseColor(_particleProperties.getColorFinish(), _pulseProperties, _created); color.spread = EntityRenderer::calculatePulseColor(_particleProperties.getColorSpread(), _pulseProperties, _created); - transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, args->getViewFrustum().getPosition())); batch.setModelTransform(transform); batch.setUniformBuffer(0, _uniformBuffer); diff --git a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp index 47b1186c59..e10e7a845c 100644 --- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp @@ -325,7 +325,8 @@ void PolyLineEntityRenderer::doRender(RenderArgs* args) { buildPipelines(); } - transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, args->getViewFrustum().getPosition())); + transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, + args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? EntityItem::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition())); batch.setModelTransform(transform); batch.setPipeline(_pipelines[{args->_renderMethod, isTransparent()}]); diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index f0a6684654..f17f775493 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -238,53 +238,6 @@ void RenderablePolyVoxEntityItem::setVoxelSurfaceStyle(PolyVoxSurfaceStyle voxel startUpdates(); } -glm::vec3 RenderablePolyVoxEntityItem::getSurfacePositionAdjustment() const { - glm::vec3 result; - withReadLock([&] { - glm::vec3 scale = getScaledDimensions() / _voxelVolumeSize; // meters / voxel-units - if (isEdged(_voxelSurfaceStyle)) { - result = scale / -2.0f; - } - return scale / 2.0f; - }); - return result; -} - -glm::mat4 RenderablePolyVoxEntityItem::voxelToLocalMatrix() const { - glm::vec3 voxelVolumeSize; - withReadLock([&] { - voxelVolumeSize = _voxelVolumeSize; - }); - - glm::vec3 dimensions = getScaledDimensions(); - glm::vec3 scale = dimensions / voxelVolumeSize; // meters / voxel-units - bool success; // TODO -- Does this actually have to happen in world space? - glm::vec3 center = getCenterPosition(success); // this handles registrationPoint changes - glm::vec3 position = getWorldPosition(success); - glm::vec3 positionToCenter = center - position; - - positionToCenter -= dimensions * Vectors::HALF - getSurfacePositionAdjustment(); - glm::mat4 centerToCorner = glm::translate(glm::mat4(), positionToCenter); - glm::mat4 scaled = glm::scale(centerToCorner, scale); - return scaled; -} - -glm::mat4 RenderablePolyVoxEntityItem::localToVoxelMatrix() const { - glm::mat4 localToModelMatrix = glm::inverse(voxelToLocalMatrix()); - return localToModelMatrix; -} - -glm::mat4 RenderablePolyVoxEntityItem::voxelToWorldMatrix() const { - glm::mat4 rotation = glm::mat4_cast(getWorldOrientation()); - glm::mat4 translation = glm::translate(getWorldPosition()); - return translation * rotation * voxelToLocalMatrix(); -} - -glm::mat4 RenderablePolyVoxEntityItem::worldToVoxelMatrix() const { - glm::mat4 worldToModelMatrix = glm::inverse(voxelToWorldMatrix()); - return worldToModelMatrix; -} - bool RenderablePolyVoxEntityItem::setVoxel(const ivec3& v, uint8_t toValue) { if (_locked) { return false; @@ -582,7 +535,7 @@ bool RenderablePolyVoxEntityItem::findDetailedRayIntersection(const glm::vec3& o return true; } - glm::mat4 wtvMatrix = worldToVoxelMatrix(); + glm::mat4 wtvMatrix = worldToVoxelMatrix(true); glm::vec3 normDirection = glm::normalize(direction); // the PolyVox ray intersection code requires a near and far point. @@ -623,7 +576,7 @@ bool RenderablePolyVoxEntityItem::findDetailedParabolaIntersection(const glm::ve return true; } - glm::mat4 wtvMatrix = worldToVoxelMatrix(); + glm::mat4 wtvMatrix = worldToVoxelMatrix(true); glm::vec4 originInVoxel = wtvMatrix * glm::vec4(origin, 1.0f); glm::vec4 velocityInVoxel = wtvMatrix * glm::vec4(velocity, 0.0f); glm::vec4 accelerationInVoxel = wtvMatrix * glm::vec4(acceleration, 0.0f); @@ -1803,7 +1756,7 @@ ShapeKey PolyVoxEntityRenderer::getShapeKey() { bool PolyVoxEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const { if (resultWithReadLock([&] { - if (entity->voxelToWorldMatrix() != _lastVoxelToWorldMatrix) { + if (entity->voxelToLocalMatrix() != _lastVoxelToLocalMatrix) { return true; } @@ -1829,7 +1782,9 @@ void PolyVoxEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& s } void PolyVoxEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) { - _lastVoxelToWorldMatrix = entity->voxelToWorldMatrix(); + _lastVoxelToLocalMatrix = entity->voxelToLocalMatrix(); + _position = entity->getWorldPosition(); + _orientation = entity->getWorldOrientation(); _lastVoxelVolumeSize = entity->getVoxelVolumeSize(); _params->setSubData(0, vec4(_lastVoxelVolumeSize, 0.0)); graphics::MeshPointer newMesh; @@ -1862,17 +1817,18 @@ void PolyVoxEntityRenderer::doRender(RenderArgs* args) { return; } - PerformanceTimer perfTimer("RenderablePolyVoxEntityItem::render"); gpu::Batch& batch = *args->_batch; - Transform transform(_lastVoxelToWorldMatrix); + glm::mat4 rotation = glm::mat4_cast(EntityItem::getBillboardRotation(_position, _orientation, _billboardMode, + args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? EntityItem::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition())); + Transform transform(glm::translate(_position) * rotation * _lastVoxelToLocalMatrix); batch.setModelTransform(transform); + batch.setInputFormat(_vertexFormat); batch.setInputBuffer(gpu::Stream::POSITION, _mesh->getVertexBuffer()._buffer, 0, sizeof(PolyVox::PositionMaterialNormal)); - // TODO -- should we be setting this? // batch.setInputBuffer(gpu::Stream::NORMAL, mesh->getVertexBuffer()._buffer, // 12, diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h index 825b4429cd..d4bcc4d19f 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h @@ -83,12 +83,6 @@ public: virtual void setVoxelVolumeSize(const glm::vec3& voxelVolumeSize) override; virtual void setVoxelSurfaceStyle(PolyVoxSurfaceStyle voxelSurfaceStyle) override; - glm::vec3 getSurfacePositionAdjustment() const; - glm::mat4 voxelToWorldMatrix() const; - glm::mat4 worldToVoxelMatrix() const; - glm::mat4 voxelToLocalMatrix() const; - glm::mat4 localToVoxelMatrix() const; - virtual ShapeType getShapeType() const override; virtual bool isReadyToComputeShape() const override; virtual void computeShapeInfo(ShapeInfo& info) override; @@ -226,7 +220,9 @@ private: gpu::BufferPointer _params; std::array _xyzTextures; glm::vec3 _lastVoxelVolumeSize; - glm::mat4 _lastVoxelToWorldMatrix; + glm::mat4 _lastVoxelToLocalMatrix; + glm::vec3 _position; + glm::quat _orientation; PolyVoxEntityItem::PolyVoxSurfaceStyle _lastSurfaceStyle { PolyVoxEntityItem::SURFACE_MARCHING_CUBES }; std::array _xyzTextureUrls; }; diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp index 87dbbd068b..f1c73dbeed 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp @@ -55,6 +55,7 @@ void ShapeEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce void* key = (void*)this; 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(); @@ -69,7 +70,6 @@ void ShapeEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce } void ShapeEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) { - _shape = entity->getShape(); _pulseProperties = entity->getPulseProperties(); bool materialChanged = false; @@ -238,7 +238,10 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) { return; } - transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, args->getViewFrustum().getPosition())); + transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, + args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? EntityItem::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition(), + _shape < entity::Shape::Cube || _shape > entity::Shape::Icosahedron)); + batch.setModelTransform(transform); if (pipelineType == Pipeline::PROCEDURAL) { auto procedural = std::static_pointer_cast(materials.top().material); diff --git a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp index acbbb57bd4..2be84110d6 100644 --- a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp @@ -131,7 +131,8 @@ void TextEntityRenderer::doRender(RenderArgs* args) { return; } - transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, args->getViewFrustum().getPosition())); + transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, + args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? EntityItem::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition())); batch.setModelTransform(transform); auto geometryCache = DependencyManager::get(); @@ -312,7 +313,8 @@ void entities::TextPayload::render(RenderArgs* args) { return; } - modelTransform.setRotation(EntityItem::getBillboardRotation(modelTransform.getTranslation(), modelTransform.getRotation(), textRenderable->_billboardMode, args->getViewFrustum().getPosition())); + modelTransform.setRotation(EntityItem::getBillboardRotation(modelTransform.getTranslation(), modelTransform.getRotation(), textRenderable->_billboardMode, + args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? EntityItem::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition())); float scale = textRenderable->_lineHeight / textRenderer->getFontSize(); modelTransform.postTranslate(glm::vec3(-0.5, 0.5, 1.0f + EPSILON / dimensions.z)); diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index 93d1b9974e..6c6215f69d 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -302,7 +302,8 @@ void WebEntityRenderer::doRender(RenderArgs* args) { batch.setResourceTexture(0, _texture); - transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, args->getViewFrustum().getPosition())); + transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, + args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? EntityItem::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition())); batch.setModelTransform(transform); // Turn off jitter for these entities diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 657d778090..f33838d146 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -51,7 +51,7 @@ int EntityItem::_maxActionsDataSize = 800; quint64 EntityItem::_rememberDeletedActionTime = 20 * USECS_PER_SECOND; QString EntityItem::_marketplacePublicKey; -std::function EntityItem::_getBillboardRotationOperator = [](const glm::vec3&, const glm::quat& rotation, BillboardMode, const glm::vec3&) { return rotation; }; +std::function EntityItem::_getBillboardRotationOperator = [](const glm::vec3&, const glm::quat& rotation, BillboardMode, const glm::vec3&, bool) { return rotation; }; std::function EntityItem::_getPrimaryViewFrustumPositionOperator = []() { return glm::vec3(0.0f); }; EntityItem::EntityItem(const EntityItemID& entityItemID) : diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 69b9abe376..ad3429c0b6 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -572,8 +572,8 @@ public: virtual void removeGrab(GrabPointer grab) override; virtual void disableGrab(GrabPointer grab) override; - static void setBillboardRotationOperator(std::function getBillboardRotationOperator) { _getBillboardRotationOperator = getBillboardRotationOperator; } - static glm::quat getBillboardRotation(const glm::vec3& position, const glm::quat& rotation, BillboardMode billboardMode, const glm::vec3& frustumPos) { return _getBillboardRotationOperator(position, rotation, billboardMode, frustumPos); } + static void setBillboardRotationOperator(std::function getBillboardRotationOperator) { _getBillboardRotationOperator = getBillboardRotationOperator; } + static glm::quat getBillboardRotation(const glm::vec3& position, const glm::quat& rotation, BillboardMode billboardMode, const glm::vec3& frustumPos, bool rotate90x = false) { return _getBillboardRotationOperator(position, rotation, billboardMode, frustumPos, rotate90x); } static void setPrimaryViewFrustumPositionOperator(std::function getPrimaryViewFrustumPositionOperator) { _getPrimaryViewFrustumPositionOperator = getPrimaryViewFrustumPositionOperator; } static glm::vec3 getPrimaryViewFrustumPosition() { return _getPrimaryViewFrustumPositionOperator(); } @@ -788,7 +788,7 @@ protected: mutable bool _needsRenderUpdate { false }; private: - static std::function _getBillboardRotationOperator; + static std::function _getBillboardRotationOperator; static std::function _getPrimaryViewFrustumPositionOperator; }; diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index 9af0bbfdb6..6e446630ee 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -219,8 +219,10 @@ EntityItemID EntityTreeElement::evalDetailedRayIntersection(const glm::vec3& ori } // extents is the entity relative, scaled, centered extents of the entity - glm::mat4 rotation = glm::mat4_cast(entity->getWorldOrientation()); - glm::mat4 translation = glm::translate(entity->getWorldPosition()); + glm::vec3 position = entity->getWorldPosition(); + glm::mat4 translation = glm::translate(position); + glm::quat orientation = entity->getWorldOrientation(); + glm::mat4 rotation = glm::mat4_cast(EntityItem::getBillboardRotation(position, orientation, entity->getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition())); glm::mat4 entityToWorldMatrix = translation * rotation; glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix); @@ -368,8 +370,10 @@ EntityItemID EntityTreeElement::evalDetailedParabolaIntersection(const glm::vec3 } // extents is the entity relative, scaled, centered extents of the entity - glm::mat4 rotation = glm::mat4_cast(entity->getWorldOrientation()); - glm::mat4 translation = glm::translate(entity->getWorldPosition()); + glm::vec3 position = entity->getWorldPosition(); + glm::mat4 translation = glm::translate(position); + glm::quat orientation = entity->getWorldOrientation(); + glm::mat4 rotation = glm::mat4_cast(EntityItem::getBillboardRotation(position, orientation, entity->getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition())); glm::mat4 entityToWorldMatrix = translation * rotation; glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix); @@ -472,8 +476,10 @@ void EntityTreeElement::evalEntitiesInSphere(const glm::vec3& position, float ra } else { // determine the worldToEntityMatrix that doesn't include scale because // we're going to use the registration aware aa box in the entity frame - glm::mat4 rotation = glm::mat4_cast(entity->getWorldOrientation()); - glm::mat4 translation = glm::translate(entity->getWorldPosition()); + glm::vec3 position = entity->getWorldPosition(); + glm::mat4 translation = glm::translate(position); + glm::quat orientation = entity->getWorldOrientation(); + glm::mat4 rotation = glm::mat4_cast(EntityItem::getBillboardRotation(position, orientation, entity->getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition())); glm::mat4 entityToWorldMatrix = translation * rotation; glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix); @@ -526,8 +532,10 @@ void EntityTreeElement::evalEntitiesInSphereWithType(const glm::vec3& position, } else { // determine the worldToEntityMatrix that doesn't include scale because // we're going to use the registration aware aa box in the entity frame - glm::mat4 rotation = glm::mat4_cast(entity->getWorldOrientation()); - glm::mat4 translation = glm::translate(entity->getWorldPosition()); + glm::vec3 position = entity->getWorldPosition(); + glm::mat4 translation = glm::translate(position); + glm::quat orientation = entity->getWorldOrientation(); + glm::mat4 rotation = glm::mat4_cast(EntityItem::getBillboardRotation(position, orientation, entity->getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition())); glm::mat4 entityToWorldMatrix = translation * rotation; glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix); @@ -585,8 +593,10 @@ void EntityTreeElement::evalEntitiesInSphereWithName(const glm::vec3& position, } else { // determine the worldToEntityMatrix that doesn't include scale because // we're going to use the registration aware aa box in the entity frame - glm::mat4 rotation = glm::mat4_cast(entity->getWorldOrientation()); - glm::mat4 translation = glm::translate(entity->getWorldPosition()); + glm::vec3 position = entity->getWorldPosition(); + glm::mat4 translation = glm::translate(position); + glm::quat orientation = entity->getWorldOrientation(); + glm::mat4 rotation = glm::mat4_cast(EntityItem::getBillboardRotation(position, orientation, entity->getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition())); 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 7ca1230fb1..60ba39b787 100644 --- a/libraries/entities/src/GizmoEntityItem.cpp +++ b/libraries/entities/src/GizmoEntityItem.cpp @@ -109,11 +109,9 @@ bool GizmoEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3 dimensions = getScaledDimensions(); glm::vec2 xyDimensions(dimensions.x, dimensions.z); glm::quat rotation = getWorldOrientation(); - rotation = glm::angleAxis(-(float)M_PI_2, rotation * Vectors::RIGHT) * rotation; + rotation *= glm::angleAxis(-(float)M_PI_2, Vectors::RIGHT); glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); - withReadLock([&] { - rotation = EntityItem::getBillboardRotation(position, rotation, _billboardMode, EntityItem::getPrimaryViewFrustumPosition()); - }); + rotation = EntityItem::getBillboardRotation(position, rotation, getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition(), false); if (findRayRectangleIntersection(origin, direction, rotation, position, xyDimensions, distance)) { glm::vec3 hitPosition = origin + (distance * direction); @@ -146,8 +144,9 @@ bool GizmoEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin, glm::vec3 dimensions = getScaledDimensions(); glm::vec2 xyDimensions(dimensions.x, dimensions.z); glm::quat rotation = getWorldOrientation(); - rotation = glm::angleAxis(-(float)M_PI_2, rotation * Vectors::RIGHT) * rotation; + rotation *= glm::angleAxis(-(float)M_PI_2, Vectors::RIGHT); glm::vec3 position = getWorldPosition(); + rotation = EntityItem::getBillboardRotation(position, rotation, getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition(), true); glm::quat inverseRot = glm::inverse(rotation); glm::vec3 localOrigin = inverseRot * (origin - position); diff --git a/libraries/entities/src/GridEntityItem.cpp b/libraries/entities/src/GridEntityItem.cpp index e635511bfc..499d21a59d 100644 --- a/libraries/entities/src/GridEntityItem.cpp +++ b/libraries/entities/src/GridEntityItem.cpp @@ -125,6 +125,60 @@ void GridEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBits APPEND_ENTITY_PROPERTY(PROP_MINOR_GRID_EVERY, getMinorGridEvery()); } +bool GridEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, + OctreeElementPointer& element, + float& distance, BoxFace& face, glm::vec3& surfaceNormal, + QVariantMap& extraInfo, bool precisionPicking) const { + glm::vec3 dimensions = getScaledDimensions(); + glm::vec2 xyDimensions(dimensions.x, dimensions.y); + glm::quat rotation = getWorldOrientation(); + glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); + rotation = EntityItem::getBillboardRotation(position, rotation, getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition()); + + if (findRayRectangleIntersection(origin, direction, rotation, position, xyDimensions, distance)) { + glm::vec3 forward = rotation * Vectors::FRONT; + if (glm::dot(forward, direction) > 0.0f) { + face = MAX_Z_FACE; + surfaceNormal = -forward; + } else { + face = MIN_Z_FACE; + surfaceNormal = forward; + } + return true; + } + return false; +} + +bool GridEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration, + OctreeElementPointer& element, float& parabolicDistance, + BoxFace& face, glm::vec3& surfaceNormal, + QVariantMap& extraInfo, bool precisionPicking) const { + glm::vec3 dimensions = getScaledDimensions(); + glm::vec2 xyDimensions(dimensions.x, dimensions.y); + glm::quat rotation = getWorldOrientation(); + glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); + rotation = EntityItem::getBillboardRotation(position, rotation, getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition()); + + glm::quat inverseRot = glm::inverse(rotation); + glm::vec3 localOrigin = inverseRot * (origin - position); + glm::vec3 localVelocity = inverseRot * velocity; + glm::vec3 localAcceleration = inverseRot * acceleration; + + if (findParabolaRectangleIntersection(localOrigin, localVelocity, localAcceleration, xyDimensions, parabolicDistance)) { + float localIntersectionVelocityZ = localVelocity.z + localAcceleration.z * parabolicDistance; + glm::vec3 forward = rotation * Vectors::FRONT; + if (localIntersectionVelocityZ > 0.0f) { + face = MIN_Z_FACE; + surfaceNormal = forward; + } else { + face = MAX_Z_FACE; + surfaceNormal = -forward; + } + return true; + } + return false; +} + void GridEntityItem::setColor(const glm::u8vec3& color) { withWriteLock([&] { _needsRenderUpdate |= _color != color; diff --git a/libraries/entities/src/GridEntityItem.h b/libraries/entities/src/GridEntityItem.h index 7dc7a475b2..fc31c93a5a 100644 --- a/libraries/entities/src/GridEntityItem.h +++ b/libraries/entities/src/GridEntityItem.h @@ -43,6 +43,16 @@ public: EntityPropertyFlags& propertyFlags, bool overwriteLocalData, bool& somethingChanged) override; + virtual bool supportsDetailedIntersection() const override { return getBillboardMode() != BillboardMode::NONE; } + virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, + OctreeElementPointer& element, float& distance, + BoxFace& face, glm::vec3& surfaceNormal, + QVariantMap& extraInfo, bool precisionPicking) const override; + virtual bool findDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, + const glm::vec3& acceleration, OctreeElementPointer& element, float& parabolicDistance, + BoxFace& face, glm::vec3& surfaceNormal, + QVariantMap& extraInfo, bool precisionPicking) const override; + static const uint32_t DEFAULT_MAJOR_GRID_EVERY; static const float DEFAULT_MINOR_GRID_EVERY; diff --git a/libraries/entities/src/ImageEntityItem.cpp b/libraries/entities/src/ImageEntityItem.cpp index fb59a85647..6cc47cc8f8 100644 --- a/libraries/entities/src/ImageEntityItem.cpp +++ b/libraries/entities/src/ImageEntityItem.cpp @@ -135,9 +135,7 @@ bool ImageEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec2 xyDimensions(dimensions.x, dimensions.y); glm::quat rotation = getWorldOrientation(); glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); - withReadLock([&] { - rotation = EntityItem::getBillboardRotation(position, rotation, _billboardMode, EntityItem::getPrimaryViewFrustumPosition()); - }); + rotation = EntityItem::getBillboardRotation(position, rotation, getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition()); if (findRayRectangleIntersection(origin, direction, rotation, position, xyDimensions, distance)) { glm::vec3 forward = rotation * Vectors::FRONT; @@ -161,9 +159,7 @@ bool ImageEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin, glm::vec2 xyDimensions(dimensions.x, dimensions.y); glm::quat rotation = getWorldOrientation(); glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); - withReadLock([&] { - rotation = EntityItem::getBillboardRotation(position, rotation, _billboardMode, EntityItem::getPrimaryViewFrustumPosition()); - }); + rotation = EntityItem::getBillboardRotation(position, rotation, getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition()); glm::quat inverseRot = glm::inverse(rotation); glm::vec3 localOrigin = inverseRot * (origin - position); diff --git a/libraries/entities/src/ImageEntityItem.h b/libraries/entities/src/ImageEntityItem.h index 0a90f93f9d..a5ed139e6b 100644 --- a/libraries/entities/src/ImageEntityItem.h +++ b/libraries/entities/src/ImageEntityItem.h @@ -43,7 +43,7 @@ public: EntityPropertyFlags& propertyFlags, bool overwriteLocalData, bool& somethingChanged) override; - virtual bool supportsDetailedIntersection() const override { return true; } + virtual bool supportsDetailedIntersection() const override { return getBillboardMode() != BillboardMode::NONE; } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, diff --git a/libraries/entities/src/PolyVoxEntityItem.cpp b/libraries/entities/src/PolyVoxEntityItem.cpp index dd55ca898b..9c8951514b 100644 --- a/libraries/entities/src/PolyVoxEntityItem.cpp +++ b/libraries/entities/src/PolyVoxEntityItem.cpp @@ -377,15 +377,21 @@ glm::mat4 PolyVoxEntityItem::localToVoxelMatrix() const { return localToModelMatrix; } -glm::mat4 PolyVoxEntityItem::voxelToWorldMatrix() const { - glm::mat4 rotation = glm::mat4_cast(getWorldOrientation()); - glm::mat4 translation = glm::translate(getWorldPosition()); +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(EntityItem::getBillboardRotation(position, orientation, getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition())); + } else { + rotation = glm::mat4_cast(orientation); + } return translation * rotation * voxelToLocalMatrix(); } -glm::mat4 PolyVoxEntityItem::worldToVoxelMatrix() const { - glm::mat4 worldToModelMatrix = glm::inverse(voxelToWorldMatrix()); - return worldToModelMatrix; +glm::mat4 PolyVoxEntityItem::worldToVoxelMatrix(bool includeBillboard) const { + return glm::inverse(voxelToWorldMatrix(includeBillboard)); } glm::vec3 PolyVoxEntityItem::voxelCoordsToWorldCoords(const glm::vec3& voxelCoords) const { diff --git a/libraries/entities/src/PolyVoxEntityItem.h b/libraries/entities/src/PolyVoxEntityItem.h index f994fcd37c..c416353ecf 100644 --- a/libraries/entities/src/PolyVoxEntityItem.h +++ b/libraries/entities/src/PolyVoxEntityItem.h @@ -167,8 +167,8 @@ class PolyVoxEntityItem : public EntityItem { bool isEdged() const; - glm::mat4 voxelToWorldMatrix() const; - glm::mat4 worldToVoxelMatrix() const; + glm::mat4 voxelToWorldMatrix(bool includeBillboard = false) const; + glm::mat4 worldToVoxelMatrix(bool includeBillboard = false) const; glm::mat4 voxelToLocalMatrix() const; glm::mat4 localToVoxelMatrix() const; diff --git a/libraries/entities/src/ShapeEntityItem.cpp b/libraries/entities/src/ShapeEntityItem.cpp index 3dbb02775a..932dc6b034 100644 --- a/libraries/entities/src/ShapeEntityItem.cpp +++ b/libraries/entities/src/ShapeEntityItem.cpp @@ -257,7 +257,8 @@ float ShapeEntityItem::getAlpha() const { void ShapeEntityItem::setUnscaledDimensions(const glm::vec3& value) { const float MAX_FLAT_DIMENSION = 0.0001f; - if ((_shape == entity::Shape::Circle || _shape == entity::Shape::Quad) && value.y > MAX_FLAT_DIMENSION) { + const auto shape = getShape(); + if ((shape == entity::Shape::Circle || shape == entity::Shape::Quad) && value.y > MAX_FLAT_DIMENSION) { // enforce flatness in Y glm::vec3 newDimensions = value; newDimensions.y = MAX_FLAT_DIMENSION; @@ -268,15 +269,24 @@ void ShapeEntityItem::setUnscaledDimensions(const glm::vec3& value) { } bool ShapeEntityItem::supportsDetailedIntersection() const { - return _shape == entity::Sphere; + return getShape() == entity::Sphere || getBillboardMode() != BillboardMode::NONE; } bool ShapeEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const { + if (getShape() != entity::Sphere) { + return true; + } + + glm::vec3 dimensions = getScaledDimensions(); + glm::quat rotation = getWorldOrientation(); + glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); + rotation = EntityItem::getBillboardRotation(position, rotation, getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition()); + // determine the ray in the frame of the entity transformed from a unit sphere - glm::mat4 entityToWorldMatrix = getEntityToWorldMatrix(); + glm::mat4 entityToWorldMatrix = glm::translate(position) * glm::mat4_cast(rotation) * glm::scale(dimensions); glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix); glm::vec3 entityFrameOrigin = glm::vec3(worldToEntityMatrix * glm::vec4(origin, 1.0f)); glm::vec3 entityFrameDirection = glm::vec3(worldToEntityMatrix * glm::vec4(direction, 0.0f)); @@ -302,8 +312,17 @@ bool ShapeEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin, OctreeElementPointer& element, float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const { + if (getShape() != entity::Sphere) { + return true; + } + + glm::vec3 dimensions = getScaledDimensions(); + glm::quat rotation = getWorldOrientation(); + glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); + rotation = EntityItem::getBillboardRotation(position, rotation, getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition()); + // determine the parabola in the frame of the entity transformed from a unit sphere - glm::mat4 entityToWorldMatrix = getEntityToWorldMatrix(); + glm::mat4 entityToWorldMatrix = glm::translate(position) * glm::mat4_cast(rotation) * glm::scale(dimensions); glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix); glm::vec3 entityFrameOrigin = glm::vec3(worldToEntityMatrix * glm::vec4(origin, 1.0f)); glm::vec3 entityFrameVelocity = glm::vec3(worldToEntityMatrix * glm::vec4(velocity, 0.0f)); @@ -343,8 +362,9 @@ void ShapeEntityItem::computeShapeInfo(ShapeInfo& info) { // is set. const glm::vec3 entityDimensions = getScaledDimensions(); + const auto shape = getShape(); - switch (_shape){ + switch (shape){ case entity::Shape::Quad: // Quads collide like flat Cubes case entity::Shape::Cube: { diff --git a/libraries/entities/src/TextEntityItem.cpp b/libraries/entities/src/TextEntityItem.cpp index 906e28288b..bfafae69cf 100644 --- a/libraries/entities/src/TextEntityItem.cpp +++ b/libraries/entities/src/TextEntityItem.cpp @@ -199,9 +199,7 @@ bool TextEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec2 xyDimensions(dimensions.x, dimensions.y); glm::quat rotation = getWorldOrientation(); glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); - withReadLock([&] { - rotation = EntityItem::getBillboardRotation(position, rotation, _billboardMode, EntityItem::getPrimaryViewFrustumPosition()); - }); + rotation = EntityItem::getBillboardRotation(position, rotation, getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition()); if (findRayRectangleIntersection(origin, direction, rotation, position, xyDimensions, distance)) { glm::vec3 forward = rotation * Vectors::FRONT; @@ -225,9 +223,7 @@ bool TextEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin, c glm::vec2 xyDimensions(dimensions.x, dimensions.y); glm::quat rotation = getWorldOrientation(); glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); - withReadLock([&] { - rotation = EntityItem::getBillboardRotation(position, rotation, _billboardMode, EntityItem::getPrimaryViewFrustumPosition()); - }); + rotation = EntityItem::getBillboardRotation(position, rotation, getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition()); glm::quat inverseRot = glm::inverse(rotation); glm::vec3 localOrigin = inverseRot * (origin - position); diff --git a/libraries/entities/src/TextEntityItem.h b/libraries/entities/src/TextEntityItem.h index 7827ab1b85..212f11e768 100644 --- a/libraries/entities/src/TextEntityItem.h +++ b/libraries/entities/src/TextEntityItem.h @@ -48,7 +48,7 @@ public: EntityPropertyFlags& propertyFlags, bool overwriteLocalData, bool& somethingChanged) override; - virtual bool supportsDetailedIntersection() const override { return true; } + virtual bool supportsDetailedIntersection() const override { return getBillboardMode() != BillboardMode::NONE; } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, diff --git a/libraries/entities/src/WebEntityItem.cpp b/libraries/entities/src/WebEntityItem.cpp index f88b40b2ee..661c0865ca 100644 --- a/libraries/entities/src/WebEntityItem.cpp +++ b/libraries/entities/src/WebEntityItem.cpp @@ -165,9 +165,7 @@ bool WebEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const g glm::vec2 xyDimensions(dimensions.x, dimensions.y); glm::quat rotation = getWorldOrientation(); glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); - withReadLock([&] { - rotation = EntityItem::getBillboardRotation(position, rotation, _billboardMode, EntityItem::getPrimaryViewFrustumPosition()); - }); + rotation = EntityItem::getBillboardRotation(position, rotation, getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition()); if (findRayRectangleIntersection(origin, direction, rotation, position, xyDimensions, distance)) { glm::vec3 forward = rotation * Vectors::FRONT; @@ -192,9 +190,7 @@ bool WebEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin, co glm::vec2 xyDimensions(dimensions.x, dimensions.y); glm::quat rotation = getWorldOrientation(); glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); - withReadLock([&] { - rotation = EntityItem::getBillboardRotation(position, rotation, _billboardMode, EntityItem::getPrimaryViewFrustumPosition()); - }); + rotation = EntityItem::getBillboardRotation(position, rotation, getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition()); glm::quat inverseRot = glm::inverse(rotation); glm::vec3 localOrigin = inverseRot * (origin - position); diff --git a/libraries/entities/src/WebEntityItem.h b/libraries/entities/src/WebEntityItem.h index 0a3db2ea78..e0a66f25b2 100644 --- a/libraries/entities/src/WebEntityItem.h +++ b/libraries/entities/src/WebEntityItem.h @@ -45,7 +45,7 @@ public: EntityPropertyFlags& propertyFlags, bool overwriteLocalData, bool& somethingChanged) override; - virtual bool supportsDetailedIntersection() const override { return true; } + virtual bool supportsDetailedIntersection() const override { return getBillboardMode() != BillboardMode::NONE; } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, From 6d1667df5a9b48719a96172069b7fd37704f5793 Mon Sep 17 00:00:00 2001 From: HifiExperiments Date: Sun, 10 Jan 2021 16:48:44 -0800 Subject: [PATCH 10/33] better picking against billboarded shapes other than spheres --- libraries/entities/src/ShapeEntityItem.cpp | 56 +++++++++++----------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/libraries/entities/src/ShapeEntityItem.cpp b/libraries/entities/src/ShapeEntityItem.cpp index 932dc6b034..691990eae1 100644 --- a/libraries/entities/src/ShapeEntityItem.cpp +++ b/libraries/entities/src/ShapeEntityItem.cpp @@ -276,10 +276,6 @@ bool ShapeEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const { - if (getShape() != entity::Sphere) { - return true; - } - glm::vec3 dimensions = getScaledDimensions(); glm::quat rotation = getWorldOrientation(); glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); @@ -291,18 +287,22 @@ bool ShapeEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3 entityFrameOrigin = glm::vec3(worldToEntityMatrix * glm::vec4(origin, 1.0f)); glm::vec3 entityFrameDirection = glm::vec3(worldToEntityMatrix * glm::vec4(direction, 0.0f)); - // NOTE: unit sphere has center of 0,0,0 and radius of 0.5 - if (findRaySphereIntersection(entityFrameOrigin, entityFrameDirection, glm::vec3(0.0f), 0.5f, distance)) { - bool success; - glm::vec3 center = getCenterPosition(success); - if (success) { - // FIXME: this is only correct for uniformly scaled spheres - // determine where on the unit sphere the hit point occured - glm::vec3 hitAt = origin + (direction * distance); - surfaceNormal = glm::normalize(hitAt - center); - } else { - return false; + if (getShape() == entity::Sphere) { + // NOTE: unit sphere has center of 0,0,0 and radius of 0.5 + if (findRaySphereIntersection(entityFrameOrigin, entityFrameDirection, glm::vec3(0.0f), 0.5f, distance)) { + bool success; + glm::vec3 center = getCenterPosition(success); + if (success) { + // FIXME: this is only correct for uniformly scaled spheres + // determine where on the unit sphere the hit point occured + glm::vec3 hitAt = origin + (direction * distance); + surfaceNormal = glm::normalize(hitAt - center); + } else { + return false; + } + return true; } + } else if (findRayAABoxIntersection(entityFrameOrigin, entityFrameDirection, 1.0f / entityFrameDirection, glm::vec3(-0.5f), glm::vec3(1.0f), distance, face, surfaceNormal)) { return true; } return false; @@ -312,10 +312,6 @@ bool ShapeEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin, OctreeElementPointer& element, float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const { - if (getShape() != entity::Sphere) { - return true; - } - glm::vec3 dimensions = getScaledDimensions(); glm::quat rotation = getWorldOrientation(); glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); @@ -328,16 +324,20 @@ bool ShapeEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin, glm::vec3 entityFrameVelocity = glm::vec3(worldToEntityMatrix * glm::vec4(velocity, 0.0f)); glm::vec3 entityFrameAcceleration = glm::vec3(worldToEntityMatrix * glm::vec4(acceleration, 0.0f)); - // NOTE: unit sphere has center of 0,0,0 and radius of 0.5 - if (findParabolaSphereIntersection(entityFrameOrigin, entityFrameVelocity, entityFrameAcceleration, glm::vec3(0.0f), 0.5f, parabolicDistance)) { - bool success; - glm::vec3 center = getCenterPosition(success); - if (success) { - // FIXME: this is only correct for uniformly scaled spheres - surfaceNormal = glm::normalize((origin + velocity * parabolicDistance + 0.5f * acceleration * parabolicDistance * parabolicDistance) - center); - } else { - return false; + if (getShape() == entity::Sphere) { + // NOTE: unit sphere has center of 0,0,0 and radius of 0.5 + if (findParabolaSphereIntersection(entityFrameOrigin, entityFrameVelocity, entityFrameAcceleration, glm::vec3(0.0f), 0.5f, parabolicDistance)) { + bool success; + glm::vec3 center = getCenterPosition(success); + if (success) { + // FIXME: this is only correct for uniformly scaled spheres + surfaceNormal = glm::normalize((origin + velocity * parabolicDistance + 0.5f * acceleration * parabolicDistance * parabolicDistance) - center); + } else { + return false; + } + return true; } + } else if (findParabolaAABoxIntersection(entityFrameOrigin, entityFrameVelocity, entityFrameAcceleration, glm::vec3(-0.5f), glm::vec3(1.0f), parabolicDistance, face, surfaceNormal)) { return true; } return false; From 2a27fc4de2344b877920cbe8dbe3427cfe794073 Mon Sep 17 00:00:00 2001 From: HifiExperiments Date: Wed, 13 Jan 2021 22:31:21 -0800 Subject: [PATCH 11/33] billboarding for model entities --- interface/src/Application.cpp | 4 +- interface/src/Menu.cpp | 2 +- .../src/RenderableGizmoEntityItem.cpp | 4 +- .../src/RenderableGridEntityItem.cpp | 4 +- .../src/RenderableImageEntityItem.cpp | 4 +- .../src/RenderableLineEntityItem.cpp | 4 +- .../src/RenderableMaterialEntityItem.cpp | 4 +- .../src/RenderableModelEntityItem.cpp | 2 + .../src/RenderablePolyLineEntityItem.cpp | 4 +- .../src/RenderablePolyVoxEntityItem.cpp | 4 +- .../src/RenderableShapeEntityItem.cpp | 4 +- .../src/RenderableTextEntityItem.cpp | 8 +- .../src/RenderableWebEntityItem.cpp | 4 +- libraries/entities/src/EntityItem.cpp | 3 - libraries/entities/src/EntityItem.h | 9 - libraries/entities/src/EntityTreeElement.cpp | 10 +- libraries/entities/src/GizmoEntityItem.cpp | 4 +- libraries/entities/src/GridEntityItem.cpp | 4 +- libraries/entities/src/ImageEntityItem.cpp | 4 +- libraries/entities/src/PolyVoxEntityItem.cpp | 2 +- libraries/entities/src/ShapeEntityItem.cpp | 4 +- libraries/entities/src/TextEntityItem.cpp | 4 +- libraries/entities/src/WebEntityItem.cpp | 4 +- .../src/CauterizedMeshPartPayload.cpp | 26 +- .../src/CauterizedMeshPartPayload.h | 6 +- .../render-utils/src/CauterizedModel.cpp | 39 +- .../render-utils/src/MeshPartPayload.cpp | 479 ++++++------------ libraries/render-utils/src/MeshPartPayload.h | 157 ++---- libraries/render-utils/src/Model.cpp | 55 +- libraries/render-utils/src/Model.h | 5 + libraries/shared/src/BillboardMode.cpp | 4 +- libraries/shared/src/BillboardMode.h | 15 +- 32 files changed, 328 insertions(+), 558 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c1911151d8..e38d156336 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2455,7 +2455,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo DependencyManager::get()->setPrecisionPicking(rayPickID, value); }); - EntityItem::setBillboardRotationOperator([](const glm::vec3& position, const glm::quat& rotation, BillboardMode billboardMode, const glm::vec3& frustumPos, bool rotate90x) { + BillboardModeHelpers::setBillboardRotationOperator([](const glm::vec3& position, const glm::quat& rotation, BillboardMode billboardMode, const glm::vec3& frustumPos, bool rotate90x) { const glm::quat ROTATE_90X = glm::angleAxis(-(float)M_PI_2, Vectors::RIGHT); if (billboardMode == BillboardMode::YAW) { //rotate about vertical to face the camera @@ -2484,7 +2484,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo } return rotation; }); - EntityItem::setPrimaryViewFrustumPositionOperator([this]() { + BillboardModeHelpers::setPrimaryViewFrustumPositionOperator([this]() { ViewFrustum viewFrustum; copyViewFrustum(viewFrustum); return viewFrustum.getPosition(); diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 19cc7eacaa..471645e342 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -509,7 +509,7 @@ Menu::Menu() { action = addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::MaterialProceduralShaders, 0, false); connect(action, &QAction::triggered, [action] { - MeshPartPayload::enableMaterialProceduralShaders = action->isChecked(); + ModelMeshPartPayload::enableMaterialProceduralShaders = action->isChecked(); }); { diff --git a/libraries/entities-renderer/src/RenderableGizmoEntityItem.cpp b/libraries/entities-renderer/src/RenderableGizmoEntityItem.cpp index 368aa59b5e..3abd120bf9 100644 --- a/libraries/entities-renderer/src/RenderableGizmoEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableGizmoEntityItem.cpp @@ -254,8 +254,8 @@ void GizmoEntityRenderer::doRender(RenderArgs* args) { geometryCache->bindSimpleProgram(batch, false, transparent, wireframe, true, true, forward, graphics::MaterialKey::CULL_NONE); - transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, - args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? EntityItem::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition(), true)); + transform.setRotation(BillboardModeHelpers::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, + args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? BillboardModeHelpers::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition(), true)); batch.setModelTransform(transform); // Background circle diff --git a/libraries/entities-renderer/src/RenderableGridEntityItem.cpp b/libraries/entities-renderer/src/RenderableGridEntityItem.cpp index 777ddda934..a5ae4acbf5 100644 --- a/libraries/entities-renderer/src/RenderableGridEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableGridEntityItem.cpp @@ -103,8 +103,8 @@ void GridEntityRenderer::doRender(RenderArgs* args) { } else { transform.setTranslation(renderTransform.getTranslation()); } - transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, - args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? EntityItem::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition())); + transform.setRotation(BillboardModeHelpers::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, + args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? BillboardModeHelpers::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition())); batch->setModelTransform(transform); auto minCorner = glm::vec2(-0.5f, -0.5f); diff --git a/libraries/entities-renderer/src/RenderableImageEntityItem.cpp b/libraries/entities-renderer/src/RenderableImageEntityItem.cpp index 34f48e25f6..e03655f09c 100644 --- a/libraries/entities-renderer/src/RenderableImageEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableImageEntityItem.cpp @@ -97,8 +97,8 @@ void ImageEntityRenderer::doRender(RenderArgs* args) { Q_ASSERT(args->_batch); gpu::Batch* batch = args->_batch; - transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, - args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? EntityItem::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition())); + transform.setRotation(BillboardModeHelpers::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, + args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? BillboardModeHelpers::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition())); batch->setModelTransform(transform); batch->setResourceTexture(0, _texture->getGPUTexture()); diff --git a/libraries/entities-renderer/src/RenderableLineEntityItem.cpp b/libraries/entities-renderer/src/RenderableLineEntityItem.cpp index f8a3230f86..a36cdde212 100644 --- a/libraries/entities-renderer/src/RenderableLineEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableLineEntityItem.cpp @@ -47,8 +47,8 @@ void LineEntityRenderer::doRender(RenderArgs* args) { const auto& modelTransform = getModelTransform(); Transform transform = Transform(); transform.setTranslation(modelTransform.getTranslation()); - transform.setRotation(EntityItem::getBillboardRotation(modelTransform.getTranslation(), modelTransform.getRotation(), _billboardMode, - args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? EntityItem::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition())); + transform.setRotation(BillboardModeHelpers::getBillboardRotation(modelTransform.getTranslation(), modelTransform.getRotation(), _billboardMode, + args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? BillboardModeHelpers::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition())); batch.setModelTransform(transform); if (_linePoints.size() > 1) { DependencyManager::get()->bindSimpleProgram(batch, false, false, false, false, true, diff --git a/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp b/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp index ac28dd517c..74b479affe 100644 --- a/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp @@ -272,8 +272,8 @@ void MaterialEntityRenderer::doRender(RenderArgs* args) { proceduralRender = true; } - transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, - args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? EntityItem::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition())); + transform.setRotation(BillboardModeHelpers::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, + args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? BillboardModeHelpers::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition())); batch.setModelTransform(transform); if (!proceduralRender) { diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index c694f496d6..c6765f2321 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -1254,6 +1254,7 @@ void ModelEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPoint _model->setTagMask(getTagMask(), scene); _model->setHifiRenderLayer(getHifiRenderLayer(), scene); _model->setPrimitiveMode(_primitiveMode, scene); + _model->setBillboardMode(_billboardMode, scene); _model->setCullWithParent(_cullWithParent, scene); _model->setRenderWithZones(_renderWithZones, scene); }); @@ -1332,6 +1333,7 @@ void ModelEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPoint model->setTagMask(getTagMask(), scene); model->setHifiRenderLayer(getHifiRenderLayer(), scene); model->setPrimitiveMode(_primitiveMode, scene); + model->setBillboardMode(_billboardMode, scene); model->setCullWithParent(_cullWithParent, scene); model->setRenderWithZones(_renderWithZones, scene); }); diff --git a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp index e10e7a845c..65e9f57b02 100644 --- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp @@ -325,8 +325,8 @@ void PolyLineEntityRenderer::doRender(RenderArgs* args) { buildPipelines(); } - transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, - args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? EntityItem::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition())); + transform.setRotation(BillboardModeHelpers::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, + args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? BillboardModeHelpers::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition())); batch.setModelTransform(transform); batch.setPipeline(_pipelines[{args->_renderMethod, isTransparent()}]); diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index f17f775493..5b6c0c8b70 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -1820,8 +1820,8 @@ void PolyVoxEntityRenderer::doRender(RenderArgs* args) { PerformanceTimer perfTimer("RenderablePolyVoxEntityItem::render"); gpu::Batch& batch = *args->_batch; - glm::mat4 rotation = glm::mat4_cast(EntityItem::getBillboardRotation(_position, _orientation, _billboardMode, - args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? EntityItem::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition())); + glm::mat4 rotation = glm::mat4_cast(BillboardModeHelpers::getBillboardRotation(_position, _orientation, _billboardMode, + args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? BillboardModeHelpers::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition())); Transform transform(glm::translate(_position) * rotation * _lastVoxelToLocalMatrix); batch.setModelTransform(transform); diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp index f1c73dbeed..9cc18a8df5 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp @@ -238,8 +238,8 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) { return; } - transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, - args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? EntityItem::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition(), + transform.setRotation(BillboardModeHelpers::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, + args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? BillboardModeHelpers::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition(), _shape < entity::Shape::Cube || _shape > entity::Shape::Icosahedron)); batch.setModelTransform(transform); diff --git a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp index 2be84110d6..1724cf69d5 100644 --- a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp @@ -131,8 +131,8 @@ void TextEntityRenderer::doRender(RenderArgs* args) { return; } - transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, - args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? EntityItem::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition())); + transform.setRotation(BillboardModeHelpers::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, + args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? BillboardModeHelpers::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition())); batch.setModelTransform(transform); auto geometryCache = DependencyManager::get(); @@ -313,8 +313,8 @@ void entities::TextPayload::render(RenderArgs* args) { return; } - modelTransform.setRotation(EntityItem::getBillboardRotation(modelTransform.getTranslation(), modelTransform.getRotation(), textRenderable->_billboardMode, - args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? EntityItem::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition())); + modelTransform.setRotation(BillboardModeHelpers::getBillboardRotation(modelTransform.getTranslation(), modelTransform.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)); diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index 6c6215f69d..e367b4cc7c 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -302,8 +302,8 @@ void WebEntityRenderer::doRender(RenderArgs* args) { batch.setResourceTexture(0, _texture); - transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, - args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? EntityItem::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition())); + transform.setRotation(BillboardModeHelpers::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, + args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? BillboardModeHelpers::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition())); batch.setModelTransform(transform); // Turn off jitter for these entities diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index f33838d146..68e824f8cc 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -51,9 +51,6 @@ int EntityItem::_maxActionsDataSize = 800; quint64 EntityItem::_rememberDeletedActionTime = 20 * USECS_PER_SECOND; QString EntityItem::_marketplacePublicKey; -std::function EntityItem::_getBillboardRotationOperator = [](const glm::vec3&, const glm::quat& rotation, BillboardMode, const glm::vec3&, bool) { return rotation; }; -std::function EntityItem::_getPrimaryViewFrustumPositionOperator = []() { return glm::vec3(0.0f); }; - EntityItem::EntityItem(const EntityItemID& entityItemID) : SpatiallyNestable(NestableType::Entity, entityItemID) { diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index ad3429c0b6..288f1682c7 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -572,11 +572,6 @@ public: virtual void removeGrab(GrabPointer grab) override; virtual void disableGrab(GrabPointer grab) override; - static void setBillboardRotationOperator(std::function getBillboardRotationOperator) { _getBillboardRotationOperator = getBillboardRotationOperator; } - static glm::quat getBillboardRotation(const glm::vec3& position, const glm::quat& rotation, BillboardMode billboardMode, const glm::vec3& frustumPos, bool rotate90x = false) { return _getBillboardRotationOperator(position, rotation, billboardMode, frustumPos, rotate90x); } - static void setPrimaryViewFrustumPositionOperator(std::function getPrimaryViewFrustumPositionOperator) { _getPrimaryViewFrustumPositionOperator = getPrimaryViewFrustumPositionOperator; } - static glm::vec3 getPrimaryViewFrustumPosition() { return _getPrimaryViewFrustumPositionOperator(); } - bool stillHasMyGrab() const; bool needsRenderUpdate() const { return _needsRenderUpdate; } @@ -786,10 +781,6 @@ protected: bool _cullWithParent { false }; mutable bool _needsRenderUpdate { false }; - -private: - static std::function _getBillboardRotationOperator; - static std::function _getPrimaryViewFrustumPositionOperator; }; #endif // hifi_EntityItem_h diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index 6e446630ee..afbb139d5f 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -222,7 +222,7 @@ EntityItemID EntityTreeElement::evalDetailedRayIntersection(const glm::vec3& ori glm::vec3 position = entity->getWorldPosition(); glm::mat4 translation = glm::translate(position); glm::quat orientation = entity->getWorldOrientation(); - glm::mat4 rotation = glm::mat4_cast(EntityItem::getBillboardRotation(position, orientation, entity->getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition())); + glm::mat4 rotation = glm::mat4_cast(BillboardModeHelpers::getBillboardRotation(position, orientation, entity->getBillboardMode(), BillboardModeHelpers::getPrimaryViewFrustumPosition())); glm::mat4 entityToWorldMatrix = translation * rotation; glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix); @@ -373,7 +373,7 @@ EntityItemID EntityTreeElement::evalDetailedParabolaIntersection(const glm::vec3 glm::vec3 position = entity->getWorldPosition(); glm::mat4 translation = glm::translate(position); glm::quat orientation = entity->getWorldOrientation(); - glm::mat4 rotation = glm::mat4_cast(EntityItem::getBillboardRotation(position, orientation, entity->getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition())); + glm::mat4 rotation = glm::mat4_cast(BillboardModeHelpers::getBillboardRotation(position, orientation, entity->getBillboardMode(), BillboardModeHelpers::getPrimaryViewFrustumPosition())); glm::mat4 entityToWorldMatrix = translation * rotation; glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix); @@ -479,7 +479,7 @@ void EntityTreeElement::evalEntitiesInSphere(const glm::vec3& position, float ra glm::vec3 position = entity->getWorldPosition(); glm::mat4 translation = glm::translate(position); glm::quat orientation = entity->getWorldOrientation(); - glm::mat4 rotation = glm::mat4_cast(EntityItem::getBillboardRotation(position, orientation, entity->getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition())); + glm::mat4 rotation = glm::mat4_cast(BillboardModeHelpers::getBillboardRotation(position, orientation, entity->getBillboardMode(), BillboardModeHelpers::getPrimaryViewFrustumPosition())); glm::mat4 entityToWorldMatrix = translation * rotation; glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix); @@ -535,7 +535,7 @@ void EntityTreeElement::evalEntitiesInSphereWithType(const glm::vec3& position, glm::vec3 position = entity->getWorldPosition(); glm::mat4 translation = glm::translate(position); glm::quat orientation = entity->getWorldOrientation(); - glm::mat4 rotation = glm::mat4_cast(EntityItem::getBillboardRotation(position, orientation, entity->getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition())); + glm::mat4 rotation = glm::mat4_cast(BillboardModeHelpers::getBillboardRotation(position, orientation, entity->getBillboardMode(), BillboardModeHelpers::getPrimaryViewFrustumPosition())); glm::mat4 entityToWorldMatrix = translation * rotation; glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix); @@ -596,7 +596,7 @@ void EntityTreeElement::evalEntitiesInSphereWithName(const glm::vec3& position, glm::vec3 position = entity->getWorldPosition(); glm::mat4 translation = glm::translate(position); glm::quat orientation = entity->getWorldOrientation(); - glm::mat4 rotation = glm::mat4_cast(EntityItem::getBillboardRotation(position, orientation, entity->getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition())); + glm::mat4 rotation = glm::mat4_cast(BillboardModeHelpers::getBillboardRotation(position, orientation, entity->getBillboardMode(), BillboardModeHelpers::getPrimaryViewFrustumPosition())); 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 60ba39b787..6586d57fde 100644 --- a/libraries/entities/src/GizmoEntityItem.cpp +++ b/libraries/entities/src/GizmoEntityItem.cpp @@ -111,7 +111,7 @@ bool GizmoEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::quat rotation = getWorldOrientation(); rotation *= glm::angleAxis(-(float)M_PI_2, Vectors::RIGHT); glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); - rotation = EntityItem::getBillboardRotation(position, rotation, getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition(), false); + rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, getBillboardMode(), BillboardModeHelpers::getPrimaryViewFrustumPosition(), false); if (findRayRectangleIntersection(origin, direction, rotation, position, xyDimensions, distance)) { glm::vec3 hitPosition = origin + (distance * direction); @@ -146,7 +146,7 @@ bool GizmoEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin, glm::quat rotation = getWorldOrientation(); rotation *= glm::angleAxis(-(float)M_PI_2, Vectors::RIGHT); glm::vec3 position = getWorldPosition(); - rotation = EntityItem::getBillboardRotation(position, rotation, getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition(), true); + rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, getBillboardMode(), BillboardModeHelpers::getPrimaryViewFrustumPosition(), true); glm::quat inverseRot = glm::inverse(rotation); glm::vec3 localOrigin = inverseRot * (origin - position); diff --git a/libraries/entities/src/GridEntityItem.cpp b/libraries/entities/src/GridEntityItem.cpp index 499d21a59d..c675a11d27 100644 --- a/libraries/entities/src/GridEntityItem.cpp +++ b/libraries/entities/src/GridEntityItem.cpp @@ -133,7 +133,7 @@ bool GridEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec2 xyDimensions(dimensions.x, dimensions.y); glm::quat rotation = getWorldOrientation(); glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); - rotation = EntityItem::getBillboardRotation(position, rotation, getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition()); + rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, getBillboardMode(), BillboardModeHelpers::getPrimaryViewFrustumPosition()); if (findRayRectangleIntersection(origin, direction, rotation, position, xyDimensions, distance)) { glm::vec3 forward = rotation * Vectors::FRONT; @@ -157,7 +157,7 @@ bool GridEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin, c glm::vec2 xyDimensions(dimensions.x, dimensions.y); glm::quat rotation = getWorldOrientation(); glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); - rotation = EntityItem::getBillboardRotation(position, rotation, getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition()); + rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, getBillboardMode(), BillboardModeHelpers::getPrimaryViewFrustumPosition()); glm::quat inverseRot = glm::inverse(rotation); glm::vec3 localOrigin = inverseRot * (origin - position); diff --git a/libraries/entities/src/ImageEntityItem.cpp b/libraries/entities/src/ImageEntityItem.cpp index 6cc47cc8f8..80711e4abc 100644 --- a/libraries/entities/src/ImageEntityItem.cpp +++ b/libraries/entities/src/ImageEntityItem.cpp @@ -135,7 +135,7 @@ bool ImageEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec2 xyDimensions(dimensions.x, dimensions.y); glm::quat rotation = getWorldOrientation(); glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); - rotation = EntityItem::getBillboardRotation(position, rotation, getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition()); + rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, getBillboardMode(), BillboardModeHelpers::getPrimaryViewFrustumPosition()); if (findRayRectangleIntersection(origin, direction, rotation, position, xyDimensions, distance)) { glm::vec3 forward = rotation * Vectors::FRONT; @@ -159,7 +159,7 @@ bool ImageEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin, glm::vec2 xyDimensions(dimensions.x, dimensions.y); glm::quat rotation = getWorldOrientation(); glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); - rotation = EntityItem::getBillboardRotation(position, rotation, getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition()); + rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, getBillboardMode(), BillboardModeHelpers::getPrimaryViewFrustumPosition()); glm::quat inverseRot = glm::inverse(rotation); glm::vec3 localOrigin = inverseRot * (origin - position); diff --git a/libraries/entities/src/PolyVoxEntityItem.cpp b/libraries/entities/src/PolyVoxEntityItem.cpp index 9c8951514b..5ed9f69b5a 100644 --- a/libraries/entities/src/PolyVoxEntityItem.cpp +++ b/libraries/entities/src/PolyVoxEntityItem.cpp @@ -383,7 +383,7 @@ glm::mat4 PolyVoxEntityItem::voxelToWorldMatrix(bool includeBillboard) const { glm::mat4 translation = glm::translate(position); glm::mat4 rotation; if (includeBillboard) { - rotation = glm::mat4_cast(EntityItem::getBillboardRotation(position, orientation, getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition())); + rotation = glm::mat4_cast(BillboardModeHelpers::getBillboardRotation(position, orientation, getBillboardMode(), BillboardModeHelpers::getPrimaryViewFrustumPosition())); } else { rotation = glm::mat4_cast(orientation); } diff --git a/libraries/entities/src/ShapeEntityItem.cpp b/libraries/entities/src/ShapeEntityItem.cpp index 691990eae1..943912b934 100644 --- a/libraries/entities/src/ShapeEntityItem.cpp +++ b/libraries/entities/src/ShapeEntityItem.cpp @@ -279,7 +279,7 @@ bool ShapeEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3 dimensions = getScaledDimensions(); glm::quat rotation = getWorldOrientation(); glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); - rotation = EntityItem::getBillboardRotation(position, rotation, getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition()); + rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, getBillboardMode(), BillboardModeHelpers::getPrimaryViewFrustumPosition()); // 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); @@ -315,7 +315,7 @@ bool ShapeEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin, glm::vec3 dimensions = getScaledDimensions(); glm::quat rotation = getWorldOrientation(); glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); - rotation = EntityItem::getBillboardRotation(position, rotation, getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition()); + rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, getBillboardMode(), BillboardModeHelpers::getPrimaryViewFrustumPosition()); // 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/entities/src/TextEntityItem.cpp b/libraries/entities/src/TextEntityItem.cpp index bfafae69cf..7fab5cee53 100644 --- a/libraries/entities/src/TextEntityItem.cpp +++ b/libraries/entities/src/TextEntityItem.cpp @@ -199,7 +199,7 @@ bool TextEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec2 xyDimensions(dimensions.x, dimensions.y); glm::quat rotation = getWorldOrientation(); glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); - rotation = EntityItem::getBillboardRotation(position, rotation, getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition()); + rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, getBillboardMode(), BillboardModeHelpers::getPrimaryViewFrustumPosition()); if (findRayRectangleIntersection(origin, direction, rotation, position, xyDimensions, distance)) { glm::vec3 forward = rotation * Vectors::FRONT; @@ -223,7 +223,7 @@ bool TextEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin, c glm::vec2 xyDimensions(dimensions.x, dimensions.y); glm::quat rotation = getWorldOrientation(); glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); - rotation = EntityItem::getBillboardRotation(position, rotation, getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition()); + rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, getBillboardMode(), BillboardModeHelpers::getPrimaryViewFrustumPosition()); glm::quat inverseRot = glm::inverse(rotation); glm::vec3 localOrigin = inverseRot * (origin - position); diff --git a/libraries/entities/src/WebEntityItem.cpp b/libraries/entities/src/WebEntityItem.cpp index 661c0865ca..d9d2425e11 100644 --- a/libraries/entities/src/WebEntityItem.cpp +++ b/libraries/entities/src/WebEntityItem.cpp @@ -165,7 +165,7 @@ bool WebEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const g glm::vec2 xyDimensions(dimensions.x, dimensions.y); glm::quat rotation = getWorldOrientation(); glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); - rotation = EntityItem::getBillboardRotation(position, rotation, getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition()); + rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, getBillboardMode(), BillboardModeHelpers::getPrimaryViewFrustumPosition()); if (findRayRectangleIntersection(origin, direction, rotation, position, xyDimensions, distance)) { glm::vec3 forward = rotation * Vectors::FRONT; @@ -190,7 +190,7 @@ bool WebEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin, co glm::vec2 xyDimensions(dimensions.x, dimensions.y); glm::quat rotation = getWorldOrientation(); glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); - rotation = EntityItem::getBillboardRotation(position, rotation, getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition()); + rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, getBillboardMode(), BillboardModeHelpers::getPrimaryViewFrustumPosition()); glm::quat inverseRot = glm::inverse(rotation); glm::vec3 localOrigin = inverseRot * (origin - position); diff --git a/libraries/render-utils/src/CauterizedMeshPartPayload.cpp b/libraries/render-utils/src/CauterizedMeshPartPayload.cpp index 9c7a2ee60b..dc1ffb7b67 100644 --- a/libraries/render-utils/src/CauterizedMeshPartPayload.cpp +++ b/libraries/render-utils/src/CauterizedMeshPartPayload.cpp @@ -19,8 +19,8 @@ using namespace render; CauterizedMeshPartPayload::CauterizedMeshPartPayload(ModelPointer model, int meshIndex, int partIndex, int shapeIndex, - const Transform& transform, const Transform& offsetTransform, const uint64_t& created) - : ModelMeshPartPayload(model, meshIndex, partIndex, shapeIndex, transform, offsetTransform, created) {} + const Transform& transform, const uint64_t& created) + : ModelMeshPartPayload(model, meshIndex, partIndex, shapeIndex, transform, created) {} void CauterizedMeshPartPayload::updateClusterBuffer(const std::vector& clusterMatrices, const std::vector& cauterizedClusterMatrices) { @@ -52,11 +52,26 @@ void CauterizedMeshPartPayload::updateClusterBuffer(const std::vector& clusterMatrices, @@ -23,9 +23,9 @@ public: void updateClusterBuffer(const std::vector& clusterDualQuaternions, const std::vector& cauterizedClusterQuaternions); - void updateTransformForCauterizedMesh(const Transform& renderTransform); + void updateTransformForCauterizedMesh(const Transform& modelTransform, const Model::MeshState& meshState, bool useDualQuaternionSkinning); - void bindTransform(gpu::Batch& batch, RenderArgs::RenderMode renderMode) const override; + void bindTransform(gpu::Batch& batch, const Transform& transform, RenderArgs::RenderMode renderMode) const override; void setEnableCauterization(bool enableCauterization) { _enableCauterization = enableCauterization; } diff --git a/libraries/render-utils/src/CauterizedModel.cpp b/libraries/render-utils/src/CauterizedModel.cpp index 94b7661b2f..a5d27dc7d2 100644 --- a/libraries/render-utils/src/CauterizedModel.cpp +++ b/libraries/render-utils/src/CauterizedModel.cpp @@ -69,10 +69,6 @@ void CauterizedModel::createRenderItemSet() { transform.setTranslation(_translation); transform.setRotation(_rotation); - Transform offset; - offset.setScale(_scale); - offset.postTranslate(_offset); - // Run through all of the meshes, and place them into their segregated, but unsorted buckets int shapeID = 0; uint32_t numMeshes = (uint32_t)meshes.size(); @@ -85,7 +81,7 @@ void CauterizedModel::createRenderItemSet() { // Create the render payloads int numParts = (int)mesh->getNumParts(); for (int partIndex = 0; partIndex < numParts; partIndex++) { - auto ptr = std::make_shared(shared_from_this(), i, partIndex, shapeID, transform, offset, _created); + auto ptr = std::make_shared(shared_from_this(), i, partIndex, shapeID, transform, _created); _modelMeshRenderItems << std::static_pointer_cast(ptr); auto material = getGeometry()->getShapeMaterial(shapeID); _modelMeshMaterialNames.push_back(material ? material->getName() : ""); @@ -235,37 +231,8 @@ void CauterizedModel::updateRenderItems() { data.computeAdjustedLocalBound(meshState.clusterMatrices); } - Transform renderTransform = modelTransform; - if (useDualQuaternionSkinning) { - if (meshState.clusterDualQuaternions.size() == 1 || meshState.clusterDualQuaternions.size() == 2) { - const auto& dq = meshState.clusterDualQuaternions[0]; - Transform transform(dq.getRotation(), - dq.getScale(), - dq.getTranslation()); - renderTransform = modelTransform.worldTransform(transform); - } - } else { - if (meshState.clusterMatrices.size() == 1 || meshState.clusterMatrices.size() == 2) { - renderTransform = modelTransform.worldTransform(Transform(meshState.clusterMatrices[0])); - } - } - data.updateTransformForSkinnedMesh(renderTransform, modelTransform); - - renderTransform = modelTransform; - if (useDualQuaternionSkinning) { - if (cauterizedMeshState.clusterDualQuaternions.size() == 1 || cauterizedMeshState.clusterDualQuaternions.size() == 2) { - const auto& dq = cauterizedMeshState.clusterDualQuaternions[0]; - Transform transform(dq.getRotation(), - dq.getScale(), - dq.getTranslation()); - renderTransform = modelTransform.worldTransform(Transform(transform)); - } - } else { - if (cauterizedMeshState.clusterMatrices.size() == 1 || cauterizedMeshState.clusterMatrices.size() == 2) { - renderTransform = modelTransform.worldTransform(Transform(cauterizedMeshState.clusterMatrices[0])); - } - } - data.updateTransformForCauterizedMesh(renderTransform); + data.updateTransformForSkinnedMesh(modelTransform, meshState, useDualQuaternionSkinning); + data.updateTransformForCauterizedMesh(modelTransform, cauterizedMeshState, useDualQuaternionSkinning); data.setEnableCauterization(enableCauterization); data.updateKey(renderItemKeyGlobalFlags); diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 84aed55d72..0e0af6fc71 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -11,8 +11,7 @@ #include "MeshPartPayload.h" -#include - +#include #include #include #include @@ -23,292 +22,33 @@ #include "RenderPipelines.h" -// static const QString ENABLE_MATERIAL_PROCEDURAL_SHADERS_STRING { "HIFI_ENABLE_MATERIAL_PROCEDURAL_SHADERS" }; -// static bool ENABLE_MATERIAL_PROCEDURAL_SHADERS = QProcessEnvironment::systemEnvironment().contains(ENABLE_MATERIAL_PROCEDURAL_SHADERS_STRING); - -bool MeshPartPayload::enableMaterialProceduralShaders = false; - using namespace render; -namespace render { -template <> const ItemKey payloadGetKey(const MeshPartPayload::Pointer& payload) { - if (payload) { - return payload->getKey(); - } - return ItemKey::Builder::opaqueShape(); // for lack of a better idea -} - -template <> const Item::Bound payloadGetBound(const MeshPartPayload::Pointer& payload) { - if (payload) { - return payload->getBound(); - } - return Item::Bound(); -} - -template <> const ShapeKey shapeGetShapeKey(const MeshPartPayload::Pointer& payload) { - if (payload) { - return payload->getShapeKey(); - } - return ShapeKey::Builder::invalid(); -} - -template <> void payloadRender(const MeshPartPayload::Pointer& payload, RenderArgs* args) { - return payload->render(args); -} - -template <> bool payloadPassesZoneOcclusionTest(const MeshPartPayload::Pointer& payload, const std::unordered_set& containingZones) { - if (payload) { - return payload->passesZoneOcclusionTest(containingZones); - } - return false; -} -} - -MeshPartPayload::MeshPartPayload(const std::shared_ptr& mesh, int partIndex, graphics::MaterialPointer material, const uint64_t& created) : - _created(created) -{ - updateMeshPart(mesh, partIndex); - addMaterial(graphics::MaterialLayer(material, 0)); -} - -void MeshPartPayload::updateMeshPart(const std::shared_ptr& drawMesh, int partIndex) { - _drawMesh = drawMesh; - if (_drawMesh) { - auto vertexFormat = _drawMesh->getVertexFormat(); - _hasColorAttrib = vertexFormat->hasAttribute(gpu::Stream::COLOR); - _drawPart = _drawMesh->getPartBuffer().get(partIndex); - _localBound = _drawMesh->evalPartBound(partIndex); - } -} - -void MeshPartPayload::updateTransform(const Transform& transform, const Transform& offsetTransform) { - _transform = transform; - Transform::mult(_drawTransform, _transform, offsetTransform); - _worldBound = _localBound; - _worldBound.transform(_drawTransform); -} - -void MeshPartPayload::addMaterial(graphics::MaterialLayer material) { - _drawMaterials.push(material); -} - -void MeshPartPayload::removeMaterial(graphics::MaterialPointer material) { - _drawMaterials.remove(material); -} - -void MeshPartPayload::updateKey(const render::ItemKey& key) { - ItemKey::Builder builder(key); - builder.withTypeShape(); - - if (_drawMaterials.shouldUpdate()) { - RenderPipelines::updateMultiMaterial(_drawMaterials); - } - - auto matKey = _drawMaterials.getMaterialKey(); - if (matKey.isTranslucent()) { - builder.withTransparent(); - } - - if (_cullWithParent) { - builder.withSubMetaCulled(); - } - - _itemKey = builder.build(); -} - -ItemKey MeshPartPayload::getKey() const { - return _itemKey; -} - -Item::Bound MeshPartPayload::getBound() const { - graphics::MaterialPointer material = _drawMaterials.empty() ? nullptr : _drawMaterials.top().material; - if (material && material->isProcedural() && material->isReady()) { - auto procedural = std::static_pointer_cast(_drawMaterials.top().material); - if (procedural->hasVertexShader() && procedural->hasBoundOperator()) { - return procedural->getBound(); - } - } - return _worldBound; -} - -ShapeKey MeshPartPayload::getShapeKey() const { - ShapeKey::Builder builder; - graphics::MaterialPointer material = _drawMaterials.empty() ? nullptr : _drawMaterials.top().material; - graphics::MaterialKey drawMaterialKey = _drawMaterials.getMaterialKey(); - - if (drawMaterialKey.isTranslucent()) { - builder.withTranslucent(); - } - - if (material && material->isProcedural() && material->isReady()) { - builder.withOwnPipeline(); - } else { - builder.withMaterial(); - - if (drawMaterialKey.isNormalMap()) { - builder.withTangents(); - } - if (drawMaterialKey.isLightMap()) { - builder.withLightMap(); - } - if (drawMaterialKey.isUnlit()) { - builder.withUnlit(); - } - if (material) { - builder.withCullFaceMode(material->getCullFaceMode()); - } - } - - return builder.build(); -} - -void MeshPartPayload::drawCall(gpu::Batch& batch) const { - batch.drawIndexed(gpu::TRIANGLES, _drawPart._numIndices, _drawPart._startIndex); -} - -void MeshPartPayload::bindMesh(gpu::Batch& batch) { - batch.setIndexBuffer(gpu::UINT32, (_drawMesh->getIndexBuffer()._buffer), 0); - - batch.setInputFormat((_drawMesh->getVertexFormat())); - - batch.setInputStream(0, _drawMesh->getVertexStream()); -} - -void MeshPartPayload::bindTransform(gpu::Batch& batch, RenderArgs::RenderMode renderMode) const { - batch.setModelTransform(_drawTransform); -} - -bool MeshPartPayload::passesZoneOcclusionTest(const std::unordered_set& containingZones) const { - if (!_renderWithZones.isEmpty()) { - if (!containingZones.empty()) { - for (auto renderWithZone : _renderWithZones) { - if (containingZones.find(renderWithZone) != containingZones.end()) { - return true; - } - } - } - return false; - } - return true; -} - -void MeshPartPayload::render(RenderArgs* args) { - PerformanceTimer perfTimer("MeshPartPayload::render"); - - if (!args) { - return; - } - - gpu::Batch& batch = *(args->_batch); - - // Bind the model transform and the skinCLusterMatrices if needed - bindTransform(batch, args->_renderMode); - - //Bind the index buffer and vertex buffer and Blend shapes if needed - bindMesh(batch); - - if (!_drawMaterials.empty() && _drawMaterials.top().material && _drawMaterials.top().material->isProcedural() && - _drawMaterials.top().material->isReady()) { - if (!enableMaterialProceduralShaders) { - return; - } - auto procedural = std::static_pointer_cast(_drawMaterials.top().material); - auto& schema = _drawMaterials.getSchemaBuffer().get(); - glm::vec4 outColor = glm::vec4(ColorUtils::tosRGBVec3(schema._albedo), schema._opacity); - outColor = procedural->getColor(outColor); - procedural->prepare(batch, _drawTransform.getTranslation(), _drawTransform.getScale(), _drawTransform.getRotation(), _created, - ProceduralProgramKey(outColor.a < 1.0f)); - batch._glColor4f(outColor.r, outColor.g, outColor.b, outColor.a); - } else { - // apply material properties - if (RenderPipelines::bindMaterials(_drawMaterials, batch, args->_renderMode, args->_enableTexturing)) { - args->_details._materialSwitches++; - } - } - - // Draw! - { - PerformanceTimer perfTimer("batch.drawIndexed()"); - drawCall(batch); - } - - const int INDICES_PER_TRIANGLE = 3; - args->_details._trianglesRendered += _drawPart._numIndices / INDICES_PER_TRIANGLE; -} - -namespace render { -template <> const ItemKey payloadGetKey(const ModelMeshPartPayload::Pointer& payload) { - if (payload) { - return payload->getKey(); - } - return ItemKey::Builder::opaqueShape(); // for lack of a better idea -} - -template <> const Item::Bound payloadGetBound(const ModelMeshPartPayload::Pointer& payload) { - if (payload) { - return payload->getBound(); - } - return Item::Bound(); -} - -template <> const ShapeKey shapeGetShapeKey(const ModelMeshPartPayload::Pointer& payload) { - if (payload) { - return payload->getShapeKey(); - } - return ShapeKey::Builder::invalid(); -} - -template <> void payloadRender(const ModelMeshPartPayload::Pointer& payload, RenderArgs* args) { - return payload->render(args); -} - -template <> bool payloadPassesZoneOcclusionTest(const ModelMeshPartPayload::Pointer& payload, const std::unordered_set& containingZones) { - if (payload) { - return payload->passesZoneOcclusionTest(containingZones); - } - return false; -} -} +bool ModelMeshPartPayload::enableMaterialProceduralShaders = false; ModelMeshPartPayload::ModelMeshPartPayload(ModelPointer model, int meshIndex, int partIndex, int shapeIndex, - const Transform& transform, const Transform& offsetTransform, const uint64_t& created) : + const Transform& transform, const uint64_t& created) : _meshIndex(meshIndex), - _shapeID(shapeIndex) { + _created(created) { assert(model && model->isLoaded()); - bool useDualQuaternionSkinning = model->getUseDualQuaternionSkinning(); - auto& modelMesh = model->getGeometry()->getMeshes().at(_meshIndex); _meshNumVertices = (int)modelMesh->getNumVertices(); const Model::MeshState& state = model->getMeshState(_meshIndex); updateMeshPart(modelMesh, partIndex); + bool useDualQuaternionSkinning = model->getUseDualQuaternionSkinning(); if (useDualQuaternionSkinning) { computeAdjustedLocalBound(state.clusterDualQuaternions); } else { computeAdjustedLocalBound(state.clusterMatrices); } - updateTransform(transform, offsetTransform); - Transform renderTransform = transform; - if (useDualQuaternionSkinning) { - if (state.clusterDualQuaternions.size() == 1) { - const auto& dq = state.clusterDualQuaternions[0]; - Transform transform(dq.getRotation(), - dq.getScale(), - dq.getTranslation()); - renderTransform = transform.worldTransform(Transform(transform)); - } - } else { - if (state.clusterMatrices.size() == 1) { - renderTransform = transform.worldTransform(Transform(state.clusterMatrices[0])); - } - } - updateTransformForSkinnedMesh(renderTransform, transform); + updateTransformForSkinnedMesh(transform, state, useDualQuaternionSkinning); - initCache(model); + initCache(model, shapeIndex); #if defined(Q_OS_MAC) || defined(Q_OS_ANDROID) // On mac AMD, we specifically need to have a _meshBlendshapeBuffer bound when using a deformed mesh pipeline @@ -322,14 +62,11 @@ ModelMeshPartPayload::ModelMeshPartPayload(ModelPointer model, int meshIndex, in _meshBlendshapeBuffer = std::make_shared(sizeof(BlendshapeOffset), reinterpret_cast(&data), sizeof(BlendshapeOffset)); } #endif - - _created = created; } -void ModelMeshPartPayload::initCache(const ModelPointer& model) { +void ModelMeshPartPayload::initCache(const ModelPointer& model, int shapeID) { if (_drawMesh) { auto vertexFormat = _drawMesh->getVertexFormat(); - _hasColorAttrib = vertexFormat->hasAttribute(gpu::Stream::COLOR); _isSkinned = vertexFormat->hasAttribute(gpu::Stream::SKIN_CLUSTER_WEIGHT) && vertexFormat->hasAttribute(gpu::Stream::SKIN_CLUSTER_INDEX); const HFMModel& hfmModel = model->getHFMModel(); @@ -339,18 +76,22 @@ void ModelMeshPartPayload::initCache(const ModelPointer& model) { _hasTangents = !mesh.tangents.isEmpty(); } - auto networkMaterial = model->getGeometry()->getShapeMaterial(_shapeID); + auto networkMaterial = model->getGeometry()->getShapeMaterial(shapeID); if (networkMaterial) { addMaterial(graphics::MaterialLayer(networkMaterial, 0)); } } -void ModelMeshPartPayload::notifyLocationChanged() { - +void ModelMeshPartPayload::updateMeshPart(const std::shared_ptr& drawMesh, int partIndex) { + _drawMesh = drawMesh; + if (_drawMesh) { + auto vertexFormat = _drawMesh->getVertexFormat(); + _drawPart = _drawMesh->getPartBuffer().get(partIndex); + _localBound = _drawMesh->evalPartBound(partIndex); + } } void ModelMeshPartPayload::updateClusterBuffer(const std::vector& clusterMatrices) { - // reset cluster buffer if we change the cluster buffer type if (_clusterBufferType != ClusterBufferType::Matrices) { _clusterBuffer.reset(); @@ -370,7 +111,6 @@ void ModelMeshPartPayload::updateClusterBuffer(const std::vector& clu } void ModelMeshPartPayload::updateClusterBuffer(const std::vector& clusterDualQuaternions) { - // reset cluster buffer if we change the cluster buffer type if (_clusterBufferType != ClusterBufferType::DualQuaternions) { _clusterBuffer.reset(); @@ -389,13 +129,78 @@ void ModelMeshPartPayload::updateClusterBuffer(const std::vector& clusterMatrices) { + _adjustedLocalBound = _localBound; + if (clusterMatrices.size() > 0) { + _adjustedLocalBound.transform(clusterMatrices.back()); + + for (int i = 0; i < (int)clusterMatrices.size() - 1; ++i) { + AABox clusterBound = _localBound; + clusterBound.transform(clusterMatrices[i]); + _adjustedLocalBound += clusterBound; + } + } +} + +void ModelMeshPartPayload::computeAdjustedLocalBound(const std::vector& clusterDualQuaternions) { + _adjustedLocalBound = _localBound; + if (clusterDualQuaternions.size() > 0) { + Transform rootTransform(clusterDualQuaternions.back().getRotation(), + clusterDualQuaternions.back().getScale(), + clusterDualQuaternions.back().getTranslation()); + _adjustedLocalBound.transform(rootTransform); + + for (int i = 0; i < (int)clusterDualQuaternions.size() - 1; ++i) { + AABox clusterBound = _localBound; + Transform transform(clusterDualQuaternions[i].getRotation(), + clusterDualQuaternions[i].getScale(), + clusterDualQuaternions[i].getTranslation()); + clusterBound.transform(transform); + _adjustedLocalBound += clusterBound; + } + } +} + +void ModelMeshPartPayload::updateTransformForSkinnedMesh(const Transform& modelTransform, const Model::MeshState& meshState, bool useDualQuaternionSkinning) { + _localTransform = Transform(); + if (useDualQuaternionSkinning) { + if (meshState.clusterDualQuaternions.size() == 1 || meshState.clusterDualQuaternions.size() == 2) { + const auto& dq = meshState.clusterDualQuaternions[0]; + _localTransform = Transform(dq.getRotation(), + dq.getScale(), + dq.getTranslation()); + } + } else { + if (meshState.clusterMatrices.size() == 1 || meshState.clusterMatrices.size() == 2) { + _localTransform = Transform(meshState.clusterMatrices[0]); + } + } + + _parentTransform = modelTransform; + _worldBound = _adjustedLocalBound; + _worldBound.transform(_parentTransform); +} + +void ModelMeshPartPayload::bindMesh(gpu::Batch& batch) { + batch.setIndexBuffer(gpu::UINT32, (_drawMesh->getIndexBuffer()._buffer), 0); + batch.setInputFormat((_drawMesh->getVertexFormat())); + if (_meshBlendshapeBuffer) { + batch.setResourceBuffer(0, _meshBlendshapeBuffer); + } + batch.setInputStream(0, _drawMesh->getVertexStream()); +} + +void ModelMeshPartPayload::bindTransform(gpu::Batch& batch, const Transform& transform, RenderArgs::RenderMode renderMode) const { + if (_clusterBuffer) { + batch.setUniformBuffer(graphics::slot::buffer::Skinning, _clusterBuffer); + } + batch.setModelTransform(transform); +} + +void ModelMeshPartPayload::drawCall(gpu::Batch& batch) const { + batch.drawIndexed(gpu::TRIANGLES, _drawPart._numIndices, _drawPart._startIndex); } -// Note that this method is called for models but not for shapes void ModelMeshPartPayload::updateKey(const render::ItemKey& key) { ItemKey::Builder builder(key); builder.withTypeShape(); @@ -480,26 +285,25 @@ void ModelMeshPartPayload::setShapeKey(bool invalidateShapeKey, PrimitiveMode pr _shapeKey = builder.build(); } +ItemKey ModelMeshPartPayload::getKey() const { + return _itemKey; +} + +Item::Bound ModelMeshPartPayload::getBound() const { + graphics::MaterialPointer material = _drawMaterials.empty() ? nullptr : _drawMaterials.top().material; + if (material && material->isProcedural() && material->isReady()) { + auto procedural = std::static_pointer_cast(_drawMaterials.top().material); + if (procedural->hasVertexShader() && procedural->hasBoundOperator()) { + return procedural->getBound(); + } + } + return _worldBound; +} + ShapeKey ModelMeshPartPayload::getShapeKey() const { return _shapeKey; } -void ModelMeshPartPayload::bindMesh(gpu::Batch& batch) { - batch.setIndexBuffer(gpu::UINT32, (_drawMesh->getIndexBuffer()._buffer), 0); - batch.setInputFormat((_drawMesh->getVertexFormat())); - if (_meshBlendshapeBuffer) { - batch.setResourceBuffer(0, _meshBlendshapeBuffer); - } - batch.setInputStream(0, _drawMesh->getVertexStream()); -} - -void ModelMeshPartPayload::bindTransform(gpu::Batch& batch, RenderArgs::RenderMode renderMode) const { - if (_clusterBuffer) { - batch.setUniformBuffer(graphics::slot::buffer::Skinning, _clusterBuffer); - } - batch.setModelTransform(_transform); -} - void ModelMeshPartPayload::render(RenderArgs* args) { PerformanceTimer perfTimer("ModelMeshPartPayload::render"); @@ -509,7 +313,12 @@ void ModelMeshPartPayload::render(RenderArgs* args) { gpu::Batch& batch = *(args->_batch); - bindTransform(batch, args->_renderMode); + Transform transform = _parentTransform; + transform.setRotation(BillboardModeHelpers::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, + args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? BillboardModeHelpers::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition())); + + Transform modelTransform = transform.worldTransform(_localTransform); + bindTransform(batch, modelTransform, args->_renderMode); //Bind the index buffer and vertex buffer and Blend shapes if needed bindMesh(batch); @@ -528,7 +337,7 @@ void ModelMeshPartPayload::render(RenderArgs* args) { auto& schema = _drawMaterials.getSchemaBuffer().get(); glm::vec4 outColor = glm::vec4(ColorUtils::tosRGBVec3(schema._albedo), schema._opacity); outColor = procedural->getColor(outColor); - procedural->prepare(batch, _drawTransform.getTranslation(), _drawTransform.getScale(), _drawTransform.getRotation(), _created, + procedural->prepare(batch, transform.getTranslation(), transform.getScale(), transform.getRotation(), _created, ProceduralProgramKey(outColor.a < 1.0f, _shapeKey.isDeformed(), _shapeKey.isDualQuatSkinned())); batch._glColor4f(outColor.r, outColor.g, outColor.b, outColor.a); } else { @@ -548,36 +357,18 @@ void ModelMeshPartPayload::render(RenderArgs* args) { args->_details._trianglesRendered += _drawPart._numIndices / INDICES_PER_TRIANGLE; } -void ModelMeshPartPayload::computeAdjustedLocalBound(const std::vector& clusterMatrices) { - _adjustedLocalBound = _localBound; - if (clusterMatrices.size() > 0) { - _adjustedLocalBound.transform(clusterMatrices.back()); - - for (int i = 0; i < (int)clusterMatrices.size() - 1; ++i) { - AABox clusterBound = _localBound; - clusterBound.transform(clusterMatrices[i]); - _adjustedLocalBound += clusterBound; - } - } -} - -void ModelMeshPartPayload::computeAdjustedLocalBound(const std::vector& clusterDualQuaternions) { - _adjustedLocalBound = _localBound; - if (clusterDualQuaternions.size() > 0) { - Transform rootTransform(clusterDualQuaternions.back().getRotation(), - clusterDualQuaternions.back().getScale(), - clusterDualQuaternions.back().getTranslation()); - _adjustedLocalBound.transform(rootTransform); - - for (int i = 0; i < (int)clusterDualQuaternions.size() - 1; ++i) { - AABox clusterBound = _localBound; - Transform transform(clusterDualQuaternions[i].getRotation(), - clusterDualQuaternions[i].getScale(), - clusterDualQuaternions[i].getTranslation()); - clusterBound.transform(transform); - _adjustedLocalBound += clusterBound; +bool ModelMeshPartPayload::passesZoneOcclusionTest(const std::unordered_set& containingZones) const { + if (!_renderWithZones.isEmpty()) { + if (!containingZones.empty()) { + for (auto renderWithZone : _renderWithZones) { + if (containingZones.find(renderWithZone) != containingZones.end()) { + return true; + } + } } + return false; } + return true; } void ModelMeshPartPayload::setBlendshapeBuffer(const std::unordered_map& blendshapeBuffers, const QVector& blendedMeshSizes) { @@ -596,3 +387,37 @@ void ModelMeshPartPayload::setBlendshapeBuffer(const std::unordered_map const ItemKey payloadGetKey(const ModelMeshPartPayload::Pointer& payload) { + if (payload) { + return payload->getKey(); + } + return ItemKey::Builder::opaqueShape(); // for lack of a better idea +} + +template <> const Item::Bound payloadGetBound(const ModelMeshPartPayload::Pointer& payload) { + if (payload) { + return payload->getBound(); + } + return Item::Bound(); +} + +template <> const ShapeKey shapeGetShapeKey(const ModelMeshPartPayload::Pointer& payload) { + if (payload) { + return payload->getShapeKey(); + } + return ShapeKey::Builder::invalid(); +} + +template <> void payloadRender(const ModelMeshPartPayload::Pointer& payload, RenderArgs* args) { + return payload->render(args); +} + +template <> bool payloadPassesZoneOcclusionTest(const ModelMeshPartPayload::Pointer& payload, const std::unordered_set& containingZones) { + if (payload) { + return payload->passesZoneOcclusionTest(containingZones); + } + return false; +} +} diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index 8ed799bd74..63ccb85470 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -12,147 +12,94 @@ #ifndef hifi_MeshPartPayload_h #define hifi_MeshPartPayload_h -#include - -#include - -#include - -#include - #include "Model.h" -class Model; +#include +#include +#include -class MeshPartPayload { +class ModelMeshPartPayload { public: - MeshPartPayload() = default; - MeshPartPayload(const std::shared_ptr& mesh, int partIndex, graphics::MaterialPointer material, const uint64_t& created); - virtual ~MeshPartPayload() = default; - - typedef render::Payload Payload; + typedef render::Payload Payload; typedef Payload::DataPointer Pointer; - virtual void updateKey(const render::ItemKey& key); + ModelMeshPartPayload(ModelPointer model, int meshIndex, int partIndex, int shapeIndex, const Transform& transform, const uint64_t& created); virtual void updateMeshPart(const std::shared_ptr& drawMesh, int partIndex); - virtual void notifyLocationChanged() {} - void updateTransform(const Transform& transform, const Transform& offsetTransform); + void updateClusterBuffer(const std::vector& clusterMatrices); // matrix palette skinning + void updateClusterBuffer(const std::vector& clusterDualQuaternions); // dual quaternion skinning - // Render Item interface - virtual render::ItemKey getKey() const; - virtual render::Item::Bound getBound() const; - virtual render::ShapeKey getShapeKey() const; - virtual void render(RenderArgs* args); + void computeAdjustedLocalBound(const std::vector& clusterMatrices); // matrix palette skinning + void computeAdjustedLocalBound(const std::vector& clusterDualQuaternions); // dual quaternion skinning + + void updateTransformForSkinnedMesh(const Transform& modelTransform, const Model::MeshState& meshState, bool useDualQuaternionSkinning); // ModelMeshPartPayload functions to perform render + void bindMesh(gpu::Batch& batch); + virtual void bindTransform(gpu::Batch& batch, const Transform& transform, RenderArgs::RenderMode renderMode) const; void drawCall(gpu::Batch& batch) const; - virtual void bindMesh(gpu::Batch& batch); - virtual void bindTransform(gpu::Batch& batch, RenderArgs::RenderMode renderMode) const; - // Payload resource cached values - Transform _drawTransform; - Transform _transform; - int _partIndex = 0; - bool _hasColorAttrib { false }; + void updateKey(const render::ItemKey& key); + void setShapeKey(bool invalidateShapeKey, PrimitiveMode primitiveMode, bool useDualQuaternionSkinning); - graphics::Box _localBound; - graphics::Box _adjustedLocalBound; - mutable graphics::Box _worldBound; - std::shared_ptr _drawMesh; - - graphics::MultiMaterial _drawMaterials; - graphics::Mesh::Part _drawPart; + // Render Item interface + render::ItemKey getKey() const; + render::Item::Bound getBound() const; + render::ShapeKey getShapeKey() const; + void render(RenderArgs* args); size_t getVerticesCount() const { return _drawMesh ? _drawMesh->getNumVertices() : 0; } size_t getMaterialTextureSize() { return _drawMaterials.getTextureSize(); } int getMaterialTextureCount() { return _drawMaterials.getTextureCount(); } bool hasTextureInfo() const { return _drawMaterials.hasTextureInfo(); } - void addMaterial(graphics::MaterialLayer material); - void removeMaterial(graphics::MaterialPointer material); - + void setCauterized(bool cauterized) { _cauterized = cauterized; } void setCullWithParent(bool value) { _cullWithParent = value; } - void setRenderWithZones(const QVector& renderWithZones) { _renderWithZones = renderWithZones; } + void setBillboardMode(BillboardMode billboardMode) { _billboardMode = billboardMode; } bool passesZoneOcclusionTest(const std::unordered_set& containingZones) const; - static bool enableMaterialProceduralShaders; - -protected: - render::ItemKey _itemKey{ render::ItemKey::Builder::opaqueShape().build() }; - bool _cullWithParent { false }; - QVector _renderWithZones; - uint64_t _created; -}; - -namespace render { - template <> const ItemKey payloadGetKey(const MeshPartPayload::Pointer& payload); - template <> const Item::Bound payloadGetBound(const MeshPartPayload::Pointer& payload); - template <> const ShapeKey shapeGetShapeKey(const MeshPartPayload::Pointer& payload); - template <> void payloadRender(const MeshPartPayload::Pointer& payload, RenderArgs* args); - template <> bool payloadPassesZoneOcclusionTest(const MeshPartPayload::Pointer& payload, const std::unordered_set& containingZones); -} - -class ModelMeshPartPayload : public MeshPartPayload { -public: - ModelMeshPartPayload(ModelPointer model, int meshIndex, int partIndex, int shapeIndex, const Transform& transform, const Transform& offsetTransform, const uint64_t& created); - - typedef render::Payload Payload; - typedef Payload::DataPointer Pointer; - - void notifyLocationChanged() override; - - void updateKey(const render::ItemKey& key) override; - - // matrix palette skinning - void updateClusterBuffer(const std::vector& clusterMatrices); - - // dual quaternion skinning - void updateClusterBuffer(const std::vector& clusterDualQuaternions); - void updateTransformForSkinnedMesh(const Transform& renderTransform, const Transform& boundTransform); - - // Render Item interface - render::ShapeKey getShapeKey() const override; - void render(RenderArgs* args) override; - - void setShapeKey(bool invalidateShapeKey, PrimitiveMode primitiveMode, bool useDualQuaternionSkinning); - void setCauterized(bool cauterized) { _cauterized = cauterized; } - - // ModelMeshPartPayload functions to perform render - void bindMesh(gpu::Batch& batch) override; - void bindTransform(gpu::Batch& batch, RenderArgs::RenderMode renderMode) const override; - - // matrix palette skinning - void computeAdjustedLocalBound(const std::vector& clusterMatrices); - - // dual quaternion skinning - void computeAdjustedLocalBound(const std::vector& clusterDualQuaternions); - - gpu::BufferPointer _clusterBuffer; - - enum class ClusterBufferType { Matrices, DualQuaternions }; - ClusterBufferType _clusterBufferType { ClusterBufferType::Matrices }; - - int _meshIndex; - int _shapeID; - - bool _isSkinned{ false }; - bool _isBlendShaped { false }; - bool _hasTangents { false }; + void addMaterial(graphics::MaterialLayer material) { _drawMaterials.push(material); } + void removeMaterial(graphics::MaterialPointer material) { _drawMaterials.remove(material); } void setBlendshapeBuffer(const std::unordered_map& blendshapeBuffers, const QVector& blendedMeshSizes); + static bool enableMaterialProceduralShaders; + private: - void initCache(const ModelPointer& model); + void initCache(const ModelPointer& model, int shapeID); + + int _meshIndex; + std::shared_ptr _drawMesh; + graphics::Mesh::Part _drawPart; + graphics::MultiMaterial _drawMaterials; + + gpu::BufferPointer _clusterBuffer; + enum class ClusterBufferType { Matrices, DualQuaternions }; + ClusterBufferType _clusterBufferType { ClusterBufferType::Matrices }; gpu::BufferPointer _meshBlendshapeBuffer; int _meshNumVertices; + + render::ItemKey _itemKey { render::ItemKey::Builder::opaqueShape().build() }; render::ShapeKey _shapeKey { render::ShapeKey::Builder::invalid() }; + + bool _isSkinned { false }; + bool _isBlendShaped { false }; + bool _hasTangents { false }; bool _prevUseDualQuaternionSkinning { false }; bool _cauterized { false }; + bool _cullWithParent { false }; + QVector _renderWithZones; + BillboardMode _billboardMode; + uint64_t _created; + Transform _localTransform; + Transform _parentTransform; + graphics::Box _localBound; + graphics::Box _adjustedLocalBound; + mutable graphics::Box _worldBound; }; namespace render { diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 9ad343639d..9bf1596a04 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -226,6 +226,7 @@ void Model::updateRenderItems() { modelTransform.setScale(glm::vec3(1.0f)); PrimitiveMode primitiveMode = self->getPrimitiveMode(); + BillboardMode billboardMode = self->getBillboardMode(); auto renderWithZones = self->getRenderWithZones(); auto renderItemKeyGlobalFlags = self->getRenderItemKeyGlobalFlags(); bool cauterized = self->isCauterized(); @@ -242,7 +243,7 @@ void Model::updateRenderItems() { bool useDualQuaternionSkinning = self->getUseDualQuaternionSkinning(); transaction.updateItem(itemID, [modelTransform, meshState, useDualQuaternionSkinning, - invalidatePayloadShapeKey, primitiveMode, renderItemKeyGlobalFlags, + invalidatePayloadShapeKey, primitiveMode, billboardMode, renderItemKeyGlobalFlags, cauterized, renderWithZones](ModelMeshPartPayload& data) { if (useDualQuaternionSkinning) { data.updateClusterBuffer(meshState.clusterDualQuaternions); @@ -252,25 +253,11 @@ void Model::updateRenderItems() { data.computeAdjustedLocalBound(meshState.clusterMatrices); } - Transform renderTransform = modelTransform; - - if (useDualQuaternionSkinning) { - if (meshState.clusterDualQuaternions.size() == 1 || meshState.clusterDualQuaternions.size() == 2) { - const auto& dq = meshState.clusterDualQuaternions[0]; - Transform transform(dq.getRotation(), - dq.getScale(), - dq.getTranslation()); - renderTransform = modelTransform.worldTransform(Transform(transform)); - } - } else { - if (meshState.clusterMatrices.size() == 1 || meshState.clusterMatrices.size() == 2) { - renderTransform = modelTransform.worldTransform(Transform(meshState.clusterMatrices[0])); - } - } - data.updateTransformForSkinnedMesh(renderTransform, modelTransform); + data.updateTransformForSkinnedMesh(modelTransform, meshState, useDualQuaternionSkinning); data.setCauterized(cauterized); data.setRenderWithZones(renderWithZones); + data.setBillboardMode(billboardMode); data.updateKey(renderItemKeyGlobalFlags); data.setShapeKey(invalidatePayloadShapeKey, primitiveMode, useDualQuaternionSkinning); }); @@ -987,6 +974,31 @@ void Model::setPrimitiveMode(PrimitiveMode primitiveMode, const render::ScenePoi } } +void Model::setBillboardMode(BillboardMode billboardMode, const render::ScenePointer& scene) { + if (_billboardMode != billboardMode) { + _billboardMode = billboardMode; + if (!scene) { + _needsFixupInScene = true; + return; + } + + bool useDualQuaternionSkinning = _useDualQuaternionSkinning; + std::unordered_map shouldInvalidatePayloadShapeKeyMap; + + for (auto& shape : _modelMeshRenderItemShapes) { + shouldInvalidatePayloadShapeKeyMap[shape.meshIndex] = shouldInvalidatePayloadShapeKey(shape.meshIndex); + } + + render::Transaction transaction; + for (auto item : _modelMeshRenderItemIDs) { + transaction.updateItem(item, [billboardMode](ModelMeshPartPayload& data) { + data.setBillboardMode(billboardMode); + }); + } + scene->enqueueTransaction(transaction); + } +} + void Model::setCullWithParent(bool cullWithParent, const render::ScenePointer& scene) { if (_cullWithParent != cullWithParent) { _cullWithParent = cullWithParent; @@ -1017,9 +1029,8 @@ void Model::setRenderWithZones(const QVector& renderWithZones, const rend } render::Transaction transaction; - auto renderItemsKey = _renderItemKeyGlobalFlags; for (auto item : _modelMeshRenderItemIDs) { - transaction.updateItem(item, [renderWithZones, renderItemsKey](ModelMeshPartPayload& data) { + transaction.updateItem(item, [renderWithZones](ModelMeshPartPayload& data) { data.setRenderWithZones(renderWithZones); }); } @@ -1545,10 +1556,6 @@ void Model::createRenderItemSet() { transform.setTranslation(_translation); transform.setRotation(_rotation); - Transform offset; - offset.setScale(_scale); - offset.postTranslate(_offset); - // Run through all of the meshes, and place them into their segregated, but unsorted buckets int shapeID = 0; uint32_t numMeshes = (uint32_t)meshes.size(); @@ -1561,7 +1568,7 @@ void Model::createRenderItemSet() { // Create the render payloads int numParts = (int)mesh->getNumParts(); for (int partIndex = 0; partIndex < numParts; partIndex++) { - _modelMeshRenderItems << std::make_shared(shared_from_this(), i, partIndex, shapeID, transform, offset, _created); + _modelMeshRenderItems << std::make_shared(shared_from_this(), i, partIndex, shapeID, transform, _created); auto material = getGeometry()->getShapeMaterial(shapeID); _modelMeshMaterialNames.push_back(material ? material->getName() : ""); _modelMeshRenderItemShapes.emplace_back(ShapeInfo{ (int)i }); diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 1e7ab55d5a..3085dcfc6f 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -38,6 +38,7 @@ #include "TextureCache.h" #include "Rig.h" #include "PrimitiveMode.h" +#include "BillboardMode.h" // Use dual quaternion skinning! // Must match define in Skinning.slh @@ -121,6 +122,9 @@ public: void setPrimitiveMode(PrimitiveMode primitiveMode, const render::ScenePointer& scene = nullptr); PrimitiveMode getPrimitiveMode() const { return _primitiveMode; } + void setBillboardMode(BillboardMode billboardMode, const render::ScenePointer& scene = nullptr); + BillboardMode getBillboardMode() const { return _billboardMode; } + void setCullWithParent(bool value, const render::ScenePointer& scene = nullptr); void setRenderWithZones(const QVector& renderWithZones, const render::ScenePointer& scene = nullptr); @@ -447,6 +451,7 @@ protected: virtual void createRenderItemSet(); PrimitiveMode _primitiveMode { PrimitiveMode::SOLID }; + BillboardMode _billboardMode { BillboardMode::NONE }; bool _useDualQuaternionSkinning { false }; // debug rendering support diff --git a/libraries/shared/src/BillboardMode.cpp b/libraries/shared/src/BillboardMode.cpp index 4b6af5db33..8243cf772d 100644 --- a/libraries/shared/src/BillboardMode.cpp +++ b/libraries/shared/src/BillboardMode.cpp @@ -15,6 +15,8 @@ const char* billboardModeNames[] = { }; static const size_t BILLBOARD_MODE_NAMES = (sizeof(billboardModeNames) / sizeof(billboardModeNames[0])); +std::function BillboardModeHelpers::_getBillboardRotationOperator = [](const glm::vec3&, const glm::quat& rotation, BillboardMode, const glm::vec3&, bool) { return rotation; }; +std::function BillboardModeHelpers::_getPrimaryViewFrustumPositionOperator = []() { return glm::vec3(0.0f); }; QString BillboardModeHelpers::getNameForBillboardMode(BillboardMode mode) { if (((int)mode <= 0) || ((int)mode >= (int)BILLBOARD_MODE_NAMES)) { @@ -22,4 +24,4 @@ QString BillboardModeHelpers::getNameForBillboardMode(BillboardMode mode) { } return billboardModeNames[(int)mode]; -} \ No newline at end of file +} diff --git a/libraries/shared/src/BillboardMode.h b/libraries/shared/src/BillboardMode.h index aa00ce34aa..31f11766d8 100644 --- a/libraries/shared/src/BillboardMode.h +++ b/libraries/shared/src/BillboardMode.h @@ -9,8 +9,13 @@ #ifndef hifi_BillboardMode_h #define hifi_BillboardMode_h +#include + #include "QString" +#include "glm/glm.hpp" +#include "glm/gtc/quaternion.hpp" + /**jsdoc *

How an entity is billboarded.

* @@ -37,7 +42,15 @@ enum class BillboardMode { class BillboardModeHelpers { public: static QString getNameForBillboardMode(BillboardMode mode); + + static void setBillboardRotationOperator(std::function getBillboardRotationOperator) { _getBillboardRotationOperator = getBillboardRotationOperator; } + static glm::quat getBillboardRotation(const glm::vec3& position, const glm::quat& rotation, BillboardMode billboardMode, const glm::vec3& frustumPos, bool rotate90x = false) { return _getBillboardRotationOperator(position, rotation, billboardMode, frustumPos, rotate90x); } + static void setPrimaryViewFrustumPositionOperator(std::function getPrimaryViewFrustumPositionOperator) { _getPrimaryViewFrustumPositionOperator = getPrimaryViewFrustumPositionOperator; } + static glm::vec3 getPrimaryViewFrustumPosition() { return _getPrimaryViewFrustumPositionOperator(); } + +private: + static std::function _getBillboardRotationOperator; + static std::function _getPrimaryViewFrustumPositionOperator; }; #endif // hifi_BillboardMode_h - From 1f71a23082bbc415a7a12ba9b5a2001a1d5dc4cf Mon Sep 17 00:00:00 2001 From: HifiExperiments Date: Sun, 17 Jan 2021 13:09:09 -0800 Subject: [PATCH 12/33] optimize picking --- interface/src/avatar/AvatarManager.cpp | 6 +- .../src/RenderableModelEntityItem.cpp | 10 +-- .../src/RenderableModelEntityItem.h | 6 +- .../src/RenderablePolyVoxEntityItem.cpp | 4 +- .../src/RenderablePolyVoxEntityItem.h | 6 +- libraries/entities/src/EntityItem.cpp | 10 --- libraries/entities/src/EntityItem.h | 8 +-- libraries/entities/src/EntityTree.cpp | 18 +++-- libraries/entities/src/EntityTreeElement.cpp | 54 +++++++-------- libraries/entities/src/EntityTreeElement.h | 10 +-- libraries/entities/src/GizmoEntityItem.cpp | 8 +-- libraries/entities/src/GizmoEntityItem.h | 7 +- libraries/entities/src/GridEntityItem.cpp | 54 --------------- libraries/entities/src/GridEntityItem.h | 10 --- libraries/entities/src/ImageEntityItem.cpp | 54 --------------- libraries/entities/src/ImageEntityItem.h | 10 --- libraries/entities/src/LightEntityItem.cpp | 6 +- libraries/entities/src/LightEntityItem.h | 6 +- libraries/entities/src/LineEntityItem.h | 6 +- libraries/entities/src/PolyLineEntityItem.h | 6 +- libraries/entities/src/PolyVoxEntityItem.h | 6 +- libraries/entities/src/ShapeEntityItem.cpp | 67 +++++++++---------- libraries/entities/src/ShapeEntityItem.h | 11 +-- libraries/entities/src/TextEntityItem.cpp | 54 --------------- libraries/entities/src/TextEntityItem.h | 10 --- libraries/entities/src/WebEntityItem.cpp | 56 ---------------- libraries/entities/src/WebEntityItem.h | 10 --- libraries/entities/src/ZoneEntityItem.cpp | 6 +- libraries/entities/src/ZoneEntityItem.h | 6 +- libraries/render-utils/src/Model.cpp | 14 ++-- libraries/render-utils/src/Model.h | 6 +- 31 files changed, 140 insertions(+), 405 deletions(-) diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 32e725388c..24d9379ab9 100755 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -767,6 +767,7 @@ RayToAvatarIntersectionResult AvatarManager::findRayIntersectionVector(const Pic glm::vec3 rayDirectionInv = { rayDirection.x != 0.0f ? 1.0f / rayDirection.x : INFINITY, rayDirection.y != 0.0f ? 1.0f / rayDirection.y : INFINITY, rayDirection.z != 0.0f ? 1.0f / rayDirection.z : INFINITY }; + glm::vec3 viewFrustumPos = BillboardModeHelpers::getPrimaryViewFrustumPosition(); for (auto &hit : physicsResults) { auto avatarID = hit._intersectWithAvatar; @@ -842,7 +843,7 @@ RayToAvatarIntersectionResult AvatarManager::findRayIntersectionVector(const Pic BoxFace subMeshFace = BoxFace::UNKNOWN_FACE; glm::vec3 subMeshSurfaceNormal; QVariantMap subMeshExtraInfo; - if (avatar->getSkeletonModel()->findRayIntersectionAgainstSubMeshes(defaultFrameRayOrigin, defaultFrameRayDirection, subMeshDistance, subMeshFace, subMeshSurfaceNormal, subMeshExtraInfo, true, false)) { + if (avatar->getSkeletonModel()->findRayIntersectionAgainstSubMeshes(defaultFrameRayOrigin, defaultFrameRayDirection, viewFrustumPos, subMeshDistance, subMeshFace, subMeshSurfaceNormal, subMeshExtraInfo, true, false)) { rayAvatarResult._distance = subMeshDistance; rayAvatarResult._intersectionPoint = ray.origin + subMeshDistance * rayDirection; rayAvatarResult._intersectionNormal = subMeshSurfaceNormal; @@ -932,6 +933,7 @@ ParabolaToAvatarIntersectionResult AvatarManager::findParabolaIntersectionVector std::sort(sortedAvatars.begin(), sortedAvatars.end(), comparator); } + glm::vec3 viewFrustumPos = BillboardModeHelpers::getPrimaryViewFrustumPosition(); for (auto it = sortedAvatars.begin(); it != sortedAvatars.end(); ++it) { const SortedAvatar& sortedAvatar = *it; // We can exit once avatarCapsuleDistance > bestDistance @@ -944,7 +946,7 @@ ParabolaToAvatarIntersectionResult AvatarManager::findParabolaIntersectionVector glm::vec3 surfaceNormal; QVariantMap extraInfo; SkeletonModelPointer avatarModel = sortedAvatar.second->getSkeletonModel(); - if (avatarModel->findParabolaIntersectionAgainstSubMeshes(pick.origin, pick.velocity, pick.acceleration, parabolicDistance, face, surfaceNormal, extraInfo, true)) { + if (avatarModel->findParabolaIntersectionAgainstSubMeshes(pick.origin, pick.velocity, pick.acceleration, viewFrustumPos, parabolicDistance, face, surfaceNormal, extraInfo, true)) { if (parabolicDistance < result.parabolicDistance) { result.intersects = true; result.avatarID = sortedAvatar.second->getID(); diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index c6765f2321..c8cfb6491a 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -224,26 +224,26 @@ bool RenderableModelEntityItem::supportsDetailedIntersection() const { } bool RenderableModelEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - OctreeElementPointer& element, float& distance, BoxFace& face, + const glm::vec3& viewFrustumPos, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const { auto model = getModel(); if (!model || !model->isLoaded()) { return false; } - return model->findRayIntersectionAgainstSubMeshes(origin, direction, distance, + return model->findRayIntersectionAgainstSubMeshes(origin, direction, viewFrustumPos, distance, face, surfaceNormal, extraInfo, precisionPicking, false); } bool RenderableModelEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, - const glm::vec3& acceleration, OctreeElementPointer& element, float& parabolicDistance, BoxFace& face, - glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const { + const glm::vec3& acceleration, const glm::vec3& viewFrustumPos, OctreeElementPointer& element, + float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const { auto model = getModel(); if (!model || !model->isLoaded()) { return false; } - return model->findParabolaIntersectionAgainstSubMeshes(origin, velocity, acceleration, parabolicDistance, + return model->findParabolaIntersectionAgainstSubMeshes(origin, velocity, acceleration, viewFrustumPos, parabolicDistance, face, surfaceNormal, extraInfo, precisionPicking, false); } diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index 4501f6d88c..29474742c1 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -65,12 +65,12 @@ public: virtual bool supportsDetailedIntersection() const override; virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - OctreeElementPointer& element, float& distance, + const glm::vec3& viewFrustumPos, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const override; virtual bool findDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, - const glm::vec3& acceleration, OctreeElementPointer& element, float& parabolicDistance, - BoxFace& face, glm::vec3& surfaceNormal, + const glm::vec3& acceleration, const glm::vec3& viewFrustumPos, OctreeElementPointer& element, + float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const override; virtual void setShapeType(ShapeType type) override; diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index 5b6c0c8b70..e3a29fc99c 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -526,7 +526,7 @@ public: #endif bool RenderablePolyVoxEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - OctreeElementPointer& element, + const glm::vec3& viewFrustumPos, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const { // TODO -- correctly pick against marching-cube generated meshes @@ -567,7 +567,7 @@ bool RenderablePolyVoxEntityItem::findDetailedRayIntersection(const glm::vec3& o } bool RenderablePolyVoxEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, - const glm::vec3& acceleration, OctreeElementPointer& element, + const glm::vec3& acceleration, const glm::vec3& viewFrustumPos, OctreeElementPointer& element, float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const { // TODO -- correctly pick against marching-cube generated meshes diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h index d4bcc4d19f..c1c35a21c8 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h @@ -71,12 +71,12 @@ public: virtual bool supportsDetailedIntersection() const override { return true; } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - OctreeElementPointer& element, float& distance, + const glm::vec3& viewFrustumPos, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const override; virtual bool findDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, const vec3& accleration, - OctreeElementPointer& element, float& parabolicDistance, - BoxFace& face, glm::vec3& surfaceNormal, + const glm::vec3& viewFrustumPos, OctreeElementPointer& element, + float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const override; virtual void setVoxelData(const QByteArray& voxelData) override; diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 68e824f8cc..e5e84abae3 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -1907,16 +1907,6 @@ void EntityItem::setScaledDimensions(const glm::vec3& value) { setUnscaledDimensions(value / parentScale); } -glm::vec3 EntityItem::getRaycastDimensions() const { - glm::vec3 dimensions = getScaledDimensions(); - if (getBillboardMode() != BillboardMode::NONE) { - float max = glm::max(dimensions.x, glm::max(dimensions.y, dimensions.z)); - const float SQRT_2 = 1.41421356237f; - return glm::vec3(SQRT_2 * max); - } - return dimensions; -} - void EntityItem::setUnscaledDimensions(const glm::vec3& value) { glm::vec3 newDimensions = glm::max(value, glm::vec3(ENTITY_ITEM_MIN_DIMENSION)); const float MIN_SCALE_CHANGE_SQUARED = 1.0e-6f; diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 288f1682c7..2acb73abbf 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -175,12 +175,12 @@ public: virtual bool supportsDetailedIntersection() const { return false; } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - OctreeElementPointer& element, float& distance, + const glm::vec3& viewFrustumPos, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const { return true; } virtual bool findDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, - const glm::vec3& acceleration, OctreeElementPointer& element, float& parabolicDistance, - BoxFace& face, glm::vec3& surfaceNormal, + const glm::vec3& acceleration, const glm::vec3& viewFrustumPos, OctreeElementPointer& element, + float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const { return true; } // attributes applicable to all entity types @@ -203,7 +203,6 @@ public: /// Dimensions in meters (0.0 - TREE_SCALE) virtual glm::vec3 getScaledDimensions() const; virtual void setScaledDimensions(const glm::vec3& value); - virtual glm::vec3 getRaycastDimensions() const; glm::vec3 getUnscaledDimensions() const; virtual void setUnscaledDimensions(const glm::vec3& value); @@ -584,6 +583,7 @@ public: void setBillboardMode(BillboardMode value); BillboardMode getBillboardMode() const; + virtual bool getRotateForPicking() const { return false; } signals: void spaceUpdate(std::pair data); diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 24b6f7ccd4..3ed1ad581c 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -798,6 +798,7 @@ public: glm::vec3 origin; glm::vec3 direction; glm::vec3 invDirection; + glm::vec3 viewFrustumPos; const QVector& entityIdsToInclude; const QVector& entityIdsToDiscard; PickFilter searchFilter; @@ -815,7 +816,7 @@ bool evalRayIntersectionOp(const OctreeElementPointer& element, void* extraData) RayArgs* args = static_cast(extraData); bool keepSearching = true; EntityTreeElementPointer entityTreeElementPointer = std::static_pointer_cast(element); - EntityItemID entityID = entityTreeElementPointer->evalRayIntersection(args->origin, args->direction, + EntityItemID entityID = entityTreeElementPointer->evalRayIntersection(args->origin, args->direction, args->viewFrustumPos, args->element, args->distance, args->face, args->surfaceNormal, args->entityIdsToInclude, args->entityIdsToDiscard, args->searchFilter, args->extraInfo); if (!entityID.isNull()) { @@ -837,7 +838,8 @@ float evalRayIntersectionSortingOp(const OctreeElementPointer& element, void* ex float boundDistance = FLT_MAX; BoxFace face; glm::vec3 surfaceNormal; - if (entityTreeElementPointer->getAACube().findRayIntersection(args->origin, args->direction, args->invDirection, boundDistance, face, surfaceNormal)) { + if (entityTreeElementPointer->getAACube().findRayIntersection(args->origin, args->direction, args->invDirection, + boundDistance, face, surfaceNormal)) { // Don't add this cell if it's already farther than our best distance so far if (boundDistance < args->distance) { distance = boundDistance; @@ -857,7 +859,7 @@ EntityItemID EntityTree::evalRayIntersection(const glm::vec3& origin, const glm: vec3 dirReciprocal = glm::vec3(direction.x == 0.0f ? 0.0f : 1.0f / direction.x, direction.y == 0.0f ? 0.0f : 1.0f / direction.y, direction.z == 0.0f ? 0.0f : 1.0f / direction.z); - RayArgs args = { origin, direction, dirReciprocal, entityIdsToInclude, entityIdsToDiscard, + RayArgs args = { origin, direction, dirReciprocal, BillboardModeHelpers::getPrimaryViewFrustumPosition(), entityIdsToInclude, entityIdsToDiscard, searchFilter, element, distance, face, surfaceNormal, extraInfo, EntityItemID() }; distance = FLT_MAX; @@ -879,6 +881,7 @@ public: glm::vec3 origin; glm::vec3 velocity; glm::vec3 acceleration; + glm::vec3 viewFrustumPos; const QVector& entityIdsToInclude; const QVector& entityIdsToDiscard; PickFilter searchFilter; @@ -896,7 +899,7 @@ bool evalParabolaIntersectionOp(const OctreeElementPointer& element, void* extra ParabolaArgs* args = static_cast(extraData); bool keepSearching = true; EntityTreeElementPointer entityTreeElementPointer = std::static_pointer_cast(element); - EntityItemID entityID = entityTreeElementPointer->evalParabolaIntersection(args->origin, args->velocity, args->acceleration, + EntityItemID entityID = entityTreeElementPointer->evalParabolaIntersection(args->origin, args->velocity, args->acceleration, args->viewFrustumPos, args->element, args->parabolicDistance, args->face, args->surfaceNormal, args->entityIdsToInclude, args->entityIdsToDiscard, args->searchFilter, args->extraInfo); if (!entityID.isNull()) { @@ -918,7 +921,8 @@ float evalParabolaIntersectionSortingOp(const OctreeElementPointer& element, voi float boundDistance = FLT_MAX; BoxFace face; glm::vec3 surfaceNormal; - if (entityTreeElementPointer->getAACube().findParabolaIntersection(args->origin, args->velocity, args->acceleration, boundDistance, face, surfaceNormal)) { + if (entityTreeElementPointer->getAACube().findParabolaIntersection(args->origin, args->velocity, args->acceleration, + boundDistance, face, surfaceNormal)) { // Don't add this cell if it's already farther than our best distance so far if (boundDistance < args->parabolicDistance) { distance = boundDistance; @@ -934,8 +938,8 @@ EntityItemID EntityTree::evalParabolaIntersection(const PickParabola& parabola, OctreeElementPointer& element, glm::vec3& intersection, float& distance, float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, Octree::lockType lockType, bool* accurateResult) { - ParabolaArgs args = { parabola.origin, parabola.velocity, parabola.acceleration, entityIdsToInclude, entityIdsToDiscard, - searchFilter, element, parabolicDistance, face, surfaceNormal, extraInfo, EntityItemID() }; + ParabolaArgs args = { parabola.origin, parabola.velocity, parabola.acceleration, BillboardModeHelpers::getPrimaryViewFrustumPosition(), + entityIdsToInclude, entityIdsToDiscard, searchFilter, element, parabolicDistance, face, surfaceNormal, extraInfo, EntityItemID() }; parabolicDistance = FLT_MAX; distance = FLT_MAX; diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index afbb139d5f..4387647383 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -162,7 +162,7 @@ bool EntityTreeElement::checkFilterSettings(const EntityItemPointer& entity, Pic return true; } -EntityItemID EntityTreeElement::evalRayIntersection(const glm::vec3& origin, const glm::vec3& direction, +EntityItemID EntityTreeElement::evalRayIntersection(const glm::vec3& origin, const glm::vec3& direction, const glm::vec3& viewFrustumPos, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, const QVector& entityIdsToInclude, const QVector& entityIdsToDiscard, PickFilter searchFilter, QVariantMap& extraInfo) { @@ -177,7 +177,7 @@ EntityItemID EntityTreeElement::evalRayIntersection(const glm::vec3& origin, con QVariantMap localExtraInfo; float distanceToElementDetails = distance; - EntityItemID entityID = evalDetailedRayIntersection(origin, direction, element, distanceToElementDetails, + EntityItemID entityID = evalDetailedRayIntersection(origin, direction, viewFrustumPos, element, distanceToElementDetails, localFace, localSurfaceNormal, entityIdsToInclude, entityIdsToDiscard, searchFilter, localExtraInfo); if (!entityID.isNull() && distanceToElementDetails < distance) { distance = distanceToElementDetails; @@ -189,7 +189,7 @@ EntityItemID EntityTreeElement::evalRayIntersection(const glm::vec3& origin, con return result; } -EntityItemID EntityTreeElement::evalDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, +EntityItemID EntityTreeElement::evalDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, const glm::vec3& viewFrustumPos, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, const QVector& entityIdsToInclude, const QVector& entityIDsToDiscard, PickFilter searchFilter, QVariantMap& extraInfo) { @@ -222,11 +222,12 @@ EntityItemID EntityTreeElement::evalDetailedRayIntersection(const glm::vec3& ori 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(), BillboardModeHelpers::getPrimaryViewFrustumPosition())); + glm::mat4 rotation = glm::mat4_cast(BillboardModeHelpers::getBillboardRotation(position, orientation, entity->getBillboardMode(), + viewFrustumPos, entity->getRotateForPicking())); glm::mat4 entityToWorldMatrix = translation * rotation; glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix); - glm::vec3 dimensions = entity->getRaycastDimensions(); + glm::vec3 dimensions = entity->getScaledDimensions(); glm::vec3 registrationPoint = entity->getRegistrationPoint(); glm::vec3 corner = -(dimensions * registrationPoint); @@ -246,7 +247,7 @@ EntityItemID EntityTreeElement::evalDetailedRayIntersection(const glm::vec3& ori // now ask the entity if we actually intersect if (entity->supportsDetailedIntersection()) { QVariantMap localExtraInfo; - if (entity->findDetailedRayIntersection(origin, direction, element, localDistance, + if (entity->findDetailedRayIntersection(origin, direction, viewFrustumPos, element, localDistance, localFace, localSurfaceNormal, localExtraInfo, searchFilter.isPrecise())) { if (localDistance < distance) { distance = localDistance; @@ -300,7 +301,7 @@ bool EntityTreeElement::findSpherePenetration(const glm::vec3& center, float rad } EntityItemID EntityTreeElement::evalParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, - const glm::vec3& acceleration, OctreeElementPointer& element, float& parabolicDistance, + const glm::vec3& acceleration, const glm::vec3& viewFrustumPos, OctreeElementPointer& element, float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, const QVector& entityIdsToInclude, const QVector& entityIdsToDiscard, PickFilter searchFilter, QVariantMap& extraInfo) { @@ -323,7 +324,7 @@ EntityItemID EntityTreeElement::evalParabolaIntersection(const glm::vec3& origin } // Get the normal of the plane, the cross product of two vectors on the plane glm::vec3 normal = glm::normalize(glm::cross(vectorOnPlane, acceleration)); - EntityItemID entityID = evalDetailedParabolaIntersection(origin, velocity, acceleration, normal, element, distanceToElementDetails, + EntityItemID entityID = evalDetailedParabolaIntersection(origin, velocity, acceleration, viewFrustumPos, normal, element, distanceToElementDetails, localFace, localSurfaceNormal, entityIdsToInclude, entityIdsToDiscard, searchFilter, localExtraInfo); if (!entityID.isNull() && distanceToElementDetails < parabolicDistance) { parabolicDistance = distanceToElementDetails; @@ -336,9 +337,9 @@ EntityItemID EntityTreeElement::evalParabolaIntersection(const glm::vec3& origin } EntityItemID EntityTreeElement::evalDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration, - const glm::vec3& normal, OctreeElementPointer& element, float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, - const QVector& entityIdsToInclude, const QVector& entityIDsToDiscard, - PickFilter searchFilter, QVariantMap& extraInfo) { + const glm::vec3& viewFrustumPos,const glm::vec3& normal, OctreeElementPointer& element, float& parabolicDistance, + BoxFace& face, glm::vec3& surfaceNormal, const QVector& entityIdsToInclude, + const QVector& entityIDsToDiscard, PickFilter searchFilter, QVariantMap& extraInfo) { // only called if we do intersect our bounding cube, but find if we actually intersect with entities... EntityItemID entityID; @@ -373,11 +374,12 @@ EntityItemID EntityTreeElement::evalDetailedParabolaIntersection(const glm::vec3 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(), BillboardModeHelpers::getPrimaryViewFrustumPosition())); + glm::mat4 rotation = glm::mat4_cast(BillboardModeHelpers::getBillboardRotation(position, orientation, entity->getBillboardMode(), + viewFrustumPos, entity->getRotateForPicking())); glm::mat4 entityToWorldMatrix = translation * rotation; glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix); - glm::vec3 dimensions = entity->getRaycastDimensions(); + glm::vec3 dimensions = entity->getScaledDimensions(); glm::vec3 registrationPoint = entity->getRegistrationPoint(); glm::vec3 corner = -(dimensions * registrationPoint); @@ -398,7 +400,7 @@ EntityItemID EntityTreeElement::evalDetailedParabolaIntersection(const glm::vec3 // now ask the entity if we actually intersect if (entity->supportsDetailedIntersection()) { QVariantMap localExtraInfo; - if (entity->findDetailedParabolaIntersection(origin, velocity, acceleration, element, localDistance, + if (entity->findDetailedParabolaIntersection(origin, velocity, acceleration, viewFrustumPos, element, localDistance, localFace, localSurfaceNormal, localExtraInfo, searchFilter.isPrecise())) { if (localDistance < parabolicDistance) { parabolicDistance = localDistance; @@ -454,7 +456,7 @@ void EntityTreeElement::evalEntitiesInSphere(const glm::vec3& position, float ra glm::vec3 penetration; if (success && entityBox.findSpherePenetration(position, radius, penetration)) { - glm::vec3 dimensions = entity->getRaycastDimensions(); + glm::vec3 dimensions = entity->getScaledDimensions(); // FIXME - consider allowing the entity to determine penetration so that // entities could presumably do actual hull testing if they wanted to @@ -476,10 +478,8 @@ void EntityTreeElement::evalEntitiesInSphere(const glm::vec3& position, float ra } else { // determine the worldToEntityMatrix that doesn't include scale because // we're going to use the registration aware aa box in the entity frame - 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(), BillboardModeHelpers::getPrimaryViewFrustumPosition())); + glm::mat4 translation = glm::translate(entity->getWorldPosition()); + glm::mat4 rotation = glm::mat4_cast(entity->getWorldOrientation()); glm::mat4 entityToWorldMatrix = translation * rotation; glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix); @@ -510,7 +510,7 @@ void EntityTreeElement::evalEntitiesInSphereWithType(const glm::vec3& position, glm::vec3 penetration; if (success && entityBox.findSpherePenetration(position, radius, penetration)) { - glm::vec3 dimensions = entity->getRaycastDimensions(); + glm::vec3 dimensions = entity->getScaledDimensions(); // FIXME - consider allowing the entity to determine penetration so that // entities could presumably do actual hull testing if they wanted to @@ -532,10 +532,8 @@ void EntityTreeElement::evalEntitiesInSphereWithType(const glm::vec3& position, } else { // determine the worldToEntityMatrix that doesn't include scale because // we're going to use the registration aware aa box in the entity frame - 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(), BillboardModeHelpers::getPrimaryViewFrustumPosition())); + glm::mat4 translation = glm::translate(entity->getWorldPosition()); + glm::mat4 rotation = glm::mat4_cast(entity->getWorldOrientation()); glm::mat4 entityToWorldMatrix = translation * rotation; glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix); @@ -571,7 +569,7 @@ void EntityTreeElement::evalEntitiesInSphereWithName(const glm::vec3& position, glm::vec3 penetration; if (success && entityBox.findSpherePenetration(position, radius, penetration)) { - glm::vec3 dimensions = entity->getRaycastDimensions(); + glm::vec3 dimensions = entity->getScaledDimensions(); // FIXME - consider allowing the entity to determine penetration so that // entities could presumably do actual hull testing if they wanted to @@ -593,10 +591,8 @@ void EntityTreeElement::evalEntitiesInSphereWithName(const glm::vec3& position, } else { // determine the worldToEntityMatrix that doesn't include scale because // we're going to use the registration aware aa box in the entity frame - 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(), BillboardModeHelpers::getPrimaryViewFrustumPosition())); + glm::mat4 translation = glm::translate(entity->getWorldPosition()); + glm::mat4 rotation = glm::mat4_cast(entity->getWorldOrientation()); glm::mat4 entityToWorldMatrix = translation * rotation; glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix); diff --git a/libraries/entities/src/EntityTreeElement.h b/libraries/entities/src/EntityTreeElement.h index f94da44138..dab56132c9 100644 --- a/libraries/entities/src/EntityTreeElement.h +++ b/libraries/entities/src/EntityTreeElement.h @@ -136,24 +136,24 @@ public: static bool checkFilterSettings(const EntityItemPointer& entity, PickFilter searchFilter); virtual bool canPickIntersect() const override { return hasEntities(); } - virtual EntityItemID evalRayIntersection(const glm::vec3& origin, const glm::vec3& direction, + virtual EntityItemID evalRayIntersection(const glm::vec3& origin, const glm::vec3& direction, const glm::vec3& viewFrustumPos, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, const QVector& entityIdsToInclude, const QVector& entityIdsToDiscard, PickFilter searchFilter, QVariantMap& extraInfo); virtual EntityItemID evalDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - OctreeElementPointer& element, float& distance, + const glm::vec3& viewFrustumPos, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, const QVector& entityIdsToInclude, const QVector& entityIdsToDiscard, PickFilter searchFilter, QVariantMap& extraInfo); virtual bool findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration, void** penetratedObject) const override; virtual EntityItemID evalParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, - const glm::vec3& acceleration, OctreeElementPointer& element, float& parabolicDistance, + const glm::vec3& acceleration, const glm::vec3& viewFrustumPos, OctreeElementPointer& element, float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, const QVector& entityIdsToInclude, const QVector& entityIdsToDiscard, PickFilter searchFilter, QVariantMap& extraInfo); virtual EntityItemID evalDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, - const glm::vec3& normal, const glm::vec3& acceleration, OctreeElementPointer& element, float& parabolicDistance, - BoxFace& face, glm::vec3& surfaceNormal, const QVector& entityIdsToInclude, + const glm::vec3& normal, const glm::vec3& acceleration, const glm::vec3& viewFrustumPos, OctreeElementPointer& element, + float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, const QVector& entityIdsToInclude, const QVector& entityIdsToDiscard, PickFilter searchFilter, QVariantMap& extraInfo); template diff --git a/libraries/entities/src/GizmoEntityItem.cpp b/libraries/entities/src/GizmoEntityItem.cpp index 6586d57fde..694371d739 100644 --- a/libraries/entities/src/GizmoEntityItem.cpp +++ b/libraries/entities/src/GizmoEntityItem.cpp @@ -103,7 +103,7 @@ bool GizmoEntityItem::supportsDetailedIntersection() const { } bool GizmoEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - OctreeElementPointer& element, + const glm::vec3& viewFrustumPos, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const { glm::vec3 dimensions = getScaledDimensions(); @@ -111,7 +111,7 @@ bool GizmoEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::quat rotation = getWorldOrientation(); 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(), BillboardModeHelpers::getPrimaryViewFrustumPosition(), false); + rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, getBillboardMode(), viewFrustumPos); if (findRayRectangleIntersection(origin, direction, rotation, position, xyDimensions, distance)) { glm::vec3 hitPosition = origin + (distance * direction); @@ -137,7 +137,7 @@ bool GizmoEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const } bool GizmoEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration, - OctreeElementPointer& element, float& parabolicDistance, + const glm::vec3& viewFrustumPos, OctreeElementPointer& element, float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const { //// Scale the dimensions by the diameter @@ -146,7 +146,7 @@ bool GizmoEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin, glm::quat rotation = getWorldOrientation(); rotation *= glm::angleAxis(-(float)M_PI_2, Vectors::RIGHT); glm::vec3 position = getWorldPosition(); - rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, getBillboardMode(), BillboardModeHelpers::getPrimaryViewFrustumPosition(), true); + rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, getBillboardMode(), viewFrustumPos); glm::quat inverseRot = glm::inverse(rotation); glm::vec3 localOrigin = inverseRot * (origin - position); diff --git a/libraries/entities/src/GizmoEntityItem.h b/libraries/entities/src/GizmoEntityItem.h index 37a802387d..a05c294523 100644 --- a/libraries/entities/src/GizmoEntityItem.h +++ b/libraries/entities/src/GizmoEntityItem.h @@ -45,13 +45,14 @@ public: bool supportsDetailedIntersection() const override; bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - OctreeElementPointer& element, float& distance, + const glm::vec3& viewFrustumPos, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const override; bool findDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, - const glm::vec3& acceleration, OctreeElementPointer& element, float& parabolicDistance, - BoxFace& face, glm::vec3& surfaceNormal, + const glm::vec3& acceleration, const glm::vec3& viewFrustumPos, OctreeElementPointer& element, + float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const override; + bool getRotateForPicking() const override { return getBillboardMode() != BillboardMode::NONE; } GizmoType getGizmoType() const; void setGizmoType(GizmoType value); diff --git a/libraries/entities/src/GridEntityItem.cpp b/libraries/entities/src/GridEntityItem.cpp index c675a11d27..e635511bfc 100644 --- a/libraries/entities/src/GridEntityItem.cpp +++ b/libraries/entities/src/GridEntityItem.cpp @@ -125,60 +125,6 @@ void GridEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBits APPEND_ENTITY_PROPERTY(PROP_MINOR_GRID_EVERY, getMinorGridEvery()); } -bool GridEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - OctreeElementPointer& element, - float& distance, BoxFace& face, glm::vec3& surfaceNormal, - QVariantMap& extraInfo, bool precisionPicking) const { - glm::vec3 dimensions = getScaledDimensions(); - glm::vec2 xyDimensions(dimensions.x, dimensions.y); - glm::quat rotation = getWorldOrientation(); - glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); - rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, getBillboardMode(), BillboardModeHelpers::getPrimaryViewFrustumPosition()); - - if (findRayRectangleIntersection(origin, direction, rotation, position, xyDimensions, distance)) { - glm::vec3 forward = rotation * Vectors::FRONT; - if (glm::dot(forward, direction) > 0.0f) { - face = MAX_Z_FACE; - surfaceNormal = -forward; - } else { - face = MIN_Z_FACE; - surfaceNormal = forward; - } - return true; - } - return false; -} - -bool GridEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration, - OctreeElementPointer& element, float& parabolicDistance, - BoxFace& face, glm::vec3& surfaceNormal, - QVariantMap& extraInfo, bool precisionPicking) const { - glm::vec3 dimensions = getScaledDimensions(); - glm::vec2 xyDimensions(dimensions.x, dimensions.y); - glm::quat rotation = getWorldOrientation(); - glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); - rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, getBillboardMode(), BillboardModeHelpers::getPrimaryViewFrustumPosition()); - - glm::quat inverseRot = glm::inverse(rotation); - glm::vec3 localOrigin = inverseRot * (origin - position); - glm::vec3 localVelocity = inverseRot * velocity; - glm::vec3 localAcceleration = inverseRot * acceleration; - - if (findParabolaRectangleIntersection(localOrigin, localVelocity, localAcceleration, xyDimensions, parabolicDistance)) { - float localIntersectionVelocityZ = localVelocity.z + localAcceleration.z * parabolicDistance; - glm::vec3 forward = rotation * Vectors::FRONT; - if (localIntersectionVelocityZ > 0.0f) { - face = MIN_Z_FACE; - surfaceNormal = forward; - } else { - face = MAX_Z_FACE; - surfaceNormal = -forward; - } - return true; - } - return false; -} - void GridEntityItem::setColor(const glm::u8vec3& color) { withWriteLock([&] { _needsRenderUpdate |= _color != color; diff --git a/libraries/entities/src/GridEntityItem.h b/libraries/entities/src/GridEntityItem.h index fc31c93a5a..7dc7a475b2 100644 --- a/libraries/entities/src/GridEntityItem.h +++ b/libraries/entities/src/GridEntityItem.h @@ -43,16 +43,6 @@ public: EntityPropertyFlags& propertyFlags, bool overwriteLocalData, bool& somethingChanged) override; - virtual bool supportsDetailedIntersection() const override { return getBillboardMode() != BillboardMode::NONE; } - virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - OctreeElementPointer& element, float& distance, - BoxFace& face, glm::vec3& surfaceNormal, - QVariantMap& extraInfo, bool precisionPicking) const override; - virtual bool findDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, - const glm::vec3& acceleration, OctreeElementPointer& element, float& parabolicDistance, - BoxFace& face, glm::vec3& surfaceNormal, - QVariantMap& extraInfo, bool precisionPicking) const override; - static const uint32_t DEFAULT_MAJOR_GRID_EVERY; static const float DEFAULT_MINOR_GRID_EVERY; diff --git a/libraries/entities/src/ImageEntityItem.cpp b/libraries/entities/src/ImageEntityItem.cpp index 80711e4abc..afa6d9ae69 100644 --- a/libraries/entities/src/ImageEntityItem.cpp +++ b/libraries/entities/src/ImageEntityItem.cpp @@ -127,60 +127,6 @@ void ImageEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBit APPEND_ENTITY_PROPERTY(PROP_SUB_IMAGE, getSubImage()); } -bool ImageEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - OctreeElementPointer& element, - float& distance, BoxFace& face, glm::vec3& surfaceNormal, - QVariantMap& extraInfo, bool precisionPicking) const { - glm::vec3 dimensions = getScaledDimensions(); - glm::vec2 xyDimensions(dimensions.x, dimensions.y); - glm::quat rotation = getWorldOrientation(); - glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); - rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, getBillboardMode(), BillboardModeHelpers::getPrimaryViewFrustumPosition()); - - if (findRayRectangleIntersection(origin, direction, rotation, position, xyDimensions, distance)) { - glm::vec3 forward = rotation * Vectors::FRONT; - if (glm::dot(forward, direction) > 0.0f) { - face = MAX_Z_FACE; - surfaceNormal = -forward; - } else { - face = MIN_Z_FACE; - surfaceNormal = forward; - } - return true; - } - return false; -} - -bool ImageEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration, - OctreeElementPointer& element, float& parabolicDistance, - BoxFace& face, glm::vec3& surfaceNormal, - QVariantMap& extraInfo, bool precisionPicking) const { - glm::vec3 dimensions = getScaledDimensions(); - glm::vec2 xyDimensions(dimensions.x, dimensions.y); - glm::quat rotation = getWorldOrientation(); - glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); - rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, getBillboardMode(), BillboardModeHelpers::getPrimaryViewFrustumPosition()); - - glm::quat inverseRot = glm::inverse(rotation); - glm::vec3 localOrigin = inverseRot * (origin - position); - glm::vec3 localVelocity = inverseRot * velocity; - glm::vec3 localAcceleration = inverseRot * acceleration; - - if (findParabolaRectangleIntersection(localOrigin, localVelocity, localAcceleration, xyDimensions, parabolicDistance)) { - float localIntersectionVelocityZ = localVelocity.z + localAcceleration.z * parabolicDistance; - glm::vec3 forward = rotation * Vectors::FRONT; - if (localIntersectionVelocityZ > 0.0f) { - face = MIN_Z_FACE; - surfaceNormal = forward; - } else { - face = MAX_Z_FACE; - surfaceNormal = -forward; - } - return true; - } - return false; -} - QString ImageEntityItem::getImageURL() const { QString result; withReadLock([&] { diff --git a/libraries/entities/src/ImageEntityItem.h b/libraries/entities/src/ImageEntityItem.h index a5ed139e6b..4f7aac0c13 100644 --- a/libraries/entities/src/ImageEntityItem.h +++ b/libraries/entities/src/ImageEntityItem.h @@ -43,16 +43,6 @@ public: EntityPropertyFlags& propertyFlags, bool overwriteLocalData, bool& somethingChanged) override; - virtual bool supportsDetailedIntersection() const override { return getBillboardMode() != BillboardMode::NONE; } - virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - OctreeElementPointer& element, float& distance, - BoxFace& face, glm::vec3& surfaceNormal, - QVariantMap& extraInfo, bool precisionPicking) const override; - virtual bool findDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, - const glm::vec3& acceleration, OctreeElementPointer& element, float& parabolicDistance, - BoxFace& face, glm::vec3& surfaceNormal, - QVariantMap& extraInfo, bool precisionPicking) const override; - void setImageURL(const QString& imageUrl); QString getImageURL() const; diff --git a/libraries/entities/src/LightEntityItem.cpp b/libraries/entities/src/LightEntityItem.cpp index 0dcb5d125a..a3e00cddba 100644 --- a/libraries/entities/src/LightEntityItem.cpp +++ b/libraries/entities/src/LightEntityItem.cpp @@ -254,7 +254,7 @@ float LightEntityItem::getCutoff() const { } bool LightEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - OctreeElementPointer& element, float& distance, + const glm::vec3& viewFrustumPos, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const { @@ -267,8 +267,8 @@ bool LightEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const } bool LightEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, - const glm::vec3& acceleration, OctreeElementPointer& element, float& parabolicDistance, - BoxFace& face, glm::vec3& surfaceNormal, + const glm::vec3& acceleration, const glm::vec3& viewFrustumPos, OctreeElementPointer& element, + float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const { // TODO: consider if this is really what we want to do. We've made it so that "lights are pickable" is a global state // this is probably reasonable since there's typically only one tree you'd be picking on at a time. Technically we could diff --git a/libraries/entities/src/LightEntityItem.h b/libraries/entities/src/LightEntityItem.h index 5245770ec8..0f21c6acd9 100644 --- a/libraries/entities/src/LightEntityItem.h +++ b/libraries/entities/src/LightEntityItem.h @@ -74,12 +74,12 @@ public: virtual bool supportsDetailedIntersection() const override { return true; } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - OctreeElementPointer& element, float& distance, + const glm::vec3& viewFrustumPos, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const override; virtual bool findDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, - const glm::vec3& acceleration, OctreeElementPointer& element, float& parabolicDistance, - BoxFace& face, glm::vec3& surfaceNormal, + const glm::vec3& acceleration, const glm::vec3& viewFrustumPos, OctreeElementPointer& element, + float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const override; private: diff --git a/libraries/entities/src/LineEntityItem.h b/libraries/entities/src/LineEntityItem.h index 38e526204e..505291cdda 100644 --- a/libraries/entities/src/LineEntityItem.h +++ b/libraries/entities/src/LineEntityItem.h @@ -52,13 +52,13 @@ class LineEntityItem : public EntityItem { // never have a ray intersection pick a LineEntityItem. virtual bool supportsDetailedIntersection() const override { return true; } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - OctreeElementPointer& element, float& distance, + const glm::vec3& viewFrustumPos, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const override { return false; } virtual bool findDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, - const glm::vec3& acceleration, OctreeElementPointer& element, float& parabolicDistance, - BoxFace& face, glm::vec3& surfaceNormal, + const glm::vec3& acceleration, const glm::vec3& viewFrustumPos, OctreeElementPointer& element, + float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const override { return false; } diff --git a/libraries/entities/src/PolyLineEntityItem.h b/libraries/entities/src/PolyLineEntityItem.h index 8fb7831c6a..23f6e36e73 100644 --- a/libraries/entities/src/PolyLineEntityItem.h +++ b/libraries/entities/src/PolyLineEntityItem.h @@ -82,12 +82,12 @@ public: // never have a ray intersection pick a PolyLineEntityItem. virtual bool supportsDetailedIntersection() const override { return true; } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - OctreeElementPointer& element, float& distance, + const glm::vec3& viewFrustumPos, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const override { return false; } virtual bool findDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, - const glm::vec3& acceleration, OctreeElementPointer& element, float& parabolicDistance, - BoxFace& face, glm::vec3& surfaceNormal, + const glm::vec3& acceleration, const glm::vec3& viewFrustumPos, OctreeElementPointer& element, + float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const override { return false; } void computeTightLocalBoundingBox(AABox& box) const; diff --git a/libraries/entities/src/PolyVoxEntityItem.h b/libraries/entities/src/PolyVoxEntityItem.h index c416353ecf..3e3fe0b18c 100644 --- a/libraries/entities/src/PolyVoxEntityItem.h +++ b/libraries/entities/src/PolyVoxEntityItem.h @@ -44,12 +44,12 @@ class PolyVoxEntityItem : public EntityItem { // never have a ray intersection pick a PolyVoxEntityItem. virtual bool supportsDetailedIntersection() const override { return true; } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - OctreeElementPointer& element, float& distance, + const glm::vec3& viewFrustumPos, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const override { return false; } virtual bool findDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, - const glm::vec3& acceleration, OctreeElementPointer& element, float& parabolicDistance, - BoxFace& face, glm::vec3& surfaceNormal, + const glm::vec3& acceleration, const glm::vec3& viewFrustumPos, OctreeElementPointer& element, + float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const override { return false; } virtual void debugDump() const override; diff --git a/libraries/entities/src/ShapeEntityItem.cpp b/libraries/entities/src/ShapeEntityItem.cpp index 943912b934..7858e62f7d 100644 --- a/libraries/entities/src/ShapeEntityItem.cpp +++ b/libraries/entities/src/ShapeEntityItem.cpp @@ -269,17 +269,17 @@ void ShapeEntityItem::setUnscaledDimensions(const glm::vec3& value) { } bool ShapeEntityItem::supportsDetailedIntersection() const { - return getShape() == entity::Sphere || getBillboardMode() != BillboardMode::NONE; + return getShape() == entity::Sphere; } bool ShapeEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - OctreeElementPointer& element, - float& distance, BoxFace& face, glm::vec3& surfaceNormal, - QVariantMap& extraInfo, bool precisionPicking) const { + const glm::vec3& viewFrustumPos, OctreeElementPointer& element, + float& distance, BoxFace& face, glm::vec3& surfaceNormal, + QVariantMap& extraInfo, bool precisionPicking) const { glm::vec3 dimensions = getScaledDimensions(); glm::quat rotation = getWorldOrientation(); glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); - rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, getBillboardMode(), BillboardModeHelpers::getPrimaryViewFrustumPosition()); + rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, getBillboardMode(), 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); @@ -287,35 +287,31 @@ bool ShapeEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3 entityFrameOrigin = glm::vec3(worldToEntityMatrix * glm::vec4(origin, 1.0f)); glm::vec3 entityFrameDirection = glm::vec3(worldToEntityMatrix * glm::vec4(direction, 0.0f)); - if (getShape() == entity::Sphere) { - // NOTE: unit sphere has center of 0,0,0 and radius of 0.5 - if (findRaySphereIntersection(entityFrameOrigin, entityFrameDirection, glm::vec3(0.0f), 0.5f, distance)) { - bool success; - glm::vec3 center = getCenterPosition(success); - if (success) { - // FIXME: this is only correct for uniformly scaled spheres - // determine where on the unit sphere the hit point occured - glm::vec3 hitAt = origin + (direction * distance); - surfaceNormal = glm::normalize(hitAt - center); - } else { - return false; - } - return true; + // NOTE: unit sphere has center of 0,0,0 and radius of 0.5 + if (findRaySphereIntersection(entityFrameOrigin, entityFrameDirection, glm::vec3(0.0f), 0.5f, distance)) { + bool success; + glm::vec3 center = getCenterPosition(success); + if (success) { + // FIXME: this is only correct for uniformly scaled spheres + // determine where on the unit sphere the hit point occured + glm::vec3 hitAt = origin + (direction * distance); + surfaceNormal = glm::normalize(hitAt - center); + } else { + return false; } - } else if (findRayAABoxIntersection(entityFrameOrigin, entityFrameDirection, 1.0f / entityFrameDirection, glm::vec3(-0.5f), glm::vec3(1.0f), distance, face, surfaceNormal)) { return true; } return false; } bool ShapeEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration, - OctreeElementPointer& element, float& parabolicDistance, + const glm::vec3& viewFrustumPos, OctreeElementPointer& element, float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const { glm::vec3 dimensions = getScaledDimensions(); glm::quat rotation = getWorldOrientation(); glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); - rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, getBillboardMode(), BillboardModeHelpers::getPrimaryViewFrustumPosition()); + rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, getBillboardMode(), 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); @@ -324,25 +320,26 @@ bool ShapeEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin, glm::vec3 entityFrameVelocity = glm::vec3(worldToEntityMatrix * glm::vec4(velocity, 0.0f)); glm::vec3 entityFrameAcceleration = glm::vec3(worldToEntityMatrix * glm::vec4(acceleration, 0.0f)); - if (getShape() == entity::Sphere) { - // NOTE: unit sphere has center of 0,0,0 and radius of 0.5 - if (findParabolaSphereIntersection(entityFrameOrigin, entityFrameVelocity, entityFrameAcceleration, glm::vec3(0.0f), 0.5f, parabolicDistance)) { - bool success; - glm::vec3 center = getCenterPosition(success); - if (success) { - // FIXME: this is only correct for uniformly scaled spheres - surfaceNormal = glm::normalize((origin + velocity * parabolicDistance + 0.5f * acceleration * parabolicDistance * parabolicDistance) - center); - } else { - return false; - } - return true; + // NOTE: unit sphere has center of 0,0,0 and radius of 0.5 + if (findParabolaSphereIntersection(entityFrameOrigin, entityFrameVelocity, entityFrameAcceleration, glm::vec3(0.0f), 0.5f, parabolicDistance)) { + bool success; + glm::vec3 center = getCenterPosition(success); + if (success) { + // FIXME: this is only correct for uniformly scaled spheres + surfaceNormal = glm::normalize((origin + velocity * parabolicDistance + 0.5f * acceleration * parabolicDistance * parabolicDistance) - center); + } else { + return false; } - } else if (findParabolaAABoxIntersection(entityFrameOrigin, entityFrameVelocity, entityFrameAcceleration, glm::vec3(-0.5f), glm::vec3(1.0f), parabolicDistance, face, surfaceNormal)) { return true; } return false; } +bool ShapeEntityItem::getRotateForPicking() const { + auto shape = getShape(); + return getBillboardMode() != BillboardMode::NONE && (_shape < entity::Shape::Cube || _shape > entity::Shape::Icosahedron); +} + void ShapeEntityItem::debugDump() const { quint64 now = usecTimestampNow(); qCDebug(entities) << "SHAPE EntityItem id:" << getEntityItemID() << "---------------------------------------------"; diff --git a/libraries/entities/src/ShapeEntityItem.h b/libraries/entities/src/ShapeEntityItem.h index c0dc9642fe..d5b934153a 100644 --- a/libraries/entities/src/ShapeEntityItem.h +++ b/libraries/entities/src/ShapeEntityItem.h @@ -86,13 +86,14 @@ public: bool supportsDetailedIntersection() const override; bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - OctreeElementPointer& element, float& distance, - BoxFace& face, glm::vec3& surfaceNormal, - QVariantMap& extraInfo, bool precisionPicking) const override; + const glm::vec3& viewFrustumPos, OctreeElementPointer& element, + float& distance, BoxFace& face, glm::vec3& surfaceNormal, + QVariantMap& extraInfo, bool precisionPicking) const override; bool findDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, - const glm::vec3& acceleration, OctreeElementPointer& element, float& parabolicDistance, - BoxFace& face, glm::vec3& surfaceNormal, + const glm::vec3& acceleration, const glm::vec3& viewFrustumPos, OctreeElementPointer& element, + float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const override; + bool getRotateForPicking() const override; void debugDump() const override; diff --git a/libraries/entities/src/TextEntityItem.cpp b/libraries/entities/src/TextEntityItem.cpp index 7fab5cee53..ebe536cae8 100644 --- a/libraries/entities/src/TextEntityItem.cpp +++ b/libraries/entities/src/TextEntityItem.cpp @@ -191,60 +191,6 @@ void TextEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBits APPEND_ENTITY_PROPERTY(PROP_TEXT_EFFECT_THICKNESS, getTextEffectThickness()); } -bool TextEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - OctreeElementPointer& element, float& distance, - BoxFace& face, glm::vec3& surfaceNormal, - QVariantMap& extraInfo, bool precisionPicking) const { - glm::vec3 dimensions = getScaledDimensions(); - glm::vec2 xyDimensions(dimensions.x, dimensions.y); - glm::quat rotation = getWorldOrientation(); - glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); - rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, getBillboardMode(), BillboardModeHelpers::getPrimaryViewFrustumPosition()); - - if (findRayRectangleIntersection(origin, direction, rotation, position, xyDimensions, distance)) { - glm::vec3 forward = rotation * Vectors::FRONT; - if (glm::dot(forward, direction) > 0.0f) { - face = MAX_Z_FACE; - surfaceNormal = -forward; - } else { - face = MIN_Z_FACE; - surfaceNormal = forward; - } - return true; - } - return false; -} - -bool TextEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration, - OctreeElementPointer& element, float& parabolicDistance, - BoxFace& face, glm::vec3& surfaceNormal, - QVariantMap& extraInfo, bool precisionPicking) const { - glm::vec3 dimensions = getScaledDimensions(); - glm::vec2 xyDimensions(dimensions.x, dimensions.y); - glm::quat rotation = getWorldOrientation(); - glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); - rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, getBillboardMode(), BillboardModeHelpers::getPrimaryViewFrustumPosition()); - - glm::quat inverseRot = glm::inverse(rotation); - glm::vec3 localOrigin = inverseRot * (origin - position); - glm::vec3 localVelocity = inverseRot * velocity; - glm::vec3 localAcceleration = inverseRot * acceleration; - - if (findParabolaRectangleIntersection(localOrigin, localVelocity, localAcceleration, xyDimensions, parabolicDistance)) { - float localIntersectionVelocityZ = localVelocity.z + localAcceleration.z * parabolicDistance; - glm::vec3 forward = rotation * Vectors::FRONT; - if (localIntersectionVelocityZ > 0.0f) { - face = MIN_Z_FACE; - surfaceNormal = forward; - } else { - face = MAX_Z_FACE; - surfaceNormal = -forward; - } - return true; - } - return false; -} - void TextEntityItem::setText(const QString& value) { withWriteLock([&] { _needsRenderUpdate |= _text != value; diff --git a/libraries/entities/src/TextEntityItem.h b/libraries/entities/src/TextEntityItem.h index 212f11e768..3e58831a72 100644 --- a/libraries/entities/src/TextEntityItem.h +++ b/libraries/entities/src/TextEntityItem.h @@ -48,16 +48,6 @@ public: EntityPropertyFlags& propertyFlags, bool overwriteLocalData, bool& somethingChanged) override; - virtual bool supportsDetailedIntersection() const override { return getBillboardMode() != BillboardMode::NONE; } - virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - OctreeElementPointer& element, float& distance, - BoxFace& face, glm::vec3& surfaceNormal, - QVariantMap& extraInfo, bool precisionPicking) const override; - virtual bool findDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, - const glm::vec3& acceleration, OctreeElementPointer& element, float& parabolicDistance, - BoxFace& face, glm::vec3& surfaceNormal, - QVariantMap& extraInfo, bool precisionPicking) const override; - static const QString DEFAULT_TEXT; void setText(const QString& value); QString getText() const; diff --git a/libraries/entities/src/WebEntityItem.cpp b/libraries/entities/src/WebEntityItem.cpp index d9d2425e11..c0ad9e7094 100644 --- a/libraries/entities/src/WebEntityItem.cpp +++ b/libraries/entities/src/WebEntityItem.cpp @@ -157,62 +157,6 @@ void WebEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBitst APPEND_ENTITY_PROPERTY(PROP_WEB_USE_BACKGROUND, getUseBackground()); } -bool WebEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - OctreeElementPointer& element, float& distance, - BoxFace& face, glm::vec3& surfaceNormal, - QVariantMap& extraInfo, bool precisionPicking) const { - glm::vec3 dimensions = getScaledDimensions(); - glm::vec2 xyDimensions(dimensions.x, dimensions.y); - glm::quat rotation = getWorldOrientation(); - glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); - rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, getBillboardMode(), BillboardModeHelpers::getPrimaryViewFrustumPosition()); - - if (findRayRectangleIntersection(origin, direction, rotation, position, xyDimensions, distance)) { - glm::vec3 forward = rotation * Vectors::FRONT; - if (glm::dot(forward, direction) > 0.0f) { - face = MAX_Z_FACE; - surfaceNormal = -forward; - } else { - face = MIN_Z_FACE; - surfaceNormal = forward; - } - return true; - } else { - return false; - } -} - -bool WebEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration, - OctreeElementPointer& element, float& parabolicDistance, - BoxFace& face, glm::vec3& surfaceNormal, - QVariantMap& extraInfo, bool precisionPicking) const { - glm::vec3 dimensions = getScaledDimensions(); - glm::vec2 xyDimensions(dimensions.x, dimensions.y); - glm::quat rotation = getWorldOrientation(); - glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); - rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, getBillboardMode(), BillboardModeHelpers::getPrimaryViewFrustumPosition()); - - glm::quat inverseRot = glm::inverse(rotation); - glm::vec3 localOrigin = inverseRot * (origin - position); - glm::vec3 localVelocity = inverseRot * velocity; - glm::vec3 localAcceleration = inverseRot * acceleration; - - if (findParabolaRectangleIntersection(localOrigin, localVelocity, localAcceleration, xyDimensions, parabolicDistance)) { - float localIntersectionVelocityZ = localVelocity.z + localAcceleration.z * parabolicDistance; - glm::vec3 forward = rotation * Vectors::FRONT; - if (localIntersectionVelocityZ > 0.0f) { - face = MIN_Z_FACE; - surfaceNormal = forward; - } else { - face = MAX_Z_FACE; - surfaceNormal = -forward; - } - return true; - } else { - return false; - } -} - void WebEntityItem::setColor(const glm::u8vec3& value) { withWriteLock([&] { _needsRenderUpdate |= _color != value; diff --git a/libraries/entities/src/WebEntityItem.h b/libraries/entities/src/WebEntityItem.h index e0a66f25b2..8edd20245f 100644 --- a/libraries/entities/src/WebEntityItem.h +++ b/libraries/entities/src/WebEntityItem.h @@ -45,16 +45,6 @@ public: EntityPropertyFlags& propertyFlags, bool overwriteLocalData, bool& somethingChanged) override; - virtual bool supportsDetailedIntersection() const override { return getBillboardMode() != BillboardMode::NONE; } - virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - OctreeElementPointer& element, float& distance, - BoxFace& face, glm::vec3& surfaceNormal, - QVariantMap& extraInfo, bool precisionPicking) const override; - virtual bool findDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, - const glm::vec3& acceleration, OctreeElementPointer& element, float& parabolicDistance, - BoxFace& face, glm::vec3& surfaceNormal, - QVariantMap& extraInfo, bool precisionPicking) const override; - glm::u8vec3 getColor() const; void setColor(const glm::u8vec3& value); diff --git a/libraries/entities/src/ZoneEntityItem.cpp b/libraries/entities/src/ZoneEntityItem.cpp index 8b020e92d5..3eabfb4f1e 100644 --- a/libraries/entities/src/ZoneEntityItem.cpp +++ b/libraries/entities/src/ZoneEntityItem.cpp @@ -318,15 +318,15 @@ void ZoneEntityItem::setCompoundShapeURL(const QString& url) { } bool ZoneEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - OctreeElementPointer& element, float& distance, + const glm::vec3& viewFrustumPos, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const { return _zonesArePickable; } bool ZoneEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, - const glm::vec3& acceleration, OctreeElementPointer& element, float& parabolicDistance, - BoxFace& face, glm::vec3& surfaceNormal, + const glm::vec3& acceleration, const glm::vec3& viewFrustumPos, OctreeElementPointer& element, + float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const { return _zonesArePickable; } diff --git a/libraries/entities/src/ZoneEntityItem.h b/libraries/entities/src/ZoneEntityItem.h index 9c8e3839b7..2b61bbd346 100644 --- a/libraries/entities/src/ZoneEntityItem.h +++ b/libraries/entities/src/ZoneEntityItem.h @@ -116,12 +116,12 @@ public: virtual bool supportsDetailedIntersection() const override { return true; } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - OctreeElementPointer& element, float& distance, + const glm::vec3& viewFrustumPos, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const override; virtual bool findDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, - const glm::vec3& acceleration, OctreeElementPointer& element, float& parabolicDistance, - BoxFace& face, glm::vec3& surfaceNormal, + const glm::vec3& acceleration, const glm::vec3& viewFrustumPos, OctreeElementPointer& element, + float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const override; bool contains(const glm::vec3& point) const override; diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 9bf1596a04..dad2f95420 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -319,8 +319,8 @@ void Model::initJointStates() { _rig.initJointStates(hfmModel, modelOffset); } -bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const glm::vec3& direction, float& distance, - BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, +bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const glm::vec3& direction, const glm::vec3& viewFrustumPos, + float& distance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool pickAgainstTriangles, bool allowBackface) { bool intersectedSomething = false; @@ -330,7 +330,8 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g } // extents is the entity relative, scaled, centered extents of the entity - glm::mat4 modelToWorldMatrix = createMatFromQuatAndPos(_rotation, _translation); + glm::quat rotation = BillboardModeHelpers::getBillboardRotation(_translation, _rotation, _billboardMode, viewFrustumPos); + glm::mat4 modelToWorldMatrix = createMatFromQuatAndPos(rotation, _translation); glm::mat4 worldToModelMatrix = glm::inverse(modelToWorldMatrix); Extents modelExtents = getMeshExtents(); // NOTE: unrotated @@ -475,8 +476,8 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g } bool Model::findParabolaIntersectionAgainstSubMeshes(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration, - float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, - bool pickAgainstTriangles, bool allowBackface) { + const glm::vec3& viewFrustumPos, float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, + QVariantMap& extraInfo, bool pickAgainstTriangles, bool allowBackface) { bool intersectedSomething = false; // if we aren't active, we can't pick yet... @@ -485,7 +486,8 @@ bool Model::findParabolaIntersectionAgainstSubMeshes(const glm::vec3& origin, co } // extents is the entity relative, scaled, centered extents of the entity - glm::mat4 modelToWorldMatrix = createMatFromQuatAndPos(_rotation, _translation); + glm::quat rotation = BillboardModeHelpers::getBillboardRotation(_translation, _rotation, _billboardMode, viewFrustumPos); + glm::mat4 modelToWorldMatrix = createMatFromQuatAndPos(rotation, _translation); glm::mat4 worldToModelMatrix = glm::inverse(modelToWorldMatrix); Extents modelExtents = getMeshExtents(); // NOTE: unrotated diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 3085dcfc6f..5a8338993a 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -198,11 +198,11 @@ public: void setJointRotation(int index, bool valid, const glm::quat& rotation, float priority); void setJointTranslation(int index, bool valid, const glm::vec3& translation, float priority); - bool findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const glm::vec3& direction, float& distance, - BoxFace& face, glm::vec3& surfaceNormal, + bool findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const glm::vec3& direction, const glm::vec3& viewFrustumPos, + float& distance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool pickAgainstTriangles = false, bool allowBackface = false); bool findParabolaIntersectionAgainstSubMeshes(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration, - float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, + const glm::vec3& viewFrustumPos, float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool pickAgainstTriangles = false, bool allowBackface = false); void setOffset(const glm::vec3& offset); From 92ea14a0591ad70b078eca6e9142deb269e25eb4 Mon Sep 17 00:00:00 2001 From: HifiExperiments Date: Sun, 17 Jan 2021 22:08:06 -0800 Subject: [PATCH 13/33] proper render bounds for models (need to pass RenderArgs to getBound everywhere) --- interface/src/graphics/WorldBox.cpp | 2 +- interface/src/graphics/WorldBox.h | 2 +- interface/src/raypick/ParabolaPointer.cpp | 4 +-- interface/src/raypick/ParabolaPointer.h | 4 +-- interface/src/ui/overlays/Overlay.h | 2 +- interface/src/ui/overlays/OverlaysPayload.cpp | 2 +- .../src/workload/GameWorkloadRenderer.cpp | 4 +-- interface/src/workload/GameWorkloadRenderer.h | 4 +-- .../src/avatars-renderer/Avatar.cpp | 2 +- .../src/avatars-renderer/Avatar.h | 2 +- .../src/RenderableEntityItem.cpp | 2 +- .../src/RenderableEntityItem.h | 2 +- .../src/RenderableGizmoEntityItem.cpp | 4 +-- .../src/RenderableGizmoEntityItem.h | 2 +- .../src/RenderableGridEntityItem.cpp | 4 +-- .../src/RenderableGridEntityItem.h | 2 +- .../src/RenderableLightEntityItem.cpp | 4 +-- .../src/RenderableLightEntityItem.h | 2 +- .../src/RenderableMaterialEntityItem.cpp | 2 +- .../RenderableParticleEffectEntityItem.cpp | 2 +- .../src/RenderableParticleEffectEntityItem.h | 2 +- .../src/RenderableShapeEntityItem.cpp | 6 ++-- .../src/RenderableShapeEntityItem.h | 2 +- .../src/RenderableTextEntityItem.cpp | 8 ++--- .../src/RenderableTextEntityItem.h | 4 +-- libraries/procedural/CMakeLists.txt | 2 +- .../procedural/src/procedural/Procedural.h | 11 +++--- libraries/render-utils/src/AnimDebugDraw.cpp | 2 +- libraries/render-utils/src/FadeEffectJobs.cpp | 8 ++--- libraries/render-utils/src/FadeEffectJobs.h | 2 +- libraries/render-utils/src/LightPayload.cpp | 4 +-- libraries/render-utils/src/LightPayload.h | 4 +-- .../render-utils/src/MeshPartPayload.cpp | 20 +++++++---- libraries/render-utils/src/MeshPartPayload.h | 5 ++- libraries/render-utils/src/Model.cpp | 2 +- libraries/render/src/render/CullTask.cpp | 34 +++++++++---------- .../render/src/render/DrawSceneOctree.cpp | 2 +- libraries/render/src/render/FilterTask.cpp | 2 +- libraries/render/src/render/Item.cpp | 8 ++--- libraries/render/src/render/Item.h | 20 +++++------ libraries/render/src/render/Scene.cpp | 6 ++-- libraries/render/src/render/SortTask.cpp | 2 +- 42 files changed, 108 insertions(+), 102 deletions(-) diff --git a/interface/src/graphics/WorldBox.cpp b/interface/src/graphics/WorldBox.cpp index 0e15d9da86..a627cf75e4 100644 --- a/interface/src/graphics/WorldBox.cpp +++ b/interface/src/graphics/WorldBox.cpp @@ -16,7 +16,7 @@ render::ItemID WorldBoxRenderData::_item{ render::Item::INVALID_ITEM_ID }; namespace render { template <> const ItemKey payloadGetKey(const WorldBoxRenderData::Pointer& stuff) { return ItemKey::Builder::opaqueShape().withTagBits(ItemKey::TAG_BITS_0 | ItemKey::TAG_BITS_1); } - template <> const Item::Bound payloadGetBound(const WorldBoxRenderData::Pointer& stuff) { return Item::Bound(); } + template <> const Item::Bound payloadGetBound(const WorldBoxRenderData::Pointer& stuff, RenderArgs* args) { return Item::Bound(); } template <> void payloadRender(const WorldBoxRenderData::Pointer& stuff, RenderArgs* args) { if (Menu::getInstance()->isOptionChecked(MenuOption::WorldAxes)) { PerformanceTimer perfTimer("worldBox"); diff --git a/interface/src/graphics/WorldBox.h b/interface/src/graphics/WorldBox.h index 4d53652c0e..0d697eb133 100644 --- a/interface/src/graphics/WorldBox.h +++ b/interface/src/graphics/WorldBox.h @@ -32,7 +32,7 @@ public: namespace render { template <> const ItemKey payloadGetKey(const WorldBoxRenderData::Pointer& stuff); - template <> const Item::Bound payloadGetBound(const WorldBoxRenderData::Pointer& stuff); + template <> const Item::Bound payloadGetBound(const WorldBoxRenderData::Pointer& stuff, RenderArgs* args); template <> void payloadRender(const WorldBoxRenderData::Pointer& stuff, RenderArgs* args); } diff --git a/interface/src/raypick/ParabolaPointer.cpp b/interface/src/raypick/ParabolaPointer.cpp index 216248f8b5..67f0772228 100644 --- a/interface/src/raypick/ParabolaPointer.cpp +++ b/interface/src/raypick/ParabolaPointer.cpp @@ -462,9 +462,9 @@ namespace render { template <> const ItemKey payloadGetKey(const ParabolaPointer::RenderState::ParabolaRenderItem::Pointer& payload) { return payload->getKey(); } - template <> const Item::Bound payloadGetBound(const ParabolaPointer::RenderState::ParabolaRenderItem::Pointer& payload) { + template <> const Item::Bound payloadGetBound(const ParabolaPointer::RenderState::ParabolaRenderItem::Pointer& payload, RenderArgs* args) { if (payload) { - return payload->getBound(); + return payload->getBound(args); } return Item::Bound(); } diff --git a/interface/src/raypick/ParabolaPointer.h b/interface/src/raypick/ParabolaPointer.h index 85d09adbdb..1701e4dcfa 100644 --- a/interface/src/raypick/ParabolaPointer.h +++ b/interface/src/raypick/ParabolaPointer.h @@ -31,7 +31,7 @@ public: void render(RenderArgs* args); render::Item::Bound& editBound() { return _bound; } - const render::Item::Bound& getBound() { return _bound; } + const render::Item::Bound& getBound(RenderArgs* args) { return _bound; } render::ItemKey getKey() const { return _key; } void setVisible(bool visible); @@ -128,7 +128,7 @@ private: namespace render { template <> const ItemKey payloadGetKey(const ParabolaPointer::RenderState::ParabolaRenderItem::Pointer& payload); - template <> const Item::Bound payloadGetBound(const ParabolaPointer::RenderState::ParabolaRenderItem::Pointer& payload); + template <> const Item::Bound payloadGetBound(const ParabolaPointer::RenderState::ParabolaRenderItem::Pointer& payload, RenderArgs* args); template <> void payloadRender(const ParabolaPointer::RenderState::ParabolaRenderItem::Pointer& payload, RenderArgs* args); template <> const ShapeKey shapeGetShapeKey(const ParabolaPointer::RenderState::ParabolaRenderItem::Pointer& payload); } diff --git a/interface/src/ui/overlays/Overlay.h b/interface/src/ui/overlays/Overlay.h index 72373d2d20..5c92cfce00 100644 --- a/interface/src/ui/overlays/Overlay.h +++ b/interface/src/ui/overlays/Overlay.h @@ -66,7 +66,7 @@ private: namespace render { template <> const ItemKey payloadGetKey(const Overlay::Pointer& overlay); - template <> const Item::Bound payloadGetBound(const Overlay::Pointer& overlay); + template <> const Item::Bound payloadGetBound(const Overlay::Pointer& overlay, RenderArgs* args); template <> void payloadRender(const Overlay::Pointer& overlay, RenderArgs* args); template <> const ShapeKey shapeGetShapeKey(const Overlay::Pointer& overlay); template <> uint32_t metaFetchMetaSubItems(const Overlay::Pointer& overlay, ItemIDs& subItems); diff --git a/interface/src/ui/overlays/OverlaysPayload.cpp b/interface/src/ui/overlays/OverlaysPayload.cpp index 0d1bcdd071..fdcd4f7205 100644 --- a/interface/src/ui/overlays/OverlaysPayload.cpp +++ b/interface/src/ui/overlays/OverlaysPayload.cpp @@ -14,7 +14,7 @@ namespace render { template <> const ItemKey payloadGetKey(const Overlay::Pointer& overlay) { return overlay->getKey(); } - template <> const Item::Bound payloadGetBound(const Overlay::Pointer& overlay) { + template <> const Item::Bound payloadGetBound(const Overlay::Pointer& overlay, RenderArgs* args) { return overlay->getBounds(); } template <> void payloadRender(const Overlay::Pointer& overlay, RenderArgs* args) { diff --git a/interface/src/workload/GameWorkloadRenderer.cpp b/interface/src/workload/GameWorkloadRenderer.cpp index f65bf88754..1310baf4b3 100644 --- a/interface/src/workload/GameWorkloadRenderer.cpp +++ b/interface/src/workload/GameWorkloadRenderer.cpp @@ -82,9 +82,9 @@ namespace render { template <> const ItemKey payloadGetKey(const GameWorkloadRenderItem::Pointer& payload) { return payload->getKey(); } - template <> const Item::Bound payloadGetBound(const GameWorkloadRenderItem::Pointer& payload) { + template <> const Item::Bound payloadGetBound(const GameWorkloadRenderItem::Pointer& payload, RenderArgs* args) { if (payload) { - return payload->getBound(); + return payload->getBound(args); } return Item::Bound(); } diff --git a/interface/src/workload/GameWorkloadRenderer.h b/interface/src/workload/GameWorkloadRenderer.h index a25598821e..ad33425774 100644 --- a/interface/src/workload/GameWorkloadRenderer.h +++ b/interface/src/workload/GameWorkloadRenderer.h @@ -57,7 +57,7 @@ public: void render(RenderArgs* args); render::Item::Bound& editBound() { return _bound; } - const render::Item::Bound& getBound() { return _bound; } + const render::Item::Bound& getBound(RenderArgs* args) { return _bound; } void setVisible(bool visible); void showProxies(bool show); @@ -96,7 +96,7 @@ protected: namespace render { template <> const ItemKey payloadGetKey(const GameWorkloadRenderItem::Pointer& payload); - template <> const Item::Bound payloadGetBound(const GameWorkloadRenderItem::Pointer& payload); + template <> const Item::Bound payloadGetBound(const GameWorkloadRenderItem::Pointer& payload, RenderArgs* args); template <> void payloadRender(const GameWorkloadRenderItem::Pointer& payload, RenderArgs* args); template <> const ShapeKey shapeGetShapeKey(const GameWorkloadRenderItem::Pointer& payload); } diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index d859454a99..f361e15999 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -63,7 +63,7 @@ namespace render { } return keyBuilder.build(); } - template <> const Item::Bound payloadGetBound(const AvatarSharedPointer& avatar) { + template <> const Item::Bound payloadGetBound(const AvatarSharedPointer& avatar, RenderArgs* args) { auto avatarPtr = static_pointer_cast(avatar); if (avatarPtr) { return avatarPtr->getRenderBounds(); diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index 25dd347484..4fc9c25595 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h @@ -39,7 +39,7 @@ namespace render { template <> const ItemKey payloadGetKey(const AvatarSharedPointer& avatar); - template <> const Item::Bound payloadGetBound(const AvatarSharedPointer& avatar); + template <> const Item::Bound payloadGetBound(const AvatarSharedPointer& avatar, RenderArgs* args); template <> void payloadRender(const AvatarSharedPointer& avatar, RenderArgs* args); template <> uint32_t metaFetchMetaSubItems(const AvatarSharedPointer& avatar, ItemIDs& subItems); } diff --git a/libraries/entities-renderer/src/RenderableEntityItem.cpp b/libraries/entities-renderer/src/RenderableEntityItem.cpp index fdb971e7a3..b2670e3bce 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableEntityItem.cpp @@ -137,7 +137,7 @@ EntityRenderer::~EntityRenderer() {} // Smart payload proxy members, implementing the payload interface // -Item::Bound EntityRenderer::getBound() { +Item::Bound EntityRenderer::getBound(RenderArgs* args) { auto bound = _bound; if (_billboardMode != BillboardMode::NONE) { glm::vec3 dimensions = bound.getScale(); diff --git a/libraries/entities-renderer/src/RenderableEntityItem.h b/libraries/entities-renderer/src/RenderableEntityItem.h index 4afcd6e231..7f0e1e16ee 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.h +++ b/libraries/entities-renderer/src/RenderableEntityItem.h @@ -64,7 +64,7 @@ public: static glm::vec3 calculatePulseColor(const glm::vec3& color, const PulsePropertyGroup& pulseProperties, quint64 start); virtual uint32_t metaFetchMetaSubItems(ItemIDs& subItems) const override; - virtual Item::Bound getBound() override; + virtual Item::Bound getBound(RenderArgs* args) override; bool passesZoneOcclusionTest(const std::unordered_set& containingZones) const override; protected: diff --git a/libraries/entities-renderer/src/RenderableGizmoEntityItem.cpp b/libraries/entities-renderer/src/RenderableGizmoEntityItem.cpp index 3abd120bf9..bf005ae2e5 100644 --- a/libraries/entities-renderer/src/RenderableGizmoEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableGizmoEntityItem.cpp @@ -195,8 +195,8 @@ void GizmoEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPoint } } -Item::Bound GizmoEntityRenderer::getBound() { - auto bound = Parent::getBound(); +Item::Bound GizmoEntityRenderer::getBound(RenderArgs* args) { + auto bound = Parent::getBound(args); if (_ringProperties.getHasTickMarks()) { glm::vec3 scale = bound.getScale(); for (int i = 0; i < 3; i += 2) { diff --git a/libraries/entities-renderer/src/RenderableGizmoEntityItem.h b/libraries/entities-renderer/src/RenderableGizmoEntityItem.h index 8593348bde..6a09d1a047 100644 --- a/libraries/entities-renderer/src/RenderableGizmoEntityItem.h +++ b/libraries/entities-renderer/src/RenderableGizmoEntityItem.h @@ -23,7 +23,7 @@ public: ~GizmoEntityRenderer(); protected: - Item::Bound getBound() override; + Item::Bound getBound(RenderArgs* args) override; ShapeKey getShapeKey() override; bool isTransparent() const override; diff --git a/libraries/entities-renderer/src/RenderableGridEntityItem.cpp b/libraries/entities-renderer/src/RenderableGridEntityItem.cpp index a5ae4acbf5..e374fe29c0 100644 --- a/libraries/entities-renderer/src/RenderableGridEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableGridEntityItem.cpp @@ -49,13 +49,13 @@ void GridEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointe _minorGridEvery = entity->getMinorGridEvery(); } -Item::Bound GridEntityRenderer::getBound() { +Item::Bound GridEntityRenderer::getBound(RenderArgs* args) { if (_followCamera) { // This is a UI element that should always be in view, lie to the octree to avoid culling const AABox DOMAIN_BOX = AABox(glm::vec3(-TREE_SCALE / 2), TREE_SCALE); return DOMAIN_BOX; } - return Parent::getBound(); + return Parent::getBound(args); } ShapeKey GridEntityRenderer::getShapeKey() { diff --git a/libraries/entities-renderer/src/RenderableGridEntityItem.h b/libraries/entities-renderer/src/RenderableGridEntityItem.h index 1958d17136..fd5b397424 100644 --- a/libraries/entities-renderer/src/RenderableGridEntityItem.h +++ b/libraries/entities-renderer/src/RenderableGridEntityItem.h @@ -23,7 +23,7 @@ public: ~GridEntityRenderer(); protected: - Item::Bound getBound() override; + Item::Bound getBound(RenderArgs* args) override; ShapeKey getShapeKey() override; bool isTransparent() const override; diff --git a/libraries/entities-renderer/src/RenderableLightEntityItem.cpp b/libraries/entities-renderer/src/RenderableLightEntityItem.cpp index 9eb2e8428d..2ab2051fcf 100644 --- a/libraries/entities-renderer/src/RenderableLightEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableLightEntityItem.cpp @@ -60,8 +60,8 @@ ItemKey LightEntityRenderer::getKey() { return payloadGetKey(_lightPayload); } -Item::Bound LightEntityRenderer::getBound() { - return payloadGetBound(_lightPayload); +Item::Bound LightEntityRenderer::getBound(RenderArgs* args) { + return payloadGetBound(_lightPayload, args); } void LightEntityRenderer::doRender(RenderArgs* args) { diff --git a/libraries/entities-renderer/src/RenderableLightEntityItem.h b/libraries/entities-renderer/src/RenderableLightEntityItem.h index 323f280795..bbb5ec346a 100644 --- a/libraries/entities-renderer/src/RenderableLightEntityItem.h +++ b/libraries/entities-renderer/src/RenderableLightEntityItem.h @@ -29,7 +29,7 @@ protected: virtual void doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) override; virtual ItemKey getKey() override; - virtual Item::Bound getBound() override; + virtual Item::Bound getBound(RenderArgs* args) override; virtual void doRender(RenderArgs* args) override; private: diff --git a/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp b/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp index 74b479affe..714defe817 100644 --- a/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp @@ -376,7 +376,7 @@ void MaterialEntityRenderer::applyMaterial(const TypedEntityPointer& entity) { if (material->isProcedural()) { auto procedural = std::static_pointer_cast(material); - procedural->setBoundOperator([this] { return getBound(); }); + procedural->setBoundOperator([this](RenderArgs* args) { return getBound(args); }); entity->setHasVertexShader(procedural->hasVertexShader()); } diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index 4fe6bc8f93..e2a57840d9 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -161,7 +161,7 @@ ShapeKey ParticleEffectEntityRenderer::getShapeKey() { return builder.build(); } -Item::Bound ParticleEffectEntityRenderer::getBound() { +Item::Bound ParticleEffectEntityRenderer::getBound(RenderArgs* args) { return _bound; } diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h index ca6bc859fb..547d654486 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h @@ -30,7 +30,7 @@ protected: virtual ItemKey getKey() override; virtual ShapeKey getShapeKey() override; - virtual Item::Bound getBound() override; + virtual Item::Bound getBound(RenderArgs* args) override; virtual void doRender(RenderArgs* args) override; private: diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp index 9cc18a8df5..674d7c297d 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp @@ -200,16 +200,16 @@ ShapeKey ShapeEntityRenderer::getShapeKey() { return builder.build(); } -Item::Bound ShapeEntityRenderer::getBound() { +Item::Bound ShapeEntityRenderer::getBound(RenderArgs* args) { auto mat = _materials.find("0"); if (mat != _materials.end() && mat->second.top().material && mat->second.top().material->isProcedural() && mat->second.top().material->isReady()) { auto procedural = std::static_pointer_cast(mat->second.top().material); if (procedural->hasVertexShader() && procedural->hasBoundOperator()) { - return procedural->getBound(); + return procedural->getBound(args); } } - return Parent::getBound(); + return Parent::getBound(args); } void ShapeEntityRenderer::doRender(RenderArgs* args) { diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.h b/libraries/entities-renderer/src/RenderableShapeEntityItem.h index 9fb2fa8f23..fe62ad48b9 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.h +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.h @@ -26,7 +26,7 @@ public: protected: ShapeKey getShapeKey() override; - Item::Bound getBound() override; + Item::Bound getBound(RenderArgs* args) override; private: virtual bool needsRenderUpdate() const override; diff --git a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp index 1724cf69d5..16d9afb913 100644 --- a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp @@ -227,12 +227,12 @@ ItemKey entities::TextPayload::getKey() const { return ItemKey::Builder::opaqueShape(); } -Item::Bound entities::TextPayload::getBound() const { +Item::Bound entities::TextPayload::getBound(RenderArgs* args) const { auto entityTreeRenderer = DependencyManager::get(); if (entityTreeRenderer) { auto renderable = entityTreeRenderer->renderableForEntityId(_entityID); if (renderable) { - return std::static_pointer_cast(renderable)->getBound(); + return std::static_pointer_cast(renderable)->getBound(args); } } return Item::Bound(); @@ -335,9 +335,9 @@ template <> const ItemKey payloadGetKey(const TextPayload::Pointer& payload) { return ItemKey::Builder::opaqueShape(); } -template <> const Item::Bound payloadGetBound(const TextPayload::Pointer& payload) { +template <> const Item::Bound payloadGetBound(const TextPayload::Pointer& payload, RenderArgs* args) { if (payload) { - return payload->getBound(); + return payload->getBound(args); } return Item::Bound(); } diff --git a/libraries/entities-renderer/src/RenderableTextEntityItem.h b/libraries/entities-renderer/src/RenderableTextEntityItem.h index 1564c98644..0f736d1229 100644 --- a/libraries/entities-renderer/src/RenderableTextEntityItem.h +++ b/libraries/entities-renderer/src/RenderableTextEntityItem.h @@ -88,7 +88,7 @@ public: typedef Payload::DataPointer Pointer; ItemKey getKey() const; - Item::Bound getBound() const; + Item::Bound getBound(RenderArgs* args) const; ShapeKey getShapeKey() const; void render(RenderArgs* args); bool passesZoneOcclusionTest(const std::unordered_set& containingZones) const; @@ -104,7 +104,7 @@ protected: namespace render { template <> const ItemKey payloadGetKey(const entities::TextPayload::Pointer& payload); - template <> const Item::Bound payloadGetBound(const entities::TextPayload::Pointer& payload); + template <> const Item::Bound payloadGetBound(const entities::TextPayload::Pointer& payload, RenderArgs* args); template <> const ShapeKey shapeGetShapeKey(const entities::TextPayload::Pointer& payload); template <> void payloadRender(const entities::TextPayload::Pointer& payload, RenderArgs* args); template <> bool payloadPassesZoneOcclusionTest(const entities::TextPayload::Pointer& payload, const std::unordered_set& containingZones); diff --git a/libraries/procedural/CMakeLists.txt b/libraries/procedural/CMakeLists.txt index d737d34e95..a7394a3670 100644 --- a/libraries/procedural/CMakeLists.txt +++ b/libraries/procedural/CMakeLists.txt @@ -1,4 +1,4 @@ set(TARGET_NAME procedural) setup_hifi_library() -link_hifi_libraries(shared gpu shaders networking graphics material-networking ktx image hfm) +link_hifi_libraries(shared gpu shaders networking render graphics material-networking ktx image hfm) diff --git a/libraries/procedural/src/procedural/Procedural.h b/libraries/procedural/src/procedural/Procedural.h index 9b3d0a9bd4..7d655b5ef4 100644 --- a/libraries/procedural/src/procedural/Procedural.h +++ b/libraries/procedural/src/procedural/Procedural.h @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -113,9 +114,9 @@ public: void setDoesFade(bool doesFade) { _doesFade = doesFade; } bool hasVertexShader() const; - void setBoundOperator(const std::function& boundOperator) { _boundOperator = boundOperator; } + void setBoundOperator(const std::function& boundOperator) { _boundOperator = boundOperator; } bool hasBoundOperator() const { return (bool)_boundOperator; } - AABox getBound() { return _boundOperator(); } + AABox getBound(RenderArgs* args) { return _boundOperator(args); } gpu::Shader::Source _vertexSource; gpu::Shader::Source _vertexSourceSkinned; @@ -199,7 +200,7 @@ private: bool _doesFade { true }; ProceduralProgramKey _prevKey; - std::function _boundOperator { nullptr }; + std::function _boundOperator { nullptr }; mutable std::mutex _mutex; }; @@ -232,9 +233,9 @@ public: void initializeProcedural(); - void setBoundOperator(const std::function& boundOperator) { _procedural.setBoundOperator(boundOperator); } + void setBoundOperator(const std::function& boundOperator) { _procedural.setBoundOperator(boundOperator); } bool hasBoundOperator() const { return _procedural.hasBoundOperator(); } - AABox getBound() { return _procedural.getBound(); } + AABox getBound(RenderArgs* args) { return _procedural.getBound(args); } private: QString _proceduralString; diff --git a/libraries/render-utils/src/AnimDebugDraw.cpp b/libraries/render-utils/src/AnimDebugDraw.cpp index c4020cb4c4..770ac0b7dd 100644 --- a/libraries/render-utils/src/AnimDebugDraw.cpp +++ b/libraries/render-utils/src/AnimDebugDraw.cpp @@ -68,7 +68,7 @@ typedef render::Payload AnimDebugDrawPayload; namespace render { template <> const ItemKey payloadGetKey(const AnimDebugDrawData::Pointer& data) { return (data->_isVisible ? ItemKey::Builder::transparentShape() : ItemKey::Builder::transparentShape().withInvisible()).withTagBits(ItemKey::TAG_BITS_ALL); } - template <> const Item::Bound payloadGetBound(const AnimDebugDrawData::Pointer& data) { return data->_bound; } + template <> const Item::Bound payloadGetBound(const AnimDebugDrawData::Pointer& data, RenderArgs* args) { return data->_bound; } template <> void payloadRender(const AnimDebugDrawData::Pointer& data, RenderArgs* args) { data->render(args); } diff --git a/libraries/render-utils/src/FadeEffectJobs.cpp b/libraries/render-utils/src/FadeEffectJobs.cpp index 43206e77fa..6f6205060a 100644 --- a/libraries/render-utils/src/FadeEffectJobs.cpp +++ b/libraries/render-utils/src/FadeEffectJobs.cpp @@ -575,7 +575,7 @@ void FadeJob::run(const render::RenderContextPointer& renderContext, FadeJob::Ou auto& item = scene->getItem(state.itemId); assert(item.getTransitionId() == transitionId); #endif - if (update(*jobConfig, scene, transaction, state, deltaTime)) { + if (update(renderContext->args, *jobConfig, scene, transaction, state, deltaTime)) { hasTransaction = true; } if (isFirstItem && (state.threshold != jobConfig->threshold)) { @@ -599,7 +599,7 @@ const FadeCategory FadeJob::transitionToCategory[render::Transition::TYPE_COUNT] FADE_AVATAR_CHANGE }; -bool FadeJob::update(const Config& config, const render::ScenePointer& scene, render::Transaction& transaction, render::Transition& transition, const double deltaTime) const { +bool FadeJob::update(RenderArgs* args, const Config& config, const render::ScenePointer& scene, render::Transaction& transaction, render::Transition& transition, const double deltaTime) const { const auto fadeCategory = transitionToCategory[transition.eventType]; auto& eventConfig = config.events[fadeCategory]; auto item = scene->getItemSafe(transition.itemId); @@ -607,11 +607,11 @@ bool FadeJob::update(const Config& config, const render::ScenePointer& scene, re const FadeConfig::Timing timing = (FadeConfig::Timing) eventConfig.timing; if (item.exist()) { - auto aabb = item.getBound(); + auto aabb = item.getBound(args); if (render::Item::isValidID(transition.boundItemId)) { auto boundItem = scene->getItemSafe(transition.boundItemId); if (boundItem.exist()) { - aabb = boundItem.getBound(); + aabb = boundItem.getBound(args); } } auto& dimensions = aabb.getDimensions(); diff --git a/libraries/render-utils/src/FadeEffectJobs.h b/libraries/render-utils/src/FadeEffectJobs.h index 449995dba5..08b49c8d2d 100644 --- a/libraries/render-utils/src/FadeEffectJobs.h +++ b/libraries/render-utils/src/FadeEffectJobs.h @@ -223,7 +223,7 @@ private: float _thresholdScale[FADE_CATEGORY_COUNT]; uint64_t _previousTime{ 0 }; - bool update(const Config& config, const render::ScenePointer& scene, render::Transaction& transaction, render::Transition& transition, const double deltaTime) const; + bool update(RenderArgs* args, const Config& config, const render::ScenePointer& scene, render::Transaction& transaction, render::Transition& transition, const double deltaTime) const; static float computeElementEnterRatio(double time, const double period, FadeConfig::Timing timing); }; diff --git a/libraries/render-utils/src/LightPayload.cpp b/libraries/render-utils/src/LightPayload.cpp index 79e0c1d94d..d1018982d0 100644 --- a/libraries/render-utils/src/LightPayload.cpp +++ b/libraries/render-utils/src/LightPayload.cpp @@ -28,7 +28,7 @@ namespace render { return builder.build(); } - template <> const Item::Bound payloadGetBound(const LightPayload::Pointer& payload) { + template <> const Item::Bound payloadGetBound(const LightPayload::Pointer& payload, RenderArgs* args) { if (payload) { return payload->editBound(); } @@ -98,7 +98,7 @@ namespace render { return builder.build(); } - template <> const Item::Bound payloadGetBound(const KeyLightPayload::Pointer& payload) { + template <> const Item::Bound payloadGetBound(const KeyLightPayload::Pointer& payload, RenderArgs* args) { if (payload) { return payload->editBound(); } diff --git a/libraries/render-utils/src/LightPayload.h b/libraries/render-utils/src/LightPayload.h index 44b79ce10c..4c6695ec58 100644 --- a/libraries/render-utils/src/LightPayload.h +++ b/libraries/render-utils/src/LightPayload.h @@ -43,7 +43,7 @@ protected: namespace render { template <> const ItemKey payloadGetKey(const LightPayload::Pointer& payload); - template <> const Item::Bound payloadGetBound(const LightPayload::Pointer& payload); + template <> const Item::Bound payloadGetBound(const LightPayload::Pointer& payload, RenderArgs* args); template <> void payloadRender(const LightPayload::Pointer& payload, RenderArgs* args); } @@ -79,7 +79,7 @@ protected: namespace render { template <> const ItemKey payloadGetKey(const KeyLightPayload::Pointer& payload); - template <> const Item::Bound payloadGetBound(const KeyLightPayload::Pointer& payload); + template <> const Item::Bound payloadGetBound(const KeyLightPayload::Pointer& payload, RenderArgs* args); template <> void payloadRender(const KeyLightPayload::Pointer& payload, RenderArgs* args); } diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 0e0af6fc71..2d07fec8bf 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -177,8 +177,6 @@ void ModelMeshPartPayload::updateTransformForSkinnedMesh(const Transform& modelT } _parentTransform = modelTransform; - _worldBound = _adjustedLocalBound; - _worldBound.transform(_parentTransform); } void ModelMeshPartPayload::bindMesh(gpu::Batch& batch) { @@ -289,15 +287,23 @@ ItemKey ModelMeshPartPayload::getKey() const { return _itemKey; } -Item::Bound ModelMeshPartPayload::getBound() const { +Item::Bound ModelMeshPartPayload::getBound(RenderArgs* args) const { graphics::MaterialPointer material = _drawMaterials.empty() ? nullptr : _drawMaterials.top().material; if (material && material->isProcedural() && material->isReady()) { auto procedural = std::static_pointer_cast(_drawMaterials.top().material); if (procedural->hasVertexShader() && procedural->hasBoundOperator()) { - return procedural->getBound(); + return procedural->getBound(args); } } - return _worldBound; + + auto worldBound = _adjustedLocalBound; + auto parentTransform = _parentTransform; + if (args) { + parentTransform.setRotation(BillboardModeHelpers::getBillboardRotation(parentTransform.getTranslation(), parentTransform.getRotation(), _billboardMode, + args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? BillboardModeHelpers::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition())); + } + worldBound.transform(parentTransform); + return worldBound; } ShapeKey ModelMeshPartPayload::getShapeKey() const { @@ -396,9 +402,9 @@ template <> const ItemKey payloadGetKey(const ModelMeshPartPayload::Pointer& pay return ItemKey::Builder::opaqueShape(); // for lack of a better idea } -template <> const Item::Bound payloadGetBound(const ModelMeshPartPayload::Pointer& payload) { +template <> const Item::Bound payloadGetBound(const ModelMeshPartPayload::Pointer& payload, RenderArgs* args) { if (payload) { - return payload->getBound(); + return payload->getBound(args); } return Item::Bound(); } diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index 63ccb85470..b5cff41bf8 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -45,7 +45,7 @@ public: // Render Item interface render::ItemKey getKey() const; - render::Item::Bound getBound() const; + render::Item::Bound getBound(RenderArgs* args) const; render::ShapeKey getShapeKey() const; void render(RenderArgs* args); @@ -99,12 +99,11 @@ private: Transform _parentTransform; graphics::Box _localBound; graphics::Box _adjustedLocalBound; - mutable graphics::Box _worldBound; }; namespace render { template <> const ItemKey payloadGetKey(const ModelMeshPartPayload::Pointer& payload); - template <> const Item::Bound payloadGetBound(const ModelMeshPartPayload::Pointer& payload); + template <> const Item::Bound payloadGetBound(const ModelMeshPartPayload::Pointer& payload, RenderArgs* args); template <> const ShapeKey shapeGetShapeKey(const ModelMeshPartPayload::Pointer& payload); template <> void payloadRender(const ModelMeshPartPayload::Pointer& payload, RenderArgs* args); template <> bool payloadPassesZoneOcclusionTest(const ModelMeshPartPayload::Pointer& payload, const std::unordered_set& containingZones); diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index dad2f95420..f4267fdf39 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -1527,7 +1527,7 @@ AABox Model::getRenderableMeshBound() const { // Build a bound using the last known bound from all the renderItems. AABox totalBound; for (auto& renderItem : _modelMeshRenderItems) { - totalBound += renderItem->getBound(); + totalBound += renderItem->getBound(nullptr); } return totalBound; } diff --git a/libraries/render/src/render/CullTask.cpp b/libraries/render/src/render/CullTask.cpp index 164d8e9f21..68bb467f66 100644 --- a/libraries/render/src/render/CullTask.cpp +++ b/libraries/render/src/render/CullTask.cpp @@ -83,7 +83,7 @@ void FetchNonspatialItems::run(const RenderContextPointer& renderContext, const for (auto& id : items) { auto& item = scene->getItem(id); if (filter.test(item.getKey()) && item.passesZoneOcclusionTest(CullTest::_containingZones)) { - outItems.emplace_back(ItemBound(id, item.getBound())); + outItems.emplace_back(ItemBound(id, item.getBound(renderContext->args))); } } } @@ -188,10 +188,10 @@ void CullSpatialSelection::run(const RenderContextPointer& renderContext, for (auto id : inSelection.insideItems) { auto& item = scene->getItem(id); if (filter.test(item.getKey()) && test.zoneOcclusionTest(item)) { - ItemBound itemBound(id, item.getBound()); + ItemBound itemBound(id, item.getBound(args)); outItems.emplace_back(itemBound); if (item.getKey().isMetaCullGroup()) { - item.fetchMetaSubItemBounds(outItems, (*scene)); + item.fetchMetaSubItemBounds(outItems, (*scene), args); } } } @@ -203,10 +203,10 @@ void CullSpatialSelection::run(const RenderContextPointer& renderContext, for (auto id : inSelection.insideSubcellItems) { auto& item = scene->getItem(id); if (filter.test(item.getKey()) && test.zoneOcclusionTest(item)) { - ItemBound itemBound(id, item.getBound()); + ItemBound itemBound(id, item.getBound(args)); outItems.emplace_back(itemBound); if (item.getKey().isMetaCullGroup()) { - item.fetchMetaSubItemBounds(outItems, (*scene)); + item.fetchMetaSubItemBounds(outItems, (*scene), args); } } } @@ -218,10 +218,10 @@ void CullSpatialSelection::run(const RenderContextPointer& renderContext, for (auto id : inSelection.partialItems) { auto& item = scene->getItem(id); if (filter.test(item.getKey()) && test.zoneOcclusionTest(item)) { - ItemBound itemBound(id, item.getBound()); + ItemBound itemBound(id, item.getBound(args)); outItems.emplace_back(itemBound); if (item.getKey().isMetaCullGroup()) { - item.fetchMetaSubItemBounds(outItems, (*scene)); + item.fetchMetaSubItemBounds(outItems, (*scene), args); } } } @@ -233,10 +233,10 @@ void CullSpatialSelection::run(const RenderContextPointer& renderContext, for (auto id : inSelection.partialSubcellItems) { auto& item = scene->getItem(id); if (filter.test(item.getKey()) && test.zoneOcclusionTest(item)) { - ItemBound itemBound(id, item.getBound()); + ItemBound itemBound(id, item.getBound(args)); outItems.emplace_back(itemBound); if (item.getKey().isMetaCullGroup()) { - item.fetchMetaSubItemBounds(outItems, (*scene)); + item.fetchMetaSubItemBounds(outItems, (*scene), args); } } } @@ -250,10 +250,10 @@ void CullSpatialSelection::run(const RenderContextPointer& renderContext, for (auto id : inSelection.insideItems) { auto& item = scene->getItem(id); if (filter.test(item.getKey()) && test.zoneOcclusionTest(item)) { - ItemBound itemBound(id, item.getBound()); + ItemBound itemBound(id, item.getBound(args)); outItems.emplace_back(itemBound); if (item.getKey().isMetaCullGroup()) { - item.fetchMetaSubItemBounds(outItems, (*scene)); + item.fetchMetaSubItemBounds(outItems, (*scene), args); } } } @@ -265,11 +265,11 @@ void CullSpatialSelection::run(const RenderContextPointer& renderContext, for (auto id : inSelection.insideSubcellItems) { auto& item = scene->getItem(id); if (filter.test(item.getKey()) && test.zoneOcclusionTest(item)) { - ItemBound itemBound(id, item.getBound()); + ItemBound itemBound(id, item.getBound(args)); if (test.solidAngleTest(itemBound.bound)) { outItems.emplace_back(itemBound); if (item.getKey().isMetaCullGroup()) { - item.fetchMetaSubItemBounds(outItems, (*scene)); + item.fetchMetaSubItemBounds(outItems, (*scene), args); } } } @@ -282,11 +282,11 @@ void CullSpatialSelection::run(const RenderContextPointer& renderContext, for (auto id : inSelection.partialItems) { auto& item = scene->getItem(id); if (filter.test(item.getKey()) && test.zoneOcclusionTest(item)) { - ItemBound itemBound(id, item.getBound()); + ItemBound itemBound(id, item.getBound(args)); if (test.frustumTest(itemBound.bound)) { outItems.emplace_back(itemBound); if (item.getKey().isMetaCullGroup()) { - item.fetchMetaSubItemBounds(outItems, (*scene)); + item.fetchMetaSubItemBounds(outItems, (*scene), args); } } } @@ -299,11 +299,11 @@ void CullSpatialSelection::run(const RenderContextPointer& renderContext, for (auto id : inSelection.partialSubcellItems) { auto& item = scene->getItem(id); if (filter.test(item.getKey()) && test.zoneOcclusionTest(item)) { - ItemBound itemBound(id, item.getBound()); + ItemBound itemBound(id, item.getBound(args)); if (test.frustumTest(itemBound.bound) && test.solidAngleTest(itemBound.bound)) { outItems.emplace_back(itemBound); if (item.getKey().isMetaCullGroup()) { - item.fetchMetaSubItemBounds(outItems, (*scene)); + item.fetchMetaSubItemBounds(outItems, (*scene), args); } } } diff --git a/libraries/render/src/render/DrawSceneOctree.cpp b/libraries/render/src/render/DrawSceneOctree.cpp index 493ed01c3f..44d54c3c28 100644 --- a/libraries/render/src/render/DrawSceneOctree.cpp +++ b/libraries/render/src/render/DrawSceneOctree.cpp @@ -194,7 +194,7 @@ void DrawItemSelection::run(const RenderContextPointer& renderContext, const Ite render::ItemBounds itemBounds; for (const auto& itemID : itemIDs) { auto& item = scene->getItem(itemID); - auto itemBound = item.getBound(); + auto itemBound = item.getBound(args); if (!itemBound.isInvalid()) { itemBounds.emplace_back(itemID, itemBound); } diff --git a/libraries/render/src/render/FilterTask.cpp b/libraries/render/src/render/FilterTask.cpp index 20d29f3e5d..b269f44b41 100644 --- a/libraries/render/src/render/FilterTask.cpp +++ b/libraries/render/src/render/FilterTask.cpp @@ -139,7 +139,7 @@ void IDsToBounds::run(const RenderContextPointer& renderContext, const ItemIDs& for (auto id : inItems) { auto& item = scene->getItem(id); if (item.exist()) { - outItems.emplace_back(ItemBound{ id, item.getBound() }); + outItems.emplace_back(ItemBound{ id, item.getBound(renderContext->args) }); } } } else { diff --git a/libraries/render/src/render/Item.cpp b/libraries/render/src/render/Item.cpp index f21df58368..369f227566 100644 --- a/libraries/render/src/render/Item.cpp +++ b/libraries/render/src/render/Item.cpp @@ -97,7 +97,7 @@ const ShapeKey Item::getShapeKey() const { return shapeKey; } -uint32_t Item::fetchMetaSubItemBounds(ItemBounds& subItemBounds, Scene& scene) const { +uint32_t Item::fetchMetaSubItemBounds(ItemBounds& subItemBounds, Scene& scene, RenderArgs* args) const { ItemIDs subItems; auto numSubs = fetchMetaSubItems(subItems); @@ -107,7 +107,7 @@ uint32_t Item::fetchMetaSubItemBounds(ItemBounds& subItemBounds, Scene& scene) c if (scene.isAllocatedID(id)) { auto& item = scene.getItem(id); if (item.exist()) { - subItemBounds.emplace_back(id, item.getBound()); + subItemBounds.emplace_back(id, item.getBound(args)); } else { numSubs--; } @@ -133,11 +133,11 @@ namespace render { return payload->getShapeKey(); } - template <> const Item::Bound payloadGetBound(const PayloadProxyInterface::Pointer& payload) { + template <> const Item::Bound payloadGetBound(const PayloadProxyInterface::Pointer& payload, RenderArgs* args) { if (!payload) { return render::Item::Bound(); } - return payload->getBound(); + return payload->getBound(args); } template <> void payloadRender(const PayloadProxyInterface::Pointer& payload, RenderArgs* args) { diff --git a/libraries/render/src/render/Item.h b/libraries/render/src/render/Item.h index 8a67108d0e..5952be8a84 100644 --- a/libraries/render/src/render/Item.h +++ b/libraries/render/src/render/Item.h @@ -431,7 +431,7 @@ public: class PayloadInterface { public: virtual const ItemKey getKey() const = 0; - virtual const Bound getBound() const = 0; + virtual const Bound getBound(RenderArgs* args) const = 0; virtual void render(RenderArgs* args) = 0; virtual const ShapeKey getShapeKey() const = 0; @@ -476,7 +476,7 @@ public: // Payload Interface // Get the bound of the item expressed in world space (or eye space depending on the key.isWorldSpace()) - const Bound getBound() const { return _payload->getBound(); } + const Bound getBound(RenderArgs* args) const { return _payload->getBound(args); } // Get the layer where the item belongs, simply reflecting the key. int getLayer() const { return _key.getLayer(); } @@ -489,7 +489,7 @@ public: // Meta Type Interface uint32_t fetchMetaSubItems(ItemIDs& subItems) const { return _payload->fetchMetaSubItems(subItems); } - uint32_t fetchMetaSubItemBounds(ItemBounds& subItemBounds, Scene& scene) const; + uint32_t fetchMetaSubItemBounds(ItemBounds& subItemBounds, Scene& scene, RenderArgs* args) const; bool passesZoneOcclusionTest(const std::unordered_set& containingZones) const { return _payload->passesZoneOcclusionTest(containingZones); } @@ -524,13 +524,13 @@ public: inline QDebug operator<<(QDebug debug, const Item& item) { - debug << "[Item: _key:" << item.getKey() << ", bounds:" << item.getBound() << "]"; + debug << "[Item: _key:" << item.getKey() << "]"; return debug; } // Item shared interface supported by the payload template const ItemKey payloadGetKey(const std::shared_ptr& payloadData) { return ItemKey(); } -template const Item::Bound payloadGetBound(const std::shared_ptr& payloadData) { return Item::Bound(); } +template const Item::Bound payloadGetBound(const std::shared_ptr& payloadData, RenderArgs* args) { return Item::Bound(); } template void payloadRender(const std::shared_ptr& payloadData, RenderArgs* args) { } // Shape type interface @@ -561,7 +561,7 @@ public: // Payload general interface virtual const ItemKey getKey() const override { return payloadGetKey(_data); } - virtual const Item::Bound getBound() const override { return payloadGetBound(_data); } + virtual const Item::Bound getBound(RenderArgs* args) const override { return payloadGetBound(_data, args); } virtual void render(RenderArgs* args) override { payloadRender(_data, args); } @@ -607,9 +607,9 @@ template <> const ItemKey payloadGetKey(const FooPointer& foo) { foo->makeMyKey(); return foo->_myownKey; } -template <> const Item::Bound payloadGetBound(const FooPointer& foo) { +template <> const Item::Bound payloadGetBound(const FooPointer& foo, RenderArgs* args) { // evaluate Foo's own bound - return foo->evaluateMyBound(); + return foo->evaluateMyBound(args); } // In this example, do not specialize the payloadRender call which means the compiler will use the default version which does nothing @@ -624,7 +624,7 @@ public: virtual ItemKey getKey() = 0; virtual ShapeKey getShapeKey() = 0; - virtual Item::Bound getBound() = 0; + virtual Item::Bound getBound(RenderArgs* args) = 0; virtual void render(RenderArgs* args) = 0; virtual uint32_t metaFetchMetaSubItems(ItemIDs& subItems) const = 0; virtual bool passesZoneOcclusionTest(const std::unordered_set& containingZones) const = 0; @@ -635,7 +635,7 @@ public: }; template <> const ItemKey payloadGetKey(const PayloadProxyInterface::Pointer& payload); -template <> const Item::Bound payloadGetBound(const PayloadProxyInterface::Pointer& payload); +template <> const Item::Bound payloadGetBound(const PayloadProxyInterface::Pointer& payload, RenderArgs* args); template <> void payloadRender(const PayloadProxyInterface::Pointer& payload, RenderArgs* args); template <> uint32_t metaFetchMetaSubItems(const PayloadProxyInterface::Pointer& payload, ItemIDs& subItems); template <> const ShapeKey shapeGetShapeKey(const PayloadProxyInterface::Pointer& payload); diff --git a/libraries/render/src/render/Scene.cpp b/libraries/render/src/render/Scene.cpp index bea111edb5..5500183196 100644 --- a/libraries/render/src/render/Scene.cpp +++ b/libraries/render/src/render/Scene.cpp @@ -305,7 +305,7 @@ void Scene::resetItems(const Transaction::Resets& transactions) { // Update the item's container assert((oldKey.isSpatial() == newKey.isSpatial()) || oldKey._flags.none()); if (newKey.isSpatial()) { - auto newCell = _masterSpatialTree.resetItem(oldCell, oldKey, item.getBound(), itemId, newKey); + auto newCell = _masterSpatialTree.resetItem(oldCell, oldKey, item.getBound(nullptr), itemId, newKey); item.resetCell(newCell, newKey.isSmall()); } else { _masterNonspatialSet.insert(itemId); @@ -361,14 +361,14 @@ void Scene::updateItems(const Transaction::Updates& transactions) { // Update the item's container if (oldKey.isSpatial() == newKey.isSpatial()) { if (newKey.isSpatial()) { - auto newCell = _masterSpatialTree.resetItem(oldCell, oldKey, item.getBound(), updateID, newKey); + auto newCell = _masterSpatialTree.resetItem(oldCell, oldKey, item.getBound(nullptr), updateID, newKey); item.resetCell(newCell, newKey.isSmall()); } } else { if (newKey.isSpatial()) { _masterNonspatialSet.erase(updateID); - auto newCell = _masterSpatialTree.resetItem(oldCell, oldKey, item.getBound(), updateID, newKey); + auto newCell = _masterSpatialTree.resetItem(oldCell, oldKey, item.getBound(nullptr), updateID, newKey); item.resetCell(newCell, newKey.isSmall()); } else { _masterSpatialTree.removeItem(oldCell, oldKey, updateID); diff --git a/libraries/render/src/render/SortTask.cpp b/libraries/render/src/render/SortTask.cpp index 5b4061a10f..266c5be41d 100644 --- a/libraries/render/src/render/SortTask.cpp +++ b/libraries/render/src/render/SortTask.cpp @@ -60,7 +60,7 @@ void render::depthSortItems(const RenderContextPointer& renderContext, bool fron for (auto itemDetails : inItems) { auto item = scene->getItem(itemDetails.id); - auto bound = itemDetails.bound; // item.getBound(); + auto bound = itemDetails.bound; // item.getBound(args); float distanceSquared = args->getViewFrustum().distanceToCameraSquared(bound.calcCenter()); itemBoundSorts.emplace_back(ItemBoundSort(distanceSquared, distanceSquared, distanceSquared, itemDetails.id, bound)); From 7030798d41a3afe6af9b0fb0d6ab7ddc20b52c34 Mon Sep 17 00:00:00 2001 From: HifiExperiments Date: Sun, 17 Jan 2021 22:47:26 -0800 Subject: [PATCH 14/33] cleanup --- libraries/render-utils/src/Model.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index f4267fdf39..234ae203cb 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -984,13 +984,6 @@ void Model::setBillboardMode(BillboardMode billboardMode, const render::ScenePoi return; } - bool useDualQuaternionSkinning = _useDualQuaternionSkinning; - std::unordered_map shouldInvalidatePayloadShapeKeyMap; - - for (auto& shape : _modelMeshRenderItemShapes) { - shouldInvalidatePayloadShapeKeyMap[shape.meshIndex] = shouldInvalidatePayloadShapeKey(shape.meshIndex); - } - render::Transaction transaction; for (auto item : _modelMeshRenderItemIDs) { transaction.updateItem(item, [billboardMode](ModelMeshPartPayload& data) { From 3a821c2b7448175d32d17cfc321fca7f8b9e91f3 Mon Sep 17 00:00:00 2001 From: HifiExperiments Date: Mon, 18 Jan 2021 11:23:44 -0800 Subject: [PATCH 15/33] update create --- .../create/assets/data/createAppTooltips.json | 15 ++------- .../html/js/entityProperties.js | 31 ++++++------------- 2 files changed, 13 insertions(+), 33 deletions(-) diff --git a/scripts/system/create/assets/data/createAppTooltips.json b/scripts/system/create/assets/data/createAppTooltips.json index 478793ab78..edfdad037b 100644 --- a/scripts/system/create/assets/data/createAppTooltips.json +++ b/scripts/system/create/assets/data/createAppTooltips.json @@ -38,10 +38,6 @@ "textEffectThickness": { "tooltip": "The magnitude of the text effect." }, - "textBillboardMode": { - "tooltip": "If enabled, determines how the entity will face the camera.", - "jsPropertyName": "billboardMode" - }, "topMargin": { "tooltip": "The top margin, in meters." }, @@ -223,10 +219,6 @@ "subImage": { "tooltip": "The area of the image that is displayed." }, - "imageBillboardMode": { - "tooltip": "If enabled, determines how the entity will face the camera.", - "jsPropertyName": "billboardMode" - }, "keepAspectRatio": { "tooltip": "If enabled, the image will maintain its original aspect ratio." }, @@ -236,10 +228,6 @@ "dpi": { "tooltip": "The resolution to display the page at, in pixels per inch. Use this to resize your web source in the frame." }, - "webBillboardMode": { - "tooltip": "If enabled, determines how the entity will face the camera.", - "jsPropertyName": "billboardMode" - }, "inputMode": { "tooltip": "The user input mode to use." }, @@ -595,6 +583,9 @@ "primitiveMode": { "tooltip": "The mode in which to draw an entity, either \"Solid\" or \"Wireframe\"." }, + "billboardMode": { + "tooltip": "Determines if and how the entity will face the camera.", + }, "renderWithZones": { "tooltip": "If set, this entity will only render when your avatar is inside of a zone in this list." }, diff --git a/scripts/system/create/entityProperties/html/js/entityProperties.js b/scripts/system/create/entityProperties/html/js/entityProperties.js index f3f92a887e..5f39cdfd45 100644 --- a/scripts/system/create/entityProperties/html/js/entityProperties.js +++ b/scripts/system/create/entityProperties/html/js/entityProperties.js @@ -116,6 +116,16 @@ const GROUPS = [ }, propertyID: "primitiveMode", }, + { + label: "Billboard Mode", + type: "dropdown", + options: { + none: "None", + yaw: "Yaw", + full: "Full" + }, + propertyID: "billboardMode", + }, { label: "Render With Zones", type: "multipleZonesSelection", @@ -229,13 +239,6 @@ const GROUPS = [ decimals: 2, propertyID: "textEffectThickness", }, - { - label: "Billboard Mode", - type: "dropdown", - options: { none: "None", yaw: "Yaw", full: "Full"}, - propertyID: "textBillboardMode", - propertyName: "billboardMode", // actual entity property name - }, { label: "Top Margin", type: "number-draggable", @@ -718,13 +721,6 @@ const GROUPS = [ subLabels: [ "x", "y", "w", "h" ], propertyID: "subImage", }, - { - label: "Billboard Mode", - type: "dropdown", - options: { none: "None", yaw: "Yaw", full: "Full"}, - propertyID: "imageBillboardMode", - propertyName: "billboardMode", // actual entity property name - }, { label: "Keep Aspect Ratio", type: "bool", @@ -774,13 +770,6 @@ const GROUPS = [ decimals: 0, propertyID: "maxFPS", }, - { - label: "Billboard Mode", - type: "dropdown", - options: { none: "None", yaw: "Yaw", full: "Full"}, - propertyID: "webBillboardMode", - propertyName: "billboardMode", // actual entity property name - }, { label: "Input Mode", type: "dropdown", From 82313eccbf919550f8eadd50b386a3e97c37e759 Mon Sep 17 00:00:00 2001 From: Kalila L Date: Thu, 21 Jan 2021 01:51:37 -0500 Subject: [PATCH 16/33] Add userAgent property for web entities. --- .../src/RenderableWebEntityItem.cpp | 10 ++++++++++ .../src/RenderableWebEntityItem.h | 2 ++ libraries/entities/src/EntityItemProperties.cpp | 12 ++++++++++++ libraries/entities/src/EntityItemProperties.h | 1 + libraries/entities/src/EntityPropertyFlags.h | 1 + libraries/entities/src/WebEntityItem.cpp | 17 +++++++++++++++++ libraries/entities/src/WebEntityItem.h | 5 +++++ libraries/networking/src/NetworkingConstants.h | 1 + libraries/networking/src/udt/PacketHeaders.h | 1 + .../create/assets/data/createAppTooltips.json | 3 +++ .../html/js/entityProperties.js | 6 ++++++ 11 files changed, 59 insertions(+) diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index 8b41a85cf8..23f506a795 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -39,6 +39,7 @@ const char* WebEntityRenderer::URL_PROPERTY = "url"; const char* WebEntityRenderer::SCRIPT_URL_PROPERTY = "scriptURL"; const char* WebEntityRenderer::GLOBAL_POSITION_PROPERTY = "globalPosition"; const char* WebEntityRenderer::USE_BACKGROUND_PROPERTY = "useBackground"; +const char* WebEntityRenderer::USER_AGENT_PROPERTY = "userAgent"; std::function&, bool&)> WebEntityRenderer::_acquireWebSurfaceOperator = nullptr; std::function&, bool&, std::vector&)> WebEntityRenderer::_releaseWebSurfaceOperator = nullptr; @@ -194,6 +195,7 @@ void WebEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene _webSurface->getRootItem()->setProperty(URL_PROPERTY, newSourceURL); _webSurface->getRootItem()->setProperty(SCRIPT_URL_PROPERTY, _scriptURL); _webSurface->getRootItem()->setProperty(USE_BACKGROUND_PROPERTY, _useBackground); + _webSurface->getRootItem()->setProperty(USER_AGENT_PROPERTY, _userAgent); _webSurface->getSurfaceContext()->setContextProperty(GLOBAL_POSITION_PROPERTY, vec3toVariant(_contextPosition)); _webSurface->setMaxFps((QUrl(newSourceURL).host().endsWith("youtube.com", Qt::CaseInsensitive)) ? YOUTUBE_MAX_FPS : _maxFPS); ::hifi::scripting::setLocalAccessSafeThread(false); @@ -231,6 +233,14 @@ void WebEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene _useBackground = useBackground; } } + + { + auto userAgent = entity->getUserAgent(); + if (_userAgent != userAgent) { + _webSurface->getRootItem()->setProperty(USER_AGENT_PROPERTY, userAgent); + _userAgent = userAgent; + } + } { auto contextPosition = entity->getWorldPosition(); diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.h b/libraries/entities-renderer/src/RenderableWebEntityItem.h index 63ec722811..7288a380d3 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.h +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.h @@ -36,6 +36,7 @@ public: static const char* SCRIPT_URL_PROPERTY; static const char* GLOBAL_POSITION_PROPERTY; static const char* USE_BACKGROUND_PROPERTY; + static const char* USER_AGENT_PROPERTY; static void setAcquireWebSurfaceOperator(std::function&, bool&)> acquireWebSurfaceOperator) { _acquireWebSurfaceOperator = acquireWebSurfaceOperator; } static void acquireWebSurface(const QString& url, bool htmlContent, QSharedPointer& webSurface, bool& cachedWebSurface) { @@ -97,6 +98,7 @@ private: QString _scriptURL; uint8_t _maxFPS; bool _useBackground; + QString _userAgent; WebInputMode _inputMode; glm::vec3 _contextPosition; diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index ff55137a03..969be6589e 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -603,6 +603,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_INPUT_MODE, inputMode); CHECK_PROPERTY_CHANGE(PROP_SHOW_KEYBOARD_FOCUS_HIGHLIGHT, showKeyboardFocusHighlight); CHECK_PROPERTY_CHANGE(PROP_WEB_USE_BACKGROUND, useBackground); + CHECK_PROPERTY_CHANGE(PROP_USER_AGENT, userAgent); // Polyline CHECK_PROPERTY_CHANGE(PROP_LINE_POINTS, linePoints); @@ -1387,6 +1388,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * @property {boolean} useBackground=true - true if the web entity should have a background, * false if the web entity's background should be transparent. The webpage must have CSS properties for transparency set * on the background-color for this property to have an effect. + * @property {string} userAgent="Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Mobile Safari/537.36" - The user agent for the web entity to use when visiting web pages. * @example * var METERS_TO_INCHES = 39.3701; * var entity = Entities.addEntity({ @@ -1825,6 +1827,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_INPUT_MODE, inputMode, getInputModeAsString()); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_SHOW_KEYBOARD_FOCUS_HIGHLIGHT, showKeyboardFocusHighlight); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_WEB_USE_BACKGROUND, useBackground); + COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_USER_AGENT, userAgent); } // PolyVoxel only @@ -2207,6 +2210,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(inputMode, InputMode); COPY_PROPERTY_FROM_QSCRIPTVALUE(showKeyboardFocusHighlight, bool, setShowKeyboardFocusHighlight); COPY_PROPERTY_FROM_QSCRIPTVALUE(useBackground, bool, setUseBackground); + COPY_PROPERTY_FROM_QSCRIPTVALUE(userAgent, QString, setUserAgent); // Polyline COPY_PROPERTY_FROM_QSCRIPTVALUE(linePoints, qVectorVec3, setLinePoints); @@ -2499,6 +2503,7 @@ void EntityItemProperties::merge(const EntityItemProperties& other) { COPY_PROPERTY_IF_CHANGED(inputMode); COPY_PROPERTY_IF_CHANGED(showKeyboardFocusHighlight); COPY_PROPERTY_IF_CHANGED(useBackground); + COPY_PROPERTY_IF_CHANGED(userAgent); // Polyline COPY_PROPERTY_IF_CHANGED(linePoints); @@ -2899,6 +2904,7 @@ bool EntityItemProperties::getPropertyInfo(const QString& propertyName, EntityPr ADD_PROPERTY_TO_MAP(PROP_INPUT_MODE, InputMode, inputMode, WebInputMode); ADD_PROPERTY_TO_MAP(PROP_SHOW_KEYBOARD_FOCUS_HIGHLIGHT, ShowKeyboardFocusHighlight, showKeyboardFocusHighlight, bool); ADD_PROPERTY_TO_MAP(PROP_WEB_USE_BACKGROUND, useBackground, useBackground, bool); + ADD_PROPERTY_TO_MAP(PROP_USER_AGENT, UserAgent, userAgent, QString); // Polyline ADD_PROPERTY_TO_MAP(PROP_LINE_POINTS, LinePoints, linePoints, QVector); @@ -3330,6 +3336,7 @@ OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketTy APPEND_ENTITY_PROPERTY(PROP_INPUT_MODE, (uint32_t)properties.getInputMode()); APPEND_ENTITY_PROPERTY(PROP_SHOW_KEYBOARD_FOCUS_HIGHLIGHT, properties.getShowKeyboardFocusHighlight()); APPEND_ENTITY_PROPERTY(PROP_WEB_USE_BACKGROUND, properties.getUseBackground()); + APPEND_ENTITY_PROPERTY(PROP_USER_AGENT, properties.getUserAgent()); } if (properties.getType() == EntityTypes::Line) { @@ -3806,6 +3813,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_INPUT_MODE, WebInputMode, setInputMode); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SHOW_KEYBOARD_FOCUS_HIGHLIGHT, bool, setShowKeyboardFocusHighlight); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_WEB_USE_BACKGROUND, bool, setUseBackground); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_USER_AGENT, QString, setUserAgent); } if (properties.getType() == EntityTypes::Line) { @@ -4194,6 +4202,7 @@ void EntityItemProperties::markAllChanged() { _inputModeChanged = true; _showKeyboardFocusHighlightChanged = true; _useBackgroundChanged = true; + _userAgentChanged = true; // Polyline _linePointsChanged = true; @@ -4887,6 +4896,9 @@ QList EntityItemProperties::listChangedProperties() { if (useBackgroundChanged()) { out += "useBackground"; } + if (userAgentChanged()) { + out += "userAgent"; + } // Shape if (shapeChanged()) { diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index f7fde73430..df163e2cd6 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -367,6 +367,7 @@ public: DEFINE_PROPERTY_REF_ENUM(PROP_INPUT_MODE, InputMode, inputMode, WebInputMode, WebInputMode::TOUCH); DEFINE_PROPERTY_REF(PROP_SHOW_KEYBOARD_FOCUS_HIGHLIGHT, ShowKeyboardFocusHighlight, showKeyboardFocusHighlight, bool, true); DEFINE_PROPERTY_REF(PROP_WEB_USE_BACKGROUND, UseBackground, useBackground, bool, true); + DEFINE_PROPERTY_REF(PROP_USER_AGENT, UserAgent, userAgent, QString, WebEntityItem::DEFAULT_USER_AGENT); // Polyline DEFINE_PROPERTY_REF(PROP_LINE_POINTS, LinePoints, linePoints, QVector, ENTITY_ITEM_DEFAULT_EMPTY_VEC3_QVEC); diff --git a/libraries/entities/src/EntityPropertyFlags.h b/libraries/entities/src/EntityPropertyFlags.h index 93bb8a89a7..76585450b8 100644 --- a/libraries/entities/src/EntityPropertyFlags.h +++ b/libraries/entities/src/EntityPropertyFlags.h @@ -319,6 +319,7 @@ enum EntityPropertyList { PROP_INPUT_MODE = PROP_DERIVED_4, PROP_SHOW_KEYBOARD_FOCUS_HIGHLIGHT = PROP_DERIVED_5, PROP_WEB_USE_BACKGROUND = PROP_DERIVED_6, + PROP_USER_AGENT = PROP_DERIVED_7, // Polyline PROP_LINE_POINTS = PROP_DERIVED_0, diff --git a/libraries/entities/src/WebEntityItem.cpp b/libraries/entities/src/WebEntityItem.cpp index 61a1ed18c5..1e3b932b6a 100644 --- a/libraries/entities/src/WebEntityItem.cpp +++ b/libraries/entities/src/WebEntityItem.cpp @@ -25,6 +25,7 @@ #include "EntityTreeElement.h" const QString WebEntityItem::DEFAULT_SOURCE_URL = NetworkingConstants::WEB_ENTITY_DEFAULT_SOURCE_URL; +const QString WebEntityItem::DEFAULT_USER_AGENT = NetworkingConstants::WEB_ENTITY_DEFAULT_USER_AGENT; const uint8_t WebEntityItem::DEFAULT_MAX_FPS = 10; EntityItemPointer WebEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { @@ -63,6 +64,7 @@ EntityItemProperties WebEntityItem::getProperties(const EntityPropertyFlags& des COPY_ENTITY_PROPERTY_TO_PROPERTIES(inputMode, getInputMode); COPY_ENTITY_PROPERTY_TO_PROPERTIES(showKeyboardFocusHighlight, getShowKeyboardFocusHighlight); COPY_ENTITY_PROPERTY_TO_PROPERTIES(useBackground, getUseBackground); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(userAgent, getUserAgent); return properties; } @@ -85,6 +87,7 @@ bool WebEntityItem::setSubClassProperties(const EntityItemProperties& properties SET_ENTITY_PROPERTY_FROM_PROPERTIES(inputMode, setInputMode); SET_ENTITY_PROPERTY_FROM_PROPERTIES(showKeyboardFocusHighlight, setShowKeyboardFocusHighlight); SET_ENTITY_PROPERTY_FROM_PROPERTIES(useBackground, setUseBackground); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(userAgent, setUserAgent); return somethingChanged; } @@ -115,6 +118,7 @@ int WebEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, i READ_ENTITY_PROPERTY(PROP_INPUT_MODE, WebInputMode, setInputMode); READ_ENTITY_PROPERTY(PROP_SHOW_KEYBOARD_FOCUS_HIGHLIGHT, bool, setShowKeyboardFocusHighlight); READ_ENTITY_PROPERTY(PROP_WEB_USE_BACKGROUND, bool, setUseBackground); + READ_ENTITY_PROPERTY(PROP_USER_AGENT, QString, setUserAgent); return bytesRead; } @@ -133,6 +137,7 @@ EntityPropertyFlags WebEntityItem::getEntityProperties(EncodeBitstreamParams& pa requestedProperties += PROP_INPUT_MODE; requestedProperties += PROP_SHOW_KEYBOARD_FOCUS_HIGHLIGHT; requestedProperties += PROP_WEB_USE_BACKGROUND; + requestedProperties += PROP_USER_AGENT; return requestedProperties; } @@ -160,6 +165,7 @@ void WebEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBitst APPEND_ENTITY_PROPERTY(PROP_INPUT_MODE, (uint32_t)getInputMode()); APPEND_ENTITY_PROPERTY(PROP_SHOW_KEYBOARD_FOCUS_HIGHLIGHT, getShowKeyboardFocusHighlight()); APPEND_ENTITY_PROPERTY(PROP_WEB_USE_BACKGROUND, getUseBackground()); + APPEND_ENTITY_PROPERTY(PROP_USER_AGENT, getUserAgent()); } glm::vec3 WebEntityItem::getRaycastDimensions() const { @@ -365,6 +371,17 @@ bool WebEntityItem::getUseBackground() const { return resultWithReadLock([&] { return _useBackground; }); } +void WebEntityItem::setUserAgent(const QString& value) { + withWriteLock([&] { + _needsRenderUpdate |= _userAgent != value; + _userAgent = value; + }); +} + +QString WebEntityItem::getUserAgent() const { + return resultWithReadLock([&] { return _userAgent; }); +} + PulsePropertyGroup WebEntityItem::getPulseProperties() const { return resultWithReadLock([&] { return _pulseProperties; diff --git a/libraries/entities/src/WebEntityItem.h b/libraries/entities/src/WebEntityItem.h index 4b39261bfb..f5cbac43cc 100644 --- a/libraries/entities/src/WebEntityItem.h +++ b/libraries/entities/src/WebEntityItem.h @@ -89,6 +89,10 @@ public: bool getUseBackground() const; void setUseBackground(bool value); + + static const QString DEFAULT_USER_AGENT; + QString getUserAgent() const; + void setUserAgent(const QString& value); PulsePropertyGroup getPulseProperties() const; @@ -105,6 +109,7 @@ protected: WebInputMode _inputMode; bool _showKeyboardFocusHighlight; bool _useBackground; + QString _userAgent; bool _localSafeContext { false }; }; diff --git a/libraries/networking/src/NetworkingConstants.h b/libraries/networking/src/NetworkingConstants.h index b64a0845ac..a3818930dd 100644 --- a/libraries/networking/src/NetworkingConstants.h +++ b/libraries/networking/src/NetworkingConstants.h @@ -46,6 +46,7 @@ namespace NetworkingConstants { // WebEntity Defaults const QString WEB_ENTITY_DEFAULT_SOURCE_URL = "https://vircadia.com/"; + const QString WEB_ENTITY_DEFAULT_USER_AGENT = "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Mobile Safari/537.36"; const QString DEFAULT_AVATAR_COLLISION_SOUND_URL = "https://hifi-public.s3.amazonaws.com/sounds/Collisions-otherorganic/Body_Hits_Impact.wav"; diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index fc74f4459c..ced3d8756b 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -283,6 +283,7 @@ enum class EntityVersion : PacketVersion { ZoneOcclusion, ModelBlendshapes, TransparentWeb, + UserAgent, // Add new versions above here NUM_PACKET_TYPE, diff --git a/scripts/system/create/assets/data/createAppTooltips.json b/scripts/system/create/assets/data/createAppTooltips.json index 478793ab78..f898d594c6 100644 --- a/scripts/system/create/assets/data/createAppTooltips.json +++ b/scripts/system/create/assets/data/createAppTooltips.json @@ -616,6 +616,9 @@ "scriptURL": { "tooltip": "The URL of a script to inject into the web page." }, + "userAgent": { + "tooltip": "The user agent that the web entity will use when visiting web pages." + }, "alignToGrid": { "tooltip": "Used to align entities to the grid, or floor of the environment.", "skipJSProperty": true diff --git a/scripts/system/create/entityProperties/html/js/entityProperties.js b/scripts/system/create/entityProperties/html/js/entityProperties.js index f3f92a887e..6898bb1b5c 100644 --- a/scripts/system/create/entityProperties/html/js/entityProperties.js +++ b/scripts/system/create/entityProperties/html/js/entityProperties.js @@ -800,6 +800,12 @@ const GROUPS = [ type: "string", propertyID: "scriptURL", placeholder: "URL", + }, + { + label: "User Agent", + type: "string", + propertyID: "userAgent", + placeholder: "User Agent", } ] }, From 54d57afdae8f952152c8ca6a667521318a284125 Mon Sep 17 00:00:00 2001 From: HifiExperiments Date: Thu, 21 Jan 2021 19:21:38 -0800 Subject: [PATCH 17/33] use rotation property to determine which axis is facing you --- interface/src/Application.cpp | 4 ++-- libraries/entities/src/EntityItemProperties.cpp | 3 ++- libraries/entities/src/EntityTree.cpp | 7 +++++++ 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index e38d156336..bad0b6a3aa 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2462,7 +2462,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo glm::vec3 dPosition = frustumPos - position; // If x and z are 0, atan(x, z) is undefined, so default to 0 degrees float yawRotation = dPosition.x == 0.0f && dPosition.z == 0.0f ? 0.0f : glm::atan(dPosition.x, dPosition.z); - glm::quat result = glm::quat(glm::vec3(0.0f, yawRotation, 0.0f)); + glm::quat result = glm::quat(glm::vec3(0.0f, yawRotation, 0.0f)) * rotation; if (rotate90x) { result *= ROTATE_90X; } @@ -2475,7 +2475,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo // make sure s is not NaN for any component if (glm::length2(s) > 0.0f) { - glm::quat result = glm::conjugate(glm::toQuat(glm::lookAt(frustumPos, position, avatarUP))); + glm::quat result = glm::conjugate(glm::toQuat(glm::lookAt(frustumPos, position, avatarUP))) * rotation; if (rotate90x) { result *= ROTATE_90X; } diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 870ed09515..1e771d8e43 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -811,7 +811,8 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * @property {Uuid[]} renderWithZones=[]] - A list of entity IDs representing with which zones this entity should render. * If it is empty, this entity will render normally. Otherwise, this entity will only render if your avatar is within * one of the zones in this list. - * @property {BillboardMode} billboardMode="none" - Whether the entity is billboarded to face the camera. + * @property {BillboardMode} billboardMode="none" - Whether the entity is billboarded to face the camera. Use the rotation + * property to control which axis is facing you. * * @property {Entities.Grab} grab - The entity's grab-related properties. * diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 3ed1ad581c..eeb42626c2 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -3141,6 +3141,13 @@ bool EntityTree::readFromMap(QVariantMap& map, const bool isImport) { } } + // Before, billboarded entities ignored rotation. Now, they use it to determine which axis is facing you. + if (contentVersion < (int)EntityVersion::AllBillboardMode) { + if (properties.getBillboardMode() != BillboardMode::NONE) { + properties.setRotation(glm::quat()); + } + } + EntityItemPointer entity = addEntity(entityItemID, properties, isImport); if (!entity) { qCDebug(entities) << "adding Entity failed:" << entityItemID << properties.getType(); From bb898aac332853c790add6e75d768050feeae073 Mon Sep 17 00:00:00 2001 From: HifiExperiments Date: Thu, 21 Jan 2021 21:05:00 -0800 Subject: [PATCH 18/33] non-exact collisions should work on models with pivots and useOriginalPivot=true --- .../src/RenderableModelEntityItem.cpp | 4 ++-- libraries/entities/src/EntityItem.cpp | 17 ++++++++++++++--- libraries/entities/src/EntityItem.h | 2 +- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 3f72527d72..3c807848f8 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -463,7 +463,7 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) { } } shapeInfo.setParams(type, 0.5f * extents, getCompoundShapeURL() + model->getSnapModelToRegistrationPoint()); - adjustShapeInfoByRegistration(shapeInfo); + adjustShapeInfoByRegistration(shapeInfo, model->getSnapModelToRegistrationPoint()); } else if (type >= SHAPE_TYPE_SIMPLE_HULL && type <= SHAPE_TYPE_STATIC_MESH) { updateModelBounds(); model->updateGeometry(); @@ -696,7 +696,7 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) { } shapeInfo.setParams(type, 0.5f * extents.size(), getModelURL() + model->getSnapModelToRegistrationPoint()); - adjustShapeInfoByRegistration(shapeInfo); + adjustShapeInfoByRegistration(shapeInfo, model->getSnapModelToRegistrationPoint()); } else { EntityItem::computeShapeInfo(shapeInfo); } diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index f7bd0266fa..4f80b8b5d1 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -1734,11 +1734,22 @@ float EntityItem::getRadius() const { return 0.5f * glm::length(getScaledDimensions()); } -void EntityItem::adjustShapeInfoByRegistration(ShapeInfo& info) const { +void EntityItem::adjustShapeInfoByRegistration(ShapeInfo& info, bool includePivot) const { + glm::vec3 offset; glm::vec3 registrationPoint = getRegistrationPoint(); if (registrationPoint != ENTITY_ITEM_DEFAULT_REGISTRATION_POINT) { - glm::vec3 registration = (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - registrationPoint) * getScaledDimensions(); - info.setOffset(registration); + offset += (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - registrationPoint) * getScaledDimensions(); + } + + if (includePivot) { + glm::vec3 pivot = getPivot(); + if (pivot != ENTITY_ITEM_ZERO_VEC3) { + offset += pivot; + } + } + + if (offset != ENTITY_ITEM_ZERO_VEC3) { + info.setOffset(offset); } } diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index e12c2d864b..bc3fd8b61e 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -404,7 +404,7 @@ public: // TODO: get rid of users of getRadius()... float getRadius() const; - virtual void adjustShapeInfoByRegistration(ShapeInfo& info) const; + virtual void adjustShapeInfoByRegistration(ShapeInfo& info, bool includePivot = true) const; virtual bool contains(const glm::vec3& point) const; virtual bool isReadyToComputeShape() const { return !isDead(); } From f8119daa47c2e46f6f9779fee5c055bf828e0f36 Mon Sep 17 00:00:00 2001 From: Kalila L Date: Sat, 23 Jan 2021 18:49:21 -0500 Subject: [PATCH 19/33] Remove user agent overwriting in RequestFilters. --- libraries/ui/src/ui/types/RequestFilters.cpp | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/libraries/ui/src/ui/types/RequestFilters.cpp b/libraries/ui/src/ui/types/RequestFilters.cpp index 0eea5230ca..ceac3d00e8 100644 --- a/libraries/ui/src/ui/types/RequestFilters.cpp +++ b/libraries/ui/src/ui/types/RequestFilters.cpp @@ -4,6 +4,7 @@ // // Created by Kunal Gosar on 2017-03-10. // Copyright 2017 High Fidelity, Inc. +// Copyright 2021 Vircadia contributors. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -25,7 +26,7 @@ namespace { - bool isAuthableHighFidelityURL(const QUrl& url) { + bool isAuthableMetaverseURL(const QUrl& url) { auto metaverseServerURL = MetaverseAPI::getCurrentMetaverseServerURL(); static QStringList HF_HOSTS = { metaverseServerURL.toString() @@ -70,7 +71,7 @@ void RequestFilters::interceptHFWebEngineRequest(QWebEngineUrlRequestInfo& info, } // check if this is a request to a highfidelity URL - bool isAuthable = isAuthableHighFidelityURL(info.requestUrl()); + bool isAuthable = isAuthableMetaverseURL(info.requestUrl()); auto accountManager = DependencyManager::get(); if (isAuthable) { // if we have an access token, add it to the right HTTP header for authorization @@ -82,13 +83,6 @@ void RequestFilters::interceptHFWebEngineRequest(QWebEngineUrlRequestInfo& info, info.setHttpHeader(OAUTH_AUTHORIZATION_HEADER.toLocal8Bit(), bearerTokenString.toLocal8Bit()); } } - static const QString USER_AGENT = "User-Agent"; - const QString tokenStringMobile{ NetworkingConstants::MOBILE_USER_AGENT }; - const QString tokenStringMetaverse{ NetworkingConstants::METAVERSE_USER_AGENT }; - const QString tokenStringLimitedCommerce{ "Chrome/48.0 (VircadiaInterface limitedCommerce)" }; - - const QString tokenString = !isAuthable ? tokenStringMobile : (accountManager->getLimitedCommerce() ? tokenStringLimitedCommerce : tokenStringMetaverse); - info.setHttpHeader(USER_AGENT.toLocal8Bit(), tokenString.toLocal8Bit()); } void RequestFilters::interceptFileType(QWebEngineUrlRequestInfo& info) { From dac9c4917562da95e1a8cd2d7c793cd07b9ed800 Mon Sep 17 00:00:00 2001 From: Kalila L Date: Fri, 29 Jan 2021 06:01:43 -0500 Subject: [PATCH 20/33] Add QML portions of userAgent handling. (FML) --- interface/resources/qml/Web3DSurface.qml | 22 ++++++++++++++----- .../+webengine/FlickableWebViewCore.qml | 16 +++++++++----- .../qml/controls/FlickableWebViewCore.qml | 12 +++++----- interface/resources/qml/controls/WebView.qml | 5 +++-- 4 files changed, 37 insertions(+), 18 deletions(-) diff --git a/interface/resources/qml/Web3DSurface.qml b/interface/resources/qml/Web3DSurface.qml index e9c8d119d6..c92e09e7bf 100644 --- a/interface/resources/qml/Web3DSurface.qml +++ b/interface/resources/qml/Web3DSurface.qml @@ -19,16 +19,17 @@ Item { property string url: "" property string scriptUrl: null property bool useBackground: true + property string userAgent: "" onUrlChanged: { - load(root.url, root.scriptUrl, root.useBackground); + load(root.url, root.scriptUrl, root.useBackground, root.userAgent); } onScriptUrlChanged: { if (root.item) { root.item.scriptUrl = root.scriptUrl; } else { - load(root.url, root.scriptUrl, root.useBackground); + load(root.url, root.scriptUrl, root.useBackground, root.userAgent); } } @@ -36,14 +37,22 @@ Item { if (root.item) { root.item.useBackground = root.useBackground; } else { - load(root.url, root.scriptUrl, root.useBackground); + load(root.url, root.scriptUrl, root.useBackground, root.userAgent); + } + } + + onUserAgentChanged: { + if (root.item) { + root.item.userAgent = root.userAgent; + } else { + load(root.url, root.scriptUrl, root.useBackground, root.userAgent); } } property var item: null - function load(url, scriptUrl, useBackground) { - // Ensure we reset any existing item to "about:blank" to ensure web audio stops: DEV-2375 + function load(url, scriptUrl, useBackground, userAgent) { + // Ensure we reset any existing item toB "about:blank" to ensure web audio stops: DEV-2375 if (root.item != null) { root.item.url = "about:blank" root.item.destroy() @@ -54,11 +63,12 @@ Item { root.item.url = url root.item.scriptUrl = scriptUrl root.item.useBackground = useBackground + root.item.userAgent = userAgent }) } Component.onCompleted: { - load(root.url, root.scriptUrl, root.useBackground); + load(root.url, root.scriptUrl, root.useBackground, root.userAgent); } signal sendToScript(var message); diff --git a/interface/resources/qml/controls/+webengine/FlickableWebViewCore.qml b/interface/resources/qml/controls/+webengine/FlickableWebViewCore.qml index a0585ae053..c39a28fb41 100644 --- a/interface/resources/qml/controls/+webengine/FlickableWebViewCore.qml +++ b/interface/resources/qml/controls/+webengine/FlickableWebViewCore.qml @@ -13,10 +13,11 @@ Item { property alias url: webViewCore.url property alias canGoBack: webViewCore.canGoBack property alias webViewCore: webViewCore - property alias webViewCoreProfile: webViewCore.profile + // property alias webViewCoreProfile: webViewCore.profile property string webViewCoreUserAgent property bool useBackground: webViewCore.useBackground + property string userAgent: webViewCore.profile.httpUserAgent property string userScriptUrl: "" property string urlTag: "noDownload=false"; @@ -34,6 +35,10 @@ Item { permissionPopupBackground.visible = false; } + onUserAgentChanged: { + webViewCore.profile.httpUserAgent = flick.userAgent; + } + StylesUIt.HifiConstants { id: hifi } @@ -74,7 +79,7 @@ Item { function onLoadingChanged(loadRequest) { if (WebEngineView.LoadStartedStatus === loadRequest.status) { - + webViewCore.profile.httpUserAgent = flick.userAgent; // Required to support clicking on "hifi://" links var url = loadRequest.url.toString(); url = (url.indexOf("?") >= 0) ? url + urlTag : url + "?" + urlTag; @@ -101,7 +106,6 @@ Item { height: parent.height backgroundColor: (flick.useBackground) ? "white" : "transparent" - profile: HFWebEngineProfile; settings.pluginsEnabled: true settings.touchIconsEnabled: true settings.allowRunningInsecureContent: true @@ -136,8 +140,10 @@ Item { webChannel.registerObject("eventBridge", eventBridge); webChannel.registerObject("eventBridgeWrapper", eventBridgeWrapper); - if (webViewCoreUserAgent !== undefined) { - webViewCore.profile.httpUserAgent = webViewCoreUserAgent + if (flick.userAgent !== undefined) { + webViewCore.profile.httpUserAgent = flick.userAgent; + webViewCore.profile.offTheRecord = false; + webViewCore.profile.storageName = "qmlWebEngine"; } else { webViewCore.profile.httpUserAgent += " (VircadiaInterface)"; } diff --git a/interface/resources/qml/controls/FlickableWebViewCore.qml b/interface/resources/qml/controls/FlickableWebViewCore.qml index 35f3182f98..876582921c 100644 --- a/interface/resources/qml/controls/FlickableWebViewCore.qml +++ b/interface/resources/qml/controls/FlickableWebViewCore.qml @@ -11,12 +11,12 @@ Item { property alias url: webViewCore.url property alias canGoBack: webViewCore.canGoBack property alias webViewCore: webViewCore - property alias webViewCoreProfile: webViewCore.profile - property string webViewCoreUserAgent + // property alias webViewCoreProfile: webViewCore.profile - property bool useBackground: webViewCore.useBackground + property alias useBackground: webViewCore.useBackground + property alias userAgent: webViewCore.userAgent property string userScriptUrl: "" - property string urlTag: "noDownload=false"; + property string urlTag: "noDownload=false" signal newViewRequestedCallback(var request) signal loadingChangedCallback(var loadRequest) @@ -43,10 +43,12 @@ Item { } function onLoadingChanged(loadRequest) { + webViewCore.profile.httpUserAgent: "LOLICON" } ControlsUit.ProxyWebView { - id: webViewCore + id: + profile: WebEngineProfile { httpUserAgent: "TEST2"} width: parent.width height: parent.height } diff --git a/interface/resources/qml/controls/WebView.qml b/interface/resources/qml/controls/WebView.qml index b46c8c904d..99fd2c0bdd 100644 --- a/interface/resources/qml/controls/WebView.qml +++ b/interface/resources/qml/controls/WebView.qml @@ -24,6 +24,7 @@ Item { property alias flickable: webroot.interactive property alias blurOnCtrlShift: webroot.blurOnCtrlShift property alias useBackground: webroot.useBackground + property alias userAgent: webroot.userAgent function stop() { webroot.stop(); @@ -37,13 +38,13 @@ Item { } */ - property alias viewProfile: webroot.webViewCoreProfile + // property alias viewProfile: webroot.webViewCoreProfile FlickableWebViewCore { id: webroot width: parent.width height: keyboardEnabled && keyboardRaised ? parent.height - keyboard.height : parent.height - + onLoadingChangedCallback: { keyboardRaised = false; punctuationMode = false; From 4576632b690956bac216d304ebdcfd4236091406 Mon Sep 17 00:00:00 2001 From: Kalila <69767640+digisomni@users.noreply.github.com> Date: Fri, 29 Jan 2021 13:31:06 -0500 Subject: [PATCH 21/33] Update FlickableWebViewCore.qml --- interface/resources/qml/controls/FlickableWebViewCore.qml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/interface/resources/qml/controls/FlickableWebViewCore.qml b/interface/resources/qml/controls/FlickableWebViewCore.qml index 876582921c..62eb592810 100644 --- a/interface/resources/qml/controls/FlickableWebViewCore.qml +++ b/interface/resources/qml/controls/FlickableWebViewCore.qml @@ -43,12 +43,10 @@ Item { } function onLoadingChanged(loadRequest) { - webViewCore.profile.httpUserAgent: "LOLICON" } ControlsUit.ProxyWebView { - id: - profile: WebEngineProfile { httpUserAgent: "TEST2"} + id: webViewCore width: parent.width height: parent.height } From b516b29e64f08efba626fd004313f35809f9b24d Mon Sep 17 00:00:00 2001 From: Kalila <69767640+digisomni@users.noreply.github.com> Date: Fri, 29 Jan 2021 13:34:52 -0500 Subject: [PATCH 22/33] Update WebView.qml --- interface/resources/qml/controls/WebView.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/qml/controls/WebView.qml b/interface/resources/qml/controls/WebView.qml index 99fd2c0bdd..c060a5660d 100644 --- a/interface/resources/qml/controls/WebView.qml +++ b/interface/resources/qml/controls/WebView.qml @@ -44,7 +44,7 @@ Item { id: webroot width: parent.width height: keyboardEnabled && keyboardRaised ? parent.height - keyboard.height : parent.height - + onLoadingChangedCallback: { keyboardRaised = false; punctuationMode = false; From cd0755d1bbec47b788ad6788db18edd36b8bb56b Mon Sep 17 00:00:00 2001 From: Kalila <69767640+digisomni@users.noreply.github.com> Date: Fri, 29 Jan 2021 13:35:27 -0500 Subject: [PATCH 23/33] Update interface/resources/qml/Web3DSurface.qml Co-authored-by: HifiExperiments <53453710+HifiExperiments@users.noreply.github.com> --- interface/resources/qml/Web3DSurface.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/qml/Web3DSurface.qml b/interface/resources/qml/Web3DSurface.qml index c92e09e7bf..3bee87d669 100644 --- a/interface/resources/qml/Web3DSurface.qml +++ b/interface/resources/qml/Web3DSurface.qml @@ -52,7 +52,7 @@ Item { property var item: null function load(url, scriptUrl, useBackground, userAgent) { - // Ensure we reset any existing item toB "about:blank" to ensure web audio stops: DEV-2375 + // Ensure we reset any existing item to "about:blank" to ensure web audio stops: DEV-2375 if (root.item != null) { root.item.url = "about:blank" root.item.destroy() From 19cd0fa6ad7cb965ce4930e3b9783fbd7a860a63 Mon Sep 17 00:00:00 2001 From: HifiExperiments Date: Fri, 29 Jan 2021 22:31:17 -0800 Subject: [PATCH 24/33] CR --- interface/src/Application.cpp | 3 ++- interface/src/avatar/AvatarManager.cpp | 3 ++- libraries/entities/src/EntityItem.h | 2 +- libraries/render-utils/src/MeshPartPayload.cpp | 2 +- libraries/shared/src/BillboardMode.cpp | 17 ++++++++++++++++- libraries/shared/src/BillboardMode.h | 8 +++++--- 6 files changed, 27 insertions(+), 8 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index bad0b6a3aa..79a8714dfe 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2455,7 +2455,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo DependencyManager::get()->setPrecisionPicking(rayPickID, value); }); - BillboardModeHelpers::setBillboardRotationOperator([](const glm::vec3& position, const glm::quat& rotation, BillboardMode billboardMode, const glm::vec3& frustumPos, bool rotate90x) { + BillboardModeHelpers::setBillboardRotationOperator([](const glm::vec3& position, const glm::quat& rotation, + BillboardMode billboardMode, const glm::vec3& frustumPos, bool rotate90x) { const glm::quat ROTATE_90X = glm::angleAxis(-(float)M_PI_2, Vectors::RIGHT); if (billboardMode == BillboardMode::YAW) { //rotate about vertical to face the camera diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 24d9379ab9..91d339a38d 100755 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -843,7 +843,8 @@ RayToAvatarIntersectionResult AvatarManager::findRayIntersectionVector(const Pic BoxFace subMeshFace = BoxFace::UNKNOWN_FACE; glm::vec3 subMeshSurfaceNormal; QVariantMap subMeshExtraInfo; - if (avatar->getSkeletonModel()->findRayIntersectionAgainstSubMeshes(defaultFrameRayOrigin, defaultFrameRayDirection, viewFrustumPos, subMeshDistance, subMeshFace, subMeshSurfaceNormal, subMeshExtraInfo, true, false)) { + if (avatar->getSkeletonModel()->findRayIntersectionAgainstSubMeshes(defaultFrameRayOrigin, defaultFrameRayDirection, viewFrustumPos, subMeshDistance, + subMeshFace, subMeshSurfaceNormal, subMeshExtraInfo, true, false)) { rayAvatarResult._distance = subMeshDistance; rayAvatarResult._intersectionPoint = ray.origin + subMeshDistance * rayDirection; rayAvatarResult._intersectionNormal = subMeshSurfaceNormal; diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 2acb73abbf..60214cdf87 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -180,7 +180,7 @@ public: QVariantMap& extraInfo, bool precisionPicking) const { return true; } virtual bool findDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration, const glm::vec3& viewFrustumPos, OctreeElementPointer& element, - float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, + float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const { return true; } // attributes applicable to all entity types diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 2d07fec8bf..8ba5be54e6 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -292,7 +292,7 @@ Item::Bound ModelMeshPartPayload::getBound(RenderArgs* args) const { if (material && material->isProcedural() && material->isReady()) { auto procedural = std::static_pointer_cast(_drawMaterials.top().material); if (procedural->hasVertexShader() && procedural->hasBoundOperator()) { - return procedural->getBound(args); + return procedural->getBound(args); } } diff --git a/libraries/shared/src/BillboardMode.cpp b/libraries/shared/src/BillboardMode.cpp index 8243cf772d..d8d1b64f65 100644 --- a/libraries/shared/src/BillboardMode.cpp +++ b/libraries/shared/src/BillboardMode.cpp @@ -15,9 +15,24 @@ const char* billboardModeNames[] = { }; static const size_t BILLBOARD_MODE_NAMES = (sizeof(billboardModeNames) / sizeof(billboardModeNames[0])); -std::function BillboardModeHelpers::_getBillboardRotationOperator = [](const glm::vec3&, const glm::quat& rotation, BillboardMode, const glm::vec3&, bool) { return rotation; }; +std::function BillboardModeHelpers::_getBillboardRotationOperator = + [](const glm::vec3&, const glm::quat& rotation, BillboardMode, const glm::vec3&, bool) { return rotation; }; std::function BillboardModeHelpers::_getPrimaryViewFrustumPositionOperator = []() { return glm::vec3(0.0f); }; +void BillboardModeHelpers::setBillboardRotationOperator(std::function getBillboardRotationOperator) { + _getBillboardRotationOperator = getBillboardRotationOperator; +} + +glm::quat BillboardModeHelpers::getBillboardRotation(const glm::vec3& position, const glm::quat& rotation, BillboardMode billboardMode, + const glm::vec3& frustumPos, bool rotate90x = false) { + return _getBillboardRotationOperator(position, rotation, billboardMode, frustumPos, rotate90x); +} + +void BillboardModeHelpers::setPrimaryViewFrustumPositionOperator(std::function getPrimaryViewFrustumPositionOperator) { + _getPrimaryViewFrustumPositionOperator = getPrimaryViewFrustumPositionOperator; +} + QString BillboardModeHelpers::getNameForBillboardMode(BillboardMode mode) { if (((int)mode <= 0) || ((int)mode >= (int)BILLBOARD_MODE_NAMES)) { mode = (BillboardMode)0; diff --git a/libraries/shared/src/BillboardMode.h b/libraries/shared/src/BillboardMode.h index 31f11766d8..4d123c0603 100644 --- a/libraries/shared/src/BillboardMode.h +++ b/libraries/shared/src/BillboardMode.h @@ -43,9 +43,11 @@ class BillboardModeHelpers { public: static QString getNameForBillboardMode(BillboardMode mode); - static void setBillboardRotationOperator(std::function getBillboardRotationOperator) { _getBillboardRotationOperator = getBillboardRotationOperator; } - static glm::quat getBillboardRotation(const glm::vec3& position, const glm::quat& rotation, BillboardMode billboardMode, const glm::vec3& frustumPos, bool rotate90x = false) { return _getBillboardRotationOperator(position, rotation, billboardMode, frustumPos, rotate90x); } - static void setPrimaryViewFrustumPositionOperator(std::function getPrimaryViewFrustumPositionOperator) { _getPrimaryViewFrustumPositionOperator = getPrimaryViewFrustumPositionOperator; } + static void setBillboardRotationOperator(std::function getBillboardRotationOperator); + static glm::quat getBillboardRotation(const glm::vec3& position, const glm::quat& rotation, BillboardMode billboardMode, + const glm::vec3& frustumPos, bool rotate90x = false); + static void setPrimaryViewFrustumPositionOperator(std::function getPrimaryViewFrustumPositionOperator); static glm::vec3 getPrimaryViewFrustumPosition() { return _getPrimaryViewFrustumPositionOperator(); } private: From c57b1a92f31d5ed00d19f5f4f214997a67f10fff Mon Sep 17 00:00:00 2001 From: Kalila L Date: Sat, 30 Jan 2021 02:16:53 -0500 Subject: [PATCH 25/33] CR + update user agent. --- .../controls/+webengine/FlickableWebViewCore.qml | 1 - .../qml/controls/FlickableWebViewCore.qml | 1 - interface/resources/qml/controls/WebView.qml | 2 -- libraries/entities/src/EntityItemProperties.cpp | 4 +++- libraries/networking/src/NetworkingConstants.h | 16 +++++++++------- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/interface/resources/qml/controls/+webengine/FlickableWebViewCore.qml b/interface/resources/qml/controls/+webengine/FlickableWebViewCore.qml index c39a28fb41..e7d4f645aa 100644 --- a/interface/resources/qml/controls/+webengine/FlickableWebViewCore.qml +++ b/interface/resources/qml/controls/+webengine/FlickableWebViewCore.qml @@ -13,7 +13,6 @@ Item { property alias url: webViewCore.url property alias canGoBack: webViewCore.canGoBack property alias webViewCore: webViewCore - // property alias webViewCoreProfile: webViewCore.profile property string webViewCoreUserAgent property bool useBackground: webViewCore.useBackground diff --git a/interface/resources/qml/controls/FlickableWebViewCore.qml b/interface/resources/qml/controls/FlickableWebViewCore.qml index 62eb592810..3e2e74b3d5 100644 --- a/interface/resources/qml/controls/FlickableWebViewCore.qml +++ b/interface/resources/qml/controls/FlickableWebViewCore.qml @@ -11,7 +11,6 @@ Item { property alias url: webViewCore.url property alias canGoBack: webViewCore.canGoBack property alias webViewCore: webViewCore - // property alias webViewCoreProfile: webViewCore.profile property alias useBackground: webViewCore.useBackground property alias userAgent: webViewCore.userAgent diff --git a/interface/resources/qml/controls/WebView.qml b/interface/resources/qml/controls/WebView.qml index c060a5660d..ebef5f85c5 100644 --- a/interface/resources/qml/controls/WebView.qml +++ b/interface/resources/qml/controls/WebView.qml @@ -38,8 +38,6 @@ Item { } */ - // property alias viewProfile: webroot.webViewCoreProfile - FlickableWebViewCore { id: webroot width: parent.width diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 969be6589e..b7fa84e623 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -1388,7 +1388,9 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * @property {boolean} useBackground=true - true if the web entity should have a background, * false if the web entity's background should be transparent. The webpage must have CSS properties for transparency set * on the background-color for this property to have an effect. - * @property {string} userAgent="Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Mobile Safari/537.36" - The user agent for the web entity to use when visiting web pages. + * @property {string} userAgent - The user agent for the web entity to use when visiting web pages. + * Default value: Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) + * Chrome/69.0.3497.113 Mobile Safari/537.36 * @example * var METERS_TO_INCHES = 39.3701; * var entity = Entities.addEntity({ diff --git a/libraries/networking/src/NetworkingConstants.h b/libraries/networking/src/NetworkingConstants.h index a3818930dd..ccdb9ea75c 100644 --- a/libraries/networking/src/NetworkingConstants.h +++ b/libraries/networking/src/NetworkingConstants.h @@ -25,6 +25,8 @@ namespace NetworkingConstants { // You can avoid changing that and still effectively use a connected domain on staging // if you manually generate a personal access token for the domains scope // at https://staging.highfidelity.com/user/tokens/new?for_domain_server=true + + const QString WEB_ENGINE_VERSION = "Chrome/69.0.3497.113"; // For now we only have one Metaverse server. const QUrl METAVERSE_SERVER_URL_STABLE { "https://metaverse.vircadia.com/live" }; @@ -37,16 +39,16 @@ namespace NetworkingConstants { // Use a custom User-Agent to avoid ModSecurity filtering, e.g. by hosting providers. const QByteArray VIRCADIA_USER_AGENT = "Mozilla/5.0 (VircadiaInterface)"; - const QString WEB_ENGINE_USER_AGENT = "Chrome/48.0 (VircadiaInterface)"; - const QString METAVERSE_USER_AGENT = "Chrome/48.0 (VircadiaInterface)"; - const QString MOBILE_USER_AGENT = "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Mobile Safari/537.36"; - - const QUrl BUILDS_XML_URL("https://highfidelity.com/builds.xml"); - const QUrl MASTER_BUILDS_XML_URL("https://highfidelity.com/dev-builds.xml"); + const QString WEB_ENGINE_USER_AGENT = "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) " + WEB_ENGINE_VERSION + " Mobile Safari/537.36"; + const QString MOBILE_USER_AGENT = "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) " + WEB_ENGINE_VERSION + " Mobile Safari/537.36"; // WebEntity Defaults const QString WEB_ENTITY_DEFAULT_SOURCE_URL = "https://vircadia.com/"; - const QString WEB_ENTITY_DEFAULT_USER_AGENT = "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Mobile Safari/537.36"; + const QString WEB_ENTITY_DEFAULT_USER_AGENT = WEB_ENGINE_USER_AGENT; + + // Builds URLs + const QUrl BUILDS_XML_URL("https://highfidelity.com/builds.xml"); + const QUrl MASTER_BUILDS_XML_URL("https://highfidelity.com/dev-builds.xml"); const QString DEFAULT_AVATAR_COLLISION_SOUND_URL = "https://hifi-public.s3.amazonaws.com/sounds/Collisions-otherorganic/Body_Hits_Impact.wav"; From 4554aa338b1a3157711df499cf5c11fcf5eb86d7 Mon Sep 17 00:00:00 2001 From: HifiExperiments <53453710+HifiExperiments@users.noreply.github.com> Date: Sat, 30 Jan 2021 00:28:25 -0800 Subject: [PATCH 26/33] Update BillboardMode.cpp --- libraries/shared/src/BillboardMode.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/shared/src/BillboardMode.cpp b/libraries/shared/src/BillboardMode.cpp index d8d1b64f65..6cc6dca976 100644 --- a/libraries/shared/src/BillboardMode.cpp +++ b/libraries/shared/src/BillboardMode.cpp @@ -25,7 +25,7 @@ void BillboardModeHelpers::setBillboardRotationOperator(std::function Date: Wed, 3 Feb 2021 17:35:17 -0800 Subject: [PATCH 27/33] dirty physics on useOriginalPivot change, other small fix for compound shapes --- .../src/RenderableModelEntityItem.cpp | 3 ++- libraries/entities/src/ModelEntityItem.cpp | 13 +++++++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 3c807848f8..6213853de7 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -456,10 +456,11 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) { // multiply each point by scale before handing the point-set off to the physics engine. // also determine the extents of the collision model. glm::vec3 registrationOffset = dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint()); + glm::vec3 offset = model->getSnapModelToRegistrationPoint() ? model->getOffset() : glm::vec3(0.0f); for (int32_t i = 0; i < pointCollection.size(); i++) { for (int32_t j = 0; j < pointCollection[i].size(); j++) { // back compensate for registration so we can apply that offset to the shapeInfo later - pointCollection[i][j] = scaleToFit * (pointCollection[i][j] + model->getOffset()) - registrationOffset; + pointCollection[i][j] = scaleToFit * (pointCollection[i][j] + offset) - registrationOffset; } } shapeInfo.setParams(type, 0.5f * extents, getCompoundShapeURL() + model->getSnapModelToRegistrationPoint()); diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index 50fd1f267a..61362896ee 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -721,10 +721,19 @@ QVector ModelEntityItem::getBlendshapeCoefficientVector() { } void ModelEntityItem::setUseOriginalPivot(bool value) { + bool changed = false; withWriteLock([&] { - _needsRenderUpdate |= _useOriginalPivot != value; - _useOriginalPivot = value; + if (_useOriginalPivot != value) { + _needsRenderUpdate = true; + _useOriginalPivot = value; + changed = true; + } }); + + if (changed) { + markDirtyFlags(Simulation::DIRTY_SHAPE | Simulation::DIRTY_MASS); + locationChanged(); + } } bool ModelEntityItem::getUseOriginalPivot() const { From 766b91f1a3b64938b44a99e358ef2d6685a68586 Mon Sep 17 00:00:00 2001 From: HifiExperiments Date: Fri, 5 Feb 2021 20:46:14 -0800 Subject: [PATCH 28/33] add note about only supporting 0,0,0 pivot --- libraries/entities/src/EntityItemProperties.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index b09c2b3938..5b4b60e599 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -1004,7 +1004,8 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * When editing this property, only coefficients that you are editing will change; it will not explicitly reset other * coefficients. * @property {boolean} useOriginalPivot=false - If false, the model will be centered based on its content, - * ignoring any offset in the model itself. If true, the model will respect its original offset. + * ignoring any offset in the model itself. If true, the model will respect its original offset. Currently, + * only pivots relative to {x: 0, y: 0, z: 0} are supported. * @property {string} textures="" - A JSON string of texture name, URL pairs used when rendering the model in place of the * model's original textures. Use a texture name from the originalTextures property to override that texture. * Only the texture names and URLs to be overridden need be specified; original textures are used where there are no From c3c9b638e114b9ac203ab1ab4b75b3619a54d5a2 Mon Sep 17 00:00:00 2001 From: Kalila L Date: Tue, 9 Feb 2021 01:50:38 -0500 Subject: [PATCH 29/33] When creating a domain ID, set networking to full (wizard) --- domain-server/resources/web/wizard/js/wizard.js | 1 + 1 file changed, 1 insertion(+) diff --git a/domain-server/resources/web/wizard/js/wizard.js b/domain-server/resources/web/wizard/js/wizard.js index d7eda38055..b54b3d658d 100644 --- a/domain-server/resources/web/wizard/js/wizard.js +++ b/domain-server/resources/web/wizard/js/wizard.js @@ -193,6 +193,7 @@ function promptToCreateDomainID() { var formJSON = { "metaverse": { + "automatic_networking": "full", "id": domainID } }; From c80283ae8f0b321b48e5579142113d9bf62ce9fc Mon Sep 17 00:00:00 2001 From: Kalila L Date: Tue, 9 Feb 2021 02:02:06 -0500 Subject: [PATCH 30/33] Also fix two other issues. --- domain-server/resources/web/js/shared.js | 2 +- domain-server/resources/web/wizard/js/wizard.js | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/domain-server/resources/web/js/shared.js b/domain-server/resources/web/js/shared.js index 542771c60e..bec8d19119 100644 --- a/domain-server/resources/web/js/shared.js +++ b/domain-server/resources/web/js/shared.js @@ -505,7 +505,7 @@ function createDomainIDPrompt(callback) { swal({ title: 'Finish Registering Domain', type: 'input', - text: 'Enter a label for this machine.

This will help you identify which domain ID belongs to which machine.

This is a required step for registration.

', + text: 'Enter a label for this Domain Server.

This will help you identify which domain ID belongs to which server.

This is a required step for registration.

Acceptable characters are [A-Z][a-z0-9]+-_. Date: Tue, 9 Feb 2021 16:43:22 -0500 Subject: [PATCH 31/33] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index db8a0c63f6..d260c76d0d 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Vircadia™ is a 3D social software project seeking to incrementally bring about a truly free and open metaverse, in desktop and XR. -### [Download](https://vircadia.com/download-vircadia/) +### [Website](https://vircadia.com/) | [Discord](https://discordapp.com/invite/Pvx2vke) | [Download](https://vircadia.com/download-vircadia/) ### Releases From 65bef5d3d434b527f86fd9e843f041262209ce28 Mon Sep 17 00:00:00 2001 From: Kalila L Date: Wed, 10 Feb 2021 06:52:29 -0500 Subject: [PATCH 32/33] Fix profile errors in QML. (also add FIXME's) --- interface/resources/qml/controls/TabletWebScreen.qml | 6 +++++- interface/resources/qml/controls/TabletWebView.qml | 6 +++++- interface/resources/qml/controls/WebView.qml | 6 ++++++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/controls/TabletWebScreen.qml b/interface/resources/qml/controls/TabletWebScreen.qml index 8aaafbd0fe..78292b8bcd 100644 --- a/interface/resources/qml/controls/TabletWebScreen.qml +++ b/interface/resources/qml/controls/TabletWebScreen.qml @@ -27,7 +27,11 @@ Item { } */ - property alias viewProfile: webroot.webViewCoreProfile + // FIXME - Reimplement profiles for... why? Was it so that new windows opened share the same profile? + // Are profiles written to by the webengine during the session? + // Removed in PR Feature/web entity user agent #988 + // + // property alias viewProfile: webroot.webViewCoreProfile FlickableWebViewCore { id: webroot diff --git a/interface/resources/qml/controls/TabletWebView.qml b/interface/resources/qml/controls/TabletWebView.qml index 9cbbd48a22..0984f09141 100644 --- a/interface/resources/qml/controls/TabletWebView.qml +++ b/interface/resources/qml/controls/TabletWebView.qml @@ -25,7 +25,11 @@ Item { property bool isDesktop: false property alias url: web.url property alias webView: web.webViewCore - property alias profile: web.webViewCoreProfile + // FIXME - Reimplement profiles for... why? Was it so that new windows opened share the same profile? + // Are profiles written to by the webengine during the session? + // Removed in PR Feature/web entity user agent #988 + // + // property alias profile: web.webViewCoreProfile property bool remove: false property bool closeButtonVisible: true diff --git a/interface/resources/qml/controls/WebView.qml b/interface/resources/qml/controls/WebView.qml index ebef5f85c5..a90824f3ad 100644 --- a/interface/resources/qml/controls/WebView.qml +++ b/interface/resources/qml/controls/WebView.qml @@ -38,6 +38,12 @@ Item { } */ + // FIXME - Reimplement profiles for... why? Was it so that new windows opened share the same profile? + // Are profiles written to by the webengine during the session? + // Removed in PR Feature/web entity user agent #988 + // + // property alias viewProfile: webroot.webViewCoreProfile + FlickableWebViewCore { id: webroot width: parent.width From dfa9b55223c8fe0b9358ddbdd3994bcd037ce124 Mon Sep 17 00:00:00 2001 From: Kalila L Date: Wed, 10 Feb 2021 16:19:53 -0500 Subject: [PATCH 33/33] Add back removed lines and add FIXME's. --- .../resources/qml/controls/+webengine/FlickableWebViewCore.qml | 3 +++ interface/resources/qml/controls/FlickableWebViewCore.qml | 3 +++ 2 files changed, 6 insertions(+) diff --git a/interface/resources/qml/controls/+webengine/FlickableWebViewCore.qml b/interface/resources/qml/controls/+webengine/FlickableWebViewCore.qml index e7d4f645aa..931233622a 100644 --- a/interface/resources/qml/controls/+webengine/FlickableWebViewCore.qml +++ b/interface/resources/qml/controls/+webengine/FlickableWebViewCore.qml @@ -13,6 +13,9 @@ Item { property alias url: webViewCore.url property alias canGoBack: webViewCore.canGoBack property alias webViewCore: webViewCore + // FIXME - This was commented out to allow for manual setting of the userAgent. + // + // property alias webViewCoreProfile: webViewCore.profile property string webViewCoreUserAgent property bool useBackground: webViewCore.useBackground diff --git a/interface/resources/qml/controls/FlickableWebViewCore.qml b/interface/resources/qml/controls/FlickableWebViewCore.qml index 3e2e74b3d5..8fdaf5feb4 100644 --- a/interface/resources/qml/controls/FlickableWebViewCore.qml +++ b/interface/resources/qml/controls/FlickableWebViewCore.qml @@ -11,6 +11,9 @@ Item { property alias url: webViewCore.url property alias canGoBack: webViewCore.canGoBack property alias webViewCore: webViewCore + // FIXME - This was commented out to allow for manual setting of the userAgent. + // + // property alias webViewCoreProfile: webViewCore.profile property alias useBackground: webViewCore.useBackground property alias userAgent: webViewCore.userAgent
Create a Web entity displaying at 1920 x 1080 resolution.Create a Web entity displaying at 1920 x 1080 resolution.