mirror of
https://github.com/AleziaKurdis/overte.git
synced 2025-04-16 02:45:06 +02:00
added support for returning accuracy of ray intersections and other octree tests that can fail due to getting lock
This commit is contained in:
parent
8a823ee4c4
commit
4aa96e1fbe
9 changed files with 112 additions and 29 deletions
|
@ -19,6 +19,12 @@ function mouseMoveEvent(event) {
|
|||
print("computePickRay direction=" + pickRay.direction.x + ", " + pickRay.direction.y + ", " + pickRay.direction.z);
|
||||
var pickRay = Camera.computePickRay(event.x, event.y);
|
||||
var intersection = Voxels.findRayIntersection(pickRay);
|
||||
if (!intersection.accurate) {
|
||||
print(">>> NOTE: intersection not accurate. will try calling Voxels.findRayIntersectionBlocking()");
|
||||
intersection = Voxels.findRayIntersectionBlocking(pickRay);
|
||||
print(">>> AFTER BLOCKING CALL intersection.accurate=" + intersection.accurate);
|
||||
}
|
||||
|
||||
if (intersection.intersects) {
|
||||
print("intersection voxel.red/green/blue=" + intersection.voxel.red + ", "
|
||||
+ intersection.voxel.green + ", " + intersection.voxel.blue);
|
||||
|
|
|
@ -594,8 +594,9 @@ bool findRayIntersectionOp(OctreeElement* node, void* extraData) {
|
|||
}
|
||||
|
||||
bool Octree::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
OctreeElement*& node, float& distance, BoxFace& face, Octree::lockType lockType) {
|
||||
RayArgs args = { origin / (float)(TREE_SCALE), direction, node, distance, face };
|
||||
OctreeElement*& node, float& distance, BoxFace& face,
|
||||
Octree::lockType lockType, bool* accurateResult) {
|
||||
RayArgs args = { origin / (float)(TREE_SCALE), direction, node, distance, face, false};
|
||||
|
||||
bool gotLock = false;
|
||||
if (lockType == Octree::Lock) {
|
||||
|
@ -604,6 +605,9 @@ bool Octree::findRayIntersection(const glm::vec3& origin, const glm::vec3& direc
|
|||
} else if (lockType == Octree::TryLock) {
|
||||
gotLock = tryLockForRead();
|
||||
if (!gotLock) {
|
||||
if (accurateResult) {
|
||||
*accurateResult = false; // if user asked to accuracy or result, let them know this is inaccurate
|
||||
}
|
||||
return args.found; // if we wanted to tryLock, and we couldn't then just bail...
|
||||
}
|
||||
}
|
||||
|
@ -614,6 +618,9 @@ bool Octree::findRayIntersection(const glm::vec3& origin, const glm::vec3& direc
|
|||
unlock();
|
||||
}
|
||||
|
||||
if (accurateResult) {
|
||||
*accurateResult = true; // if user asked to accuracy or result, let them know this is accurate
|
||||
}
|
||||
return args.found;
|
||||
}
|
||||
|
||||
|
@ -640,7 +647,8 @@ bool findSpherePenetrationOp(OctreeElement* element, void* extraData) {
|
|||
if (element->hasContent()) {
|
||||
glm::vec3 elementPenetration;
|
||||
if (element->findSpherePenetration(args->center, args->radius, elementPenetration, &args->penetratedObject)) {
|
||||
// NOTE: it is possible for this penetration accumulation algorithm to produce a final penetration vector with zero length.
|
||||
// NOTE: it is possible for this penetration accumulation algorithm to produce a
|
||||
// final penetration vector with zero length.
|
||||
args->penetration = addPenetrations(args->penetration, elementPenetration * (float)(TREE_SCALE));
|
||||
args->found = true;
|
||||
}
|
||||
|
@ -649,7 +657,7 @@ bool findSpherePenetrationOp(OctreeElement* element, void* extraData) {
|
|||
}
|
||||
|
||||
bool Octree::findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration,
|
||||
void** penetratedObject, Octree::lockType lockType) {
|
||||
void** penetratedObject, Octree::lockType lockType, bool* accurateResult) {
|
||||
|
||||
SphereArgs args = {
|
||||
center / (float)(TREE_SCALE),
|
||||
|
@ -666,6 +674,9 @@ bool Octree::findSpherePenetration(const glm::vec3& center, float radius, glm::v
|
|||
} else if (lockType == Octree::TryLock) {
|
||||
gotLock = tryLockForRead();
|
||||
if (!gotLock) {
|
||||
if (accurateResult) {
|
||||
*accurateResult = false; // if user asked to accuracy or result, let them know this is inaccurate
|
||||
}
|
||||
return args.found; // if we wanted to tryLock, and we couldn't then just bail...
|
||||
}
|
||||
}
|
||||
|
@ -679,6 +690,9 @@ bool Octree::findSpherePenetration(const glm::vec3& center, float radius, glm::v
|
|||
unlock();
|
||||
}
|
||||
|
||||
if (accurateResult) {
|
||||
*accurateResult = true; // if user asked to accuracy or result, let them know this is accurate
|
||||
}
|
||||
return args.found;
|
||||
}
|
||||
|
||||
|
@ -741,7 +755,7 @@ bool findShapeCollisionsOp(OctreeElement* node, void* extraData) {
|
|||
}
|
||||
|
||||
bool Octree::findCapsulePenetration(const glm::vec3& start, const glm::vec3& end, float radius,
|
||||
glm::vec3& penetration, Octree::lockType lockType) {
|
||||
glm::vec3& penetration, Octree::lockType lockType, bool* accurateResult) {
|
||||
|
||||
CapsuleArgs args = {
|
||||
start / (float)(TREE_SCALE),
|
||||
|
@ -758,6 +772,9 @@ bool Octree::findCapsulePenetration(const glm::vec3& start, const glm::vec3& end
|
|||
} else if (lockType == Octree::TryLock) {
|
||||
gotLock = tryLockForRead();
|
||||
if (!gotLock) {
|
||||
if (accurateResult) {
|
||||
*accurateResult = false; // if user asked to accuracy or result, let them know this is inaccurate
|
||||
}
|
||||
return args.found; // if we wanted to tryLock, and we couldn't then just bail...
|
||||
}
|
||||
}
|
||||
|
@ -767,10 +784,15 @@ bool Octree::findCapsulePenetration(const glm::vec3& start, const glm::vec3& end
|
|||
if (gotLock) {
|
||||
unlock();
|
||||
}
|
||||
|
||||
if (accurateResult) {
|
||||
*accurateResult = true; // if user asked to accuracy or result, let them know this is accurate
|
||||
}
|
||||
return args.found;
|
||||
}
|
||||
|
||||
bool Octree::findShapeCollisions(const Shape* shape, CollisionList& collisions, Octree::lockType lockType) {
|
||||
bool Octree::findShapeCollisions(const Shape* shape, CollisionList& collisions,
|
||||
Octree::lockType lockType, bool* accurateResult) {
|
||||
|
||||
ShapeArgs args = { shape, collisions, false };
|
||||
|
||||
|
@ -781,6 +803,9 @@ bool Octree::findShapeCollisions(const Shape* shape, CollisionList& collisions,
|
|||
} else if (lockType == Octree::TryLock) {
|
||||
gotLock = tryLockForRead();
|
||||
if (!gotLock) {
|
||||
if (accurateResult) {
|
||||
*accurateResult = false; // if user asked to accuracy or result, let them know this is inaccurate
|
||||
}
|
||||
return args.found; // if we wanted to tryLock, and we couldn't then just bail...
|
||||
}
|
||||
}
|
||||
|
@ -790,6 +815,10 @@ bool Octree::findShapeCollisions(const Shape* shape, CollisionList& collisions,
|
|||
if (gotLock) {
|
||||
unlock();
|
||||
}
|
||||
|
||||
if (accurateResult) {
|
||||
*accurateResult = true; // if user asked to accuracy or result, let them know this is accurate
|
||||
}
|
||||
return args.found;
|
||||
}
|
||||
|
||||
|
@ -816,7 +845,7 @@ bool getElementEnclosingOperation(OctreeElement* element, void* extraData) {
|
|||
return true; // keep looking
|
||||
}
|
||||
|
||||
OctreeElement* Octree::getElementEnclosingPoint(const glm::vec3& point, Octree::lockType lockType) {
|
||||
OctreeElement* Octree::getElementEnclosingPoint(const glm::vec3& point, Octree::lockType lockType, bool* accurateResult) {
|
||||
GetElementEnclosingArgs args;
|
||||
args.point = point;
|
||||
args.element = NULL;
|
||||
|
@ -828,6 +857,9 @@ OctreeElement* Octree::getElementEnclosingPoint(const glm::vec3& point, Octree::
|
|||
} else if (lockType == Octree::TryLock) {
|
||||
gotLock = tryLockForRead();
|
||||
if (!gotLock) {
|
||||
if (accurateResult) {
|
||||
*accurateResult = false; // if user asked to accuracy or result, let them know this is inaccurate
|
||||
}
|
||||
return args.element; // if we wanted to tryLock, and we couldn't then just bail...
|
||||
}
|
||||
}
|
||||
|
@ -838,6 +870,9 @@ OctreeElement* Octree::getElementEnclosingPoint(const glm::vec3& point, Octree::
|
|||
unlock();
|
||||
}
|
||||
|
||||
if (accurateResult) {
|
||||
*accurateResult = false; // if user asked to accuracy or result, let them know this is inaccurate
|
||||
}
|
||||
return args.element;
|
||||
}
|
||||
|
||||
|
|
|
@ -249,17 +249,20 @@ public:
|
|||
} lockType;
|
||||
|
||||
bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
OctreeElement*& node, float& distance, BoxFace& face, Octree::lockType lockType = Octree::TryLock);
|
||||
OctreeElement*& node, float& distance, BoxFace& face,
|
||||
Octree::lockType lockType = Octree::TryLock, bool* accurateResult = NULL);
|
||||
|
||||
bool findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration,
|
||||
void** penetratedObject = NULL, Octree::lockType lockType = Octree::TryLock);
|
||||
bool findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration, void** penetratedObject = NULL,
|
||||
Octree::lockType lockType = Octree::TryLock, bool* accurateResult = NULL);
|
||||
|
||||
bool findCapsulePenetration(const glm::vec3& start, const glm::vec3& end, float radius,
|
||||
glm::vec3& penetration, Octree::lockType lockType = Octree::TryLock);
|
||||
bool findCapsulePenetration(const glm::vec3& start, const glm::vec3& end, float radius, glm::vec3& penetration,
|
||||
Octree::lockType lockType = Octree::TryLock, bool* accurateResult = NULL);
|
||||
|
||||
bool findShapeCollisions(const Shape* shape, CollisionList& collisions, Octree::lockType = Octree::TryLock);
|
||||
bool findShapeCollisions(const Shape* shape, CollisionList& collisions,
|
||||
Octree::lockType = Octree::TryLock, bool* accurateResult = NULL);
|
||||
|
||||
OctreeElement* getElementEnclosingPoint(const glm::vec3& point, Octree::lockType lockType = Octree::TryLock);
|
||||
OctreeElement* getElementEnclosingPoint(const glm::vec3& point,
|
||||
Octree::lockType lockType = Octree::TryLock, bool* accurateResult = NULL);
|
||||
|
||||
// Note: this assumes the fileFormat is the HIO individual voxels code files
|
||||
void loadOctreeFile(const char* fileName, bool wantColorRandomizer);
|
||||
|
|
|
@ -119,10 +119,19 @@ void LocalVoxels::pasteFrom(float x, float y, float z, float scale, const QStrin
|
|||
}
|
||||
|
||||
RayToVoxelIntersectionResult LocalVoxels::findRayIntersection(const PickRay& ray) {
|
||||
return findRayIntersectionWorker(ray, Octree::TryLock);
|
||||
}
|
||||
|
||||
RayToVoxelIntersectionResult LocalVoxels::findRayIntersectionBlocking(const PickRay& ray) {
|
||||
return findRayIntersectionWorker(ray, Octree::Lock);
|
||||
}
|
||||
|
||||
RayToVoxelIntersectionResult LocalVoxels::findRayIntersectionWorker(const PickRay& ray, Octree::lockType lockType) {
|
||||
RayToVoxelIntersectionResult result;
|
||||
if (_tree) {
|
||||
OctreeElement* element;
|
||||
result.intersects = _tree->findRayIntersection(ray.origin, ray.direction, element, result.distance, result.face);
|
||||
result.intersects = _tree->findRayIntersection(ray.origin, ray.direction, element, result.distance, result.face,
|
||||
lockType, &result.accurate);
|
||||
if (result.intersects) {
|
||||
VoxelTreeElement* voxel = (VoxelTreeElement*)element;
|
||||
result.voxel.x = voxel->getCorner().x;
|
||||
|
|
|
@ -76,13 +76,22 @@ public:
|
|||
/// \param source LocalVoxels' source tree
|
||||
Q_INVOKABLE void pasteFrom(float x, float y, float z, float scale, const QString source);
|
||||
|
||||
/// If the scripting context has visible voxels, this will determine a ray intersection
|
||||
/// If the scripting context has visible voxels, this will determine a ray intersection, the results
|
||||
/// may be inaccurate if the engine is unable to access the visible voxels, in which case result.accurate
|
||||
/// will be false.
|
||||
Q_INVOKABLE RayToVoxelIntersectionResult findRayIntersection(const PickRay& ray);
|
||||
|
||||
/// If the scripting context has visible voxels, this will determine a ray intersection, and will block in
|
||||
/// order to return an accurate result
|
||||
Q_INVOKABLE RayToVoxelIntersectionResult findRayIntersectionBlocking(const PickRay& ray);
|
||||
|
||||
/// returns a voxel space axis aligned vector for the face, useful in doing voxel math
|
||||
Q_INVOKABLE glm::vec3 getFaceVector(const QString& face);
|
||||
|
||||
private:
|
||||
/// actually does the work of finding the ray intersection, can be called in locking mode or tryLock mode
|
||||
RayToVoxelIntersectionResult findRayIntersectionWorker(const PickRay& ray, Octree::lockType lockType);
|
||||
|
||||
QString _name;
|
||||
StrongVoxelTreePointer _tree;
|
||||
};
|
||||
|
|
|
@ -41,6 +41,7 @@ void voxelDetailFromScriptValue(const QScriptValue &object, VoxelDetail& voxelDe
|
|||
|
||||
RayToVoxelIntersectionResult::RayToVoxelIntersectionResult() :
|
||||
intersects(false),
|
||||
accurate(true), // assume it's accurate
|
||||
voxel(),
|
||||
distance(0),
|
||||
face()
|
||||
|
@ -50,6 +51,7 @@ RayToVoxelIntersectionResult::RayToVoxelIntersectionResult() :
|
|||
QScriptValue rayToVoxelIntersectionResultToScriptValue(QScriptEngine* engine, const RayToVoxelIntersectionResult& value) {
|
||||
QScriptValue obj = engine->newObject();
|
||||
obj.setProperty("intersects", value.intersects);
|
||||
obj.setProperty("accurate", value.accurate);
|
||||
QScriptValue voxelValue = voxelDetailToScriptValue(engine, value.voxel);
|
||||
obj.setProperty("voxel", voxelValue);
|
||||
obj.setProperty("distance", value.distance);
|
||||
|
@ -88,6 +90,7 @@ QScriptValue rayToVoxelIntersectionResultToScriptValue(QScriptEngine* engine, co
|
|||
|
||||
void rayToVoxelIntersectionResultFromScriptValue(const QScriptValue& object, RayToVoxelIntersectionResult& value) {
|
||||
value.intersects = object.property("intersects").toVariant().toBool();
|
||||
value.accurate = object.property("accurate").toVariant().toBool();
|
||||
QScriptValue voxelValue = object.property("voxel");
|
||||
if (voxelValue.isValid()) {
|
||||
voxelDetailFromScriptValue(voxelValue, value.voxel);
|
||||
|
|
|
@ -39,6 +39,7 @@ class RayToVoxelIntersectionResult {
|
|||
public:
|
||||
RayToVoxelIntersectionResult();
|
||||
bool intersects;
|
||||
bool accurate;
|
||||
VoxelDetail voxel;
|
||||
float distance;
|
||||
BoxFace face;
|
||||
|
|
|
@ -122,12 +122,21 @@ void VoxelsScriptingInterface::eraseVoxel(float x, float y, float z, float scale
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
RayToVoxelIntersectionResult VoxelsScriptingInterface::findRayIntersection(const PickRay& ray) {
|
||||
return findRayIntersectionWorker(ray, Octree::TryLock);
|
||||
}
|
||||
|
||||
RayToVoxelIntersectionResult VoxelsScriptingInterface::findRayIntersectionBlocking(const PickRay& ray) {
|
||||
return findRayIntersectionWorker(ray, Octree::Lock);
|
||||
}
|
||||
|
||||
RayToVoxelIntersectionResult VoxelsScriptingInterface::findRayIntersectionWorker(const PickRay& ray,
|
||||
Octree::lockType lockType) {
|
||||
RayToVoxelIntersectionResult result;
|
||||
if (_tree) {
|
||||
OctreeElement* element;
|
||||
result.intersects = _tree->findRayIntersection(ray.origin, ray.direction, element, result.distance, result.face);
|
||||
result.intersects = _tree->findRayIntersection(ray.origin, ray.direction, element, result.distance, result.face,
|
||||
lockType, &result.accurate);
|
||||
if (result.intersects) {
|
||||
VoxelTreeElement* voxel = (VoxelTreeElement*)element;
|
||||
result.voxel.x = voxel->getCorner().x;
|
||||
|
|
|
@ -35,17 +35,16 @@ public:
|
|||
void setVoxelTree(VoxelTree* tree) { _tree = tree; }
|
||||
void setUndoStack(QUndoStack* undoStack) { _undoStack = undoStack; }
|
||||
|
||||
public slots:
|
||||
|
||||
public:
|
||||
/// provide the world scale
|
||||
const int getTreeScale() const { return TREE_SCALE; }
|
||||
Q_INVOKABLE const int getTreeScale() const { return TREE_SCALE; }
|
||||
|
||||
/// checks the local voxel tree for a voxel at the specified location and scale
|
||||
/// \param x the x-coordinate of the voxel (in meter units)
|
||||
/// \param y the y-coordinate of the voxel (in meter units)
|
||||
/// \param z the z-coordinate of the voxel (in meter units)
|
||||
/// \param scale the scale of the voxel (in meter units)
|
||||
VoxelDetail getVoxelAt(float x, float y, float z, float scale);
|
||||
Q_INVOKABLE VoxelDetail getVoxelAt(float x, float y, float z, float scale);
|
||||
|
||||
/// queues the creation of a voxel which will be sent by calling process on the PacketSender
|
||||
/// \param x the x-coordinate of the voxel (in meter units)
|
||||
|
@ -55,7 +54,7 @@ public slots:
|
|||
/// \param red the R value for RGB color of voxel
|
||||
/// \param green the G value for RGB color of voxel
|
||||
/// \param blue the B value for RGB color of voxel
|
||||
void setVoxelNonDestructive(float x, float y, float z, float scale, uchar red, uchar green, uchar blue);
|
||||
Q_INVOKABLE void setVoxelNonDestructive(float x, float y, float z, float scale, uchar red, uchar green, uchar blue);
|
||||
|
||||
/// queues the destructive creation of a voxel which will be sent by calling process on the PacketSender
|
||||
/// \param x the x-coordinate of the voxel (in meter units)
|
||||
|
@ -65,27 +64,36 @@ public slots:
|
|||
/// \param red the R value for RGB color of voxel
|
||||
/// \param green the G value for RGB color of voxel
|
||||
/// \param blue the B value for RGB color of voxel
|
||||
void setVoxel(float x, float y, float z, float scale, uchar red, uchar green, uchar blue);
|
||||
Q_INVOKABLE void setVoxel(float x, float y, float z, float scale, uchar red, uchar green, uchar blue);
|
||||
|
||||
/// queues the deletion of a voxel, sent by calling process on the PacketSender
|
||||
/// \param x the x-coordinate of the voxel (in meter units)
|
||||
/// \param y the y-coordinate of the voxel (in meter units)
|
||||
/// \param z the z-coordinate of the voxel (in meter units)
|
||||
/// \param scale the scale of the voxel (in meter units)
|
||||
void eraseVoxel(float x, float y, float z, float scale);
|
||||
Q_INVOKABLE void eraseVoxel(float x, float y, float z, float scale);
|
||||
|
||||
/// If the scripting context has visible voxels, this will determine a ray intersection
|
||||
RayToVoxelIntersectionResult findRayIntersection(const PickRay& ray);
|
||||
/// If the scripting context has visible voxels, this will determine a ray intersection, the results
|
||||
/// may be inaccurate if the engine is unable to access the visible voxels, in which case result.accurate
|
||||
/// will be false.
|
||||
Q_INVOKABLE RayToVoxelIntersectionResult findRayIntersection(const PickRay& ray);
|
||||
|
||||
/// If the scripting context has visible voxels, this will determine a ray intersection, and will block in
|
||||
/// order to return an accurate result
|
||||
Q_INVOKABLE RayToVoxelIntersectionResult findRayIntersectionBlocking(const PickRay& ray);
|
||||
|
||||
/// returns a voxel space axis aligned vector for the face, useful in doing voxel math
|
||||
glm::vec3 getFaceVector(const QString& face);
|
||||
Q_INVOKABLE glm::vec3 getFaceVector(const QString& face);
|
||||
|
||||
/// checks the local voxel tree for the smallest voxel enclosing the point
|
||||
/// \param point the x,y,z coordinates of the point (in meter units)
|
||||
/// \return VoxelDetail - if no voxel encloses the point then VoxelDetail items will be 0
|
||||
VoxelDetail getVoxelEnclosingPoint(const glm::vec3& point);
|
||||
Q_INVOKABLE VoxelDetail getVoxelEnclosingPoint(const glm::vec3& point);
|
||||
|
||||
private:
|
||||
/// actually does the work of finding the ray intersection, can be called in locking mode or tryLock mode
|
||||
RayToVoxelIntersectionResult findRayIntersectionWorker(const PickRay& ray, Octree::lockType lockType);
|
||||
|
||||
void queueVoxelAdd(PacketType addPacketType, VoxelDetail& addVoxelDetails);
|
||||
VoxelTree* _tree;
|
||||
QUndoStack* _undoStack;
|
||||
|
|
Loading…
Reference in a new issue