mirror of
https://github.com/overte-org/overte.git
synced 2025-04-08 09:33:49 +02:00
Implement Entities.findInFrustum() method
This commit is contained in:
parent
ce58edc4e0
commit
38c2efa22f
8 changed files with 148 additions and 12 deletions
|
@ -21,6 +21,7 @@
|
|||
#include "EntityTree.h"
|
||||
#include "LightEntityItem.h"
|
||||
#include "ModelEntityItem.h"
|
||||
#include "QVariantGLM.h"
|
||||
#include "SimulationOwner.h"
|
||||
#include "ZoneEntityItem.h"
|
||||
|
||||
|
@ -550,14 +551,6 @@ QVector<QUuid> EntityScriptingInterface::findEntities(const glm::vec3& center, f
|
|||
return result;
|
||||
}
|
||||
|
||||
QVector<QUuid> EntityScriptingInterface::findEntitiesInView(const glm::vec3& center, float radius) const {
|
||||
QVector<QUuid> result;
|
||||
|
||||
// TODO
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
QVector<QUuid> EntityScriptingInterface::findEntitiesInBox(const glm::vec3& corner, const glm::vec3& dimensions) const {
|
||||
QVector<QUuid> result;
|
||||
if (_entityTree) {
|
||||
|
@ -574,6 +567,48 @@ QVector<QUuid> EntityScriptingInterface::findEntitiesInBox(const glm::vec3& corn
|
|||
return result;
|
||||
}
|
||||
|
||||
QVector<QUuid> EntityScriptingInterface::findEntitiesInFrustum(QVariantMap frustum) const {
|
||||
QVector<QUuid> result;
|
||||
|
||||
const QString POSITION_PROPERTY = "position";
|
||||
bool positionOK = frustum.contains(POSITION_PROPERTY);
|
||||
glm::vec3 position = positionOK ? qMapToGlmVec3(frustum[POSITION_PROPERTY]) : glm::vec3();
|
||||
|
||||
const QString ORIENTATION_PROPERTY = "orientation";
|
||||
bool orientationOK = frustum.contains(ORIENTATION_PROPERTY);
|
||||
glm::quat orientation = orientationOK ? qMapToGlmQuat(frustum[ORIENTATION_PROPERTY]) : glm::quat();
|
||||
|
||||
const QString PROJECTION_PROPERTY = "projection";
|
||||
bool projectionOK = frustum.contains(PROJECTION_PROPERTY);
|
||||
glm::mat4 projection = projectionOK ? qMapToGlmMat4(frustum[PROJECTION_PROPERTY]) : glm::mat4();
|
||||
|
||||
const QString CENTER_RADIUS_PROPERTY = "centerRadius";
|
||||
bool centerRadiusOK = frustum.contains(CENTER_RADIUS_PROPERTY);
|
||||
float centerRadius = centerRadiusOK ? frustum[CENTER_RADIUS_PROPERTY].toFloat() : 0.0f;
|
||||
|
||||
if (positionOK && orientationOK && projectionOK && centerRadiusOK) {
|
||||
ViewFrustum viewFrustum;
|
||||
viewFrustum.setPosition(position);
|
||||
viewFrustum.setOrientation(orientation);
|
||||
viewFrustum.setProjection(projection);
|
||||
viewFrustum.setCenterRadius(centerRadius);
|
||||
viewFrustum.calculate();
|
||||
|
||||
if (_entityTree) {
|
||||
QVector<EntityItemPointer> entities;
|
||||
_entityTree->withReadLock([&] {
|
||||
_entityTree->findEntities(viewFrustum, entities);
|
||||
});
|
||||
|
||||
foreach(EntityItemPointer entity, entities) {
|
||||
result << entity->getEntityItemID();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
RayToEntityIntersectionResult EntityScriptingInterface::findRayIntersection(const PickRay& ray, bool precisionPicking,
|
||||
const QScriptValue& entityIdsToInclude, const QScriptValue& entityIdsToDiscard) {
|
||||
|
||||
|
|
|
@ -127,14 +127,19 @@ public slots:
|
|||
/// this function will not find any models in script engine contexts which don't have access to models
|
||||
Q_INVOKABLE QVector<QUuid> findEntities(const glm::vec3& center, float radius) const;
|
||||
|
||||
/// finds models within the search sphere specified by the center point and radius
|
||||
/// this function will not find any models in script engine contexts which don't have access to models
|
||||
Q_INVOKABLE QVector<QUuid> findEntitiesInView(const glm::vec3& center, float radius) const;
|
||||
|
||||
/// finds models within the box specified by the corner and dimensions
|
||||
/// this function will not find any models in script engine contexts which don't have access to models
|
||||
Q_INVOKABLE QVector<QUuid> findEntitiesInBox(const glm::vec3& corner, const glm::vec3& dimensions) const;
|
||||
|
||||
/// finds models within the frustum
|
||||
/// the frustum must have the following properties:
|
||||
/// - position
|
||||
/// - orientation
|
||||
/// - projection
|
||||
/// - centerRadius
|
||||
/// this function will not find any models in script engine contexts which don't have access to models
|
||||
Q_INVOKABLE QVector<QUuid> findEntitiesInFrustum(QVariantMap frustum) const;
|
||||
|
||||
/// If the scripting context has visible entities, this will determine a ray intersection, the results
|
||||
/// may be inaccurate if the engine is unable to access the visible entities, in which case result.accurate
|
||||
/// will be false.
|
||||
|
|
|
@ -688,6 +688,31 @@ void EntityTree::findEntities(const AABox& box, QVector<EntityItemPointer>& foun
|
|||
foundEntities.swap(args._foundEntities);
|
||||
}
|
||||
|
||||
class FindInFrustumArgs {
|
||||
public:
|
||||
ViewFrustum frustum;
|
||||
QVector<EntityItemPointer> entities;
|
||||
};
|
||||
|
||||
bool EntityTree::findInFrustumOperation(OctreeElementPointer element, void* extraData) {
|
||||
FindInFrustumArgs* args = static_cast<FindInFrustumArgs*>(extraData);
|
||||
if (element->isInView(args->frustum)) {
|
||||
EntityTreeElementPointer entityTreeElement = std::static_pointer_cast<EntityTreeElement>(element);
|
||||
entityTreeElement->getEntities(args->frustum, args->entities);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// NOTE: assumes caller has handled locking
|
||||
void EntityTree::findEntities(const ViewFrustum& frustum, QVector<EntityItemPointer>& foundEntities) {
|
||||
FindInFrustumArgs args = { frustum, QVector<EntityItemPointer>() };
|
||||
// NOTE: This should use recursion, since this is a spatial operation
|
||||
recurseTreeWithOperation(findInFrustumOperation, &args);
|
||||
// swap the two lists of entity pointers instead of copy
|
||||
foundEntities.swap(args.entities);
|
||||
}
|
||||
|
||||
EntityItemPointer EntityTree::findEntityByID(const QUuid& id) {
|
||||
EntityItemID entityID(id);
|
||||
return findEntityByEntityItemID(entityID);
|
||||
|
|
|
@ -153,6 +153,11 @@ public:
|
|||
/// \remark Side effect: any initial contents in entities will be lost
|
||||
void findEntities(const AABox& box, QVector<EntityItemPointer>& foundEntities);
|
||||
|
||||
/// finds all entities within a frustum
|
||||
/// \parameter frustum the query frustum
|
||||
/// \param foundEntities[out] vector of EntityItemPointer
|
||||
void findEntities(const ViewFrustum& frustum, QVector<EntityItemPointer>& foundEntities);
|
||||
|
||||
void addNewlyCreatedHook(NewlyCreatedEntityHook* hook);
|
||||
void removeNewlyCreatedHook(NewlyCreatedEntityHook* hook);
|
||||
|
||||
|
@ -276,6 +281,7 @@ protected:
|
|||
static bool findInSphereOperation(OctreeElementPointer element, void* extraData);
|
||||
static bool findInCubeOperation(OctreeElementPointer element, void* extraData);
|
||||
static bool findInBoxOperation(OctreeElementPointer element, void* extraData);
|
||||
static bool findInFrustumOperation(OctreeElementPointer element, void* extraData);
|
||||
static bool sendEntitiesOperation(OctreeElementPointer element, void* extraData);
|
||||
|
||||
void notifyNewlyCreatedEntity(const EntityItem& newEntity, const SharedNodePointer& senderNode);
|
||||
|
|
|
@ -796,6 +796,17 @@ void EntityTreeElement::getEntities(const AABox& box, QVector<EntityItemPointer>
|
|||
});
|
||||
}
|
||||
|
||||
void EntityTreeElement::getEntities(const ViewFrustum& frustum, QVector<EntityItemPointer>& foundEntities) {
|
||||
forEachEntity([&](EntityItemPointer entity) {
|
||||
bool success;
|
||||
AABox entityBox = entity->getAABox(success);
|
||||
// FIXME - See FIXMEs for similar methods above.
|
||||
if (!success || frustum.boxIntersectsFrustum(entityBox) || frustum.boxIntersectsKeyhole(entityBox)) {
|
||||
foundEntities.push_back(entity);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
EntityItemPointer EntityTreeElement::getEntityWithEntityItemID(const EntityItemID& id) const {
|
||||
EntityItemPointer foundEntity = NULL;
|
||||
withReadLock([&] {
|
||||
|
|
|
@ -194,6 +194,11 @@ public:
|
|||
/// \param entities[out] vector of non-const EntityItemPointer
|
||||
void getEntities(const AABox& box, QVector<EntityItemPointer>& foundEntities);
|
||||
|
||||
/// finds all entities that touch a frustum
|
||||
/// \param frustum the query frustum
|
||||
/// \param entities[out] vector of non-const EntityItemPointer
|
||||
void getEntities(const ViewFrustum& frustum, QVector<EntityItemPointer>& foundEntities);
|
||||
|
||||
EntityItemPointer getEntityWithID(uint32_t id) const;
|
||||
EntityItemPointer getEntityWithEntityItemID(const EntityItemID& id) const;
|
||||
void getEntitiesInside(const AACube& box, QVector<EntityItemPointer>& foundEntities);
|
||||
|
|
|
@ -62,3 +62,48 @@ void qListtoRgbColor(const QVariant& q, rgbColor& returnValue) {
|
|||
returnValue[GREEN_INDEX] = qList[GREEN_INDEX].toInt();
|
||||
returnValue[BLUE_INDEX] = qList[BLUE_INDEX].toInt();
|
||||
}
|
||||
|
||||
|
||||
glm::vec3 qMapToGlmVec3(const QVariant& q) {
|
||||
QVariantMap qMap = q.toMap();
|
||||
if (qMap.contains("x") && qMap.contains("y") && qMap.contains("y")) {
|
||||
return glm::vec3(
|
||||
qMap["x"].toFloat(),
|
||||
qMap["y"].toFloat(),
|
||||
qMap["z"].toFloat()
|
||||
);
|
||||
} else {
|
||||
return glm::vec3();
|
||||
}
|
||||
}
|
||||
|
||||
glm::quat qMapToGlmQuat(const QVariant& q) {
|
||||
QVariantMap qMap = q.toMap();
|
||||
if (qMap.contains("w") && qMap.contains("x") && qMap.contains("y") && qMap.contains("z")) {
|
||||
return glm::quat(
|
||||
qMap["w"].toFloat(),
|
||||
qMap["x"].toFloat(),
|
||||
qMap["y"].toFloat(),
|
||||
qMap["z"].toFloat()
|
||||
);
|
||||
} else {
|
||||
return glm::quat();
|
||||
}
|
||||
}
|
||||
|
||||
glm::mat4 qMapToGlmMat4(const QVariant& q) {
|
||||
QVariantMap qMap = q.toMap();
|
||||
if (qMap.contains("r0c0") && qMap.contains("r1c0") && qMap.contains("r2c0") && qMap.contains("r3c0")
|
||||
&& qMap.contains("r0c1") && qMap.contains("r1c1") && qMap.contains("r2c1") && qMap.contains("r3c1")
|
||||
&& qMap.contains("r0c2") && qMap.contains("r1c2") && qMap.contains("r2c2") && qMap.contains("r3c2")
|
||||
&& qMap.contains("r0c3") && qMap.contains("r1c3") && qMap.contains("r2c3") && qMap.contains("r3c3")) {
|
||||
return glm::mat4(
|
||||
qMap["r0c0"].toFloat(), qMap["r1c0"].toFloat(), qMap["r2c0"].toFloat(), qMap["r3c0"].toFloat(),
|
||||
qMap["r0c1"].toFloat(), qMap["r1c1"].toFloat(), qMap["r2c1"].toFloat(), qMap["r3c1"].toFloat(),
|
||||
qMap["r0c2"].toFloat(), qMap["r1c2"].toFloat(), qMap["r2c2"].toFloat(), qMap["r3c2"].toFloat(),
|
||||
qMap["r0c3"].toFloat(), qMap["r1c3"].toFloat(), qMap["r2c3"].toFloat(), qMap["r3c3"].toFloat()
|
||||
);
|
||||
} else {
|
||||
return glm::mat4();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,3 +27,7 @@ QVariantMap glmToQMap(const glm::quat& glmQuat);
|
|||
glm::vec3 qListToGlmVec3(const QVariant& q);
|
||||
glm::quat qListToGlmQuat(const QVariant& q);
|
||||
void qListtoRgbColor(const QVariant& q, rgbColor& returnValue);
|
||||
|
||||
glm::vec3 qMapToGlmVec3(const QVariant& q);
|
||||
glm::quat qMapToGlmQuat(const QVariant& q);
|
||||
glm::mat4 qMapToGlmMat4(const QVariant& q);
|
||||
|
|
Loading…
Reference in a new issue