location getters also return a success boolean so that callers can know if the value they are receiving is bad due to lack of information about an object's parent

This commit is contained in:
Seth Alves 2015-12-14 09:13:36 -08:00
parent 270d5fc8e1
commit c74f8bca49
27 changed files with 506 additions and 202 deletions

View file

@ -11,9 +11,14 @@
#include "AssignmentParentFinder.h" #include "AssignmentParentFinder.h"
SpatiallyNestableWeakPointer AssignmentParentFinder::find(QUuid parentID) const { SpatiallyNestableWeakPointer AssignmentParentFinder::find(QUuid parentID, bool& success) const {
SpatiallyNestableWeakPointer parent; SpatiallyNestableWeakPointer parent;
// search entities // search entities
parent = _tree->findEntityByEntityItemID(parentID); parent = _tree->findEntityByEntityItemID(parentID);
if (parent.lock()) {
success = true;
} else {
success = false;
}
return parent; return parent;
} }

View file

@ -25,7 +25,7 @@ class AssignmentParentFinder : public SpatialParentFinder {
public: public:
AssignmentParentFinder(EntityTreePointer tree) : _tree(tree) { } AssignmentParentFinder(EntityTreePointer tree) : _tree(tree) { }
virtual ~AssignmentParentFinder() { } virtual ~AssignmentParentFinder() { }
virtual SpatiallyNestableWeakPointer find(QUuid parentID) const; virtual SpatiallyNestableWeakPointer find(QUuid parentID, bool& success) const;
protected: protected:
EntityTreePointer _tree; EntityTreePointer _tree;

View file

@ -21,7 +21,7 @@ class InterfaceParentFinder : public SpatialParentFinder {
public: public:
InterfaceParentFinder() { } InterfaceParentFinder() { }
virtual ~InterfaceParentFinder() { } virtual ~InterfaceParentFinder() { }
virtual SpatiallyNestableWeakPointer find(QUuid parentID) const; virtual SpatiallyNestableWeakPointer find(QUuid parentID, bool& success) const;
}; };
#endif // hifi_InterfaceParentFinder_h #endif // hifi_InterfaceParentFinder_h

View file

@ -158,7 +158,9 @@ public:
void setMotionState(AvatarMotionState* motionState) { _motionState = motionState; } void setMotionState(AvatarMotionState* motionState) { _motionState = motionState; }
AvatarMotionState* getMotionState() { return _motionState; } AvatarMotionState* getMotionState() { return _motionState; }
using SpatiallyNestable::setPosition;
virtual void setPosition(const glm::vec3& position) override; virtual void setPosition(const glm::vec3& position) override;
using SpatiallyNestable::setOrientation;
virtual void setOrientation(const glm::quat& orientation) override; virtual void setOrientation(const glm::quat& orientation) override;
public slots: public slots:

View file

@ -93,7 +93,11 @@ void AvatarData::nextAttitude(glm::vec3 position, glm::quat orientation) {
Transform trans; Transform trans;
trans.setTranslation(position); trans.setTranslation(position);
trans.setRotation(orientation); trans.setRotation(orientation);
SpatiallyNestable::setTransform(trans); bool success;
SpatiallyNestable::setTransform(trans, success);
if (!success) {
qDebug() << "Warning -- AvatarData::nextAttitude failed";
}
avatarLock.unlock(); avatarLock.unlock();
updateAttitude(); updateAttitude();
} }
@ -211,8 +215,9 @@ QByteArray AvatarData::toByteArray(bool cullSmallChanges, bool sendAll) {
setAtBit(bitItems, IS_EYE_TRACKER_CONNECTED); setAtBit(bitItems, IS_EYE_TRACKER_CONNECTED);
} }
// referential state // referential state
SpatiallyNestablePointer parent = getParentPointer(); bool success;
if (parent) { SpatiallyNestablePointer parent = getParentPointer(success);
if (parent && success) {
setAtBit(bitItems, HAS_REFERENTIAL); setAtBit(bitItems, HAS_REFERENTIAL);
} }
*destinationBuffer++ = bitItems; *destinationBuffer++ = bitItems;
@ -1443,7 +1448,11 @@ QJsonObject AvatarData::toJson() const {
} }
auto recordingBasis = getRecordingBasis(); 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()); avatarTransform.setScale(getTargetScale());
if (recordingBasis) { if (recordingBasis) {
root[JSON_AVATAR_BASIS] = Transform::toJson(*recordingBasis); root[JSON_AVATAR_BASIS] = Transform::toJson(*recordingBasis);

View file

@ -201,7 +201,9 @@ public:
float getBodyRoll() const; float getBodyRoll() const;
void setBodyRoll(float bodyRoll); void setBodyRoll(float bodyRoll);
using SpatiallyNestable::setPosition;
virtual void setPosition(const glm::vec3& position) override; virtual void setPosition(const glm::vec3& position) override;
using SpatiallyNestable::setOrientation;
virtual void setOrientation(const glm::quat& orientation) override; virtual void setOrientation(const glm::quat& orientation) override;
void nextAttitude(glm::vec3 position, glm::quat orientation); // Can be safely called at any time. void nextAttitude(glm::vec3 position, glm::quat orientation); // Can be safely called at any time.

View file

@ -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) // 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 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); AudioInjector::playSound(collisionSoundURL, volume, stretchFactor, position);
} }

View file

@ -56,14 +56,20 @@ void RenderableBoxEntityItem::render(RenderArgs* args) {
gpu::Batch& batch = *args->_batch; gpu::Batch& batch = *args->_batch;
glm::vec4 cubeColor(toGlm(getXColor()), getLocalRenderAlpha()); glm::vec4 cubeColor(toGlm(getXColor()), getLocalRenderAlpha());
bool success;
auto transToCenter = getTransformToCenter(success);
if (!success) {
return;
}
if (_procedural->ready()) { 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()); _procedural->prepare(batch, getPosition(), getDimensions());
auto color = _procedural->getColor(cubeColor); auto color = _procedural->getColor(cubeColor);
batch._glColor4f(color.r, color.g, color.b, color.a); batch._glColor4f(color.r, color.g, color.b, color.a);
DependencyManager::get<GeometryCache>()->renderCube(batch); DependencyManager::get<GeometryCache>()->renderCube(batch);
} else { } else {
DependencyManager::get<DeferredLightingEffect>()->renderSolidCubeInstance(batch, getTransformToCenter(), cubeColor); DependencyManager::get<DeferredLightingEffect>()->renderSolidCubeInstance(batch, transToCenter, cubeColor);
} }
static const auto triCount = DependencyManager::get<GeometryCache>()->getCubeTriangleCount(); static const auto triCount = DependencyManager::get<GeometryCache>()->getCubeTriangleCount();
args->_details._trianglesRendered += triCount; args->_details._trianglesRendered += triCount;

View file

@ -28,7 +28,12 @@ namespace render {
template <> const Item::Bound payloadGetBound(const RenderableEntityItemProxy::Pointer& payload) { template <> const Item::Bound payloadGetBound(const RenderableEntityItemProxy::Pointer& payload) {
if (payload && payload->entity) { 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(); return render::Item::Bound();
} }

View file

@ -196,7 +196,12 @@ namespace render {
template <> const Item::Bound payloadGetBound(const RenderableModelEntityItemMeta::Pointer& payload) { template <> const Item::Bound payloadGetBound(const RenderableModelEntityItemMeta::Pointer& payload) {
if (payload && payload->entity) { 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(); return render::Item::Bound();
} }
@ -338,9 +343,12 @@ void RenderableModelEntityItem::render(RenderArgs* args) {
} else { } else {
static glm::vec4 greenColor(0.0f, 1.0f, 0.0f, 1.0f); static glm::vec4 greenColor(0.0f, 1.0f, 0.0f, 1.0f);
gpu::Batch& batch = *args->_batch; gpu::Batch& batch = *args->_batch;
auto shapeTransform = getTransformToCenter(); bool success;
batch.setModelTransform(Transform()); // we want to include the scale as well auto shapeTransform = getTransformToCenter(success);
DependencyManager::get<DeferredLightingEffect>()->renderWireCubeInstance(batch, shapeTransform, greenColor); if (success) {
batch.setModelTransform(Transform()); // we want to include the scale as well
DependencyManager::get<DeferredLightingEffect>()->renderWireCubeInstance(batch, shapeTransform, greenColor);
}
} }
} }

View file

@ -235,10 +235,15 @@ void RenderableParticleEffectEntityItem::updateRenderItem() {
for (auto& particle : _particles) { for (auto& particle : _particles) {
particlePrimitives->emplace_back(particle.position, glm::vec2(particle.lifetime, particle.seed)); particlePrimitives->emplace_back(particle.position, glm::vec2(particle.lifetime, particle.seed));
} }
auto bounds = getAABox(); bool successb, successp, successr;
auto position = getPosition(); auto bounds = getAABox(successb);
auto rotation = getRotation(); auto position = getPosition(successp);
auto rotation = getOrientation(successr);
bool success = successb && successp && successr;
if (!success) {
return;
}
Transform transform; Transform transform;
transform.setTranslation(position); transform.setTranslation(position);
transform.setRotation(rotation); transform.setRotation(rotation);

View file

@ -135,9 +135,11 @@ glm::vec3 RenderablePolyVoxEntityItem::getSurfacePositionAdjustment() const {
glm::mat4 RenderablePolyVoxEntityItem::voxelToLocalMatrix() const { glm::mat4 RenderablePolyVoxEntityItem::voxelToLocalMatrix() const {
glm::vec3 scale = getDimensions() / _voxelVolumeSize; // meters / voxel-units glm::vec3 scale = getDimensions() / _voxelVolumeSize; // meters / voxel-units
glm::vec3 center = getCenterPosition(); bool success; // XXX Does this actually have to happen in world space?
glm::vec3 position = getPosition(); glm::vec3 center = getCenterPosition(success);
glm::vec3 position = getPosition(success);
glm::vec3 positionToCenter = center - position; glm::vec3 positionToCenter = center - position;
positionToCenter -= getDimensions() * Vectors::HALF - getSurfacePositionAdjustment(); positionToCenter -= getDimensions() * Vectors::HALF - getSurfacePositionAdjustment();
glm::mat4 centerToCorner = glm::translate(glm::mat4(), positionToCenter); glm::mat4 centerToCorner = glm::translate(glm::mat4(), positionToCenter);
glm::mat4 scaled = glm::scale(centerToCorner, scale); glm::mat4 scaled = glm::scale(centerToCorner, scale);
@ -574,7 +576,12 @@ namespace render {
template <> const Item::Bound payloadGetBound(const PolyVoxPayload::Pointer& payload) { template <> const Item::Bound payloadGetBound(const PolyVoxPayload::Pointer& payload) {
if (payload && payload->_owner) { if (payload && payload->_owner) {
auto polyVoxEntity = std::dynamic_pointer_cast<RenderablePolyVoxEntityItem>(payload->_owner); auto polyVoxEntity = std::dynamic_pointer_cast<RenderablePolyVoxEntityItem>(payload->_owner);
return polyVoxEntity->getAABox(); bool success;
auto result = polyVoxEntity->getAABox(success);
if (!success) {
return render::Item::Bound();
}
return result;
} }
return render::Item::Bound(); return render::Item::Bound();
} }

View file

@ -59,7 +59,11 @@ void RenderableSphereEntityItem::render(RenderArgs* args) {
gpu::Batch& batch = *args->_batch; gpu::Batch& batch = *args->_batch;
glm::vec4 sphereColor(toGlm(getXColor()), getLocalRenderAlpha()); glm::vec4 sphereColor(toGlm(getXColor()), getLocalRenderAlpha());
Transform modelTransform = getTransformToCenter(); bool success;
Transform modelTransform = getTransformToCenter(success);
if (!success) {
return;
}
modelTransform.postScale(SPHERE_ENTITY_SCALE); modelTransform.postScale(SPHERE_ENTITY_SCALE);
if (_procedural->ready()) { if (_procedural->ready()) {
batch.setModelTransform(modelTransform); // use a transform with scale, rotation, registration point and translation batch.setModelTransform(modelTransform); // use a transform with scale, rotation, registration point and translation

View file

@ -44,8 +44,12 @@ void RenderableTextEntityItem::render(RenderArgs* args) {
// Batch render calls // Batch render calls
Q_ASSERT(args->_batch); Q_ASSERT(args->_batch);
gpu::Batch& batch = *args->_batch; gpu::Batch& batch = *args->_batch;
Transform transformToTopLeft = getTransformToCenter(); bool success;
Transform transformToTopLeft = getTransformToCenter(success);
if (!success) {
return;
}
if (getFaceCamera()) { if (getFaceCamera()) {
//rotate about vertical to face the camera //rotate about vertical to face the camera
glm::vec3 dPosition = args->_viewFrustum->getPosition() - getPosition(); glm::vec3 dPosition = args->_viewFrustum->getPosition() - getPosition();

View file

@ -185,7 +185,11 @@ void RenderableWebEntityItem::render(RenderArgs* args) {
Q_ASSERT(args->_batch); Q_ASSERT(args->_batch);
gpu::Batch& batch = *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; bool textured = false, culled = false, emissive = false;
if (_texture) { if (_texture) {
batch._glActiveBindTexture(GL_TEXTURE0, GL_TEXTURE_2D, _texture); batch._glActiveBindTexture(GL_TEXTURE0, GL_TEXTURE_2D, _texture);

View file

@ -135,7 +135,11 @@ void RenderableZoneEntityItem::render(RenderArgs* args) {
gpu::Batch& batch = *args->_batch; gpu::Batch& batch = *args->_batch;
batch.setModelTransform(Transform()); batch.setModelTransform(Transform());
auto shapeTransform = getTransformToCenter(); bool success;
auto shapeTransform = getTransformToCenter(success);
if (!success) {
break;
}
auto deferredLightingEffect = DependencyManager::get<DeferredLightingEffect>(); auto deferredLightingEffect = DependencyManager::get<DeferredLightingEffect>();
if (getShapeType() == SHAPE_TYPE_SPHERE) { if (getShapeType() == SHAPE_TYPE_SPHERE) {
shapeTransform.postScale(SPHERE_ENTITY_SCALE); shapeTransform.postScale(SPHERE_ENTITY_SCALE);
@ -190,7 +194,12 @@ namespace render {
template <> const Item::Bound payloadGetBound(const RenderableZoneEntityItemMeta::Pointer& payload) { template <> const Item::Bound payloadGetBound(const RenderableZoneEntityItemMeta::Pointer& payload) {
if (payload && payload->entity) { 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(); return render::Item::Bound();
} }

View file

@ -25,7 +25,14 @@ AddEntityOperator::AddEntityOperator(EntityTreePointer tree, EntityItemPointer n
// caller must have verified existence of newEntity // caller must have verified existence of newEntity
assert(_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) { bool AddEntityOperator::preRecursion(OctreeElementPointer element) {

View file

@ -1156,8 +1156,8 @@ void EntityItem::recordCreationTime() {
_lastSimulated = now; _lastSimulated = now;
} }
const Transform EntityItem::getTransformToCenter() const { const Transform EntityItem::getTransformToCenter(bool& success) const {
Transform result = getTransform(); Transform result = getTransform(success);
if (getRegistrationPoint() != ENTITY_ITEM_HALF_VEC3) { // If it is not already centered, translate to center 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 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. /// The maximum bounding cube for the entity, independent of it's rotation.
/// This accounts for the registration point (upon which rotation occurs around). /// 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) { if (_recalcMaxAACube) {
// * we know that the position is the center of rotation // * 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 know that if you rotate in any direction you would create a sphere
// * we can calculate the length of the furthest extent from the registration point // that has a radius of the length of furthest extent from registration point
// as the dimensions * max (registrationPoint, (1.0,1.0,1.0) - registrationPoint) float radius = glm::length(furthestExtentFromRegistration);
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 // * we know that the minimum bounding cube of this maximum possible sphere is
// that has a radius of the length of furthest extent from registration point // (center - radius) to (center + radius)
float radius = glm::length(furthestExtentFromRegistration); glm::vec3 minimumCorner = centerOfRotation - glm::vec3(radius, radius, radius);
// * we know that the minimum bounding cube of this maximum possible sphere is _maxAACube = AACube(minimumCorner, radius * 2.0f);
// (center - radius) to (center + radius) _recalcMaxAACube = false;
glm::vec3 minimumCorner = centerOfRotation - glm::vec3(radius, radius, radius); }
_maxAACube = AACube(minimumCorner, radius * 2.0f);
_recalcMaxAACube = false;
} }
return _maxAACube; return _maxAACube;
} }
@ -1204,7 +1205,7 @@ const AACube& EntityItem::getMaximumAACube() const {
/// The minimum bounding cube for the entity accounting for it's rotation. /// The minimum bounding cube for the entity accounting for it's rotation.
/// This accounts for the registration point (upon which rotation occurs around). /// 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) { if (_recalcMinAACube) {
// _position represents the position of the registration point. // _position represents the position of the registration point.
glm::vec3 registrationRemainder = glm::vec3(1.0f, 1.0f, 1.0f) - _registrationPoint; 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 unrotatedMinRelativeToEntity = - (getDimensions() * getRegistrationPoint());
glm::vec3 unrotatedMaxRelativeToEntity = getDimensions() * registrationRemainder; glm::vec3 unrotatedMaxRelativeToEntity = getDimensions() * registrationRemainder;
Extents unrotatedExtentsRelativeToRegistrationPoint = { unrotatedMinRelativeToEntity, unrotatedMaxRelativeToEntity }; 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 // 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... if (success) {
AABox box(rotatedExtentsRelativeToRegistrationPoint); // the cube that best encompasses extents is...
glm::vec3 centerOfBox = box.calcCenter(); AABox box(rotatedExtentsRelativeToRegistrationPoint);
float longestSide = box.getLargestDimension(); glm::vec3 centerOfBox = box.calcCenter();
float halfLongestSide = longestSide / 2.0f; float longestSide = box.getLargestDimension();
glm::vec3 cornerOfCube = centerOfBox - glm::vec3(halfLongestSide, halfLongestSide, halfLongestSide); float halfLongestSide = longestSide / 2.0f;
glm::vec3 cornerOfCube = centerOfBox - glm::vec3(halfLongestSide, halfLongestSide, halfLongestSide);
_minAACube = AACube(cornerOfCube, longestSide); _minAACube = AACube(cornerOfCube, longestSide);
_recalcMinAACube = false; _recalcMinAACube = false;
}
} }
return _minAACube; return _minAACube;
} }
const AABox& EntityItem::getAABox() const { const AABox& EntityItem::getAABox(bool& success) const {
if (_recalcAABox) { if (_recalcAABox) {
// _position represents the position of the registration point. // _position represents the position of the registration point.
glm::vec3 registrationRemainder = glm::vec3(1.0f, 1.0f, 1.0f) - _registrationPoint; 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 unrotatedMinRelativeToEntity = - (getDimensions() * _registrationPoint);
glm::vec3 unrotatedMaxRelativeToEntity = getDimensions() * registrationRemainder; glm::vec3 unrotatedMaxRelativeToEntity = getDimensions() * registrationRemainder;
Extents unrotatedExtentsRelativeToRegistrationPoint = { unrotatedMinRelativeToEntity, unrotatedMaxRelativeToEntity }; 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 // shift the extents to be relative to the position/registration point
rotatedExtentsRelativeToRegistrationPoint.shiftBy(getPosition()); rotatedExtentsRelativeToRegistrationPoint.shiftBy(getPosition(success));
_cachedAABox = AABox(rotatedExtentsRelativeToRegistrationPoint); if (success) {
_recalcAABox = false; _cachedAABox = AABox(rotatedExtentsRelativeToRegistrationPoint);
_recalcAABox = false;
}
} }
return _cachedAABox; return _cachedAABox;
} }
AACube EntityItem::getQueryAACube() const { AACube EntityItem::getQueryAACube(bool& success) const {
// XXX AACube result = getMaximumAACube(success);
if (!_queryAACubeSet) { if (success) {
_queryAACube = getMaximumAACube(); return result;
_queryAACubeSet = true;
} }
return SpatiallyNestable::getQueryAACube(); return SpatiallyNestable::getQueryAACube(success);
} }
@ -1288,7 +1294,9 @@ float EntityItem::getRadius() const {
bool EntityItem::contains(const glm::vec3& point) const { bool EntityItem::contains(const glm::vec3& point) const {
if (getShapeType() == SHAPE_TYPE_COMPOUND) { if (getShapeType() == SHAPE_TYPE_COMPOUND) {
return getAABox().contains(point); bool success;
bool result = getAABox(success).contains(point);
return result & success;
} else { } else {
ShapeInfo info; ShapeInfo info;
info.setParams(getShapeType(), glm::vec3(0.5f)); info.setParams(getShapeType(), glm::vec3(0.5f));
@ -1831,6 +1839,14 @@ QList<EntityActionPointer> EntityItem::getActionsOfType(EntityActionType typeToG
return result; 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() { void EntityItem::locationChanged() {
requiresRecalcBoxes(); requiresRecalcBoxes();
SpatiallyNestable::locationChanged(); // tell all the children, also SpatiallyNestable::locationChanged(); // tell all the children, also

View file

@ -161,11 +161,10 @@ public:
// attributes applicable to all entity types // attributes applicable to all entity types
EntityTypes::EntityType getType() const { return _type; } 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); void setCenterPosition(const glm::vec3& position);
const Transform getTransformToCenter() const; const Transform getTransformToCenter(bool& success) const;
void setTranformToCenter(const Transform& transform);
inline void requiresRecalcBoxes() { _recalcAABox = true; _recalcMinAACube = true; _recalcMaxAACube = true; } inline void requiresRecalcBoxes() { _recalcAABox = true; _recalcMinAACube = true; _recalcMaxAACube = true; }
@ -232,11 +231,12 @@ public:
quint64 getExpiry() const; quint64 getExpiry() const;
// position, size, and bounds related helpers // position, size, and bounds related helpers
const AACube& getMaximumAACube() const; const AACube& getMaximumAACube(bool& success) const;
const AACube& getMinimumAACube() const; const AACube& getMinimumAACube(bool& success) const;
const AABox& getAABox() const; /// axis aligned bounding box in world-frame (meters) 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; } const QString& getScript() const { return _script; }
void setScript(const QString& value) { _script = value; } void setScript(const QString& value) { _script = value; }
@ -381,8 +381,8 @@ public:
QList<EntityActionPointer> getActionsOfType(EntityActionType typeToGet); QList<EntityActionPointer> getActionsOfType(EntityActionType typeToGet);
// these are in the frame of this object // these are in the frame of this object
virtual glm::quat getAbsoluteJointRotationInObjectFrame(int index) const override { return glm::quat(); } virtual glm::quat getAbsoluteJointRotationInObjectFrame(int index) const override;
virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const override { return glm::vec3(0.0f); } virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const override;
virtual void loader() {} // called indirectly when urls for geometry are updated virtual void loader() {} // called indirectly when urls for geometry are updated

View file

@ -72,12 +72,15 @@ EntityItemProperties convertLocationToScriptSemantics(const EntityItemProperties
scriptSideProperties.setLocalPosition(entitySideProperties.getPosition()); scriptSideProperties.setLocalPosition(entitySideProperties.getPosition());
scriptSideProperties.setLocalRotation(entitySideProperties.getRotation()); scriptSideProperties.setLocalRotation(entitySideProperties.getRotation());
bool success;
glm::vec3 worldPosition = SpatiallyNestable::localToWorld(entitySideProperties.getPosition(), glm::vec3 worldPosition = SpatiallyNestable::localToWorld(entitySideProperties.getPosition(),
entitySideProperties.getParentID(), entitySideProperties.getParentID(),
entitySideProperties.getParentJointIndex()); entitySideProperties.getParentJointIndex(),
success);
glm::quat worldRotation = SpatiallyNestable::localToWorld(entitySideProperties.getRotation(), glm::quat worldRotation = SpatiallyNestable::localToWorld(entitySideProperties.getRotation(),
entitySideProperties.getParentID(), entitySideProperties.getParentID(),
entitySideProperties.getParentJointIndex()); entitySideProperties.getParentJointIndex(),
success);
scriptSideProperties.setPosition(worldPosition); scriptSideProperties.setPosition(worldPosition);
scriptSideProperties.setRotation(worldRotation); 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 // 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. // are set. If they are set, they overwrite position and rotation.
EntityItemProperties entitySideProperties = scriptSideProperties; EntityItemProperties entitySideProperties = scriptSideProperties;
bool success;
if (scriptSideProperties.localPositionChanged()) { if (scriptSideProperties.localPositionChanged()) {
entitySideProperties.setPosition(scriptSideProperties.getLocalPosition()); entitySideProperties.setPosition(scriptSideProperties.getLocalPosition());
} else if (scriptSideProperties.positionChanged()) { } else if (scriptSideProperties.positionChanged()) {
glm::vec3 localPosition = SpatiallyNestable::worldToLocal(entitySideProperties.getPosition(), glm::vec3 localPosition = SpatiallyNestable::worldToLocal(entitySideProperties.getPosition(),
entitySideProperties.getParentID(), entitySideProperties.getParentID(),
entitySideProperties.getParentJointIndex()); entitySideProperties.getParentJointIndex(),
success);
entitySideProperties.setPosition(localPosition); entitySideProperties.setPosition(localPosition);
} }
@ -104,7 +109,8 @@ EntityItemProperties convertLocationFromScriptSemantics(const EntityItemProperti
} else if (scriptSideProperties.rotationChanged()) { } else if (scriptSideProperties.rotationChanged()) {
glm::quat localRotation = SpatiallyNestable::worldToLocal(entitySideProperties.getRotation(), glm::quat localRotation = SpatiallyNestable::worldToLocal(entitySideProperties.getRotation(),
entitySideProperties.getParentID(), entitySideProperties.getParentID(),
entitySideProperties.getParentJointIndex()); entitySideProperties.getParentJointIndex(),
success);
entitySideProperties.setRotation(localRotation); entitySideProperties.setRotation(localRotation);
} }

View file

@ -119,8 +119,9 @@ void EntitySimulation::sortEntitiesThatMoved() {
while (itemItr != _entitiesToSort.end()) { while (itemItr != _entitiesToSort.end()) {
EntityItemPointer entity = *itemItr; EntityItemPointer entity = *itemItr;
// check to see if this movement has sent the entity outside of the domain. // check to see if this movement has sent the entity outside of the domain.
AACube newCube = entity->getQueryAACube(); bool success;
if (!domainBounds.touches(newCube)) { AACube newCube = entity->getQueryAACube(success);
if (success && !domainBounds.touches(newCube)) {
qCDebug(entities) << "Entity " << entity->getEntityItemID() << " moved out of domain bounds."; qCDebug(entities) << "Entity " << entity->getEntityItemID() << " moved out of domain bounds.";
_entitiesToDelete.insert(entity); _entitiesToDelete.insert(entity);
_mortalEntities.remove(entity); _mortalEntities.remove(entity);
@ -200,8 +201,9 @@ void EntitySimulation::changeEntity(EntityItemPointer entity) {
uint32_t dirtyFlags = entity->getDirtyFlags(); uint32_t dirtyFlags = entity->getDirtyFlags();
if (dirtyFlags & Simulation::DIRTY_POSITION) { if (dirtyFlags & Simulation::DIRTY_POSITION) {
AACube domainBounds(glm::vec3((float)-HALF_TREE_SCALE), (float)TREE_SCALE); AACube domainBounds(glm::vec3((float)-HALF_TREE_SCALE), (float)TREE_SCALE);
AACube newCube = entity->getQueryAACube(); bool success;
if (!domainBounds.touches(newCube)) { AACube newCube = entity->getQueryAACube(success);
if (success && !domainBounds.touches(newCube)) {
qCDebug(entities) << "Entity " << entity->getEntityItemID() << " moved out of domain bounds."; qCDebug(entities) << "Entity " << entity->getEntityItemID() << " moved out of domain bounds.";
_entitiesToDelete.insert(entity); _entitiesToDelete.insert(entity);
_mortalEntities.remove(entity); _mortalEntities.remove(entity);

View file

@ -141,7 +141,12 @@ bool EntityTree::updateEntityWithElement(EntityItemPointer entity, const EntityI
EntityItemProperties tempProperties; EntityItemProperties tempProperties;
tempProperties.setLocked(wantsLocked); 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); recurseTreeWithOperator(&theOperator);
entity->setProperties(tempProperties); entity->setProperties(tempProperties);
_isDirty = true; _isDirty = true;
@ -230,9 +235,15 @@ bool EntityTree::updateEntityWithElement(EntityItemPointer entity, const EntityI
if (!containingElement) { if (!containingElement) {
continue; continue;
} }
UpdateEntityOperator theChildOperator(getThisPointer(),
containingElement, bool success;
childEntity, childEntity->getQueryAACube()); 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); recurseTreeWithOperator(&theChildOperator);
foreach (SpatiallyNestablePointer childChild, childEntity->getChildren()) { foreach (SpatiallyNestablePointer childChild, childEntity->getChildren()) {
if (childChild && childChild->getNestableType() == NestableType::Entity) { if (childChild && childChild->getNestableType() == NestableType::Entity) {

View file

@ -302,8 +302,9 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData
// simulation changing what's visible. consider the case where the entity contains an angular velocity // 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 // 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. // frustum culling on rendering.
AACube entityCube = entity->getQueryAACube(); bool success;
if (params.viewFrustum->cubeInFrustum(entityCube) == ViewFrustum::OUTSIDE) { AACube entityCube = entity->getQueryAACube(success);
if (!success || params.viewFrustum->cubeInFrustum(entityCube) == ViewFrustum::OUTSIDE) {
includeThisEntity = false; // out of view, don't include it includeThisEntity = false; // out of view, don't include it
} }
} }
@ -413,11 +414,21 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData
} }
bool EntityTreeElement::containsEntityBounds(EntityItemPointer entity) const { 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 { 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 { 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, bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching,
OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal,
const QVector<EntityItemID>& entityIdsToInclude, void** intersectedObject, bool precisionPicking, float distanceToElementCube) { const QVector<EntityItemID>& entityIdsToInclude, void** intersectedObject,
bool precisionPicking, float distanceToElementCube) {
// only called if we do intersect our bounding cube, but find if we actually intersect with entities... // only called if we do intersect our bounding cube, but find if we actually intersect with entities...
int entityNumber = 0; int entityNumber = 0;
@ -526,7 +538,12 @@ bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, con
return; return;
} }
AABox entityBox = entity->getAABox(); bool success;
AABox entityBox = entity->getAABox(success);
if (!success) {
return;
}
float localDistance; float localDistance;
BoxFace localFace; BoxFace localFace;
glm::vec3 localSurfaceNormal; glm::vec3 localSurfaceNormal;
@ -631,11 +648,12 @@ EntityItemPointer EntityTreeElement::getClosestEntity(glm::vec3 position) const
void EntityTreeElement::getEntities(const glm::vec3& searchPosition, float searchRadius, QVector<EntityItemPointer>& foundEntities) const { void EntityTreeElement::getEntities(const glm::vec3& searchPosition, float searchRadius, QVector<EntityItemPointer>& foundEntities) const {
forEachEntity([&](EntityItemPointer entity) { 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 // if the sphere doesn't intersect with our world frame AABox, we don't need to consider the more complex case
glm::vec3 penetration; glm::vec3 penetration;
if (entityBox.findSpherePenetration(searchPosition, searchRadius, penetration)) { if (success && entityBox.findSpherePenetration(searchPosition, searchRadius, penetration)) {
glm::vec3 dimensions = entity->getDimensions(); 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 // maximum bounding sphere, which is actually larger than our actual radius
float entityTrueRadius = dimensions.x / 2.0f; float entityTrueRadius = dimensions.x / 2.0f;
if (findSphereSpherePenetration(searchPosition, searchRadius, bool success;
entity->getCenterPosition(), entityTrueRadius, penetration)) { if (findSphereSpherePenetration(searchPosition, searchRadius,
foundEntities.push_back(entity); entity->getCenterPosition(success), entityTrueRadius, penetration)) {
if (success) {
foundEntities.push_back(entity);
}
} }
} else { } else {
// determine the worldToEntityMatrix that doesn't include scale because // 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<EntityItemPointer>& foundEntities) { void EntityTreeElement::getEntities(const AACube& cube, QVector<EntityItemPointer>& foundEntities) {
forEachEntity([&](EntityItemPointer entity) { forEachEntity([&](EntityItemPointer entity) {
AABox entityBox = entity->getAABox(); bool success;
AABox entityBox = entity->getAABox(success);
// FIXME - handle entity->getShapeType() == SHAPE_TYPE_SPHERE case better // FIXME - handle entity->getShapeType() == SHAPE_TYPE_SPHERE case better
// FIXME - consider allowing the entity to determine penetration so that // FIXME - consider allowing the entity to determine penetration so that
// entities could presumably dull actuall hull testing if they wanted to // entities could presumably dull actuall hull testing if they wanted to
@ -693,10 +715,10 @@ void EntityTreeElement::getEntities(const AACube& cube, QVector<EntityItemPointe
// test the triangles of the face against the box? // test the triangles of the face against the box?
// if translated search face triangle intersect target box // if translated search face triangle intersect target box
// add to result // add to result
// //
// If the entities AABox touches the search cube then consider it to be found // If the entities AABox touches the search cube then consider it to be found
if (entityBox.touches(cube)) { if (success && entityBox.touches(cube)) {
foundEntities.push_back(entity); foundEntities.push_back(entity);
} }
}); });
@ -704,7 +726,8 @@ void EntityTreeElement::getEntities(const AACube& cube, QVector<EntityItemPointe
void EntityTreeElement::getEntities(const AABox& box, QVector<EntityItemPointer>& foundEntities) { void EntityTreeElement::getEntities(const AABox& box, QVector<EntityItemPointer>& foundEntities) {
forEachEntity([&](EntityItemPointer entity) { forEachEntity([&](EntityItemPointer entity) {
AABox entityBox = entity->getAABox(); bool success;
AABox entityBox = entity->getAABox(success);
// FIXME - handle entity->getShapeType() == SHAPE_TYPE_SPHERE case better // FIXME - handle entity->getShapeType() == SHAPE_TYPE_SPHERE case better
// FIXME - consider allowing the entity to determine penetration so that // FIXME - consider allowing the entity to determine penetration so that
// entities could presumably dull actuall hull testing if they wanted to // entities could presumably dull actuall hull testing if they wanted to
@ -718,10 +741,10 @@ void EntityTreeElement::getEntities(const AABox& box, QVector<EntityItemPointer>
// test the triangles of the face against the box? // test the triangles of the face against the box?
// if translated search face triangle intersect target box // if translated search face triangle intersect target box
// add to result // add to result
// //
// If the entities AABox touches the search cube then consider it to be found // 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); foundEntities.push_back(entity);
} }
}); });
@ -940,7 +963,11 @@ bool EntityTreeElement::pruneChildren() {
void EntityTreeElement::expandExtentsToContents(Extents& extents) { void EntityTreeElement::expandExtentsToContents(Extents& extents) {
withReadLock([&] { withReadLock([&] {
foreach(EntityItemPointer entity, _entityItems) { foreach(EntityItemPointer entity, _entityItems) {
extents.add(entity->getAABox()); bool success;
AABox aaBox = entity->getAABox(success);
if (success) {
extents.add(aaBox);
}
} }
}); });
} }

View file

@ -110,7 +110,11 @@ bool SphereEntityItem::findDetailedRayIntersection(const glm::vec3& origin, cons
// then translate back to work coordinates // then translate back to work coordinates
glm::vec3 hitAt = glm::vec3(entityToWorldMatrix * glm::vec4(entityFrameHitAt, 1.0f)); glm::vec3 hitAt = glm::vec3(entityToWorldMatrix * glm::vec4(entityFrameHitAt, 1.0f));
distance = glm::distance(origin, hitAt); 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 true;
} }
return false; return false;

View file

@ -31,7 +31,7 @@ public:
SpatialParentFinder() { } SpatialParentFinder() { }
virtual ~SpatialParentFinder() { } virtual ~SpatialParentFinder() { }
virtual SpatiallyNestableWeakPointer find(QUuid parentID) const = 0; virtual SpatiallyNestableWeakPointer find(QUuid parentID, bool& success) const = 0;
}; };
#endif // hifi_SpatialParentFinder_h #endif // hifi_SpatialParentFinder_h

View file

@ -24,21 +24,25 @@ SpatiallyNestable::SpatiallyNestable(NestableType nestableType, QUuid id) :
_transform.setRotation(glm::quat()); _transform.setRotation(glm::quat());
} }
Transform SpatiallyNestable::getParentTransform() const { Transform SpatiallyNestable::getParentTransform(bool& success) const {
Transform result; Transform result;
SpatiallyNestablePointer parent = getParentPointer(); SpatiallyNestablePointer parent = getParentPointer(success);
if (!success) {
return result;
}
if (parent) { if (parent) {
Transform parentTransform = parent->getTransform(_parentJointIndex); Transform parentTransform = parent->getTransform(_parentJointIndex, success);
result = parentTransform.setScale(1.0f); result = parentTransform.setScale(1.0f); // TODO: scaling
} }
return result; return result;
} }
SpatiallyNestablePointer SpatiallyNestable::getParentPointer() const { SpatiallyNestablePointer SpatiallyNestable::getParentPointer(bool& success) const {
SpatiallyNestablePointer parent = _parent.lock(); SpatiallyNestablePointer parent = _parent.lock();
if (!parent && _parentID.isNull()) { if (!parent && _parentID.isNull()) {
// no parent // no parent
success = true;
return nullptr; return nullptr;
} }
@ -48,6 +52,7 @@ SpatiallyNestablePointer SpatiallyNestable::getParentPointer() const {
parent->beParentOfChild(getThisPointer()); parent->beParentOfChild(getThisPointer());
_parentKnowsMe = true; _parentKnowsMe = true;
} }
success = true;
return parent; 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 // we have a _parentID but no parent pointer, or our parent pointer was to the wrong thing
QSharedPointer<SpatialParentFinder> parentFinder = DependencyManager::get<SpatialParentFinder>(); QSharedPointer<SpatialParentFinder> parentFinder = DependencyManager::get<SpatialParentFinder>();
if (!parentFinder) { if (!parentFinder) {
success = false;
return nullptr; return nullptr;
} }
_parent = parentFinder->find(_parentID); _parent = parentFinder->find(_parentID, success);
if (!success) {
return nullptr;
}
parent = _parent.lock(); parent = _parent.lock();
if (parent) { if (parent) {
parent->beParentOfChild(thisPointer); parent->beParentOfChild(thisPointer);
@ -73,7 +83,9 @@ SpatiallyNestablePointer SpatiallyNestable::getParentPointer() const {
} }
if (parent || _parentID.isNull()) { if (parent || _parentID.isNull()) {
thisPointer->parentChanged(); success = true;
} else {
success = false;
} }
return parent; return parent;
@ -96,136 +108,245 @@ void SpatiallyNestable::setParentID(const QUuid& parentID) {
_parentID = parentID; _parentID = parentID;
_parentKnowsMe = false; _parentKnowsMe = false;
} }
parentChanged();
} }
void SpatiallyNestable::setParentJointIndex(quint16 parentJointIndex) { void SpatiallyNestable::setParentJointIndex(quint16 parentJointIndex) {
_parentJointIndex = parentJointIndex; _parentJointIndex = parentJointIndex;
} }
glm::vec3 SpatiallyNestable::worldToLocal(const glm::vec3& position,
glm::vec3 SpatiallyNestable::worldToLocal(const glm::vec3& position, const QUuid& parentID, int parentJointIndex) { const QUuid& parentID, int parentJointIndex,
bool& success) {
Transform result;
QSharedPointer<SpatialParentFinder> parentFinder = DependencyManager::get<SpatialParentFinder>(); QSharedPointer<SpatialParentFinder> parentFinder = DependencyManager::get<SpatialParentFinder>();
Transform parentTransform; if (!parentFinder) {
if (parentFinder) { success = false;
auto parentWP = parentFinder->find(parentID); return glm::vec3(0.0f);
auto parent = parentWP.lock();
if (parent) {
parentTransform = parent->getTransform(parentJointIndex);
parentTransform.setScale(1.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; Transform positionTransform;
positionTransform.setTranslation(position); positionTransform.setTranslation(position);
Transform myWorldTransform; Transform myWorldTransform;
Transform::mult(myWorldTransform, parentTransform, positionTransform); Transform::mult(myWorldTransform, parentTransform, positionTransform);
myWorldTransform.setTranslation(position); myWorldTransform.setTranslation(position);
Transform result;
Transform::inverseMult(result, parentTransform, myWorldTransform); Transform::inverseMult(result, parentTransform, myWorldTransform);
return result.getTranslation(); 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<SpatialParentFinder> parentFinder = DependencyManager::get<SpatialParentFinder>(); QSharedPointer<SpatialParentFinder> parentFinder = DependencyManager::get<SpatialParentFinder>();
Transform parentTransform; if (!parentFinder) {
if (parentFinder) { success = false;
auto parentWP = parentFinder->find(parentID); return glm::quat();
auto parent = parentWP.lock();
if (parent) {
parentTransform = parent->getTransform(parentJointIndex);
parentTransform.setScale(1.0f);
}
} }
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; Transform orientationTransform;
orientationTransform.setRotation(orientation); orientationTransform.setRotation(orientation);
Transform myWorldTransform; Transform myWorldTransform;
Transform::mult(myWorldTransform, parentTransform, orientationTransform); Transform::mult(myWorldTransform, parentTransform, orientationTransform);
myWorldTransform.setRotation(orientation); myWorldTransform.setRotation(orientation);
Transform result;
Transform::inverseMult(result, parentTransform, myWorldTransform); Transform::inverseMult(result, parentTransform, myWorldTransform);
return result.getRotation(); 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<SpatialParentFinder> parentFinder = DependencyManager::get<SpatialParentFinder>(); QSharedPointer<SpatialParentFinder> parentFinder = DependencyManager::get<SpatialParentFinder>();
Transform parentTransform; if (!parentFinder) {
if (parentFinder) { success = false;
auto parentWP = parentFinder->find(parentID); return glm::vec3(0.0f);
auto parent = parentWP.lock();
if (parent) {
parentTransform = parent->getTransform(parentJointIndex);
parentTransform.setScale(1.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; Transform positionTransform;
positionTransform.setTranslation(position); positionTransform.setTranslation(position);
Transform result;
Transform::mult(result, parentTransform, positionTransform); Transform::mult(result, parentTransform, positionTransform);
return result.getTranslation(); 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<SpatialParentFinder> parentFinder = DependencyManager::get<SpatialParentFinder>(); QSharedPointer<SpatialParentFinder> parentFinder = DependencyManager::get<SpatialParentFinder>();
Transform parentTransform; if (!parentFinder) {
if (parentFinder) { success = false;
auto parentWP = parentFinder->find(parentID); return glm::quat();
auto parent = parentWP.lock();
if (parent) {
parentTransform = parent->getTransform(parentJointIndex);
parentTransform.setScale(1.0f);
}
} }
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; Transform orientationTransform;
orientationTransform.setRotation(orientation); orientationTransform.setRotation(orientation);
Transform result;
Transform::mult(result, parentTransform, orientationTransform); Transform::mult(result, parentTransform, orientationTransform);
return result.getRotation(); return result.getRotation();
} }
glm::vec3 SpatiallyNestable::getPosition(bool& success) const {
return getTransform(success).getTranslation();
}
glm::vec3 SpatiallyNestable::getPosition() const { 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 { glm::vec3 SpatiallyNestable::getPosition(int jointIndex, bool& success) const {
return getTransform(jointIndex).getTranslation(); return getTransform(jointIndex, success).getTranslation();
} }
void SpatiallyNestable::setPosition(const glm::vec3& position) { void SpatiallyNestable::setPosition(const glm::vec3& position, bool& success) {
Transform parentTransform = getParentTransform(); Transform parentTransform = getParentTransform(success);
Transform myWorldTransform; Transform myWorldTransform;
_transformLock.withWriteLock([&] { _transformLock.withWriteLock([&] {
Transform::mult(myWorldTransform, parentTransform, _transform); Transform::mult(myWorldTransform, parentTransform, _transform);
myWorldTransform.setTranslation(position); myWorldTransform.setTranslation(position);
Transform::inverseMult(_transform, parentTransform, myWorldTransform); 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 { 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 { glm::quat SpatiallyNestable::getOrientation(int jointIndex, bool& success) const {
return getTransform(jointIndex).getRotation(); return getTransform(jointIndex, success).getRotation();
} }
void SpatiallyNestable::setOrientation(const glm::quat& orientation) { void SpatiallyNestable::setOrientation(const glm::quat& orientation, bool& success) {
Transform parentTransform = getParentTransform(); Transform parentTransform = getParentTransform(success);
Transform myWorldTransform; Transform myWorldTransform;
_transformLock.withWriteLock([&] { _transformLock.withWriteLock([&] {
Transform::mult(myWorldTransform, parentTransform, _transform); Transform::mult(myWorldTransform, parentTransform, _transform);
myWorldTransform.setRotation(orientation); myWorldTransform.setRotation(orientation);
Transform::inverseMult(_transform, parentTransform, myWorldTransform); 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 // return a world-space transform for this object's location
Transform parentTransform = getParentTransform(); Transform parentTransform = getParentTransform(success);
Transform result; Transform result;
_transformLock.withReadLock([&] { _transformLock.withReadLock([&] {
Transform::mult(result, parentTransform, _transform); Transform::mult(result, parentTransform, _transform);
@ -233,25 +354,34 @@ const Transform SpatiallyNestable::getTransform() const {
return result; 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 // 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. // 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 jointInWorldFrame;
Transform worldTransform = getTransform(success);
if (!success) {
return jointInWorldFrame;
}
Transform jointInObjectFrame = getAbsoluteJointTransformInObjectFrame(jointIndex);
Transform::mult(jointInWorldFrame, worldTransform, jointInObjectFrame); Transform::mult(jointInWorldFrame, worldTransform, jointInObjectFrame);
success = true;
return jointInWorldFrame; return jointInWorldFrame;
} }
void SpatiallyNestable::setTransform(const Transform& transform) { void SpatiallyNestable::setTransform(const Transform& transform, bool& success) {
Transform parentTransform = getParentTransform(); Transform parentTransform = getParentTransform(success);
_transformLock.withWriteLock([&] { _transformLock.withWriteLock([&] {
Transform::inverseMult(_transform, parentTransform, transform); Transform::inverseMult(_transform, parentTransform, transform);
}); });
locationChanged(); if (success) {
locationChanged();
}
} }
glm::vec3 SpatiallyNestable::getScale() const { glm::vec3 SpatiallyNestable::getScale() const {
// TODO: scale
glm::vec3 result; glm::vec3 result;
_transformLock.withReadLock([&] { _transformLock.withReadLock([&] {
result = _transform.getScale(); result = _transform.getScale();
@ -260,11 +390,12 @@ glm::vec3 SpatiallyNestable::getScale() const {
} }
glm::vec3 SpatiallyNestable::getScale(int jointIndex) const { glm::vec3 SpatiallyNestable::getScale(int jointIndex) const {
// XXX ... something with joints // TODO: scale
return getScale(); return getScale();
} }
void SpatiallyNestable::setScale(const glm::vec3& scale) { void SpatiallyNestable::setScale(const glm::vec3& scale) {
// TODO: scale
_transformLock.withWriteLock([&] { _transformLock.withWriteLock([&] {
_transform.setScale(scale); _transform.setScale(scale);
}); });
@ -317,6 +448,7 @@ void SpatiallyNestable::setLocalOrientation(const glm::quat& orientation) {
} }
glm::vec3 SpatiallyNestable::getLocalScale() const { glm::vec3 SpatiallyNestable::getLocalScale() const {
// TODO: scale
glm::vec3 result; glm::vec3 result;
_transformLock.withReadLock([&] { _transformLock.withReadLock([&] {
result = _transform.getScale(); result = _transform.getScale();
@ -325,6 +457,7 @@ glm::vec3 SpatiallyNestable::getLocalScale() const {
} }
void SpatiallyNestable::setLocalScale(const glm::vec3& scale) { void SpatiallyNestable::setLocalScale(const glm::vec3& scale) {
// TODO: scale
_transformLock.withWriteLock([&] { _transformLock.withWriteLock([&] {
_transform.setScale(scale); _transform.setScale(scale);
}); });
@ -353,6 +486,16 @@ const Transform SpatiallyNestable::getAbsoluteJointTransformInObjectFrame(int jo
return jointTransformInObjectFrame; 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 { SpatiallyNestablePointer SpatiallyNestable::getThisPointer() const {
SpatiallyNestableConstPointer constThisPointer = shared_from_this(); SpatiallyNestableConstPointer constThisPointer = shared_from_this();
SpatiallyNestablePointer thisPointer = std::const_pointer_cast<SpatiallyNestable>(constThisPointer); // ermahgerd !!! SpatiallyNestablePointer thisPointer = std::const_pointer_cast<SpatiallyNestable>(constThisPointer); // ermahgerd !!!
@ -391,10 +534,19 @@ void SpatiallyNestable::setQueryAACube(const AACube& queryAACube) {
_queryAACubeSet = true; _queryAACubeSet = true;
} }
AACube SpatiallyNestable::getQueryAACube() const { AACube SpatiallyNestable::getQueryAACube(bool& success) const {
if (!_queryAACubeSet) { if (_queryAACubeSet) {
_queryAACube = AACube(getPosition() - glm::vec3(0.5f), 1.0f); // XXX success = true;
_queryAACubeSet = 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;
} }

View file

@ -45,34 +45,39 @@ public:
virtual quint16 getParentJointIndex() const { return _parentJointIndex; } virtual quint16 getParentJointIndex() const { return _parentJointIndex; }
virtual void setParentJointIndex(quint16 parentJointIndex); virtual void setParentJointIndex(quint16 parentJointIndex);
static glm::vec3 worldToLocal(const glm::vec3& position, 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); 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::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); static glm::quat localToWorld(const glm::quat& orientation, const QUuid& parentID, int parentJointIndex, bool& success);
// world frame // world frame
virtual const Transform getTransform() const; virtual const Transform getTransform(bool& success) const;
virtual void setTransform(const Transform& transform); 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 glm::vec3 getPosition() const;
virtual void setPosition(const glm::vec3& position, bool& success);
virtual void setPosition(const glm::vec3& position); virtual void setPosition(const glm::vec3& position);
virtual glm::quat getOrientation(bool& success) const;
virtual glm::quat getOrientation() 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 setOrientation(const glm::quat& orientation);
virtual void setQueryAACube(const AACube& queryAACube); virtual void setQueryAACube(const AACube& queryAACube);
virtual AACube getQueryAACube(bool& success) const;
virtual AACube getQueryAACube() const; virtual AACube getQueryAACube() const;
virtual glm::vec3 getScale() const; virtual glm::vec3 getScale() const;
virtual void setScale(const glm::vec3& scale); virtual void setScale(const glm::vec3& scale);
// get world-frame values for a specific joint // get world-frame values for a specific joint
virtual const Transform getTransform(int jointIndex) const; virtual const Transform getTransform(int jointIndex, bool& success) const;
virtual glm::vec3 getPosition(int jointIndex) const; virtual glm::vec3 getPosition(int jointIndex, bool& success) const;
virtual glm::vec3 getScale(int jointIndex) const; virtual glm::vec3 getScale(int jointIndex) const;
// object's parent's frame // object's parent's frame
@ -93,8 +98,8 @@ public:
// this object's frame // this object's frame
virtual const Transform getAbsoluteJointTransformInObjectFrame(int jointIndex) const; virtual const Transform getAbsoluteJointTransformInObjectFrame(int jointIndex) const;
virtual glm::quat getAbsoluteJointRotationInObjectFrame(int index) const { assert(false); return glm::quat(); } virtual glm::quat getAbsoluteJointRotationInObjectFrame(int index) const;
virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const { assert(false); return glm::vec3(); } virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const;
SpatiallyNestablePointer getThisPointer() const; SpatiallyNestablePointer getThisPointer() const;
@ -103,7 +108,7 @@ protected:
QUuid _id; QUuid _id;
QUuid _parentID; // what is this thing's transform relative to? QUuid _parentID; // what is this thing's transform relative to?
quint16 _parentJointIndex { 0 }; // which joint of the parent is this 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; mutable SpatiallyNestableWeakPointer _parent;
virtual void beParentOfChild(SpatiallyNestablePointer newChild) const; virtual void beParentOfChild(SpatiallyNestablePointer newChild) const;
@ -112,7 +117,6 @@ protected:
mutable ReadWriteLockable _childrenLock; mutable ReadWriteLockable _childrenLock;
mutable QHash<QUuid, SpatiallyNestableWeakPointer> _children; mutable QHash<QUuid, SpatiallyNestableWeakPointer> _children;
virtual void parentChanged() {} // called when parent pointer is updated
virtual void locationChanged(); // called when a this object's location has changed virtual void locationChanged(); // called when a this object's location has changed
virtual void dimensionsChanged() {} // called when a this object's dimensions have changed virtual void dimensionsChanged() {} // called when a this object's dimensions have changed