#include "Map.h" int BitCount(unsigned int u) { unsigned int uCount; uCount = u - ((u >> 1) & 033333333333) - ((u >> 2) & 011111111111); return ((uCount + (uCount >> 3)) & 030707070707) % 63; } void SetBit(int position, char* c) { *c |= (uint64_t)1 << position; } void FlipBit(int position, char* c) { *c ^= (uint64_t)1 << position; } int GetBit(int position, char* c) { return (*c >> position) & (uint64_t)1; } void SetBit(int position, uint64_t* c) { *c |= (uint64_t)1 << position; } void FlipBit(int position, uint64_t* c) { *c ^= (uint64_t)1 << position; } int GetBit(int position, uint64_t* c) { return (*c >> position) & (uint64_t)1; } bool CheckLeafSign(const uint64_t descriptor) { uint64_t valid_mask = 0xFF0000; // Return true if all 1's, false if contiguous 0's if ((descriptor & valid_mask) == valid_mask) { return true; } if ((descriptor & valid_mask) == 0) { return false; } // Error out, something funky abort(); } bool CheckContiguousValid(const uint64_t c) { uint64_t bitmask = 0xFF0000; return (c & bitmask) == bitmask; } bool IsLeaf(const uint64_t descriptor) { uint64_t leaf_mask = 0xFF000000; uint64_t valid_mask = 0xFF0000; // Check for contiguous valid values of either 0's or 1's if (((descriptor & valid_mask) == valid_mask) || ((descriptor & valid_mask) == 0)) { // Check for a full leaf mask // Only if valid and leaf are contiguous, then it's a leaf if ((descriptor & leaf_mask) == leaf_mask) return true; else return false; } else return false; } Map::Map(sf::Vector3i position) { load_unload(position); for (int i = 0; i < OCT_DIM * OCT_DIM * OCT_DIM; i++) { if (rand() % 8 > 2) voxel_data[i] = 0; else voxel_data[i] = 1; } } uint64_t Map::generate_children(sf::Vector3i pos, int dim) { // 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); } // Set the leaf mask to full tmp |= 0xFF000000; // The CP will be left blank, contours will be added maybe return tmp; } else { uint64_t tmp = 0; uint64_t child = 0; std::vector children; // Generate down the recursion, returning the descriptor of the current node for (int i = 0; i < v.size(); i++) { // Get the child descriptor from the i'th to 8th subvoxel child = generate_children(v.at(i), dim / 2); PrettyPrintUINT64(child, &ss); ss << " " << dim << " " << counter++ << std::endl; if (IsLeaf(child)) { if (CheckLeafSign(child)) SetBit(i + 16, &tmp); SetBit(i + 16 + 8, &tmp); } else { SetBit(i + 16, &tmp); children.push_back(child); } } // 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. int y = 0; tmp |= a.copy_to_stack(children); if ((tmp & 0xFFFFFFFF00000000) != 0) { abort(); } return tmp; } return 0; } void Map::generate_octree() { // Launch the recursive generator at (0,0,0) as the first point // and the octree dimension as the initial block size uint64_t root_node = generate_children(sf::Vector3i(0, 0, 0), OCT_DIM/2); uint64_t tmp = 0; PrettyPrintUINT64(root_node, &ss); ss << " " << OCT_DIM << " " << counter++ << std::endl; if (IsLeaf(root_node)) { if (CheckLeafSign(root_node)) SetBit(0 + 16, &tmp); SetBit(0 + 16 + 8, &tmp); } else { SetBit(0 + 16, &tmp); } tmp |= a.copy_to_stack(std::vector{root_node}); DumpLog(&ss, "raw_output.txt"); a.print_block(0); //a.get_voxel(sf::Vector2i(0, 0)); } void Map::load_unload(sf::Vector3i world_position) { //sf::Vector3i chunk_pos(world_to_chunk(world_position)); // ////Don't forget the middle chunk //if (chunk_map.find(chunk_pos) == chunk_map.end()) { // chunk_map[chunk_pos] = Chunk(5); //} //for (int x = chunk_pos.x - chunk_radius / 2; x < chunk_pos.x + chunk_radius / 2; x++) { // for (int y = chunk_pos.y - chunk_radius / 2; y < chunk_pos.y + chunk_radius / 2; y++) { // for (int z = chunk_pos.z - chunk_radius / 2; z < chunk_pos.z + chunk_radius / 2; z++) { // if (chunk_map.find(sf::Vector3i(x, y, z)) == chunk_map.end()) { // chunk_map.emplace(sf::Vector3i(x, y, z), Chunk(rand() % 6)); // //chunk_map[sf::Vector3i(x, y, z)] = Chunk(rand() % 6); // } // } // } //} } void Map::load_single(sf::Vector3i world_position) { //sf::Vector3i chunk_pos(world_to_chunk(world_position)); ////Don't forget the middle chunk //if (chunk_map.find(chunk_pos) == chunk_map.end()) { // chunk_map[chunk_pos] = Chunk(0); //} } sf::Vector3i Map::getDimensions() { return sf::Vector3i(0, 0, 0); } void Map::setVoxel(sf::Vector3i world_position, int val) { //load_single(world_position); //sf::Vector3i chunk_pos(world_to_chunk(world_position)); //sf::Vector3i in_chunk_pos( // world_position.x % CHUNK_DIM, // world_position.y % CHUNK_DIM, // world_position.z % CHUNK_DIM //); //chunk_map.at(chunk_pos).voxel_data[in_chunk_pos.x + CHUNK_DIM * (in_chunk_pos.y + CHUNK_DIM * in_chunk_pos.z)] // = val; } char Map::getVoxelFromOctree(sf::Vector3i position) { return a.get_voxel(position); } char Map::getVoxel(sf::Vector3i pos){ return voxel_data[pos.x + OCT_DIM * (pos.y + OCT_DIM * pos.z)]; }