mirror of
https://github.com/overte-org/overte.git
synced 2025-04-25 20:36:38 +02:00
Merge pull request #198 from ey6es/master
Support for generating pick rays and finding intersections between rays and voxel nodes.
This commit is contained in:
commit
83c8ac6111
6 changed files with 94 additions and 1 deletions
|
@ -8,6 +8,8 @@
|
||||||
// Simple axis aligned box class.
|
// Simple axis aligned box class.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#include "SharedUtil.h"
|
||||||
|
|
||||||
#include "AABox.h"
|
#include "AABox.h"
|
||||||
|
|
||||||
|
|
||||||
|
@ -66,3 +68,50 @@ glm::vec3 AABox::getVertexN(const glm::vec3 &normal) const {
|
||||||
|
|
||||||
return(res);
|
return(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// determines whether a value is within the extents
|
||||||
|
static bool isWithin(float value, float corner, float size) {
|
||||||
|
return value >= corner && value <= corner + size;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AABox::contains(const glm::vec3& point) const {
|
||||||
|
return isWithin(point.x, _corner.x, _size.x) &&
|
||||||
|
isWithin(point.y, _corner.y, _size.y) &&
|
||||||
|
isWithin(point.z, _corner.z, _size.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
// finds the intersection between a ray and the facing plane on one axis
|
||||||
|
static bool findIntersection(float origin, float direction, float corner, float size, float& distance) {
|
||||||
|
if (direction > EPSILON) {
|
||||||
|
distance = (corner - origin) / direction;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
} else if (direction < -EPSILON) {
|
||||||
|
distance = (corner + size - origin) / direction;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AABox::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const {
|
||||||
|
// handle the trivial case where the box contains the origin
|
||||||
|
if (contains(origin)) {
|
||||||
|
distance = 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// check each axis
|
||||||
|
float axisDistance;
|
||||||
|
if (findIntersection(origin.x, direction.x, _corner.x, _size.x, axisDistance) && axisDistance >= 0 &&
|
||||||
|
isWithin(origin.y + axisDistance*direction.y, _corner.y, _size.y) &&
|
||||||
|
isWithin(origin.z + axisDistance*direction.z, _corner.z, _size.z) ||
|
||||||
|
findIntersection(origin.y, direction.y, _corner.y, _size.y, axisDistance) && axisDistance >= 0 &&
|
||||||
|
isWithin(origin.x + axisDistance*direction.x, _corner.x, _size.x) &&
|
||||||
|
isWithin(origin.z + axisDistance*direction.z, _corner.z, _size.z) ||
|
||||||
|
findIntersection(origin.z, direction.z, _corner.z, _size.z, axisDistance) && axisDistance >= 0 &&
|
||||||
|
isWithin(origin.y + axisDistance*direction.y, _corner.y, _size.y) &&
|
||||||
|
isWithin(origin.x + axisDistance*direction.x, _corner.x, _size.x)) {
|
||||||
|
distance = axisDistance;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
|
@ -35,10 +35,13 @@ public:
|
||||||
const glm::vec3& getCorner() const { return _corner; };
|
const glm::vec3& getCorner() const { return _corner; };
|
||||||
const glm::vec3& getSize() const { return _size; };
|
const glm::vec3& getSize() const { return _size; };
|
||||||
|
|
||||||
|
bool contains(const glm::vec3& point) const;
|
||||||
|
bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
glm::vec3 _corner;
|
glm::vec3 _corner;
|
||||||
glm::vec3 _size;
|
glm::vec3 _size;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -225,3 +225,7 @@ int ViewFrustum::boxInFrustum(const AABox& box) const {
|
||||||
return(result);
|
return(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ViewFrustum::computePickRay(float x, float y, glm::vec3& origin, glm::vec3& direction) const {
|
||||||
|
origin = _nearTopLeft + x*(_nearTopRight - _nearTopLeft) + y*(_nearBottomLeft - _nearTopLeft);
|
||||||
|
direction = glm::normalize(origin - _position);
|
||||||
|
}
|
||||||
|
|
|
@ -98,6 +98,7 @@ public:
|
||||||
int sphereInFrustum(const glm::vec3& center, float radius) const;
|
int sphereInFrustum(const glm::vec3& center, float radius) const;
|
||||||
int boxInFrustum(const AABox& box) const;
|
int boxInFrustum(const AABox& box) const;
|
||||||
|
|
||||||
|
void computePickRay(float x, float y, glm::vec3& origin, glm::vec3& direction) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -552,7 +552,41 @@ int VoxelTree::searchForColoredNodes(int maxSearchLevel, VoxelNode* node, const
|
||||||
return levelReached;
|
return levelReached;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// combines the ray cast arguments into a single object
|
||||||
|
class RayArgs {
|
||||||
|
public:
|
||||||
|
glm::vec3 origin;
|
||||||
|
glm::vec3 direction;
|
||||||
|
VoxelNode*& node;
|
||||||
|
float& distance;
|
||||||
|
bool found;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool findRayOperation(VoxelNode* node, void* extraData) {
|
||||||
|
RayArgs* args = static_cast<RayArgs*>(extraData);
|
||||||
|
AABox box;
|
||||||
|
node->getAABox(box);
|
||||||
|
float distance;
|
||||||
|
if (!box.findRayIntersection(args->origin, args->direction, distance)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!node->isLeaf()) {
|
||||||
|
return true; // recurse on children
|
||||||
|
}
|
||||||
|
if (!args->found || distance < args->distance) {
|
||||||
|
args->node = node;
|
||||||
|
args->distance = distance;
|
||||||
|
args->found = true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VoxelTree::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, VoxelNode*& node, float& distance)
|
||||||
|
{
|
||||||
|
RayArgs args = { origin / (float)TREE_SCALE, direction, node, distance };
|
||||||
|
recurseTreeWithOperation(findRayOperation, &args);
|
||||||
|
return args.found;
|
||||||
|
}
|
||||||
|
|
||||||
int VoxelTree::searchForColoredNodesRecursion(int maxSearchLevel, int& currentSearchLevel,
|
int VoxelTree::searchForColoredNodesRecursion(int maxSearchLevel, int& currentSearchLevel,
|
||||||
VoxelNode* node, const ViewFrustum& viewFrustum, VoxelNodeBag& bag) {
|
VoxelNode* node, const ViewFrustum& viewFrustum, VoxelNodeBag& bag) {
|
||||||
|
|
|
@ -62,6 +62,8 @@ public:
|
||||||
void clearDirtyBit() { _isDirty = false; };
|
void clearDirtyBit() { _isDirty = false; };
|
||||||
unsigned long int getNodesChangedFromBitstream() const { return _nodesChangedFromBitstream; };
|
unsigned long int getNodesChangedFromBitstream() const { return _nodesChangedFromBitstream; };
|
||||||
|
|
||||||
|
bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, VoxelNode*& node, float& distance);
|
||||||
|
|
||||||
// Note: this assumes the fileFormat is the HIO individual voxels code files
|
// Note: this assumes the fileFormat is the HIO individual voxels code files
|
||||||
void loadVoxelsFile(const char* fileName, bool wantColorRandomizer);
|
void loadVoxelsFile(const char* fileName, bool wantColorRandomizer);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue