diff --git a/assignment-client/src/entities/AssignmentParentFinder.cpp b/assignment-client/src/entities/AssignmentParentFinder.cpp index 5fe4742b90..fbcaba84ae 100644 --- a/assignment-client/src/entities/AssignmentParentFinder.cpp +++ b/assignment-client/src/entities/AssignmentParentFinder.cpp @@ -11,9 +11,14 @@ #include "AssignmentParentFinder.h" -SpatiallyNestableWeakPointer AssignmentParentFinder::find(QUuid parentID) const { +SpatiallyNestableWeakPointer AssignmentParentFinder::find(QUuid parentID, bool& success) const { SpatiallyNestableWeakPointer parent; // search entities parent = _tree->findEntityByEntityItemID(parentID); + if (parent.lock()) { + success = true; + } else { + success = false; + } return parent; } diff --git a/assignment-client/src/entities/AssignmentParentFinder.h b/assignment-client/src/entities/AssignmentParentFinder.h index 99fa58ffed..9a776bc7dd 100644 --- a/assignment-client/src/entities/AssignmentParentFinder.h +++ b/assignment-client/src/entities/AssignmentParentFinder.h @@ -25,7 +25,7 @@ class AssignmentParentFinder : public SpatialParentFinder { public: AssignmentParentFinder(EntityTreePointer tree) : _tree(tree) { } virtual ~AssignmentParentFinder() { } - virtual SpatiallyNestableWeakPointer find(QUuid parentID) const; + virtual SpatiallyNestableWeakPointer find(QUuid parentID, bool& success) const; protected: EntityTreePointer _tree; diff --git a/interface/src/InterfaceParentFinder.h b/interface/src/InterfaceParentFinder.h index c8e8d4ed9f..db579c2144 100644 --- a/interface/src/InterfaceParentFinder.h +++ b/interface/src/InterfaceParentFinder.h @@ -21,7 +21,7 @@ class InterfaceParentFinder : public SpatialParentFinder { public: InterfaceParentFinder() { } virtual ~InterfaceParentFinder() { } - virtual SpatiallyNestableWeakPointer find(QUuid parentID) const; + virtual SpatiallyNestableWeakPointer find(QUuid parentID, bool& success) const; }; #endif // hifi_InterfaceParentFinder_h diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index 09685c318e..6c5338414f 100644 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -158,7 +158,9 @@ public: void setMotionState(AvatarMotionState* motionState) { _motionState = motionState; } AvatarMotionState* getMotionState() { return _motionState; } + using SpatiallyNestable::setPosition; virtual void setPosition(const glm::vec3& position) override; + using SpatiallyNestable::setOrientation; virtual void setOrientation(const glm::quat& orientation) override; public slots: diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index d241df7e0e..76130f7136 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -93,7 +93,11 @@ void AvatarData::nextAttitude(glm::vec3 position, glm::quat orientation) { Transform trans; trans.setTranslation(position); trans.setRotation(orientation); - SpatiallyNestable::setTransform(trans); + bool success; + SpatiallyNestable::setTransform(trans, success); + if (!success) { + qDebug() << "Warning -- AvatarData::nextAttitude failed"; + } avatarLock.unlock(); updateAttitude(); } @@ -211,8 +215,9 @@ QByteArray AvatarData::toByteArray(bool cullSmallChanges, bool sendAll) { setAtBit(bitItems, IS_EYE_TRACKER_CONNECTED); } // referential state - SpatiallyNestablePointer parent = getParentPointer(); - if (parent) { + bool success; + SpatiallyNestablePointer parent = getParentPointer(success); + if (parent && success) { setAtBit(bitItems, HAS_REFERENTIAL); } *destinationBuffer++ = bitItems; @@ -1443,7 +1448,11 @@ QJsonObject AvatarData::toJson() const { } auto recordingBasis = getRecordingBasis(); - Transform avatarTransform = getTransform(); + bool success; + Transform avatarTransform = getTransform(success); + if (!success) { + qDebug() << "Warning -- AvatarData::toJson couldn't get avatar transform"; + } avatarTransform.setScale(getTargetScale()); if (recordingBasis) { root[JSON_AVATAR_BASIS] = Transform::toJson(*recordingBasis); diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 1fa33ff606..c9a2286cb2 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -201,7 +201,9 @@ public: float getBodyRoll() const; void setBodyRoll(float bodyRoll); + using SpatiallyNestable::setPosition; virtual void setPosition(const glm::vec3& position) override; + using SpatiallyNestable::setOrientation; virtual void setOrientation(const glm::quat& orientation) override; void nextAttitude(glm::vec3 position, glm::quat orientation); // Can be safely called at any time. diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index e3618d0e2a..3dc702f5dd 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -761,7 +761,12 @@ void EntityTreeRenderer::playEntityCollisionSound(const QUuid& myNodeID, EntityT // Shift the pitch down by ln(1 + (size / COLLISION_SIZE_FOR_STANDARD_PITCH)) / ln(2) const float COLLISION_SIZE_FOR_STANDARD_PITCH = 0.2f; - const float stretchFactor = log(1.0f + (entity->getMinimumAACube().getLargestDimension() / COLLISION_SIZE_FOR_STANDARD_PITCH)) / log(2); + bool success; + auto minAACube = entity->getMinimumAACube(success); + if (!success) { + return; + } + const float stretchFactor = log(1.0f + (minAACube.getLargestDimension() / COLLISION_SIZE_FOR_STANDARD_PITCH)) / log(2); AudioInjector::playSound(collisionSoundURL, volume, stretchFactor, position); } diff --git a/libraries/entities-renderer/src/RenderableBoxEntityItem.cpp b/libraries/entities-renderer/src/RenderableBoxEntityItem.cpp index 54fe491c46..7318177deb 100644 --- a/libraries/entities-renderer/src/RenderableBoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableBoxEntityItem.cpp @@ -56,14 +56,20 @@ void RenderableBoxEntityItem::render(RenderArgs* args) { gpu::Batch& batch = *args->_batch; glm::vec4 cubeColor(toGlm(getXColor()), getLocalRenderAlpha()); + bool success; + auto transToCenter = getTransformToCenter(success); + if (!success) { + return; + } + if (_procedural->ready()) { - batch.setModelTransform(getTransformToCenter()); // we want to include the scale as well + batch.setModelTransform(transToCenter); // we want to include the scale as well _procedural->prepare(batch, getPosition(), getDimensions()); auto color = _procedural->getColor(cubeColor); batch._glColor4f(color.r, color.g, color.b, color.a); DependencyManager::get()->renderCube(batch); } else { - DependencyManager::get()->renderSolidCubeInstance(batch, getTransformToCenter(), cubeColor); + DependencyManager::get()->renderSolidCubeInstance(batch, transToCenter, cubeColor); } static const auto triCount = DependencyManager::get()->getCubeTriangleCount(); args->_details._trianglesRendered += triCount; diff --git a/libraries/entities-renderer/src/RenderableEntityItem.cpp b/libraries/entities-renderer/src/RenderableEntityItem.cpp index 5504268dce..25f4052c75 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableEntityItem.cpp @@ -28,7 +28,12 @@ namespace render { template <> const Item::Bound payloadGetBound(const RenderableEntityItemProxy::Pointer& payload) { if (payload && payload->entity) { - return payload->entity->getAABox(); + bool success; + auto result = payload->entity->getAABox(success); + if (!success) { + return render::Item::Bound(); + } + return result; } return render::Item::Bound(); } diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 14e89b59fd..fc39297914 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -196,7 +196,12 @@ namespace render { template <> const Item::Bound payloadGetBound(const RenderableModelEntityItemMeta::Pointer& payload) { if (payload && payload->entity) { - return payload->entity->getAABox(); + bool success; + auto result = payload->entity->getAABox(success); + if (!success) { + return render::Item::Bound(); + } + return result; } return render::Item::Bound(); } @@ -338,9 +343,12 @@ void RenderableModelEntityItem::render(RenderArgs* args) { } else { static glm::vec4 greenColor(0.0f, 1.0f, 0.0f, 1.0f); gpu::Batch& batch = *args->_batch; - auto shapeTransform = getTransformToCenter(); - batch.setModelTransform(Transform()); // we want to include the scale as well - DependencyManager::get()->renderWireCubeInstance(batch, shapeTransform, greenColor); + bool success; + auto shapeTransform = getTransformToCenter(success); + if (success) { + batch.setModelTransform(Transform()); // we want to include the scale as well + DependencyManager::get()->renderWireCubeInstance(batch, shapeTransform, greenColor); + } } } diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index 520069abdf..6b128d0810 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -235,10 +235,15 @@ void RenderableParticleEffectEntityItem::updateRenderItem() { for (auto& particle : _particles) { particlePrimitives->emplace_back(particle.position, glm::vec2(particle.lifetime, particle.seed)); } - - auto bounds = getAABox(); - auto position = getPosition(); - auto rotation = getRotation(); + + bool successb, successp, successr; + auto bounds = getAABox(successb); + auto position = getPosition(successp); + auto rotation = getOrientation(successr); + bool success = successb && successp && successr; + if (!success) { + return; + } Transform transform; transform.setTranslation(position); transform.setRotation(rotation); diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index 10593a9e04..d798508ff6 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -135,9 +135,11 @@ glm::vec3 RenderablePolyVoxEntityItem::getSurfacePositionAdjustment() const { glm::mat4 RenderablePolyVoxEntityItem::voxelToLocalMatrix() const { glm::vec3 scale = getDimensions() / _voxelVolumeSize; // meters / voxel-units - glm::vec3 center = getCenterPosition(); - glm::vec3 position = getPosition(); + bool success; // XXX Does this actually have to happen in world space? + glm::vec3 center = getCenterPosition(success); + glm::vec3 position = getPosition(success); glm::vec3 positionToCenter = center - position; + positionToCenter -= getDimensions() * Vectors::HALF - getSurfacePositionAdjustment(); glm::mat4 centerToCorner = glm::translate(glm::mat4(), positionToCenter); glm::mat4 scaled = glm::scale(centerToCorner, scale); @@ -574,7 +576,12 @@ namespace render { template <> const Item::Bound payloadGetBound(const PolyVoxPayload::Pointer& payload) { if (payload && payload->_owner) { auto polyVoxEntity = std::dynamic_pointer_cast(payload->_owner); - return polyVoxEntity->getAABox(); + bool success; + auto result = polyVoxEntity->getAABox(success); + if (!success) { + return render::Item::Bound(); + } + return result; } return render::Item::Bound(); } diff --git a/libraries/entities-renderer/src/RenderableSphereEntityItem.cpp b/libraries/entities-renderer/src/RenderableSphereEntityItem.cpp index 8768e41a07..81a24c07a7 100644 --- a/libraries/entities-renderer/src/RenderableSphereEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableSphereEntityItem.cpp @@ -59,7 +59,11 @@ void RenderableSphereEntityItem::render(RenderArgs* args) { gpu::Batch& batch = *args->_batch; glm::vec4 sphereColor(toGlm(getXColor()), getLocalRenderAlpha()); - Transform modelTransform = getTransformToCenter(); + bool success; + Transform modelTransform = getTransformToCenter(success); + if (!success) { + return; + } modelTransform.postScale(SPHERE_ENTITY_SCALE); if (_procedural->ready()) { batch.setModelTransform(modelTransform); // use a transform with scale, rotation, registration point and translation diff --git a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp index bdf3b5b97c..d88b4d5f0a 100644 --- a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp @@ -44,8 +44,12 @@ void RenderableTextEntityItem::render(RenderArgs* args) { // Batch render calls Q_ASSERT(args->_batch); gpu::Batch& batch = *args->_batch; - - Transform transformToTopLeft = getTransformToCenter(); + + bool success; + Transform transformToTopLeft = getTransformToCenter(success); + if (!success) { + return; + } if (getFaceCamera()) { //rotate about vertical to face the camera glm::vec3 dPosition = args->_viewFrustum->getPosition() - getPosition(); diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index 44a0740a4d..8aae853f5e 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -185,7 +185,11 @@ void RenderableWebEntityItem::render(RenderArgs* args) { Q_ASSERT(args->_batch); gpu::Batch& batch = *args->_batch; - batch.setModelTransform(getTransformToCenter()); + bool success; + batch.setModelTransform(getTransformToCenter(success)); + if (!success) { + return; + } bool textured = false, culled = false, emissive = false; if (_texture) { batch._glActiveBindTexture(GL_TEXTURE0, GL_TEXTURE_2D, _texture); diff --git a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp index ca16b3aca1..eb01bd551e 100644 --- a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp @@ -135,7 +135,11 @@ void RenderableZoneEntityItem::render(RenderArgs* args) { gpu::Batch& batch = *args->_batch; batch.setModelTransform(Transform()); - auto shapeTransform = getTransformToCenter(); + bool success; + auto shapeTransform = getTransformToCenter(success); + if (!success) { + break; + } auto deferredLightingEffect = DependencyManager::get(); if (getShapeType() == SHAPE_TYPE_SPHERE) { shapeTransform.postScale(SPHERE_ENTITY_SCALE); @@ -190,7 +194,12 @@ namespace render { template <> const Item::Bound payloadGetBound(const RenderableZoneEntityItemMeta::Pointer& payload) { if (payload && payload->entity) { - return payload->entity->getAABox(); + bool success; + auto result = payload->entity->getAABox(success); + if (!success) { + return render::Item::Bound(); + } + return result; } return render::Item::Bound(); } diff --git a/libraries/entities/src/AddEntityOperator.cpp b/libraries/entities/src/AddEntityOperator.cpp index 9fd1de74fe..b11cec8e81 100644 --- a/libraries/entities/src/AddEntityOperator.cpp +++ b/libraries/entities/src/AddEntityOperator.cpp @@ -25,7 +25,14 @@ AddEntityOperator::AddEntityOperator(EntityTreePointer tree, EntityItemPointer n // caller must have verified existence of newEntity assert(_newEntity); - _newEntityBox = _newEntity->getQueryAACube().clamp((float)(-HALF_TREE_SCALE), (float)HALF_TREE_SCALE); + bool success; + auto queryCube = _newEntity->getQueryAACube(success); + if (!success) { + // XXX put on a list for reprocessing? + qDebug() << "Warning -- AddEntityOperator failed to get queryAACube:" << _newEntity->getID(); + } + + _newEntityBox = queryCube.clamp((float)(-HALF_TREE_SCALE), (float)HALF_TREE_SCALE); } bool AddEntityOperator::preRecursion(OctreeElementPointer element) { diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 70cecbc357..519ae5895f 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -1156,8 +1156,8 @@ void EntityItem::recordCreationTime() { _lastSimulated = now; } -const Transform EntityItem::getTransformToCenter() const { - Transform result = getTransform(); +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()); // Position to center } @@ -1175,28 +1175,29 @@ void EntityItem::setDimensions(const glm::vec3& value) { /// The maximum bounding cube for the entity, independent of it's rotation. /// This accounts for the registration point (upon which rotation occurs around). /// -const AACube& EntityItem::getMaximumAACube() const { +const AACube& EntityItem::getMaximumAACube(bool& success) const { if (_recalcMaxAACube) { // * we know that the position is the center of rotation - glm::vec3 centerOfRotation = getPosition(); // also where _registration point is + glm::vec3 centerOfRotation = getPosition(success); // also where _registration point is + if (success) { + // * we know that the registration point is the center of rotation + // * we can calculate the length of the furthest extent from the registration point + // as the dimensions * max (registrationPoint, (1.0,1.0,1.0) - registrationPoint) + glm::vec3 registrationPoint = (getDimensions() * getRegistrationPoint()); + glm::vec3 registrationRemainder = (getDimensions() * (glm::vec3(1.0f, 1.0f, 1.0f) - getRegistrationPoint())); + glm::vec3 furthestExtentFromRegistration = glm::max(registrationPoint, registrationRemainder); - // * we know that the registration point is the center of rotation - // * we can calculate the length of the furthest extent from the registration point - // as the dimensions * max (registrationPoint, (1.0,1.0,1.0) - registrationPoint) - glm::vec3 registrationPoint = (getDimensions() * getRegistrationPoint()); - glm::vec3 registrationRemainder = (getDimensions() * (glm::vec3(1.0f, 1.0f, 1.0f) - getRegistrationPoint())); - glm::vec3 furthestExtentFromRegistration = glm::max(registrationPoint, registrationRemainder); + // * we know that if you rotate in any direction you would create a sphere + // that has a radius of the length of furthest extent from registration point + float radius = glm::length(furthestExtentFromRegistration); - // * we know that if you rotate in any direction you would create a sphere - // that has a radius of the length of furthest extent from registration point - float radius = glm::length(furthestExtentFromRegistration); + // * we know that the minimum bounding cube of this maximum possible sphere is + // (center - radius) to (center + radius) + glm::vec3 minimumCorner = centerOfRotation - glm::vec3(radius, radius, radius); - // * we know that the minimum bounding cube of this maximum possible sphere is - // (center - radius) to (center + radius) - glm::vec3 minimumCorner = centerOfRotation - glm::vec3(radius, radius, radius); - - _maxAACube = AACube(minimumCorner, radius * 2.0f); - _recalcMaxAACube = false; + _maxAACube = AACube(minimumCorner, radius * 2.0f); + _recalcMaxAACube = false; + } } return _maxAACube; } @@ -1204,7 +1205,7 @@ const AACube& EntityItem::getMaximumAACube() const { /// The minimum bounding cube for the entity accounting for it's rotation. /// This accounts for the registration point (upon which rotation occurs around). /// -const AACube& EntityItem::getMinimumAACube() const { +const AACube& EntityItem::getMinimumAACube(bool& success) const { if (_recalcMinAACube) { // _position represents the position of the registration point. glm::vec3 registrationRemainder = glm::vec3(1.0f, 1.0f, 1.0f) - _registrationPoint; @@ -1212,25 +1213,28 @@ const AACube& EntityItem::getMinimumAACube() const { glm::vec3 unrotatedMinRelativeToEntity = - (getDimensions() * getRegistrationPoint()); glm::vec3 unrotatedMaxRelativeToEntity = getDimensions() * registrationRemainder; Extents unrotatedExtentsRelativeToRegistrationPoint = { unrotatedMinRelativeToEntity, unrotatedMaxRelativeToEntity }; - Extents rotatedExtentsRelativeToRegistrationPoint = unrotatedExtentsRelativeToRegistrationPoint.getRotated(getRotation()); + Extents rotatedExtentsRelativeToRegistrationPoint = + unrotatedExtentsRelativeToRegistrationPoint.getRotated(getRotation()); // shift the extents to be relative to the position/registration point - rotatedExtentsRelativeToRegistrationPoint.shiftBy(getPosition()); + rotatedExtentsRelativeToRegistrationPoint.shiftBy(getPosition(success)); - // the cube that best encompasses extents is... - AABox box(rotatedExtentsRelativeToRegistrationPoint); - glm::vec3 centerOfBox = box.calcCenter(); - float longestSide = box.getLargestDimension(); - float halfLongestSide = longestSide / 2.0f; - glm::vec3 cornerOfCube = centerOfBox - glm::vec3(halfLongestSide, halfLongestSide, halfLongestSide); + if (success) { + // the cube that best encompasses extents is... + AABox box(rotatedExtentsRelativeToRegistrationPoint); + glm::vec3 centerOfBox = box.calcCenter(); + float longestSide = box.getLargestDimension(); + float halfLongestSide = longestSide / 2.0f; + glm::vec3 cornerOfCube = centerOfBox - glm::vec3(halfLongestSide, halfLongestSide, halfLongestSide); - _minAACube = AACube(cornerOfCube, longestSide); - _recalcMinAACube = false; + _minAACube = AACube(cornerOfCube, longestSide); + _recalcMinAACube = false; + } } return _minAACube; } -const AABox& EntityItem::getAABox() const { +const AABox& EntityItem::getAABox(bool& success) const { if (_recalcAABox) { // _position represents the position of the registration point. glm::vec3 registrationRemainder = glm::vec3(1.0f, 1.0f, 1.0f) - _registrationPoint; @@ -1238,24 +1242,26 @@ const AABox& EntityItem::getAABox() const { glm::vec3 unrotatedMinRelativeToEntity = - (getDimensions() * _registrationPoint); glm::vec3 unrotatedMaxRelativeToEntity = getDimensions() * registrationRemainder; Extents unrotatedExtentsRelativeToRegistrationPoint = { unrotatedMinRelativeToEntity, unrotatedMaxRelativeToEntity }; - Extents rotatedExtentsRelativeToRegistrationPoint = unrotatedExtentsRelativeToRegistrationPoint.getRotated(getRotation()); + Extents rotatedExtentsRelativeToRegistrationPoint = + unrotatedExtentsRelativeToRegistrationPoint.getRotated(getRotation()); // shift the extents to be relative to the position/registration point - rotatedExtentsRelativeToRegistrationPoint.shiftBy(getPosition()); + rotatedExtentsRelativeToRegistrationPoint.shiftBy(getPosition(success)); - _cachedAABox = AABox(rotatedExtentsRelativeToRegistrationPoint); - _recalcAABox = false; + if (success) { + _cachedAABox = AABox(rotatedExtentsRelativeToRegistrationPoint); + _recalcAABox = false; + } } return _cachedAABox; } -AACube EntityItem::getQueryAACube() const { - // XXX - if (!_queryAACubeSet) { - _queryAACube = getMaximumAACube(); - _queryAACubeSet = true; +AACube EntityItem::getQueryAACube(bool& success) const { + AACube result = getMaximumAACube(success); + if (success) { + return result; } - return SpatiallyNestable::getQueryAACube(); + return SpatiallyNestable::getQueryAACube(success); } @@ -1288,7 +1294,9 @@ float EntityItem::getRadius() const { bool EntityItem::contains(const glm::vec3& point) const { if (getShapeType() == SHAPE_TYPE_COMPOUND) { - return getAABox().contains(point); + bool success; + bool result = getAABox(success).contains(point); + return result & success; } else { ShapeInfo info; info.setParams(getShapeType(), glm::vec3(0.5f)); @@ -1831,6 +1839,14 @@ QList EntityItem::getActionsOfType(EntityActionType typeToG return result; } +glm::quat EntityItem::getAbsoluteJointRotationInObjectFrame(int index) const { + return glm::quat(); +} + +glm::vec3 EntityItem::getAbsoluteJointTranslationInObjectFrame(int index) const { + return glm::vec3(0.0f); +} + void EntityItem::locationChanged() { requiresRecalcBoxes(); SpatiallyNestable::locationChanged(); // tell all the children, also diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 1b4d86850b..1aebcba705 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -161,11 +161,10 @@ public: // attributes applicable to all entity types EntityTypes::EntityType getType() const { return _type; } - inline glm::vec3 getCenterPosition() const { return getTransformToCenter().getTranslation(); } + inline glm::vec3 getCenterPosition(bool& success) const { return getTransformToCenter(success).getTranslation(); } void setCenterPosition(const glm::vec3& position); - const Transform getTransformToCenter() const; - void setTranformToCenter(const Transform& transform); + const Transform getTransformToCenter(bool& success) const; inline void requiresRecalcBoxes() { _recalcAABox = true; _recalcMinAACube = true; _recalcMaxAACube = true; } @@ -232,11 +231,12 @@ public: quint64 getExpiry() const; // position, size, and bounds related helpers - const AACube& getMaximumAACube() const; - const AACube& getMinimumAACube() const; - const AABox& getAABox() const; /// axis aligned bounding box in world-frame (meters) + const AACube& getMaximumAACube(bool& success) const; + const AACube& getMinimumAACube(bool& success) const; + const AABox& getAABox(bool& success) const; /// axis aligned bounding box in world-frame (meters) - virtual AACube getQueryAACube() const; + using SpatiallyNestable::getQueryAACube; + virtual AACube getQueryAACube(bool& success) const override; const QString& getScript() const { return _script; } void setScript(const QString& value) { _script = value; } @@ -381,8 +381,8 @@ public: QList getActionsOfType(EntityActionType typeToGet); // these are in the frame of this object - virtual glm::quat getAbsoluteJointRotationInObjectFrame(int index) const override { return glm::quat(); } - virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const override { return glm::vec3(0.0f); } + virtual glm::quat getAbsoluteJointRotationInObjectFrame(int index) const override; + virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const override; virtual void loader() {} // called indirectly when urls for geometry are updated diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index a0a6719521..fbbf6dbef3 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -72,12 +72,15 @@ EntityItemProperties convertLocationToScriptSemantics(const EntityItemProperties scriptSideProperties.setLocalPosition(entitySideProperties.getPosition()); scriptSideProperties.setLocalRotation(entitySideProperties.getRotation()); + bool success; glm::vec3 worldPosition = SpatiallyNestable::localToWorld(entitySideProperties.getPosition(), entitySideProperties.getParentID(), - entitySideProperties.getParentJointIndex()); + entitySideProperties.getParentJointIndex(), + success); glm::quat worldRotation = SpatiallyNestable::localToWorld(entitySideProperties.getRotation(), entitySideProperties.getParentID(), - entitySideProperties.getParentJointIndex()); + entitySideProperties.getParentJointIndex(), + success); scriptSideProperties.setPosition(worldPosition); scriptSideProperties.setRotation(worldRotation); @@ -89,13 +92,15 @@ EntityItemProperties convertLocationFromScriptSemantics(const EntityItemProperti // 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; + bool success; if (scriptSideProperties.localPositionChanged()) { entitySideProperties.setPosition(scriptSideProperties.getLocalPosition()); } else if (scriptSideProperties.positionChanged()) { glm::vec3 localPosition = SpatiallyNestable::worldToLocal(entitySideProperties.getPosition(), entitySideProperties.getParentID(), - entitySideProperties.getParentJointIndex()); + entitySideProperties.getParentJointIndex(), + success); entitySideProperties.setPosition(localPosition); } @@ -104,7 +109,8 @@ EntityItemProperties convertLocationFromScriptSemantics(const EntityItemProperti } else if (scriptSideProperties.rotationChanged()) { glm::quat localRotation = SpatiallyNestable::worldToLocal(entitySideProperties.getRotation(), entitySideProperties.getParentID(), - entitySideProperties.getParentJointIndex()); + entitySideProperties.getParentJointIndex(), + success); entitySideProperties.setRotation(localRotation); } diff --git a/libraries/entities/src/EntitySimulation.cpp b/libraries/entities/src/EntitySimulation.cpp index 86536315b8..ad354465d0 100644 --- a/libraries/entities/src/EntitySimulation.cpp +++ b/libraries/entities/src/EntitySimulation.cpp @@ -119,8 +119,9 @@ void EntitySimulation::sortEntitiesThatMoved() { while (itemItr != _entitiesToSort.end()) { EntityItemPointer entity = *itemItr; // check to see if this movement has sent the entity outside of the domain. - AACube newCube = entity->getQueryAACube(); - if (!domainBounds.touches(newCube)) { + bool success; + AACube newCube = entity->getQueryAACube(success); + if (success && !domainBounds.touches(newCube)) { qCDebug(entities) << "Entity " << entity->getEntityItemID() << " moved out of domain bounds."; _entitiesToDelete.insert(entity); _mortalEntities.remove(entity); @@ -200,8 +201,9 @@ void EntitySimulation::changeEntity(EntityItemPointer entity) { uint32_t dirtyFlags = entity->getDirtyFlags(); if (dirtyFlags & Simulation::DIRTY_POSITION) { AACube domainBounds(glm::vec3((float)-HALF_TREE_SCALE), (float)TREE_SCALE); - AACube newCube = entity->getQueryAACube(); - if (!domainBounds.touches(newCube)) { + bool success; + AACube newCube = entity->getQueryAACube(success); + if (success && !domainBounds.touches(newCube)) { qCDebug(entities) << "Entity " << entity->getEntityItemID() << " moved out of domain bounds."; _entitiesToDelete.insert(entity); _mortalEntities.remove(entity); diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 36f23edee2..6c2682c554 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -141,7 +141,12 @@ bool EntityTree::updateEntityWithElement(EntityItemPointer entity, const EntityI EntityItemProperties tempProperties; tempProperties.setLocked(wantsLocked); - UpdateEntityOperator theOperator(getThisPointer(), containingElement, entity, entity->getQueryAACube()); + bool success; + AACube queryCube = entity->getQueryAACube(success); + if (!success) { + qCDebug(entities) << "Warning -- failed to get query-cube for" << entity->getID(); + } + UpdateEntityOperator theOperator(getThisPointer(), containingElement, entity, queryCube); recurseTreeWithOperator(&theOperator); entity->setProperties(tempProperties); _isDirty = true; @@ -230,9 +235,15 @@ bool EntityTree::updateEntityWithElement(EntityItemPointer entity, const EntityI if (!containingElement) { continue; } - UpdateEntityOperator theChildOperator(getThisPointer(), - containingElement, - childEntity, childEntity->getQueryAACube()); + + bool success; + AACube queryCube = childEntity->getQueryAACube(success); + if (!success) { + qCDebug(entities) << "Can't update child -- failed to get query-cube for" << childEntity->getID(); + // XXX put on a list for later checking? + } + + UpdateEntityOperator theChildOperator(getThisPointer(), containingElement, childEntity, queryCube); recurseTreeWithOperator(&theChildOperator); foreach (SpatiallyNestablePointer childChild, childEntity->getChildren()) { if (childChild && childChild->getNestableType() == NestableType::Entity) { diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index 7154e6fce0..77e2318bc8 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -302,8 +302,9 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData // simulation changing what's visible. consider the case where the entity contains an angular velocity // the entity may not be in view and then in view a frame later, let the client side handle it's view // frustum culling on rendering. - AACube entityCube = entity->getQueryAACube(); - if (params.viewFrustum->cubeInFrustum(entityCube) == ViewFrustum::OUTSIDE) { + bool success; + AACube entityCube = entity->getQueryAACube(success); + if (!success || params.viewFrustum->cubeInFrustum(entityCube) == ViewFrustum::OUTSIDE) { includeThisEntity = false; // out of view, don't include it } } @@ -413,11 +414,21 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData } bool EntityTreeElement::containsEntityBounds(EntityItemPointer entity) const { - return containsBounds(entity->getQueryAACube()); + bool success; + auto queryCube = entity->getQueryAACube(success); + if (!success) { + return false; + } + return containsBounds(queryCube); } bool EntityTreeElement::bestFitEntityBounds(EntityItemPointer entity) const { - return bestFitBounds(entity->getQueryAACube()); + bool success; + auto queryCube = entity->getQueryAACube(success); + if (!success) { + return false; + } + return bestFitBounds(queryCube); } bool EntityTreeElement::containsBounds(const EntityItemProperties& properties) const { @@ -516,7 +527,8 @@ bool EntityTreeElement::findRayIntersection(const glm::vec3& origin, const glm:: bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, - const QVector& entityIdsToInclude, void** intersectedObject, bool precisionPicking, float distanceToElementCube) { + const QVector& entityIdsToInclude, void** intersectedObject, + bool precisionPicking, float distanceToElementCube) { // only called if we do intersect our bounding cube, but find if we actually intersect with entities... int entityNumber = 0; @@ -526,7 +538,12 @@ bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, con return; } - AABox entityBox = entity->getAABox(); + bool success; + AABox entityBox = entity->getAABox(success); + if (!success) { + return; + } + float localDistance; BoxFace localFace; glm::vec3 localSurfaceNormal; @@ -631,11 +648,12 @@ EntityItemPointer EntityTreeElement::getClosestEntity(glm::vec3 position) const void EntityTreeElement::getEntities(const glm::vec3& searchPosition, float searchRadius, QVector& foundEntities) const { forEachEntity([&](EntityItemPointer entity) { - AABox entityBox = entity->getAABox(); + 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 (entityBox.findSpherePenetration(searchPosition, searchRadius, penetration)) { + if (success && entityBox.findSpherePenetration(searchPosition, searchRadius, penetration)) { glm::vec3 dimensions = entity->getDimensions(); @@ -651,9 +669,12 @@ void EntityTreeElement::getEntities(const glm::vec3& searchPosition, float searc // maximum bounding sphere, which is actually larger than our actual radius float entityTrueRadius = dimensions.x / 2.0f; - if (findSphereSpherePenetration(searchPosition, searchRadius, - entity->getCenterPosition(), entityTrueRadius, penetration)) { - foundEntities.push_back(entity); + bool success; + if (findSphereSpherePenetration(searchPosition, searchRadius, + entity->getCenterPosition(success), entityTrueRadius, penetration)) { + if (success) { + foundEntities.push_back(entity); + } } } else { // determine the worldToEntityMatrix that doesn't include scale because @@ -679,7 +700,8 @@ void EntityTreeElement::getEntities(const glm::vec3& searchPosition, float searc void EntityTreeElement::getEntities(const AACube& cube, QVector& foundEntities) { forEachEntity([&](EntityItemPointer entity) { - AABox entityBox = entity->getAABox(); + 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 @@ -693,10 +715,10 @@ void EntityTreeElement::getEntities(const AACube& cube, QVector& foundEntities) { forEachEntity([&](EntityItemPointer entity) { - AABox entityBox = entity->getAABox(); + 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 @@ -718,10 +741,10 @@ void EntityTreeElement::getEntities(const AABox& box, QVector // test the triangles of the face against the box? // if translated search face triangle intersect target box // add to result - // + // // If the entities AABox touches the search cube then consider it to be found - if (entityBox.touches(box)) { + if (success && entityBox.touches(box)) { foundEntities.push_back(entity); } }); @@ -940,7 +963,11 @@ bool EntityTreeElement::pruneChildren() { void EntityTreeElement::expandExtentsToContents(Extents& extents) { withReadLock([&] { foreach(EntityItemPointer entity, _entityItems) { - extents.add(entity->getAABox()); + bool success; + AABox aaBox = entity->getAABox(success); + if (success) { + extents.add(aaBox); + } } }); } diff --git a/libraries/entities/src/SphereEntityItem.cpp b/libraries/entities/src/SphereEntityItem.cpp index 841b70aa56..7ad7b39f20 100644 --- a/libraries/entities/src/SphereEntityItem.cpp +++ b/libraries/entities/src/SphereEntityItem.cpp @@ -110,7 +110,11 @@ bool SphereEntityItem::findDetailedRayIntersection(const glm::vec3& origin, cons // then translate back to work coordinates glm::vec3 hitAt = glm::vec3(entityToWorldMatrix * glm::vec4(entityFrameHitAt, 1.0f)); distance = glm::distance(origin, hitAt); - surfaceNormal = glm::normalize(hitAt - getCenterPosition()); + bool success; + surfaceNormal = glm::normalize(hitAt - getCenterPosition(success)); + if (!success) { + return false; + } return true; } return false; diff --git a/libraries/shared/src/SpatialParentFinder.h b/libraries/shared/src/SpatialParentFinder.h index 936d497eae..9b49490fa5 100644 --- a/libraries/shared/src/SpatialParentFinder.h +++ b/libraries/shared/src/SpatialParentFinder.h @@ -31,7 +31,7 @@ public: SpatialParentFinder() { } virtual ~SpatialParentFinder() { } - virtual SpatiallyNestableWeakPointer find(QUuid parentID) const = 0; + virtual SpatiallyNestableWeakPointer find(QUuid parentID, bool& success) const = 0; }; #endif // hifi_SpatialParentFinder_h diff --git a/libraries/shared/src/SpatiallyNestable.cpp b/libraries/shared/src/SpatiallyNestable.cpp index 42b4c9ead3..7c25fc0ec8 100644 --- a/libraries/shared/src/SpatiallyNestable.cpp +++ b/libraries/shared/src/SpatiallyNestable.cpp @@ -24,21 +24,25 @@ SpatiallyNestable::SpatiallyNestable(NestableType nestableType, QUuid id) : _transform.setRotation(glm::quat()); } -Transform SpatiallyNestable::getParentTransform() const { +Transform SpatiallyNestable::getParentTransform(bool& success) const { Transform result; - SpatiallyNestablePointer parent = getParentPointer(); + SpatiallyNestablePointer parent = getParentPointer(success); + if (!success) { + return result; + } if (parent) { - Transform parentTransform = parent->getTransform(_parentJointIndex); - result = parentTransform.setScale(1.0f); + Transform parentTransform = parent->getTransform(_parentJointIndex, success); + result = parentTransform.setScale(1.0f); // TODO: scaling } return result; } -SpatiallyNestablePointer SpatiallyNestable::getParentPointer() const { +SpatiallyNestablePointer SpatiallyNestable::getParentPointer(bool& success) const { SpatiallyNestablePointer parent = _parent.lock(); if (!parent && _parentID.isNull()) { // no parent + success = true; return nullptr; } @@ -48,6 +52,7 @@ SpatiallyNestablePointer SpatiallyNestable::getParentPointer() const { parent->beParentOfChild(getThisPointer()); _parentKnowsMe = true; } + success = true; return parent; } @@ -63,9 +68,14 @@ SpatiallyNestablePointer SpatiallyNestable::getParentPointer() const { // we have a _parentID but no parent pointer, or our parent pointer was to the wrong thing QSharedPointer parentFinder = DependencyManager::get(); if (!parentFinder) { + success = false; return nullptr; } - _parent = parentFinder->find(_parentID); + _parent = parentFinder->find(_parentID, success); + if (!success) { + return nullptr; + } + parent = _parent.lock(); if (parent) { parent->beParentOfChild(thisPointer); @@ -73,7 +83,9 @@ SpatiallyNestablePointer SpatiallyNestable::getParentPointer() const { } if (parent || _parentID.isNull()) { - thisPointer->parentChanged(); + success = true; + } else { + success = false; } return parent; @@ -96,136 +108,245 @@ void SpatiallyNestable::setParentID(const QUuid& parentID) { _parentID = parentID; _parentKnowsMe = false; } - parentChanged(); } void SpatiallyNestable::setParentJointIndex(quint16 parentJointIndex) { _parentJointIndex = parentJointIndex; } - -glm::vec3 SpatiallyNestable::worldToLocal(const glm::vec3& position, const QUuid& parentID, int parentJointIndex) { +glm::vec3 SpatiallyNestable::worldToLocal(const glm::vec3& position, + const QUuid& parentID, int parentJointIndex, + bool& success) { + Transform result; QSharedPointer parentFinder = DependencyManager::get(); - Transform parentTransform; - if (parentFinder) { - auto parentWP = parentFinder->find(parentID); - auto parent = parentWP.lock(); - if (parent) { - parentTransform = parent->getTransform(parentJointIndex); - parentTransform.setScale(1.0f); - } + if (!parentFinder) { + success = false; + return glm::vec3(0.0f); } + Transform parentTransform; + auto parentWP = parentFinder->find(parentID, success); + if (!success) { + return glm::vec3(0.0f); + } + + auto parent = parentWP.lock(); + if (!parentID.isNull() && !parent) { + success = false; + return glm::vec3(0.0f); + } + + if (parent) { + parentTransform = parent->getTransform(parentJointIndex, success); + if (!success) { + return glm::vec3(0.0f); + } + parentTransform.setScale(1.0f); // TODO: scale + } + success = true; + Transform positionTransform; positionTransform.setTranslation(position); Transform myWorldTransform; Transform::mult(myWorldTransform, parentTransform, positionTransform); - myWorldTransform.setTranslation(position); - Transform result; Transform::inverseMult(result, parentTransform, myWorldTransform); return result.getTranslation(); } -glm::quat SpatiallyNestable::worldToLocal(const glm::quat& orientation, const QUuid& parentID, int parentJointIndex) { +glm::quat SpatiallyNestable::worldToLocal(const glm::quat& orientation, + const QUuid& parentID, int parentJointIndex, + bool& success) { + Transform result; QSharedPointer parentFinder = DependencyManager::get(); - Transform parentTransform; - if (parentFinder) { - auto parentWP = parentFinder->find(parentID); - auto parent = parentWP.lock(); - if (parent) { - parentTransform = parent->getTransform(parentJointIndex); - parentTransform.setScale(1.0f); - } + if (!parentFinder) { + success = false; + return glm::quat(); } + Transform parentTransform; + auto parentWP = parentFinder->find(parentID, success); + if (!success) { + return glm::quat(); + } + + auto parent = parentWP.lock(); + if (!parentID.isNull() && !parent) { + success = false; + return glm::quat(); + } + + if (parent) { + parentTransform = parent->getTransform(parentJointIndex, success); + if (!success) { + return glm::quat(); + } + parentTransform.setScale(1.0f); // TODO: scale + } + success = true; + Transform orientationTransform; orientationTransform.setRotation(orientation); Transform myWorldTransform; Transform::mult(myWorldTransform, parentTransform, orientationTransform); myWorldTransform.setRotation(orientation); - Transform result; Transform::inverseMult(result, parentTransform, myWorldTransform); return result.getRotation(); } -glm::vec3 SpatiallyNestable::localToWorld(const glm::vec3& position, const QUuid& parentID, int parentJointIndex) { +glm::vec3 SpatiallyNestable::localToWorld(const glm::vec3& position, + const QUuid& parentID, int parentJointIndex, + bool& success) { + Transform result; QSharedPointer parentFinder = DependencyManager::get(); - Transform parentTransform; - if (parentFinder) { - auto parentWP = parentFinder->find(parentID); - auto parent = parentWP.lock(); - if (parent) { - parentTransform = parent->getTransform(parentJointIndex); - parentTransform.setScale(1.0f); - } + if (!parentFinder) { + success = false; + return glm::vec3(0.0f); } + + Transform parentTransform; + auto parentWP = parentFinder->find(parentID, success); + if (!success) { + return glm::vec3(0.0f); + } + + auto parent = parentWP.lock(); + if (!parentID.isNull() && !parent) { + success = false; + return glm::vec3(0.0f); + } + + if (parent) { + parentTransform = parent->getTransform(parentJointIndex, success); + if (!success) { + return glm::vec3(0.0f); + } + parentTransform.setScale(1.0f); // TODO: scale + } + success = true; + Transform positionTransform; positionTransform.setTranslation(position); - Transform result; Transform::mult(result, parentTransform, positionTransform); return result.getTranslation(); } -glm::quat SpatiallyNestable::localToWorld(const glm::quat& orientation, const QUuid& parentID, int parentJointIndex) { +glm::quat SpatiallyNestable::localToWorld(const glm::quat& orientation, + const QUuid& parentID, int parentJointIndex, + bool& success) { + Transform result; QSharedPointer parentFinder = DependencyManager::get(); - Transform parentTransform; - if (parentFinder) { - auto parentWP = parentFinder->find(parentID); - auto parent = parentWP.lock(); - if (parent) { - parentTransform = parent->getTransform(parentJointIndex); - parentTransform.setScale(1.0f); - } + if (!parentFinder) { + success = false; + return glm::quat(); } + + Transform parentTransform; + auto parentWP = parentFinder->find(parentID, success); + if (!success) { + return glm::quat(); + } + + auto parent = parentWP.lock(); + if (!parentID.isNull() && !parent) { + success = false; + return glm::quat(); + } + + if (parent) { + parentTransform = parent->getTransform(parentJointIndex, success); + if (!success) { + return glm::quat(); + } + parentTransform.setScale(1.0f); + } + success = true; + Transform orientationTransform; orientationTransform.setRotation(orientation); - Transform result; Transform::mult(result, parentTransform, orientationTransform); return result.getRotation(); } +glm::vec3 SpatiallyNestable::getPosition(bool& success) const { + return getTransform(success).getTranslation(); +} + glm::vec3 SpatiallyNestable::getPosition() const { - return getTransform().getTranslation(); + bool success; + auto result = getPosition(success); + if (!success) { + qDebug() << "Warning -- getPosition failed"; + } + return result; } -glm::vec3 SpatiallyNestable::getPosition(int jointIndex) const { - return getTransform(jointIndex).getTranslation(); +glm::vec3 SpatiallyNestable::getPosition(int jointIndex, bool& success) const { + return getTransform(jointIndex, success).getTranslation(); } -void SpatiallyNestable::setPosition(const glm::vec3& position) { - Transform parentTransform = getParentTransform(); +void SpatiallyNestable::setPosition(const glm::vec3& position, bool& success) { + Transform parentTransform = getParentTransform(success); Transform myWorldTransform; _transformLock.withWriteLock([&] { Transform::mult(myWorldTransform, parentTransform, _transform); myWorldTransform.setTranslation(position); Transform::inverseMult(_transform, parentTransform, myWorldTransform); }); - locationChanged(); + if (success) { + locationChanged(); + } +} + +void SpatiallyNestable::setPosition(const glm::vec3& position) { + bool success; + setPosition(position, success); + if (!success) { + qDebug() << "Warning -- setPosition failed"; + } +} + +glm::quat SpatiallyNestable::getOrientation(bool& success) const { + return getTransform(success).getRotation(); } glm::quat SpatiallyNestable::getOrientation() const { - return getTransform().getRotation(); + bool success; + auto result = getOrientation(success); + if (!success) { + qDebug() << "Warning -- getOrientation failed"; + } + return result; } -glm::quat SpatiallyNestable::getOrientation(int jointIndex) const { - return getTransform(jointIndex).getRotation(); +glm::quat SpatiallyNestable::getOrientation(int jointIndex, bool& success) const { + return getTransform(jointIndex, success).getRotation(); } -void SpatiallyNestable::setOrientation(const glm::quat& orientation) { - Transform parentTransform = getParentTransform(); +void SpatiallyNestable::setOrientation(const glm::quat& orientation, bool& success) { + Transform parentTransform = getParentTransform(success); Transform myWorldTransform; _transformLock.withWriteLock([&] { Transform::mult(myWorldTransform, parentTransform, _transform); myWorldTransform.setRotation(orientation); Transform::inverseMult(_transform, parentTransform, myWorldTransform); }); - locationChanged(); + if (success) { + locationChanged(); + } } -const Transform SpatiallyNestable::getTransform() const { +void SpatiallyNestable::setOrientation(const glm::quat& orientation) { + bool success; + setOrientation(orientation, success); + if (!success) { + qDebug() << "Wanring -- setOrientation failed"; + } +} + +const Transform SpatiallyNestable::getTransform(bool& success) const { // return a world-space transform for this object's location - Transform parentTransform = getParentTransform(); + Transform parentTransform = getParentTransform(success); Transform result; _transformLock.withReadLock([&] { Transform::mult(result, parentTransform, _transform); @@ -233,25 +354,34 @@ const Transform SpatiallyNestable::getTransform() const { return result; } -const Transform SpatiallyNestable::getTransform(int jointIndex) const { +const Transform SpatiallyNestable::getTransform(int jointIndex, bool& success) const { // this returns the world-space transform for this object. It finds its parent's transform (which may // cause this object's parent to query its parent, etc) and multiplies this object's local transform onto it. - Transform worldTransform = getTransform(); - Transform jointInObjectFrame = getAbsoluteJointTransformInObjectFrame(jointIndex); Transform jointInWorldFrame; + + Transform worldTransform = getTransform(success); + if (!success) { + return jointInWorldFrame; + } + + Transform jointInObjectFrame = getAbsoluteJointTransformInObjectFrame(jointIndex); Transform::mult(jointInWorldFrame, worldTransform, jointInObjectFrame); + success = true; return jointInWorldFrame; } -void SpatiallyNestable::setTransform(const Transform& transform) { - Transform parentTransform = getParentTransform(); +void SpatiallyNestable::setTransform(const Transform& transform, bool& success) { + Transform parentTransform = getParentTransform(success); _transformLock.withWriteLock([&] { Transform::inverseMult(_transform, parentTransform, transform); }); - locationChanged(); + if (success) { + locationChanged(); + } } glm::vec3 SpatiallyNestable::getScale() const { + // TODO: scale glm::vec3 result; _transformLock.withReadLock([&] { result = _transform.getScale(); @@ -260,11 +390,12 @@ glm::vec3 SpatiallyNestable::getScale() const { } glm::vec3 SpatiallyNestable::getScale(int jointIndex) const { - // XXX ... something with joints + // TODO: scale return getScale(); } void SpatiallyNestable::setScale(const glm::vec3& scale) { + // TODO: scale _transformLock.withWriteLock([&] { _transform.setScale(scale); }); @@ -317,6 +448,7 @@ void SpatiallyNestable::setLocalOrientation(const glm::quat& orientation) { } glm::vec3 SpatiallyNestable::getLocalScale() const { + // TODO: scale glm::vec3 result; _transformLock.withReadLock([&] { result = _transform.getScale(); @@ -325,6 +457,7 @@ glm::vec3 SpatiallyNestable::getLocalScale() const { } void SpatiallyNestable::setLocalScale(const glm::vec3& scale) { + // TODO: scale _transformLock.withWriteLock([&] { _transform.setScale(scale); }); @@ -353,6 +486,16 @@ const Transform SpatiallyNestable::getAbsoluteJointTransformInObjectFrame(int jo return jointTransformInObjectFrame; } +glm::quat SpatiallyNestable::getAbsoluteJointRotationInObjectFrame(int index) const { + assert(false); + return glm::quat(); +} + +glm::vec3 SpatiallyNestable::getAbsoluteJointTranslationInObjectFrame(int index) const { + assert(false); + return glm::vec3(); +} + SpatiallyNestablePointer SpatiallyNestable::getThisPointer() const { SpatiallyNestableConstPointer constThisPointer = shared_from_this(); SpatiallyNestablePointer thisPointer = std::const_pointer_cast(constThisPointer); // ermahgerd !!! @@ -391,10 +534,19 @@ void SpatiallyNestable::setQueryAACube(const AACube& queryAACube) { _queryAACubeSet = true; } -AACube SpatiallyNestable::getQueryAACube() const { - if (!_queryAACubeSet) { - _queryAACube = AACube(getPosition() - glm::vec3(0.5f), 1.0f); // XXX - _queryAACubeSet = true; +AACube SpatiallyNestable::getQueryAACube(bool& success) const { + if (_queryAACubeSet) { + success = true; + return _queryAACube; } - return _queryAACube; + return AACube(getPosition(success) - glm::vec3(0.5f), 1.0f); // XXX +} + +AACube SpatiallyNestable::getQueryAACube() const { + bool success; + auto result = getQueryAACube(success); + if (!success) { + qDebug() << "getQueryAACube failed:" << getID(); + } + return result; } diff --git a/libraries/shared/src/SpatiallyNestable.h b/libraries/shared/src/SpatiallyNestable.h index 8aa97ac77f..f61ac487fd 100644 --- a/libraries/shared/src/SpatiallyNestable.h +++ b/libraries/shared/src/SpatiallyNestable.h @@ -45,34 +45,39 @@ 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); - static glm::quat worldToLocal(const glm::quat& orientation, const QUuid& parentID, int 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 localToWorld(const glm::vec3& position, const QUuid& parentID, int parentJointIndex); - static glm::quat localToWorld(const glm::quat& orientation, const QUuid& parentID, int parentJointIndex); + 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); // world frame - virtual const Transform getTransform() const; - virtual void setTransform(const Transform& transform); + virtual const Transform getTransform(bool& success) const; + virtual void setTransform(const Transform& transform, bool& success); - virtual Transform getParentTransform() const; + virtual Transform getParentTransform(bool& success) const; + virtual glm::vec3 getPosition(bool& success) const; virtual glm::vec3 getPosition() const; + virtual void setPosition(const glm::vec3& position, bool& success); virtual void setPosition(const glm::vec3& position); + virtual glm::quat getOrientation(bool& success) const; virtual glm::quat getOrientation() const; - virtual glm::quat getOrientation(int jointIndex) const; + virtual glm::quat getOrientation(int jointIndex, bool& success) const; + virtual void setOrientation(const glm::quat& orientation, bool& success); virtual void setOrientation(const glm::quat& orientation); virtual void setQueryAACube(const AACube& queryAACube); + virtual AACube getQueryAACube(bool& success) const; virtual AACube getQueryAACube() const; virtual glm::vec3 getScale() const; virtual void setScale(const glm::vec3& scale); // get world-frame values for a specific joint - virtual const Transform getTransform(int jointIndex) const; - virtual glm::vec3 getPosition(int jointIndex) const; + virtual const Transform getTransform(int jointIndex, bool& success) const; + virtual glm::vec3 getPosition(int jointIndex, bool& success) const; virtual glm::vec3 getScale(int jointIndex) const; // object's parent's frame @@ -93,8 +98,8 @@ public: // this object's frame virtual const Transform getAbsoluteJointTransformInObjectFrame(int jointIndex) const; - virtual glm::quat getAbsoluteJointRotationInObjectFrame(int index) const { assert(false); return glm::quat(); } - virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const { assert(false); return glm::vec3(); } + virtual glm::quat getAbsoluteJointRotationInObjectFrame(int index) const; + virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const; SpatiallyNestablePointer getThisPointer() const; @@ -103,7 +108,7 @@ protected: QUuid _id; QUuid _parentID; // what is this thing's transform relative to? quint16 _parentJointIndex { 0 }; // which joint of the parent is this relative to? - SpatiallyNestablePointer getParentPointer() const; + SpatiallyNestablePointer getParentPointer(bool& success) const; mutable SpatiallyNestableWeakPointer _parent; virtual void beParentOfChild(SpatiallyNestablePointer newChild) const; @@ -112,7 +117,6 @@ protected: mutable ReadWriteLockable _childrenLock; mutable QHash _children; - virtual void parentChanged() {} // called when parent pointer is updated virtual void locationChanged(); // called when a this object's location has changed virtual void dimensionsChanged() {} // called when a this object's dimensions have changed