Cleaned up and pulled out some code into Map.cpp in order to start working on the meat of the *Correct* voxel traversal method as explained in the paper.
This commit is contained in:
@@ -7,6 +7,8 @@
|
||||
#include <CL/opencl.h>
|
||||
|
||||
#elif defined _WIN32
|
||||
// Good lord, the C++ std overwrote windows.h min() max() definitions
|
||||
#define NOMINMAX
|
||||
#include <windows.h>
|
||||
|
||||
// As if hardware is ever going to move away from 1.2
|
||||
@@ -68,6 +70,9 @@ sf::Texture window_texture;
|
||||
// - Inconsistent lighting constants. GUI manipulation
|
||||
// Ancilary settings buffer and memory controller
|
||||
// - Attachment lookup and aux buffer, contour lookup & masking
|
||||
// - Traversal algorithm + related stacks and data structures
|
||||
// - Octree, Map interface with the GPU
|
||||
// - Octree, Map refactoring
|
||||
|
||||
|
||||
int main() {
|
||||
@@ -76,7 +81,9 @@ int main() {
|
||||
Map _map(32);
|
||||
//_map.test();
|
||||
//std::cin.get();
|
||||
return 0;
|
||||
|
||||
|
||||
//return 0;
|
||||
// =============================
|
||||
|
||||
sf::RenderWindow window(sf::VideoMode(WINDOW_X, WINDOW_Y), "SFML");
|
||||
|
||||
301
src/map/Map.cpp
301
src/map/Map.cpp
@@ -3,6 +3,8 @@
|
||||
|
||||
Map::Map(uint32_t dimensions) {
|
||||
|
||||
|
||||
// ========= TEMP 3D voxel data ===========
|
||||
srand(time(nullptr));
|
||||
|
||||
voxel_data = new char[dimensions * dimensions * dimensions];
|
||||
@@ -17,10 +19,20 @@ Map::Map(uint32_t dimensions) {
|
||||
else
|
||||
voxel_data[i] = 0;
|
||||
}
|
||||
sf::Vector3i dim3(dimensions, dimensions, dimensions);
|
||||
|
||||
octree.Generate(voxel_data, sf::Vector3i(dimensions, dimensions, dimensions));
|
||||
octree.Generate(voxel_data, dim3);
|
||||
|
||||
octree.Validate(voxel_data, dim3);
|
||||
|
||||
sf::Vector2f cam_dir(2, 0.01);
|
||||
sf::Vector3f cam_pos(10, 10, 10);
|
||||
std::vector<std::tuple<sf::Vector3i, char>> list1 = CastRayCharArray(voxel_data, &dim3, &cam_dir, &cam_pos);
|
||||
std::vector<std::tuple<sf::Vector3i, char>> list2 = CastRayOctree(&octree, &dim3, &cam_dir, &cam_pos);
|
||||
|
||||
|
||||
return;
|
||||
|
||||
octree.Validate(voxel_data, sf::Vector3i(dimensions, dimensions, dimensions));
|
||||
}
|
||||
|
||||
void Map::setVoxel(sf::Vector3i pos, int val) {
|
||||
@@ -28,76 +40,261 @@ void Map::setVoxel(sf::Vector3i pos, int val) {
|
||||
voxel_data[pos.x + OCT_DIM * (pos.y + OCT_DIM * pos.z)] = val;
|
||||
}
|
||||
|
||||
bool Map::getVoxelFromOctree(sf::Vector3i position)
|
||||
{
|
||||
return 0;
|
||||
char Map::getVoxel(sf::Vector3i pos){
|
||||
|
||||
return octree.GetVoxel(pos).found;
|
||||
}
|
||||
|
||||
bool Map::getVoxel(sf::Vector3i pos){
|
||||
std::vector<std::tuple<sf::Vector3i, char>> Map::CastRayCharArray(
|
||||
char* map,
|
||||
sf::Vector3i* map_dim,
|
||||
sf::Vector2f* cam_dir,
|
||||
sf::Vector3f* cam_pos
|
||||
) {
|
||||
|
||||
if (voxel_data[pos.x + OCT_DIM * (pos.y + OCT_DIM * pos.z)]) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
std::vector<std::tuple<sf::Vector3i, char>> travel_path;
|
||||
|
||||
sf::Vector3f ray_dir(1, 0, 0);
|
||||
|
||||
// Pitch
|
||||
ray_dir = sf::Vector3f(
|
||||
ray_dir.z * sin((*cam_dir).x) + ray_dir.x * cos((*cam_dir).x),
|
||||
ray_dir.y,
|
||||
ray_dir.z * cos((*cam_dir).x) - ray_dir.x * sin((*cam_dir).x)
|
||||
);
|
||||
|
||||
// Yaw
|
||||
ray_dir = sf::Vector3f(
|
||||
ray_dir.x * cos((*cam_dir).y) - ray_dir.y * sin((*cam_dir).y),
|
||||
ray_dir.x * sin((*cam_dir).y) + ray_dir.y * cos((*cam_dir).y),
|
||||
ray_dir.z
|
||||
);
|
||||
|
||||
|
||||
// Setup the voxel step based on what direction the ray is pointing
|
||||
sf::Vector3i voxel_step(1, 1, 1);
|
||||
|
||||
voxel_step.x *= (ray_dir.x > 0) - (ray_dir.x < 0);
|
||||
voxel_step.y *= (ray_dir.y > 0) - (ray_dir.y < 0);
|
||||
voxel_step.z *= (ray_dir.z > 0) - (ray_dir.z < 0);
|
||||
|
||||
// Setup the voxel coords from the camera origin
|
||||
sf::Vector3i voxel(*cam_pos);
|
||||
|
||||
// Delta T is the units a ray must travel along an axis in order to
|
||||
// traverse an integer split
|
||||
sf::Vector3f delta_t(
|
||||
fabs(1.0f / ray_dir.x),
|
||||
fabs(1.0f / ray_dir.y),
|
||||
fabs(1.0f / ray_dir.z)
|
||||
);
|
||||
|
||||
// offset is how far we are into a voxel, enables sub voxel movement
|
||||
// Intersection T is the collection of the next intersection points
|
||||
// for all 3 axis XYZ.
|
||||
sf::Vector3f intersection_t(
|
||||
delta_t.x * (cam_pos->x - floor(cam_pos->x)) * voxel_step.x,
|
||||
delta_t.y * (cam_pos->y - floor(cam_pos->y)) * voxel_step.y,
|
||||
delta_t.z * (cam_pos->z - floor(cam_pos->z)) * voxel_step.z
|
||||
);
|
||||
|
||||
// for negative values, wrap around the delta_t
|
||||
intersection_t.x += delta_t.x * -(std::min(intersection_t.x, 0.0f));
|
||||
intersection_t.y += delta_t.y * -(std::min(intersection_t.y, 0.0f));
|
||||
intersection_t.z += delta_t.z * -(std::min(intersection_t.z, 0.0f));
|
||||
|
||||
|
||||
int dist = 0;
|
||||
sf::Vector3i face_mask(0, 0, 0);
|
||||
int voxel_data = 0;
|
||||
|
||||
// Andrew Woo's raycasting algo
|
||||
do {
|
||||
|
||||
face_mask.x = intersection_t.x <= std::min(intersection_t.y, intersection_t.z);
|
||||
face_mask.y = intersection_t.y <= std::min(intersection_t.z, intersection_t.x);
|
||||
face_mask.z = intersection_t.z <= std::min(intersection_t.x, intersection_t.y);
|
||||
|
||||
|
||||
intersection_t.x += delta_t.x * fabs(face_mask.x);
|
||||
intersection_t.y += delta_t.y * fabs(face_mask.y);
|
||||
intersection_t.z += delta_t.z * fabs(face_mask.z);
|
||||
|
||||
voxel.x += voxel_step.x * face_mask.x;
|
||||
voxel.y += voxel_step.y * face_mask.y;
|
||||
voxel.z += voxel_step.z * face_mask.z;
|
||||
|
||||
if ((intersection_t.x) < (intersection_t.y)) {
|
||||
if ((intersection_t.x) < (intersection_t.z)) {
|
||||
|
||||
voxel.x += voxel_step.x;
|
||||
intersection_t.x = intersection_t.x + delta_t.x;
|
||||
}
|
||||
else {
|
||||
|
||||
voxel.z += voxel_step.z;
|
||||
intersection_t.z = intersection_t.z + delta_t.z;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ((intersection_t.y) < (intersection_t.z)) {
|
||||
|
||||
voxel.y += voxel_step.y;
|
||||
intersection_t.y = intersection_t.y + delta_t.y;
|
||||
}
|
||||
else {
|
||||
|
||||
voxel.z += voxel_step.z;
|
||||
intersection_t.z = intersection_t.z + delta_t.z;
|
||||
}
|
||||
}
|
||||
|
||||
if (voxel.x >= map_dim->x || voxel.y >= map_dim->y || voxel.z >= map_dim->z) {
|
||||
return travel_path;
|
||||
}
|
||||
if (voxel.x < 0 || voxel.y < 0 || voxel.z < 0) {
|
||||
return travel_path;
|
||||
}
|
||||
|
||||
// If we hit a voxel
|
||||
voxel_data = map[voxel.x + (*map_dim).x * (voxel.y + (*map_dim).z * (voxel.z))];
|
||||
|
||||
travel_path.push_back(std::make_tuple(voxel, voxel_data));
|
||||
|
||||
if (voxel_data != 0)
|
||||
return travel_path;
|
||||
|
||||
|
||||
} while (++dist < 700.0f);
|
||||
|
||||
return travel_path;
|
||||
}
|
||||
|
||||
bool Map::test() {
|
||||
class Octree;
|
||||
|
||||
std::cout << "Validating map..." << std::endl;
|
||||
std::vector<std::tuple<sf::Vector3i, char>> Map::CastRayOctree(
|
||||
Octree *octree,
|
||||
sf::Vector3i* map_dim,
|
||||
sf::Vector2f* cam_dir,
|
||||
sf::Vector3f* cam_pos
|
||||
) {
|
||||
|
||||
for (int x = 0; x < OCT_DIM; x++) {
|
||||
for (int y = 0; y < OCT_DIM; y++) {
|
||||
for (int z = 0; z < OCT_DIM; z++) {
|
||||
std::vector<std::tuple<sf::Vector3i, char>> travel_path;
|
||||
|
||||
sf::Vector3i pos(x, y, z);
|
||||
sf::Vector3f ray_dir(1, 0, 0);
|
||||
|
||||
bool arr1 = getVoxel(pos);
|
||||
bool arr2 = getVoxelFromOctree(pos);
|
||||
// Pitch
|
||||
ray_dir = sf::Vector3f(
|
||||
ray_dir.z * sin((*cam_dir).x) + ray_dir.x * cos((*cam_dir).x),
|
||||
ray_dir.y,
|
||||
ray_dir.z * cos((*cam_dir).x) - ray_dir.x * sin((*cam_dir).x)
|
||||
);
|
||||
|
||||
if (arr1 != arr2) {
|
||||
std::cout << "X: " << pos.x << "Y: " << pos.y << "Z: " << pos.z << std::endl;
|
||||
}
|
||||
// Yaw
|
||||
ray_dir = sf::Vector3f(
|
||||
ray_dir.x * cos((*cam_dir).y) - ray_dir.y * sin((*cam_dir).y),
|
||||
ray_dir.x * sin((*cam_dir).y) + ray_dir.y * cos((*cam_dir).y),
|
||||
ray_dir.z
|
||||
);
|
||||
|
||||
|
||||
// Setup the voxel step based on what direction the ray is pointing
|
||||
sf::Vector3i voxel_step(1, 1, 1);
|
||||
|
||||
voxel_step.x *= (ray_dir.x > 0) - (ray_dir.x < 0);
|
||||
voxel_step.y *= (ray_dir.y > 0) - (ray_dir.y < 0);
|
||||
voxel_step.z *= (ray_dir.z > 0) - (ray_dir.z < 0);
|
||||
|
||||
// Setup the voxel coords from the camera origin
|
||||
sf::Vector3i voxel(*cam_pos);
|
||||
|
||||
// Delta T is the units a ray must travel along an axis in order to
|
||||
// traverse an integer split
|
||||
sf::Vector3f delta_t(
|
||||
fabs(1.0f / ray_dir.x),
|
||||
fabs(1.0f / ray_dir.y),
|
||||
fabs(1.0f / ray_dir.z)
|
||||
);
|
||||
|
||||
// offset is how far we are into a voxel, enables sub voxel movement
|
||||
// Intersection T is the collection of the next intersection points
|
||||
// for all 3 axis XYZ.
|
||||
sf::Vector3f intersection_t(
|
||||
delta_t.x * (cam_pos->y - floor(cam_pos->x)) * voxel_step.x,
|
||||
delta_t.y * (cam_pos->x - floor(cam_pos->y)) * voxel_step.y,
|
||||
delta_t.z * (cam_pos->z - floor(cam_pos->z)) * voxel_step.z
|
||||
);
|
||||
|
||||
// for negative values, wrap around the delta_t
|
||||
intersection_t.x += delta_t.x * -(std::min(intersection_t.x, 0.0f));
|
||||
intersection_t.y += delta_t.y * -(std::min(intersection_t.y, 0.0f));
|
||||
intersection_t.z += delta_t.z * -(std::min(intersection_t.z, 0.0f));
|
||||
|
||||
|
||||
int dist = 0;
|
||||
sf::Vector3i face_mask(0, 0, 0);
|
||||
int voxel_data = 0;
|
||||
|
||||
OctState traversal_state = octree->GetVoxel(voxel);
|
||||
|
||||
// Andrew Woo's raycasting algo
|
||||
do {
|
||||
|
||||
face_mask.x = intersection_t.x <= std::min(intersection_t.y, intersection_t.z);
|
||||
face_mask.y = intersection_t.y <= std::min(intersection_t.z, intersection_t.x);
|
||||
face_mask.z = intersection_t.z <= std::min(intersection_t.x, intersection_t.y);
|
||||
|
||||
|
||||
intersection_t.x += delta_t.x * fabs(face_mask.x);
|
||||
intersection_t.y += delta_t.y * fabs(face_mask.y);
|
||||
intersection_t.z += delta_t.z * fabs(face_mask.z);
|
||||
|
||||
voxel.x += voxel_step.x * face_mask.x;
|
||||
voxel.y += voxel_step.y * face_mask.y;
|
||||
voxel.z += voxel_step.z * face_mask.z;
|
||||
|
||||
if ((intersection_t.x) < (intersection_t.y)) {
|
||||
if ((intersection_t.x) < (intersection_t.z)) {
|
||||
|
||||
voxel.x += voxel_step.x;
|
||||
intersection_t.x = intersection_t.x + delta_t.x;
|
||||
}
|
||||
else {
|
||||
|
||||
voxel.z += voxel_step.z;
|
||||
intersection_t.z = intersection_t.z + delta_t.z;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ((intersection_t.y) < (intersection_t.z)) {
|
||||
|
||||
std::cout << "Done" << std::endl;
|
||||
voxel.y += voxel_step.y;
|
||||
intersection_t.y = intersection_t.y + delta_t.y;
|
||||
}
|
||||
else {
|
||||
|
||||
sf::Clock timer;
|
||||
|
||||
timer.restart();
|
||||
|
||||
for (int x = 0; x < OCT_DIM; x++) {
|
||||
for (int y = 0; y < OCT_DIM; y++) {
|
||||
for (int z = 0; z < OCT_DIM; z++) {
|
||||
|
||||
sf::Vector3i pos(x, y, z);
|
||||
|
||||
bool arr1 = getVoxel(pos);
|
||||
voxel.z += voxel_step.z;
|
||||
intersection_t.z = intersection_t.z + delta_t.z;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "Array linear xyz access : ";
|
||||
std::cout << timer.restart().asMicroseconds() << " microseconds" << std::endl;
|
||||
|
||||
for (int x = 0; x < OCT_DIM; x++) {
|
||||
for (int y = 0; y < OCT_DIM; y++) {
|
||||
for (int z = 0; z < OCT_DIM; z++) {
|
||||
|
||||
sf::Vector3i pos(x, y, z);
|
||||
|
||||
bool arr2 = getVoxelFromOctree(pos);
|
||||
}
|
||||
if (voxel.x >= map_dim->x || voxel.y >= map_dim->y || voxel.z >= map_dim->z) {
|
||||
return travel_path;
|
||||
}
|
||||
if (voxel.x < 0 || voxel.y < 0 || voxel.z < 0) {
|
||||
return travel_path;
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "Octree linear xyz access : ";
|
||||
std::cout << timer.restart().asMicroseconds() << " microseconds" << std::endl;
|
||||
// If we hit a voxel
|
||||
//voxel_data = map[voxel.x + (*map_dim).x * (voxel.y + (*map_dim).z * (voxel.z))];
|
||||
voxel_data = getVoxel(voxel);
|
||||
travel_path.push_back(std::make_tuple(voxel, voxel_data));
|
||||
|
||||
if (voxel_data != 0)
|
||||
return travel_path;
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
} while (++dist < 700.0f);
|
||||
|
||||
return travel_path;
|
||||
}
|
||||
@@ -3,7 +3,6 @@
|
||||
Octree::Octree() {
|
||||
|
||||
// initialize the the buffers to 0's
|
||||
trunk_buffer = new uint64_t[buffer_size]();
|
||||
descriptor_buffer = new uint64_t[buffer_size]();
|
||||
attachment_lookup = new uint32_t[buffer_size]();
|
||||
attachment_buffer = new uint64_t[buffer_size]();
|
||||
@@ -41,10 +40,10 @@ void Octree::Generate(char* data, sf::Vector3i dimensions) {
|
||||
GetVoxel(sf::Vector3i(0, 0, 0));
|
||||
}
|
||||
|
||||
bool Octree::GetVoxel(sf::Vector3i position) {
|
||||
OctState Octree::GetVoxel(sf::Vector3i position) {
|
||||
|
||||
// Struct that holds the state necessary to continue the traversal from the found voxel
|
||||
oct_state state;
|
||||
OctState state;
|
||||
|
||||
// push the root node to the parent stack
|
||||
uint64_t current_index = root_index;
|
||||
@@ -115,7 +114,8 @@ bool Octree::GetVoxel(sf::Vector3i position) {
|
||||
if ((head >> 24) & mask_8[mask_index]) {
|
||||
|
||||
// If it is, then we cannot traverse further as CP's won't have been generated
|
||||
return true;
|
||||
state.found = 1;
|
||||
return state;
|
||||
}
|
||||
|
||||
// If all went well and we found a valid non-leaf oct then we will traverse further down the hierarchy
|
||||
@@ -134,7 +134,7 @@ bool Octree::GetVoxel(sf::Vector3i position) {
|
||||
// Increment the parent stack position and put the new oct node as the parent
|
||||
state.parent_stack_position++;
|
||||
state.parent_stack[state.parent_stack_position] = head;
|
||||
|
||||
|
||||
}
|
||||
else {
|
||||
// If the oct was not valid, then no CP's exists any further
|
||||
@@ -144,11 +144,13 @@ bool Octree::GetVoxel(sf::Vector3i position) {
|
||||
// to focus on how to now take care of the end condition.
|
||||
// Currently it adds the last parent on the second to lowest
|
||||
// oct CP. Not sure if thats correct
|
||||
return false;
|
||||
state.found = 0;
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
state.found = 1;
|
||||
return state;
|
||||
}
|
||||
|
||||
void Octree::print_block(int block_pos) {
|
||||
@@ -234,7 +236,8 @@ std::tuple<uint64_t, uint64_t> Octree::GenerationRecursion(char* data, sf::Vecto
|
||||
}
|
||||
|
||||
// We are working bottom up so we need to subtract from the stack position
|
||||
// the amount of elements we want to use
|
||||
// the amount of elements we want to use. In the worst case this will be
|
||||
// a far pointer for ever descriptor (size * 2)
|
||||
|
||||
int worst_case_insertion_size = descriptor_position_array.size() * 2;
|
||||
|
||||
@@ -329,7 +332,7 @@ bool Octree::Validate(char* data, sf::Vector3i dimensions){
|
||||
sf::Vector3i pos(x, y, z);
|
||||
|
||||
char arr_val = get1DIndexedVoxel(data, dimensions, pos);
|
||||
char oct_val = GetVoxel(pos);
|
||||
char oct_val = GetVoxel(pos).found;
|
||||
|
||||
if (arr_val != oct_val) {
|
||||
std::cout << "X: " << pos.x << " Y: " << pos.y << " Z: " << pos.z << " ";
|
||||
@@ -342,5 +345,5 @@ bool Octree::Validate(char* data, sf::Vector3i dimensions){
|
||||
|
||||
std::cout << "Done" << std::endl;
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user