Update video demo, tweaking my refactor of the maps. Working on downwards navigation in the oct traversal

master
MitchellHansen 7 years ago
parent c35f867c76
commit 3f09515c0a

@ -15,7 +15,7 @@ In order to build this project you must have Cmake, GLEW, SFML, and the OpenCL d
Video demo: Video demo:
[![Video demo](http://img.youtube.com/vi/JmD5ISHbKbU/0.jpg)](http://www.youtube.com/watch?v=JmD5ISHbKbU) [![Video demo](http://img.youtube.com/vi/LqmXZJR_gxU/0.jpg)](http://www.youtube.com/watch?v=LqmXZJr_gxU)
Screenshots: Screenshots:

@ -92,10 +92,8 @@ public:
static const uint64_t contour_mask = 0xFF00000000000000; static const uint64_t contour_mask = 0xFF00000000000000;
std::vector<std::tuple<sf::Vector3i, char>> Octree::CastRayOctree( std::vector<std::tuple<sf::Vector3i, char>> Octree::CastRayOctree(
Octree *octree, sf::Vector2f cam_dir,
sf::Vector3i* map_dim, sf::Vector3f cam_pos
sf::Vector2f* cam_dir,
sf::Vector3f* cam_pos
); );
private: private:

@ -30,9 +30,13 @@ bool Application::init_clcaster() {
sf::Image bitmap = map->GenerateHeightBitmap(sf::Vector3i(MAP_X, MAP_Y, MAP_Z)); sf::Image bitmap = map->GenerateHeightBitmap(sf::Vector3i(MAP_X, MAP_Y, MAP_Z));
map->ApplyHeightmap(bitmap); map->ApplyHeightmap(bitmap);
map->octree.CastRayOctree(sf::Vector2f(1.5f, -2.0f), sf::Vector3f(5.0f, 5.0f, 5.0f));
raycaster->assign_octree(map); raycaster->assign_octree(map);
raycaster->assign_map(map); raycaster->assign_map(map);
// Create a new camera with (starting position, direction) // Create a new camera with (starting position, direction)
camera = std::make_shared<Camera>( camera = std::make_shared<Camera>(
sf::Vector3f(50, 60, 10), sf::Vector3f(50, 60, 10),

@ -218,7 +218,8 @@ bool CLCaster::compute() {
// There is a possibility that I would want to move this over to be all inside it's own // There is a possibility that I would want to move this over to be all inside it's own
// container to make it so it can be changed via CL_MEM_USE_HOST_PTR. But I doubt it // container to make it so it can be changed via CL_MEM_USE_HOST_PTR. But I doubt it
// would ever be called enough to warrent that // would ever be called enough to warrant that
// TODO : Move CL interaction into the CLCaster?
bool CLCaster::create_viewport(int width, int height, float v_fov, float h_fov) { bool CLCaster::create_viewport(int width, int height, float v_fov, float h_fov) {
// CL needs the screen resolution // CL needs the screen resolution

@ -12,21 +12,27 @@
* This project should not be viewed as a product or really anything other than * This project should not be viewed as a product or really anything other than
* a cool little example on how real time volumetric ray marching is becoming * a cool little example on how real time volumetric ray marching is becoming
* very possible on todays hardware. Don't expect this program to work on your hardware, * very possible on todays hardware. Don't expect this program to work on your hardware,
* preform as expected, have documentation, walk your dog, etc. * perform as expected, have documentation, walk your dog, etc.
* *
*/ */
/** /**
* TODO: * TODO:
*
* - Inconsistent lighting constants. GUI manipulation * - Inconsistent lighting constants. GUI manipulation
* + Ancillary settings buffer and memory controller * + Ancillary settings buffer and memory controller
* - Attachment lookup and aux buffer, contour lookup & masking * - Attachment lookup and aux buffer, contour lookup & masking
* - Traversal algorithm + related stacks and data structures * - Traversal algorithm + related stacks and data structures
* + Passing to GPU, Syncing? * + Syncing, loading, unloading
* - Octree, Map interface with the GPU * - Octree, Map interface with the GPU
* - Octree, Map refactoring * - Map/Oct raycasting algo that has parity with GPU
* - Separate Application stages into areas that make sense * - Separate Application stages into areas that make sense
* - Saving, loading of RLE voxel data and raw oct data * - Saving, loading of RLE voxel data and raw oct data
* - Bodgy mem sharing of lights with the GPU
* - Multi-stage rendering kernels
* - Multi light support via first-strike resetting
* -
*
*/ */
#include "Application.h" #include "Application.h"

@ -8,14 +8,14 @@ ArrayMap::ArrayMap(sf::Vector3i dimensions) {
voxel_data = new char[dimensions.x * dimensions.y * dimensions.z]; voxel_data = new char[dimensions.x * dimensions.y * dimensions.z];
for (int i = 0; i < dimensions.x * dimensions.y * dimensions.z; i++) { for (int i = 0; i < dimensions.x * dimensions.y * dimensions.z; i++) {
voxel_data[i] = 0; voxel_data[i] = 1;
} }
for (int x = 0; x < dimensions.x; x++) { //for (int x = 0; x < dimensions.x; x++) {
for (int y = 0; y < dimensions.y; y++) { // for (int y = 0; y < dimensions.y; y++) {
setVoxel(sf::Vector3i(x, y, 1), 5); // setVoxel(sf::Vector3i(x, y, 1), 5);
} // }
} //}
} }

@ -330,10 +330,6 @@ char Octree::get1DIndexedVoxel(char* data, sf::Vector3i dimensions, sf::Vector3i
bool Octree::Validate(char* data, sf::Vector3i dimensions){ bool Octree::Validate(char* data, sf::Vector3i dimensions){
// std::cout << (int)get1DIndexedVoxel(data, dimensions, sf::Vector3i(16, 16, 16)) << std::endl;
// std::cout << (int)GetVoxel(sf::Vector3i(16, 16, 16)) << std::endl;
for (int x = 0; x < dimensions.x; x++) { for (int x = 0; x < dimensions.x; x++) {
for (int y = 0; y < dimensions.y; y++) { for (int y = 0; y < dimensions.y; y++) {
for (int z = 0; z < dimensions.z; z++) { for (int z = 0; z < dimensions.z; z++) {
@ -348,7 +344,6 @@ bool Octree::Validate(char* data, sf::Vector3i dimensions){
std::cout << (int)arr_val << " : " << (int)oct_val << std::endl; std::cout << (int)arr_val << " : " << (int)oct_val << std::endl;
return false; return false;
} }
} }
} }
} }
@ -362,10 +357,8 @@ unsigned int Octree::getDimensions() {
std::vector<std::tuple<sf::Vector3i, char>> Octree::CastRayOctree( std::vector<std::tuple<sf::Vector3i, char>> Octree::CastRayOctree(
Octree *octree, sf::Vector2f cam_dir,
sf::Vector3i* map_dim, sf::Vector3f cam_pos
sf::Vector2f* cam_dir,
sf::Vector3f* cam_pos
) { ) {
// Setup the voxel coords from the camera origin // Setup the voxel coords from the camera origin
@ -375,7 +368,7 @@ std::vector<std::tuple<sf::Vector3i, char>> Octree::CastRayOctree(
// This function when passed an "air" voxel will return as far down // This function when passed an "air" voxel will return as far down
// the IDX stack as it could go. We use this oct-level to determine // the IDX stack as it could go. We use this oct-level to determine
// our first position and jump. Updating it as we go // our first position and jump. Updating it as we go
OctState traversal_state = octree->GetVoxel(voxel); OctState traversal_state = GetVoxel(voxel);
std::vector<std::tuple<sf::Vector3i, char>> travel_path; std::vector<std::tuple<sf::Vector3i, char>> travel_path;
@ -383,15 +376,15 @@ std::vector<std::tuple<sf::Vector3i, char>> Octree::CastRayOctree(
// Pitch // Pitch
ray_dir = sf::Vector3f( ray_dir = sf::Vector3f(
ray_dir.z * sin((*cam_dir).x) + ray_dir.x * cos((*cam_dir).x), ray_dir.z * sin(cam_dir.x) + ray_dir.x * cos(cam_dir.x),
ray_dir.y, ray_dir.y,
ray_dir.z * cos((*cam_dir).x) - ray_dir.x * sin((*cam_dir).x) ray_dir.z * cos(cam_dir.x) - ray_dir.x * sin(cam_dir.x)
); );
// Yaw // Yaw
ray_dir = sf::Vector3f( ray_dir = sf::Vector3f(
ray_dir.x * cos((*cam_dir).y) - ray_dir.y * sin((*cam_dir).y), 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.x * sin(cam_dir.y) + ray_dir.y * cos(cam_dir.y),
ray_dir.z ray_dir.z
); );
@ -411,7 +404,7 @@ std::vector<std::tuple<sf::Vector3i, char>> Octree::CastRayOctree(
voxel_step.z *= (ray_dir.z > 0) - (ray_dir.z < 0); voxel_step.z *= (ray_dir.z > 0) - (ray_dir.z < 0);
// set the jump multiplier based on the traversal state vs the log base 2 of the maps dimensions // set the jump multiplier based on the traversal state vs the log base 2 of the maps dimensions
int jump_power = log2(map_dim->x) - traversal_state.scale; int jump_power = log2(oct_dimensions) - traversal_state.scale;
// Delta T is the units a ray must travel along an axis in order to // Delta T is the units a ray must travel along an axis in order to
@ -424,21 +417,14 @@ std::vector<std::tuple<sf::Vector3i, char>> Octree::CastRayOctree(
delta_t *= static_cast<float>(jump_power); delta_t *= static_cast<float>(jump_power);
// TODO: start here
// Whats the issue?
// Using traversal_scale
// set intersection t to the current hierarchy level each time we change levels
// and use that to step
// Intersection T is the collection of the next intersection points // Intersection T is the collection of the next intersection points
// for all 3 axis XYZ. We take the full positive cardinality when // for all 3 axis XYZ. We take the full positive cardinality when
// subtracting the floor, so we must transfer the sign over from // subtracting the floor, so we must transfer the sign over from
// the voxel step // the voxel step
sf::Vector3f intersection_t( sf::Vector3f intersection_t(
delta_t.x * (cam_pos->y - floor(cam_pos->x)) * voxel_step.x, 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.y * (cam_pos.x - floor(cam_pos.y)) * voxel_step.y,
delta_t.z * (cam_pos->z - floor(cam_pos->z)) * voxel_step.z delta_t.z * (cam_pos.z - floor(cam_pos.z)) * voxel_step.z
); );
// When we transfer the sign over, we get the correct direction of // When we transfer the sign over, we get the correct direction of
@ -494,6 +480,7 @@ std::vector<std::tuple<sf::Vector3i, char>> Octree::CastRayOctree(
// If it decreased // If it decreased
// Pop up the stack until the oct that the idx flip is valid and we landed on a valid oct // Pop up the stack until the oct that the idx flip is valid and we landed on a valid oct
while (traversal_state.idx_stack[traversal_state.scale] < prev_val || while (traversal_state.idx_stack[traversal_state.scale] < prev_val ||
// This will endless loop if we hit the empty portion of an octree and cant find a leaf until the we go OOB
!((traversal_state.parent_stack[traversal_state.parent_stack_position] >> 16) & Octree::mask_8[mask_index]) !((traversal_state.parent_stack[traversal_state.parent_stack_position] >> 16) & Octree::mask_8[mask_index])
) { ) {
@ -515,6 +502,11 @@ std::vector<std::tuple<sf::Vector3i, char>> Octree::CastRayOctree(
traversal_state.parent_stack[traversal_state.parent_stack_position] = 0; traversal_state.parent_stack[traversal_state.parent_stack_position] = 0;
traversal_state.parent_stack_position--; traversal_state.parent_stack_position--;
// Compute the new (0,0,0) origin'd oct position
traversal_state.oct_pos.x = floor(traversal_state.oct_pos.x / pow(2, jump_power)) * pow(2, jump_power);
traversal_state.oct_pos.y = floor(traversal_state.oct_pos.y / pow(2, jump_power)) * pow(2, jump_power);
traversal_state.oct_pos.z = floor(traversal_state.oct_pos.z / pow(2, jump_power)) * pow(2, jump_power);
// Set the current CD to the one on top of the stack // Set the current CD to the one on top of the stack
traversal_state.current_descriptor = traversal_state.current_descriptor =
traversal_state.parent_stack[traversal_state.parent_stack_position]; traversal_state.parent_stack[traversal_state.parent_stack_position];
@ -524,18 +516,100 @@ std::vector<std::tuple<sf::Vector3i, char>> Octree::CastRayOctree(
mask_index = traversal_state.idx_stack[traversal_state.scale]; mask_index = traversal_state.idx_stack[traversal_state.scale];
} }
// At this point we are at the CP of an oct with a valid oct at the leaf indicated by the current idx in the idx stack
while (jump_power > 1) {
// Do the logic steps to find which sub oct we step down into
if (voxel.x >= (jump_power / 2) + traversal_state.oct_pos.x) {
// Set our voxel position to the (0,0) of the correct oct
traversal_state.oct_pos.x += (jump_power / 2);
// Set the idx to represent the move
traversal_state.idx_stack[traversal_state.scale] |= idx_set_x_mask;
}
if (voxel.y >= (jump_power / 2) + traversal_state.oct_pos.y) {
// TODO What the hell is going on with the or operator on this one!??!?!?!
traversal_state.oct_pos.y += (jump_power / 2);
// TODO What is up with the XOR operator that was on this one?
traversal_state.idx_stack[traversal_state.scale] |= idx_set_y_mask;
}
if (voxel.z >= (jump_power / 2) + traversal_state.oct_pos.z) {
traversal_state.oct_pos.z += (jump_power / 2);
traversal_state.idx_stack[traversal_state.scale] |= idx_set_z_mask;
}
// Our count mask matches the way we index our idx so we can just
// copy it over
int mask_index = traversal_state.idx_stack[traversal_state.scale];
// Check to see if we are on a valid oct
if ((traversal_state.parent_stack[traversal_state.parent_stack_position] >> 16) & mask_8[mask_index]) {
// Check to see if it is a leaf
if ((traversal_state.parent_stack[traversal_state.parent_stack_position] >> 24) & mask_8[mask_index]) {
// If it is, then we cannot traverse further as CP's won't have been generated
traversal_state.found = 1;
return;
}
// If all went well and we found a valid non-leaf oct then we will traverse further down the hierarchy
traversal_state.scale++;
jump_power /= 2;
// Count the number of valid octs that come before and add it to the index to get the position
// Negate it by one as it counts itself
int count = count_bits((uint8_t)(traversal_state.parent_stack[traversal_state.parent_stack_position] >> 16) & count_mask_8[mask_index]) - 1;
// access the far point at which the head points too. Determine it's value, and add
// a count of the valid bits to the index
if (far_bit_mask & descriptor_buffer[current_index]) {
int far_pointer_index = current_index + (traversal_state.parent_stack[traversal_state.parent_stack_position] & child_pointer_mask);
current_index = descriptor_buffer[far_pointer_index] + count;
}
// access the element at which head points to and then add the specified number of indices
// to get to the correct child descriptor
else {
current_index = current_index + (traversal_state.parent_stack[traversal_state.parent_stack_position] & child_pointer_mask) + count;
}
traversal_state.parent_stack[traversal_state.parent_stack_position] = descriptor_buffer[current_index];
// Increment the parent stack position and put the new oct node as the parent
traversal_state.parent_stack_position++;
traversal_state.parent_stack[traversal_state.parent_stack_position] = traversal_state.parent_stack[traversal_state.parent_stack_position];
}
else {
// If the oct was not valid, then no CP's exists any further
// This implicitly says that if it's non-valid then it must be a leaf!!
// It appears that the traversal is now working but I need
// 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
traversal_state.found = 0;
return;
}
}
// Check to see if we are on a valid oct // Check to see if we are on a valid oct
//if ((traversal_state.parent_stack[traversal_state.parent_stack_position] >> 16) & Octree::mask_8[mask_index]) { if ((traversal_state.parent_stack[traversal_state.parent_stack_position] >> 16) & Octree::mask_8[mask_index]) {
// // Check to see if it is a leaf
// if ((traversal_state.parent_stack[traversal_state.parent_stack_position] >> 24) & Octree::mask_8[mask_index]) {
// // If it is, then we cannot traverse further as CP's won't have been generated
// state.found = 1; }
// return state;
// }
//}
// Check to see if we are on top of a valid branch // Check to see if we are on top of a valid branch
// Traverse down to the lowest valid oct that the ray is within // Traverse down to the lowest valid oct that the ray is within

Loading…
Cancel
Save