Return the box face, as well as the distance, from the ray intersection test.

Use it to determine which voxel neighbor we create when adding.
This commit is contained in:
Andrzej Kapolka 2013-05-09 10:46:52 -07:00
parent 2b9c2ca9a2
commit 7ff8b84f4c
7 changed files with 68 additions and 19 deletions

View file

@ -680,9 +680,10 @@ void VoxelSystem::removeOutOfView() {
} }
} }
bool VoxelSystem::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, VoxelDetail& detail, float& distance) { bool VoxelSystem::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
VoxelDetail& detail, float& distance, BoxFace& face) {
VoxelNode* node; VoxelNode* node;
if (!_tree->findRayIntersection(origin, direction, node, distance)) { if (!_tree->findRayIntersection(origin, direction, node, distance, face)) {
return false; return false;
} }
detail.x = node->getCorner().x; detail.x = node->getCorner().x;

View file

@ -65,7 +65,8 @@ public:
void removeOutOfView(); void removeOutOfView();
bool hasViewChanged(); bool hasViewChanged();
bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, VoxelDetail& detail, float& distance); bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
VoxelDetail& detail, float& distance, BoxFace& face);
private: private:
int _callsToTreesToArrays; int _callsToTreesToArrays;

View file

@ -1489,11 +1489,34 @@ void addVoxelUnderCursor() {
VoxelDetail detail; VoxelDetail detail;
float distance; float distance;
if (voxels.findRayIntersection(origin, direction, detail, distance)) { BoxFace face;
// get the hit location relative to the center of the voxel if (voxels.findRayIntersection(origin, direction, detail, distance, face)) {
float half = detail.s * 0.5f; // use the face to determine the side on which to create a neighbor
glm::vec3 hit = origin + distance*direction - glm::vec3(detail.x + half, detail.y + half, detail.z + half); switch (face) {
case MIN_X_FACE:
detail.x -= detail.s;
break;
case MAX_X_FACE:
detail.x += detail.s;
break;
case MIN_Y_FACE:
detail.y -= detail.s;
break;
case MAX_Y_FACE:
detail.y += detail.s;
break;
case MIN_Z_FACE:
detail.z -= detail.s;
break;
case MAX_Z_FACE:
detail.z += detail.s;
break;
}
unsigned char* bufferOut; unsigned char* bufferOut;
int sizeOut; int sizeOut;
@ -1510,7 +1533,8 @@ void deleteVoxelUnderCursor() {
VoxelDetail detail; VoxelDetail detail;
float distance; float distance;
if (voxels.findRayIntersection(origin, direction, detail, distance)) { BoxFace face;
if (voxels.findRayIntersection(origin, direction, detail, distance, face)) {
unsigned char* bufferOut; unsigned char* bufferOut;
int sizeOut; int sizeOut;

View file

@ -95,7 +95,7 @@ static bool findIntersection(float origin, float direction, float corner, float
return false; return false;
} }
bool AABox::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const { bool AABox::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face) const {
// handle the trivial case where the box contains the origin // handle the trivial case where the box contains the origin
if (contains(origin)) { if (contains(origin)) {
distance = 0; distance = 0;
@ -105,14 +105,23 @@ bool AABox::findRayIntersection(const glm::vec3& origin, const glm::vec3& direct
float axisDistance; float axisDistance;
if ((findIntersection(origin.x, direction.x, _corner.x, _size.x, axisDistance) && axisDistance >= 0 && 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.y + axisDistance*direction.y, _corner.y, _size.y) &&
isWithin(origin.z + axisDistance*direction.z, _corner.z, _size.z)) || isWithin(origin.z + axisDistance*direction.z, _corner.z, _size.z))) {
(findIntersection(origin.y, direction.y, _corner.y, _size.y, axisDistance) && axisDistance >= 0 && distance = axisDistance;
face = direction.x > 0 ? MIN_X_FACE : MAX_X_FACE;
return true;
}
if ((findIntersection(origin.y, direction.y, _corner.y, _size.y, axisDistance) && axisDistance >= 0 &&
isWithin(origin.x + axisDistance*direction.x, _corner.x, _size.x) && isWithin(origin.x + axisDistance*direction.x, _corner.x, _size.x) &&
isWithin(origin.z + axisDistance*direction.z, _corner.z, _size.z)) || isWithin(origin.z + axisDistance*direction.z, _corner.z, _size.z))) {
(findIntersection(origin.z, direction.z, _corner.z, _size.z, axisDistance) && axisDistance >= 0 && distance = axisDistance;
face = direction.y > 0 ? MIN_Y_FACE : MAX_Y_FACE;
return true;
}
if ((findIntersection(origin.z, direction.z, _corner.z, _size.z, axisDistance) && axisDistance >= 0 &&
isWithin(origin.y + axisDistance*direction.y, _corner.y, _size.y) && isWithin(origin.y + axisDistance*direction.y, _corner.y, _size.y) &&
isWithin(origin.x + axisDistance*direction.x, _corner.x, _size.x))) { isWithin(origin.x + axisDistance*direction.x, _corner.x, _size.x))) {
distance = axisDistance; distance = axisDistance;
face = direction.z > 0 ? MIN_Z_FACE : MAX_Z_FACE;
return true; return true;
} }
return false; return false;

View file

@ -13,6 +13,15 @@
#include <glm/glm.hpp> #include <glm/glm.hpp>
enum BoxFace {
MIN_X_FACE,
MAX_X_FACE,
MIN_Y_FACE,
MAX_Y_FACE,
MIN_Z_FACE,
MAX_Z_FACE
};
class AABox class AABox
{ {
@ -37,7 +46,7 @@ public:
const glm::vec3& getCenter() const { return _center; }; const glm::vec3& getCenter() const { return _center; };
bool contains(const glm::vec3& point) const; bool contains(const glm::vec3& point) const;
bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const; bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face) const;
private: private:
glm::vec3 _corner; glm::vec3 _corner;

View file

@ -605,6 +605,7 @@ public:
glm::vec3 direction; glm::vec3 direction;
VoxelNode*& node; VoxelNode*& node;
float& distance; float& distance;
BoxFace& face;
bool found; bool found;
}; };
@ -612,7 +613,8 @@ bool findRayOperation(VoxelNode* node, void* extraData) {
RayArgs* args = static_cast<RayArgs*>(extraData); RayArgs* args = static_cast<RayArgs*>(extraData);
AABox box = node->getAABox(); AABox box = node->getAABox();
float distance; float distance;
if (!box.findRayIntersection(args->origin, args->direction, distance)) { BoxFace face;
if (!box.findRayIntersection(args->origin, args->direction, distance, face)) {
return false; return false;
} }
if (!node->isLeaf()) { if (!node->isLeaf()) {
@ -621,14 +623,16 @@ bool findRayOperation(VoxelNode* node, void* extraData) {
if (!args->found || distance < args->distance) { if (!args->found || distance < args->distance) {
args->node = node; args->node = node;
args->distance = distance; args->distance = distance;
args->face = face;
args->found = true; args->found = true;
} }
return false; return false;
} }
bool VoxelTree::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, VoxelNode*& node, float& distance) bool VoxelTree::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
VoxelNode*& node, float& distance, BoxFace& face)
{ {
RayArgs args = { origin / (float)TREE_SCALE, direction, node, distance }; RayArgs args = { origin / (float)TREE_SCALE, direction, node, distance, face };
recurseTreeWithOperation(findRayOperation, &args); recurseTreeWithOperation(findRayOperation, &args);
return args.found; return args.found;
} }

View file

@ -63,7 +63,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); bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
VoxelNode*& node, float& distance, BoxFace& face);
// 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);