Took out position from octree nodes
This commit is contained in:
parent
bd10e89dea
commit
0ee054dc3c
@ -5,6 +5,7 @@
|
|||||||
#include "../octree_tables.h"
|
#include "../octree_tables.h"
|
||||||
#include "../util/object_pool.h"
|
#include "../util/object_pool.h"
|
||||||
|
|
||||||
|
// Octree designed to handle level of detail.
|
||||||
template <class T>
|
template <class T>
|
||||||
class LodOctree {
|
class LodOctree {
|
||||||
public:
|
public:
|
||||||
@ -14,9 +15,10 @@ public:
|
|||||||
// It needs to be booleanizable, where `true` means presence of data, and `false` means no data.
|
// It needs to be booleanizable, where `true` means presence of data, and `false` means no data.
|
||||||
// Typically a pointer, but can be a straight boolean too.
|
// Typically a pointer, but can be a straight boolean too.
|
||||||
T block;
|
T block;
|
||||||
// Position divided by chunk size at the current LOD,
|
|
||||||
|
// Node positions are calculated on the fly to save memory,
|
||||||
|
// and divided by chunk size at the current LOD,
|
||||||
// so it is sequential within each LOD, which makes it usable for grid storage
|
// so it is sequential within each LOD, which makes it usable for grid storage
|
||||||
Vector3i position;
|
|
||||||
|
|
||||||
Node() {
|
Node() {
|
||||||
init();
|
init();
|
||||||
@ -27,7 +29,6 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline void init() {
|
inline void init() {
|
||||||
position = Vector3i();
|
|
||||||
block = T();
|
block = T();
|
||||||
children[0] = nullptr;
|
children[0] = nullptr;
|
||||||
// for (int i = 0; i < 8; ++i) {
|
// for (int i = 0; i < 8; ++i) {
|
||||||
@ -37,12 +38,12 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct NoDestroyAction {
|
struct NoDestroyAction {
|
||||||
inline void operator()(Node *node, int lod) {}
|
inline void operator()(Node *node, Vector3i node_pos, int lod) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename A>
|
template <typename A>
|
||||||
void clear(A &destroy_action) {
|
void clear(A &destroy_action) {
|
||||||
join_all_recursively(&_root, _max_depth, destroy_action);
|
join_all_recursively(&_root, Vector3i(), _max_depth, destroy_action);
|
||||||
_max_depth = 0;
|
_max_depth = 0;
|
||||||
_base_size = 0;
|
_base_size = 0;
|
||||||
}
|
}
|
||||||
@ -98,12 +99,12 @@ public:
|
|||||||
void update(Vector3 view_pos, A &create_action, B &destroy_action) {
|
void update(Vector3 view_pos, A &create_action, B &destroy_action) {
|
||||||
|
|
||||||
if (_root.block || _root.has_children()) {
|
if (_root.block || _root.has_children()) {
|
||||||
update(&_root, _max_depth, view_pos, create_action, destroy_action);
|
update(&_root, Vector3i(), _max_depth, view_pos, create_action, destroy_action);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// Treat the root in a slightly different way the first time.
|
// Treat the root in a slightly different way the first time.
|
||||||
if (create_action.can_do_root(_max_depth)) {
|
if (create_action.can_do_root(_max_depth)) {
|
||||||
_root.block = create_action(&_root, _max_depth);
|
_root.block = create_action(&_root, Vector3i(), _max_depth);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -132,25 +133,24 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename A, typename B>
|
template <typename A, typename B>
|
||||||
void update(Node *node, int lod, Vector3 view_pos, A &create_action, B &destroy_action) {
|
void update(Node *node, Vector3i node_pos, int lod, Vector3 view_pos, A &create_action, B &destroy_action) {
|
||||||
// This function should be called regularly over frames.
|
// This function should be called regularly over frames.
|
||||||
|
|
||||||
int lod_factor = get_lod_factor(lod);
|
int lod_factor = get_lod_factor(lod);
|
||||||
int chunk_size = _base_size * lod_factor;
|
int chunk_size = _base_size * lod_factor;
|
||||||
Vector3 world_center = static_cast<real_t>(chunk_size) * (node->position.to_vec3() + Vector3(0.5, 0.5, 0.5));
|
Vector3 world_center = static_cast<real_t>(chunk_size) * (node_pos.to_vec3() + Vector3(0.5, 0.5, 0.5));
|
||||||
float split_distance = chunk_size * _split_scale;
|
float split_distance = chunk_size * _split_scale;
|
||||||
|
|
||||||
if (!node->has_children()) {
|
if (!node->has_children()) {
|
||||||
|
|
||||||
// If it's not the last LOD, if close enough and custom conditions get fulfilled
|
// If it's not the last LOD, if close enough and custom conditions get fulfilled
|
||||||
if (lod > 0 && world_center.distance_to(view_pos) < split_distance && create_action.can_do_children(node, lod - 1)) {
|
if (lod > 0 && world_center.distance_to(view_pos) < split_distance && create_action.can_do_children(node, node_pos, lod - 1)) {
|
||||||
// Split
|
// Split
|
||||||
for (int i = 0; i < 8; ++i) {
|
for (int i = 0; i < 8; ++i) {
|
||||||
|
|
||||||
Node *child = _pool.create();
|
Node *child = _pool.create();
|
||||||
|
|
||||||
child->position = get_child_position(node->position, i);
|
child->block = create_action(child, get_child_position(node_pos, i), lod - 1);
|
||||||
child->block = create_action(child, lod - 1);
|
|
||||||
|
|
||||||
node->children[i] = child;
|
node->children[i] = child;
|
||||||
// If the node needs to split more, we'll ask more recycling at the next frame...
|
// If the node needs to split more, we'll ask more recycling at the next frame...
|
||||||
@ -159,7 +159,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (node->block) {
|
if (node->block) {
|
||||||
destroy_action(node, lod);
|
destroy_action(node, node_pos, lod);
|
||||||
node->block = T();
|
node->block = T();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -170,17 +170,17 @@ private:
|
|||||||
|
|
||||||
for (int i = 0; i < 8; ++i) {
|
for (int i = 0; i < 8; ++i) {
|
||||||
Node *child = node->children[i];
|
Node *child = node->children[i];
|
||||||
update(child, lod - 1, view_pos, create_action, destroy_action);
|
update(child, get_child_position(node_pos, i), lod - 1, view_pos, create_action, destroy_action);
|
||||||
has_split_child |= child->has_children();
|
has_split_child |= child->has_children();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!has_split_child && world_center.distance_to(view_pos) > split_distance && destroy_action.can_do(node, lod)) {
|
if (!has_split_child && world_center.distance_to(view_pos) > split_distance && destroy_action.can_do(node, node_pos, lod)) {
|
||||||
// Join
|
// Join
|
||||||
if (node->has_children()) {
|
if (node->has_children()) {
|
||||||
|
|
||||||
for (int i = 0; i < 8; ++i) {
|
for (int i = 0; i < 8; ++i) {
|
||||||
Node *child = node->children[i];
|
Node *child = node->children[i];
|
||||||
destroy_action(child, lod - 1);
|
destroy_action(child, get_child_position(node_pos, i), lod - 1);
|
||||||
child->block = T();
|
child->block = T();
|
||||||
_pool.recycle(child);
|
_pool.recycle(child);
|
||||||
}
|
}
|
||||||
@ -191,28 +191,28 @@ private:
|
|||||||
// When subdividing a node, that node's block must be destroyed as it is replaced by its children.
|
// When subdividing a node, that node's block must be destroyed as it is replaced by its children.
|
||||||
CRASH_COND(node->block);
|
CRASH_COND(node->block);
|
||||||
|
|
||||||
node->block = create_action(node, lod);
|
node->block = create_action(node, node_pos, lod);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename A>
|
template <typename A>
|
||||||
void join_all_recursively(Node *node, int lod, A &destroy_action) {
|
void join_all_recursively(Node *node, Vector3i node_pos, int lod, A &destroy_action) {
|
||||||
|
|
||||||
if (node->has_children()) {
|
if (node->has_children()) {
|
||||||
Node **children = node->children;
|
Node **children = node->children;
|
||||||
|
|
||||||
for (int i = 0; i < 8; ++i) {
|
for (int i = 0; i < 8; ++i) {
|
||||||
Node *child = children[i];
|
Node *child = children[i];
|
||||||
join_all_recursively(child, lod - 1, destroy_action);
|
join_all_recursively(child, get_child_position(node_pos, i), lod - 1, destroy_action);
|
||||||
_pool.recycle(child);
|
_pool.recycle(child);
|
||||||
children[0] = nullptr;
|
children[0] = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (node->block) {
|
if (node->block) {
|
||||||
destroy_action(node, lod);
|
destroy_action(node, node_pos, lod);
|
||||||
node->block = T();
|
node->block = T();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -661,10 +661,10 @@ void VoxelLodTerrain::_process() {
|
|||||||
VoxelLodTerrain *self;
|
VoxelLodTerrain *self;
|
||||||
Vector3i block_offset_lod0;
|
Vector3i block_offset_lod0;
|
||||||
|
|
||||||
void operator()(LodOctree<bool>::Node *node, unsigned int lod_index) {
|
void operator()(LodOctree<bool>::Node *node, Vector3i node_pos, unsigned int lod_index) {
|
||||||
Lod &lod = self->_lods[lod_index];
|
Lod &lod = self->_lods[lod_index];
|
||||||
|
|
||||||
Vector3i bpos = node->position;
|
Vector3i bpos = node_pos;
|
||||||
bpos += block_offset_lod0 >> lod_index;
|
bpos += block_offset_lod0 >> lod_index;
|
||||||
|
|
||||||
VoxelBlock *block = lod.map->get_block(bpos);
|
VoxelBlock *block = lod.map->get_block(bpos);
|
||||||
@ -758,7 +758,7 @@ void VoxelLodTerrain::_process() {
|
|||||||
return self->check_block_loaded_and_updated(offset, lod_index);
|
return self->check_block_loaded_and_updated(offset, lod_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool can_do_children(LodOctree<bool>::Node *node, unsigned int child_lod_index) {
|
bool can_do_children(LodOctree<bool>::Node *node, Vector3i node_pos, unsigned int child_lod_index) {
|
||||||
|
|
||||||
Vector3i offset = block_offset_lod0 >> child_lod_index;
|
Vector3i offset = block_offset_lod0 >> child_lod_index;
|
||||||
bool can = true;
|
bool can = true;
|
||||||
@ -767,7 +767,7 @@ void VoxelLodTerrain::_process() {
|
|||||||
for (int i = 0; i < 8; ++i) {
|
for (int i = 0; i < 8; ++i) {
|
||||||
|
|
||||||
// Get block pos local-to-region
|
// Get block pos local-to-region
|
||||||
Vector3i child_pos = LodOctree<bool>::get_child_position(node->position, i);
|
Vector3i child_pos = LodOctree<bool>::get_child_position(node_pos, i);
|
||||||
|
|
||||||
// Convert to local-to-terrain
|
// Convert to local-to-terrain
|
||||||
child_pos += offset;
|
child_pos += offset;
|
||||||
@ -783,11 +783,11 @@ void VoxelLodTerrain::_process() {
|
|||||||
return can;
|
return can;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator()(LodOctree<bool>::Node *node, unsigned int lod_index) {
|
bool operator()(LodOctree<bool>::Node *node, Vector3i node_pos, unsigned int lod_index) {
|
||||||
|
|
||||||
Lod &lod = self->_lods[lod_index];
|
Lod &lod = self->_lods[lod_index];
|
||||||
|
|
||||||
Vector3i bpos = node->position;
|
Vector3i bpos = node_pos;
|
||||||
bpos += block_offset_lod0 >> lod_index;
|
bpos += block_offset_lod0 >> lod_index;
|
||||||
|
|
||||||
VoxelBlock *block = lod.map->get_block(bpos);
|
VoxelBlock *block = lod.map->get_block(bpos);
|
||||||
@ -805,10 +805,10 @@ void VoxelLodTerrain::_process() {
|
|||||||
Vector3i block_offset_lod0;
|
Vector3i block_offset_lod0;
|
||||||
unsigned int blocked_count = 0;
|
unsigned int blocked_count = 0;
|
||||||
|
|
||||||
bool can_do(LodOctree<bool>::Node *node, unsigned int parent_lod_index) {
|
bool can_do(LodOctree<bool>::Node *node, Vector3i node_pos, unsigned int parent_lod_index) {
|
||||||
|
|
||||||
// Can only unsubdivide if the parent mesh is ready
|
// Can only unsubdivide if the parent mesh is ready
|
||||||
Vector3i bpos = node->position;
|
Vector3i bpos = node_pos;
|
||||||
bpos += block_offset_lod0 >> parent_lod_index;
|
bpos += block_offset_lod0 >> parent_lod_index;
|
||||||
|
|
||||||
bool can = self->check_block_loaded_and_updated(bpos, parent_lod_index);
|
bool can = self->check_block_loaded_and_updated(bpos, parent_lod_index);
|
||||||
@ -820,11 +820,11 @@ void VoxelLodTerrain::_process() {
|
|||||||
return can;
|
return can;
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator()(LodOctree<bool>::Node *node, unsigned int lod_index) {
|
void operator()(LodOctree<bool>::Node *node, Vector3i node_pos, unsigned int lod_index) {
|
||||||
|
|
||||||
Lod &lod = self->_lods[lod_index];
|
Lod &lod = self->_lods[lod_index];
|
||||||
|
|
||||||
Vector3i bpos = node->position;
|
Vector3i bpos = node_pos;
|
||||||
bpos += block_offset_lod0 >> lod_index;
|
bpos += block_offset_lod0 >> lod_index;
|
||||||
|
|
||||||
VoxelBlock *block = lod.map->get_block(bpos);
|
VoxelBlock *block = lod.map->get_block(bpos);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user