diff --git a/interface/src/raypick/CollisionPick.cpp b/interface/src/raypick/CollisionPick.cpp index 091ceb0794..b2137fc80c 100644 --- a/interface/src/raypick/CollisionPick.cpp +++ b/interface/src/raypick/CollisionPick.cpp @@ -32,9 +32,6 @@ PickResultPointer CollisionPickResult::compareAndProcessNewResult(const PickResu } intersects = entityIntersections.size() || avatarIntersections.size(); - if (newCollisionResult->loadState == LOAD_STATE_NOT_LOADED || loadState == LOAD_STATE_UNKNOWN) { - loadState = (LoadState)newCollisionResult->loadState; - } return std::make_shared(*this); } @@ -80,24 +77,29 @@ QVariantMap CollisionPickResult::toVariantMap() const { } variantMap["intersectingObjects"] = qIntersectingObjects; - variantMap["loaded"] = (loadState == LOAD_STATE_LOADED); variantMap["collisionRegion"] = pickVariant; return variantMap; } +bool CollisionPick::isLoaded() const { + return !_mathPick.shouldComputeShapeInfo() || (_cachedResource && _cachedResource->isLoaded()); +} + bool CollisionPick::getShapeInfoReady() { if (_mathPick.shouldComputeShapeInfo()) { if (_cachedResource && _cachedResource->isLoaded()) { computeShapeInfo(_mathPick, *_mathPick.shapeInfo, _cachedResource); - return true; + _mathPick.loaded = true; + } else { + _mathPick.loaded = false; } - - return false; } else { computeShapeInfoDimensionsOnly(_mathPick, *_mathPick.shapeInfo, _cachedResource); - return true; + _mathPick.loaded = true; } + + return _mathPick.loaded; } void CollisionPick::computeShapeInfoDimensionsOnly(CollisionRegion& pick, ShapeInfo& shapeInfo, QSharedPointer resource) { @@ -349,15 +351,19 @@ CollisionPick::CollisionPick(const PickFilter& filter, float maxDistance, bool e if (collisionRegion.shouldComputeShapeInfo()) { _cachedResource = DependencyManager::get()->getCollisionGeometryResource(collisionRegion.modelURL); } + _mathPick.loaded = isLoaded(); } CollisionRegion CollisionPick::getMathematicalPick() const { + CollisionRegion mathPick = _mathPick; + if (!mathPick.loaded) { + mathPick.loaded = isLoaded(); + } if (!parentTransform) { - return _mathPick; + return mathPick; } else { - CollisionRegion transformedMathPick = _mathPick; - transformedMathPick.transform = parentTransform->getTransform().worldTransform(_mathPick.transform); - return transformedMathPick; + mathPick.transform = parentTransform->getTransform().worldTransform(mathPick.transform); + return mathPick; } } @@ -385,33 +391,35 @@ void CollisionPick::filterIntersections(std::vector& intersec } PickResultPointer CollisionPick::getEntityIntersection(const CollisionRegion& pick) { - if (!getShapeInfoReady()) { + if (!pick.loaded) { // Cannot compute result - return std::make_shared(pick.toVariantMap(), CollisionPickResult::LOAD_STATE_NOT_LOADED, std::vector(), std::vector()); + return std::make_shared(pick.toVariantMap(), std::vector(), std::vector()); } + getShapeInfoReady(); auto entityIntersections = _physicsEngine->contactTest(USER_COLLISION_MASK_ENTITIES, *pick.shapeInfo, pick.transform, USER_COLLISION_GROUP_DYNAMIC, pick.threshold); filterIntersections(entityIntersections); - return std::make_shared(pick, CollisionPickResult::LOAD_STATE_LOADED, entityIntersections, std::vector()); + return std::make_shared(pick, entityIntersections, std::vector()); } PickResultPointer CollisionPick::getOverlayIntersection(const CollisionRegion& pick) { - return std::make_shared(pick, getShapeInfoReady() ? CollisionPickResult::LOAD_STATE_LOADED : CollisionPickResult::LOAD_STATE_NOT_LOADED, std::vector(), std::vector()); + return std::make_shared(pick, std::vector(), std::vector()); } PickResultPointer CollisionPick::getAvatarIntersection(const CollisionRegion& pick) { - if (!getShapeInfoReady()) { + if (!pick.loaded) { // Cannot compute result - return std::make_shared(pick, CollisionPickResult::LOAD_STATE_NOT_LOADED, std::vector(), std::vector()); + return std::make_shared(pick, std::vector(), std::vector()); } + getShapeInfoReady(); auto avatarIntersections = _physicsEngine->contactTest(USER_COLLISION_MASK_AVATARS, *pick.shapeInfo, pick.transform, USER_COLLISION_GROUP_DYNAMIC, pick.threshold); filterIntersections(avatarIntersections); - return std::make_shared(pick, CollisionPickResult::LOAD_STATE_LOADED, std::vector(), avatarIntersections); + return std::make_shared(pick, std::vector(), avatarIntersections); } PickResultPointer CollisionPick::getHUDIntersection(const CollisionRegion& pick) { - return std::make_shared(pick.toVariantMap(), getShapeInfoReady() ? CollisionPickResult::LOAD_STATE_LOADED : CollisionPickResult::LOAD_STATE_NOT_LOADED, std::vector(), std::vector()); + return std::make_shared(pick.toVariantMap(), std::vector(), std::vector()); } Transform CollisionPick::getResultTransform() const { diff --git a/interface/src/raypick/CollisionPick.h b/interface/src/raypick/CollisionPick.h index f46f0742f5..a1636e4b47 100644 --- a/interface/src/raypick/CollisionPick.h +++ b/interface/src/raypick/CollisionPick.h @@ -16,18 +16,11 @@ class CollisionPickResult : public PickResult { public: - enum LoadState { - LOAD_STATE_UNKNOWN, - LOAD_STATE_NOT_LOADED, - LOAD_STATE_LOADED - }; - CollisionPickResult() {} CollisionPickResult(const QVariantMap& pickVariant) : PickResult(pickVariant) {} - CollisionPickResult(const CollisionRegion& searchRegion, LoadState loadState, const std::vector& entityIntersections, const std::vector& avatarIntersections) : + CollisionPickResult(const CollisionRegion& searchRegion, const std::vector& entityIntersections, const std::vector& avatarIntersections) : PickResult(searchRegion.toVariantMap()), - loadState(loadState), intersects(entityIntersections.size() || avatarIntersections.size()), entityIntersections(entityIntersections), avatarIntersections(avatarIntersections) @@ -38,10 +31,8 @@ public: avatarIntersections = collisionPickResult.avatarIntersections; entityIntersections = collisionPickResult.entityIntersections; intersects = collisionPickResult.intersects; - loadState = collisionPickResult.loadState; } - LoadState loadState { LOAD_STATE_UNKNOWN }; bool intersects { false }; std::vector entityIntersections; std::vector avatarIntersections; @@ -61,7 +52,7 @@ public: CollisionRegion getMathematicalPick() const override; PickResultPointer getDefaultResult(const QVariantMap& pickVariant) const override { - return std::make_shared(pickVariant, CollisionPickResult::LOAD_STATE_UNKNOWN, std::vector(), std::vector()); + return std::make_shared(pickVariant, std::vector(), std::vector()); } PickResultPointer getEntityIntersection(const CollisionRegion& pick) override; PickResultPointer getOverlayIntersection(const CollisionRegion& pick) override; @@ -69,7 +60,9 @@ public: PickResultPointer getHUDIntersection(const CollisionRegion& pick) override; Transform getResultTransform() const override; protected: - // Returns true if pick.shapeInfo is valid. Otherwise, attempts to get the shapeInfo ready for use. + // Returns true if the resource for _mathPick.shapeInfo is loaded or if a resource is not needed. + bool isLoaded() const; + // Returns true if _mathPick.shapeInfo is valid. Otherwise, attempts to get the _mathPick ready for use. bool getShapeInfoReady(); void computeShapeInfo(CollisionRegion& pick, ShapeInfo& shapeInfo, QSharedPointer resource); void computeShapeInfoDimensionsOnly(CollisionRegion& pick, ShapeInfo& shapeInfo, QSharedPointer resource); diff --git a/interface/src/raypick/PickScriptingInterface.h b/interface/src/raypick/PickScriptingInterface.h index 717436a13b..4d99309618 100644 --- a/interface/src/raypick/PickScriptingInterface.h +++ b/interface/src/raypick/PickScriptingInterface.h @@ -152,9 +152,6 @@ public: * @property {CollisionRegion} collisionRegion The CollisionRegion that was used. Valid even if there was no intersection. */ - // TODO: Add this to the CollisionPickResult jsdoc once model collision picks are working - //* @property {boolean} loaded If the CollisionRegion was successfully loaded (may be false if a model was used) - /**jsdoc * Information about the Collision Pick's intersection with an object * diff --git a/libraries/shared/src/RegisteredMetaTypes.h b/libraries/shared/src/RegisteredMetaTypes.h index 8fefc37741..8fb1301484 100644 --- a/libraries/shared/src/RegisteredMetaTypes.h +++ b/libraries/shared/src/RegisteredMetaTypes.h @@ -253,6 +253,8 @@ public: } }; +// TODO: Add "loaded" to CollisionRegion jsdoc once model collision picks are supported. + /**jsdoc * A CollisionRegion defines a volume for checking collisions in the physics simulation. @@ -270,6 +272,7 @@ public: CollisionRegion() { } CollisionRegion(const CollisionRegion& collisionRegion) : + loaded(collisionRegion.loaded), modelURL(collisionRegion.modelURL), shapeInfo(std::make_shared()), transform(collisionRegion.transform), @@ -279,6 +282,7 @@ public: } CollisionRegion(const QVariantMap& pickVariant) { + // "loaded" is not deserialized here because there is no way to know if the shape is actually loaded if (pickVariant["shape"].isValid()) { auto shape = pickVariant["shape"].toMap(); if (!shape.empty()) { @@ -322,6 +326,7 @@ public: shape["dimensions"] = vec3toVariant(transform.getScale()); collisionRegion["shape"] = shape; + collisionRegion["loaded"] = loaded; collisionRegion["threshold"] = threshold; @@ -339,7 +344,8 @@ public: } bool operator==(const CollisionRegion& other) const { - return threshold == other.threshold && + return loaded == other.loaded && + threshold == other.threshold && glm::all(glm::equal(transform.getTranslation(), other.transform.getTranslation())) && glm::all(glm::equal(transform.getRotation(), other.transform.getRotation())) && glm::all(glm::equal(transform.getScale(), other.transform.getScale())) && @@ -359,6 +365,7 @@ public: } // We can't load the model here because it would create a circular dependency, so we delegate that responsibility to the owning CollisionPick + bool loaded = false; QUrl modelURL; // We can't compute the shapeInfo here without loading the model first, so we delegate that responsibility to the owning CollisionPick