Added basic ray intersection testing to VoxelTree.

This commit is contained in:
Andrzej Kapolka 2013-05-03 17:27:57 -07:00
parent 33b4159a95
commit f8cbe34e07
4 changed files with 89 additions and 1 deletions

View file

@ -8,6 +8,8 @@
// Simple axis aligned box class.
//
#include "SharedUtil.h"
#include "AABox.h"
@ -66,3 +68,50 @@ glm::vec3 AABox::getVertexN(const glm::vec3 &normal) const {
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 the closer plane in one direction
static bool findIntersection(float origin, float direction, float corner, float size, float* t) {
if (direction > EPSILON) {
*t = (corner - origin) / direction;
return true;
} else if (direction < -EPSILON) {
*t = (corner + size - origin) / direction;
return true;
}
return false;
}
bool AABox::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float* t) const {
// handle the trivial case where the box contains the origin
if (contains(origin)) {
*t = 0;
return true;
}
// check each direction
float nt;
if (findIntersection(origin.x, direction.x, _corner.x, _size.x, &nt) &&
isWithin(origin.y + nt*direction.y, _corner.y, _size.y) &&
isWithin(origin.z + nt*direction.z, _corner.z, _size.z) ||
findIntersection(origin.y, direction.y, _corner.y, _size.y, &nt) &&
isWithin(origin.x + nt*direction.x, _corner.x, _size.x) &&
isWithin(origin.z + nt*direction.z, _corner.z, _size.z) ||
findIntersection(origin.z, direction.z, _corner.z, _size.z, &nt) &&
isWithin(origin.y + nt*direction.y, _corner.y, _size.y) &&
isWithin(origin.x + nt*direction.x, _corner.x, _size.x)) {
*t = nt;
return true;
}
return false;
}

View file

@ -35,10 +35,13 @@ public:
const glm::vec3& getCorner() const { return _corner; };
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* t) const;
private:
glm::vec3 _corner;
glm::vec3 _size;
};
#endif
#endif

View file

@ -546,7 +546,41 @@ int VoxelTree::searchForColoredNodes(int maxSearchLevel, VoxelNode* node, const
return levelReached;
}
// combines the ray cast arguments into a single object
class RayArgs {
public:
glm::vec3 origin;
glm::vec3 direction;
VoxelNode** node;
float* t;
bool found;
};
bool findRayOperation(VoxelNode* node, void* extraData) {
RayArgs* args = static_cast<RayArgs*>(extraData);
AABox box;
node->getAABox(box);
float t;
if (!box.findRayIntersection(args->origin, args->direction, &t)) {
return false;
}
if (!node->isLeaf()) {
return true; // recurse on children
}
if (!args->found || t < *(args->t)) {
*(args->node) = node;
*(args->t) = t;
args->found = true;
}
return false;
}
bool VoxelTree::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, VoxelNode** node, float* t)
{
RayArgs args = { origin, direction, node, t };
recurseTreeWithOperation(findRayOperation, &args);
return args.found;
}
int VoxelTree::searchForColoredNodesRecursion(int maxSearchLevel, int& currentSearchLevel,
VoxelNode* node, const ViewFrustum& viewFrustum, VoxelNodeBag& bag) {

View file

@ -61,6 +61,8 @@ public:
bool isDirty() const { return _isDirty; };
void clearDirtyBit() { _isDirty = false; };
unsigned long int getNodesChangedFromBitstream() const { return _nodesChangedFromBitstream; };
bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, VoxelNode** node, float* t);
private:
int encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEncodeLevel,