A decent ways towards getting the octree built. Small snag in the way fully valid or invalid non-leafs are handled

master
MitchellHansen 8 years ago
parent b844744a97
commit c6ac333232

@ -11,12 +11,13 @@
#include "util.hpp" #include "util.hpp"
#include <deque> #include <deque>
#include <unordered_map> #include <unordered_map>
#include <bitset>
#define _USE_MATH_DEFINES #define _USE_MATH_DEFINES
#include <math.h> #include <math.h>
#define CHUNK_DIM 32 #define CHUNK_DIM 32
#define OCT_DIM 64 #define OCT_DIM 16
struct KeyHasher { struct KeyHasher {
std::size_t operator()(const sf::Vector3i& k) const { std::size_t operator()(const sf::Vector3i& k) const {
@ -35,17 +36,42 @@ struct Chunk {
int* voxel_data; int* voxel_data;
}; };
class Allocator { class Octree {
public: public:
uint64_t dat[10000]; Octree() {
int dat_pos = 0; dat = new uint64_t[(int)pow(2, 15)];
Allocator() {}; for (int i = 0; i < (int)pow(2, 15); i++) {
~Allocator() {}; dat[i] = 0;
void reserve(int presidence, std::vector<uint64_t> cps) { }
memcpy(&dat[dat_pos], cps.data(), cps.size() * sizeof(uint64_t)); };
dat_pos += cps.size();
} ~Octree() {};
uint64_t *dat;
uint64_t stack_pos = 0x8000;
uint64_t global_pos = 0;
uint64_t copy_to_stack(std::vector<uint64_t> 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); void moveLight(sf::Vector2f in);
sf::Vector3f global_light; sf::Vector3f global_light;
Allocator a; Octree a;
protected: protected:

@ -5,6 +5,7 @@
#include <fstream> #include <fstream>
#include <sstream> #include <sstream>
#include "Vector4.hpp" #include "Vector4.hpp"
#include <bitset>
const double PI = 3.141592653589793238463; const double PI = 3.141592653589793238463;
const float PI_F = 3.14159265358979f; const float PI_F = 3.14159265358979f;
@ -170,3 +171,13 @@ inline std::string read_file(std::string file_name){
input_file.close(); input_file.close();
return buf.str(); 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;
}

@ -8,6 +8,10 @@ Map::Map(sf::Vector3i position) {
for (int i = 0; i < 1024; i++) { for (int i = 0; i < 1024; i++) {
block[i] = 0; 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) { int BitCount(unsigned int u) {
@ -41,111 +45,106 @@ int GetBit(int position, uint64_t* c) {
return (*c >> position) & 1; return (*c >> position) & 1;
} }
struct nonleaf { bool CheckFullValid(const uint64_t c) {
std::vector<nonleaf> children; uint64_t bitmask = 0xFF0000;
char leaf_mask; return (c & bitmask) == bitmask;
char valid_mask; }
};
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); // This first one is wrong, I think it's in it's endianness
sf::Vector3i t2 = sf::Vector3i(pos.x + dim, pos.y, pos.z); // Im currently useing bit 0 as the start to the child pointer, yes no?
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);
sf::Vector3i t5 = sf::Vector3i(pos.x, pos.y, pos.z + dim); // Checks if there are any non-leafs
sf::Vector3i t6 = sf::Vector3i(pos.x + dim, pos.y, pos.z + dim); uint64_t leaf_mask = 0xFF000000;
sf::Vector3i t7 = sf::Vector3i(pos.x, pos.y + dim, pos.z + dim); if ((descriptor & leaf_mask) == leaf_mask)
sf::Vector3i t8 = sf::Vector3i(pos.x + dim, pos.y + dim, pos.z + dim); return false;
// Valid mask checks for contiguous values
uint64_t valid_mask = 0xFF0000;
std::vector<uint64_t> cps; if ((descriptor & valid_mask) == valid_mask)
uint64_t tmp = 0; 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? uint64_t Map::generate_children(sf::Vector3i pos, int dim) {
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);
}
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<sf::Vector3i> 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); // Set the leaf mask to full
if (tmp != 0) tmp |= 0xFF000000;
cps.push_back(tmp);
tmp = generate_children(t2, dim / 2); // The CP will be left blank, contours will be added maybe
if (tmp != 0) return tmp;
cps.push_back(tmp);
tmp = generate_children(t3, dim / 2); }
if (tmp != 0) else {
cps.push_back(tmp);
tmp = generate_children(t4, dim / 2); uint64_t tmp;
if (tmp != 0) uint64_t child;
cps.push_back(tmp);
tmp = generate_children(t5, dim / 2); std::vector<uint64_t> children;
if (tmp != 0)
cps.push_back(tmp);
tmp = generate_children(t6, dim / 2); // Generate down the recursion, returning the descriptor of the current node
if (tmp != 0) for (int i = 0; i < v.size(); i++) {
cps.push_back(tmp); 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); // Now put those values onto the block stack, it returns the
if (tmp != 0) // 16 bit topmost pointer to the block. The 16th bit being
cps.push_back(tmp); // a switch to jump to a far pointer.
tmp |= a.copy_to_stack(children);
tmp = generate_children(t8, dim / 2); return tmp;
if (tmp != 0)
cps.push_back(tmp);
} }
a.reserve(cycle_num, cps);
return 0; return 0;
} }
void Map::generate_octree() { 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]; generate_children(sf::Vector3i(0, 0, 0), OCT_DIM);
for (int i = 0; i < 32 * 32 * 32; i++) { for (int i = 1000; i >= 0 ; i--) {
dataset[0] = rand() % 2; PrettyPrintUINT64(a.dat[i]);
} }
// levels defines how many levels to traverse before we hit raw data // 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. // 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? // Possible have some upper static nodes that will stay full regardless of contents?

Loading…
Cancel
Save