From b590cd5b8928766d14f6e2cf4bb8b020a6f21a52 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 28 Nov 2017 17:51:06 -0800 Subject: [PATCH] avatar-entities which are children of an avatar will scale with the avatar --- interface/src/Application.cpp | 4 +- interface/src/Util.cpp | 2 +- interface/src/ui/overlays/Base3DOverlay.cpp | 10 +- interface/src/ui/overlays/Line3DOverlay.cpp | 8 +- .../src/avatars-renderer/Avatar.h | 1 + .../src/EntityTreeRenderer.cpp | 2 +- .../src/RenderableLightEntityItem.cpp | 2 +- .../src/RenderableModelEntityItem.cpp | 22 ++-- .../src/RenderableModelEntityItem.h | 2 +- .../src/RenderablePolyVoxEntityItem.cpp | 12 +- .../src/RenderableShapeEntityItem.cpp | 4 +- .../src/RenderableTextEntityItem.cpp | 4 +- .../src/RenderableWebEntityItem.cpp | 4 +- .../src/RenderableZoneEntityItem.cpp | 4 +- libraries/entities/src/EntityItem.cpp | 65 +++++++--- libraries/entities/src/EntityItem.h | 11 +- .../entities/src/EntityItemProperties.cpp | 21 ++++ libraries/entities/src/EntityItemProperties.h | 2 + libraries/entities/src/EntityPropertyFlags.h | 2 + .../entities/src/EntityScriptingInterface.cpp | 64 ++++++++-- libraries/entities/src/EntityTreeElement.cpp | 4 +- libraries/entities/src/LightEntityItem.cpp | 14 +-- libraries/entities/src/LightEntityItem.h | 2 +- libraries/entities/src/LineEntityItem.cpp | 6 +- libraries/entities/src/ModelEntityItem.cpp | 2 +- .../entities/src/ParticleEffectEntityItem.cpp | 4 +- libraries/entities/src/PolyLineEntityItem.cpp | 4 +- libraries/entities/src/PolyVoxEntityItem.cpp | 6 +- libraries/entities/src/ShapeEntityItem.cpp | 14 +-- libraries/entities/src/ShapeEntityItem.h | 2 +- libraries/entities/src/TextEntityItem.cpp | 6 +- libraries/entities/src/TextEntityItem.h | 2 +- libraries/entities/src/WebEntityItem.cpp | 6 +- libraries/entities/src/WebEntityItem.h | 2 +- libraries/entities/src/ZoneEntityItem.cpp | 2 +- libraries/shared/src/SpatiallyNestable.cpp | 119 ++++++++++++++++-- libraries/shared/src/SpatiallyNestable.h | 28 +++-- 37 files changed, 336 insertions(+), 133 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index d7fcbf6467..45ede258b7 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4238,7 +4238,7 @@ void Application::init() { getEntities()->init(); getEntities()->setEntityLoadingPriorityFunction([this](const EntityItem& item) { - auto dims = item.getDimensions(); + auto dims = item.getScaledDimensions(); auto maxSize = glm::compMax(dims); if (maxSize <= 0.0f) { @@ -4590,7 +4590,7 @@ void Application::setKeyboardFocusEntity(const EntityItemID& entityItemID) { _lastAcceptedKeyPress = usecTimestampNow(); setKeyboardFocusHighlight(entity->getWorldPosition(), entity->getWorldOrientation(), - entity->getDimensions() * FOCUS_HIGHLIGHT_EXPANSION_FACTOR); + entity->getScaledDimensions() * FOCUS_HIGHLIGHT_EXPANSION_FACTOR); } } } diff --git a/interface/src/Util.cpp b/interface/src/Util.cpp index aad7768b99..e5e94da68a 100644 --- a/interface/src/Util.cpp +++ b/interface/src/Util.cpp @@ -407,7 +407,7 @@ void shapeInfoCalculator(const ShapeEntityItem * const shapeEntity, ShapeInfo &s ShapeInfo::PointList points; pointCollection.push_back(points); - GeometryCache::computeSimpleHullPointListForShape((int)shapeEntity->getShape(), shapeEntity->getDimensions(), pointCollection.back()); + GeometryCache::computeSimpleHullPointListForShape((int)shapeEntity->getShape(), shapeEntity->getScaledDimensions(), pointCollection.back()); shapeInfo.setPointCollection(pointCollection); } diff --git a/interface/src/ui/overlays/Base3DOverlay.cpp b/interface/src/ui/overlays/Base3DOverlay.cpp index 3e29395eba..884a174041 100644 --- a/interface/src/ui/overlays/Base3DOverlay.cpp +++ b/interface/src/ui/overlays/Base3DOverlay.cpp @@ -42,7 +42,7 @@ Base3DOverlay::Base3DOverlay(const Base3DOverlay* base3DOverlay) : setTransform(base3DOverlay->getTransform()); } -QVariantMap convertOverlayLocationFromScriptSemantics(const QVariantMap& properties) { +QVariantMap convertOverlayLocationFromScriptSemantics(const QVariantMap& properties, bool scalesWithParent) { // the position and rotation in _transform are relative to the parent (aka local). The versions coming from // scripts are in world-frame, unless localPosition or localRotation are used. Patch up the properties // so that "position" and "rotation" are relative-to-parent values. @@ -56,7 +56,7 @@ QVariantMap convertOverlayLocationFromScriptSemantics(const QVariantMap& propert result["position"] = result["localPosition"]; } else if (result["position"].isValid()) { glm::vec3 localPosition = SpatiallyNestable::worldToLocal(vec3FromVariant(result["position"]), - parentID, parentJointIndex, success); + parentID, parentJointIndex, scalesWithParent, success); if (success) { result["position"] = vec3toVariant(localPosition); } @@ -66,7 +66,7 @@ QVariantMap convertOverlayLocationFromScriptSemantics(const QVariantMap& propert result["orientation"] = result["localOrientation"]; } else if (result["orientation"].isValid()) { glm::quat localOrientation = SpatiallyNestable::worldToLocal(quatFromVariant(result["orientation"]), - parentID, parentJointIndex, success); + parentID, parentJointIndex, scalesWithParent, success); if (success) { result["orientation"] = quatToVariant(localOrientation); } @@ -118,7 +118,7 @@ void Base3DOverlay::setProperties(const QVariantMap& originalProperties) { } } - properties = convertOverlayLocationFromScriptSemantics(properties); + properties = convertOverlayLocationFromScriptSemantics(properties, getScalesWithParent()); Overlay::setProperties(properties); bool needRenderItemUpdate = false; @@ -310,4 +310,4 @@ SpatialParentTree* Base3DOverlay::getParentTree() const { void Base3DOverlay::setVisible(bool visible) { Parent::setVisible(visible); notifyRenderVariableChange(); -} \ No newline at end of file +} diff --git a/interface/src/ui/overlays/Line3DOverlay.cpp b/interface/src/ui/overlays/Line3DOverlay.cpp index 66a6772aa5..2fa9f7c7d3 100644 --- a/interface/src/ui/overlays/Line3DOverlay.cpp +++ b/interface/src/ui/overlays/Line3DOverlay.cpp @@ -56,12 +56,12 @@ glm::vec3 Line3DOverlay::getEnd() const { if (_endParentID != QUuid()) { glm::vec3 localOffset = _direction * _length; bool success; - worldEnd = localToWorld(localOffset, _endParentID, _endParentJointIndex, success); + worldEnd = localToWorld(localOffset, _endParentID, _endParentJointIndex, getScalesWithParent(), success); return worldEnd; } localEnd = getLocalEnd(); - worldEnd = localToWorld(localEnd, getParentID(), getParentJointIndex(), success); + worldEnd = localToWorld(localEnd, getParentID(), getParentJointIndex(), getScalesWithParent(), success); if (!success) { qDebug() << "Line3DOverlay::getEnd failed"; } @@ -79,10 +79,10 @@ void Line3DOverlay::setEnd(const glm::vec3& end) { glm::vec3 offset; if (_endParentID != QUuid()) { - offset = worldToLocal(end, _endParentID, _endParentJointIndex, success); + offset = worldToLocal(end, _endParentID, _endParentJointIndex, getScalesWithParent(), success); } else { localStart = getLocalStart(); - localEnd = worldToLocal(end, getParentID(), getParentJointIndex(), success); + localEnd = worldToLocal(end, getParentID(), getParentJointIndex(), getScalesWithParent(), success); offset = localEnd - localStart; } if (!success) { diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index a723a8e1b0..959cb6912b 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h @@ -264,6 +264,7 @@ public: virtual float getModelScale() const { return _modelScale; } virtual void setModelScale(float scale) { _modelScale = scale; } + virtual glm::vec3 scaleForChildren() const override { return glm::vec3(getModelScale()); } virtual void setAvatarEntityDataChanged(bool value) override; diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 5f7899ae74..77c538619c 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -610,7 +610,7 @@ static glm::vec2 projectOntoEntityXYPlane(EntityItemPointer entity, const PickRa glm::vec3 entityPosition = entity->getWorldPosition(); glm::quat entityRotation = entity->getWorldOrientation(); - glm::vec3 entityDimensions = entity->getDimensions(); + glm::vec3 entityDimensions = entity->getScaledDimensions(); glm::vec3 entityRegistrationPoint = entity->getRegistrationPoint(); // project the intersection point onto the local xy plane of the object. diff --git a/libraries/entities-renderer/src/RenderableLightEntityItem.cpp b/libraries/entities-renderer/src/RenderableLightEntityItem.cpp index 696d7ab8db..fc33ebc498 100644 --- a/libraries/entities-renderer/src/RenderableLightEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableLightEntityItem.cpp @@ -37,7 +37,7 @@ void LightEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPoint lightPayload.editBound() = render::Item::Bound(); } - glm::vec3 dimensions = entity->getDimensions(); + glm::vec3 dimensions = entity->getScaledDimensions(); float largestDiameter = glm::compMax(dimensions); light->setMaximumRadius(largestDiameter / 2.0f); diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 06b81ff428..3921432a43 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -74,11 +74,11 @@ RenderableModelEntityItem::RenderableModelEntityItem(const EntityItemID& entityI RenderableModelEntityItem::~RenderableModelEntityItem() { } -void RenderableModelEntityItem::setDimensions(const glm::vec3& value) { +void RenderableModelEntityItem::setUnscaledDimensions(const glm::vec3& value) { glm::vec3 newDimensions = glm::max(value, glm::vec3(0.0f)); // can never have negative dimensions - if (getDimensions() != newDimensions) { + if (getUnscaledDimensions() != newDimensions) { _dimensionsInitialized = true; - ModelEntityItem::setDimensions(value); + ModelEntityItem::setUnscaledDimensions(value); } } @@ -120,11 +120,11 @@ void RenderableModelEntityItem::doInitialModelSimulation() { // 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. This doesn't cause the // entity values to change -- it just allows the model to match once it comes in. - model->setScaleToFit(false, getDimensions()); + model->setScaleToFit(false, getScaledDimensions()); model->setSnapModelToRegistrationPoint(false, getRegistrationPoint()); // now recalculate the bounds and registration - model->setScaleToFit(true, getDimensions()); + model->setScaleToFit(true, getScaledDimensions()); model->setSnapModelToRegistrationPoint(true, getRegistrationPoint()); model->setRotation(getWorldOrientation()); model->setTranslation(getWorldPosition()); @@ -165,7 +165,7 @@ bool RenderableModelEntityItem::needsUpdateModelBounds() const { return true; } - if (model->getScaleToFitDimensions() != getDimensions()) { + if (model->getScaleToFitDimensions() != getScaledDimensions()) { return true; } @@ -205,17 +205,17 @@ void RenderableModelEntityItem::updateModelBounds() { updateRenderItems = true; } - if (model->getScaleToFitDimensions() != getDimensions() || + if (model->getScaleToFitDimensions() != getScaledDimensions() || model->getRegistrationPoint() != getRegistrationPoint()) { // 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. // This doesn't cause the entity values to change -- it just allows the model to match once it comes in. - model->setScaleToFit(false, getDimensions()); + model->setScaleToFit(false, getScaledDimensions()); model->setSnapModelToRegistrationPoint(false, getRegistrationPoint()); // now recalculate the bounds and registration - model->setScaleToFit(true, getDimensions()); + model->setScaleToFit(true, getScaledDimensions()); model->setSnapModelToRegistrationPoint(true, getRegistrationPoint()); updateRenderItems = true; model->scaleToFit(); @@ -368,7 +368,7 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) { const uint32_t QUAD_STRIDE = 4; ShapeType type = getShapeType(); - glm::vec3 dimensions = getDimensions(); + glm::vec3 dimensions = getScaledDimensions(); auto model = getModel(); if (type == SHAPE_TYPE_COMPOUND) { updateModelBounds(); @@ -1163,7 +1163,7 @@ bool ModelEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPoin return true; } - if (model->getScaleToFitDimensions() != entity->getDimensions() || + if (model->getScaleToFitDimensions() != entity->getScaledDimensions() || model->getRegistrationPoint() != entity->getRegistrationPoint()) { return true; } diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index 0272bed575..34c0a8f81d 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -60,7 +60,7 @@ public: RenderableModelEntityItem(const EntityItemID& entityItemID, bool dimensionsInitialized); virtual ~RenderableModelEntityItem(); - virtual void setDimensions(const glm::vec3& value) override; + virtual void setUnscaledDimensions(const glm::vec3& value) override; virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const override; void doInitialModelSimulation(); diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index 356bf3a69c..496f8b7323 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -213,7 +213,7 @@ void RenderablePolyVoxEntityItem::setVoxelSurfaceStyle(PolyVoxSurfaceStyle voxel glm::vec3 RenderablePolyVoxEntityItem::getSurfacePositionAdjustment() const { glm::vec3 result; withReadLock([&] { - glm::vec3 scale = getDimensions() / _voxelVolumeSize; // meters / voxel-units + glm::vec3 scale = getScaledDimensions() / _voxelVolumeSize; // meters / voxel-units if (isEdged(_voxelSurfaceStyle)) { result = scale / -2.0f; } @@ -228,7 +228,7 @@ glm::mat4 RenderablePolyVoxEntityItem::voxelToLocalMatrix() const { voxelVolumeSize = _voxelVolumeSize; }); - glm::vec3 dimensions = getDimensions(); + 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 @@ -393,7 +393,7 @@ bool RenderablePolyVoxEntityItem::setSphere(const vec3& centerWorldCoords, float glm::mat4 vtwMatrix = voxelToWorldMatrix(); glm::mat4 wtvMatrix = glm::inverse(vtwMatrix); - glm::vec3 dimensions = getDimensions(); + glm::vec3 dimensions = getScaledDimensions(); glm::vec3 voxelSize = dimensions / _voxelVolumeSize; float smallestDimensionSize = voxelSize.x; smallestDimensionSize = glm::min(smallestDimensionSize, voxelSize.y); @@ -454,7 +454,7 @@ bool RenderablePolyVoxEntityItem::setCapsule(const vec3& startWorldCoords, const glm::mat4 vtwMatrix = voxelToWorldMatrix(); glm::mat4 wtvMatrix = glm::inverse(vtwMatrix); - glm::vec3 dimensions = getDimensions(); + glm::vec3 dimensions = getScaledDimensions(); glm::vec3 voxelSize = dimensions / _voxelVolumeSize; float smallestDimensionSize = voxelSize.x; smallestDimensionSize = glm::min(smallestDimensionSize, voxelSize.y); @@ -580,7 +580,7 @@ bool RenderablePolyVoxEntityItem::findDetailedRayIntersection(const glm::vec3& o // the PolyVox ray intersection code requires a near and far point. // set ray cast length to long enough to cover all of the voxel space float distanceToEntity = glm::distance(origin, getWorldPosition()); - glm::vec3 dimensions = getDimensions(); + glm::vec3 dimensions = getScaledDimensions(); float largestDimension = glm::compMax(dimensions) * 2.0f; glm::vec3 farPoint = origin + normDirection * (distanceToEntity + largestDimension); @@ -668,7 +668,7 @@ bool RenderablePolyVoxEntityItem::isReadyToComputeShape() const { void RenderablePolyVoxEntityItem::computeShapeInfo(ShapeInfo& info) { ShapeType shapeType = getShapeType(); if (shapeType == SHAPE_TYPE_NONE) { - info.setParams(getShapeType(), 0.5f * getDimensions()); + info.setParams(getShapeType(), 0.5f * getScaledDimensions()); return; } diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp index 3524709395..cbee221399 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp @@ -63,7 +63,7 @@ bool ShapeEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPoin return true; } - if (_dimensions != entity->getDimensions()) { + if (_dimensions != entity->getScaledDimensions()) { return true; } @@ -82,7 +82,7 @@ void ShapeEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce _shape = entity->getShape(); _position = entity->getWorldPosition(); - _dimensions = entity->getDimensions(); + _dimensions = entity->getScaledDimensions(); _orientation = entity->getWorldOrientation(); _renderTransform = getModelTransform(); diff --git a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp index 6c0f4447ae..968c181940 100644 --- a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp @@ -54,7 +54,7 @@ bool TextEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPoint return true; } - if (_dimensions != entity->getDimensions()) { + if (_dimensions != entity->getScaledDimensions()) { return true; } @@ -67,7 +67,7 @@ bool TextEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPoint void TextEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) { _textColor = toGlm(entity->getTextColorX()); _backgroundColor = toGlm(entity->getBackgroundColorX()); - _dimensions = entity->getDimensions(); + _dimensions = entity->getScaledDimensions(); _faceCamera = entity->getFaceCamera(); _lineHeight = entity->getLineHeight(); _text = entity->getText(); diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index cdd260e73c..05a2228607 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -144,7 +144,7 @@ void WebEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene glm::vec2 windowSize = getWindowSize(entity); _webSurface->resize(QSize(windowSize.x, windowSize.y)); _renderTransform = getModelTransform(); - _renderTransform.postScale(entity->getDimensions()); + _renderTransform.postScale(entity->getScaledDimensions()); }); } @@ -274,7 +274,7 @@ void WebEntityRenderer::destroyWebSurface() { } glm::vec2 WebEntityRenderer::getWindowSize(const TypedEntityPointer& entity) const { - glm::vec2 dims = glm::vec2(entity->getDimensions()); + glm::vec2 dims = glm::vec2(entity->getScaledDimensions()); dims *= METERS_TO_INCHES * _lastDPI; // ensure no side is never larger then MAX_WINDOW_SIZE diff --git a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp index 7a5c50df50..784945f0bb 100644 --- a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp @@ -206,7 +206,7 @@ void ZoneEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scen entity->resetRenderingPropertiesChanged(); _lastPosition = entity->getWorldPosition(); _lastRotation = entity->getWorldOrientation(); - _lastDimensions = entity->getDimensions(); + _lastDimensions = entity->getScaledDimensions(); _keyLightProperties = entity->getKeyLightProperties(); _skyboxProperties = entity->getSkyboxProperties(); @@ -278,7 +278,7 @@ bool ZoneEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPoint if (entity->getWorldPosition() != _lastPosition) { return true; } - if (entity->getDimensions() != _lastDimensions) { + if (entity->getScaledDimensions() != _lastDimensions) { return true; } if (entity->getWorldOrientation() != _lastRotation) { diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index c8e7ce6c11..d244f6d557 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -49,6 +49,7 @@ EntityItem::EntityItem(const EntityItemID& entityItemID) : { setLocalVelocity(ENTITY_ITEM_DEFAULT_VELOCITY); setLocalAngularVelocity(ENTITY_ITEM_DEFAULT_ANGULAR_VELOCITY); + setUnscaledDimensions(ENTITY_ITEM_DEFAULT_DIMENSIONS); // explicitly set transform parts to set dirty flags used by batch rendering locationChanged(); dimensionsChanged(); @@ -241,7 +242,7 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet APPEND_ENTITY_PROPERTY(PROP_ANGULAR_VELOCITY, getLocalAngularVelocity()); APPEND_ENTITY_PROPERTY(PROP_ACCELERATION, getAcceleration()); - APPEND_ENTITY_PROPERTY(PROP_DIMENSIONS, getDimensions()); + APPEND_ENTITY_PROPERTY(PROP_DIMENSIONS, getUnscaledDimensions()); APPEND_ENTITY_PROPERTY(PROP_DENSITY, getDensity()); APPEND_ENTITY_PROPERTY(PROP_GRAVITY, getGravity()); APPEND_ENTITY_PROPERTY(PROP_DAMPING, getDamping()); @@ -776,7 +777,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef READ_ENTITY_PROPERTY(PROP_ACCELERATION, glm::vec3, customSetAcceleration); } - READ_ENTITY_PROPERTY(PROP_DIMENSIONS, glm::vec3, setDimensions); + READ_ENTITY_PROPERTY(PROP_DIMENSIONS, glm::vec3, setUnscaledDimensions); READ_ENTITY_PROPERTY(PROP_DENSITY, float, setDensity); READ_ENTITY_PROPERTY(PROP_GRAVITY, glm::vec3, setGravity); @@ -894,7 +895,7 @@ void EntityItem::debugDump() const { qCDebug(entities) << "EntityItem id:" << getEntityItemID(); qCDebug(entities, " edited ago:%f", (double)getEditedAgo()); qCDebug(entities, " position:%f,%f,%f", (double)position.x, (double)position.y, (double)position.z); - qCDebug(entities) << " dimensions:" << getDimensions(); + qCDebug(entities) << " dimensions:" << getScaledDimensions(); } // adjust any internal timestamps to fix clock skew for this server @@ -919,7 +920,7 @@ void EntityItem::adjustEditPacketForClockSkew(QByteArray& buffer, qint64 clockSk } float EntityItem::computeMass() const { - glm::vec3 dimensions = getDimensions(); + glm::vec3 dimensions = getScaledDimensions(); return getDensity() * _volumeMultiplier * dimensions.x * dimensions.y * dimensions.z; } @@ -938,7 +939,7 @@ void EntityItem::setMass(float mass) { // we must protect the density range to help maintain stability of physics simulation // therefore this method might not accept the mass that is supplied. - glm::vec3 dimensions = getDimensions(); + glm::vec3 dimensions = getScaledDimensions(); float volume = _volumeMultiplier * dimensions.x * dimensions.y * dimensions.z; // compute new density @@ -1172,7 +1173,7 @@ bool EntityItem::wantTerseEditLogging() const { glm::mat4 EntityItem::getEntityToWorldMatrix() const { glm::mat4 translation = glm::translate(getWorldPosition()); glm::mat4 rotation = glm::mat4_cast(getWorldOrientation()); - glm::mat4 scale = glm::scale(getDimensions()); + glm::mat4 scale = glm::scale(getScaledDimensions()); glm::mat4 registration = glm::translate(ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint()); return translation * rotation * scale * registration; } @@ -1212,7 +1213,7 @@ EntityItemProperties EntityItem::getProperties(EntityPropertyFlags desiredProper COPY_ENTITY_PROPERTY_TO_PROPERTIES(simulationOwner, getSimulationOwner); COPY_ENTITY_PROPERTY_TO_PROPERTIES(position, getLocalPosition); - COPY_ENTITY_PROPERTY_TO_PROPERTIES(dimensions, getDimensions); // NOTE: radius is obsolete + COPY_ENTITY_PROPERTY_TO_PROPERTIES(dimensions, getUnscaledDimensions); COPY_ENTITY_PROPERTY_TO_PROPERTIES(rotation, getLocalOrientation); COPY_ENTITY_PROPERTY_TO_PROPERTIES(density, getDensity); COPY_ENTITY_PROPERTY_TO_PROPERTIES(velocity, getLocalVelocity); @@ -1319,7 +1320,7 @@ bool EntityItem::setProperties(const EntityItemProperties& properties) { SET_ENTITY_PROPERTY_FROM_PROPERTIES(acceleration, setAcceleration); // these (along with "position" above) affect tree structure - SET_ENTITY_PROPERTY_FROM_PROPERTIES(dimensions, setDimensions); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(dimensions, setUnscaledDimensions); SET_ENTITY_PROPERTY_FROM_PROPERTIES(registrationPoint, setRegistrationPoint); // these (along with all properties above) affect the simulation @@ -1421,7 +1422,7 @@ 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()) * getDimensions()); // Position to center + result.postTranslate((ENTITY_ITEM_HALF_VEC3 - getRegistrationPoint()) * getScaledDimensions()); // Position to center } return result; } @@ -1437,7 +1438,7 @@ 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 = getDimensions() * glm::max(_registrationPoint, glm::vec3(1.0f) - _registrationPoint); + 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); @@ -1462,7 +1463,7 @@ AACube EntityItem::getMinimumAACube(bool& success) const { glm::vec3 position = getWorldPosition(success); if (success) { _recalcMinAACube = false; - glm::vec3 dimensions = getDimensions(); + glm::vec3 dimensions = getScaledDimensions(); glm::vec3 unrotatedMinRelativeToEntity = - (dimensions * _registrationPoint); glm::vec3 unrotatedMaxRelativeToEntity = dimensions * (glm::vec3(1.0f, 1.0f, 1.0f) - _registrationPoint); Extents extents = { unrotatedMinRelativeToEntity, unrotatedMaxRelativeToEntity }; @@ -1492,7 +1493,7 @@ AABox EntityItem::getAABox(bool& success) const { glm::vec3 position = getWorldPosition(success); if (success) { _recalcAABox = false; - glm::vec3 dimensions = getDimensions(); + glm::vec3 dimensions = getScaledDimensions(); glm::vec3 unrotatedMinRelativeToEntity = - (dimensions * _registrationPoint); glm::vec3 unrotatedMaxRelativeToEntity = dimensions * (glm::vec3(1.0f, 1.0f, 1.0f) - _registrationPoint); Extents extents = { unrotatedMinRelativeToEntity, unrotatedMaxRelativeToEntity }; @@ -1532,12 +1533,12 @@ bool EntityItem::shouldPuffQueryAACube() const { // ... cornerToCornerLength = sqrt(3 x maxDimension ^ 2) // ... radius = sqrt(3 x maxDimension ^ 2) / 2.0f; float EntityItem::getRadius() const { - return 0.5f * glm::length(getDimensions()); + return 0.5f * glm::length(getScaledDimensions()); } void EntityItem::adjustShapeInfoByRegistration(ShapeInfo& info) const { if (_registrationPoint != ENTITY_ITEM_DEFAULT_REGISTRATION_POINT) { - glm::mat4 scale = glm::scale(getDimensions()); + 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); @@ -1558,12 +1559,12 @@ bool EntityItem::contains(const glm::vec3& point) const { } void EntityItem::computeShapeInfo(ShapeInfo& info) { - info.setParams(getShapeType(), 0.5f * getDimensions()); + info.setParams(getShapeType(), 0.5f * getScaledDimensions()); adjustShapeInfoByRegistration(info); } float EntityItem::getVolumeEstimate() const { - glm::vec3 dimensions = getDimensions(); + glm::vec3 dimensions = getScaledDimensions(); return dimensions.x * dimensions.y * dimensions.z; } @@ -1617,11 +1618,25 @@ void EntityItem::setParentID(const QUuid& value) { } } -void EntityItem::setDimensions(const glm::vec3& value) { +glm::vec3 EntityItem::getScaledDimensions() const { + glm::vec3 scale = getSNScale(); + return glm::vec3(_unscaledDimensions.x * scale.x, + _unscaledDimensions.y * scale.y, + _unscaledDimensions.z * scale.z); +} + +void EntityItem::setScaledDimensions(const glm::vec3& value) { + glm::vec3 parentScale = getSNScale(); + setUnscaledDimensions(glm::vec3(value.x / parentScale.x, + value.y / parentScale.y, + value.z / parentScale.z)); +} + +void EntityItem::setUnscaledDimensions(const glm::vec3& value) { glm::vec3 newDimensions = glm::max(value, glm::vec3(0.0f)); // can never have negative dimensions - if (getDimensions() != newDimensions) { + if (getUnscaledDimensions() != newDimensions) { withWriteLock([&] { - _dimensions = newDimensions; + _unscaledDimensions = newDimensions; }); locationChanged(); dimensionsChanged(); @@ -2292,6 +2307,16 @@ void EntityItem::dimensionsChanged() { somethingChangedNotification(); } +bool EntityItem::getScalesWithParent() const { + // keep this logic the same as in EntityItemProperties::getScalesWithParent + if (getClientOnly()) { + QUuid ancestorID = findAncestorOfType(NestableType::Avatar); + return !ancestorID.isNull(); + } else { + return false; + } +} + void EntityItem::globalizeProperties(EntityItemProperties& properties, const QString& messageTemplate, const glm::vec3& offset) const { // TODO -- combine this with convertLocationToScriptSemantics bool success; @@ -2299,7 +2324,7 @@ void EntityItem::globalizeProperties(EntityItemProperties& properties, const QSt if (success) { properties.setPosition(globalPosition + offset); properties.setRotation(getWorldOrientation()); - properties.setDimensions(getDimensions()); + properties.setDimensions(getScaledDimensions()); // Should we do velocities and accelerations, too? This could end up being quite involved, which is why the method exists. } else { properties.setPosition(getQueryAACube().calcCenter() + offset); // best we can do diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 882b8e6812..985dbdcaae 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -180,8 +180,11 @@ public: void setDescription(const QString& value); /// Dimensions in meters (0.0 - TREE_SCALE) - inline const glm::vec3 getDimensions() const { return _dimensions; } - virtual void setDimensions(const glm::vec3& value); + glm::vec3 getScaledDimensions() const; + virtual void setScaledDimensions(const glm::vec3& value); + + inline const glm::vec3 getUnscaledDimensions() const { return _unscaledDimensions; } + virtual void setUnscaledDimensions(const glm::vec3& value); float getLocalRenderAlpha() const; void setLocalRenderAlpha(float localRenderAlpha); @@ -454,6 +457,8 @@ public: virtual void locationChanged(bool tellPhysics = true) override; + virtual bool getScalesWithParent() const override; + using ChangeHandlerCallback = std::function; using ChangeHandlerId = QUuid; ChangeHandlerId registerChangeHandler(const ChangeHandlerCallback& handler); @@ -474,7 +479,7 @@ protected: virtual void dimensionsChanged() override; - glm::vec3 _dimensions { ENTITY_ITEM_DEFAULT_DIMENSIONS }; + glm::vec3 _unscaledDimensions { ENTITY_ITEM_DEFAULT_DIMENSIONS }; EntityTypes::EntityType _type { EntityTypes::Unknown }; quint64 _lastSimulated { 0 }; // last time this entity called simulate(), this includes velocity, angular velocity, // and physics changes diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 5ab4bdee01..8f57db772a 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -365,6 +365,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_LOCAL_ROTATION, localRotation); CHECK_PROPERTY_CHANGE(PROP_LOCAL_VELOCITY, localVelocity); CHECK_PROPERTY_CHANGE(PROP_LOCAL_ANGULAR_VELOCITY, localAngularVelocity); + CHECK_PROPERTY_CHANGE(PROP_LOCAL_DIMENSIONS, localDimensions); CHECK_PROPERTY_CHANGE(PROP_FLYING_ALLOWED, flyingAllowed); CHECK_PROPERTY_CHANGE(PROP_GHOSTING_ALLOWED, ghostingAllowed); @@ -627,6 +628,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LOCAL_ROTATION, localRotation); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LOCAL_VELOCITY, localVelocity); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LOCAL_ANGULAR_VELOCITY, localAngularVelocity); + COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LOCAL_DIMENSIONS, localDimensions); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_CLIENT_ONLY, clientOnly); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_OWNING_AVATAR_ID, owningAvatarID); @@ -803,6 +805,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool COPY_PROPERTY_FROM_QSCRIPTVALUE(localRotation, glmQuat, setLocalRotation); COPY_PROPERTY_FROM_QSCRIPTVALUE(localVelocity, glmVec3, setLocalVelocity); COPY_PROPERTY_FROM_QSCRIPTVALUE(localAngularVelocity, glmVec3, setLocalAngularVelocity); + COPY_PROPERTY_FROM_QSCRIPTVALUE(localDimensions, glmVec3, setLocalDimensions); COPY_PROPERTY_FROM_QSCRIPTVALUE(jointRotationsSet, qVectorBool, setJointRotationsSet); COPY_PROPERTY_FROM_QSCRIPTVALUE(jointRotations, qVectorQuat, setJointRotations); @@ -950,6 +953,7 @@ void EntityItemProperties::merge(const EntityItemProperties& other) { COPY_PROPERTY_IF_CHANGED(localRotation); COPY_PROPERTY_IF_CHANGED(localVelocity); COPY_PROPERTY_IF_CHANGED(localAngularVelocity); + COPY_PROPERTY_IF_CHANGED(localDimensions); COPY_PROPERTY_IF_CHANGED(jointRotationsSet); COPY_PROPERTY_IF_CHANGED(jointRotations); @@ -1128,6 +1132,7 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue ADD_PROPERTY_TO_MAP(PROP_LOCAL_ROTATION, LocalRotation, localRotation, glm::quat); ADD_PROPERTY_TO_MAP(PROP_LOCAL_VELOCITY, LocalVelocity, localVelocity, glm::vec3); ADD_PROPERTY_TO_MAP(PROP_LOCAL_ANGULAR_VELOCITY, LocalAngularVelocity, localAngularVelocity, glm::vec3); + ADD_PROPERTY_TO_MAP(PROP_LOCAL_DIMENSIONS, LocalDimensions, localDimensions, glm::vec3); ADD_PROPERTY_TO_MAP(PROP_JOINT_ROTATIONS_SET, JointRotationsSet, jointRotationsSet, QVector); ADD_PROPERTY_TO_MAP(PROP_JOINT_ROTATIONS, JointRotations, jointRotations, QVector); @@ -2460,9 +2465,25 @@ bool EntityItemProperties::transformChanged() const { localPositionChanged() || localRotationChanged(); } +bool EntityItemProperties::getScalesWithParent() const { + // keep this logic the same as in EntityItem::getScalesWithParent + bool scalesWithParent { false }; + if (parentIDChanged()) { + bool success; + SpatiallyNestablePointer parent = SpatiallyNestable::findByID(getParentID(), success); + if (success && parent) { + bool avatarAncestor = (parent->getNestableType() == NestableType::Avatar || + parent->hasAncestorOfType(NestableType::Avatar)); + scalesWithParent = getClientOnly() && avatarAncestor; + } + } + return scalesWithParent; +} + bool EntityItemProperties::parentRelatedPropertyChanged() const { return positionChanged() || rotationChanged() || localPositionChanged() || localRotationChanged() || + localDimensionsChanged() || parentIDChanged() || parentJointIndexChanged(); } diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index ec192d7c9f..a1118e8441 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -88,6 +88,7 @@ public: EntityPropertyFlags getChangedProperties() const; bool transformChanged() const; + bool getScalesWithParent() const; bool parentRelatedPropertyChanged() const; bool queryAACubeRelatedPropertyChanged() const; @@ -226,6 +227,7 @@ public: DEFINE_PROPERTY_REF(PROP_LOCAL_ROTATION, LocalRotation, localRotation, glmQuat, ENTITY_ITEM_DEFAULT_ROTATION); DEFINE_PROPERTY_REF(PROP_LOCAL_VELOCITY, LocalVelocity, localVelocity, glmVec3, ENTITY_ITEM_ZERO_VEC3); DEFINE_PROPERTY_REF(PROP_LOCAL_ANGULAR_VELOCITY, LocalAngularVelocity, localAngularVelocity, glmVec3, ENTITY_ITEM_ZERO_VEC3); + DEFINE_PROPERTY_REF(PROP_LOCAL_DIMENSIONS, LocalDimensions, localDimensions, glmVec3, ENTITY_ITEM_ZERO_VEC3); DEFINE_PROPERTY_REF(PROP_JOINT_ROTATIONS_SET, JointRotationsSet, jointRotationsSet, QVector, QVector()); DEFINE_PROPERTY_REF(PROP_JOINT_ROTATIONS, JointRotations, jointRotations, QVector, QVector()); diff --git a/libraries/entities/src/EntityPropertyFlags.h b/libraries/entities/src/EntityPropertyFlags.h index 35d40b669a..c44f8091e0 100644 --- a/libraries/entities/src/EntityPropertyFlags.h +++ b/libraries/entities/src/EntityPropertyFlags.h @@ -219,6 +219,8 @@ enum EntityPropertyList { PROP_HAZE_KEYLIGHT_RANGE, PROP_HAZE_KEYLIGHT_ALTITUDE, + PROP_LOCAL_DIMENSIONS, // only used to convert values to and from scripts + //////////////////////////////////////////////////////////////////////////////////////////////////// // ATTENTION: add new properties to end of list just ABOVE this line PROP_AFTER_LAST_ITEM, diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 35941c09d3..25eb126704 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -117,7 +117,8 @@ void EntityScriptingInterface::setEntityTree(EntityTreePointer elementTree) { } } -EntityItemProperties convertLocationToScriptSemantics(const EntityItemProperties& entitySideProperties) { +EntityItemProperties convertPropertiesToScriptSemantics(const EntityItemProperties& entitySideProperties, + bool scalesWithParent) { // In EntityTree code, properties.position and properties.rotation are relative to the parent. In javascript, // they are in world-space. The local versions are put into localPosition and localRotation and position and // rotation are converted from local to world space. @@ -126,35 +127,48 @@ EntityItemProperties convertLocationToScriptSemantics(const EntityItemProperties scriptSideProperties.setLocalRotation(entitySideProperties.getRotation()); scriptSideProperties.setLocalVelocity(entitySideProperties.getLocalVelocity()); scriptSideProperties.setLocalAngularVelocity(entitySideProperties.getLocalAngularVelocity()); + scriptSideProperties.setLocalDimensions(entitySideProperties.getDimensions()); bool success; glm::vec3 worldPosition = SpatiallyNestable::localToWorld(entitySideProperties.getPosition(), entitySideProperties.getParentID(), entitySideProperties.getParentJointIndex(), + scalesWithParent, success); glm::quat worldRotation = SpatiallyNestable::localToWorld(entitySideProperties.getRotation(), entitySideProperties.getParentID(), entitySideProperties.getParentJointIndex(), + scalesWithParent, success); glm::vec3 worldVelocity = SpatiallyNestable::localToWorldVelocity(entitySideProperties.getVelocity(), entitySideProperties.getParentID(), entitySideProperties.getParentJointIndex(), + scalesWithParent, success); glm::vec3 worldAngularVelocity = SpatiallyNestable::localToWorldAngularVelocity(entitySideProperties.getAngularVelocity(), entitySideProperties.getParentID(), entitySideProperties.getParentJointIndex(), + scalesWithParent, success); + glm::vec3 worldDimensions = SpatiallyNestable::localToWorldDimensions(entitySideProperties.getDimensions(), + entitySideProperties.getParentID(), + entitySideProperties.getParentJointIndex(), + scalesWithParent, + success); + scriptSideProperties.setPosition(worldPosition); scriptSideProperties.setRotation(worldRotation); scriptSideProperties.setVelocity(worldVelocity); scriptSideProperties.setAngularVelocity(worldAngularVelocity); + scriptSideProperties.setDimensions(worldDimensions); return scriptSideProperties; } -EntityItemProperties convertLocationFromScriptSemantics(const EntityItemProperties& scriptSideProperties) { +EntityItemProperties convertPropertiesFromScriptSemantics(const EntityItemProperties& scriptSideProperties, + bool scalesWithParent) { // convert position and rotation properties from world-space to local, unless localPosition and localRotation // are set. If they are set, they overwrite position and rotation. EntityItemProperties entitySideProperties = scriptSideProperties; @@ -168,7 +182,7 @@ EntityItemProperties convertLocationFromScriptSemantics(const EntityItemProperti glm::vec3 localPosition = SpatiallyNestable::worldToLocal(entitySideProperties.getPosition(), entitySideProperties.getParentID(), entitySideProperties.getParentJointIndex(), - success); + scalesWithParent, success); entitySideProperties.setPosition(localPosition); } @@ -178,7 +192,7 @@ EntityItemProperties convertLocationFromScriptSemantics(const EntityItemProperti glm::quat localRotation = SpatiallyNestable::worldToLocal(entitySideProperties.getRotation(), entitySideProperties.getParentID(), entitySideProperties.getParentJointIndex(), - success); + scalesWithParent, success); entitySideProperties.setRotation(localRotation); } @@ -188,7 +202,7 @@ EntityItemProperties convertLocationFromScriptSemantics(const EntityItemProperti glm::vec3 localVelocity = SpatiallyNestable::worldToLocalVelocity(entitySideProperties.getVelocity(), entitySideProperties.getParentID(), entitySideProperties.getParentJointIndex(), - success); + scalesWithParent, success); entitySideProperties.setVelocity(localVelocity); } @@ -199,10 +213,20 @@ EntityItemProperties convertLocationFromScriptSemantics(const EntityItemProperti SpatiallyNestable::worldToLocalAngularVelocity(entitySideProperties.getAngularVelocity(), entitySideProperties.getParentID(), entitySideProperties.getParentJointIndex(), - success); + scalesWithParent, success); entitySideProperties.setAngularVelocity(localAngularVelocity); } + if (scriptSideProperties.localDimensionsChanged()) { + entitySideProperties.setDimensions(scriptSideProperties.getLocalDimensions()); + } else if (scriptSideProperties.dimensionsChanged()) { + glm::vec3 localDimensions = SpatiallyNestable::worldToLocalDimensions(entitySideProperties.getDimensions(), + entitySideProperties.getParentID(), + entitySideProperties.getParentJointIndex(), + scalesWithParent, success); + entitySideProperties.setDimensions(localDimensions); + } + return entitySideProperties; } @@ -212,9 +236,7 @@ QUuid EntityScriptingInterface::addEntity(const EntityItemProperties& properties _activityTracking.addedEntityCount++; - EntityItemProperties propertiesWithSimID = convertLocationFromScriptSemantics(properties); - propertiesWithSimID.setDimensionsInitialized(properties.dimensionsChanged()); - + EntityItemProperties propertiesWithSimID = properties; if (clientOnly) { auto nodeList = DependencyManager::get(); const QUuid myNodeID = nodeList->getSessionUUID(); @@ -222,6 +244,11 @@ QUuid EntityScriptingInterface::addEntity(const EntityItemProperties& properties propertiesWithSimID.setOwningAvatarID(myNodeID); } + bool scalesWithParent = propertiesWithSimID.getScalesWithParent(); + + propertiesWithSimID = convertPropertiesFromScriptSemantics(propertiesWithSimID, scalesWithParent); + propertiesWithSimID.setDimensionsInitialized(properties.dimensionsChanged()); + auto dimensions = propertiesWithSimID.getDimensions(); float volume = dimensions.x * dimensions.y * dimensions.z; auto density = propertiesWithSimID.getDensity(); @@ -295,15 +322,20 @@ EntityItemProperties EntityScriptingInterface::getEntityProperties(QUuid identit EntityItemProperties EntityScriptingInterface::getEntityProperties(QUuid identity, EntityPropertyFlags desiredProperties) { PROFILE_RANGE(script_entities, __FUNCTION__); + bool scalesWithParent { false }; EntityItemProperties results; if (_entityTree) { _entityTree->withReadLock([&] { EntityItemPointer entity = _entityTree->findEntityByEntityItemID(EntityItemID(identity)); if (entity) { + scalesWithParent = entity->getScalesWithParent(); if (desiredProperties.getHasProperty(PROP_POSITION) || desiredProperties.getHasProperty(PROP_ROTATION) || desiredProperties.getHasProperty(PROP_LOCAL_POSITION) || - desiredProperties.getHasProperty(PROP_LOCAL_ROTATION)) { + desiredProperties.getHasProperty(PROP_LOCAL_ROTATION) || + desiredProperties.getHasProperty(PROP_LOCAL_VELOCITY) || + desiredProperties.getHasProperty(PROP_LOCAL_ANGULAR_VELOCITY) || + desiredProperties.getHasProperty(PROP_LOCAL_DIMENSIONS)) { // if we are explicitly getting position or rotation, we need parent information to make sense of them. desiredProperties.setHasProperty(PROP_PARENT_ID); desiredProperties.setHasProperty(PROP_PARENT_JOINT_INDEX); @@ -316,6 +348,9 @@ EntityItemProperties EntityScriptingInterface::getEntityProperties(QUuid identit desiredProperties = entity->getEntityProperties(params); desiredProperties.setHasProperty(PROP_LOCAL_POSITION); desiredProperties.setHasProperty(PROP_LOCAL_ROTATION); + desiredProperties.setHasProperty(PROP_LOCAL_VELOCITY); + desiredProperties.setHasProperty(PROP_LOCAL_ANGULAR_VELOCITY); + desiredProperties.setHasProperty(PROP_LOCAL_DIMENSIONS); } results = entity->getProperties(desiredProperties); @@ -323,7 +358,7 @@ EntityItemProperties EntityScriptingInterface::getEntityProperties(QUuid identit }); } - return convertLocationToScriptSemantics(results); + return convertPropertiesToScriptSemantics(results, scalesWithParent); } QUuid EntityScriptingInterface::editEntity(QUuid id, const EntityItemProperties& scriptSideProperties) { @@ -390,10 +425,13 @@ QUuid EntityScriptingInterface::editEntity(QUuid id, const EntityItemProperties& if (!scriptSideProperties.localRotationChanged() && !scriptSideProperties.rotationChanged()) { properties.setRotation(entity->getWorldOrientation()); } + if (!scriptSideProperties.localDimensionsChanged() && !scriptSideProperties.dimensionsChanged()) { + properties.setDimensions(entity->getScaledDimensions()); + } } - properties = convertLocationFromScriptSemantics(properties); properties.setClientOnly(entity->getClientOnly()); properties.setOwningAvatarID(entity->getOwningAvatarID()); + properties = convertPropertiesFromScriptSemantics(properties, properties.getScalesWithParent()); float cost = calculateCost(density * volume, oldVelocity, newVelocity); cost *= costMultiplier; @@ -529,7 +567,7 @@ void EntityScriptingInterface::deleteEntity(QUuid id) { return; } - auto dimensions = entity->getDimensions(); + auto dimensions = entity->getScaledDimensions(); float volume = dimensions.x * dimensions.y * dimensions.z; auto density = entity->getDensity(); auto velocity = entity->getWorldVelocity().length(); diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index 7e2958583d..926975f735 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -667,7 +667,7 @@ bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, con glm::mat4 entityToWorldMatrix = translation * rotation; glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix); - glm::vec3 dimensions = entity->getDimensions(); + glm::vec3 dimensions = entity->getScaledDimensions(); glm::vec3 registrationPoint = entity->getRegistrationPoint(); glm::vec3 corner = -(dimensions * registrationPoint); @@ -763,7 +763,7 @@ void EntityTreeElement::getEntities(const glm::vec3& searchPosition, float searc glm::vec3 penetration; if (!success || entityBox.findSpherePenetration(searchPosition, searchRadius, penetration)) { - glm::vec3 dimensions = entity->getDimensions(); + glm::vec3 dimensions = entity->getScaledDimensions(); // FIXME - consider allowing the entity to determine penetration so that // entities could presumably dull actuall hull testing if they wanted to diff --git a/libraries/entities/src/LightEntityItem.cpp b/libraries/entities/src/LightEntityItem.cpp index f4944603f1..45f36a1744 100644 --- a/libraries/entities/src/LightEntityItem.cpp +++ b/libraries/entities/src/LightEntityItem.cpp @@ -41,16 +41,16 @@ LightEntityItem::LightEntityItem(const EntityItemID& entityItemID) : EntityItem( _color[RED_INDEX] = _color[GREEN_INDEX] = _color[BLUE_INDEX] = 0; } -void LightEntityItem::setDimensions(const glm::vec3& value) { +void LightEntityItem::setUnscaledDimensions(const glm::vec3& value) { if (_isSpotlight) { // If we are a spotlight, treat the z value as our radius or length, and // recalculate the x/y dimensions to properly encapsulate the spotlight. const float length = value.z; const float width = length * glm::sin(glm::radians(_cutoff)); - EntityItem::setDimensions(glm::vec3(width, width, length)); + EntityItem::setUnscaledDimensions(glm::vec3(width, width, length)); } else { float maxDimension = glm::compMax(value); - EntityItem::setDimensions(glm::vec3(maxDimension, maxDimension, maxDimension)); + EntityItem::setUnscaledDimensions(glm::vec3(maxDimension, maxDimension, maxDimension)); } } @@ -98,7 +98,7 @@ void LightEntityItem::setIsSpotlight(bool value) { return; } - glm::vec3 dimensions = getDimensions(); + glm::vec3 dimensions = getScaledDimensions(); glm::vec3 newDimensions; if (value) { const float length = dimensions.z; @@ -112,7 +112,7 @@ void LightEntityItem::setIsSpotlight(bool value) { _isSpotlight = value; _lightPropertiesChanged = true; }); - setDimensions(newDimensions); + setScaledDimensions(newDimensions); } void LightEntityItem::setCutoff(float value) { @@ -128,9 +128,9 @@ void LightEntityItem::setCutoff(float value) { if (getIsSpotlight()) { // If we are a spotlight, adjusting the cutoff will affect the area we encapsulate, // so update the dimensions to reflect this. - const float length = getDimensions().z; + const float length = getScaledDimensions().z; const float width = length * glm::sin(glm::radians(_cutoff)); - setDimensions(glm::vec3(width, width, length)); + setScaledDimensions(glm::vec3(width, width, length)); } withWriteLock([&] { diff --git a/libraries/entities/src/LightEntityItem.h b/libraries/entities/src/LightEntityItem.h index edc7376079..870b283c26 100644 --- a/libraries/entities/src/LightEntityItem.h +++ b/libraries/entities/src/LightEntityItem.h @@ -29,7 +29,7 @@ public: ALLOW_INSTANTIATION // This class can be instantiated /// set dimensions in domain scale units (0.0 - 1.0) this will also reset radius appropriately - virtual void setDimensions(const glm::vec3& value) override; + virtual void setUnscaledDimensions(const glm::vec3& value) override; virtual bool setProperties(const EntityItemProperties& properties) override; virtual bool setSubClassProperties(const EntityItemProperties& properties) override; diff --git a/libraries/entities/src/LineEntityItem.cpp b/libraries/entities/src/LineEntityItem.cpp index 02d16f2537..00196d7b23 100644 --- a/libraries/entities/src/LineEntityItem.cpp +++ b/libraries/entities/src/LineEntityItem.cpp @@ -80,7 +80,7 @@ bool LineEntityItem::appendPoint(const glm::vec3& point) { qCDebug(entities) << "MAX POINTS REACHED!"; return false; } - glm::vec3 halfBox = getDimensions() * 0.5f; + glm::vec3 halfBox = getScaledDimensions() * 0.5f; if ( (point.x < - halfBox.x || point.x > halfBox.x) || (point.y < -halfBox.y || point.y > halfBox.y) || (point.z < - halfBox.z || point.z > halfBox.z) ) { qCDebug(entities) << "Point is outside entity's bounding box"; return false; @@ -96,7 +96,7 @@ bool LineEntityItem::setLinePoints(const QVector& points) { if (points.size() > MAX_POINTS_PER_LINE) { return false; } - glm::vec3 halfBox = getDimensions() * 0.5f; + glm::vec3 halfBox = getScaledDimensions() * 0.5f; for (int i = 0; i < points.size(); i++) { glm::vec3 point = points.at(i); if ( (point.x < - halfBox.x || point.x > halfBox.x) || (point.y < -halfBox.y || point.y > halfBox.y) || (point.z < - halfBox.z || point.z > halfBox.z) ) { @@ -157,7 +157,7 @@ void LineEntityItem::debugDump() const { qCDebug(entities) << " LINE EntityItem id:" << getEntityItemID() << "---------------------------------------------"; qCDebug(entities) << " color:" << _color[0] << "," << _color[1] << "," << _color[2]; qCDebug(entities) << " position:" << debugTreeVector(getWorldPosition()); - qCDebug(entities) << " dimensions:" << debugTreeVector(getDimensions()); + qCDebug(entities) << " dimensions:" << debugTreeVector(getScaledDimensions()); qCDebug(entities) << " getLastEdited:" << debugTime(getLastEdited(), now); } diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index 313721ff54..5ec86e2f76 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -190,7 +190,7 @@ void ModelEntityItem::debugDump() const { qCDebug(entities) << "ModelEntityItem id:" << getEntityItemID(); qCDebug(entities) << " edited ago:" << getEditedAgo(); qCDebug(entities) << " position:" << getWorldPosition(); - qCDebug(entities) << " dimensions:" << getDimensions(); + qCDebug(entities) << " dimensions:" << getScaledDimensions(); qCDebug(entities) << " model URL:" << getModelURL(); qCDebug(entities) << " compound shape URL:" << getCompoundShapeURL(); } diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index bc0c093518..c20572a491 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -353,7 +353,7 @@ void ParticleEffectEntityItem::computeAndUpdateDimensions() { float maxDistanceValue = glm::compMax(maxDistance); //times 2 because dimensions are diameters not radii glm::vec3 dims(2.0f * maxDistanceValue); - EntityItem::setDimensions(dims); + EntityItem::setScaledDimensions(dims); } @@ -593,7 +593,7 @@ void ParticleEffectEntityItem::debugDump() const { _particleProperties.color.gradient.target.green << "," << _particleProperties.color.gradient.target.blue; qCDebug(entities) << " position:" << debugTreeVector(getWorldPosition()); - qCDebug(entities) << " dimensions:" << debugTreeVector(getDimensions()); + qCDebug(entities) << " dimensions:" << debugTreeVector(getScaledDimensions()); qCDebug(entities) << " getLastEdited:" << debugTime(getLastEdited(), now); } diff --git a/libraries/entities/src/PolyLineEntityItem.cpp b/libraries/entities/src/PolyLineEntityItem.cpp index e69fb2e100..498d13058e 100644 --- a/libraries/entities/src/PolyLineEntityItem.cpp +++ b/libraries/entities/src/PolyLineEntityItem.cpp @@ -191,7 +191,7 @@ void PolyLineEntityItem::calculateScaleAndRegistrationPoint() { } // if Polyline has only one or fewer points, use default dimension settings - setDimensions(newScale); + setScaledDimensions(newScale); EntityItem::setRegistrationPoint(newRegistrationPoint); } @@ -257,7 +257,7 @@ void PolyLineEntityItem::debugDump() const { qCDebug(entities) << " QUAD EntityItem id:" << getEntityItemID() << "---------------------------------------------"; qCDebug(entities) << " color:" << _color[0] << "," << _color[1] << "," << _color[2]; qCDebug(entities) << " position:" << debugTreeVector(getWorldPosition()); - qCDebug(entities) << " dimensions:" << debugTreeVector(getDimensions()); + qCDebug(entities) << " dimensions:" << debugTreeVector(getScaledDimensions()); qCDebug(entities) << " getLastEdited:" << debugTime(getLastEdited(), now); } diff --git a/libraries/entities/src/PolyVoxEntityItem.cpp b/libraries/entities/src/PolyVoxEntityItem.cpp index b08d94ca7e..84ce83d3a1 100644 --- a/libraries/entities/src/PolyVoxEntityItem.cpp +++ b/libraries/entities/src/PolyVoxEntityItem.cpp @@ -229,7 +229,7 @@ void PolyVoxEntityItem::debugDump() const { quint64 now = usecTimestampNow(); qCDebug(entities) << " POLYVOX EntityItem id:" << getEntityItemID() << "---------------------------------------------"; qCDebug(entities) << " position:" << debugTreeVector(getWorldPosition()); - qCDebug(entities) << " dimensions:" << debugTreeVector(getDimensions()); + qCDebug(entities) << " dimensions:" << debugTreeVector(getScaledDimensions()); qCDebug(entities) << " getLastEdited:" << debugTime(getLastEdited(), now); } @@ -377,7 +377,7 @@ EntityItemID PolyVoxEntityItem::getZPNeighborID() const { glm::vec3 PolyVoxEntityItem::getSurfacePositionAdjustment() const { glm::vec3 result; withReadLock([&] { - glm::vec3 scale = getDimensions() / _voxelVolumeSize; // meters / voxel-units + glm::vec3 scale = getScaledDimensions() / _voxelVolumeSize; // meters / voxel-units if (isEdged()) { result = scale / -2.0f; } @@ -392,7 +392,7 @@ glm::mat4 PolyVoxEntityItem::voxelToLocalMatrix() const { voxelVolumeSize = _voxelVolumeSize; }); - glm::vec3 dimensions = getDimensions(); + 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 diff --git a/libraries/entities/src/ShapeEntityItem.cpp b/libraries/entities/src/ShapeEntityItem.cpp index 15704ebc17..f564c89d21 100644 --- a/libraries/entities/src/ShapeEntityItem.cpp +++ b/libraries/entities/src/ShapeEntityItem.cpp @@ -106,11 +106,11 @@ void ShapeEntityItem::setShape(const entity::Shape& shape) { break; case entity::Shape::Circle: // Circle is implicitly flat so we enforce flat dimensions - setDimensions(getDimensions()); + setUnscaledDimensions(getUnscaledDimensions()); break; case entity::Shape::Quad: // Quad is implicitly flat so we enforce flat dimensions - setDimensions(getDimensions()); + setUnscaledDimensions(getUnscaledDimensions()); break; default: _type = EntityTypes::Shape; @@ -204,15 +204,15 @@ void ShapeEntityItem::setColor(const QColor& value) { setAlpha(value.alpha()); } -void ShapeEntityItem::setDimensions(const glm::vec3& value) { +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) { // enforce flatness in Y glm::vec3 newDimensions = value; newDimensions.y = MAX_FLAT_DIMENSION; - EntityItem::setDimensions(newDimensions); + EntityItem::setUnscaledDimensions(newDimensions); } else { - EntityItem::setDimensions(value); + EntityItem::setUnscaledDimensions(value); } } @@ -256,7 +256,7 @@ void ShapeEntityItem::debugDump() const { qCDebug(entities) << " collisionShapeType:" << ShapeInfo::getNameForShapeType(getShapeType()); qCDebug(entities) << " color:" << _color[0] << "," << _color[1] << "," << _color[2]; qCDebug(entities) << " position:" << debugTreeVector(getWorldPosition()); - qCDebug(entities) << " dimensions:" << debugTreeVector(getDimensions()); + qCDebug(entities) << " dimensions:" << debugTreeVector(getScaledDimensions()); qCDebug(entities) << " getLastEdited:" << debugTime(getLastEdited(), now); qCDebug(entities) << "SHAPE EntityItem Ptr:" << this; } @@ -266,7 +266,7 @@ void ShapeEntityItem::computeShapeInfo(ShapeInfo& info) { // This will be called whenever DIRTY_SHAPE flag (set by dimension change, etc) // is set. - const glm::vec3 entityDimensions = getDimensions(); + const glm::vec3 entityDimensions = getScaledDimensions(); switch (_shape){ case entity::Shape::Quad: diff --git a/libraries/entities/src/ShapeEntityItem.h b/libraries/entities/src/ShapeEntityItem.h index 20e36c88e6..c5df17db54 100644 --- a/libraries/entities/src/ShapeEntityItem.h +++ b/libraries/entities/src/ShapeEntityItem.h @@ -80,7 +80,7 @@ public: const rgbColor& getColor() const { return _color; } void setColor(const rgbColor& value); - void setDimensions(const glm::vec3& value) override; + void setUnscaledDimensions(const glm::vec3& value) override; xColor getXColor() const; void setColor(const xColor& value); diff --git a/libraries/entities/src/TextEntityItem.cpp b/libraries/entities/src/TextEntityItem.cpp index 67e83ab3fd..639da69a17 100644 --- a/libraries/entities/src/TextEntityItem.cpp +++ b/libraries/entities/src/TextEntityItem.cpp @@ -41,9 +41,9 @@ TextEntityItem::TextEntityItem(const EntityItemID& entityItemID) : EntityItem(en const float TEXT_ENTITY_ITEM_FIXED_DEPTH = 0.01f; -void TextEntityItem::setDimensions(const glm::vec3& value) { +void TextEntityItem::setUnscaledDimensions(const glm::vec3& value) { // NOTE: Text Entities always have a "depth" of 1cm. - EntityItem::setDimensions(glm::vec3(value.x, value.y, TEXT_ENTITY_ITEM_FIXED_DEPTH)); + EntityItem::setUnscaledDimensions(glm::vec3(value.x, value.y, TEXT_ENTITY_ITEM_FIXED_DEPTH)); } EntityItemProperties TextEntityItem::getProperties(EntityPropertyFlags desiredProperties) const { @@ -132,7 +132,7 @@ bool TextEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, void** intersectedObject, bool precisionPicking) const { - glm::vec3 dimensions = getDimensions(); + glm::vec3 dimensions = getScaledDimensions(); glm::vec2 xyDimensions(dimensions.x, dimensions.y); glm::quat rotation = getWorldOrientation(); glm::vec3 position = getWorldPosition() + rotation * diff --git a/libraries/entities/src/TextEntityItem.h b/libraries/entities/src/TextEntityItem.h index 8db929fa47..520a935e55 100644 --- a/libraries/entities/src/TextEntityItem.h +++ b/libraries/entities/src/TextEntityItem.h @@ -23,7 +23,7 @@ public: ALLOW_INSTANTIATION // This class can be instantiated /// set dimensions in domain scale units (0.0 - 1.0) this will also reset radius appropriately - virtual void setDimensions(const glm::vec3& value) override; + virtual void setUnscaledDimensions(const glm::vec3& value) override; virtual ShapeType getShapeType() const override { return SHAPE_TYPE_BOX; } // methods for getting/setting all properties of an entity diff --git a/libraries/entities/src/WebEntityItem.cpp b/libraries/entities/src/WebEntityItem.cpp index 5ee630d8ed..54db6e7c3b 100644 --- a/libraries/entities/src/WebEntityItem.cpp +++ b/libraries/entities/src/WebEntityItem.cpp @@ -36,9 +36,9 @@ WebEntityItem::WebEntityItem(const EntityItemID& entityItemID) : EntityItem(enti const float WEB_ENTITY_ITEM_FIXED_DEPTH = 0.01f; -void WebEntityItem::setDimensions(const glm::vec3& value) { +void WebEntityItem::setUnscaledDimensions(const glm::vec3& value) { // NOTE: Web Entities always have a "depth" of 1cm. - EntityItem::setDimensions(glm::vec3(value.x, value.y, WEB_ENTITY_ITEM_FIXED_DEPTH)); + EntityItem::setUnscaledDimensions(glm::vec3(value.x, value.y, WEB_ENTITY_ITEM_FIXED_DEPTH)); } EntityItemProperties WebEntityItem::getProperties(EntityPropertyFlags desiredProperties) const { @@ -109,7 +109,7 @@ bool WebEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const g bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, void** intersectedObject, bool precisionPicking) const { - glm::vec3 dimensions = getDimensions(); + 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())); diff --git a/libraries/entities/src/WebEntityItem.h b/libraries/entities/src/WebEntityItem.h index 9e84a3a776..f5066beebc 100644 --- a/libraries/entities/src/WebEntityItem.h +++ b/libraries/entities/src/WebEntityItem.h @@ -22,7 +22,7 @@ public: ALLOW_INSTANTIATION // This class can be instantiated /// set dimensions in domain scale units (0.0 - 1.0) this will also reset radius appropriately - virtual void setDimensions(const glm::vec3& value) override; + virtual void setUnscaledDimensions(const glm::vec3& value) override; virtual ShapeType getShapeType() const override { return SHAPE_TYPE_BOX; } // methods for getting/setting all properties of an entity diff --git a/libraries/entities/src/ZoneEntityItem.cpp b/libraries/entities/src/ZoneEntityItem.cpp index 0ed523202b..fbfbc71a85 100644 --- a/libraries/entities/src/ZoneEntityItem.cpp +++ b/libraries/entities/src/ZoneEntityItem.cpp @@ -242,7 +242,7 @@ void ZoneEntityItem::debugDump() const { quint64 now = usecTimestampNow(); qCDebug(entities) << " ZoneEntityItem id:" << getEntityItemID() << "---------------------------------------------"; qCDebug(entities) << " position:" << debugTreeVector(getWorldPosition()); - qCDebug(entities) << " dimensions:" << debugTreeVector(getDimensions()); + qCDebug(entities) << " dimensions:" << debugTreeVector(getScaledDimensions()); qCDebug(entities) << " getLastEdited:" << debugTime(getLastEdited(), now); qCDebug(entities) << " _backgroundMode:" << EntityItemProperties::getBackgroundModeString(_backgroundMode); qCDebug(entities) << " _hazeMode:" << EntityItemProperties::getHazeModeString(_hazeMode); diff --git a/libraries/shared/src/SpatiallyNestable.cpp b/libraries/shared/src/SpatiallyNestable.cpp index 2114cbf944..20a5a76b73 100644 --- a/libraries/shared/src/SpatiallyNestable.cpp +++ b/libraries/shared/src/SpatiallyNestable.cpp @@ -19,7 +19,7 @@ #include "SharedLogging.h" const float defaultAACubeSize = 1.0f; -const int maxParentingChain = 30; +const int MAX_PARENTING_CHAIN_SIZE = 30; SpatiallyNestable::SpatiallyNestable(NestableType nestableType, QUuid id) : _nestableType(nestableType), @@ -28,6 +28,7 @@ SpatiallyNestable::SpatiallyNestable(NestableType nestableType, QUuid id) : // set flags in _transform _transform.setTranslation(glm::vec3(0.0f)); _transform.setRotation(glm::quat()); + _transform.setScale(1.0f); _scaleChanged = usecTimestampNow(); _translationChanged = usecTimestampNow(); _rotationChanged = usecTimestampNow(); @@ -85,6 +86,9 @@ Transform SpatiallyNestable::getParentTransform(bool& success, int depth) const } if (parent) { result = parent->getTransform(_parentJointIndex, success, depth + 1); + if (getScalesWithParent()) { + result.setScale(parent->scaleForChildren()); + } } return result; } @@ -165,7 +169,7 @@ void SpatiallyNestable::setParentJointIndex(quint16 parentJointIndex) { glm::vec3 SpatiallyNestable::worldToLocal(const glm::vec3& position, const QUuid& parentID, int parentJointIndex, - bool& success) { + bool scalesWithParent, bool& success) { QSharedPointer parentFinder = DependencyManager::get(); if (!parentFinder) { success = false; @@ -189,6 +193,9 @@ glm::vec3 SpatiallyNestable::worldToLocal(const glm::vec3& position, if (!success) { return glm::vec3(0.0f); } + if (scalesWithParent) { + parentTransform.setScale(parent->scaleForChildren()); + } } success = true; @@ -199,7 +206,7 @@ glm::vec3 SpatiallyNestable::worldToLocal(const glm::vec3& position, glm::quat SpatiallyNestable::worldToLocal(const glm::quat& orientation, const QUuid& parentID, int parentJointIndex, - bool& success) { + bool scalesWithParent, bool& success) { QSharedPointer parentFinder = DependencyManager::get(); if (!parentFinder) { success = false; @@ -223,6 +230,9 @@ glm::quat SpatiallyNestable::worldToLocal(const glm::quat& orientation, if (!success) { return glm::quat(); } + if (scalesWithParent) { + parentTransform.setScale(parent->scaleForChildren()); + } } success = true; @@ -231,7 +241,7 @@ glm::quat SpatiallyNestable::worldToLocal(const glm::quat& orientation, } glm::vec3 SpatiallyNestable::worldToLocalVelocity(const glm::vec3& velocity, const QUuid& parentID, - int parentJointIndex, bool& success) { + int parentJointIndex, bool scalesWithParent, bool& success) { SpatiallyNestablePointer parent = SpatiallyNestable::findByID(parentID, success); if (!success || !parent) { return velocity; @@ -240,6 +250,9 @@ glm::vec3 SpatiallyNestable::worldToLocalVelocity(const glm::vec3& velocity, con if (!success) { return velocity; } + if (scalesWithParent) { + parentTransform.setScale(parent->scaleForChildren()); + } glm::vec3 parentVelocity = parent->getWorldVelocity(success); if (!success) { return velocity; @@ -249,7 +262,7 @@ glm::vec3 SpatiallyNestable::worldToLocalVelocity(const glm::vec3& velocity, con } glm::vec3 SpatiallyNestable::worldToLocalAngularVelocity(const glm::vec3& angularVelocity, const QUuid& parentID, - int parentJointIndex, bool& success) { + int parentJointIndex, bool scalesWithParent, bool& success) { SpatiallyNestablePointer parent = SpatiallyNestable::findByID(parentID, success); if (!success || !parent) { return angularVelocity; @@ -258,12 +271,50 @@ glm::vec3 SpatiallyNestable::worldToLocalAngularVelocity(const glm::vec3& angula if (!success) { return angularVelocity; } + if (scalesWithParent) { + parentTransform.setScale(parent->scaleForChildren()); + } return glm::inverse(parentTransform.getRotation()) * angularVelocity; } + +glm::vec3 SpatiallyNestable::worldToLocalDimensions(const glm::vec3& dimensions, + const QUuid& parentID, int parentJointIndex, + bool scalesWithParent, bool& success) { + if (!scalesWithParent) { + success = true; + return dimensions; + } + + QSharedPointer parentFinder = DependencyManager::get(); + if (!parentFinder) { + success = false; + return dimensions; + } + + Transform parentTransform; + auto parentWP = parentFinder->find(parentID, success); + if (!success) { + return dimensions; + } + + auto parent = parentWP.lock(); + if (!parentID.isNull() && !parent) { + success = false; + return dimensions; + } + + success = true; + if (parent) { + return dimensions / parent->scaleForChildren(); + } + return dimensions; +} + glm::vec3 SpatiallyNestable::localToWorld(const glm::vec3& position, const QUuid& parentID, int parentJointIndex, + bool scalesWithParent, bool& success) { Transform result; QSharedPointer parentFinder = DependencyManager::get(); @@ -289,6 +340,9 @@ glm::vec3 SpatiallyNestable::localToWorld(const glm::vec3& position, if (!success) { return glm::vec3(0.0f); } + if (scalesWithParent) { + parentTransform.setScale(parent->scaleForChildren()); + } } success = true; @@ -300,6 +354,7 @@ glm::vec3 SpatiallyNestable::localToWorld(const glm::vec3& position, glm::quat SpatiallyNestable::localToWorld(const glm::quat& orientation, const QUuid& parentID, int parentJointIndex, + bool scalesWithParent, bool& success) { Transform result; QSharedPointer parentFinder = DependencyManager::get(); @@ -325,7 +380,9 @@ glm::quat SpatiallyNestable::localToWorld(const glm::quat& orientation, if (!success) { return glm::quat(); } - parentTransform.setScale(1.0f); + if (scalesWithParent) { + parentTransform.setScale(parent->scaleForChildren()); + } } success = true; @@ -336,7 +393,7 @@ glm::quat SpatiallyNestable::localToWorld(const glm::quat& orientation, } glm::vec3 SpatiallyNestable::localToWorldVelocity(const glm::vec3& velocity, const QUuid& parentID, - int parentJointIndex, bool& success) { + int parentJointIndex, bool scalesWithParent, bool& success) { SpatiallyNestablePointer parent = SpatiallyNestable::findByID(parentID, success); if (!success || !parent) { return velocity; @@ -345,6 +402,9 @@ glm::vec3 SpatiallyNestable::localToWorldVelocity(const glm::vec3& velocity, con if (!success) { return velocity; } + if (scalesWithParent) { + parentTransform.setScale(parent->scaleForChildren()); + } glm::vec3 parentVelocity = parent->getWorldVelocity(success); if (!success) { return velocity; @@ -354,7 +414,7 @@ glm::vec3 SpatiallyNestable::localToWorldVelocity(const glm::vec3& velocity, con } glm::vec3 SpatiallyNestable::localToWorldAngularVelocity(const glm::vec3& angularVelocity, const QUuid& parentID, - int parentJointIndex, bool& success) { + int parentJointIndex, bool scalesWithParent, bool& success) { SpatiallyNestablePointer parent = SpatiallyNestable::findByID(parentID, success); if (!success || !parent) { return angularVelocity; @@ -363,10 +423,47 @@ glm::vec3 SpatiallyNestable::localToWorldAngularVelocity(const glm::vec3& angula if (!success) { return angularVelocity; } - + if (scalesWithParent) { + parentTransform.setScale(parent->scaleForChildren()); + } return parentTransform.getRotation() * angularVelocity; } + +glm::vec3 SpatiallyNestable::localToWorldDimensions(const glm::vec3& dimensions, + const QUuid& parentID, int parentJointIndex, bool scalesWithParent, + bool& success) { + if (!scalesWithParent) { + success = true; + return dimensions; + } + + Transform result; + QSharedPointer parentFinder = DependencyManager::get(); + if (!parentFinder) { + success = false; + return dimensions; + } + + Transform parentTransform; + auto parentWP = parentFinder->find(parentID, success); + if (!success) { + return dimensions; + } + + auto parent = parentWP.lock(); + if (!parentID.isNull() && !parent) { + success = false; + return dimensions; + } + + success = true; + if (parent) { + return dimensions * parent->scaleForChildren(); + } + return dimensions; +} + glm::vec3 SpatiallyNestable::getWorldPosition(bool& success) const { return getTransform(success).getTranslation(); } @@ -615,10 +712,10 @@ const Transform SpatiallyNestable::getTransform(int jointIndex, bool& success, i // cause this object's parent to query its parent, etc) and multiplies this object's local transform onto it. Transform jointInWorldFrame; - if (depth > maxParentingChain) { + if (depth > MAX_PARENTING_CHAIN_SIZE) { success = false; // someone created a loop. break it... - qCDebug(shared) << "Parenting loop detected."; + qCDebug(shared) << "Parenting loop detected: " << getID(); SpatiallyNestablePointer _this = getThisPointer(); _this->setParentID(QUuid()); bool setPositionSuccess; diff --git a/libraries/shared/src/SpatiallyNestable.h b/libraries/shared/src/SpatiallyNestable.h index 9cd38f9ce9..2a315e9230 100644 --- a/libraries/shared/src/SpatiallyNestable.h +++ b/libraries/shared/src/SpatiallyNestable.h @@ -50,19 +50,28 @@ public: virtual quint16 getParentJointIndex() const { return _parentJointIndex; } virtual void setParentJointIndex(quint16 parentJointIndex); - static glm::vec3 worldToLocal(const glm::vec3& position, const QUuid& parentID, int parentJointIndex, bool& success); - static glm::quat worldToLocal(const glm::quat& orientation, const QUuid& parentID, int parentJointIndex, bool& success); + static glm::vec3 worldToLocal(const glm::vec3& position, const QUuid& parentID, int parentJointIndex, + bool scalesWithParent, bool& success); + static glm::quat worldToLocal(const glm::quat& orientation, const QUuid& parentID, int parentJointIndex, + bool scalesWithParent, bool& success); static glm::vec3 worldToLocalVelocity(const glm::vec3& velocity, const QUuid& parentID, - int parentJointIndex, bool& success); + int parentJointIndex, bool scalesWithParent, bool& success); static glm::vec3 worldToLocalAngularVelocity(const glm::vec3& angularVelocity, const QUuid& parentID, - int parentJointIndex, bool& success); + int parentJointIndex, bool scalesWithParent, bool& success); + static glm::vec3 worldToLocalDimensions(const glm::vec3& dimensions, const QUuid& parentID, + int parentJointIndex, bool scalesWithParent, bool& success); - static glm::vec3 localToWorld(const glm::vec3& position, const QUuid& parentID, int parentJointIndex, bool& success); - static glm::quat localToWorld(const glm::quat& orientation, const QUuid& parentID, int parentJointIndex, bool& success); + static glm::vec3 localToWorld(const glm::vec3& position, const QUuid& parentID, int parentJointIndex, + bool scalesWithParent, bool& success); + static glm::quat localToWorld(const glm::quat& orientation, const QUuid& parentID, int parentJointIndex, + bool scalesWithParent, bool& success); static glm::vec3 localToWorldVelocity(const glm::vec3& velocity, - const QUuid& parentID, int parentJointIndex, bool& success); + const QUuid& parentID, int parentJointIndex, bool scalesWithParent, bool& success); static glm::vec3 localToWorldAngularVelocity(const glm::vec3& angularVelocity, - const QUuid& parentID, int parentJointIndex, bool& success); + const QUuid& parentID, int parentJointIndex, + bool scalesWithParent, bool& success); + static glm::vec3 localToWorldDimensions(const glm::vec3& dimensions, const QUuid& parentID, + int parentJointIndex, bool scalesWithParent, bool& success); static QString nestableTypeToString(NestableType nestableType); @@ -140,6 +149,9 @@ public: virtual glm::vec3 getLocalSNScale() const; virtual void setLocalSNScale(const glm::vec3& scale); + virtual bool getScalesWithParent() const { return false; } + virtual glm::vec3 scaleForChildren() const { return glm::vec3(1.0f); } + QList getChildren() const; bool hasChildren() const;