From c6ac33323246eebd9ce61ddce1288c7043d7405f Mon Sep 17 00:00:00 2001 From: MitchellHansen Date: Wed, 14 Dec 2016 01:22:52 -0800 Subject: [PATCH] A decent ways towards getting the octree built. Small snag in the way fully valid or invalid non-leafs are handled --- include/Map.h | 48 +++++++++++---- include/util.hpp | 11 ++++ src/Map.cpp | 151 +++++++++++++++++++++++------------------------ 3 files changed, 123 insertions(+), 87 deletions(-) diff --git a/include/Map.h b/include/Map.h index 02322bc..3673600 100644 --- a/include/Map.h +++ b/include/Map.h @@ -11,12 +11,13 @@ #include "util.hpp" #include #include +#include #define _USE_MATH_DEFINES #include #define CHUNK_DIM 32 -#define OCT_DIM 64 +#define OCT_DIM 16 struct KeyHasher { std::size_t operator()(const sf::Vector3i& k) const { @@ -35,17 +36,42 @@ struct Chunk { int* voxel_data; }; -class Allocator { +class Octree { public: - uint64_t dat[10000]; - int dat_pos = 0; - Allocator() {}; - ~Allocator() {}; - void reserve(int presidence, std::vector cps) { - memcpy(&dat[dat_pos], cps.data(), cps.size() * sizeof(uint64_t)); - dat_pos += cps.size(); - } + Octree() { + dat = new uint64_t[(int)pow(2, 15)]; + for (int i = 0; i < (int)pow(2, 15); i++) { + dat[i] = 0; + } + }; + + ~Octree() {}; + + uint64_t *dat; + uint64_t stack_pos = 0x8000; + uint64_t global_pos = 0; + + uint64_t copy_to_stack(std::vector children) { + + // Check to make sure these children will fit on the top of the stack + // if not, allocate a new block and paste them at the bottom + // Make sure to reset the position + + // Copy the children on the stack, bottom up, first node to last + memcpy(&dat[stack_pos], children.data(), children.size() * sizeof(int64_t)); + stack_pos -= children.size(); + + // Return the bitmask encoding the index of that value + // If we tripped the far bit, allocate a far index to the stack and place + // it one above preferably. + // And then shift the far bit to 1 + + // If not, shift the index to its correct place + return stack_pos; + }; + + }; @@ -68,7 +94,7 @@ public: void moveLight(sf::Vector2f in); sf::Vector3f global_light; - Allocator a; + Octree a; protected: diff --git a/include/util.hpp b/include/util.hpp index 92d35fe..46e6c5e 100644 --- a/include/util.hpp +++ b/include/util.hpp @@ -5,6 +5,7 @@ #include #include #include "Vector4.hpp" +#include const double PI = 3.141592653589793238463; const float PI_F = 3.14159265358979f; @@ -170,3 +171,13 @@ inline std::string read_file(std::string file_name){ input_file.close(); return buf.str(); } + +inline void PrettyPrintUINT64(uint64_t i) { + + std::cout << "[" << std::bitset<15>(i) << "]"; + std::cout << "[" << std::bitset<1>(i >> 15) << "]"; + std::cout << "[" << std::bitset<8>(i >> 16) << "]"; + std::cout << "[" << std::bitset<8>(i >> 24) << "]"; + std::cout << "[" << std::bitset<32>(i >> 32) << "]" << std::endl; + +} \ No newline at end of file diff --git a/src/Map.cpp b/src/Map.cpp index 4a9f9b1..69b3396 100644 --- a/src/Map.cpp +++ b/src/Map.cpp @@ -8,6 +8,10 @@ Map::Map(sf::Vector3i position) { for (int i = 0; i < 1024; i++) { block[i] = 0; } + + for (int i = 0; i < OCT_DIM * OCT_DIM * OCT_DIM; i++) { + voxel_data[i] = rand() % 2; + } } int BitCount(unsigned int u) { @@ -41,111 +45,106 @@ int GetBit(int position, uint64_t* c) { return (*c >> position) & 1; } -struct nonleaf { - std::vector children; - char leaf_mask; - char valid_mask; -}; +bool CheckFullValid(const uint64_t c) { + uint64_t bitmask = 0xFF0000; + return (c & bitmask) == bitmask; +} -uint64_t Map::generate_children(sf::Vector3i pos, int dim) { +bool CheckShouldInclude(const uint64_t descriptor) { - sf::Vector3i t1 = sf::Vector3i(pos.x, pos.y, pos.z); - sf::Vector3i t2 = sf::Vector3i(pos.x + dim, pos.y, pos.z); - sf::Vector3i t3 = sf::Vector3i(pos.x, pos.y + dim, pos.z); - sf::Vector3i t4 = sf::Vector3i(pos.x + dim, pos.y + dim, pos.z); + // This first one is wrong, I think it's in it's endianness + // Im currently useing bit 0 as the start to the child pointer, yes no? - sf::Vector3i t5 = sf::Vector3i(pos.x, pos.y, pos.z + dim); - sf::Vector3i t6 = sf::Vector3i(pos.x + dim, pos.y, pos.z + dim); - sf::Vector3i t7 = sf::Vector3i(pos.x, pos.y + dim, pos.z + dim); - sf::Vector3i t8 = sf::Vector3i(pos.x + dim, pos.y + dim, pos.z + dim); + // Checks if there are any non-leafs + uint64_t leaf_mask = 0xFF000000; + if ((descriptor & leaf_mask) == leaf_mask) + return false; + + // Valid mask checks for contiguous values + uint64_t valid_mask = 0xFF0000; - std::vector cps; - uint64_t tmp = 0; + if ((descriptor & valid_mask) == valid_mask) + return true; + else if ((descriptor & valid_mask) == ~valid_mask) + return true; + else + return false; - int cycle_num = cycle_counter; - cycle_counter++; - if (dim == 1) { +} - // These don't bound check, should they? - if (getVoxel(t1)) - SetBit(16, &tmp); - if (getVoxel(t2)) - SetBit(17, &tmp); - if (getVoxel(t3)) - SetBit(18, &tmp); - if (getVoxel(t4)) - SetBit(19, &tmp); - if (getVoxel(t5)) - SetBit(20, &tmp); - if (getVoxel(t6)) - SetBit(21, &tmp); - if (getVoxel(t7)) - SetBit(22, &tmp); - if (getVoxel(t8)) - SetBit(23, &tmp); - - cps.push_back(tmp); +uint64_t Map::generate_children(sf::Vector3i pos, int dim) { - } - else { - // Generate all 8 sub trees accounting for each of their unique positions + // The 8 subvoxel coords starting from the 1th direction, the direction of the origin of the 3d grid + // XY, Z++, XY + std::vector v = { + sf::Vector3i(pos.x, pos.y, pos.z), + sf::Vector3i(pos.x + dim, pos.y, pos.z), + sf::Vector3i(pos.x, pos.y + dim, pos.z), + sf::Vector3i(pos.x + dim, pos.y + dim, pos.z), + sf::Vector3i(pos.x, pos.y, pos.z + dim), + sf::Vector3i(pos.x + dim, pos.y, pos.z + dim), + sf::Vector3i(pos.x, pos.y + dim, pos.z + dim), + sf::Vector3i(pos.x + dim, pos.y + dim, pos.z + dim) + }; + + if (dim == 1) { + + // Return the base 2x2 leaf node + uint64_t tmp = 0; + + // These don't bound check, should they? + // Setting the individual valid mask bits + for (int i = 0; i < v.size(); i++) { + if (getVoxel(v.at(i))) + SetBit(i + 16, &tmp); + } - tmp = generate_children(t1, dim / 2); - if (tmp != 0) - cps.push_back(tmp); + // Set the leaf mask to full + tmp |= 0xFF000000; - tmp = generate_children(t2, dim / 2); - if (tmp != 0) - cps.push_back(tmp); + // The CP will be left blank, contours will be added maybe + return tmp; - tmp = generate_children(t3, dim / 2); - if (tmp != 0) - cps.push_back(tmp); + } + else { - tmp = generate_children(t4, dim / 2); - if (tmp != 0) - cps.push_back(tmp); + uint64_t tmp; + uint64_t child; - tmp = generate_children(t5, dim / 2); - if (tmp != 0) - cps.push_back(tmp); + std::vector children; - tmp = generate_children(t6, dim / 2); - if (tmp != 0) - cps.push_back(tmp); + // Generate down the recursion, returning the descriptor of the current node + for (int i = 0; i < v.size(); i++) { + child = generate_children(v.at(i), dim / 2); + if (child != 0 && CheckShouldInclude(child)) { + children.push_back(child); + SetBit(i + 16, &tmp); + } + } - tmp = generate_children(t7, dim / 2); - if (tmp != 0) - cps.push_back(tmp); + // Now put those values onto the block stack, it returns the + // 16 bit topmost pointer to the block. The 16th bit being + // a switch to jump to a far pointer. + tmp |= a.copy_to_stack(children); - tmp = generate_children(t8, dim / 2); - if (tmp != 0) - cps.push_back(tmp); + return tmp; } - a.reserve(cycle_num, cps); - return 0; } void Map::generate_octree() { - char* arr[8192]; - for (int i = 0; i < 8192; i++) { - arr[i] = 0; - } - generate_children(sf::Vector3i(0, 0, 0), 64); - int* dataset = new int[32 * 32 * 32]; - for (int i = 0; i < 32 * 32 * 32; i++) { - dataset[0] = rand() % 2; + generate_children(sf::Vector3i(0, 0, 0), OCT_DIM); + for (int i = 1000; i >= 0 ; i--) { + PrettyPrintUINT64(a.dat[i]); } - // levels defines how many levels to traverse before we hit raw data // Will be the map width I presume. Will still need to handle how to swap in and out data. // Possible have some upper static nodes that will stay full regardless of contents?