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;
if (!_tree->findRayIntersection(origin, direction, node, distance)) {
if (!_tree->findRayIntersection(origin, direction, node, distance, face)) {
return false;
}
detail.x = node->getCorner().x;

View file

@ -65,7 +65,8 @@ public:
void removeOutOfView();
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:
int _callsToTreesToArrays;

View file

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

View file

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

View file

@ -13,6 +13,15 @@
#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
{
@ -37,7 +46,7 @@ public:
const glm::vec3& getCenter() const { return _center; };
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:
glm::vec3 _corner;

View file

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

View file

@ -63,7 +63,8 @@ public:
void clearDirtyBit() { _isDirty = false; };
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
void loadVoxelsFile(const char* fileName, bool wantColorRandomizer);